Skip to content

Commit e5fe12d

Browse files
pmachataBrian Maly
authored andcommitted
mlxsw: spectrum_router: Link CRIFs to RIFs
When a RIF is about to be created, the registration of the netdevice that it should be associated with must have been seen in the past, and a CRIF created. Therefore make this a hard requirement by looking up the CRIF during RIF creation, and complaining loudly when there isn't one. This then allows to keep a link between a RIF and its corresponding CRIF (and back, as the relationship is one-to-at-most-one), which do. The CRIF will later be useful as the objects tracked there will be offloaded lazily as a result of RIF creation. CRIFs are created when an "interesting" netdevice is registered, and destroyed after such device is unregistered. CRIFs are supposed to already exist when a RIF creation request arises, and exist at least as long as that RIF exists. This makes for a simple invariant: it is always safe to dereference CRIF pointer from "its" RIF. To guarantee this, CRIFs cannot be removed immediately when the UNREGISTER event is delivered. The reason is that if a RIF's netdevices has an IPv6 address, removal of this address is notified in an atomic block. To remove the RIF, the IPv6 removal handler schedules a work item. It must be safe for this work item to access the associated CRIF as well. Thus when a netdevice that backs the CRIF is removed, if it still has a RIF, do not actually free the CRIF, only toggle its can_destroy flag, which this patch adds. Later on, mlxsw_sp_rif_destroy() collects the CRIF. Signed-off-by: Petr Machata <[email protected]> Reviewed-by: Danielle Ratson <[email protected]> Link: https://lore.kernel.org/r/68c8e33afa6b8c03c431b435e1685ffdff752e63.1687438411.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski <[email protected]> Orabug: 35622106 (cherry picked from commit aa21242) cherry-pick-repo=kernel/git/torvalds/linux.git unmodified-from-upstream: aa21242 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 93464e6 commit e5fe12d

File tree

1 file changed

+47
-12
lines changed

1 file changed

