Skip to content

Commit ac65fd7

Browse files
edumazetgregkh
authored andcommitted
net/mlx5e: fix csum adjustments caused by RXFCS
[ Upstream commit d48051c ] 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 commit 88078d9 "net: pskb_trim_rcsum() and CHECKSUM_COMPLETE are friends"), the whole skb csum was thrown away, so RXFCS changes were ignored. Then before commit d55bef5 ("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: 902a545 ("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>
1 parent 855cb69 commit ac65fd7

1 file changed

Lines changed: 9 additions & 36 deletions

File tree

  • drivers/net/ethernet/mellanox/mlx5/core

drivers/net/ethernet/mellanox/mlx5/core/en_rx.c

Lines changed: 9 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -635,43 +635,15 @@ static inline bool is_first_ethertype_ip(struct sk_buff *skb)
635635
return (ethertype == htons(ETH_P_IP) || ethertype == htons(ETH_P_IPV6));
636636
}
637637

638-
static __be32 mlx5e_get_fcs(struct sk_buff *skb)
638+
static u32 mlx5e_get_fcs(const struct sk_buff *skb)
639639
{
640-
int last_frag_sz, bytes_in_prev, nr_frags;
641-
u8 *fcs_p1, *fcs_p2;
642-
skb_frag_t *last_frag;
643-
__be32 fcs_bytes;
640+
const void *fcs_bytes;
641+
u32 _fcs_bytes;
644642

645-
if (!skb_is_nonlinear(skb))
646-
return *(__be32 *)(skb->data + skb->len - ETH_FCS_LEN);
643+
fcs_bytes = skb_header_pointer(skb, skb->len - ETH_FCS_LEN,
644+
ETH_FCS_LEN, &_fcs_bytes);
647645

648-
nr_frags = skb_shinfo(skb)->nr_frags;
649-
last_frag = &skb_shinfo(skb)->frags[nr_frags - 1];
650-
last_frag_sz = skb_frag_size(last_frag);
651-
652-
/* If all FCS data is in last frag */
653-
if (last_frag_sz >= ETH_FCS_LEN)
654-
return *(__be32 *)(skb_frag_address(last_frag) +
655-
last_frag_sz - ETH_FCS_LEN);
656-
657-
fcs_p2 = (u8 *)skb_frag_address(last_frag);
658-
bytes_in_prev = ETH_FCS_LEN - last_frag_sz;
659-
660-
/* Find where the other part of the FCS is - Linear or another frag */
661-
if (nr_frags == 1) {
662-
fcs_p1 = skb_tail_pointer(skb);
663-
} else {
664-
skb_frag_t *prev_frag = &skb_shinfo(skb)->frags[nr_frags - 2];
665-
666-
fcs_p1 = skb_frag_address(prev_frag) +
667-
skb_frag_size(prev_frag);
668-
}
669-
fcs_p1 -= bytes_in_prev;
670-
671-
memcpy(&fcs_bytes, fcs_p1, bytes_in_prev);
672-
memcpy(((u8 *)&fcs_bytes) + bytes_in_prev, fcs_p2, last_frag_sz);
673-
674-
return fcs_bytes;
646+
return __get_unaligned_cpu32(fcs_bytes);
675647
}
676648

677649
static inline void mlx5e_handle_csum(struct net_device *netdev,
@@ -693,8 +665,9 @@ static inline void mlx5e_handle_csum(struct net_device *netdev,
693665
skb->ip_summed = CHECKSUM_COMPLETE;
694666
skb->csum = csum_unfold((__force __sum16)cqe->check_sum);
695667
if (unlikely(netdev->features & NETIF_F_RXFCS))
696-
skb->csum = csum_add(skb->csum,
697-
(__force __wsum)mlx5e_get_fcs(skb));
668+
skb->csum = csum_block_add(skb->csum,
669+
(__force __wsum)mlx5e_get_fcs(skb),
670+
skb->len - ETH_FCS_LEN);
698671
rq->stats.csum_complete++;
699672
return;
700673
}

0 commit comments

Comments
 (0)