From f29abb53364a5328b953083aa89f80514fc31903 Mon Sep 17 00:00:00 2001 From: Manish Chopra Date: Fri, 14 Oct 2016 05:19:19 -0400 Subject: [PATCH] qede: Prevent GSO on long Geneve headers Orabug: 25477939 Due to hardware limitation, when transmitting a geneve-encapsulated packet with more than 32 bytes worth of geneve options the hardware would not be able to crack the packet and consider it a regular UDP packet. This implements the ndo_features_check() in qede in order to prevent GSO on said transmitted packets. Signed-off-by: Manish Chopra Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller (cherry picked from commit 256958538ae2616e4aa14efab8c0d11df1e188db) Signed-off-by: Brian Maly Conflicts: drivers/net/ethernet/qlogic/qede/qede_main.c --- drivers/net/ethernet/qlogic/qede/qede_main.c | 35 ++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c index 2f7125429930..d788360d4200 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_main.c +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c @@ -2204,6 +2204,40 @@ static void qede_del_vxlan_port(struct net_device *dev, } #endif +/* 8B udp header + 8B base tunnel header + 32B option length */ +#define QEDE_MAX_TUN_HDR_LEN 48 + +static netdev_features_t qede_features_check(struct sk_buff *skb, + struct net_device *dev, + netdev_features_t features) +{ + if (skb->encapsulation) { + u8 l4_proto = 0; + + switch (vlan_get_protocol(skb)) { + case htons(ETH_P_IP): + l4_proto = ip_hdr(skb)->protocol; + break; + case htons(ETH_P_IPV6): + l4_proto = ipv6_hdr(skb)->nexthdr; + break; + default: + return features; + } + + /* Disable offloads for geneve tunnels, as HW can't parse + * the geneve header which has option length greater than 32B. + */ + if ((l4_proto == IPPROTO_UDP) && + ((skb_inner_mac_header(skb) - + skb_transport_header(skb)) > QEDE_MAX_TUN_HDR_LEN)) + return features & ~((NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \ + NETIF_F_HW_CSUM) | NETIF_F_GSO_MASK); + } + + return features; +} + static const struct net_device_ops qede_netdev_ops = { .ndo_open = qede_open, .ndo_stop = qede_close, @@ -2230,6 +2264,7 @@ static const struct net_device_ops qede_netdev_ops = { .ndo_add_vxlan_port = qede_add_vxlan_port, .ndo_del_vxlan_port = qede_del_vxlan_port, #endif + .ndo_features_check = qede_features_check, }; /* ------------------------------------------------------------------------- -- 2.50.1