| From foo@baz Sun Feb 10 12:47:17 CET 2019 |
| From: Cong Wang <xiyou.wangcong@gmail.com> |
| Date: Mon, 3 Dec 2018 22:14:04 -0800 |
| Subject: net/mlx5e: Force CHECKSUM_UNNECESSARY for short ethernet frames |
| |
| From: Cong Wang <xiyou.wangcong@gmail.com> |
| |
| [ Upstream commit e8c8b53ccaff568fef4c13a6ccaf08bf241aa01a ] |
| |
| When an ethernet frame is padded to meet the minimum ethernet frame |
| size, the padding octets are not covered by the hardware checksum. |
| Fortunately the padding octets are usually zero's, which don't affect |
| checksum. However, we have a switch which pads non-zero octets, this |
| causes kernel hardware checksum fault repeatedly. |
| |
| Prior to: |
| commit '88078d98d1bb ("net: pskb_trim_rcsum() and CHECKSUM_COMPLETE ...")' |
| skb checksum was forced to be CHECKSUM_NONE when padding is detected. |
| After it, we need to keep skb->csum updated, like what we do for RXFCS. |
| However, fixing up CHECKSUM_COMPLETE requires to verify and parse IP |
| headers, it is not worthy the effort as the packets are so small that |
| CHECKSUM_COMPLETE can't save anything. |
| |
| Fixes: 88078d98d1bb ("net: pskb_trim_rcsum() and CHECKSUM_COMPLETE are friends"), |
| Cc: Eric Dumazet <edumazet@google.com> |
| Cc: Tariq Toukan <tariqt@mellanox.com> |
| Cc: Nikola Ciprich <nikola.ciprich@linuxbox.cz> |
| Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> |
| Signed-off-by: Saeed Mahameed <saeedm@mellanox.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 14 ++++++++++++++ |
| 1 file changed, 14 insertions(+) |
| |
| --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c |
| +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c |
| @@ -646,6 +646,8 @@ static u32 mlx5e_get_fcs(const struct sk |
| return __get_unaligned_cpu32(fcs_bytes); |
| } |
| |
| +#define short_frame(size) ((size) <= ETH_ZLEN + ETH_FCS_LEN) |
| + |
| static inline void mlx5e_handle_csum(struct net_device *netdev, |
| struct mlx5_cqe64 *cqe, |
| struct mlx5e_rq *rq, |
| @@ -661,6 +663,17 @@ static inline void mlx5e_handle_csum(str |
| return; |
| } |
| |
| + /* CQE csum doesn't cover padding octets in short ethernet |
| + * frames. And the pad field is appended prior to calculating |
| + * and appending the FCS field. |
| + * |
| + * Detecting these padded frames requires to verify and parse |
| + * IP headers, so we simply force all those small frames to be |
| + * CHECKSUM_UNNECESSARY even if they are not padded. |
| + */ |
| + if (short_frame(skb->len)) |
| + goto csum_unnecessary; |
| + |
| if (is_first_ethertype_ip(skb)) { |
| skb->ip_summed = CHECKSUM_COMPLETE; |
| skb->csum = csum_unfold((__force __sum16)cqe->check_sum); |
| @@ -672,6 +685,7 @@ static inline void mlx5e_handle_csum(str |
| return; |
| } |
| |
| +csum_unnecessary: |
| if (likely((cqe->hds_ip_ext & CQE_L3_OK) && |
| (cqe->hds_ip_ext & CQE_L4_OK))) { |
| skb->ip_summed = CHECKSUM_UNNECESSARY; |