diff options
author | Vlad Buslov <vladbu@mellanox.com> | 2019-08-04 12:25:57 +0300 |
---|---|---|
committer | Saeed Mahameed <saeedm@mellanox.com> | 2019-08-21 15:55:17 -0700 |
commit | 2a1f1768fa17805ca2e937e2e034a7c3433d3bdc (patch) | |
tree | 5d60669efcc68d884101be755b2b5b4d1388aaf3 /drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | |
parent | net/mlx5e: Refactor neigh used value update for concurrent execution (diff) | |
download | linux-dev-2a1f1768fa17805ca2e937e2e034a7c3433d3bdc.tar.xz linux-dev-2a1f1768fa17805ca2e937e2e034a7c3433d3bdc.zip |
net/mlx5e: Refactor neigh update for concurrent execution
In order to remove dependency on rtnl lock and allow neigh update workqueue
task to execute concurrently with tc, refactor mlx5e_rep_neigh_update() for
concurrent execution:
- Lock encap table when accessing encap entry to prevent concurrent
changes. To do this properly, the initial encap state check is moved from
mlx5e_rep_neigh_update() into mlx5e_rep_update_flows() to be performed
under encap_tbl_lock protection.
- Wait for encap to be fully initialized before accessing it by means of
'res_ready' completion.
- Add mlx5e_take_all_encap_flows() helper which is used to construct a
temporary list of flows and efi indexes that is used to access current
encap data in flow which can be attached to multiple encaps
simultaneously. Release the flows from temporary list after
encap_tbl_lock critical section. This is necessary because
mlx5e_flow_put() can't be called while holding encap_tbl_lock.
- Modify mlx5e_tc_encap_flows_add() and mlx5e_tc_encap_flows_del() to work
with user-provided list of flows built by mlx5e_take_all_encap_flows(),
instead of traversing encap flow list directly.
This is first step in complex neigh update refactoring, which is finished
by following commit in this series.
Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
Reviewed-by: Roi Dayan <roid@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlx5/core/en_rep.c')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 29 |
1 files changed, 20 insertions, 9 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index f26edf458152..5217f39828a4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -595,12 +595,26 @@ static void mlx5e_rep_update_flows(struct mlx5e_priv *priv, unsigned char ha[ETH_ALEN]) { struct ethhdr *eth = (struct ethhdr *)e->encap_header; + struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; + bool encap_connected; + LIST_HEAD(flow_list); ASSERT_RTNL(); + /* wait for encap to be fully initialized */ + wait_for_completion(&e->res_ready); + + mutex_lock(&esw->offloads.encap_tbl_lock); + encap_connected = !!(e->flags & MLX5_ENCAP_ENTRY_VALID); + if (e->compl_result || (encap_connected == neigh_connected && + ether_addr_equal(e->h_dest, ha))) + goto unlock; + + mlx5e_take_all_encap_flows(e, &flow_list); + if ((e->flags & MLX5_ENCAP_ENTRY_VALID) && (!neigh_connected || !ether_addr_equal(e->h_dest, ha))) - mlx5e_tc_encap_flows_del(priv, e); + mlx5e_tc_encap_flows_del(priv, e, &flow_list); if (neigh_connected && !(e->flags & MLX5_ENCAP_ENTRY_VALID)) { ether_addr_copy(e->h_dest, ha); @@ -610,8 +624,11 @@ static void mlx5e_rep_update_flows(struct mlx5e_priv *priv, */ ether_addr_copy(eth->h_source, e->route_dev->dev_addr); - mlx5e_tc_encap_flows_add(priv, e); + mlx5e_tc_encap_flows_add(priv, e, &flow_list); } +unlock: + mutex_unlock(&esw->offloads.encap_tbl_lock); + mlx5e_put_encap_flow_list(priv, &flow_list); } static void mlx5e_rep_neigh_update(struct work_struct *work) @@ -623,7 +640,6 @@ static void mlx5e_rep_neigh_update(struct work_struct *work) unsigned char ha[ETH_ALEN]; struct mlx5e_priv *priv; bool neigh_connected; - bool encap_connected; u8 nud_state, dead; rtnl_lock(); @@ -645,13 +661,8 @@ static void mlx5e_rep_neigh_update(struct work_struct *work) if (!mlx5e_encap_take(e)) continue; - encap_connected = !!(e->flags & MLX5_ENCAP_ENTRY_VALID); priv = netdev_priv(e->out_dev); - - if (encap_connected != neigh_connected || - !ether_addr_equal(e->h_dest, ha)) - mlx5e_rep_update_flows(priv, e, neigh_connected, ha); - + mlx5e_rep_update_flows(priv, e, neigh_connected, ha); mlx5e_encap_put(priv, e); } mlx5e_rep_neigh_entry_release(nhe); |