Skip to content

Commit 4796c28

Browse files
pmachatakuba-moo
authored andcommitted
mlxsw: spectrum_router: Maintain a hash table of CRIFs
CRIFs are objects that mlxsw maintains for netdevices that may not have an associated RIF (i.e. they may not have been instantiated in the ASIC), but if indeed they do not, it is quite possible they will in the future. These netdevices are candidate RIFs, hence CRIFs. Netdevices for which CRIFs are created include e.g. bridges, LAGs, or front panel ports. The idea is that next hops would be kept at CRIFs, not RIFs, and thus it would be easier to offload and unoffload the entities that have been added before the RIF was created. In this patch, add the code for low-level CRIF maintenance: create and destroy, and keep in a table keyed by the netdevice pointer for easy recall. Signed-off-by: Petr Machata <[email protected]> Reviewed-by: Danielle Ratson <[email protected]> Link: https://lore.kernel.org/r/186d44e399c475159da20689f2c540719f2d1ed0.1687438411.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski <[email protected]>
1 parent f3c85ee commit 4796c28

File tree

2 files changed

+176
-0
lines changed

2 files changed

+176
-0
lines changed

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

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,21 @@ struct mlxsw_sp_vr;
5151
struct mlxsw_sp_lpm_tree;
5252
struct mlxsw_sp_rif_ops;
5353

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+
5469
struct mlxsw_sp_rif {
5570
struct list_head nexthop_list;
5671
struct list_head neigh_list;
@@ -1060,6 +1075,56 @@ u32 mlxsw_sp_ipip_dev_ul_tb_id(const struct net_device *ol_dev)
10601075
return tb_id;
10611076
}
10621077

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+
10631128
static struct mlxsw_sp_rif *
10641129
mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
10651130
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,
91489213
return -ENOBUFS;
91499214
}
91509215

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+
91519305
static bool mlxsw_sp_is_offload_xstats_event(unsigned long event)
91529306
{
91539307
switch (event) {
@@ -9367,6 +9521,15 @@ static int mlxsw_sp_router_netdevice_event(struct notifier_block *nb,
93679521

93689522
mutex_lock(&mlxsw_sp->router->lock);
93699523

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+
93709533
if (mlxsw_sp_is_offload_xstats_event(event))
93719534
err = mlxsw_sp_netdevice_offload_xstats_cmd(mlxsw_sp, dev,
93729535
event, ptr);
@@ -9381,6 +9544,10 @@ static int mlxsw_sp_router_netdevice_event(struct notifier_block *nb,
93819544
else if (mlxsw_sp_is_vrf_event(event, ptr))
93829545
err = mlxsw_sp_netdevice_vrf_event(dev, event, ptr);
93839546

9547+
if (event == NETDEV_UNREGISTER)
9548+
mlxsw_sp_netdevice_unregister(router, dev);
9549+
9550+
out:
93849551
mutex_unlock(&mlxsw_sp->router->lock);
93859552

93869553
return notifier_from_errno(err);
@@ -10649,6 +10816,11 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp,
1064910816
if (err)
1065010817
goto err_ipips_init;
1065110818

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+
1065210824
err = mlxsw_sp_rifs_init(mlxsw_sp);
1065310825
if (err)
1065410826
goto err_rifs_init;
@@ -10780,6 +10952,8 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp,
1078010952
err_nexthop_ht_init:
1078110953
mlxsw_sp_rifs_fini(mlxsw_sp);
1078210954
err_rifs_init:
10955+
rhashtable_destroy(&mlxsw_sp->router->crif_ht);
10956+
err_crif_ht_init:
1078310957
mlxsw_sp_ipips_fini(mlxsw_sp);
1078410958
err_ipips_init:
1078510959
__mlxsw_sp_router_fini(mlxsw_sp);
@@ -10815,6 +10989,7 @@ void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
1081510989
rhashtable_destroy(&router->nexthop_group_ht);
1081610990
rhashtable_destroy(&router->nexthop_ht);
1081710991
mlxsw_sp_rifs_fini(mlxsw_sp);
10992+
rhashtable_destroy(&mlxsw_sp->router->crif_ht);
1081810993
mlxsw_sp_ipips_fini(mlxsw_sp);
1081910994
__mlxsw_sp_router_fini(mlxsw_sp);
1082010995
cancel_delayed_work_sync(&router->nh_grp_activity_dw);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ struct mlxsw_sp_router_nve_decap {
2020

2121
struct mlxsw_sp_router {
2222
struct mlxsw_sp *mlxsw_sp;
23+
struct rhashtable crif_ht;
2324
struct gen_pool *rifs_table;
2425
struct mlxsw_sp_rif **rifs;
2526
struct idr rif_mac_profiles_idr;

0 commit comments

Comments
 (0)