net/mlx5e: RX, verify received packet size in Linear Striding RQ
authorMoshe Shemesh <moshe@mellanox.com>
Thu, 11 Oct 2018 04:31:10 +0000 (07:31 +0300)
committerSaeed Mahameed <saeedm@mellanox.com>
Mon, 19 Nov 2018 22:35:04 +0000 (14:35 -0800)
In case of striding RQ, we use  MPWRQ (Multi Packet WQE RQ), which means
that WQE (RX descriptor) can be used for many packets and so the WQE is
much bigger than MTU.  In virtualization setups where the port mtu can
be larger than the vf mtu, if received packet is bigger than MTU, it
won't be dropped by HW on too small receive WQE. If we use linear SKB in
striding RQ, since each stride has room for mtu size payload and skb
info, an oversized packet can lead to crash for crossing allocated page
boundary upon the call to build_skb. So driver needs to check packet
size and drop it.

Introduce new SW rx counter, rx_oversize_pkts_sw_drop, which counts the
number of packets dropped by the driver for being too large.

As a new field is added to the RQ struct, re-open the channels whenever
this field is being used in datapath (i.e., in the case of linear
Striding RQ).

Fixes: 619a8f2a42f1 ("net/mlx5e: Use linear SKB in Striding RQ")
Signed-off-by: Moshe Shemesh <moshe@mellanox.com>
Reviewed-by: Tariq Toukan <tariqt@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
drivers/net/ethernet/mellanox/mlx5/core/en_stats.h

index d7fbd5b6ac957d0b3b9ed9fa0000eed1ae0e73bc..11832480292646c9fcbd881402ed95497218c67e 100644 (file)
@@ -569,6 +569,7 @@ struct mlx5e_rq {
 
        unsigned long          state;
        int                    ix;
+       unsigned int           hw_mtu;
 
        struct net_dim         dim; /* Dynamic Interrupt Moderation */
 
index 25b09bb68e8b308f7ca89f24fa195709b718876d..871313d6b34d1b315e6ef1a9c07cba396de14186 100644 (file)
@@ -502,6 +502,7 @@ static int mlx5e_alloc_rq(struct mlx5e_channel *c,
        rq->channel = c;
        rq->ix      = c->ix;
        rq->mdev    = mdev;
+       rq->hw_mtu  = MLX5E_SW2HW_MTU(params, params->sw_mtu);
        rq->stats   = &c->priv->channel_stats[c->ix].rq;
 
        rq->xdp_prog = params->xdp_prog ? bpf_prog_inc(params->xdp_prog) : NULL;
@@ -3766,10 +3767,11 @@ int mlx5e_change_mtu(struct net_device *netdev, int new_mtu,
        }
 
        if (params->rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) {
+               bool is_linear = mlx5e_rx_mpwqe_is_linear_skb(priv->mdev, &new_channels.params);
                u8 ppw_old = mlx5e_mpwqe_log_pkts_per_wqe(params);
                u8 ppw_new = mlx5e_mpwqe_log_pkts_per_wqe(&new_channels.params);
 
-               reset = reset && (ppw_old != ppw_new);
+               reset = reset && (is_linear || (ppw_old != ppw_new));
        }
 
        if (!reset) {
index 79638dcbae78395fb723c9bf3fa877e7a42d91cd..16985ca3248d72c4001f5997f0ead50ac10e6d0a 100644 (file)
@@ -1104,6 +1104,12 @@ mlx5e_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi,
        u32 frag_size;
        bool consumed;
 
+       /* Check packet size. Note LRO doesn't use linear SKB */
+       if (unlikely(cqe_bcnt > rq->hw_mtu)) {
+               rq->stats->oversize_pkts_sw_drop++;
+               return NULL;
+       }
+
        va             = page_address(di->page) + head_offset;
        data           = va + rx_headroom;
        frag_size      = MLX5_SKB_FRAG_SZ(rx_headroom + cqe_bcnt32);
index 1e55b9c27ffc0f1c3c20156458d85765cd5d6703..3e99d0728b2f2c5366a13f01400d4354d3c80b2c 100644 (file)
@@ -83,6 +83,7 @@ static const struct counter_desc sw_stats_desc[] = {
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_wqe_err) },
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_mpwqe_filler_cqes) },
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_mpwqe_filler_strides) },
+       { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_oversize_pkts_sw_drop) },
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_buff_alloc_err) },
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_cqe_compress_blks) },
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_cqe_compress_pkts) },
@@ -161,6 +162,7 @@ void mlx5e_grp_sw_update_stats(struct mlx5e_priv *priv)
                s->rx_wqe_err   += rq_stats->wqe_err;
                s->rx_mpwqe_filler_cqes    += rq_stats->mpwqe_filler_cqes;
                s->rx_mpwqe_filler_strides += rq_stats->mpwqe_filler_strides;
+               s->rx_oversize_pkts_sw_drop += rq_stats->oversize_pkts_sw_drop;
                s->rx_buff_alloc_err += rq_stats->buff_alloc_err;
                s->rx_cqe_compress_blks += rq_stats->cqe_compress_blks;
                s->rx_cqe_compress_pkts += rq_stats->cqe_compress_pkts;
@@ -1189,6 +1191,7 @@ static const struct counter_desc rq_stats_desc[] = {
        { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, wqe_err) },
        { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, mpwqe_filler_cqes) },
        { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, mpwqe_filler_strides) },
+       { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, oversize_pkts_sw_drop) },
        { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, buff_alloc_err) },
        { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, cqe_compress_blks) },
        { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, cqe_compress_pkts) },
index 77f74ce11280e26a461343adc92e56d63b387812..3f8e870ef4c903bbca01e894bc2608bbb8ead182 100644 (file)
@@ -96,6 +96,7 @@ struct mlx5e_sw_stats {
        u64 rx_wqe_err;
        u64 rx_mpwqe_filler_cqes;
        u64 rx_mpwqe_filler_strides;
+       u64 rx_oversize_pkts_sw_drop;
        u64 rx_buff_alloc_err;
        u64 rx_cqe_compress_blks;
        u64 rx_cqe_compress_pkts;
@@ -193,6 +194,7 @@ struct mlx5e_rq_stats {
        u64 wqe_err;
        u64 mpwqe_filler_cqes;
        u64 mpwqe_filler_strides;
+       u64 oversize_pkts_sw_drop;
        u64 buff_alloc_err;
        u64 cqe_compress_blks;
        u64 cqe_compress_pkts;