@@ -59,6 +59,7 @@ struct mlxsw_sp_crif {
59
59
struct mlxsw_sp_crif_key key ;
60
60
struct rhash_head ht_node ;
61
61
bool can_destroy ;
62
+ struct list_head nexthop_list ;
62
63
struct mlxsw_sp_rif * rif ;
63
64
};
64
65
@@ -70,7 +71,6 @@ static const struct rhashtable_params mlxsw_sp_crif_ht_params = {
70
71
71
72
struct mlxsw_sp_rif {
72
73
struct mlxsw_sp_crif * crif ; /* NULL for underlay RIF */
73
- struct list_head nexthop_list ;
74
74
struct list_head neigh_list ;
75
75
struct mlxsw_sp_fid * fid ;
76
76
unsigned char addr [ETH_ALEN ];
@@ -1083,6 +1083,7 @@ static void
1083
1083
mlxsw_sp_crif_init (struct mlxsw_sp_crif * crif , struct net_device * dev )
1084
1084
{
1085
1085
crif -> key .dev = dev ;
1086
+ INIT_LIST_HEAD (& crif -> nexthop_list );
1086
1087
}
1087
1088
1088
1089
static struct mlxsw_sp_crif *
@@ -1103,6 +1104,7 @@ static void mlxsw_sp_crif_free(struct mlxsw_sp_crif *crif)
1103
1104
if (WARN_ON (crif -> rif ))
1104
1105
return ;
1105
1106
1107
+ WARN_ON (!list_empty (& crif -> nexthop_list ));
1106
1108
kfree (crif );
1107
1109
}
1108
1110
@@ -1720,17 +1722,26 @@ static void mlxsw_sp_netdevice_ipip_ol_down_event(struct mlxsw_sp *mlxsw_sp,
1720
1722
mlxsw_sp_ipip_entry_ol_down_event (mlxsw_sp , ipip_entry );
1721
1723
}
1722
1724
1723
- static void mlxsw_sp_nexthop_rif_migrate (struct mlxsw_sp * mlxsw_sp ,
1724
- struct mlxsw_sp_rif * old_rif ,
1725
- struct mlxsw_sp_rif * new_rif );
1725
+ static void mlxsw_sp_nexthop_rif_update (struct mlxsw_sp * mlxsw_sp ,
1726
+ struct mlxsw_sp_rif * rif );
1727
+
1726
1728
static void mlxsw_sp_rif_migrate_destroy (struct mlxsw_sp * mlxsw_sp ,
1727
1729
struct mlxsw_sp_rif * old_rif ,
1728
1730
struct mlxsw_sp_rif * new_rif ,
1729
1731
bool migrate_nhs )
1730
1732
{
1733
+ struct mlxsw_sp_crif * crif = old_rif -> crif ;
1734
+ struct mlxsw_sp_crif mock_crif = {};
1735
+
1731
1736
if (migrate_nhs )
1732
- mlxsw_sp_nexthop_rif_migrate (mlxsw_sp , old_rif , new_rif );
1737
+ mlxsw_sp_nexthop_rif_update (mlxsw_sp , new_rif );
1733
1738
1739
+ /* Plant a mock CRIF so that destroying the old RIF doesn't unoffload
1740
+ * our nexthops and IPIP tunnels, and doesn't sever the crif->rif link.
1741
+ */
1742
+ mlxsw_sp_crif_init (& mock_crif , crif -> key .dev );
1743
+ old_rif -> crif = & mock_crif ;
1744
+ mock_crif .rif = old_rif ;
1734
1745
mlxsw_sp_rif_destroy (old_rif );
1735
1746
}
1736
1747
@@ -1756,9 +1767,6 @@ mlxsw_sp_ipip_entry_ol_lb_update(struct mlxsw_sp *mlxsw_sp,
1756
1767
return 0 ;
1757
1768
}
1758
1769
1759
- static void mlxsw_sp_nexthop_rif_update (struct mlxsw_sp * mlxsw_sp ,
1760
- struct mlxsw_sp_rif * rif );
1761
-
1762
1770
/**
1763
1771
* __mlxsw_sp_ipip_entry_update_tunnel - Update offload related to IPIP entry.
1764
1772
* @mlxsw_sp: mlxsw_sp.
@@ -2987,7 +2995,7 @@ struct mlxsw_sp_nexthop_key {
2987
2995
2988
2996
struct mlxsw_sp_nexthop {
2989
2997
struct list_head neigh_list_node ; /* member of neigh entry list */
2990
- struct list_head rif_list_node ;
2998
+ struct list_head crif_list_node ;
2991
2999
struct list_head router_list_node ;
2992
3000
struct mlxsw_sp_nexthop_group_info * nhgi ; /* pointer back to the group
2993
3001
* this nexthop belongs to
@@ -3000,7 +3008,7 @@ struct mlxsw_sp_nexthop {
3000
3008
int nh_weight ;
3001
3009
int norm_nh_weight ;
3002
3010
int num_adj_entries ;
3003
- struct mlxsw_sp_rif * rif ;
3011
+ struct mlxsw_sp_crif * crif ;
3004
3012
u8 should_offload :1 , /* set indicates this nexthop should be written
3005
3013
* to the adjacency table.
3006
3014
*/
@@ -3023,9 +3031,9 @@ struct mlxsw_sp_nexthop {
3023
3031
static struct net_device *
3024
3032
mlxsw_sp_nexthop_dev (const struct mlxsw_sp_nexthop * nh )
3025
3033
{
3026
- if (nh -> rif )
3027
- return mlxsw_sp_rif_dev ( nh -> rif ) ;
3028
- return NULL ;
3034
+ if (! nh -> crif )
3035
+ return NULL ;
3036
+ return nh -> crif -> key . dev ;
3029
3037
}
3030
3038
3031
3039
enum mlxsw_sp_nexthop_group_type {
@@ -3050,7 +3058,11 @@ struct mlxsw_sp_nexthop_group_info {
3050
3058
static struct mlxsw_sp_rif *
3051
3059
mlxsw_sp_nhgi_rif (const struct mlxsw_sp_nexthop_group_info * nhgi )
3052
3060
{
3053
- return nhgi -> nexthops [0 ].rif ;
3061
+ struct mlxsw_sp_crif * crif = nhgi -> nexthops [0 ].crif ;
3062
+
3063
+ if (!crif )
3064
+ return NULL ;
3065
+ return crif -> rif ;
3054
3066
}
3055
3067
3056
3068
struct mlxsw_sp_nexthop_group_vr_key {
@@ -3174,7 +3186,9 @@ int mlxsw_sp_nexthop_indexes(struct mlxsw_sp_nexthop *nh, u32 *p_adj_index,
3174
3186
3175
3187
struct mlxsw_sp_rif * mlxsw_sp_nexthop_rif (struct mlxsw_sp_nexthop * nh )
3176
3188
{
3177
- return nh -> rif ;
3189
+ if (WARN_ON (!nh -> crif ))
3190
+ return NULL ;
3191
+ return nh -> crif -> rif ;
3178
3192
}
3179
3193
3180
3194
bool mlxsw_sp_nexthop_group_has_ipip (struct mlxsw_sp_nexthop * nh )
@@ -3559,11 +3573,12 @@ static int __mlxsw_sp_nexthop_eth_update(struct mlxsw_sp *mlxsw_sp,
3559
3573
bool force , char * ratr_pl )
3560
3574
{
3561
3575
struct mlxsw_sp_neigh_entry * neigh_entry = nh -> neigh_entry ;
3576
+ struct mlxsw_sp_rif * rif = mlxsw_sp_nexthop_rif (nh );
3562
3577
enum mlxsw_reg_ratr_op op ;
3563
3578
u16 rif_index ;
3564
3579
3565
- rif_index = nh -> rif ? nh -> rif -> rif_index :
3566
- mlxsw_sp -> router -> lb_crif -> rif -> rif_index ;
3580
+ rif_index = rif ? rif -> rif_index :
3581
+ mlxsw_sp -> router -> lb_crif -> rif -> rif_index ;
3567
3582
op = force ? MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY :
3568
3583
MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY_ON_ACTIVITY ;
3569
3584
mlxsw_reg_ratr_pack (ratr_pl , op , true, MLXSW_REG_RATR_TYPE_ETHERNET ,
@@ -4181,23 +4196,23 @@ mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp *mlxsw_sp,
4181
4196
}
4182
4197
}
4183
4198
4184
- static void mlxsw_sp_nexthop_rif_init (struct mlxsw_sp_nexthop * nh ,
4185
- struct mlxsw_sp_rif * rif )
4199
+ static void mlxsw_sp_nexthop_crif_init (struct mlxsw_sp_nexthop * nh ,
4200
+ struct mlxsw_sp_crif * crif )
4186
4201
{
4187
- if (nh -> rif )
4202
+ if (nh -> crif )
4188
4203
return ;
4189
4204
4190
- nh -> rif = rif ;
4191
- list_add (& nh -> rif_list_node , & rif -> nexthop_list );
4205
+ nh -> crif = crif ;
4206
+ list_add (& nh -> crif_list_node , & crif -> nexthop_list );
4192
4207
}
4193
4208
4194
- static void mlxsw_sp_nexthop_rif_fini (struct mlxsw_sp_nexthop * nh )
4209
+ static void mlxsw_sp_nexthop_crif_fini (struct mlxsw_sp_nexthop * nh )
4195
4210
{
4196
- if (!nh -> rif )
4211
+ if (!nh -> crif )
4197
4212
return ;
4198
4213
4199
- list_del (& nh -> rif_list_node );
4200
- nh -> rif = NULL ;
4214
+ list_del (& nh -> crif_list_node );
4215
+ nh -> crif = NULL ;
4201
4216
}
4202
4217
4203
4218
static int mlxsw_sp_nexthop_neigh_init (struct mlxsw_sp * mlxsw_sp ,
@@ -4209,6 +4224,9 @@ static int mlxsw_sp_nexthop_neigh_init(struct mlxsw_sp *mlxsw_sp,
4209
4224
u8 nud_state , dead ;
4210
4225
int err ;
4211
4226
4227
+ if (WARN_ON (!nh -> crif -> rif ))
4228
+ return 0 ;
4229
+
4212
4230
if (!nh -> nhgi -> gateway || nh -> neigh_entry )
4213
4231
return 0 ;
4214
4232
dev = mlxsw_sp_nexthop_dev (nh );
@@ -4299,15 +4317,20 @@ static void mlxsw_sp_nexthop_ipip_init(struct mlxsw_sp *mlxsw_sp,
4299
4317
struct mlxsw_sp_nexthop * nh ,
4300
4318
struct mlxsw_sp_ipip_entry * ipip_entry )
4301
4319
{
4320
+ struct mlxsw_sp_crif * crif ;
4302
4321
bool removing ;
4303
4322
4304
4323
if (!nh -> nhgi -> gateway || nh -> ipip_entry )
4305
4324
return ;
4306
4325
4326
+ crif = mlxsw_sp_crif_lookup (mlxsw_sp -> router , ipip_entry -> ol_dev );
4327
+ if (WARN_ON (!crif ))
4328
+ return ;
4329
+
4307
4330
nh -> ipip_entry = ipip_entry ;
4308
4331
removing = !mlxsw_sp_ipip_netdev_ul_up (ipip_entry -> ol_dev );
4309
4332
__mlxsw_sp_nexthop_neigh_update (nh , removing );
4310
- mlxsw_sp_nexthop_rif_init (nh , & ipip_entry -> ol_lb -> common );
4333
+ mlxsw_sp_nexthop_crif_init (nh , crif );
4311
4334
}
4312
4335
4313
4336
static void mlxsw_sp_nexthop_ipip_fini (struct mlxsw_sp * mlxsw_sp ,
@@ -4339,7 +4362,7 @@ static int mlxsw_sp_nexthop_type_init(struct mlxsw_sp *mlxsw_sp,
4339
4362
{
4340
4363
const struct mlxsw_sp_ipip_ops * ipip_ops ;
4341
4364
struct mlxsw_sp_ipip_entry * ipip_entry ;
4342
- struct mlxsw_sp_rif * rif ;
4365
+ struct mlxsw_sp_crif * crif ;
4343
4366
int err ;
4344
4367
4345
4368
ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev (mlxsw_sp , dev );
@@ -4353,19 +4376,23 @@ static int mlxsw_sp_nexthop_type_init(struct mlxsw_sp *mlxsw_sp,
4353
4376
}
4354
4377
4355
4378
nh -> type = MLXSW_SP_NEXTHOP_TYPE_ETH ;
4356
- rif = mlxsw_sp_rif_find_by_dev (mlxsw_sp , dev );
4357
- if (!rif )
4379
+ crif = mlxsw_sp_crif_lookup (mlxsw_sp -> router , dev );
4380
+ if (!crif )
4381
+ return 0 ;
4382
+
4383
+ mlxsw_sp_nexthop_crif_init (nh , crif );
4384
+
4385
+ if (!crif -> rif )
4358
4386
return 0 ;
4359
4387
4360
- mlxsw_sp_nexthop_rif_init (nh , rif );
4361
4388
err = mlxsw_sp_nexthop_neigh_init (mlxsw_sp , nh );
4362
4389
if (err )
4363
4390
goto err_neigh_init ;
4364
4391
4365
4392
return 0 ;
4366
4393
4367
4394
err_neigh_init :
4368
- mlxsw_sp_nexthop_rif_fini (nh );
4395
+ mlxsw_sp_nexthop_crif_fini (nh );
4369
4396
return err ;
4370
4397
}
4371
4398
@@ -4386,7 +4413,7 @@ static void mlxsw_sp_nexthop_type_fini(struct mlxsw_sp *mlxsw_sp,
4386
4413
struct mlxsw_sp_nexthop * nh )
4387
4414
{
4388
4415
mlxsw_sp_nexthop_type_rif_gone (mlxsw_sp , nh );
4389
- mlxsw_sp_nexthop_rif_fini (nh );
4416
+ mlxsw_sp_nexthop_crif_fini (nh );
4390
4417
}
4391
4418
4392
4419
static int mlxsw_sp_nexthop4_init (struct mlxsw_sp * mlxsw_sp ,
@@ -4479,7 +4506,7 @@ static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp,
4479
4506
struct mlxsw_sp_nexthop * nh ;
4480
4507
bool removing ;
4481
4508
4482
- list_for_each_entry (nh , & rif -> nexthop_list , rif_list_node ) {
4509
+ list_for_each_entry (nh , & rif -> crif -> nexthop_list , crif_list_node ) {
4483
4510
switch (nh -> type ) {
4484
4511
case MLXSW_SP_NEXTHOP_TYPE_ETH :
4485
4512
removing = false;
@@ -4497,25 +4524,14 @@ static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp,
4497
4524
}
4498
4525
}
4499
4526
4500
- static void mlxsw_sp_nexthop_rif_migrate (struct mlxsw_sp * mlxsw_sp ,
4501
- struct mlxsw_sp_rif * old_rif ,
4502
- struct mlxsw_sp_rif * new_rif )
4503
- {
4504
- struct mlxsw_sp_nexthop * nh ;
4505
-
4506
- list_splice_init (& old_rif -> nexthop_list , & new_rif -> nexthop_list );
4507
- list_for_each_entry (nh , & new_rif -> nexthop_list , rif_list_node )
4508
- nh -> rif = new_rif ;
4509
- mlxsw_sp_nexthop_rif_update (mlxsw_sp , new_rif );
4510
- }
4511
-
4512
4527
static void mlxsw_sp_nexthop_rif_gone_sync (struct mlxsw_sp * mlxsw_sp ,
4513
4528
struct mlxsw_sp_rif * rif )
4514
4529
{
4515
4530
struct mlxsw_sp_nexthop * nh , * tmp ;
4516
4531
4517
- list_for_each_entry_safe (nh , tmp , & rif -> nexthop_list , rif_list_node ) {
4518
- mlxsw_sp_nexthop_type_fini (mlxsw_sp , nh );
4532
+ list_for_each_entry_safe (nh , tmp , & rif -> crif -> nexthop_list ,
4533
+ crif_list_node ) {
4534
+ mlxsw_sp_nexthop_type_rif_gone (mlxsw_sp , nh );
4519
4535
mlxsw_sp_nexthop_group_refresh (mlxsw_sp , nh -> nhgi -> nh_grp );
4520
4536
}
4521
4537
}
@@ -4857,13 +4873,13 @@ static void mlxsw_sp_nexthop_obj_blackhole_init(struct mlxsw_sp *mlxsw_sp,
4857
4873
* via an egress RIF, they still need to be programmed using a
4858
4874
* valid RIF, so use the loopback RIF created during init.
4859
4875
*/
4860
- nh -> rif = mlxsw_sp -> router -> lb_crif -> rif ;
4876
+ nh -> crif = mlxsw_sp -> router -> lb_crif ;
4861
4877
}
4862
4878
4863
4879
static void mlxsw_sp_nexthop_obj_blackhole_fini (struct mlxsw_sp * mlxsw_sp ,
4864
4880
struct mlxsw_sp_nexthop * nh )
4865
4881
{
4866
- nh -> rif = NULL ;
4882
+ nh -> crif = NULL ;
4867
4883
nh -> should_offload = 0 ;
4868
4884
}
4869
4885
@@ -7871,6 +7887,9 @@ static int mlxsw_sp_router_rif_disable(struct mlxsw_sp *mlxsw_sp, u16 rif)
7871
7887
static void mlxsw_sp_router_rif_gone_sync (struct mlxsw_sp * mlxsw_sp ,
7872
7888
struct mlxsw_sp_rif * rif )
7873
7889
{
7890
+ /* Signal to nexthop cleanup that the RIF is going away. */
7891
+ rif -> crif -> rif = NULL ;
7892
+
7874
7893
mlxsw_sp_router_rif_disable (mlxsw_sp , rif -> rif_index );
7875
7894
mlxsw_sp_nexthop_rif_gone_sync (mlxsw_sp , rif );
7876
7895
mlxsw_sp_neigh_rif_gone_sync (mlxsw_sp , rif );
@@ -7989,7 +8008,6 @@ static struct mlxsw_sp_rif *mlxsw_sp_rif_alloc(size_t rif_size, u16 rif_index,
7989
8008
if (!rif )
7990
8009
return NULL ;
7991
8010
7992
- INIT_LIST_HEAD (& rif -> nexthop_list );
7993
8011
INIT_LIST_HEAD (& rif -> neigh_list );
7994
8012
if (l3_dev ) {
7995
8013
ether_addr_copy (rif -> addr , l3_dev -> dev_addr );
@@ -8008,7 +8026,6 @@ static struct mlxsw_sp_rif *mlxsw_sp_rif_alloc(size_t rif_size, u16 rif_index,
8008
8026
static void mlxsw_sp_rif_free (struct mlxsw_sp_rif * rif )
8009
8027
{
8010
8028
WARN_ON (!list_empty (& rif -> neigh_list ));
8011
- WARN_ON (!list_empty (& rif -> nexthop_list ));
8012
8029
8013
8030
if (rif -> crif )
8014
8031
rif -> crif -> rif = NULL ;
@@ -9290,7 +9307,13 @@ mlxsw_sp_crif_register(struct mlxsw_sp_router *router, struct net_device *dev)
9290
9307
static void mlxsw_sp_crif_unregister (struct mlxsw_sp_router * router ,
9291
9308
struct mlxsw_sp_crif * crif )
9292
9309
{
9310
+ struct mlxsw_sp_nexthop * nh , * tmp ;
9311
+
9293
9312
mlxsw_sp_crif_remove (router , crif );
9313
+
9314
+ list_for_each_entry_safe (nh , tmp , & crif -> nexthop_list , crif_list_node )
9315
+ mlxsw_sp_nexthop_type_fini (router -> mlxsw_sp , nh );
9316
+
9294
9317
if (crif -> rif )
9295
9318
crif -> can_destroy = true;
9296
9319
else
0 commit comments