Skip to content

Commit dacad7b

Browse files
idoschdavem330
authored andcommitted
mlxsw: spectrum_router: Start using new IPv6 route notifications
With the new notifications mlxsw does not need to handle identical routes itself, as this is taken care of by the core IPv6 code. Instead, mlxsw only needs to take care of inserting and removing routes from the device. Convert mlxsw to use the new IPv6 route notifications and simplify the code. Signed-off-by: Ido Schimmel <[email protected]> Reviewed-by: Jiri Pirko <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 0284696 commit dacad7b

File tree

1 file changed

+76
-149
lines changed

1 file changed

+76
-149
lines changed

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

Lines changed: 76 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -4989,51 +4989,13 @@ static void mlxsw_sp_rt6_destroy(struct mlxsw_sp_rt6 *mlxsw_sp_rt6)
49894989
kfree(mlxsw_sp_rt6);
49904990
}
49914991

4992-
static bool mlxsw_sp_fib6_rt_can_mp(const struct fib6_info *rt)
4993-
{
4994-
/* RTF_CACHE routes are ignored */
4995-
return !(rt->fib6_flags & RTF_ADDRCONF) &&
4996-
rt->fib6_nh->fib_nh_gw_family;
4997-
}
4998-
49994992
static struct fib6_info *
50004993
mlxsw_sp_fib6_entry_rt(const struct mlxsw_sp_fib6_entry *fib6_entry)
50014994
{
50024995
return list_first_entry(&fib6_entry->rt6_list, struct mlxsw_sp_rt6,
50034996
list)->rt;
50044997
}
50054998

5006-
static struct mlxsw_sp_fib6_entry *
5007-
mlxsw_sp_fib6_node_mp_entry_find(const struct mlxsw_sp_fib_node *fib_node,
5008-
const struct fib6_info *nrt, bool replace)
5009-
{
5010-
struct mlxsw_sp_fib6_entry *fib6_entry;
5011-
5012-
if (!mlxsw_sp_fib6_rt_can_mp(nrt) || replace)
5013-
return NULL;
5014-
5015-
list_for_each_entry(fib6_entry, &fib_node->entry_list, common.list) {
5016-
struct fib6_info *rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
5017-
5018-
/* RT6_TABLE_LOCAL and RT6_TABLE_MAIN share the same
5019-
* virtual router.
5020-
*/
5021-
if (rt->fib6_table->tb6_id > nrt->fib6_table->tb6_id)
5022-
continue;
5023-
if (rt->fib6_table->tb6_id != nrt->fib6_table->tb6_id)
5024-
break;
5025-
if (rt->fib6_metric < nrt->fib6_metric)
5026-
continue;
5027-
if (rt->fib6_metric == nrt->fib6_metric &&
5028-
mlxsw_sp_fib6_rt_can_mp(rt))
5029-
return fib6_entry;
5030-
if (rt->fib6_metric > nrt->fib6_metric)
5031-
break;
5032-
}
5033-
5034-
return NULL;
5035-
}
5036-
50374999
static struct mlxsw_sp_rt6 *
50385000
mlxsw_sp_fib6_entry_rt_find(const struct mlxsw_sp_fib6_entry *fib6_entry,
50395001
const struct fib6_info *rt)
@@ -5424,86 +5386,13 @@ static void mlxsw_sp_fib6_entry_destroy(struct mlxsw_sp *mlxsw_sp,
54245386
kfree(fib6_entry);
54255387
}
54265388

