[Intel-wired-lan] [PATCH V3] ixgbe: Handle extended IPv6 headers in tx path
Mark D Rustad
mark.d.rustad at intel.com
Tue Nov 17 23:07:14 UTC 2015
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.
Reported-by: Tom Herbert <tom at herbertland.com>
Signed-off-by: Mark Rustad <mark.d.rustad at intel.com>
---
Changed in V2:
- Use ipv6_skip_exthdr instead of ipv6_find_hdr
- Move code into L3 processing and avoid any possible loop
- Handle encapsulated IPv6 extended headers correctly
Changed in V3:
- Call skb_checksum_help for unexpected cases
- Move unlikely() calls to more appropriate places
- Reaarange terms in call to ipv6_skip_exthdr to reduce line count
- Combined 2 unlikely error cases into one
---
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 1ffbe85eab7b..c058ce616b28 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -7229,6 +7229,8 @@ static void ixgbe_tx_csum(struct ixgbe_ring *tx_ring,
struct tcphdr *tcphdr;
u8 *raw;
} transport_hdr;
+ __be16 frag_off;
+ int rc;
if (skb->encapsulation) {
network_hdr.raw = skb_inner_network_header(skb);
@@ -7252,6 +7254,21 @@ 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;
+ rc = ipv6_skip_exthdr(skb, network_hdr.raw - skb->data +
+ sizeof(struct ipv6hdr),
+ &l4_hdr, &frag_off);
+ if (unlikely(rc < 0 || frag_off)) {
+ if (net_ratelimit()) {
+ dev_warn(tx_ring->dev,
+ "ipv6_skip_exthdr returns %d\n",
+ rc);
+ }
+ skb_checksum_help(skb);
+ goto no_csum;
+ }
break;
default:
if (unlikely(net_ratelimit())) {
@@ -7259,6 +7276,8 @@ static void ixgbe_tx_csum(struct ixgbe_ring *tx_ring,
"partial checksum but version=%d\n",
network_hdr.ipv4->version);
}
+ skb_checksum_help(skb);
+ goto no_csum;
}
switch (l4_hdr) {
@@ -7282,13 +7301,15 @@ static void ixgbe_tx_csum(struct ixgbe_ring *tx_ring,
"partial checksum but l4 proto=%x!\n",
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;
More information about the Intel-wired-lan
mailing list