i40e/i40evf: Handle IPv6 extension headers in checksum offload
authorAlexander Duyck <aduyck@mirantis.com>
Mon, 25 Jan 2016 05:16:54 +0000 (21:16 -0800)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Thu, 18 Feb 2016 18:49:42 +0000 (10:49 -0800)
This patch adds support for IPv6 extension headers in setting up the Tx
checksum.  Without this patch extension headers would cause IPv6 traffic to
fail as the transport protocol could not be identified.

Signed-off-by: Alexander Duyck <aduyck@mirantis.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/i40e/i40e_txrx.c
drivers/net/ethernet/intel/i40evf/i40e_txrx.c

index 1404cae04b83d81ab92c6cec027cd2b400eab98c..e49fe8f580b1efbc5fff12150840d04662431bc5 100644 (file)
@@ -2402,7 +2402,9 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
                struct udphdr *udp;
                unsigned char *hdr;
        } l4;
+       unsigned char *exthdr;
        u32 l4_tunnel = 0;
+       __be16 frag_off;
        u8 l4_proto = 0;
 
        ip.hdr = skb_network_header(skb);
@@ -2419,7 +2421,12 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
                        l4_proto = ip.v4->protocol;
                } else if (*tx_flags & I40E_TX_FLAGS_IPV6) {
                        *cd_tunneling |= I40E_TX_CTX_EXT_IP_IPV6;
+
+                       exthdr = ip.hdr + sizeof(*ip.v6);
                        l4_proto = ip.v6->nexthdr;
+                       if (l4.hdr != exthdr)
+                               ipv6_skip_exthdr(skb, exthdr - skb->data,
+                                                &l4_proto, &frag_off);
                }
 
                /* define outer transport */
@@ -2469,8 +2476,13 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
                        *td_cmd |= I40E_TX_DESC_CMD_IIPT_IPV4;
                }
        } else if (*tx_flags & I40E_TX_FLAGS_IPV6) {
-               l4_proto = ip.v6->nexthdr;
                *td_cmd |= I40E_TX_DESC_CMD_IIPT_IPV6;
+
+               exthdr = ip.hdr + sizeof(*ip.v6);
+               l4_proto = ip.v6->nexthdr;
+               if (l4.hdr != exthdr)
+                       ipv6_skip_exthdr(skb, exthdr - skb->data,
+                                        &l4_proto, &frag_off);
        }
 
        /* Now set the td_offset for IP header length */
index 39d5f807f08c3c1b2b580c0378cace0540a3e957..48ec7631b3dd8f30ba1576b17918f810262dd4fa 100644 (file)
@@ -1619,7 +1619,9 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
                struct udphdr *udp;
                unsigned char *hdr;
        } l4;
+       unsigned char *exthdr;
        u32 l4_tunnel = 0;
+       __be16 frag_off;
        u8 l4_proto = 0;
 
        ip.hdr = skb_network_header(skb);
@@ -1636,7 +1638,12 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
                        l4_proto = ip.v4->protocol;
                } else if (*tx_flags & I40E_TX_FLAGS_IPV6) {
                        *cd_tunneling |= I40E_TX_CTX_EXT_IP_IPV6;
+
+                       exthdr = ip.hdr + sizeof(*ip.v6);
                        l4_proto = ip.v6->nexthdr;
+                       if (l4.hdr != exthdr)
+                               ipv6_skip_exthdr(skb, exthdr - skb->data,
+                                                &l4_proto, &frag_off);
                }
 
                /* define outer transport */
@@ -1686,8 +1693,13 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
                        *td_cmd |= I40E_TX_DESC_CMD_IIPT_IPV4;
                }
        } else if (*tx_flags & I40E_TX_FLAGS_IPV6) {
-               l4_proto = ip.v6->nexthdr;
                *td_cmd |= I40E_TX_DESC_CMD_IIPT_IPV6;
+
+               exthdr = ip.hdr + sizeof(*ip.v6);
+               l4_proto = ip.v6->nexthdr;
+               if (l4.hdr != exthdr)
+                       ipv6_skip_exthdr(skb, exthdr - skb->data,
+                                        &l4_proto, &frag_off);
        }
 
        /* Now set the td_offset for IP header length */