Re: [PATCH net] net/mlx5e: fix csum adjustments caused by RXFCS
From: Eric Dumazet Date: Tue, 30 Oct 2018 00:57:25 -0700 > 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 88078d98d1bb "net: pskb_trim_rcsum() > and CHECKSUM_COMPLETE are friends"), the whole skb csum was thrown away, > so RXFCS changes were ignored. > > Then before commit d55bef5059dd ("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: 902a545904c7 ("net/mlx5e: When RXFCS is set, add FCS data into > checksum calculation") > Reported-by: Paweł Staszewski > Signed-off-by: Eric Dumazet Applied and queued up for -stable.
Re: [PATCH net] net/mlx5e: fix csum adjustments caused by RXFCS
On 10/30/2018 9:57 AM, Eric Dumazet wrote: > 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 88078d98d1bb "net: pskb_trim_rcsum() > and CHECKSUM_COMPLETE are friends"), the whole skb csum was thrown away, > so RXFCS changes were ignored. > > Then before commit d55bef5059dd ("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: 902a545904c7 ("net/mlx5e: When RXFCS is set, add FCS data into > checksum calculation") > Reported-by: Paweł Staszewski > Signed-off-by: Eric Dumazet > Cc: Eran Ben Elisha > Cc: Saeed Mahameed > Cc: Dimitris Michailidis > Cc: Cong Wang > Cc: Paweł Staszewski > --- > .../net/ethernet/mellanox/mlx5/core/en_rx.c | 45 --- > 1 file changed, 9 insertions(+), 36 deletions(-) Thanks for the modification! We run a direct test we had for this scenario and it passed. Reviewed-by: Eran Ben Elisha Tested-By: Maria Pasechnik
Re: [PATCH net] net/mlx5e: fix csum adjustments caused by RXFCS
On Tue, Oct 30, 2018 at 11:59 AM Cong Wang wrote: > I wonder how compiler recognizes it as "never fail" when marked with > __must_check. __must_check means that you can not ignore the return value of a function. Here we do use the return value. Also prior code was not checking skb->length so really my patch does add explicit check if in the future skb->len gets wrong after a bug is added in this driver. (A NULL deref will trap the bug, instead of potentially reading garbage from skb->data)
Re: [PATCH net] net/mlx5e: fix csum adjustments caused by RXFCS
On Tue, Oct 30, 2018 at 11:42 AM Eric Dumazet wrote: > > On Tue, Oct 30, 2018 at 11:09 AM Cong Wang wrote: > > > At least skb_header_pointer() is marked as __must_check, I don't see > > you check its return value here. > > This can not fail here. > > skb->length must be above 14+4 at this point. Never say it is wrong, just saying what compiler thinks. > > My compiler seems to be okay with that. I wonder how compiler recognizes it as "never fail" when marked with __must_check.
Re: [PATCH net] net/mlx5e: fix csum adjustments caused by RXFCS
From: Cong Wang Date: Tue, 30 Oct 2018 11:09:21 -0700 > On Tue, Oct 30, 2018 at 12:57 AM Eric Dumazet wrote: >> -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); > > At least skb_header_pointer() is marked as __must_check, I don't see > you check its return value here. In this case we reasonably know it is guaranteed to succeed though. We know skb->len is non-zero and we are asking for the skb->len - 1 byte or something like that.
Re: [PATCH net] net/mlx5e: fix csum adjustments caused by RXFCS
On Tue, Oct 30, 2018 at 11:09 AM Cong Wang wrote: > At least skb_header_pointer() is marked as __must_check, I don't see > you check its return value here. This can not fail here. skb->length must be above 14+4 at this point. My compiler seems to be okay with that.
Re: [PATCH net] net/mlx5e: fix csum adjustments caused by RXFCS
On Tue, Oct 30, 2018 at 12:57 AM Eric Dumazet wrote: > -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); At least skb_header_pointer() is marked as __must_check, I don't see you check its return value here.
[PATCH net] net/mlx5e: fix csum adjustments caused by RXFCS
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 88078d98d1bb "net: pskb_trim_rcsum() and CHECKSUM_COMPLETE are friends"), the whole skb csum was thrown away, so RXFCS changes were ignored. Then before commit d55bef5059dd ("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: 902a545904c7 ("net/mlx5e: When RXFCS is set, add FCS data into checksum calculation") Reported-by: Paweł Staszewski Signed-off-by: Eric Dumazet Cc: Eran Ben Elisha Cc: Saeed Mahameed Cc: Dimitris Michailidis Cc: Cong Wang Cc: Paweł Staszewski --- .../net/ethernet/mellanox/mlx5/core/en_rx.c | 45 --- 1 file changed, 9 insertions(+), 36 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index 94224c22ecc310a87b6715051e335446f29bec03..79638dcbae78395fb723c9bf3fa877e7a42d91cd 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -713,43 +713,15 @@ static inline void mlx5e_enable_ecn(struct mlx5e_rq *rq, struct sk_buff *skb) rq->stats->ecn_mark += !!rc; } -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 u8 get_ip_proto(struct sk_buff *skb, __be16 proto) @@ -797,8 +769,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; } -- 2.19.1.568.g152ad8e336-goog