net/mlx5: make header reformat action thread safe

To support multi-thread flow insertion, this patch updates flow header
reformat action list to use thread safe hash list with write-most mode.

Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
This commit is contained in:
Suanming Mou 2020-10-28 17:33:39 +08:00 committed by Ferruh Yigit
parent f7f73ac130
commit f961fd490f
3 changed files with 116 additions and 84 deletions

View File

@ -264,12 +264,17 @@ mlx5_alloc_shared_dr(struct mlx5_priv *priv)
snprintf(s, sizeof(s), "%s_encaps_decaps", sh->ibdev_name);
sh->encaps_decaps = mlx5_hlist_create(s,
MLX5_FLOW_ENCAP_DECAP_HTABLE_SZ,
0, 0, NULL, NULL, NULL);
0, MLX5_HLIST_DIRECT_KEY |
MLX5_HLIST_WRITE_MOST,
flow_dv_encap_decap_create_cb,
flow_dv_encap_decap_match_cb,
flow_dv_encap_decap_remove_cb);
if (!sh->encaps_decaps) {
DRV_LOG(ERR, "encap decap hash creation failed");
err = ENOMEM;
goto error;
}
sh->encaps_decaps->ctx = sh;
#endif
#ifdef HAVE_MLX5DV_DR
void *domain;

View File