5427-
static struct mlxsw_sp_fib6_entry *
5428-
mlxsw_sp_fib6_node_entry_find(const struct mlxsw_sp_fib_node *fib_node,
5429-
const struct fib6_info *nrt, bool replace)
5430-
{
5431-
struct mlxsw_sp_fib6_entry *fib6_entry, *fallback = NULL;
5432-
5433-
list_for_each_entry(fib6_entry, &fib_node->entry_list, common.list) {
5434-
struct fib6_info *rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
5435-
5436-
if (rt->fib6_table->tb6_id > nrt->fib6_table->tb6_id)
5437-
continue;
5438-
if (rt->fib6_table->tb6_id != nrt->fib6_table->tb6_id)
5439-
break;
5440-
if (replace && rt->fib6_metric == nrt->fib6_metric) {
5441-
if (mlxsw_sp_fib6_rt_can_mp(rt) ==
5442-
mlxsw_sp_fib6_rt_can_mp(nrt))
5443-
return fib6_entry;
5444-
if (mlxsw_sp_fib6_rt_can_mp(nrt))
5445-
fallback = fallback ?: fib6_entry;
5446-
}
5447-
if (rt->fib6_metric > nrt->fib6_metric)
5448-
return fallback ?: fib6_entry;
5449-
}
5450-
5451-
return fallback;
5452-
}
5453-
5454-
static int
5455-
mlxsw_sp_fib6_node_list_insert(struct mlxsw_sp_fib6_entry *new6_entry,
5456-
bool *p_replace)
5457-
{
5458-
struct mlxsw_sp_fib_node *fib_node = new6_entry->common.fib_node;
5459-
struct fib6_info *nrt = mlxsw_sp_fib6_entry_rt(new6_entry);
5460-
struct mlxsw_sp_fib6_entry *fib6_entry;
5461-
5462-
fib6_entry = mlxsw_sp_fib6_node_entry_find(fib_node, nrt, *p_replace);
5463-
5464-
if (*p_replace && !fib6_entry)
5465-
*p_replace = false;
5466-
5467-
if (fib6_entry) {
5468-
list_add_tail(&new6_entry->common.list,
5469-
&fib6_entry->common.list);
5470-
} else {
5471-
struct mlxsw_sp_fib6_entry *last;
5472-
5473-
list_for_each_entry(last, &fib_node->entry_list, common.list) {
5474-
struct fib6_info *rt = mlxsw_sp_fib6_entry_rt(last);
5475-
5476-
if (nrt->fib6_table->tb6_id > rt->fib6_table->tb6_id)
5477-
break;
5478-
fib6_entry = last;
5479-
}
5480-
5481-
if (fib6_entry)
5482-
list_add(&new6_entry->common.list,
5483-
&fib6_entry->common.list);
5484-
else
5485-
list_add(&new6_entry->common.list,
5486-
&fib_node->entry_list);
5487-
}
5488-
5489-
return 0;
5490-
}
5491-
5492-
static void
5493-
mlxsw_sp_fib6_node_list_remove(struct mlxsw_sp_fib6_entry *fib6_entry)
5494-
{
5495-
list_del(&fib6_entry->common.list);
5496-
}
5497-
54985389
static int mlxsw_sp_fib6_node_entry_link(struct mlxsw_sp *mlxsw_sp,
5499-
struct mlxsw_sp_fib6_entry *fib6_entry,
5500-
bool *p_replace)
5390+
struct mlxsw_sp_fib6_entry *fib6_entry)
55015391
{
5392+
struct mlxsw_sp_fib_node *fib_node = fib6_entry->common.fib_node;
55025393
int err;
55035394

5504-
err = mlxsw_sp_fib6_node_list_insert(fib6_entry, p_replace);
5505-
if (err)
5506-
return err;
5395+
list_add(&fib6_entry->common.list, &fib_node->entry_list);
55075396

55085397
err = mlxsw_sp_fib_node_entry_add(mlxsw_sp, &fib6_entry->common);
55095398
if (err)
@@ -5512,7 +5401,7 @@ static int mlxsw_sp_fib6_node_entry_link(struct mlxsw_sp *mlxsw_sp,
55125401
return 0;
55135402

55145403
err_fib_node_entry_add:
5515-
mlxsw_sp_fib6_node_list_remove(fib6_entry);
5404+
list_del(&fib6_entry->common.list);
55165405
return err;
55175406
}
55185407

@@ -5521,7 +5410,7 @@ mlxsw_sp_fib6_node_entry_unlink(struct mlxsw_sp *mlxsw_sp,
55215410
struct mlxsw_sp_fib6_entry *fib6_entry)
55225411
{
55235412
mlxsw_sp_fib_node_entry_del(mlxsw_sp, &fib6_entry->common);
5524-
mlxsw_sp_fib6_node_list_remove(fib6_entry);
5413+
list_del(&fib6_entry->common.list);
55255414
}
55265415

55275416
static struct mlxsw_sp_fib6_entry *
@@ -5557,25 +5446,25 @@ mlxsw_sp_fib6_entry_lookup(struct mlxsw_sp *mlxsw_sp,
55575446
}
55585447

55595448
static void mlxsw_sp_fib6_entry_replace(struct mlxsw_sp *mlxsw_sp,
5560-
struct mlxsw_sp_fib6_entry *fib6_entry,
5561-
bool replace)
5449+
struct mlxsw_sp_fib6_entry *fib6_entry)
55625450
{
55635451
struct mlxsw_sp_fib_node *fib_node = fib6_entry->common.fib_node;
55645452
struct mlxsw_sp_fib6_entry *replaced;
55655453

5566-
if (!replace)
5454+
if (list_is_singular(&fib_node->entry_list))
55675455
return;
55685456

5457+
/* We inserted the new entry before replaced one */
55695458
replaced = list_next_entry(fib6_entry, common.list);
55705459

55715460
mlxsw_sp_fib6_node_entry_unlink(mlxsw_sp, replaced);
55725461
mlxsw_sp_fib6_entry_destroy(mlxsw_sp, replaced);
55735462
mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
55745463
}
55755464

