Skip to content

Commit f38656d

Browse files
idoschdavem330
authored andcommitted
mlxsw: spectrum_mr: Protect multicast route list with a lock
Protect the per-table multicast route list with a lock and remove RTNL from the delayed work that periodically updates the kernel about packets and bytes statistics from each multicast route. Signed-off-by: Ido Schimmel <[email protected]> Acked-by: Jiri Pirko <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent c366de8 commit f38656d

File tree

1 file changed

+20
-4
lines changed

1 file changed

+20
-4
lines changed

drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ struct mlxsw_sp_mr_table {
6868
u32 vr_id;
6969
struct mlxsw_sp_mr_vif vifs[MAXVIFS];
7070
struct list_head route_list;
71+
struct mutex route_list_lock; /* Protects route_list */
7172
struct rhashtable route_ht;
7273
const struct mlxsw_sp_mr_table_ops *ops;
7374
char catchall_route_priv[];
@@ -372,6 +373,8 @@ static void mlxsw_sp_mr_mfc_offload_update(struct mlxsw_sp_mr_route *mr_route)
372373
static void __mlxsw_sp_mr_route_del(struct mlxsw_sp_mr_table *mr_table,
373374
struct mlxsw_sp_mr_route *mr_route)
374375
{
376+
WARN_ON_ONCE(!mutex_is_locked(&mr_table->route_list_lock));
377+
375378
mlxsw_sp_mr_mfc_offload_set(mr_route, false);
376379
rhashtable_remove_fast(&mr_table->route_ht, &mr_route->ht_node,
377380
mlxsw_sp_mr_route_ht_params);
@@ -423,7 +426,9 @@ int mlxsw_sp_mr_route_add(struct mlxsw_sp_mr_table *mr_table,
423426
goto err_mr_route_write;
424427

425428
/* Put it in the table data-structures */
429+
mutex_lock(&mr_table->route_list_lock);
426430
list_add_tail(&mr_route->node, &mr_table->route_list);
431+
mutex_unlock(&mr_table->route_list_lock);
427432
err = rhashtable_insert_fast(&mr_table->route_ht,
428433
&mr_route->ht_node,
429434
mlxsw_sp_mr_route_ht_params);
@@ -443,7 +448,9 @@ int mlxsw_sp_mr_route_add(struct mlxsw_sp_mr_table *mr_table,
443448
return 0;
444449

445450
err_rhashtable_insert:
451+
mutex_lock(&mr_table->route_list_lock);
446452
list_del(&mr_route->node);
453+
mutex_unlock(&mr_table->route_list_lock);
447454
mlxsw_sp_mr_route_erase(mr_table, mr_route);
448455
err_mr_route_write:
449456
err_no_orig_route:
@@ -461,8 +468,11 @@ void mlxsw_sp_mr_route_del(struct mlxsw_sp_mr_table *mr_table,
461468
mr_table->ops->key_create(mr_table, &key, mfc);
462469
mr_route = rhashtable_lookup_fast(&mr_table->route_ht, &key,
463470
mlxsw_sp_mr_route_ht_params);
464-
if (mr_route)
471+
if (mr_route) {
472+
mutex_lock(&mr_table->route_list_lock);
465473
__mlxsw_sp_mr_route_del(mr_table, mr_route);
474+
mutex_unlock(&mr_table->route_list_lock);
475+
}
466476
}
467477

468478
/* Should be called after the VIF struct is updated */
@@ -911,6 +921,7 @@ struct mlxsw_sp_mr_table *mlxsw_sp_mr_table_create(struct mlxsw_sp *mlxsw_sp,
911921
mr_table->proto = proto;
912922
mr_table->ops = &mlxsw_sp_mr_table_ops_arr[proto];
913923
INIT_LIST_HEAD(&mr_table->route_list);
924+
mutex_init(&mr_table->route_list_lock);
914925

915926
err = rhashtable_init(&mr_table->route_ht,
916927
&mlxsw_sp_mr_route_ht_params);
@@ -936,6 +947,7 @@ struct mlxsw_sp_mr_table *mlxsw_sp_mr_table_create(struct mlxsw_sp *mlxsw_sp,
936947
err_ops_route_create:
937948
rhashtable_destroy(&mr_table->route_ht);
938949
err_route_rhashtable_init:
950+
mutex_destroy(&mr_table->route_list_lock);
939951
kfree(mr_table);
940952
return ERR_PTR(err);
941953
}
@@ -952,6 +964,7 @@ void mlxsw_sp_mr_table_destroy(struct mlxsw_sp_mr_table *mr_table)
952964
mr->mr_ops->route_destroy(mlxsw_sp, mr->priv,
953965
&mr_table->catchall_route_priv);
954966
rhashtable_destroy(&mr_table->route_ht);
967+
mutex_destroy(&mr_table->route_list_lock);
955968
kfree(mr_table);
956969
}
957970

@@ -960,8 +973,10 @@ void mlxsw_sp_mr_table_flush(struct mlxsw_sp_mr_table *mr_table)
960973
struct mlxsw_sp_mr_route *mr_route, *tmp;
961974
int i;
962975

976+
mutex_lock(&mr_table->route_list_lock);
963977
list_for_each_entry_safe(mr_route, tmp, &mr_table->route_list, node)
964978
__mlxsw_sp_mr_route_del(mr_table, mr_route);
979+
mutex_unlock(&mr_table->route_list_lock);
965980

966981
for (i = 0; i < MAXVIFS; i++) {
967982
mr_table->vifs[i].dev = NULL;
@@ -1005,14 +1020,15 @@ static void mlxsw_sp_mr_stats_update(struct work_struct *work)
10051020
struct mlxsw_sp_mr_route *mr_route;
10061021
unsigned long interval;
10071022

1008-
rtnl_lock();
10091023
mutex_lock(&mr->table_list_lock);
1010-
list_for_each_entry(mr_table, &mr->table_list, node)
1024+
list_for_each_entry(mr_table, &mr->table_list, node) {
1025+
mutex_lock(&mr_table->route_list_lock);
10111026
list_for_each_entry(mr_route, &mr_table->route_list, node)
10121027
mlxsw_sp_mr_route_stats_update(mr_table->mlxsw_sp,
10131028
mr_route);
1029+
mutex_unlock(&mr_table->route_list_lock);
1030+
}
10141031
mutex_unlock(&mr->table_list_lock);
1015-
rtnl_unlock();
10161032

10171033
interval = msecs_to_jiffies(MLXSW_SP_MR_ROUTES_COUNTER_UPDATE_INTERVAL);
10181034
mlxsw_core_schedule_dw(&mr->stats_update_dw, interval);

0 commit comments

Comments
 (0)