@ -1439,4 +1439,11 @@ struct mlx5_hlist_entry *flow_dv_mreg_create_cb(struct mlx5_hlist *list,
void flow_dv_mreg_remove_cb(struct mlx5_hlist *list,
struct mlx5_hlist_entry *entry);
int flow_dv_encap_decap_match_cb(struct mlx5_hlist *list,
struct mlx5_hlist_entry *entry,
uint64_t key, void *cb_ctx);
struct mlx5_hlist_entry *flow_dv_encap_decap_create_cb(struct mlx5_hlist *list,
uint64_t key, void *cb_ctx);
void flow_dv_encap_decap_remove_cb(struct mlx5_hlist *list,
struct mlx5_hlist_entry *entry);
#endif /* RTE_PMD_MLX5_FLOW_H_ */

View File

@ -2784,21 +2784,27 @@ flow_dv_validate_action_raw_encap_decap
/**
* Match encap_decap resource.
*
* @param list
* Pointer to the hash list.
* @param entry
* Pointer to exist resource entry object.
* @param ctx
* @param key
* Key of the new entry.
* @param ctx_cb
* Pointer to new encap_decap resource.
*
* @return
* 0 on matching, -1 otherwise.
* 0 on matching, none-zero otherwise.
*/
static int
flow_dv_encap_decap_resource_match(struct mlx5_hlist_entry *entry, void *ctx)
int
flow_dv_encap_decap_match_cb(struct mlx5_hlist *list __rte_unused,
struct mlx5_hlist_entry *entry,
uint64_t key __rte_unused, void *cb_ctx)
{
struct mlx5_flow_dv_encap_decap_resource *resource;
struct mlx5_flow_cb_ctx *ctx = cb_ctx;
struct mlx5_flow_dv_encap_decap_resource *resource = ctx->data;
struct mlx5_flow_dv_encap_decap_resource *cache_resource;
resource = (struct mlx5_flow_dv_encap_decap_resource *)ctx;
cache_resource = container_of(entry,
struct mlx5_flow_dv_encap_decap_resource,
entry);
@ -2814,6 +2820,63 @@ flow_dv_encap_decap_resource_match(struct mlx5_hlist_entry *entry, void *ctx)
return -1;
}
/**
* Allocate encap_decap resource.
*
* @param list
* Pointer to the hash list.
* @param entry
* Pointer to exist resource entry object.
* @param ctx_cb
* Pointer to new encap_decap resource.
*
* @return
* 0 on matching, none-zero otherwise.
*/
struct mlx5_hlist_entry *
flow_dv_encap_decap_create_cb(struct mlx5_hlist *list,
uint64_t key __rte_unused,
void *cb_ctx)
{
struct mlx5_dev_ctx_shared *sh = list->ctx;
struct mlx5_flow_cb_ctx *ctx = cb_ctx;
struct mlx5dv_dr_domain *domain;
struct mlx5_flow_dv_encap_decap_resource *resource = ctx->data;
struct mlx5_flow_dv_encap_decap_resource *cache_resource;
uint32_t idx;
int ret;
if (resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB)
domain = sh->fdb_domain;
else if (resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_NIC_RX)
domain = sh->rx_domain;
else
domain = sh->tx_domain;
/* Register new encap/decap resource. */
cache_resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_DECAP_ENCAP],
&idx);
if (!cache_resource) {
rte_flow_error_set(ctx->error, ENOMEM,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
"cannot allocate resource memory");
return NULL;
}
*cache_resource = *resource;
cache_resource->idx = idx;
ret = mlx5_flow_os_create_flow_action_packet_reformat
(sh->ctx, domain, cache_resource,
&cache_resource->action);
if (ret) {
mlx5_ipool_free(sh->ipool[MLX5_IPOOL_DECAP_ENCAP], idx);
rte_flow_error_set(ctx->error, ENOMEM,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
NULL, "cannot create action");
return NULL;
}
return &cache_resource->entry;
}
/**
* Find existing encap/decap resource or create and register a new one.
*
@ -2838,8 +2901,6 @@ flow_dv_encap_decap_resource_register
{
struct mlx5_priv *priv = dev->data->dev_private;
struct mlx5_dev_ctx_shared *sh = priv->sh;
struct mlx5_flow_dv_encap_decap_resource *cache_resource;
struct mlx5dv_dr_domain *domain;
struct mlx5_hlist_entry *entry;
union mlx5_flow_encap_decap_key encap_decap_key = {
{
@ -2850,69 +2911,22 @@ flow_dv_encap_decap_resource_register
.cksum = 0,
}
};
int ret;
struct mlx5_flow_cb_ctx ctx = {
.error = error,
.data = resource,
};
resource->flags = dev_flow->dv.group ? 0 : 1;
if (resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB)
domain = sh->fdb_domain;
else if (resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_NIC_RX)
domain = sh->rx_domain;
else
domain = sh->tx_domain;
encap_decap_key.cksum = __rte_raw_cksum(resource->buf,
resource->size, 0);
resource->entry.key = encap_decap_key.v64;
/* Lookup a matching resource from cache. */
entry = mlx5_hlist_lookup_ex(sh->encaps_decaps, resource->entry.key,
flow_dv_encap_decap_resource_match,
(void *)resource);
if (entry) {
cache_resource = container_of(entry,
struct mlx5_flow_dv_encap_decap_resource, entry);
DRV_LOG(DEBUG, "encap/decap resource %p: refcnt %d++",
(void *)cache_resource,
__atomic_load_n(&cache_resource->refcnt,
__ATOMIC_RELAXED));
__atomic_fetch_add(&cache_resource->refcnt, 1,
__ATOMIC_RELAXED);
dev_flow->handle->dvh.rix_encap_decap = cache_resource->idx;
dev_flow->dv.encap_decap = cache_resource;
return 0;
}
/* Register new encap/decap resource. */
cache_resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_DECAP_ENCAP],
&dev_flow->handle->dvh.rix_encap_decap);
if (!cache_resource)
return rte_flow_error_set(error, ENOMEM,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
"cannot allocate resource memory");
*cache_resource = *resource;
cache_resource->idx = dev_flow->handle->dvh.rix_encap_decap;
ret = mlx5_flow_os_create_flow_action_packet_reformat
(sh->ctx, domain, cache_resource,
&cache_resource->action);
if (ret) {
mlx5_free(cache_resource);
return rte_flow_error_set(error, ENOMEM,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
NULL, "cannot create action");
}
__atomic_store_n(&cache_resource->refcnt, 1, __ATOMIC_RELAXED);
if (mlx5_hlist_insert_ex(sh->encaps_decaps, &cache_resource->entry,
flow_dv_encap_decap_resource_match,
(void *)cache_resource)) {
claim_zero(mlx5_flow_os_destroy_flow_action
(cache_resource->action));
mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_DECAP_ENCAP],
cache_resource->idx);
return rte_flow_error_set(error, EEXIST,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
NULL, "action exist");
}
dev_flow->dv.encap_decap = cache_resource;
DRV_LOG(DEBUG, "new encap/decap resource %p: refcnt %d++",
(void *)cache_resource,
__atomic_load_n(&cache_resource->refcnt, __ATOMIC_RELAXED));
entry = mlx5_hlist_register(sh->encaps_decaps, resource->entry.key,
&ctx);
if (!entry)
return -rte_errno;
resource = container_of(entry, typeof(*resource), entry);
dev_flow->dv.encap_decap = resource;
dev_flow->handle->dvh.rix_encap_decap = resource->idx;
return 0;
}
@ -10411,6 +10425,26 @@ flow_dv_matcher_release(struct rte_eth_dev *dev,
return 1;
}
/**
* Release encap_decap resource.
*
* @param list
* Pointer to the hash list.
* @param entry
* Pointer to exist resource entry object.
*/
void
flow_dv_encap_decap_remove_cb(struct mlx5_hlist *list,
struct mlx5_hlist_entry *entry)
{
struct mlx5_dev_ctx_shared *sh = list->ctx;
struct mlx5_flow_dv_encap_decap_resource *res =
container_of(entry, typeof(*res), entry);
claim_zero(mlx5_flow_os_destroy_flow_action(res->action));
mlx5_ipool_free(sh->ipool[MLX5_IPOOL_DECAP_ENCAP], res->idx);
}
/**
* Release an encap/decap resource.
*
@ -10427,29 +10461,15 @@ flow_dv_encap_decap_resource_release(struct rte_eth_dev *dev,
uint32_t encap_decap_idx)
{
struct mlx5_priv *priv = dev->data->dev_private;
uint32_t idx = encap_decap_idx;
struct mlx5_flow_dv_encap_decap_resource *cache_resource;
cache_resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_DECAP_ENCAP],
idx);
encap_decap_idx);
if (!cache_resource)
return 0;
MLX5_ASSERT(cache_resource->action);
DRV_LOG(DEBUG, "encap/decap resource %p: refcnt %d--",
(void *)cache_resource,
__atomic_load_n(&cache_resource->refcnt, __ATOMIC_RELAXED));
if (__atomic_sub_fetch(&cache_resource->refcnt, 1,
__ATOMIC_RELAXED) == 0) {
claim_zero(mlx5_flow_os_destroy_flow_action
(cache_resource->action));
mlx5_hlist_remove(priv->sh->encaps_decaps,
&cache_resource->entry);
mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_DECAP_ENCAP], idx);
DRV_LOG(DEBUG, "encap/decap resource %p: removed",
(void *)cache_resource);
return 0;
}
return 1;
return mlx5_hlist_unregister(priv->sh->encaps_decaps,
&cache_resource->entry);
}
/**