diff options
author | Wei-Chun Chao <weichunc@plumgrid.com> | 2013-12-26 16:10:22 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-01-02 19:06:47 -0500 |
commit | 7a7ffbabf99445704be01bff5d7e360da908cf8e (patch) | |
tree | 3b4f71699307ac2853a8fdffde60fb7055cb1b04 /include/linux/netdevice.h | |
parent | 619a60ee04be33238721a15c1f9704a2a515a33e (diff) |
ipv4: fix tunneled VM traffic over hw VXLAN/GRE GSO NIC
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>
Diffstat (limited to 'include/linux/netdevice.h')
-rw-r--r-- | include/linux/netdevice.h | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 7514b9c37a39..5faaadb0c74f 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -3017,6 +3017,19 @@ static inline void netif_set_gso_max_size(struct net_device *dev, | |||
3017 | dev->gso_max_size = size; | 3017 | dev->gso_max_size = size; |
3018 | } | 3018 | } |
3019 | 3019 | ||
3020 | static inline void skb_gso_error_unwind(struct sk_buff *skb, __be16 protocol, | ||
3021 | int pulled_hlen, u16 mac_offset, | ||
3022 | int mac_len) | ||
3023 | { | ||
3024 | skb->protocol = protocol; | ||
3025 | skb->encapsulation = 1; | ||
3026 | skb_push(skb, pulled_hlen); | ||
3027 | skb_reset_transport_header(skb); | ||
3028 | skb->mac_header = mac_offset; | ||
3029 | skb->network_header = skb->mac_header + mac_len; | ||
3030 | skb->mac_len = mac_len; | ||
3031 | } | ||
3032 | |||
3020 | static inline bool netif_is_macvlan(struct net_device *dev) | 3033 | static inline bool netif_is_macvlan(struct net_device *dev) |
3021 | { | 3034 | { |
3022 | return dev->priv_flags & IFF_MACVLAN; | 3035 | return dev->priv_flags & IFF_MACVLAN; |