]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
qede: Prevent GSO on long Geneve headers
authorManish Chopra <manish.chopra@caviumnetworks.com>
Fri, 14 Oct 2016 09:19:19 +0000 (05:19 -0400)
committerChuck Anderson <chuck.anderson@oracle.com>
Mon, 6 Mar 2017 04:59:57 +0000 (20:59 -0800)
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 <manish.chopra@caviumnetworks.com>
Signed-off-by: Yuval Mintz <Yuval.Mintz@caviumnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
(cherry picked from commit 256958538ae2616e4aa14efab8c0d11df1e188db)
Signed-off-by: Brian Maly <brian.maly@oracle.com>
Conflicts:
drivers/net/ethernet/qlogic/qede/qede_main.c

drivers/net/ethernet/qlogic/qede/qede_main.c

index 2f712542993031e1cda162ec361bf7475d7c230c..d788360d42008fc4d3729181e5867da1e0790bd6 100644 (file)
@@ -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,
 };
 
 /* -------------------------------------------------------------------------