net/mlx5: fix xstats reset reinitialization
authorShiri Kuzin <shirik@nvidia.com>
Mon, 19 Oct 2020 06:36:50 +0000 (09:36 +0300)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 3 Nov 2020 22:24:25 +0000 (23:24 +0100)
The mlx5_xstats_reset clears the device extended statistics.
In this function the driver may reinitialize the structures
that are used to read device counters.

In case of reinitialization, the number of counters may
change, which wouldn't be taken into account by the
reset API callback and can cause a segmentation fault.

This issue is fixed by allocating the counters size after
the reinitialization.

Fixes: a4193ae3bc4f ("net/mlx5: support extended statistics")
Cc: stable@dpdk.org
Reported-by: Ralf Hoffmann <ralf.hoffmann@allegro-packets.com>
Signed-off-by: Shiri Kuzin <shirik@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
drivers/net/mlx5/mlx5_stats.c

index e30542e..82d4d4a 100644 (file)
@@ -17,6 +17,7 @@
 #include "mlx5_defs.h"
 #include "mlx5.h"
 #include "mlx5_rxtx.h"
+#include "mlx5_malloc.h"
 
 /**
  * DPDK callback to get extended device statistics.
@@ -216,8 +217,7 @@ mlx5_xstats_reset(struct rte_eth_dev *dev)
        struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
        int stats_n;
        unsigned int i;
-       unsigned int n = xstats_ctrl->mlx5_stats_n;
-       uint64_t counters[n];
+       uint64_t *counters;
        int ret;
 
        stats_n = mlx5_os_get_stats_n(dev);
@@ -228,17 +228,29 @@ mlx5_xstats_reset(struct rte_eth_dev *dev)
        }
        if (xstats_ctrl->stats_n != stats_n)
                mlx5_os_stats_init(dev);
+       counters =  mlx5_malloc(MLX5_MEM_SYS, sizeof(*counters) *
+                       xstats_ctrl->mlx5_stats_n, 0,
+                       SOCKET_ID_ANY);
+       if (!counters) {
+               DRV_LOG(WARNING, "port %u unable to allocate memory for xstats "
+                               "counters",
+                    dev->data->port_id);
+               rte_errno = ENOMEM;
+               return -rte_errno;
+       }
        ret = mlx5_os_read_dev_counters(dev, counters);
        if (ret) {
                DRV_LOG(ERR, "port %u cannot read device counters: %s",
                        dev->data->port_id, strerror(rte_errno));
+               mlx5_free(counters);
                return ret;
        }
-       for (i = 0; i != n; ++i) {
+       for (i = 0; i != xstats_ctrl->mlx5_stats_n; ++i) {
                xstats_ctrl->base[i] = counters[i];
                xstats_ctrl->hw_stats[i] = 0;
        }
        mlx5_txpp_xstats_reset(dev);
+       mlx5_free(counters);
        return 0;
 }