]> git.droids-corp.org - dpdk.git/commitdiff
net/mlx5: fix age action pool protection
authorJiawei Wang <jiaweiw@nvidia.com>
Mon, 1 Nov 2021 06:30:39 +0000 (08:30 +0200)
committerRaslan Darawsheh <rasland@nvidia.com>
Mon, 1 Nov 2021 13:53:35 +0000 (14:53 +0100)
The age action with flows creation could be supported on the multiple
threads. The age pools were created to manage the age resources, if
there is no room in the current pool then resize the age pool to the new
pool size and free the old one.

There's a race condition while one thread resizes the age pool and the
old pool resource be freed, and another thread query the age action
value of the old pool so the queried value is invalid.

This patch uses the read-write lock to protect the pool resource while
resizing and query.

Fixes: a5835d530f00 ("net/mlx5: optimize Rx queue match")
Cc: stable@dpdk.org
Signed-off-by: Jiawei Wang <jiaweiw@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
drivers/net/mlx5/mlx5.c
drivers/net/mlx5/mlx5.h
drivers/net/mlx5/mlx5_flow.c
drivers/net/mlx5/mlx5_flow_aso.c
drivers/net/mlx5/mlx5_flow_dv.c

index 4fe7e345781fecea34efb0ccc57daaee72326491..b90752c56df759073260904cc38a3ec74ea45551 100644 (file)
@@ -450,7 +450,7 @@ mlx5_flow_aso_age_mng_init(struct mlx5_dev_ctx_shared *sh)
                mlx5_free(sh->aso_age_mng);
                return -1;
        }
-       rte_spinlock_init(&sh->aso_age_mng->resize_sl);
+       rte_rwlock_init(&sh->aso_age_mng->resize_rwl);
        rte_spinlock_init(&sh->aso_age_mng->free_sl);
        LIST_INIT(&sh->aso_age_mng->free);
        return 0;
index a3b2a3d8e51fc3c145e80fd0b1493574210869db..5e88dfcfea1623ab5f5eadab7c8c850d856e6f57 100644 (file)
@@ -549,7 +549,7 @@ struct mlx5_aso_age_mng {
        struct mlx5_aso_age_pool **pools;
        uint16_t n; /* Total number of pools. */
        uint16_t next; /* Number of pools in use, index of next free pool. */
-       rte_spinlock_t resize_sl; /* Lock for resize objects. */
+       rte_rwlock_t resize_rwl; /* Lock for resize objects. */
        rte_spinlock_t free_sl; /* Lock for free list access. */
        struct aso_age_list free; /* Free age actions list - ready to use. */
        struct mlx5_aso_sq aso_sq; /* ASO queue objects. */
index d222914cf5f923db86c12f4d6a60334b42bb4c49..d5ed673891f27372df26997ad633d3060e00b5e1 100644 (file)
@@ -3675,8 +3675,11 @@ flow_aso_age_get_by_idx(struct rte_eth_dev *dev, uint32_t age_idx)
        uint16_t offset = (age_idx >> 16) & UINT16_MAX;
        struct mlx5_priv *priv = dev->data->dev_private;
        struct mlx5_aso_age_mng *mng = priv->sh->aso_age_mng;
-       struct mlx5_aso_age_pool *pool = mng->pools[pool_idx];
+       struct mlx5_aso_age_pool *pool;
 
+       rte_rwlock_read_lock(&mng->resize_rwl);
+       pool = mng->pools[pool_idx];
+       rte_rwlock_read_unlock(&mng->resize_rwl);
        return &pool->actions[offset - 1];
 }
 
index 1fc1000b01c43f39e9a582ca218c9d212b5623db..bcdad31330738de30c2c4ef8d0129a0b1ffa7c6a 100644 (file)
@@ -417,9 +417,9 @@ mlx5_aso_sq_enqueue_burst(struct mlx5_aso_age_mng *mng, uint16_t n)
                wqe = &sq->sq_obj.aso_wqes[sq->head & mask];
                rte_prefetch0(&sq->sq_obj.aso_wqes[(sq->head + 1) & mask]);
                /* Fill next WQE. */
-               rte_spinlock_lock(&mng->resize_sl);
+               rte_rwlock_read_lock(&mng->resize_rwl);
                pool = mng->pools[sq->next];
-               rte_spinlock_unlock(&mng->resize_sl);
+               rte_rwlock_read_unlock(&mng->resize_rwl);
                sq->elts[sq->head & mask].pool = pool;
                wqe->general_cseg.misc =
                                rte_cpu_to_be_32(((struct mlx5_devx_obj *)
@@ -635,9 +635,9 @@ mlx5_flow_aso_alarm(void *arg)
        uint32_t us = 100u;
        uint16_t n;
 
-       rte_spinlock_lock(&sh->aso_age_mng->resize_sl);
+       rte_rwlock_read_lock(&sh->aso_age_mng->resize_rwl);
        n = sh->aso_age_mng->next;
-       rte_spinlock_unlock(&sh->aso_age_mng->resize_sl);
+       rte_rwlock_read_unlock(&sh->aso_age_mng->resize_rwl);
        mlx5_aso_completion_handle(sh);
        if (sq->next == n) {
                /* End of loop: wait 1 second. */
index 852993089782fa3fa2051425b3f599f9c27ec5c5..22081dddd31d397990b017633471aadebc57c421 100644 (file)
@@ -11857,18 +11857,18 @@ flow_dv_age_pool_create(struct rte_eth_dev *dev,
        }
        pool->flow_hit_aso_obj = obj;
        pool->time_of_last_age_check = MLX5_CURR_TIME_SEC;
-       rte_spinlock_lock(&mng->resize_sl);
+       rte_rwlock_write_lock(&mng->resize_rwl);
        pool->index = mng->next;
        /* Resize pools array if there is no room for the new pool in it. */
        if (pool->index == mng->n && flow_dv_aso_age_pools_resize(dev)) {
                claim_zero(mlx5_devx_cmd_destroy(obj));
                mlx5_free(pool);
-               rte_spinlock_unlock(&mng->resize_sl);
+               rte_rwlock_write_unlock(&mng->resize_rwl);
                return NULL;
        }
        mng->pools[pool->index] = pool;
        mng->next++;
-       rte_spinlock_unlock(&mng->resize_sl);
+       rte_rwlock_write_unlock(&mng->resize_rwl);
        /* Assign the first action in the new pool, the rest go to free list. */
        *age_free = &pool->actions[0];
        for (i = 1; i < MLX5_ASO_AGE_ACTIONS_PER_POOL; i++) {