@@ -59,6 +59,7 @@ struct mlxsw_sp_crif {
5959 struct mlxsw_sp_crif_key key ;
6060 struct rhash_head ht_node ;
6161 bool can_destroy ;
62+ struct list_head nexthop_list ;
6263 struct mlxsw_sp_rif * rif ;
6364};
6465
@@ -70,7 +71,6 @@ static const struct rhashtable_params mlxsw_sp_crif_ht_params = {
7071
7172struct mlxsw_sp_rif {
7273 struct mlxsw_sp_crif * crif ; /* NULL for underlay RIF */
73- struct list_head nexthop_list ;
7474 struct list_head neigh_list ;
7575 struct mlxsw_sp_fid * fid ;
7676 unsigned char addr [ETH_ALEN ];
@@ -1083,6 +1083,7 @@ static void
10831083mlxsw_sp_crif_init (struct mlxsw_sp_crif * crif , struct net_device * dev )
10841084{
10851085 crif -> key .dev = dev ;
1086+ INIT_LIST_HEAD (& crif -> nexthop_list );
10861087}
10871088
10881089static struct mlxsw_sp_crif *
@@ -1103,6 +1104,7 @@ static void mlxsw_sp_crif_free(struct mlxsw_sp_crif *crif)
11031104 if (WARN_ON (crif -> rif ))
11041105 return ;
11051106
1107+ WARN_ON (!list_empty (& crif -> nexthop_list ));
11061108 kfree (crif );
11071109}
11081110
@@ -1720,17 +1722,26 @@ static void mlxsw_sp_netdevice_ipip_ol_down_event(struct mlxsw_sp *mlxsw_sp,
17201722 mlxsw_sp_ipip_entry_ol_down_event (mlxsw_sp , ipip_entry );
17211723}
17221724
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+
17261728static void mlxsw_sp_rif_migrate_destroy (struct mlxsw_sp * mlxsw_sp ,
17271729 struct mlxsw_sp_rif * old_rif ,
17281730 struct mlxsw_sp_rif * new_rif ,
17291731 bool migrate_nhs )
17301732{
1733+ struct mlxsw_sp_crif * crif = old_rif -> crif ;
1734+ struct mlxsw_sp_crif mock_crif = {};
1735+
17311736 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 );
17331738
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 ;
17341745 mlxsw_sp_rif_destroy (old_rif );
17351746}
17361747
@@ -1756,9 +1767,6 @@ mlxsw_sp_ipip_entry_ol_lb_update(struct mlxsw_sp *mlxsw_sp,
17561767 return 0 ;
17571768}
17581769
1759- static void mlxsw_sp_nexthop_rif_update (struct mlxsw_sp * mlxsw_sp ,
1760- struct mlxsw_sp_rif * rif );
1761-
17621770/**
17631771 * __mlxsw_sp_ipip_entry_update_tunnel - Update offload related to IPIP entry.
17641772 * @mlxsw_sp: mlxsw_sp.
@@ -2987,7 +2995,7 @@ struct mlxsw_sp_nexthop_key {
29872995
29882996struct mlxsw_sp_nexthop {
29892997 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 ;
29912999 struct list_head router_list_node ;
29923000 struct mlxsw_sp_nexthop_group_info * nhgi ; /* pointer back to the group
29933001 * this nexthop belongs to
@@ -3000,7 +3008,7 @@ struct mlxsw_sp_nexthop {
30003008 int nh_weight ;
30013009 int norm_nh_weight ;
30023010 int num_adj_entries ;
3003- struct mlxsw_sp_rif * rif ;
3011+ struct mlxsw_sp_crif * crif ;
30043012 u8 should_offload :1 , /* set indicates this nexthop should be written
30053013 * to the adjacency table.
30063014 */
@@ -3023,9 +3031,9 @@ struct mlxsw_sp_nexthop {
30233031static struct net_device *
30243032mlxsw_sp_nexthop_dev (const struct mlxsw_sp_nexthop * nh )
30253033{
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 ;
30293037}
30303038
30313039enum mlxsw_sp_nexthop_group_type {
@@ -3050,7 +3058,11 @@ struct mlxsw_sp_nexthop_group_info {
30503058static struct mlxsw_sp_rif *
30513059mlxsw_sp_nhgi_rif (const struct mlxsw_sp_nexthop_group_info * nhgi )
30523060{
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 ;
30543066}
30553067
30563068struct mlxsw_sp_nexthop_group_vr_key {
@@ -3174,7 +3186,9 @@ int mlxsw_sp_nexthop_indexes(struct mlxsw_sp_nexthop *nh, u32 *p_adj_index,
31743186
31753187struct mlxsw_sp_rif * mlxsw_sp_nexthop_rif (struct mlxsw_sp_nexthop * nh )
31763188{
3177- return nh -> rif ;
3189+ if (WARN_ON (!nh -> crif ))
3190+ return NULL ;
3191+ return nh -> crif -> rif ;
31783192}
31793193
31803194bool 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,
35593573 bool force , char * ratr_pl )
35603574{
35613575 struct mlxsw_sp_neigh_entry * neigh_entry = nh -> neigh_entry ;
3576+ struct mlxsw_sp_rif * rif = mlxsw_sp_nexthop_rif (nh );
35623577 enum mlxsw_reg_ratr_op op ;
35633578 u16 rif_index ;
35643579
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 ;
35673582 op = force ? MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY :
35683583 MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY_ON_ACTIVITY ;
35693584 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,
41814196 }
41824197}
41834198
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 )
41864201{
4187- if (nh -> rif )
4202+ if (nh -> crif )
41884203 return ;
41894204
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 );
41924207}
41934208
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 )
41954210{
4196- if (!nh -> rif )
4211+ if (!nh -> crif )
41974212 return ;
41984213
4199- list_del (& nh -> rif_list_node );
4200- nh -> rif = NULL ;
4214+ list_del (& nh -> crif_list_node );
4215+ nh -> crif = NULL ;
42014216}
42024217
42034218static 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,
42094224 u8 nud_state , dead ;
42104225 int err ;
42114226
4227+ if (WARN_ON (!nh -> crif -> rif ))
4228+ return 0 ;
4229+
42124230 if (!nh -> nhgi -> gateway || nh -> neigh_entry )
42134231 return 0 ;
42144232 dev = mlxsw_sp_nexthop_dev (nh );
@@ -4299,15 +4317,20 @@ static void mlxsw_sp_nexthop_ipip_init(struct mlxsw_sp *mlxsw_sp,
42994317 struct mlxsw_sp_nexthop * nh ,
43004318 struct mlxsw_sp_ipip_entry * ipip_entry )
43014319{
4320+ struct mlxsw_sp_crif * crif ;
43024321 bool removing ;
43034322
43044323 if (!nh -> nhgi -> gateway || nh -> ipip_entry )
43054324 return ;
43064325
4326+ crif = mlxsw_sp_crif_lookup (mlxsw_sp -> router , ipip_entry -> ol_dev );
4327+ if (WARN_ON (!crif ))
4328+ return ;
4329+
43074330 nh -> ipip_entry = ipip_entry ;
43084331 removing = !mlxsw_sp_ipip_netdev_ul_up (ipip_entry -> ol_dev );
43094332 __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 );
43114334}
43124335
43134336static 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,
43394362{
43404363 const struct mlxsw_sp_ipip_ops * ipip_ops ;
43414364 struct mlxsw_sp_ipip_entry * ipip_entry ;
4342- struct mlxsw_sp_rif * rif ;
4365+ struct mlxsw_sp_crif * crif ;
43434366 int err ;
43444367
43454368 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,
43534376 }
43544377
43554378 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 )
43584386 return 0 ;
43594387
4360- mlxsw_sp_nexthop_rif_init (nh , rif );
43614388 err = mlxsw_sp_nexthop_neigh_init (mlxsw_sp , nh );
43624389 if (err )
43634390 goto err_neigh_init ;
43644391
43654392 return 0 ;
43664393
43674394err_neigh_init :
4368- mlxsw_sp_nexthop_rif_fini (nh );
4395+ mlxsw_sp_nexthop_crif_fini (nh );
43694396 return err ;
43704397}
43714398
@@ -4386,7 +4413,7 @@ static void mlxsw_sp_nexthop_type_fini(struct mlxsw_sp *mlxsw_sp,
43864413 struct mlxsw_sp_nexthop * nh )
43874414{
43884415 mlxsw_sp_nexthop_type_rif_gone (mlxsw_sp , nh );
4389- mlxsw_sp_nexthop_rif_fini (nh );
4416+ mlxsw_sp_nexthop_crif_fini (nh );
43904417}
43914418
43924419static 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,
44794506 struct mlxsw_sp_nexthop * nh ;
44804507 bool removing ;
44814508
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 ) {
44834510 switch (nh -> type ) {
44844511 case MLXSW_SP_NEXTHOP_TYPE_ETH :
44854512 removing = false;
@@ -4497,25 +4524,14 @@ static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp,
44974524 }
44984525}
44994526
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-
45124527static void mlxsw_sp_nexthop_rif_gone_sync (struct mlxsw_sp * mlxsw_sp ,
45134528 struct mlxsw_sp_rif * rif )
45144529{
45154530 struct mlxsw_sp_nexthop * nh , * tmp ;
45164531
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 );
45194535 mlxsw_sp_nexthop_group_refresh (mlxsw_sp , nh -> nhgi -> nh_grp );
45204536 }
45214537}
@@ -4857,13 +4873,13 @@ static void mlxsw_sp_nexthop_obj_blackhole_init(struct mlxsw_sp *mlxsw_sp,
48574873 * via an egress RIF, they still need to be programmed using a
48584874 * valid RIF, so use the loopback RIF created during init.
48594875 */
4860- nh -> rif = mlxsw_sp -> router -> lb_crif -> rif ;
4876+ nh -> crif = mlxsw_sp -> router -> lb_crif ;
48614877}
48624878
48634879static void mlxsw_sp_nexthop_obj_blackhole_fini (struct mlxsw_sp * mlxsw_sp ,
48644880 struct mlxsw_sp_nexthop * nh )
48654881{
4866- nh -> rif = NULL ;
4882+ nh -> crif = NULL ;
48674883 nh -> should_offload = 0 ;
48684884}
48694885
@@ -7871,6 +7887,9 @@ static int mlxsw_sp_router_rif_disable(struct mlxsw_sp *mlxsw_sp, u16 rif)
78717887static void mlxsw_sp_router_rif_gone_sync (struct mlxsw_sp * mlxsw_sp ,
78727888 struct mlxsw_sp_rif * rif )
78737889{
7890+ /* Signal to nexthop cleanup that the RIF is going away. */
7891+ rif -> crif -> rif = NULL ;
7892+
78747893 mlxsw_sp_router_rif_disable (mlxsw_sp , rif -> rif_index );
78757894 mlxsw_sp_nexthop_rif_gone_sync (mlxsw_sp , rif );
78767895 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,
79898008 if (!rif )
79908009 return NULL ;
79918010
7992- INIT_LIST_HEAD (& rif -> nexthop_list );
79938011 INIT_LIST_HEAD (& rif -> neigh_list );
79948012 if (l3_dev ) {
79958013 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,
80088026static void mlxsw_sp_rif_free (struct mlxsw_sp_rif * rif )
80098027{
80108028 WARN_ON (!list_empty (& rif -> neigh_list ));
8011- WARN_ON (!list_empty (& rif -> nexthop_list ));
80128029
80138030 if (rif -> crif )
80148031 rif -> crif -> rif = NULL ;
@@ -9290,7 +9307,13 @@ mlxsw_sp_crif_register(struct mlxsw_sp_router *router, struct net_device *dev)
92909307static void mlxsw_sp_crif_unregister (struct mlxsw_sp_router * router ,
92919308 struct mlxsw_sp_crif * crif )
92929309{
9310+ struct mlxsw_sp_nexthop * nh , * tmp ;
9311+
92939312 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+
92949317 if (crif -> rif )
92959318 crif -> can_destroy = true;
92969319 else
0 commit comments