Skip to content

Commit

Permalink
net/mlx5: fix flow table hash list conversion
Browse files Browse the repository at this point in the history
For the case when DR is not supported and DV is supported:
	multi-tables feature is off.
	In this case, only table 0 is supported.
	Table 0 structure wrongly was not created what prevented any
	matcher object to be created and even caused crashes.

Create the table hash list in DV case too.
Create table zero empty structure for each domain when DR is not
supported.
Allow NULL DR internal table object to be used.

Fixes: 860897d ("net/mlx5: reorganize flow tables with hash list")

Signed-off-by: Matan Azrad <matan@mellanox.com>
  • Loading branch information
Matan Azrad authored and Ferruh Yigit committed Nov 20, 2019
1 parent b1fb5d2 commit 5453472
Show file tree
Hide file tree
Showing 2 changed files with 153 additions and 65 deletions.
184 changes: 151 additions & 33 deletions drivers/net/mlx5/mlx5.c
Expand Up @@ -714,6 +714,143 @@ mlx5_free_shared_ibctx(struct mlx5_ibv_shared *sh)
pthread_mutex_unlock(&mlx5_ibv_list_mutex);
}

/**
* Destroy table hash list and all the root entries per domain.
*
* @param[in] priv
* Pointer to the private device data structure.
*/
static void
mlx5_free_table_hash_list(struct mlx5_priv *priv)
{
struct mlx5_ibv_shared *sh = priv->sh;
struct mlx5_flow_tbl_data_entry *tbl_data;
union mlx5_flow_tbl_key table_key = {
{
.table_id = 0,
.reserved = 0,
.domain = 0,
.direction = 0,
}
};
struct mlx5_hlist_entry *pos;

if (!sh->flow_tbls)
return;
pos = mlx5_hlist_lookup(sh->flow_tbls, table_key.v64);
if (pos) {
tbl_data = container_of(pos, struct mlx5_flow_tbl_data_entry,
entry);
assert(tbl_data);
mlx5_hlist_remove(sh->flow_tbls, pos);
rte_free(tbl_data);
}
table_key.direction = 1;
pos = mlx5_hlist_lookup(sh->flow_tbls, table_key.v64);
if (pos) {
tbl_data = container_of(pos, struct mlx5_flow_tbl_data_entry,
entry);
assert(tbl_data);
mlx5_hlist_remove(sh->flow_tbls, pos);
rte_free(tbl_data);
}
table_key.direction = 0;
table_key.domain = 1;
pos = mlx5_hlist_lookup(sh->flow_tbls, table_key.v64);
if (pos) {
tbl_data = container_of(pos, struct mlx5_flow_tbl_data_entry,
entry);
assert(tbl_data);
mlx5_hlist_remove(sh->flow_tbls, pos);
rte_free(tbl_data);
}
mlx5_hlist_destroy(sh->flow_tbls, NULL, NULL);
}

