@@ -51,6 +51,21 @@ struct mlxsw_sp_vr;
51
51
struct mlxsw_sp_lpm_tree ;
52
52
struct mlxsw_sp_rif_ops ;
53
53
54
+ struct mlxsw_sp_crif_key {
55
+ struct net_device * dev ;
56
+ };
57
+
58
+ struct mlxsw_sp_crif {
59
+ struct mlxsw_sp_crif_key key ;
60
+ struct rhash_head ht_node ;
61
+ };
62
+
63
+ static const struct rhashtable_params mlxsw_sp_crif_ht_params = {
64
+ .key_offset = offsetof(struct mlxsw_sp_crif , key ),
65
+ .key_len = sizeof_field (struct mlxsw_sp_crif , key ),
66
+ .head_offset = offsetof(struct mlxsw_sp_crif , ht_node ),
67
+ };
68
+
54
69
struct mlxsw_sp_rif {
55
70
struct list_head nexthop_list ;
56
71
struct list_head neigh_list ;
@@ -1060,6 +1075,56 @@ u32 mlxsw_sp_ipip_dev_ul_tb_id(const struct net_device *ol_dev)
1060
1075
return tb_id ;
1061
1076
}
1062
1077
1078
+ static void
1079
+ mlxsw_sp_crif_init (struct mlxsw_sp_crif * crif , struct net_device * dev )
1080
+ {
1081
+ crif -> key .dev = dev ;
1082
+ }
1083
+
1084
+ static struct mlxsw_sp_crif *
1085
+ mlxsw_sp_crif_alloc (struct net_device * dev )
1086
+ {
1087
+ struct mlxsw_sp_crif * crif ;
1088
+
1089
+ crif = kzalloc (sizeof (* crif ), GFP_KERNEL );
1090
+ if (!crif )
1091
+ return NULL ;
1092
+
1093
+ mlxsw_sp_crif_init (crif , dev );
1094
+ return crif ;
1095
+ }
1096
+
1097
+ static void mlxsw_sp_crif_free (struct mlxsw_sp_crif * crif )
1098
+ {
1099
+ kfree (crif );
1100
+ }
1101
+
1102
+ static int mlxsw_sp_crif_insert (struct mlxsw_sp_router * router ,
1103
+ struct mlxsw_sp_crif * crif )
1104
+ {
1105
+ return rhashtable_insert_fast (& router -> crif_ht , & crif -> ht_node ,
1106
+ mlxsw_sp_crif_ht_params );
1107
+ }
1108
+
1109
+ static void mlxsw_sp_crif_remove (struct mlxsw_sp_router * router ,
1110
+ struct mlxsw_sp_crif * crif )
1111
+ {
1112
+ rhashtable_remove_fast (& router -> crif_ht , & crif -> ht_node ,
1113
+ mlxsw_sp_crif_ht_params );
1114
+ }
1115
+
1116
+ static struct mlxsw_sp_crif *
1117
+ mlxsw_sp_crif_lookup (struct mlxsw_sp_router * router ,
1118
+ const struct net_device * dev )
1119
+ {
1120
+ struct mlxsw_sp_crif_key key = {
1121
+ .dev = (struct net_device * )dev ,
1122
+ };
1123
+
1124
+ return rhashtable_lookup_fast (& router -> crif_ht , & key ,
1125
+ mlxsw_sp_crif_ht_params );
1126
+ }
1127
+
1063
1128
static struct mlxsw_sp_rif *
1064
1129
mlxsw_sp_rif_create (struct mlxsw_sp * mlxsw_sp ,
1065
1130
const struct mlxsw_sp_rif_params * params ,
@@ -9148,6 +9213,95 @@ static int mlxsw_sp_router_port_pre_changeaddr_event(struct mlxsw_sp_rif *rif,
9148
9213
return - ENOBUFS ;
9149
9214
}
9150
9215
9216
+ static bool mlxsw_sp_router_netdevice_interesting (struct mlxsw_sp * mlxsw_sp ,
9217
+ struct net_device * dev )
9218
+ {
9219
+ struct vlan_dev_priv * vlan ;
9220
+
9221
+ if (netif_is_lag_master (dev ) ||
9222
+ netif_is_bridge_master (dev ) ||
9223
+ mlxsw_sp_port_dev_check (dev ) ||
9224
+ mlxsw_sp_netdev_is_ipip_ol (mlxsw_sp , dev ) ||
9225
+ netif_is_l3_master (dev ))
9226
+ return true;
9227
+
9228
+ if (!is_vlan_dev (dev ))
9229
+ return false;
9230
+
9231
+ vlan = vlan_dev_priv (dev );
9232
+ return netif_is_lag_master (vlan -> real_dev ) ||
9233
+ netif_is_bridge_master (vlan -> real_dev ) ||
9234
+ mlxsw_sp_port_dev_check (vlan -> real_dev );
9235
+ }
9236
+
9237
+ static struct mlxsw_sp_crif *
9238
+ mlxsw_sp_crif_register (struct mlxsw_sp_router * router , struct net_device * dev )
9239
+ {
9240
+ struct mlxsw_sp_crif * crif ;
9241
+ int err ;
9242
+
9243
+ if (WARN_ON (mlxsw_sp_crif_lookup (router , dev )))
9244
+ return NULL ;
9245
+
9246
+ crif = mlxsw_sp_crif_alloc (dev );
9247
+ if (!crif )
9248
+ return ERR_PTR (- ENOMEM );
9249
+
9250
+ err = mlxsw_sp_crif_insert (router , crif );
9251
+ if (err )
9252
+ goto err_netdev_insert ;
9253
+
9254
+ return crif ;
9255
+
9256
+ err_netdev_insert :
9257
+ mlxsw_sp_crif_free (crif );
9258
+ return ERR_PTR (err );
9259
+ }
9260
+
9261
+ static void mlxsw_sp_crif_unregister (struct mlxsw_sp_router * router ,
9262
+ struct mlxsw_sp_crif * crif )
9263
+ {
9264
+ mlxsw_sp_crif_remove (router , crif );
9265
+ mlxsw_sp_crif_free (crif );
9266
+ }
9267
+
9268
+ static int mlxsw_sp_netdevice_register (struct mlxsw_sp_router * router ,
9269
+ struct net_device * dev )
9270
+ {
9271
+ struct mlxsw_sp_crif * crif ;
9272
+
9273
+ if (!mlxsw_sp_router_netdevice_interesting (router -> mlxsw_sp , dev ))
9274
+ return 0 ;
9275
+
9276
+ crif = mlxsw_sp_crif_register (router , dev );
9277
+ return PTR_ERR_OR_ZERO (crif );
9278
+ }
9279
+
9280
+ static void mlxsw_sp_netdevice_unregister (struct mlxsw_sp_router * router ,
9281
+ struct net_device * dev )
9282
+ {
9283
+ struct mlxsw_sp_crif * crif ;
9284
+
9285
+ if (!mlxsw_sp_router_netdevice_interesting (router -> mlxsw_sp , dev ))
9286
+ return ;
9287
+
9288
+ /* netdev_run_todo(), by way of netdev_wait_allrefs_any(), rebroadcasts
9289
+ * the NETDEV_UNREGISTER message, so we can get here twice. If that's
9290
+ * what happened, the netdevice state is NETREG_UNREGISTERED. In that
9291
+ * case, we expect to have collected the CRIF already, and warn if it
9292
+ * still exists. Otherwise we expect the CRIF to exist.
9293
+ */
9294
+ crif = mlxsw_sp_crif_lookup (router , dev );
9295
+ if (dev -> reg_state == NETREG_UNREGISTERED ) {
9296
+ if (!WARN_ON (crif ))
9297
+ return ;
9298
+ }
9299
+ if (WARN_ON (!crif ))
9300
+ return ;
9301
+
9302
+ mlxsw_sp_crif_unregister (router , crif );
9303
+ }
9304
+
9151
9305
static bool mlxsw_sp_is_offload_xstats_event (unsigned long event )
9152
9306
{
9153
9307
switch (event ) {
@@ -9367,6 +9521,15 @@ static int mlxsw_sp_router_netdevice_event(struct notifier_block *nb,
9367
9521
9368
9522
mutex_lock (& mlxsw_sp -> router -> lock );
9369
9523
9524
+ if (event == NETDEV_REGISTER ) {
9525
+ err = mlxsw_sp_netdevice_register (router , dev );
9526
+ if (err )
9527
+ /* No need to roll this back, UNREGISTER will collect it
9528
+ * anyhow.
9529
+ */
9530
+ goto out ;
9531
+ }
9532
+
9370
9533
if (mlxsw_sp_is_offload_xstats_event (event ))
9371
9534
err = mlxsw_sp_netdevice_offload_xstats_cmd (mlxsw_sp , dev ,
9372
9535
event , ptr );
@@ -9381,6 +9544,10 @@ static int mlxsw_sp_router_netdevice_event(struct notifier_block *nb,
9381
9544
else if (mlxsw_sp_is_vrf_event (event , ptr ))
9382
9545
err = mlxsw_sp_netdevice_vrf_event (dev , event , ptr );
9383
9546
9547
+ if (event == NETDEV_UNREGISTER )
9548
+ mlxsw_sp_netdevice_unregister (router , dev );
9549
+
9550
+ out :
9384
9551
mutex_unlock (& mlxsw_sp -> router -> lock );
9385
9552
9386
9553
return notifier_from_errno (err );
@@ -10649,6 +10816,11 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp,
10649
10816
if (err )
10650
10817
goto err_ipips_init ;
10651
10818
10819
+ err = rhashtable_init (& mlxsw_sp -> router -> crif_ht ,
10820
+ & mlxsw_sp_crif_ht_params );
10821
+ if (err )
10822
+ goto err_crif_ht_init ;
10823
+
10652
10824
err = mlxsw_sp_rifs_init (mlxsw_sp );
10653
10825
if (err )
10654
10826
goto err_rifs_init ;
@@ -10780,6 +10952,8 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp,
10780
10952
err_nexthop_ht_init :
10781
10953
mlxsw_sp_rifs_fini (mlxsw_sp );
10782
10954
err_rifs_init :
10955
+ rhashtable_destroy (& mlxsw_sp -> router -> crif_ht );
10956
+ err_crif_ht_init :
10783
10957
mlxsw_sp_ipips_fini (mlxsw_sp );
10784
10958
err_ipips_init :
10785
10959
__mlxsw_sp_router_fini (mlxsw_sp );
@@ -10815,6 +10989,7 @@ void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
10815
10989
rhashtable_destroy (& router -> nexthop_group_ht );
10816
10990
rhashtable_destroy (& router -> nexthop_ht );
10817
10991
mlxsw_sp_rifs_fini (mlxsw_sp );
10992
+ rhashtable_destroy (& mlxsw_sp -> router -> crif_ht );
10818
10993
mlxsw_sp_ipips_fini (mlxsw_sp );
10819
10994
__mlxsw_sp_router_fini (mlxsw_sp );
10820
10995
cancel_delayed_work_sync (& router -> nh_grp_activity_dw );
0 commit comments