Skip to content

Commit 9e66104

Browse files
pmachataBrian Maly
authored andcommitted
mlxsw: spectrum_router: Track next hops at CRIFs
Move the list of next hops from struct mlxsw_sp_rif to mlxsw_sp_crif. The reason is that eventually, next hops for mlxsw uppers should be offloaded and unoffloaded on demand as a netdevice becomes an upper, or stops being one. Currently, next hops are tracked at RIFs, but RIFs do not exist when a netdevice is not an mlxsw uppers. CRIFs are kept track of throughout the netdevice lifetime. Correspondingly, track at each next hop not its RIF, but its CRIF (from which a RIF can always be deduced). Note that now that next hops are tracked at a CRIF, it is not necessary to move each over to a new RIF when it is necessary to edit a RIF. Therefore drop mlxsw_sp_nexthop_rif_migrate() and have mlxsw_sp_rif_migrate_destroy() call mlxsw_sp_nexthop_rif_update() directly. Signed-off-by: Petr Machata <[email protected]> Reviewed-by: Danielle Ratson <[email protected]> Link: https://lore.kernel.org/r/e7c1c0a7dd13883b0f09aeda12c4fcf4d63a70e3.1687438411.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski <[email protected]> Orabug: 35622106 (cherry picked from commit 9464a3d) cherry-pick-repo=kernel/git/torvalds/linux.git unmodified-from-upstream: 9464a3d Signed-off-by: Mikhael Goikhman <[email protected]> Signed-off-by: Qing Huang <[email protected]> Reviewed-by: Devesh Sharma <[email protected]> Signed-off-by: Brian Maly <[email protected]>
1 parent b6751d1 commit 9e66104

File tree

1 file changed

+75
-52
lines changed

1 file changed

+75
-52
lines changed

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

Lines changed: 75 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -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

7172
struct 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
10831083
mlxsw_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

10881089
static 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+
17261728
static 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

29882996
struct 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 {
30233031
static struct net_device *
30243032
mlxsw_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

30313039
enum mlxsw_sp_nexthop_group_type {
@@ -3050,7 +3058,11 @@ struct mlxsw_sp_nexthop_group_info {
30503058
static struct mlxsw_sp_rif *
30513059
mlxsw_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

30563068
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,
31743186

31753187
struct 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

31803194
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,
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

42034218
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,
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

43134336
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,
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

43674394
err_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

43924419
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,
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-
45124527
static 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

48634879
static 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)
78717887
static 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,
80088026
static 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)
92909307
static 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

Comments
 (0)