mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 18:41:58 +09:00
net/mlx5e: fix csum adjustments caused by RXFCS
[ Upstream commitd48051c5b8] As shown by Dmitris, we need to use csum_block_add() instead of csum_add() when adding the FCS contribution to skb csum. Before 4.18 (more exactly commit88078d98d1"net: pskb_trim_rcsum() and CHECKSUM_COMPLETE are friends"), the whole skb csum was thrown away, so RXFCS changes were ignored. Then before commitd55bef5059("net: fix pskb_trim_rcsum_slow() with odd trim offset") both mlx5 and pskb_trim_rcsum_slow() bugs were canceling each other. Now we fixed pskb_trim_rcsum_slow() we need to fix mlx5. Note that this patch also rewrites mlx5e_get_fcs() to : - Use skb_header_pointer() instead of reinventing it. - Use __get_unaligned_cpu32() to avoid possible non aligned accesses as Dmitris pointed out. Fixes:902a545904("net/mlx5e: When RXFCS is set, add FCS data into checksum calculation") Reported-by: Paweł Staszewski <pstaszewski@itcare.pl> Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Eran Ben Elisha <eranbe@mellanox.com> Cc: Saeed Mahameed <saeedm@mellanox.com> Cc: Dimitris Michailidis <dmichail@google.com> Cc: Cong Wang <xiyou.wangcong@gmail.com> Cc: Paweł Staszewski <pstaszewski@itcare.pl> Reviewed-by: Eran Ben Elisha <eranbe@mellanox.com> Tested-By: Maria Pasechnik <mariap@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
dc31623a99
commit
c5eebcf073
@@ -696,43 +696,15 @@ static inline bool is_last_ethertype_ip(struct sk_buff *skb, int *network_depth)
|
||||
return (ethertype == htons(ETH_P_IP) || ethertype == htons(ETH_P_IPV6));
|
||||
}
|
||||
|
||||
static __be32 mlx5e_get_fcs(struct sk_buff *skb)
|
||||
static u32 mlx5e_get_fcs(const struct sk_buff *skb)
|
||||
{
|
||||
int last_frag_sz, bytes_in_prev, nr_frags;
|
||||
u8 *fcs_p1, *fcs_p2;
|
||||
skb_frag_t *last_frag;
|
||||
__be32 fcs_bytes;
|
||||
const void *fcs_bytes;
|
||||
u32 _fcs_bytes;
|
||||
|
||||
if (!skb_is_nonlinear(skb))
|
||||
return *(__be32 *)(skb->data + skb->len - ETH_FCS_LEN);
|
||||
fcs_bytes = skb_header_pointer(skb, skb->len - ETH_FCS_LEN,
|
||||
ETH_FCS_LEN, &_fcs_bytes);
|
||||
|
||||
nr_frags = skb_shinfo(skb)->nr_frags;
|
||||
last_frag = &skb_shinfo(skb)->frags[nr_frags - 1];
|
||||
last_frag_sz = skb_frag_size(last_frag);
|
||||
|
||||
/* If all FCS data is in last frag */
|
||||
if (last_frag_sz >= ETH_FCS_LEN)
|
||||
return *(__be32 *)(skb_frag_address(last_frag) +
|
||||
last_frag_sz - ETH_FCS_LEN);
|
||||
|
||||
fcs_p2 = (u8 *)skb_frag_address(last_frag);
|
||||
bytes_in_prev = ETH_FCS_LEN - last_frag_sz;
|
||||
|
||||
/* Find where the other part of the FCS is - Linear or another frag */
|
||||
if (nr_frags == 1) {
|
||||
fcs_p1 = skb_tail_pointer(skb);
|
||||
} else {
|
||||
skb_frag_t *prev_frag = &skb_shinfo(skb)->frags[nr_frags - 2];
|
||||
|
||||
fcs_p1 = skb_frag_address(prev_frag) +
|
||||
skb_frag_size(prev_frag);
|
||||
}
|
||||
fcs_p1 -= bytes_in_prev;
|
||||
|
||||
memcpy(&fcs_bytes, fcs_p1, bytes_in_prev);
|
||||
memcpy(((u8 *)&fcs_bytes) + bytes_in_prev, fcs_p2, last_frag_sz);
|
||||
|
||||
return fcs_bytes;
|
||||
return __get_unaligned_cpu32(fcs_bytes);
|
||||
}
|
||||
|
||||
static inline void mlx5e_handle_csum(struct net_device *netdev,
|
||||
@@ -765,8 +737,9 @@ static inline void mlx5e_handle_csum(struct net_device *netdev,
|
||||
network_depth - ETH_HLEN,
|
||||
skb->csum);
|
||||
if (unlikely(netdev->features & NETIF_F_RXFCS))
|
||||
skb->csum = csum_add(skb->csum,
|
||||
(__force __wsum)mlx5e_get_fcs(skb));
|
||||
skb->csum = csum_block_add(skb->csum,
|
||||
(__force __wsum)mlx5e_get_fcs(skb),
|
||||
skb->len - ETH_FCS_LEN);
|
||||
stats->csum_complete++;
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user