fm10k: fix incorrect IPv6 extended header checksum
Check for and handle IPv6 extended headers so that Tx checksum offload can be done. Also use skb_checksum_help for unexpected cases. This was originally discovered in ixgbe. Reported-by: Mark Rustad <mark.d.rustad@intel.com> Signed-off-by: Jacob Keller <jacob.e.keller@intel.com> Tested-by: Krishneil Singh <Krishneil.k.singh@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
parent
8664109467
commit
dc1b4c2b88
@ -820,6 +820,8 @@ static void fm10k_tx_csum(struct fm10k_ring *tx_ring,
|
||||
struct ipv6hdr *ipv6;
|
||||
u8 *raw;
|
||||
} network_hdr;
|
||||
u8 *transport_hdr;
|
||||
__be16 frag_off;
|
||||
__be16 protocol;
|
||||
u8 l4_hdr = 0;
|
||||
|
||||
@ -837,9 +839,11 @@ static void fm10k_tx_csum(struct fm10k_ring *tx_ring,
|
||||
goto no_csum;
|
||||
}
|
||||
network_hdr.raw = skb_inner_network_header(skb);
|
||||
transport_hdr = skb_inner_transport_header(skb);
|
||||
} else {
|
||||
protocol = vlan_get_protocol(skb);
|
||||
network_hdr.raw = skb_network_header(skb);
|
||||
transport_hdr = skb_transport_header(skb);
|
||||
}
|
||||
|
||||
switch (protocol) {
|
||||
@ -848,15 +852,17 @@ static void fm10k_tx_csum(struct fm10k_ring *tx_ring,
|
||||
break;
|
||||
case htons(ETH_P_IPV6):
|
||||
l4_hdr = network_hdr.ipv6->nexthdr;
|
||||
if (likely((transport_hdr - 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 ip version=%x!\n",
|
||||
protocol);
|
||||
}
|
||||
tx_ring->tx_stats.csum_err++;
|
||||
goto no_csum;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (l4_hdr) {
|
||||
@ -869,9 +875,10 @@ static void fm10k_tx_csum(struct fm10k_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",
|
||||
protocol, l4_hdr);
|
||||
}
|
||||
skb_checksum_help(skb);
|
||||
tx_ring->tx_stats.csum_err++;
|
||||
goto no_csum;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user