net/mlx5e: Protect mod_hdr hash table with mutex
To remove dependency on rtnl lock, protect mod_hdr hash table from concurrent modifications with new mutex. Implement helper function to get flow namespace to prevent code duplication. Signed-off-by: Vlad Buslov <vladbu@mellanox.com> Reviewed-by: Roi Dayan <roid@mellanox.com> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
This commit is contained in:
parent
83a52f0d52
commit
d2faae25c3
|
@ -315,22 +315,31 @@ mlx5e_mod_hdr_get(struct mod_hdr_tbl *tbl, struct mod_hdr_key *key, u32 hash_key
|
|||
}
|
||||
|
||||
static void mlx5e_mod_hdr_put(struct mlx5e_priv *priv,
|
||||
struct mlx5e_mod_hdr_entry *mh)
|
||||
struct mlx5e_mod_hdr_entry *mh,
|
||||
int namespace)
|
||||
{
|
||||
if (!refcount_dec_and_test(&mh->refcnt))
|
||||
struct mod_hdr_tbl *tbl = get_mod_hdr_table(priv, namespace);
|
||||
|
||||
if (!refcount_dec_and_mutex_lock(&mh->refcnt, &tbl->lock))
|
||||
return;
|
||||
hash_del(&mh->mod_hdr_hlist);
|
||||
mutex_unlock(&tbl->lock);
|
||||
|
||||
WARN_ON(!list_empty(&mh->flows));
|
||||
mlx5_modify_header_dealloc(priv->mdev, mh->mod_hdr_id);
|
||||
hash_del(&mh->mod_hdr_hlist);
|
||||
|
||||
kfree(mh);
|
||||
}
|
||||
|
||||
static int get_flow_name_space(struct mlx5e_tc_flow *flow)
|
||||
{
|
||||
return mlx5e_is_eswitch_flow(flow) ?
|
||||
MLX5_FLOW_NAMESPACE_FDB : MLX5_FLOW_NAMESPACE_KERNEL;
|
||||
}
|
||||
static int mlx5e_attach_mod_hdr(struct mlx5e_priv *priv,
|
||||
struct mlx5e_tc_flow *flow,
|
||||
struct mlx5e_tc_flow_parse_attr *parse_attr)
|
||||
{
|
||||
bool is_eswitch_flow = mlx5e_is_eswitch_flow(flow);
|
||||
int num_actions, actions_size, namespace, err;
|
||||
struct mlx5e_mod_hdr_entry *mh;
|
||||
struct mod_hdr_tbl *tbl;
|
||||
|
@ -345,17 +354,19 @@ static int mlx5e_attach_mod_hdr(struct mlx5e_priv *priv,
|
|||
|
||||
hash_key = hash_mod_hdr_info(&key);
|
||||
|
||||
namespace = is_eswitch_flow ?
|
||||
MLX5_FLOW_NAMESPACE_FDB : MLX5_FLOW_NAMESPACE_KERNEL;
|
||||
namespace = get_flow_name_space(flow);
|
||||
tbl = get_mod_hdr_table(priv, namespace);
|
||||
|
||||
mutex_lock(&tbl->lock);
|
||||
mh = mlx5e_mod_hdr_get(tbl, &key, hash_key);
|
||||
if (mh)
|
||||
goto attach_flow;
|
||||
|
||||
mh = kzalloc(sizeof(*mh) + actions_size, GFP_KERNEL);
|
||||
if (!mh)
|
||||
return -ENOMEM;
|
||||
if (!mh) {
|
||||
err = -ENOMEM;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
mh->key.actions = (void *)mh + sizeof(*mh);
|
||||
memcpy(mh->key.actions, key.actions, actions_size);
|
||||
|
@ -374,11 +385,12 @@ static int mlx5e_attach_mod_hdr(struct mlx5e_priv *priv,
|
|||
hash_add(tbl->hlist, &mh->mod_hdr_hlist, hash_key);
|
||||
|
||||
attach_flow:
|
||||
mutex_unlock(&tbl->lock);
|
||||
flow->mh = mh;
|
||||
spin_lock(&mh->flows_lock);
|
||||
list_add(&flow->mod_hdr, &mh->flows);
|
||||
spin_unlock(&mh->flows_lock);
|
||||
if (is_eswitch_flow)
|
||||
if (mlx5e_is_eswitch_flow(flow))
|
||||
flow->esw_attr->mod_hdr_id = mh->mod_hdr_id;
|
||||
else
|
||||
flow->nic_attr->mod_hdr_id = mh->mod_hdr_id;
|
||||
|
@ -386,6 +398,7 @@ attach_flow:
|
|||
return 0;
|
||||
|
||||
out_err:
|
||||
mutex_unlock(&tbl->lock);
|
||||
kfree(mh);
|
||||
return err;
|
||||
}
|
||||
|
@ -401,7 +414,7 @@ static void mlx5e_detach_mod_hdr(struct mlx5e_priv *priv,
|
|||
list_del(&flow->mod_hdr);
|
||||
spin_unlock(&flow->mh->flows_lock);
|
||||
|
||||
mlx5e_mod_hdr_put(priv, flow->mh);
|
||||
mlx5e_mod_hdr_put(priv, flow->mh, get_flow_name_space(flow));
|
||||
flow->mh = NULL;
|
||||
}
|
||||
|
||||
|
@ -3865,6 +3878,7 @@ int mlx5e_tc_nic_init(struct mlx5e_priv *priv)
|
|||
int err;
|
||||
|
||||
mutex_init(&tc->t_lock);
|
||||
mutex_init(&tc->mod_hdr.lock);
|
||||
hash_init(tc->mod_hdr.hlist);
|
||||
mutex_init(&tc->hairpin_tbl_lock);
|
||||
hash_init(tc->hairpin_tbl);
|
||||
|
@ -3898,6 +3912,7 @@ void mlx5e_tc_nic_cleanup(struct mlx5e_priv *priv)
|
|||
if (tc->netdevice_nb.notifier_call)
|
||||
unregister_netdevice_notifier(&tc->netdevice_nb);
|
||||
|
||||
mutex_destroy(&tc->mod_hdr.lock);
|
||||
mutex_destroy(&tc->hairpin_tbl_lock);
|
||||
|
||||
rhashtable_destroy(&tc->ht);
|
||||
|
|
|
@ -2000,6 +2000,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
|
|||
goto abort;
|
||||
|
||||
hash_init(esw->offloads.encap_tbl);
|
||||
mutex_init(&esw->offloads.mod_hdr.lock);
|
||||
hash_init(esw->offloads.mod_hdr.hlist);
|
||||
atomic64_set(&esw->offloads.num_flows, 0);
|
||||
mutex_init(&esw->state_lock);
|
||||
|
@ -2037,6 +2038,7 @@ void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw)
|
|||
esw->dev->priv.eswitch = NULL;
|
||||
destroy_workqueue(esw->work_queue);
|
||||
esw_offloads_cleanup_reps(esw);
|
||||
mutex_destroy(&esw->offloads.mod_hdr.lock);
|
||||
kfree(esw->vports);
|
||||
kfree(esw);
|
||||
}
|
||||
|
|
|
@ -127,6 +127,7 @@ struct mlx5_flow_destination {
|
|||
};
|
||||
|
||||
struct mod_hdr_tbl {
|
||||
struct mutex lock; /* protects hlist */
|
||||
DECLARE_HASHTABLE(hlist, 8);
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue