]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
ixgbe: Handle extended IPv6 headers in Tx path
authorMark Rustad <mark.d.rustad@intel.com>
Wed, 18 Nov 2015 17:21:28 +0000 (09:21 -0800)
committerChuck Anderson <chuck.anderson@oracle.com>
Wed, 6 Jul 2016 23:40:22 +0000 (16:40 -0700)
Orabug: 23177316

Check for and handle IPv6 extended headers so that Tx checksum
offload can be done. Also use skb_checksum_help for unexpected
cases. Thanks to Tom Herbert for noticing these problems. Thanks
to Alexander Duyck for recognizing problems with the first version
of this patch and recognizing how to coalesce error conditions
into a single location.

Reported-by: Tom Herbert <tom@herbertland.com>
Signed-off-by: Mark Rustad <mark.d.rustad@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
(cherry picked from commit 36a92d7190e68e9387347695fe4625eb2c9e7e1c)
Signed-off-by: Brian Maly <brian.maly@oracle.com>
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c

index aa6d994df0f03685e54b79aa926fe592f71a7daf..c8570990bdd128615bae33764ed513fa8ba61bc4 100644 (file)
@@ -7054,6 +7054,7 @@ static void ixgbe_tx_csum(struct ixgbe_ring *tx_ring,
                        struct tcphdr *tcphdr;
                        u8 *raw;
                } transport_hdr;
+               __be16 frag_off;
 
                if (skb->encapsulation) {
                        network_hdr.raw = skb_inner_network_header(skb);
@@ -7077,13 +7078,17 @@ static void ixgbe_tx_csum(struct ixgbe_ring *tx_ring,
                case 6:
                        vlan_macip_lens |= transport_hdr.raw - network_hdr.raw;
                        l4_hdr = network_hdr.ipv6->nexthdr;
+                       if (likely((transport_hdr.raw - network_hdr.raw) ==
+                                  sizeof(struct ipv6hdr)))
+                               break;
+                       ipv6_skip_exthdr(skb, network_hdr.raw - skb->data +
+                                             sizeof(struct ipv6hdr),
+                                        &l4_hdr, &frag_off);
+                       if (unlikely(frag_off))
+                               l4_hdr = NEXTHDR_FRAGMENT;
                        break;
                default:
-                       if (unlikely(net_ratelimit())) {
-                               dev_warn(tx_ring->dev,
-                                        "partial checksum but version=%d\n",
-                                        network_hdr.ipv4->version);
-                       }
+                       break;
                }
 
                switch (l4_hdr) {
@@ -7104,16 +7109,18 @@ static void ixgbe_tx_csum(struct ixgbe_ring *tx_ring,
                default:
                        if (unlikely(net_ratelimit())) {
                                dev_warn(tx_ring->dev,
-                                "partial checksum but l4 proto=%x!\n",
-                                l4_hdr);
+                                        "partial checksum, version=%d, l4 proto=%x\n",
+                                        network_hdr.ipv4->version, l4_hdr);
                        }
-                       break;
+                       skb_checksum_help(skb);
+                       goto no_csum;
                }
 
                /* update TX checksum flag */
                first->tx_flags |= IXGBE_TX_FLAGS_CSUM;
        }
 
+no_csum:
        /* vlan_macip_lens: MACLEN, VLAN tag */
        vlan_macip_lens |= first->tx_flags & IXGBE_TX_FLAGS_VLAN_MASK;