/**
* Initialize flow table hash list and create the root tables entry
* for each domain.
*
* @param[in] priv
* Pointer to the private device data structure.
*
* @return
* Zero on success, positive error code otherwise.
*/
static int
mlx5_alloc_table_hash_list(struct mlx5_priv *priv)
{
struct mlx5_ibv_shared *sh = priv->sh;
char s[MLX5_HLIST_NAMESIZE];
int err = 0;

assert(sh);
snprintf(s, sizeof(s), "%s_flow_table", priv->sh->ibdev_name);
sh->flow_tbls = mlx5_hlist_create(s, MLX5_FLOW_TABLE_HLIST_ARRAY_SIZE);
if (!sh->flow_tbls) {
DRV_LOG(ERR, "flow tables with hash creation failed.\n");
err = ENOMEM;
return err;
}
#ifndef HAVE_MLX5DV_DR
/*
* In case we have not DR support, the zero tables should be created
* because DV expect to see them even if they cannot be created by
* RDMA-CORE.
*/
union mlx5_flow_tbl_key table_key = {
{
.table_id = 0,
.reserved = 0,
.domain = 0,
.direction = 0,
}
};
struct mlx5_flow_tbl_data_entry *tbl_data = rte_zmalloc(NULL,
sizeof(*tbl_data), 0);

if (!tbl_data) {
err = ENOMEM;
goto error;
}
tbl_data->entry.key = table_key.v64;
err = mlx5_hlist_insert(sh->flow_tbls, &tbl_data->entry);
if (err)
goto error;
rte_atomic32_init(&tbl_data->tbl.refcnt);
rte_atomic32_inc(&tbl_data->tbl.refcnt);
table_key.direction = 1;
tbl_data = rte_zmalloc(NULL, sizeof(*tbl_data), 0);
if (!tbl_data) {
err = ENOMEM;
goto error;
}
tbl_data->entry.key = table_key.v64;
err = mlx5_hlist_insert(sh->flow_tbls, &tbl_data->entry);
if (err)
goto error;
rte_atomic32_init(&tbl_data->tbl.refcnt);
rte_atomic32_inc(&tbl_data->tbl.refcnt);
table_key.direction = 0;
table_key.domain = 1;
tbl_data = rte_zmalloc(NULL, sizeof(*tbl_data), 0);
if (!tbl_data) {
err = ENOMEM;
goto error;
}
tbl_data->entry.key = table_key.v64;
err = mlx5_hlist_insert(sh->flow_tbls, &tbl_data->entry);
if (err)
goto error;
rte_atomic32_init(&tbl_data->tbl.refcnt);
rte_atomic32_inc(&tbl_data->tbl.refcnt);
return err;
error:
mlx5_free_table_hash_list(priv);
#endif /* HAVE_MLX5DV_DR */
return err;
}

/**
* Initialize DR related data within private structure.
* Routine checks the reference counter and does actual
Expand All @@ -728,13 +865,15 @@ mlx5_free_shared_ibctx(struct mlx5_ibv_shared *sh)
static int
mlx5_alloc_shared_dr(struct mlx5_priv *priv)
{
int err = mlx5_alloc_table_hash_list(priv);

if (err)
return err;
#ifdef HAVE_MLX5DV_DR
struct mlx5_ibv_shared *sh = priv->sh;
int err = 0;
void *domain;
char s[MLX5_HLIST_NAMESIZE];
void *domain;

assert(sh);
if (sh->dv_refcnt) {
/* Shared DV/DR structures is already initialized. */
sh->dv_refcnt++;
Expand Down Expand Up @@ -772,20 +911,11 @@ mlx5_alloc_shared_dr(struct mlx5_priv *priv)
sh->esw_drop_action = mlx5_glue->dr_create_flow_action_drop();
}
#endif
snprintf(s, sizeof(s), "%s_flow_table", priv->sh->ibdev_name);
sh->flow_tbls = mlx5_hlist_create(s,
MLX5_FLOW_TABLE_HLIST_ARRAY_SIZE);
if (!sh->flow_tbls) {
DRV_LOG(ERR, "flow tables with hash creation failed.\n");
err = -ENOMEM;
goto error;
}
/* create tags hash list table. */
snprintf(s, sizeof(s), "%s_tags", priv->sh->ibdev_name);
sh->tag_table = mlx5_hlist_create(s, MLX5_TAGS_HLIST_ARRAY_SIZE);
if (!sh->flow_tbls) {
DRV_LOG(ERR, "tags with hash creation failed.\n");
err = -ENOMEM;
goto error;
}
sh->pop_vlan_action = mlx5_glue->dr_create_flow_action_pop_vlan();
Expand All @@ -807,10 +937,6 @@ mlx5_alloc_shared_dr(struct mlx5_priv *priv)
mlx5_glue->dr_destroy_domain(sh->fdb_domain);
sh->fdb_domain = NULL;
}
if (sh->flow_tbls) {
mlx5_hlist_destroy(sh->flow_tbls, NULL, NULL);
sh->flow_tbls = NULL;
}
if (sh->esw_drop_action) {
mlx5_glue->destroy_flow_action(sh->esw_drop_action);
sh->esw_drop_action = NULL;
Expand All @@ -819,11 +945,9 @@ mlx5_alloc_shared_dr(struct mlx5_priv *priv)
mlx5_glue->destroy_flow_action(sh->pop_vlan_action);
sh->pop_vlan_action = NULL;
}
return err;
#else
(void)priv;
return 0;
mlx5_free_table_hash_list(priv);
#endif
return err;
}