5576-
static int mlxsw_sp_router_fib6_add(struct mlxsw_sp *mlxsw_sp,
5577-
struct fib6_info **rt_arr,
5578-
unsigned int nrt6, bool replace)
5465+
static int mlxsw_sp_router_fib6_replace(struct mlxsw_sp *mlxsw_sp,
5466+
struct fib6_info **rt_arr,
5467+
unsigned int nrt6)
55795468
{
55805469
struct mlxsw_sp_fib6_entry *fib6_entry;
55815470
struct mlxsw_sp_fib_node *fib_node;
@@ -5599,36 +5488,68 @@ static int mlxsw_sp_router_fib6_add(struct mlxsw_sp *mlxsw_sp,
55995488
if (IS_ERR(fib_node))
56005489
return PTR_ERR(fib_node);
56015490

5602-
/* Before creating a new entry, try to append route to an existing
5603-
* multipath entry.
5604-
*/
5605-
fib6_entry = mlxsw_sp_fib6_node_mp_entry_find(fib_node, rt, replace);
5606-
if (fib6_entry) {
5607-
err = mlxsw_sp_fib6_entry_nexthop_add(mlxsw_sp, fib6_entry,
5608-
rt_arr, nrt6);
5609-
if (err)
5610-
goto err_fib6_entry_nexthop_add;
5611-
return 0;
5612-
}
5613-
56145491
fib6_entry = mlxsw_sp_fib6_entry_create(mlxsw_sp, fib_node, rt_arr,
56155492
nrt6);
56165493
if (IS_ERR(fib6_entry)) {
56175494
err = PTR_ERR(fib6_entry);
56185495
goto err_fib6_entry_create;
56195496
}
56205497

5621-
err = mlxsw_sp_fib6_node_entry_link(mlxsw_sp, fib6_entry, &replace);
5498+
err = mlxsw_sp_fib6_node_entry_link(mlxsw_sp, fib6_entry);
56225499
if (err)
56235500
goto err_fib6_node_entry_link;
56245501

5625-
mlxsw_sp_fib6_entry_replace(mlxsw_sp, fib6_entry, replace);
5502+
mlxsw_sp_fib6_entry_replace(mlxsw_sp, fib6_entry);
56265503

56275504
return 0;
56285505

56295506
err_fib6_node_entry_link:
56305507
mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
56315508
err_fib6_entry_create:
5509+
mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
5510+
return err;
5511+
}
5512+
5513+
static int mlxsw_sp_router_fib6_append(struct mlxsw_sp *mlxsw_sp,
5514+
struct fib6_info **rt_arr,
5515+
unsigned int nrt6)
5516+
{
5517+
struct mlxsw_sp_fib6_entry *fib6_entry;
5518+
struct mlxsw_sp_fib_node *fib_node;
5519+
struct fib6_info *rt = rt_arr[0];
5520+
int err;
5521+
5522+
if (mlxsw_sp->router->aborted)
5523+
return 0;
5524+
5525+
if (rt->fib6_src.plen)
5526+
return -EINVAL;
5527+
5528+
if (mlxsw_sp_fib6_rt_should_ignore(rt))
5529+
return 0;
5530+
5531+
fib_node = mlxsw_sp_fib_node_get(mlxsw_sp, rt->fib6_table->tb6_id,
5532+
&rt->fib6_dst.addr,
5533+
sizeof(rt->fib6_dst.addr),
5534+
rt->fib6_dst.plen,
5535+
MLXSW_SP_L3_PROTO_IPV6);
5536+
if (IS_ERR(fib_node))
5537+
return PTR_ERR(fib_node);
5538+
5539+
if (WARN_ON_ONCE(list_empty(&fib_node->entry_list))) {
5540+
mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
5541+
return -EINVAL;
5542+
}
5543+
5544+
fib6_entry = list_first_entry(&fib_node->entry_list,
5545+
struct mlxsw_sp_fib6_entry, common.list);
5546+
err = mlxsw_sp_fib6_entry_nexthop_add(mlxsw_sp, fib6_entry, rt_arr,
5547+
nrt6);
5548+
if (err)
5549+
goto err_fib6_entry_nexthop_add;
5550+
5551+
return 0;
5552+
56325553
err_fib6_entry_nexthop_add:
56335554
mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
56345555
return err;
@@ -6039,25 +5960,29 @@ static void mlxsw_sp_router_fib6_event_work(struct work_struct *work)
60395960
struct mlxsw_sp_fib_event_work *fib_work =
60405961
container_of(work, struct mlxsw_sp_fib_event_work, work);
60415962
struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp;
6042-
bool replace;
60435963
int err;
60445964

60455965
rtnl_lock();
60465966
mlxsw_sp_span_respin(mlxsw_sp);
60475967

60485968
switch (fib_work->event) {
6049-
case FIB_EVENT_ENTRY_REPLACE: /* fall through */
6050-
case FIB_EVENT_ENTRY_ADD:
6051-
replace = fib_work->event == FIB_EVENT_ENTRY_REPLACE;
6052-
err = mlxsw_sp_router_fib6_add(mlxsw_sp,
6053-
fib_work->fib6_work.rt_arr,
6054-
fib_work->fib6_work.nrt6,
6055-
replace);
5969+
case FIB_EVENT_ENTRY_REPLACE_TMP:
5970+
err = mlxsw_sp_router_fib6_replace(mlxsw_sp,
5971+
fib_work->fib6_work.rt_arr,
5972+
fib_work->fib6_work.nrt6);
60565973
if (err)
60575974
mlxsw_sp_router_fib_abort(mlxsw_sp);
60585975
mlxsw_sp_router_fib6_work_fini(&fib_work->fib6_work);
60595976
break;
6060-
case FIB_EVENT_ENTRY_DEL:
5977+
case FIB_EVENT_ENTRY_APPEND:
5978+
err = mlxsw_sp_router_fib6_append(mlxsw_sp,
5979+
fib_work->fib6_work.rt_arr,
5980+
fib_work->fib6_work.nrt6);
5981+
if (err)
5982+
mlxsw_sp_router_fib_abort(mlxsw_sp);
5983+
mlxsw_sp_router_fib6_work_fini(&fib_work->fib6_work);
5984+
break;
5985+
case FIB_EVENT_ENTRY_DEL_TMP:
60615986
mlxsw_sp_router_fib6_del(mlxsw_sp,
60625987
fib_work->fib6_work.rt_arr,
60635988
fib_work->fib6_work.nrt6);
@@ -6143,9 +6068,9 @@ static int mlxsw_sp_router_fib6_event(struct mlxsw_sp_fib_event_work *fib_work,
61436068
int err;
61446069

61456070
switch (fib_work->event) {
6146-
case FIB_EVENT_ENTRY_REPLACE: /* fall through */
6147-
case FIB_EVENT_ENTRY_ADD: /* fall through */
6148-
case FIB_EVENT_ENTRY_DEL:
6071+
case FIB_EVENT_ENTRY_REPLACE_TMP: /* fall through */
6072+
case FIB_EVENT_ENTRY_APPEND: /* fall through */
6073+
case FIB_EVENT_ENTRY_DEL_TMP:
61496074
fen6_info = container_of(info, struct fib6_entry_notifier_info,
61506075
info);
61516076
err = mlxsw_sp_router_fib6_work_init(&fib_work->fib6_work,
@@ -6248,7 +6173,9 @@ static int mlxsw_sp_router_fib_event(struct notifier_block *nb,
62486173
router->mlxsw_sp);
62496174
return notifier_from_errno(err);
62506175
case FIB_EVENT_ENTRY_ADD: /* fall through */
6251-
case FIB_EVENT_ENTRY_REPLACE:
6176+
case FIB_EVENT_ENTRY_REPLACE: /* fall through */
6177+
case FIB_EVENT_ENTRY_REPLACE_TMP: /* fall through */
6178+
case FIB_EVENT_ENTRY_APPEND:
62526179
if (router->aborted) {
62536180
NL_SET_ERR_MSG_MOD(info->extack, "FIB offload was aborted. Not configuring route");
62546181
return notifier_from_errno(-EINVAL);

0 commit comments

Comments
 (0)