net/mlx5: add ID generation

When splitting flows for example in hairpin / metering, there is a need
to combine the flows. This is done using ID.
This commit introduce a simple way to generate such IDs.

The reason why bitmap was not used is due to fact that the release and
allocation are O(n) while in the chosen approch the allocation and
release are O(1)

Signed-off-by: Ori Kam <orika@mellanox.com>
Acked-by: Viacheslav Ovsiienko <viacheslavo@mellanox.com>
This commit is contained in:
Ori Kam 2019-10-30 23:53:21 +00:00 committed by Ferruh Yigit
parent 70d84dc797
commit 830d209161
2 changed files with 133 additions and 1 deletions

View File

@ -178,6 +178,124 @@ struct mlx5_dev_spawn_data {
static LIST_HEAD(, mlx5_ibv_shared) mlx5_ibv_list = LIST_HEAD_INITIALIZER();
static pthread_mutex_t mlx5_ibv_list_mutex = PTHREAD_MUTEX_INITIALIZER;
#define MLX5_FLOW_MIN_ID_POOL_SIZE 512
#define MLX5_ID_GENERATION_ARRAY_FACTOR 16
/**
* Allocate ID pool structure.
*
* @return
* Pointer to pool object, NULL value otherwise.
*/
struct mlx5_flow_id_pool *
mlx5_flow_id_pool_alloc(void)
{
struct mlx5_flow_id_pool *pool;
void *mem;
pool = rte_zmalloc("id pool allocation", sizeof(*pool),
RTE_CACHE_LINE_SIZE);
if (!pool) {
DRV_LOG(ERR, "can't allocate id pool");
rte_errno = ENOMEM;
return NULL;
}
mem = rte_zmalloc("", MLX5_FLOW_MIN_ID_POOL_SIZE * sizeof(uint32_t),
RTE_CACHE_LINE_SIZE);
if (!mem) {
DRV_LOG(ERR, "can't allocate mem for id pool");
rte_errno = ENOMEM;
goto error;
}
pool->free_arr = mem;
pool->curr = pool->free_arr;
pool->last = pool->free_arr + MLX5_FLOW_MIN_ID_POOL_SIZE;
pool->base_index = 0;
return pool;
error:
rte_free(pool);
return NULL;
}
/**
* Release ID pool structure.
*
* @param[in] pool
* Pointer to flow id pool object to free.
*/
void
mlx5_flow_id_pool_release(struct mlx5_flow_id_pool *pool)
{
rte_free(pool->free_arr);
rte_free(pool);
}
/**
* Generate ID.
*
* @param[in] pool
* Pointer to flow id pool.
* @param[out] id
* The generated ID.
*
* @return
* 0 on success, error value otherwise.
*/
uint32_t
mlx5_flow_id_get(struct mlx5_flow_id_pool *pool, uint32_t *id)
{
if (pool->curr == pool->free_arr) {
if (pool->base_index == UINT32_MAX) {
rte_errno = ENOMEM;
DRV_LOG(ERR, "no free id");
return -rte_errno;
}
*id = ++pool->base_index;
return 0;
}
*id = *(--pool->curr);
return 0;
}
/**
* Release ID.
*
* @param[in] pool
* Pointer to flow id pool.
* @param[out] id
* The generated ID.
*
* @return
* 0 on success, error value otherwise.
*/
uint32_t
mlx5_flow_id_release(struct mlx5_flow_id_pool *pool, uint32_t id)
{
uint32_t size;
uint32_t size2;
void *mem;
if (pool->curr == pool->last) {
size = pool->curr - pool->free_arr;
size2 = size * MLX5_ID_GENERATION_ARRAY_FACTOR;
assert(size2 > size);
mem = rte_malloc("", size2 * sizeof(uint32_t), 0);
if (!mem) {
DRV_LOG(ERR, "can't allocate mem for id pool");
rte_errno = ENOMEM;
return -rte_errno;
}
memcpy(mem, pool->free_arr, size * sizeof(uint32_t));
rte_free(pool->free_arr);
pool->free_arr = mem;
pool->curr = pool->free_arr + size;
pool->last = pool->free_arr + size2;
}
*pool->curr = id;
pool->curr++;
return 0;
}
/**
* Initialize the counters management structure.
*
@ -328,7 +446,7 @@ mlx5_alloc_shared_ibctx(const struct mlx5_dev_spawn_data *spawn)
struct mlx5_devx_tis_attr tis_attr = { 0 };
#endif
assert(spawn);
assert(spawn);
/* Secondary process should not create the shared context. */
assert(rte_eal_process_type() == RTE_PROC_PRIMARY);
pthread_mutex_lock(&mlx5_ibv_list_mutex);

View File

@ -527,8 +527,22 @@ struct mlx5_flow_driver_ops {
#define MLX5_CNT_CONTAINER_UNUSED(sh, batch, thread) (&(sh)->cmng.ccont \
[(~((sh)->cmng.mhi[batch] >> (thread)) & 0x1) * 2 + (batch)])
/* ID generation structure. */
struct mlx5_flow_id_pool {
uint32_t *free_arr; /**< Pointer to the a array of free values. */
uint32_t base_index;
/**< The next index that can be used without any free elements. */
uint32_t *curr; /**< Pointer to the index to pop. */
uint32_t *last; /**< Pointer to the last element in the empty arrray. */
};
/* mlx5_flow.c */
struct mlx5_flow_id_pool *mlx5_flow_id_pool_alloc(void);
void mlx5_flow_id_pool_release(struct mlx5_flow_id_pool *pool);
uint32_t mlx5_flow_id_get(struct mlx5_flow_id_pool *pool, uint32_t *id);
uint32_t mlx5_flow_id_release(struct mlx5_flow_id_pool *pool,
uint32_t id);
int mlx5_flow_group_to_table(const struct rte_flow_attr *attributes,
bool external, uint32_t group, uint32_t *table,
struct rte_flow_error *error);