aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorWei-Chun Chao <weichunc@plumgrid.com>2013-12-26 13:10:22 -0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-01-15 15:31:37 -0800
commitb21d217ce4403082908511d0296ee854f30a8014 (patch)
treeeb0877f4483b0a03b9c6644967a07dcc8712df0e /include
parenteffb6d243d4da7ab063e6c0668a4f6e23cb5adb9 (diff)
ipv4: fix tunneled VM traffic over hw VXLAN/GRE GSO NIC
[ Upstream commit 7a7ffbabf99445704be01bff5d7e360da908cf8e ] VM to VM GSO traffic is broken if it goes through VXLAN or GRE tunnel and the physical NIC on the host supports hardware VXLAN/GRE GSO offload (e.g. bnx2x and next-gen mlx4). Two issues - (VXLAN) VM traffic has SKB_GSO_DODGY and SKB_GSO_UDP_TUNNEL with SKB_GSO_TCP/UDP set depending on the inner protocol. GSO header integrity check fails in udp4_ufo_fragment if inner protocol is TCP. Also gso_segs is calculated incorrectly using skb->len that includes tunnel header. Fix: robust check should only be applied to the inner packet. (VXLAN & GRE) Once GSO header integrity check passes, NULL segs is returned and the original skb is sent to hardware. However the tunnel header is already pulled. Fix: tunnel header needs to be restored so that hardware can perform GSO properly on the original packet. Signed-off-by: Wei-Chun Chao <weichunc@plumgrid.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'include')
-rw-r--r--include/linux/netdevice.h13
1 files changed, 13 insertions, 0 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index c8d3375d5f5..21eae43348f 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2954,6 +2954,19 @@ static inline void netif_set_gso_max_size(struct net_device *dev,
dev->gso_max_size = size;
}
+static inline void skb_gso_error_unwind(struct sk_buff *skb, __be16 protocol,
+ int pulled_hlen, u16 mac_offset,
+ int mac_len)
+{
+ skb->protocol = protocol;
+ skb->encapsulation = 1;
+ skb_push(skb, pulled_hlen);
+ skb_reset_transport_header(skb);
+ skb->mac_header = mac_offset;
+ skb->network_header = skb->mac_header + mac_len;
+ skb->mac_len = mac_len;
+}
+
static inline bool netif_is_bond_master(struct net_device *dev)
{
return dev->flags & IFF_MASTER && dev->priv_flags & IFF_BONDING;