Received: by 2002:a05:6a10:6744:0:0:0:0 with SMTP id w4csp5366809pxu; Wed, 21 Oct 2020 23:35:47 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzvvtOZbEkD+semaKQzod/vSNZbxbK3aPBBi75oCQaw0GxCUtuKPFwRIRRMdIxVld/UNYVA X-Received: by 2002:a17:906:3e4b:: with SMTP id t11mr838994eji.420.1603348547751; Wed, 21 Oct 2020 23:35:47 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1603348547; cv=none; d=google.com; s=arc-20160816; b=q9ZJo710o/SrI79Efz9GVV8ZpBoIKJmQV1MU3Esp90d9WAdG/9f7IDdOMgQ3xA8v3r mIfq5zHStWQWDr0MUv5rXa7zpPH73BQTZhiOk+LgnTValH0VsLsUpPLhwXFBNIheMOPZ 32GwAXJ7j1qxtRGy8k5wCMK45OgZOeBKQwikzsWrZv5lw6ssb2WQvsWlUkaVe8OFwn4c UBPmISaGNb/KVLI7phd3cNJE4COV8uf8mjr2tv1RGp2MurXpQ5d7LGUZcuxDIqXXMXP2 zj5VBbohVs86HfUlRZJKwVFTlvmtdbM8w7A5OF4bA1GahQTvMJlAe1O0wGuNDqcWvS9k tc6Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=csPN4PZ3cTvIg25S3b37N4wFlpLL1RUKl2UcNvSOcGk=; b=JU7CBGOqlq+Puc1ffLb8oeT2TuYmacWBmyQrrYyXWG8IFKr68kfjdecu67SI3EB4WD ILha+EdT3dyp+ETyUooegoebFTEBly/bOHUQGZ7Caw/tn9LzzlcUUQ3NxkQJJZuLqmcd 8SIwwWZQs+3X5SOn/wTaqmrClkimVm0L8NJGwfz//i4LLf5ChNqLQNvKw6xy5XBjwtFo yZk0jRayiFdM0ik+a1MfYZwQpsYJT1R5G1dJAbQk6x/rN2wCZ5eOyJrb+mkzPWr9eqyl pGaGyyI7wsNSANZICKTD3cY/LD27jY2eyf8UHp/awOF3Weaup/8guEBOLHcChybY6O6r 6SAQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=uniroma2.it Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id bv12si289212ejb.662.2020.10.21.23.35.25; Wed, 21 Oct 2020 23:35:47 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=uniroma2.it Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2504459AbgJUSvH (ORCPT + 99 others); Wed, 21 Oct 2020 14:51:07 -0400 Received: from smtp.uniroma2.it ([160.80.6.22]:47193 "EHLO smtp.uniroma2.it" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2437233AbgJUSvH (ORCPT ); Wed, 21 Oct 2020 14:51:07 -0400 Received: from localhost.localdomain ([160.80.103.126]) by smtp-2015.uniroma2.it (8.14.4/8.14.4/Debian-8) with ESMTP id 09LIga9g005673 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Wed, 21 Oct 2020 20:42:38 +0200 From: Andrea Mayer To: "David S. Miller" , David Ahern , Alexey Kuznetsov , Hideaki YOSHIFUJI , Jakub Kicinski , Shuah Khan , Shrijeet Mukherjee , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Cc: Stefano Salsano , Paolo Lungaroni , Ahmed Abdelsalam , Andrea Mayer Subject: [RFC,net-next, 1/4] vrf: push mac header for tunneled packets when sniffer is attached Date: Wed, 21 Oct 2020 20:41:13 +0200 Message-Id: <20201021184116.2722-2-andrea.mayer@uniroma2.it> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201021184116.2722-1-andrea.mayer@uniroma2.it> References: <20201021184116.2722-1-andrea.mayer@uniroma2.it> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Virus-Scanned: clamav-milter 0.100.0 at smtp-2015 X-Virus-Status: Clean Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Before this patch, a sniffer attached to a VRF used as the receiving interface of L3 tunneled packets detects them as malformed packets and it complains about that (i.e.: tcpdump shows bogus packets). The reason is that a tunneled L3 packet does not carry any L2 information and when the VRF is set as the receiving interface of a decapsulated L3 packet, no mac header is currently set or valid. Therefore the purpose of this patch consists of adding a MAC header to any packet which is directly received on the VRF interface ONLY IF: i) a sniffer is attached on the VRF and ii) the mac header is not set. In this case, the mac address of the VRF is copied in both the destination and the source address of the ethernet header. The protocol type is set either to IPv4 or IPv6, depending on which L3 packet is received. Signed-off-by: Andrea Mayer --- drivers/net/vrf.c | 78 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 72 insertions(+), 6 deletions(-) diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 60c1aadece89..abb09c6036a6 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -1263,6 +1263,61 @@ static void vrf_ip6_input_dst(struct sk_buff *skb, struct net_device *vrf_dev, skb_dst_set(skb, &rt6->dst); } +static int vrf_prepare_mac_header(struct sk_buff *skb, + struct net_device *vrf_dev, u16 proto) +{ + struct ethhdr *eth; + int err; + + /* in general, we do not know if there is enough space in the head of + * the packet for hosting the mac header. + */ + err = skb_cow_head(skb, LL_RESERVED_SPACE(vrf_dev)); + if (unlikely(err)) + /* no space in the skb head */ + return -ENOBUFS; + + __skb_push(skb, ETH_HLEN); + eth = (struct ethhdr *)skb->data; + + skb_reset_mac_header(skb); + + /* we set the ethernet destination and the source addresses to the + * address of the VRF device. + */ + ether_addr_copy(eth->h_dest, vrf_dev->dev_addr); + ether_addr_copy(eth->h_source, vrf_dev->dev_addr); + eth->h_proto = htons(proto); + + /* the destination address of the Ethernet frame corresponds to the + * address set on the VRF interface; therefore, the packet is intended + * to be processed locally. + */ + skb->protocol = eth->h_proto; + skb->pkt_type = PACKET_HOST; + + skb_postpush_rcsum(skb, skb->data, ETH_HLEN); + + skb_pull_inline(skb, ETH_HLEN); + + return 0; +} + +/* prepare and add the mac header to the packet if it was not previously set. + * In this way, packet sniffers such as tcpdump can parse the packet correctly. + * If the mac header was previously set, the original mac header is left + * untouched and the function returns immediately. + */ +static int vrf_add_mac_header_if_unset(struct sk_buff *skb, + struct net_device *vrf_dev, + u16 proto) +{ + if (skb_mac_header_was_set(skb)) + return 0; + + return vrf_prepare_mac_header(skb, vrf_dev, proto); +} + static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev, struct sk_buff *skb) { @@ -1289,9 +1344,15 @@ static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev, skb->skb_iif = vrf_dev->ifindex; if (!list_empty(&vrf_dev->ptype_all)) { - skb_push(skb, skb->mac_len); - dev_queue_xmit_nit(skb, vrf_dev); - skb_pull(skb, skb->mac_len); + int err; + + err = vrf_add_mac_header_if_unset(skb, vrf_dev, + ETH_P_IPV6); + if (likely(!err)) { + skb_push(skb, skb->mac_len); + dev_queue_xmit_nit(skb, vrf_dev); + skb_pull(skb, skb->mac_len); + } } IP6CB(skb)->flags |= IP6SKB_L3SLAVE; @@ -1334,9 +1395,14 @@ static struct sk_buff *vrf_ip_rcv(struct net_device *vrf_dev, vrf_rx_stats(vrf_dev, skb->len); if (!list_empty(&vrf_dev->ptype_all)) { - skb_push(skb, skb->mac_len); - dev_queue_xmit_nit(skb, vrf_dev); - skb_pull(skb, skb->mac_len); + int err; + + err = vrf_add_mac_header_if_unset(skb, vrf_dev, ETH_P_IP); + if (likely(!err)) { + skb_push(skb, skb->mac_len); + dev_queue_xmit_nit(skb, vrf_dev); + skb_pull(skb, skb->mac_len); + } } skb = vrf_rcv_nfhook(NFPROTO_IPV4, NF_INET_PRE_ROUTING, skb, vrf_dev); -- 2.20.1