/**
Expand All @@ -846,16 +970,6 @@ mlx5_free_shared_dr(struct mlx5_priv *priv)
assert(sh->dv_refcnt);
if (sh->dv_refcnt && --sh->dv_refcnt)
return;
if (sh->flow_tbls) {
/* flow table entries should be handled properly before. */
mlx5_hlist_destroy(sh->flow_tbls, NULL, NULL);
sh->flow_tbls = NULL;
}
if (sh->tag_table) {
/* tags should be destroyed with flow before. */
mlx5_hlist_destroy(sh->tag_table, NULL, NULL);
sh->tag_table = NULL;
}
if (sh->rx_domain) {
mlx5_glue->dr_destroy_domain(sh->rx_domain);
sh->rx_domain = NULL;
Expand All @@ -874,14 +988,18 @@ mlx5_free_shared_dr(struct mlx5_priv *priv)
sh->esw_drop_action = NULL;
}
#endif
if (sh->tag_table) {
/* tags should be destroyed with flow before. */
mlx5_hlist_destroy(sh->tag_table, NULL, NULL);
sh->tag_table = NULL;
}
if (sh->pop_vlan_action) {
mlx5_glue->destroy_flow_action(sh->pop_vlan_action);
sh->pop_vlan_action = NULL;
}
pthread_mutex_destroy(&sh->dv_mutex);
#else
(void)priv;
#endif
#endif /* HAVE_MLX5DV_DR */
mlx5_free_table_hash_list(priv);
}

/**
Expand Down
34 changes: 2 additions & 32 deletions drivers/net/mlx5/mlx5_flow_dv.c
Expand Up @@ -6173,24 +6173,16 @@ flow_dv_tbl_resource_get(struct rte_eth_dev *dev,
.direction = !!egress,
}
};
struct mlx5_hlist_entry *pos;
struct mlx5_hlist_entry *pos = mlx5_hlist_lookup(sh->flow_tbls,
table_key.v64);
struct mlx5_flow_tbl_data_entry *tbl_data;

#ifdef HAVE_MLX5DV_DR
int ret;
void *domain;

pos = mlx5_hlist_lookup(sh->flow_tbls, table_key.v64);
if (pos) {
tbl_data = container_of(pos, struct mlx5_flow_tbl_data_entry,
entry);
tbl = &tbl_data->tbl;
if (!tbl->obj) {
rte_flow_error_set(error, ENOKEY,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
NULL, "cannot find created table");
return NULL;
}
rte_atomic32_inc(&tbl->refcnt);
return tbl;
}
Expand Down Expand Up @@ -6236,24 +6228,6 @@ flow_dv_tbl_resource_get(struct rte_eth_dev *dev,
}
rte_atomic32_inc(&tbl->refcnt);
return tbl;
#else
/* Just to make the compiling pass when no HAVE_MLX5DV_DR defined. */
pos = mlx5_hlist_lookup(sh->flow_tbls, table_key.v64);
if (pos) {
tbl_data = container_of(pos, struct mlx5_flow_tbl_data_entry,
entry);
tbl = &tbl_data->tbl;
if (!tbl->obj) {
rte_flow_error_set(error, ENOKEY,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
NULL, "cannot find created table");
return NULL;
}
rte_atomic32_inc(&tbl->refcnt);
return tbl;
}
return NULL;
#endif
}

/**
Expand Down Expand Up @@ -6348,18 +6322,14 @@ flow_dv_matcher_register(struct rte_eth_dev *dev,
rte_atomic32_inc(&cache_matcher->refcnt);
dev_flow->dv.matcher = cache_matcher;
/* old matcher should not make the table ref++. */
#ifdef HAVE_MLX5DV_DR
flow_dv_tbl_resource_release(dev, tbl);
#endif
return 0;
}
}
/* Register new matcher. */
cache_matcher = rte_calloc(__func__, 1, sizeof(*cache_matcher), 0);
if (!cache_matcher) {
#ifdef HAVE_MLX5DV_DR
flow_dv_tbl_resource_release(dev, tbl);
#endif
return rte_flow_error_set(error, ENOMEM,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
"cannot allocate matcher memory");
Expand Down

0 comments on commit 5453472

Please sign in to comment.