Commit d34a614a authored by Mark Rustad's avatar Mark Rustad Committed by Jeff Kirsher

ixgbevf: Handle extended IPv6 headers in Tx path

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 seeing how to coalesce the error handling
into one location.
Reported-by: default avatarTom Herbert <tom@herbertland.com>
Signed-off-by: default avatarMark Rustad <mark.d.rustad@intel.com>
Tested-by: default avatarDarin Miller <darin.j.miller@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 3c2f2b77
...@@ -3344,6 +3344,7 @@ static void ixgbevf_tx_csum(struct ixgbevf_ring *tx_ring, ...@@ -3344,6 +3344,7 @@ static void ixgbevf_tx_csum(struct ixgbevf_ring *tx_ring,
if (skb->ip_summed == CHECKSUM_PARTIAL) { if (skb->ip_summed == CHECKSUM_PARTIAL) {
u8 l4_hdr = 0; u8 l4_hdr = 0;
__be16 frag_off;
switch (first->protocol) { switch (first->protocol) {
case htons(ETH_P_IP): case htons(ETH_P_IP):
...@@ -3354,13 +3355,16 @@ static void ixgbevf_tx_csum(struct ixgbevf_ring *tx_ring, ...@@ -3354,13 +3355,16 @@ static void ixgbevf_tx_csum(struct ixgbevf_ring *tx_ring,
case htons(ETH_P_IPV6): case htons(ETH_P_IPV6):
vlan_macip_lens |= skb_network_header_len(skb); vlan_macip_lens |= skb_network_header_len(skb);
l4_hdr = ipv6_hdr(skb)->nexthdr; l4_hdr = ipv6_hdr(skb)->nexthdr;
if (likely(skb_network_header_len(skb) ==
sizeof(struct ipv6hdr)))
break;
ipv6_skip_exthdr(skb, skb_network_offset(skb) +
sizeof(struct ipv6hdr),
&l4_hdr, &frag_off);
if (unlikely(frag_off))
l4_hdr = NEXTHDR_FRAGMENT;
break; break;
default: default:
if (unlikely(net_ratelimit())) {
dev_warn(tx_ring->dev,
"partial checksum but proto=%x!\n",
first->protocol);
}
break; break;
} }
...@@ -3382,16 +3386,18 @@ static void ixgbevf_tx_csum(struct ixgbevf_ring *tx_ring, ...@@ -3382,16 +3386,18 @@ static void ixgbevf_tx_csum(struct ixgbevf_ring *tx_ring,
default: default:
if (unlikely(net_ratelimit())) { if (unlikely(net_ratelimit())) {
dev_warn(tx_ring->dev, dev_warn(tx_ring->dev,
"partial checksum but l4 proto=%x!\n", "partial checksum, l3 proto=%x, l4 proto=%x\n",
l4_hdr); first->protocol, l4_hdr);
} }
break; skb_checksum_help(skb);
goto no_csum;
} }
/* update TX checksum flag */ /* update TX checksum flag */
first->tx_flags |= IXGBE_TX_FLAGS_CSUM; first->tx_flags |= IXGBE_TX_FLAGS_CSUM;
} }
no_csum:
/* vlan_macip_lens: MACLEN, VLAN tag */ /* vlan_macip_lens: MACLEN, VLAN tag */
vlan_macip_lens |= skb_network_offset(skb) << IXGBE_ADVTXD_MACLEN_SHIFT; vlan_macip_lens |= skb_network_offset(skb) << IXGBE_ADVTXD_MACLEN_SHIFT;
vlan_macip_lens |= first->tx_flags & IXGBE_TX_FLAGS_VLAN_MASK; vlan_macip_lens |= first->tx_flags & IXGBE_TX_FLAGS_VLAN_MASK;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment