Commit 24d41e5e authored by Alexander Duyck's avatar Alexander Duyck Committed by Jeff Kirsher

i40e/i40evf: Fix TSO checksum pseudo-header adjustment

With IPv4 and IPv6 now using the same format for checksums based on the
length of the frame we need to update the i40e and i40evf drivers so that
they correctly account for lengths greater than or equal to 64K.

With this patch the driver should now correctly update checksums for frames
up to 16776960 in length which should be more than large enough for all
possible TSO frames in the near future.
Signed-off-by: default avatarAlexander Duyck <aduyck@mirantis.com>
Tested-by: default avatarAndrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 066439ce
...@@ -2304,10 +2304,8 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb, ...@@ -2304,10 +2304,8 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb,
l4_offset = l4.hdr - skb->data; l4_offset = l4.hdr - skb->data;
/* remove payload length from outer checksum */ /* remove payload length from outer checksum */
paylen = (__force u16)l4.udp->check; paylen = skb->len - l4_offset;
paylen += ntohs((__force __be16)1) * csum_replace_by_diff(&l4.udp->check, htonl(paylen));
(u16)~(skb->len - l4_offset);
l4.udp->check = ~csum_fold((__force __wsum)paylen);
} }
/* reset pointers to inner headers */ /* reset pointers to inner headers */
...@@ -2327,9 +2325,8 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb, ...@@ -2327,9 +2325,8 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb,
l4_offset = l4.hdr - skb->data; l4_offset = l4.hdr - skb->data;
/* remove payload length from inner checksum */ /* remove payload length from inner checksum */
paylen = (__force u16)l4.tcp->check; paylen = skb->len - l4_offset;
paylen += ntohs((__force __be16)1) * (u16)~(skb->len - l4_offset); csum_replace_by_diff(&l4.tcp->check, htonl(paylen));
l4.tcp->check = ~csum_fold((__force __wsum)paylen);
/* compute length of segmentation header */ /* compute length of segmentation header */
*hdr_len = (l4.tcp->doff * 4) + l4_offset; *hdr_len = (l4.tcp->doff * 4) + l4_offset;
......
...@@ -1571,10 +1571,8 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb, ...@@ -1571,10 +1571,8 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb,
l4_offset = l4.hdr - skb->data; l4_offset = l4.hdr - skb->data;
/* remove payload length from outer checksum */ /* remove payload length from outer checksum */
paylen = (__force u16)l4.udp->check; paylen = skb->len - l4_offset;
paylen += ntohs((__force __be16)1) * csum_replace_by_diff(&l4.udp->check, htonl(paylen));
(u16)~(skb->len - l4_offset);
l4.udp->check = ~csum_fold((__force __wsum)paylen);
} }
/* reset pointers to inner headers */ /* reset pointers to inner headers */
...@@ -1594,9 +1592,8 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb, ...@@ -1594,9 +1592,8 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb,
l4_offset = l4.hdr - skb->data; l4_offset = l4.hdr - skb->data;
/* remove payload length from inner checksum */ /* remove payload length from inner checksum */
paylen = (__force u16)l4.tcp->check; paylen = skb->len - l4_offset;
paylen += ntohs((__force __be16)1) * (u16)~(skb->len - l4_offset); csum_replace_by_diff(&l4.tcp->check, htonl(paylen));
l4.tcp->check = ~csum_fold((__force __wsum)paylen);
/* compute length of segmentation header */ /* compute length of segmentation header */
*hdr_len = (l4.tcp->doff * 4) + l4_offset; *hdr_len = (l4.tcp->doff * 4) + l4_offset;
......
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