History

Merge branch 'mlxsw-maintain-candidate-rifs'

Petr Machata says: ==================== mlxsw: Maintain candidate RIFs The mlxsw driver currently makes the assumption that the user applies configuration in a bottom-up manner. Thus netdevices need to be added to the bridge before IP addresses are configured on that bridge or SVI added on top of it. Enslaving a netdevice to another netdevice that already has uppers is in fact forbidden by mlxsw for this reason. Despite this safety, it is rather easy to get into situations where the offloaded configuration is just plain wrong. As an example, take a front panel port, configure an IP address: it gets a RIF. Now enslave the port to the bridge, and the RIF is gone. Remove the port from the bridge again, but the RIF never comes back. There is a number of similar situations, where changing the configuration there and back utterly breaks the offload. The situation is going to be made better by implementing a range of replays and post-hoc offloads. This patch set lays the ground for replay of next hops. The particular issue that it deals with is that currently, driver-specific bookkeeping for next hops is hooked off RIF objects, which come and go across the lifetime of a netdevice. We would rather keep these objects at an entity that mirrors the lifetime of the netdevice itself. That way they are at hand and can be offloaded when a RIF is eventually created. To that end, with this patchset, mlxsw keeps a hash table of CRIFs: candidate RIFs, persistent handles for netdevices that mlxsw deems potentially interesting. The lifetime of a CRIF matches that of the underlying netdevice, and thus a RIF can always assume a CRIF exists. A CRIF is where next hops are kept, and when RIF is created, these next hops can be easily offloaded. (Previously only the next hops created after the RIF was created were offloaded.) - Patches #1 and #2 are minor adjustments. - In patches #3 and #4, add CRIF bookkeeping. - In patch #5, link CRIFs to RIFs such that given a netdevice-backed RIF, the corresponding CRIF is easy to look up. - Patch #6 is a clean-up allowed by the previous patches - Patches #7 and #8 move next hop tracking to CRIFs No observable effects are intended as of yet. This will be useful once there is support for RIF creation for netdevices that become mlxsw uppers, which will come in following patch sets. ====================

Jakub Kicinski committed 3 years ago

Commit d1d29a42 parents faaa5fd 9464a3d2 files · +326 −79Browse files

Unified · Split

