]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
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)
committerChuck Anderson <chuck.anderson@oracle.com>
Thu, 10 Mar 2016 16:37:37 +0000 (08:37 -0800)
Orabug: 22342532

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>
(cherry picked from commit a3fd9d8876a589f05725237aced606b995956860)
Signed-off-by: Brian Maly <brian.maly@oracle.com>
drivers/net/ethernet/intel/i40e/i40e_txrx.c
drivers/net/ethernet/intel/i40evf/i40e_txrx.c

index 7f2fce74cf1ea3c9530777930aa1a43107a99d64..173df9f66955a08104c552be6735188a526b0fd0 100644 (file)
@@ -2401,7 +2401,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);
@@ -2418,7 +2420,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 */
@@ -2468,8 +2475,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 b8a78a2dd011f0df728a43e993ead2b73c2423eb..1ba357355ecd1d8dec82f217c4238f06b5d542e8 100644 (file)
@@ -1618,7 +1618,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);
@@ -1635,7 +1637,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 */
@@ -1685,8 +1692,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 */