]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
i40e/i40evf: Consolidate all header changes into TSO function
authorAlexander Duyck <aduyck@mirantis.com>
Mon, 25 Jan 2016 05:16:35 +0000 (21:16 -0800)
committerChuck Anderson <chuck.anderson@oracle.com>
Thu, 10 Mar 2016 16:37:36 +0000 (08:37 -0800)
Orabug: 22342532

This patch goes through and pulls all of the spots where we were updating
either the TCP or IP checksums in the TSO and checksum path into the TSO
function.  The general idea here is that we should only be updating the
header after we verify we have completed a skb_cow_head check to verify the
head is writable.

One other advantage to doing this is that it makes things much more
obvious.  For example, in the case of IPv6 there was one spot where the
offset of the IPv4 header checksum was being updated which is obviously
incorrect.

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 c777019af1dc7343be8dc44bb4d32f5e2ef072dd)
Signed-off-by: Brian Maly <brian.maly@oracle.com>
Conflicts:
drivers/net/ethernet/intel/i40e/i40e_txrx.c

drivers/net/ethernet/intel/i40e/i40e_txrx.c
drivers/net/ethernet/intel/i40evf/i40e_txrx.c

index 2b97b0756cdedbc6ab11f7993e39925311f39bc8..f9c75db99684ca404135da874b236d9325bf1037 100644 (file)
@@ -2267,8 +2267,11 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb,
                    u8 *hdr_len, u64 *cd_type_cmd_tso_mss)
 {
        u64 cd_cmd, cd_tso_len, cd_mss;
-       struct ipv6hdr *ipv6h;
-       struct iphdr *iph;
+       union {
+               struct iphdr *v4;
+               struct ipv6hdr *v6;
+               unsigned char *hdr;
+       } ip;
        union {
                struct tcphdr *tcp;
                unsigned char *hdr;
@@ -2286,16 +2289,29 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb,
        if (err < 0)
                return err;
 
-       iph = skb->encapsulation ? inner_ip_hdr(skb) : ip_hdr(skb);
-       ipv6h = skb->encapsulation ? inner_ipv6_hdr(skb) : ipv6_hdr(skb);
-       l4.hdr = skb->encapsulation ? skb_inner_transport_header(skb) :
-                                     skb_transport_header(skb);
+       ip.hdr = skb_network_header(skb);
+       l4.hdr = skb_transport_header(skb);
 
-       if (iph->version == 4) {
-               iph->tot_len = 0;
-               iph->check = 0;
+       /* initialize outer IP header fields */
+       if (ip.v4->version == 4) {
+               ip.v4->tot_len = 0;
+               ip.v4->check = 0;
        } else {
-               ipv6h->payload_len = 0;
+               ip.v6->payload_len = 0;
+       }
+
+       if (skb_shinfo(skb)->gso_type & (SKB_GSO_UDP_TUNNEL | SKB_GSO_GRE)) {
+               /* reset pointers to inner headers */
+               ip.hdr = skb_inner_network_header(skb);
+               l4.hdr = skb_inner_transport_header(skb);
+
+               /* initialize inner IP header fields */
+               if (ip.v4->version == 4) {
+                       ip.v4->tot_len = 0;
+                       ip.v4->check = 0;
+               } else {
+                       ip.v6->payload_len = 0;
+               }
        }
 
        /* determine offset of inner transport header */
@@ -2380,15 +2396,11 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
        struct iphdr *this_ip_hdr;
        u32 network_hdr_len;
        u8 l4_hdr = 0;
-       struct udphdr *oudph;
-       struct iphdr *oiph;
        u32 l4_tunnel = 0;
 
        if (skb->encapsulation) {
                switch (ip_hdr(skb)->protocol) {
                case IPPROTO_UDP:
-                       oudph = udp_hdr(skb);
-                       oiph = ip_hdr(skb);
                        l4_tunnel = I40E_TXD_CTX_UDP_TUNNELING;
                        *tx_flags |= I40E_TX_FLAGS_UDP_TUNNEL;
                        break;
@@ -2406,15 +2418,12 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
                if (*tx_flags & I40E_TX_FLAGS_IPV4) {
                        if (*tx_flags & I40E_TX_FLAGS_TSO) {
                                *cd_tunneling |= I40E_TX_CTX_EXT_IP_IPV4;
-                               ip_hdr(skb)->check = 0;
                        } else {
                                *cd_tunneling |=
                                         I40E_TX_CTX_EXT_IP_IPV4_NO_CSUM;
                        }
                } else if (*tx_flags & I40E_TX_FLAGS_IPV6) {
                        *cd_tunneling |= I40E_TX_CTX_EXT_IP_IPV6;
-                       if (*tx_flags & I40E_TX_FLAGS_TSO)
-                               ip_hdr(skb)->check = 0;
                }
 
                /* Now set the ctx descriptor fields */
@@ -2443,7 +2452,6 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
                 */
                if (*tx_flags & I40E_TX_FLAGS_TSO) {
                        *td_cmd |= I40E_TX_DESC_CMD_IIPT_IPV4_CSUM;
-                       this_ip_hdr->check = 0;
                } else {
                        *td_cmd |= I40E_TX_DESC_CMD_IIPT_IPV4;
                }
index 0f207a158955a96e54c1b98589697b197441ef5d..2a69af57ceae3a4ce0e48e0e09055965091de0a4 100644 (file)
@@ -1527,8 +1527,11 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb,
                    u8 *hdr_len, u64 *cd_type_cmd_tso_mss)
 {
        u64 cd_cmd, cd_tso_len, cd_mss;
-       struct ipv6hdr *ipv6h;
-       struct iphdr *iph;
+       union {
+               struct iphdr *v4;
+               struct ipv6hdr *v6;
+               unsigned char *hdr;
+       } ip;
        union {
                struct tcphdr *tcp;
                unsigned char *hdr;
@@ -1546,16 +1549,29 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb,
        if (err < 0)
                return err;
 
-       iph = skb->encapsulation ? inner_ip_hdr(skb) : ip_hdr(skb);
-       ipv6h = skb->encapsulation ? inner_ipv6_hdr(skb) : ipv6_hdr(skb);
-       l4.hdr = skb->encapsulation ? skb_inner_transport_header(skb) :
-                                     skb_transport_header(skb);
+       ip.hdr = skb_network_header(skb);
+       l4.hdr = skb_transport_header(skb);
 
-       if (iph->version == 4) {
-               iph->tot_len = 0;
-               iph->check = 0;
+       /* initialize outer IP header fields */
+       if (ip.v4->version == 4) {
+               ip.v4->tot_len = 0;
+               ip.v4->check = 0;
        } else {
-               ipv6h->payload_len = 0;
+               ip.v6->payload_len = 0;
+       }
+
+       if (skb_shinfo(skb)->gso_type & (SKB_GSO_UDP_TUNNEL | SKB_GSO_GRE)) {
+               /* reset pointers to inner headers */
+               ip.hdr = skb_inner_network_header(skb);
+               l4.hdr = skb_inner_transport_header(skb);
+
+               /* initialize inner IP header fields */
+               if (ip.v4->version == 4) {
+                       ip.v4->tot_len = 0;
+                       ip.v4->check = 0;
+               } else {
+                       ip.v6->payload_len = 0;
+               }
        }
 
        /* determine offset of inner transport header */
@@ -1597,15 +1613,11 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
        struct iphdr *this_ip_hdr;
        u32 network_hdr_len;
        u8 l4_hdr = 0;
-       struct udphdr *oudph;
-       struct iphdr *oiph;
        u32 l4_tunnel = 0;
 
        if (skb->encapsulation) {
                switch (ip_hdr(skb)->protocol) {
                case IPPROTO_UDP:
-                       oudph = udp_hdr(skb);
-                       oiph = ip_hdr(skb);
                        l4_tunnel = I40E_TXD_CTX_UDP_TUNNELING;
                        *tx_flags |= I40E_TX_FLAGS_VXLAN_TUNNEL;
                        break;
@@ -1620,15 +1632,12 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
                if (*tx_flags & I40E_TX_FLAGS_IPV4) {
                        if (*tx_flags & I40E_TX_FLAGS_TSO) {
                                *cd_tunneling |= I40E_TX_CTX_EXT_IP_IPV4;
-                               ip_hdr(skb)->check = 0;
                        } else {
                                *cd_tunneling |=
                                         I40E_TX_CTX_EXT_IP_IPV4_NO_CSUM;
                        }
                } else if (*tx_flags & I40E_TX_FLAGS_IPV6) {
                        *cd_tunneling |= I40E_TX_CTX_EXT_IP_IPV6;
-                       if (*tx_flags & I40E_TX_FLAGS_TSO)
-                               ip_hdr(skb)->check = 0;
                }
 
                /* Now set the ctx descriptor fields */
@@ -1658,7 +1667,6 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
                 */
                if (*tx_flags & I40E_TX_FLAGS_TSO) {
                        *td_cmd |= I40E_TX_DESC_CMD_IIPT_IPV4_CSUM;
-                       this_ip_hdr->check = 0;
                } else {
                        *td_cmd |= I40E_TX_DESC_CMD_IIPT_IPV4;
                }