2 files
  1. drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +324 −78
  2. drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h +2 −1
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c+324−78
@@ -51,10 +51,27 @@ struct mlxsw_sp_vr; · 50 unmodified lines
5151 struct mlxsw_sp_lpm_tree;
5252 struct mlxsw_sp_rif_ops;
5353
54−struct mlxsw_sp_rif {
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+ bool can_destroy;
5562 struct list_head nexthop_list;
63+ struct mlxsw_sp_rif *rif;
64+};
65+
66+static const struct rhashtable_params mlxsw_sp_crif_ht_params = {
67+ .key_offset = offsetof(struct mlxsw_sp_crif, key),
68+ .key_len = sizeof_field(struct mlxsw_sp_crif, key),
69+ .head_offset = offsetof(struct mlxsw_sp_crif, ht_node),
70+};
71+
72+struct mlxsw_sp_rif {
73+ struct mlxsw_sp_crif *crif; /* NULL for underlay RIF */
5674 struct list_head neigh_list;
57− struct net_device *dev; /* NULL for underlay RIF */
5875 struct mlxsw_sp_fid *fid;
5976 unsigned char addr[ETH_ALEN];
6077 int mtu;
@@ -73,7 +90,9 @@ struct mlxsw_sp_rif { · 12 unmodified lines
7390
7491 static struct net_device *mlxsw_sp_rif_dev(const struct mlxsw_sp_rif *rif)
7592 {
76− return rif->dev;
93+ if (!rif->crif)
94+ return NULL;
95+ return rif->crif->key.dev;
7796 }
7897
7998 struct mlxsw_sp_rif_params {
@@ -1060,6 +1079,61 @@ u32 mlxsw_sp_ipip_dev_ul_tb_id(const struct net_device *ol_dev) · 980 unmodified lines
10601079 return tb_id;
10611080 }
10621081
1082+static void
1083+mlxsw_sp_crif_init(struct mlxsw_sp_crif *crif, struct net_device *dev)
1084+{
1085+ crif->key.dev = dev;
1086+ INIT_LIST_HEAD(&crif->nexthop_list);
1087+}
1088+
1089+static struct mlxsw_sp_crif *
1090+mlxsw_sp_crif_alloc(struct net_device *dev)
1091+{
1092+ struct mlxsw_sp_crif *crif;
1093+
1094+ crif = kzalloc(sizeof(*crif), GFP_KERNEL);
1095+ if (!crif)
1096+ return NULL;
1097+
1098+ mlxsw_sp_crif_init(crif, dev);
1099+ return crif;
1100+}
1101+
1102+static void mlxsw_sp_crif_free(struct mlxsw_sp_crif *crif)
1103+{
1104+ if (WARN_ON(crif->rif))
1105+ return;
1106+
1107+ WARN_ON(!list_empty(&crif->nexthop_list));
1108+ kfree(crif);
1109+}
1110+
1111+static int mlxsw_sp_crif_insert(struct mlxsw_sp_router *router,
1112+ struct mlxsw_sp_crif *crif)
1113+{
1114+ return rhashtable_insert_fast(&router->crif_ht, &crif->ht_node,
1115+ mlxsw_sp_crif_ht_params);
1116+}
1117+
1118+static void mlxsw_sp_crif_remove(struct mlxsw_sp_router *router,
1119+ struct mlxsw_sp_crif *crif)
1120+{
1121+ rhashtable_remove_fast(&router->crif_ht, &crif->ht_node,
1122+ mlxsw_sp_crif_ht_params);
1123+}
1124+
1125+static struct mlxsw_sp_crif *
1126+mlxsw_sp_crif_lookup(struct mlxsw_sp_router *router,
1127+ const struct net_device *dev)
1128+{
1129+ struct mlxsw_sp_crif_key key = {
1130+ .dev = (struct net_device *)dev,
1131+ };
1132+
1133+ return rhashtable_lookup_fast(&router->crif_ht, &key,
1134+ mlxsw_sp_crif_ht_params);
1135+}
1136+
10631137 static struct mlxsw_sp_rif *
10641138 mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
10651139 const struct mlxsw_sp_rif_params *params,
@@ -1648,17 +1722,26 @@ static void mlxsw_sp_netdevice_ipip_ol_down_event(struct mlxsw_sp *mlxsw_sp, · 582 unmodified lines
16481722 mlxsw_sp_ipip_entry_ol_down_event(mlxsw_sp, ipip_entry);
16491723 }
16501724
1651−static void mlxsw_sp_nexthop_rif_migrate(struct mlxsw_sp *mlxsw_sp,
1652− struct mlxsw_sp_rif *old_rif,
1653− 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+
16541728 static void mlxsw_sp_rif_migrate_destroy(struct mlxsw_sp *mlxsw_sp,
16551729 struct mlxsw_sp_rif *old_rif,
16561730 struct mlxsw_sp_rif *new_rif,
16571731 bool migrate_nhs)
16581732 {
1733+ struct mlxsw_sp_crif *crif = old_rif->crif;
1734+ struct mlxsw_sp_crif mock_crif = {};
1735+
16591736 if (migrate_nhs)
1660− mlxsw_sp_nexthop_rif_migrate(mlxsw_sp, old_rif, new_rif);
1737+ mlxsw_sp_nexthop_rif_update(mlxsw_sp, new_rif);
16611738
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;
16621745 mlxsw_sp_rif_destroy(old_rif);
16631746 }
16641747
@@ -1684,9 +1767,6 @@ mlxsw_sp_ipip_entry_ol_lb_update(struct mlxsw_sp *mlxsw_sp, · 19 unmodified lines
16841767 return 0;
16851768 }
16861769
1687−static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp,
1688− struct mlxsw_sp_rif *rif);
1689−
16901770 /**
16911771 * __mlxsw_sp_ipip_entry_update_tunnel - Update offload related to IPIP entry.
16921772 * @mlxsw_sp: mlxsw_sp.
@@ -2915,7 +2995,7 @@ struct mlxsw_sp_nexthop_key { · 1222 unmodified lines
29152995
29162996 struct mlxsw_sp_nexthop {
29172997 struct list_head neigh_list_node; /* member of neigh entry list */
2918− struct list_head rif_list_node;
2998+ struct list_head crif_list_node;
29192999 struct list_head router_list_node;
29203000 struct mlxsw_sp_nexthop_group_info *nhgi; /* pointer back to the group
29213001 * this nexthop belongs to
@@ -2928,7 +3008,7 @@ struct mlxsw_sp_nexthop { · 6 unmodified lines
29283008 int nh_weight;
29293009 int norm_nh_weight;
29303010 int num_adj_entries;
2931− struct mlxsw_sp_rif *rif;
3011+ struct mlxsw_sp_crif *crif;
29323012 u8 should_offload:1, /* set indicates this nexthop should be written
29333013 * to the adjacency table.
29343014 */
@@ -2951,9 +3031,9 @@ struct mlxsw_sp_nexthop { · 16 unmodified lines
29513031 static struct net_device *
29523032 mlxsw_sp_nexthop_dev(const struct mlxsw_sp_nexthop *nh)
29533033 {
2954− if (nh->rif)
2955− return mlxsw_sp_rif_dev(nh->rif);
2956− return NULL;
3034+ if (!nh->crif)
3035+ return NULL;
3036+ return nh->crif->key.dev;
29573037 }
29583038
29593039 enum mlxsw_sp_nexthop_group_type {
@@ -2978,7 +3058,11 @@ struct mlxsw_sp_nexthop_group_info { · 18 unmodified lines
29783058 static struct mlxsw_sp_rif *
29793059 mlxsw_sp_nhgi_rif(const struct mlxsw_sp_nexthop_group_info *nhgi)
29803060 {
2981− 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;
29823066 }
29833067
29843068 struct mlxsw_sp_nexthop_group_vr_key {
@@ -3102,7 +3186,9 @@ int mlxsw_sp_nexthop_indexes(struct mlxsw_sp_nexthop *nh, u32 *p_adj_index, · 117 unmodified lines
31023186
31033187 struct mlxsw_sp_rif *mlxsw_sp_nexthop_rif(struct mlxsw_sp_nexthop *nh)
31043188 {
3105− return nh->rif;
3189+ if (WARN_ON(!nh->crif))
3190+ return NULL;
3191+ return nh->crif->rif;
31063192 }
31073193
31083194 bool mlxsw_sp_nexthop_group_has_ipip(struct mlxsw_sp_nexthop *nh)
@@ -3487,11 +3573,12 @@ static int __mlxsw_sp_nexthop_eth_update(struct mlxsw_sp *mlxsw_sp, · 378 unmodified lines
34873573 bool force, char *ratr_pl)
34883574 {
34893575 struct mlxsw_sp_neigh_entry *neigh_entry = nh->neigh_entry;
3576+ struct mlxsw_sp_rif *rif = mlxsw_sp_nexthop_rif(nh);
34903577 enum mlxsw_reg_ratr_op op;
34913578 u16 rif_index;
34923579
3493− rif_index = nh->rif ? nh->rif->rif_index :
3494− mlxsw_sp->router->lb_rif_index;
3580+ rif_index = rif ? rif->rif_index :
3581+ mlxsw_sp->router->lb_crif->rif->rif_index;
34953582 op = force ? MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY :
34963583 MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY_ON_ACTIVITY;
34973584 mlxsw_reg_ratr_pack(ratr_pl, op, true, MLXSW_REG_RATR_TYPE_ETHERNET,
@@ -4109,23 +4196,23 @@ mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp *mlxsw_sp, · 611 unmodified lines
41094196 }
41104197 }
41114198
4112−static void mlxsw_sp_nexthop_rif_init(struct mlxsw_sp_nexthop *nh,
4113− struct mlxsw_sp_rif *rif)
4199+static void mlxsw_sp_nexthop_crif_init(struct mlxsw_sp_nexthop *nh,
4200+ struct mlxsw_sp_crif *crif)
41144201 {
4115− if (nh->rif)
4202+ if (nh->crif)
41164203 return;
41174204
4118− nh->rif = rif;
4119− list_add(&nh->rif_list_node, &rif->nexthop_list);
4205+ nh->crif = crif;
4206+ list_add(&nh->crif_list_node, &crif->nexthop_list);
41204207 }
41214208
4122−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)
41234210 {
4124− if (!nh->rif)
4211+ if (!nh->crif)
41254212 return;
41264213
4127− list_del(&nh->rif_list_node);
4128− nh->rif = NULL;
4214+ list_del(&nh->crif_list_node);
4215+ nh->crif = NULL;
41294216 }
41304217
41314218 static int mlxsw_sp_nexthop_neigh_init(struct mlxsw_sp *mlxsw_sp,
@@ -4137,6 +4224,9 @@ static int mlxsw_sp_nexthop_neigh_init(struct mlxsw_sp *mlxsw_sp, · 5 unmodified lines
41374224 u8 nud_state, dead;
41384225 int err;
41394226
4227+ if (WARN_ON(!nh->crif->rif))
4228+ return 0;
4229+
41404230 if (!nh->nhgi->gateway || nh->neigh_entry)
41414231 return 0;
41424232 dev = mlxsw_sp_nexthop_dev(nh);
@@ -4227,15 +4317,20 @@ static void mlxsw_sp_nexthop_ipip_init(struct mlxsw_sp *mlxsw_sp, · 84 unmodified lines
42274317 struct mlxsw_sp_nexthop *nh,
42284318 struct mlxsw_sp_ipip_entry *ipip_entry)
42294319 {
4320+ struct mlxsw_sp_crif *crif;
42304321 bool removing;
42314322
42324323 if (!nh->nhgi->gateway || nh->ipip_entry)
42334324 return;
42344325
4326+ crif = mlxsw_sp_crif_lookup(mlxsw_sp->router, ipip_entry->ol_dev);
4327+ if (WARN_ON(!crif))
4328+ return;
4329+
42354330 nh->ipip_entry = ipip_entry;
42364331 removing = !mlxsw_sp_ipip_netdev_ul_up(ipip_entry->ol_dev);
42374332 __mlxsw_sp_nexthop_neigh_update(nh, removing);
4238− mlxsw_sp_nexthop_rif_init(nh, &ipip_entry->ol_lb->common);
4333+ mlxsw_sp_nexthop_crif_init(nh, crif);
42394334 }
42404335
42414336 static void mlxsw_sp_nexthop_ipip_fini(struct mlxsw_sp *mlxsw_sp,
@@ -4267,7 +4362,7 @@ static int mlxsw_sp_nexthop_type_init(struct mlxsw_sp *mlxsw_sp, · 25 unmodified lines
42674362 {
42684363 const struct mlxsw_sp_ipip_ops *ipip_ops;
42694364 struct mlxsw_sp_ipip_entry *ipip_entry;
4270− struct mlxsw_sp_rif *rif;
4365+ struct mlxsw_sp_crif *crif;
42714366 int err;
42724367
42734368 ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, dev);
@@ -4281,11 +4376,15 @@ static int mlxsw_sp_nexthop_type_init(struct mlxsw_sp *mlxsw_sp, · 7 unmodified lines
42814376 }
42824377
42834378 nh->type = MLXSW_SP_NEXTHOP_TYPE_ETH;
4284− rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
4285− 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)
42864386 return 0;
42874387
4288− mlxsw_sp_nexthop_rif_init(nh, rif);
42894388 err = mlxsw_sp_nexthop_neigh_init(mlxsw_sp, nh);
42904389 if (err)
42914390 goto err_neigh_init;
@@ -4293,25 +4392,30 @@ static int mlxsw_sp_nexthop_type_init(struct mlxsw_sp *mlxsw_sp, · 1 unmodified line
42934392 return 0;
42944393
42954394 err_neigh_init:
4296− mlxsw_sp_nexthop_rif_fini(nh);
4395+ mlxsw_sp_nexthop_crif_fini(nh);
42974396 return err;
42984397 }
42994398
4300−static void mlxsw_sp_nexthop_type_fini(struct mlxsw_sp *mlxsw_sp,
4301− struct mlxsw_sp_nexthop *nh)
4399+static void mlxsw_sp_nexthop_type_rif_gone(struct mlxsw_sp *mlxsw_sp,
4400+ struct mlxsw_sp_nexthop *nh)
43024401 {
43034402 switch (nh->type) {
43044403 case MLXSW_SP_NEXTHOP_TYPE_ETH:
43054404 mlxsw_sp_nexthop_neigh_fini(mlxsw_sp, nh);
4306− mlxsw_sp_nexthop_rif_fini(nh);
43074405 break;
43084406 case MLXSW_SP_NEXTHOP_TYPE_IPIP:
4309− mlxsw_sp_nexthop_rif_fini(nh);
43104407 mlxsw_sp_nexthop_ipip_fini(mlxsw_sp, nh);
43114408 break;
43124409 }
43134410 }
43144411
4412+static void mlxsw_sp_nexthop_type_fini(struct mlxsw_sp *mlxsw_sp,
4413+ struct mlxsw_sp_nexthop *nh)
4414+{
4415+ mlxsw_sp_nexthop_type_rif_gone(mlxsw_sp, nh);
4416+ mlxsw_sp_nexthop_crif_fini(nh);
4417+}
4418+
43154419 static int mlxsw_sp_nexthop4_init(struct mlxsw_sp *mlxsw_sp,
43164420 struct mlxsw_sp_nexthop_group *nh_grp,
43174421 struct mlxsw_sp_nexthop *nh,
@@ -4402,7 +4506,7 @@ static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp, · 84 unmodified lines
44024506 struct mlxsw_sp_nexthop *nh;
44034507 bool removing;
44044508
4405− list_for_each_entry(nh, &rif->nexthop_list, rif_list_node) {
4509+ list_for_each_entry(nh, &rif->crif->nexthop_list, crif_list_node) {
44064510 switch (nh->type) {
44074511 case MLXSW_SP_NEXTHOP_TYPE_ETH:
44084512 removing = false;
@@ -4420,25 +4524,14 @@ static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp, · 11 unmodified lines
44204524 }
44214525 }
44224526
4423−static void mlxsw_sp_nexthop_rif_migrate(struct mlxsw_sp *mlxsw_sp,
4424− struct mlxsw_sp_rif *old_rif,
4425− struct mlxsw_sp_rif *new_rif)
4426−{
4427− struct mlxsw_sp_nexthop *nh;
4428−
4429− list_splice_init(&old_rif->nexthop_list, &new_rif->nexthop_list);
4430− list_for_each_entry(nh, &new_rif->nexthop_list, rif_list_node)
4431− nh->rif = new_rif;
4432− mlxsw_sp_nexthop_rif_update(mlxsw_sp, new_rif);
4433−}
4434−
44354527 static void mlxsw_sp_nexthop_rif_gone_sync(struct mlxsw_sp *mlxsw_sp,
44364528 struct mlxsw_sp_rif *rif)
44374529 {
44384530 struct mlxsw_sp_nexthop *nh, *tmp;
44394531
4440− list_for_each_entry_safe(nh, tmp, &rif->nexthop_list, rif_list_node) {
4441− 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);
44424535 mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nhgi->nh_grp);
44434536 }
44444537 }
@@ -4458,7 +4551,7 @@ static int mlxsw_sp_adj_trap_entry_init(struct mlxsw_sp *mlxsw_sp) · 13 unmodified lines
44584551 mlxsw_reg_ratr_pack(ratr_pl, MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY, true,
44594552 MLXSW_REG_RATR_TYPE_ETHERNET,
44604553 mlxsw_sp->router->adj_trap_index,
4461− mlxsw_sp->router->lb_rif_index);
4554+ mlxsw_sp->router->lb_crif->rif->rif_index);
44624555 mlxsw_reg_ratr_trap_action_set(ratr_pl, trap_action);
44634556 mlxsw_reg_ratr_trap_id_set(ratr_pl, MLXSW_TRAP_ID_RTR_EGRESS0);
44644557 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ratr), ratr_pl);
@@ -4774,21 +4867,19 @@ static bool mlxsw_sp_nexthop_obj_is_gateway(struct mlxsw_sp *mlxsw_sp, · 309 unmodified lines
47744867 static void mlxsw_sp_nexthop_obj_blackhole_init(struct mlxsw_sp *mlxsw_sp,
47754868 struct mlxsw_sp_nexthop *nh)
47764869 {
4777− u16 lb_rif_index = mlxsw_sp->router->lb_rif_index;
4778−
47794870 nh->action = MLXSW_SP_NEXTHOP_ACTION_DISCARD;
47804871 nh->should_offload = 1;
47814872 /* While nexthops that discard packets do not forward packets
47824873 * via an egress RIF, they still need to be programmed using a
47834874 * valid RIF, so use the loopback RIF created during init.
47844875 */
4785− nh->rif = mlxsw_sp->router->rifs[lb_rif_index];
4876+ nh->crif = mlxsw_sp->router->lb_crif;
47864877 }
47874878
47884879 static void mlxsw_sp_nexthop_obj_blackhole_fini(struct mlxsw_sp *mlxsw_sp,
47894880 struct mlxsw_sp_nexthop *nh)
47904881 {
4791− nh->rif = NULL;
4882+ nh->crif = NULL;
47924883 nh->should_offload = 0;
47934884 }
47944885
@@ -7796,6 +7887,9 @@ static int mlxsw_sp_router_rif_disable(struct mlxsw_sp *mlxsw_sp, u16 rif) · 3001 unmodified lines
77967887 static void mlxsw_sp_router_rif_gone_sync(struct mlxsw_sp *mlxsw_sp,
77977888 struct mlxsw_sp_rif *rif)
77987889 {
7890+ /* Signal to nexthop cleanup that the RIF is going away. */
7891+ rif->crif->rif = NULL;
7892+
77997893 mlxsw_sp_router_rif_disable(mlxsw_sp, rif->rif_index);
78007894 mlxsw_sp_nexthop_rif_gone_sync(mlxsw_sp, rif);
78017895 mlxsw_sp_neigh_rif_gone_sync(mlxsw_sp, rif);
@@ -7905,23 +7999,26 @@ static void mlxsw_sp_rif_index_free(struct mlxsw_sp *mlxsw_sp, u16 rif_index, · 103 unmodified lines
79057999
79068000 static struct mlxsw_sp_rif *mlxsw_sp_rif_alloc(size_t rif_size, u16 rif_index,
79078001 u16 vr_id,
7908− struct net_device *l3_dev)
8002+ struct mlxsw_sp_crif *crif)
79098003 {
8004+ struct net_device *l3_dev = crif ? crif->key.dev : NULL;
79108005 struct mlxsw_sp_rif *rif;
79118006
79128007 rif = kzalloc(rif_size, GFP_KERNEL);
79138008 if (!rif)
79148009 return NULL;
79158010
7916− INIT_LIST_HEAD(&rif->nexthop_list);
79178011 INIT_LIST_HEAD(&rif->neigh_list);
79188012 if (l3_dev) {
79198013 ether_addr_copy(rif->addr, l3_dev->dev_addr);
79208014 rif->mtu = l3_dev->mtu;
7921− rif->dev = l3_dev;
79228015 }
79238016 rif->vr_id = vr_id;
79248017 rif->rif_index = rif_index;
8018+ if (crif) {
8019+ rif->crif = crif;
8020+ crif->rif = rif;
8021+ }
79258022
79268023 return rif;
79278024 }
@@ -7929,7 +8026,9 @@ static struct mlxsw_sp_rif *mlxsw_sp_rif_alloc(size_t rif_size, u16 rif_index, · 1 unmodified line
79298026 static void mlxsw_sp_rif_free(struct mlxsw_sp_rif *rif)
79308027 {
79318028 WARN_ON(!list_empty(&rif->neigh_list));
7932− WARN_ON(!list_empty(&rif->nexthop_list));
8029+
8030+ if (rif->crif)
8031+ rif->crif->rif = NULL;
79338032 kfree(rif);
79348033 }
79358034
@@ -8163,6 +8262,7 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, · 227 unmodified lines
81638262 const struct mlxsw_sp_rif_ops *ops;
81648263 struct mlxsw_sp_fid *fid = NULL;
81658264 enum mlxsw_sp_rif_type type;
8265+ struct mlxsw_sp_crif *crif;
81668266 struct mlxsw_sp_rif *rif;
81678267 struct mlxsw_sp_vr *vr;
81688268 u16 rif_index;
@@ -8182,7 +8282,13 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, · 13 unmodified lines
81828282 goto err_rif_index_alloc;
81838283 }
81848284
8185− rif = mlxsw_sp_rif_alloc(ops->rif_size, rif_index, vr->id, params->dev);
8285+ crif = mlxsw_sp_crif_lookup(mlxsw_sp->router, params->dev);
8286+ if (WARN_ON(!crif)) {
8287+ err = -ENOENT;
8288+ goto err_crif_lookup;
8289+ }
8290+
8291+ rif = mlxsw_sp_rif_alloc(ops->rif_size, rif_index, vr->id, crif);
81868292 if (!rif) {
81878293 err = -ENOMEM;
81888294 goto err_rif_alloc;
@@ -8241,6 +8347,7 @@ err_fid_get: · 52 unmodified lines
82418347 dev_put(params->dev);
82428348 mlxsw_sp_rif_free(rif);
82438349 err_rif_alloc:
8350+err_crif_lookup:
82448351 mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries);
82458352 err_rif_index_alloc:
82468353 vr->rif_count--;
@@ -8253,6 +8360,7 @@ static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif) · 6 unmodified lines
82538360 struct net_device *dev = mlxsw_sp_rif_dev(rif);
82548361 const struct mlxsw_sp_rif_ops *ops = rif->ops;
82558362 struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
8363+ struct mlxsw_sp_crif *crif = rif->crif;
82568364 struct mlxsw_sp_fid *fid = rif->fid;
82578365 u8 rif_entries = rif->rif_entries;
82588366 u16 rif_index = rif->rif_index;
@@ -8283,6 +8391,9 @@ static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif) · 24 unmodified lines
82838391 mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries);
82848392 vr->rif_count--;
82858393 mlxsw_sp_vr_put(mlxsw_sp, vr);
8394+
8395+ if (crif->can_destroy)
8396+ mlxsw_sp_crif_free(crif);
82868397 }
82878398
82888399 void mlxsw_sp_rif_destroy_by_dev(struct mlxsw_sp *mlxsw_sp,
@@ -9148,6 +9259,104 @@ static int mlxsw_sp_router_port_pre_changeaddr_event(struct mlxsw_sp_rif *rif, · 859 unmodified lines
91489259 return -ENOBUFS;
91499260 }
91509261
9262+static bool mlxsw_sp_router_netdevice_interesting(struct mlxsw_sp *mlxsw_sp,
9263+ struct net_device *dev)
9264+{
9265+ struct vlan_dev_priv *vlan;
9266+
9267+ if (netif_is_lag_master(dev) ||
9268+ netif_is_bridge_master(dev) ||
9269+ mlxsw_sp_port_dev_check(dev) ||
9270+ mlxsw_sp_netdev_is_ipip_ol(mlxsw_sp, dev) ||
9271+ netif_is_l3_master(dev))
9272+ return true;
9273+
9274+ if (!is_vlan_dev(dev))
9275+ return false;
9276+
9277+ vlan = vlan_dev_priv(dev);
9278+ return netif_is_lag_master(vlan->real_dev) ||
9279+ netif_is_bridge_master(vlan->real_dev) ||
9280+ mlxsw_sp_port_dev_check(vlan->real_dev);
9281+}
9282+
9283+static struct mlxsw_sp_crif *
9284+mlxsw_sp_crif_register(struct mlxsw_sp_router *router, struct net_device *dev)
9285+{
9286+ struct mlxsw_sp_crif *crif;
9287+ int err;
9288+
9289+ if (WARN_ON(mlxsw_sp_crif_lookup(router, dev)))
9290+ return NULL;
9291+
9292+ crif = mlxsw_sp_crif_alloc(dev);
9293+ if (!crif)
9294+ return ERR_PTR(-ENOMEM);
9295+
9296+ err = mlxsw_sp_crif_insert(router, crif);
9297+ if (err)
9298+ goto err_netdev_insert;
9299+
9300+ return crif;
9301+
9302+err_netdev_insert:
9303+ mlxsw_sp_crif_free(crif);
9304+ return ERR_PTR(err);
9305+}
9306+
9307+static void mlxsw_sp_crif_unregister(struct mlxsw_sp_router *router,
9308+ struct mlxsw_sp_crif *crif)
9309+{
9310+ struct mlxsw_sp_nexthop *nh, *tmp;
9311+
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+
9317+ if (crif->rif)
9318+ crif->can_destroy = true;
9319+ else
9320+ mlxsw_sp_crif_free(crif);
9321+}
9322+
9323+static int mlxsw_sp_netdevice_register(struct mlxsw_sp_router *router,
9324+ struct net_device *dev)
9325+{
9326+ struct mlxsw_sp_crif *crif;
9327+
9328+ if (!mlxsw_sp_router_netdevice_interesting(router->mlxsw_sp, dev))
9329+ return 0;
9330+
9331+ crif = mlxsw_sp_crif_register(router, dev);
9332+ return PTR_ERR_OR_ZERO(crif);
9333+}
9334+
9335+static void mlxsw_sp_netdevice_unregister(struct mlxsw_sp_router *router,
9336+ struct net_device *dev)
9337+{
9338+ struct mlxsw_sp_crif *crif;
9339+
9340+ if (!mlxsw_sp_router_netdevice_interesting(router->mlxsw_sp, dev))
9341+ return;
9342+
9343+ /* netdev_run_todo(), by way of netdev_wait_allrefs_any(), rebroadcasts
9344+ * the NETDEV_UNREGISTER message, so we can get here twice. If that's
9345+ * what happened, the netdevice state is NETREG_UNREGISTERED. In that
9346+ * case, we expect to have collected the CRIF already, and warn if it
9347+ * still exists. Otherwise we expect the CRIF to exist.
9348+ */
9349+ crif = mlxsw_sp_crif_lookup(router, dev);
9350+ if (dev->reg_state == NETREG_UNREGISTERED) {
9351+ if (!WARN_ON(crif))
9352+ return;
9353+ }
9354+ if (WARN_ON(!crif))
9355+ return;
9356+
9357+ mlxsw_sp_crif_unregister(router, crif);
9358+}
9359+
91519360 static bool mlxsw_sp_is_offload_xstats_event(unsigned long event)
91529361 {
91539362 switch (event) {
@@ -9367,6 +9576,15 @@ static int mlxsw_sp_router_netdevice_event(struct notifier_block *nb, · 213 unmodified lines
93679576
93689577 mutex_lock(&mlxsw_sp->router->lock);
93699578
9579+ if (event == NETDEV_REGISTER) {
9580+ err = mlxsw_sp_netdevice_register(router, dev);
9581+ if (err)
9582+ /* No need to roll this back, UNREGISTER will collect it
9583+ * anyhow.
9584+ */
9585+ goto out;
9586+ }
9587+
93709588 if (mlxsw_sp_is_offload_xstats_event(event))
93719589 err = mlxsw_sp_netdevice_offload_xstats_cmd(mlxsw_sp, dev,
93729590 event, ptr);
@@ -9381,6 +9599,10 @@ static int mlxsw_sp_router_netdevice_event(struct notifier_block *nb, · 8 unmodified lines
93819599 else if (mlxsw_sp_is_vrf_event(event, ptr))
93829600 err = mlxsw_sp_netdevice_vrf_event(dev, event, ptr);
93839601
9602+ if (event == NETDEV_UNREGISTER)
9603+ mlxsw_sp_netdevice_unregister(router, dev);
9604+
9605+out:
93849606 mutex_unlock(&mlxsw_sp->router->lock);
93859607
93869608 return notifier_from_errno(err);
@@ -9901,6 +10123,7 @@ mlxsw_sp_rif_ipip_lb_ul_rif_op(struct mlxsw_sp_rif *ul_rif, bool enable) · 514 unmodified lines
990110123
990210124 static struct mlxsw_sp_rif *
990310125 mlxsw_sp_ul_rif_create(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_vr *vr,
10126+ struct mlxsw_sp_crif *ul_crif,
990410127 struct netlink_ext_ack *extack)
990510128 {
990610129 struct mlxsw_sp_rif *ul_rif;
@@ -9914,7 +10137,8 @@ mlxsw_sp_ul_rif_create(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_vr *vr, · 7 unmodified lines
991410137 return ERR_PTR(err);
991510138 }
991610139
9917− ul_rif = mlxsw_sp_rif_alloc(sizeof(*ul_rif), rif_index, vr->id, NULL);
10140+ ul_rif = mlxsw_sp_rif_alloc(sizeof(*ul_rif), rif_index, vr->id,
10141+ ul_crif);
991810142 if (!ul_rif) {
991910143 err = -ENOMEM;
992010144 goto err_rif_alloc;
@@ -9953,6 +10177,7 @@ static void mlxsw_sp_ul_rif_destroy(struct mlxsw_sp_rif *ul_rif) · 32 unmodified lines
995310177
995410178 static struct mlxsw_sp_rif *
995510179 mlxsw_sp_ul_rif_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id,
10180+ struct mlxsw_sp_crif *ul_crif,
995610181 struct netlink_ext_ack *extack)
995710182 {
995810183 struct mlxsw_sp_vr *vr;
@@ -9965,7 +10190,7 @@ mlxsw_sp_ul_rif_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id, · 6 unmodified lines
996510190 if (refcount_inc_not_zero(&vr->ul_rif_refcnt))
996610191 return vr->ul_rif;
996710192
9968− vr->ul_rif = mlxsw_sp_ul_rif_create(mlxsw_sp, vr, extack);
10193+ vr->ul_rif = mlxsw_sp_ul_rif_create(mlxsw_sp, vr, ul_crif, extack);
996910194 if (IS_ERR(vr->ul_rif)) {
997010195 err = PTR_ERR(vr->ul_rif);
997110196 goto err_ul_rif_create;
@@ -10003,7 +10228,7 @@ int mlxsw_sp_router_ul_rif_get(struct mlxsw_sp *mlxsw_sp, u32 ul_tb_id, · 31 unmodified lines
1000310228 int err = 0;
1000410229
1000510230 mutex_lock(&mlxsw_sp->router->lock);
10006− ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, NULL);
10231+ ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, NULL, NULL);
1000710232 if (IS_ERR(ul_rif)) {
1000810233 err = PTR_ERR(ul_rif);
1000910234 goto out;
@@ -10039,7 +10264,7 @@ mlxsw_sp2_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif, · 29 unmodified lines
1003910264 struct mlxsw_sp_rif *ul_rif;
1004010265 int err;
1004110266
10042− ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, extack);
10267+ ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, NULL, extack);
1004310268 if (IS_ERR(ul_rif))
1004410269 return PTR_ERR(ul_rif);
1004510270
@@ -10561,28 +10786,41 @@ static void __mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp) · 515 unmodified lines
1056110786 mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl);
1056210787 }
1056310788
10564−static int mlxsw_sp_lb_rif_init(struct mlxsw_sp *mlxsw_sp)
10789+static int mlxsw_sp_lb_rif_init(struct mlxsw_sp *mlxsw_sp,
10790+ struct netlink_ext_ack *extack)
1056510791 {
10566− u16 lb_rif_index;
10792+ struct mlxsw_sp_router *router = mlxsw_sp->router;
10793+ struct mlxsw_sp_rif *lb_rif;
1056710794 int err;
1056810795
10796+ router->lb_crif = mlxsw_sp_crif_alloc(NULL);
10797+ if (IS_ERR(router->lb_crif))
10798+ return PTR_ERR(router->lb_crif);
10799+
1056910800 /* Create a generic loopback RIF associated with the main table
1057010801 * (default VRF). Any table can be used, but the main table exists
10571− * anyway, so we do not waste resources.
10802+ * anyway, so we do not waste resources. Loopback RIFs are usually
10803+ * created with a NULL CRIF, but this RIF is used as a fallback RIF
10804+ * for blackhole nexthops, and nexthops expect to have a valid CRIF.
1057210805 */
10573− err = mlxsw_sp_router_ul_rif_get(mlxsw_sp, RT_TABLE_MAIN,
10574− &lb_rif_index);
10575− if (err)
10576− return err;
10577−
10578− mlxsw_sp->router->lb_rif_index = lb_rif_index;
10806+ lb_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, RT_TABLE_MAIN, router->lb_crif,
10807+ extack);
10808+ if (IS_ERR(lb_rif)) {
10809+ err = PTR_ERR(lb_rif);
10810+ goto err_ul_rif_get;
10811+ }
1057910812
1058010813 return 0;
10814+
10815+err_ul_rif_get:
10816+ mlxsw_sp_crif_free(router->lb_crif);
10817+ return err;
1058110818 }
1058210819
1058310820 static void mlxsw_sp_lb_rif_fini(struct mlxsw_sp *mlxsw_sp)
1058410821 {
10585− mlxsw_sp_router_ul_rif_put(mlxsw_sp, mlxsw_sp->router->lb_rif_index);
10822+ mlxsw_sp_ul_rif_put(mlxsw_sp->router->lb_crif->rif);
10823+ mlxsw_sp_crif_free(mlxsw_sp->router->lb_crif);
1058610824 }
1058710825
1058810826 static int mlxsw_sp1_router_init(struct mlxsw_sp *mlxsw_sp)
@@ -10647,6 +10885,11 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp, · 58 unmodified lines
1064710885 if (err)
1064810886 goto err_ipips_init;
1064910887
10888+ err = rhashtable_init(&mlxsw_sp->router->crif_ht,
10889+ &mlxsw_sp_crif_ht_params);
10890+ if (err)
10891+ goto err_crif_ht_init;
10892+
1065010893 err = mlxsw_sp_rifs_init(mlxsw_sp);
1065110894 if (err)
1065210895 goto err_rifs_init;
@@ -10674,7 +10917,7 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp, · 21 unmodified lines
1067410917 if (err)
1067510918 goto err_vrs_init;
1067610919
10677− err = mlxsw_sp_lb_rif_init(mlxsw_sp);
10920+ err = mlxsw_sp_lb_rif_init(mlxsw_sp, extack);
1067810921 if (err)
1067910922 goto err_lb_rif_init;
1068010923
@@ -10778,6 +11021,8 @@ err_nexthop_group_ht_init: · 97 unmodified lines
1077811021 err_nexthop_ht_init:
1077911022 mlxsw_sp_rifs_fini(mlxsw_sp);
1078011023 err_rifs_init:
11024+ rhashtable_destroy(&mlxsw_sp->router->crif_ht);
11025+err_crif_ht_init:
1078111026 mlxsw_sp_ipips_fini(mlxsw_sp);
1078211027 err_ipips_init:
1078311028 __mlxsw_sp_router_fini(mlxsw_sp);
@@ -10813,6 +11058,7 @@ void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp) · 29 unmodified lines
1081311058 rhashtable_destroy(&router->nexthop_group_ht);
1081411059 rhashtable_destroy(&router->nexthop_ht);
1081511060 mlxsw_sp_rifs_fini(mlxsw_sp);
11061+ rhashtable_destroy(&mlxsw_sp->router->crif_ht);
1081611062 mlxsw_sp_ipips_fini(mlxsw_sp);
1081711063 __mlxsw_sp_router_fini(mlxsw_sp);
1081811064 cancel_delayed_work_sync(&router->nh_grp_activity_dw);
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h+2−1
@@ -20,6 +20,7 @@ struct mlxsw_sp_router_nve_decap { · 19 unmodified lines
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;
@@ -59,7 +60,7 @@ struct mlxsw_sp_router { · 33 unmodified lines
5960 struct mlxsw_sp_router_nve_decap nve_decap_config;
6061 struct mutex lock; /* Protects shared router resources */
6162 struct mlxsw_sp_fib_entry_op_ctx *ll_op_ctx;
62− u16 lb_rif_index;
63+ struct mlxsw_sp_crif *lb_crif;
6364 const struct mlxsw_sp_adj_grp_size_range *adj_grp_size_ranges;
6465 size_t adj_grp_size_ranges_count;
6566 struct delayed_work nh_grp_activity_dw;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t