+47
-12
lines changed

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

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ struct mlxsw_sp_crif_key {
5858
struct mlxsw_sp_crif {
5959
struct mlxsw_sp_crif_key key;
6060
struct rhash_head ht_node;
61+
bool can_destroy;
62+
struct mlxsw_sp_rif *rif;
6163
};
6264

6365
static const struct rhashtable_params mlxsw_sp_crif_ht_params = {
@@ -67,9 +69,9 @@ static const struct rhashtable_params mlxsw_sp_crif_ht_params = {
6769
};
6870

6971
struct mlxsw_sp_rif {
72+
struct mlxsw_sp_crif *crif; /* NULL for underlay RIF */
7073
struct list_head nexthop_list;
7174
struct list_head neigh_list;
72-
struct net_device *dev; /* NULL for underlay RIF */
7375
struct mlxsw_sp_fid *fid;
7476
unsigned char addr[ETH_ALEN];
7577
int mtu;
@@ -88,7 +90,9 @@ struct mlxsw_sp_rif {
8890

8991
static struct net_device *mlxsw_sp_rif_dev(const struct mlxsw_sp_rif *rif)
9092
{
91-
return rif->dev;
93+
if (!rif->crif)
94+
return NULL;
95+
return rif->crif->key.dev;
9296
}
9397

9498
struct mlxsw_sp_rif_params {
@@ -1096,6 +1100,9 @@ mlxsw_sp_crif_alloc(struct net_device *dev)
10961100

10971101
static void mlxsw_sp_crif_free(struct mlxsw_sp_crif *crif)
10981102
{
1103+
if (WARN_ON(crif->rif))
1104+
return;
1105+
10991106
kfree(crif);
11001107
}
11011108

@@ -7970,8 +7977,9 @@ static void mlxsw_sp_rif_index_free(struct mlxsw_sp *mlxsw_sp, u16 rif_index,
79707977

79717978
static struct mlxsw_sp_rif *mlxsw_sp_rif_alloc(size_t rif_size, u16 rif_index,
79727979
u16 vr_id,
7973-
struct net_device *l3_dev)
7980+
struct mlxsw_sp_crif *crif)
79747981
{
7982+
struct net_device *l3_dev = crif ? crif->key.dev : NULL;
79757983
struct mlxsw_sp_rif *rif;
79767984

79777985
rif = kzalloc(rif_size, GFP_KERNEL);
@@ -7983,10 +7991,13 @@ static struct mlxsw_sp_rif *mlxsw_sp_rif_alloc(size_t rif_size, u16 rif_index,
79837991
if (l3_dev) {
79847992
ether_addr_copy(rif->addr, l3_dev->dev_addr);
79857993
rif->mtu = l3_dev->mtu;
7986-
rif->dev = l3_dev;
79877994
}
79887995
rif->vr_id = vr_id;
79897996
rif->rif_index = rif_index;
7997+
if (crif) {
7998+
rif->crif = crif;
7999+
crif->rif = rif;
8000+
}
79908001

79918002
return rif;
79928003
}
@@ -7995,6 +8006,9 @@ static void mlxsw_sp_rif_free(struct mlxsw_sp_rif *rif)
79958006
{
79968007
WARN_ON(!list_empty(&rif->neigh_list));
79978008
WARN_ON(!list_empty(&rif->nexthop_list));
8009+
8010+
if (rif->crif)
8011+
rif->crif->rif = NULL;
79988012
kfree(rif);
79998013
}
80008014

@@ -8228,6 +8242,7 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
82288242
const struct mlxsw_sp_rif_ops *ops;
82298243
struct mlxsw_sp_fid *fid = NULL;
82308244
enum mlxsw_sp_rif_type type;
8245+
struct mlxsw_sp_crif *crif;
82318246
struct mlxsw_sp_rif *rif;
82328247
struct mlxsw_sp_vr *vr;
82338248
u16 rif_index;
@@ -8247,7 +8262,13 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
82478262
goto err_rif_index_alloc;
82488263
}
82498264

8250-
rif = mlxsw_sp_rif_alloc(ops->rif_size, rif_index, vr->id, params->dev);
8265+
crif = mlxsw_sp_crif_lookup(mlxsw_sp->router, params->dev);
8266+
if (WARN_ON(!crif)) {
8267+
err = -ENOENT;
8268+
goto err_crif_lookup;
8269+
}
8270+
8271+
rif = mlxsw_sp_rif_alloc(ops->rif_size, rif_index, vr->id, crif);
82518272
if (!rif) {
82528273
err = -ENOMEM;
82538274
goto err_rif_alloc;
@@ -8306,6 +8327,7 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
83068327
dev_put(params->dev);
83078328
mlxsw_sp_rif_free(rif);
83088329
err_rif_alloc:
8330+
err_crif_lookup:
83098331
mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries);
83108332
err_rif_index_alloc:
83118333
vr->rif_count--;
@@ -8318,6 +8340,7 @@ static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif)
83188340
struct net_device *dev = mlxsw_sp_rif_dev(rif);
83198341
const struct mlxsw_sp_rif_ops *ops = rif->ops;
83208342
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
8343+
struct mlxsw_sp_crif *crif = rif->crif;
83218344
struct mlxsw_sp_fid *fid = rif->fid;
83228345
u8 rif_entries = rif->rif_entries;
83238346
u16 rif_index = rif->rif_index;
@@ -8348,6 +8371,9 @@ static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif)
83488371
mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries);
83498372
vr->rif_count--;
83508373
mlxsw_sp_vr_put(mlxsw_sp, vr);
8374+
8375+
if (crif->can_destroy)
8376+
mlxsw_sp_crif_free(crif);
83518377
}
83528378

83538379
void mlxsw_sp_rif_destroy_by_dev(struct mlxsw_sp *mlxsw_sp,
@@ -9262,7 +9288,10 @@ static void mlxsw_sp_crif_unregister(struct mlxsw_sp_router *router,
92629288
struct mlxsw_sp_crif *crif)
92639289
{
92649290
mlxsw_sp_crif_remove(router, crif);
9265-
mlxsw_sp_crif_free(crif);
9291+
if (crif->rif)
9292+
crif->can_destroy = true;
9293+
else
9294+
mlxsw_sp_crif_free(crif);
92669295
}
92679296

92689297
static int mlxsw_sp_netdevice_register(struct mlxsw_sp_router *router,
@@ -10068,6 +10097,7 @@ mlxsw_sp_rif_ipip_lb_ul_rif_op(struct mlxsw_sp_rif *ul_rif, bool enable)
1006810097

1006910098
static struct mlxsw_sp_rif *
1007010099
mlxsw_sp_ul_rif_create(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_vr *vr,
10100+
struct mlxsw_sp_crif *ul_crif,
1007110101
struct netlink_ext_ack *extack)
1007210102
{
1007310103
struct mlxsw_sp_rif *ul_rif;
@@ -10081,7 +10111,8 @@ mlxsw_sp_ul_rif_create(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_vr *vr,
1008110111
return ERR_PTR(err);
1008210112
}
1008310113

10084-
ul_rif = mlxsw_sp_rif_alloc(sizeof(*ul_rif), rif_index, vr->id, NULL);
10114+
ul_rif = mlxsw_sp_rif_alloc(sizeof(*ul_rif), rif_index, vr->id,
10115+
ul_crif);
1008510116
if (!ul_rif) {
1008610117
err = -ENOMEM;
1008710118
goto err_rif_alloc;
@@ -10120,6 +10151,7 @@ static void mlxsw_sp_ul_rif_destroy(struct mlxsw_sp_rif *ul_rif)
1012010151

1012110152
static struct mlxsw_sp_rif *
1012210153
mlxsw_sp_ul_rif_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id,
10154+
struct mlxsw_sp_crif *ul_crif,
1012310155
struct netlink_ext_ack *extack)
1012410156
{
1012510157
struct mlxsw_sp_vr *vr;
@@ -10132,7 +10164,7 @@ mlxsw_sp_ul_rif_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id,
1013210164
if (refcount_inc_not_zero(&vr->ul_rif_refcnt))
1013310165
return vr->ul_rif;
1013410166

10135-
vr->ul_rif = mlxsw_sp_ul_rif_create(mlxsw_sp, vr, extack);
10167+
vr->ul_rif = mlxsw_sp_ul_rif_create(mlxsw_sp, vr, ul_crif, extack);
1013610168
if (IS_ERR(vr->ul_rif)) {
1013710169
err = PTR_ERR(vr->ul_rif);
1013810170
goto err_ul_rif_create;
@@ -10170,7 +10202,7 @@ int mlxsw_sp_router_ul_rif_get(struct mlxsw_sp *mlxsw_sp, u32 ul_tb_id,
1017010202
int err = 0;
1017110203

1017210204
mutex_lock(&mlxsw_sp->router->lock);
10173-
ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, NULL);
10205+
ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, NULL, NULL);
1017410206
if (IS_ERR(ul_rif)) {
1017510207
err = PTR_ERR(ul_rif);
1017610208
goto out;
@@ -10206,7 +10238,7 @@ mlxsw_sp2_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif,
1020610238
struct mlxsw_sp_rif *ul_rif;
1020710239
int err;
1020810240

10209-
ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, extack);
10241+
ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, NULL, extack);
1021010242
if (IS_ERR(ul_rif))
1021110243
return PTR_ERR(ul_rif);
1021210244

@@ -10741,9 +10773,12 @@ static int mlxsw_sp_lb_rif_init(struct mlxsw_sp *mlxsw_sp,
1074110773

1074210774
/* Create a generic loopback RIF associated with the main table
1074310775
* (default VRF). Any table can be used, but the main table exists
10744-
* anyway, so we do not waste resources.
10776+
* anyway, so we do not waste resources. Loopback RIFs are usually
10777+
* created with a NULL CRIF, but this RIF is used as a fallback RIF
10778+
* for blackhole nexthops, and nexthops expect to have a valid CRIF.
1074510779
*/
10746-
lb_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, RT_TABLE_MAIN, extack);
10780+
lb_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, RT_TABLE_MAIN, router->lb_crif,
10781+
extack);
1074710782
if (IS_ERR(lb_rif)) {
1074810783
err = PTR_ERR(lb_rif);
1074910784
goto err_ul_rif_get;

0 commit comments

Comments
 (0)