Commit b2157149 authored by Yotam Gigi's avatar Yotam Gigi Committed by David S. Miller

mlxsw: spectrum_router: Add the nexthop neigh activity update

For nexthop neighbours we need to make kernel to think there is a traffic
flowing to them preventing it from going to stale state. Otherwise
kernel would stale it and eventually the neigh would be removed from HW
and nexthop as well. That would reduce ECMP group in HW.
Signed-off-by: default avatarYotam Gigi <yotamg@mellanox.com>
Signed-off-by: default avatarIdo Schimmel <idosch@mellanox.com>
Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a7ff87ac
...@@ -223,6 +223,7 @@ struct mlxsw_sp_router { ...@@ -223,6 +223,7 @@ struct mlxsw_sp_router {
unsigned long interval; /* ms */ unsigned long interval; /* ms */
} neighs_update; } neighs_update;
struct list_head nexthop_group_list; struct list_head nexthop_group_list;
struct list_head nexthop_neighs_list;
}; };
struct mlxsw_sp { struct mlxsw_sp {
......
...@@ -570,6 +570,7 @@ struct mlxsw_sp_neigh_entry { ...@@ -570,6 +570,7 @@ struct mlxsw_sp_neigh_entry {
struct list_head nexthop_list; /* list of nexthops using struct list_head nexthop_list; /* list of nexthops using
* this neigh entry * this neigh entry
*/ */
struct list_head nexthop_neighs_list_node;
}; };
static const struct rhashtable_params mlxsw_sp_neigh_ht_params = { static const struct rhashtable_params mlxsw_sp_neigh_ht_params = {
...@@ -770,28 +771,15 @@ static void mlxsw_sp_router_neigh_rec_process(struct mlxsw_sp *mlxsw_sp, ...@@ -770,28 +771,15 @@ static void mlxsw_sp_router_neigh_rec_process(struct mlxsw_sp *mlxsw_sp,
} }
} }
static void static int mlxsw_sp_router_neighs_update_rauhtd(struct mlxsw_sp *mlxsw_sp)
mlxsw_sp_router_neighs_update_work_schedule(struct mlxsw_sp *mlxsw_sp)
{ {
unsigned long interval = mlxsw_sp->router.neighs_update.interval;
mlxsw_core_schedule_dw(&mlxsw_sp->router.neighs_update.dw,
msecs_to_jiffies(interval));
}
static void mlxsw_sp_router_neighs_update_work(struct work_struct *work)
{
struct mlxsw_sp *mlxsw_sp;
char *rauhtd_pl; char *rauhtd_pl;
u8 num_rec; u8 num_rec;
int i, err; int i, err;
rauhtd_pl = kmalloc(MLXSW_REG_RAUHTD_LEN, GFP_KERNEL); rauhtd_pl = kmalloc(MLXSW_REG_RAUHTD_LEN, GFP_KERNEL);
if (!rauhtd_pl) if (!rauhtd_pl)
return; return -ENOMEM;
mlxsw_sp = container_of(work, struct mlxsw_sp,
router.neighs_update.dw.work);
/* Make sure the neighbour's netdev isn't removed in the /* Make sure the neighbour's netdev isn't removed in the
* process. * process.
...@@ -813,6 +801,47 @@ static void mlxsw_sp_router_neighs_update_work(struct work_struct *work) ...@@ -813,6 +801,47 @@ static void mlxsw_sp_router_neighs_update_work(struct work_struct *work)
rtnl_unlock(); rtnl_unlock();
kfree(rauhtd_pl); kfree(rauhtd_pl);
return err;
}
static void mlxsw_sp_router_neighs_update_nh(struct mlxsw_sp *mlxsw_sp)
{
struct mlxsw_sp_neigh_entry *neigh_entry;
/* Take RTNL mutex here to prevent lists from changes */
rtnl_lock();
list_for_each_entry(neigh_entry, &mlxsw_sp->router.nexthop_neighs_list,
nexthop_neighs_list_node) {
/* If this neigh have nexthops, make the kernel think this neigh
* is active regardless of the traffic.
*/
if (!list_empty(&neigh_entry->nexthop_list))
neigh_event_send(neigh_entry->n, NULL);
}
rtnl_unlock();
}
static void
mlxsw_sp_router_neighs_update_work_schedule(struct mlxsw_sp *mlxsw_sp)
{
unsigned long interval = mlxsw_sp->router.neighs_update.interval;
mlxsw_core_schedule_dw(&mlxsw_sp->router.neighs_update.dw,
msecs_to_jiffies(interval));
}
static void mlxsw_sp_router_neighs_update_work(struct work_struct *work)
{
struct mlxsw_sp *mlxsw_sp = container_of(work, struct mlxsw_sp,
router.neighs_update.dw.work);
int err;
err = mlxsw_sp_router_neighs_update_rauhtd(mlxsw_sp);
if (err)
dev_err(mlxsw_sp->bus_info->dev, "Could not update kernel for neigh activity");
mlxsw_sp_router_neighs_update_nh(mlxsw_sp);
mlxsw_sp_router_neighs_update_work_schedule(mlxsw_sp); mlxsw_sp_router_neighs_update_work_schedule(mlxsw_sp);
} }
...@@ -1277,6 +1306,14 @@ static int mlxsw_sp_nexthop_init(struct mlxsw_sp *mlxsw_sp, ...@@ -1277,6 +1306,14 @@ static int mlxsw_sp_nexthop_init(struct mlxsw_sp *mlxsw_sp,
n = neigh_entry->n; n = neigh_entry->n;
neigh_clone(n); neigh_clone(n);
} }
/* If that is the first nexthop connected to that neigh, add to
* nexthop_neighs_list
*/
if (list_empty(&neigh_entry->nexthop_list))
list_add_tail(&neigh_entry->nexthop_neighs_list_node,
&mlxsw_sp->router.nexthop_neighs_list);
nh->nh_grp = nh_grp; nh->nh_grp = nh_grp;
nh->neigh_entry = neigh_entry; nh->neigh_entry = neigh_entry;
list_add_tail(&nh->neigh_list_node, &neigh_entry->nexthop_list); list_add_tail(&nh->neigh_list_node, &neigh_entry->nexthop_list);
...@@ -1294,6 +1331,13 @@ static void mlxsw_sp_nexthop_fini(struct mlxsw_sp *mlxsw_sp, ...@@ -1294,6 +1331,13 @@ static void mlxsw_sp_nexthop_fini(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_neigh_entry *neigh_entry = nh->neigh_entry; struct mlxsw_sp_neigh_entry *neigh_entry = nh->neigh_entry;
list_del(&nh->neigh_list_node); list_del(&nh->neigh_list_node);
/* If that is the last nexthop connected to that neigh, remove from
* nexthop_neighs_list
*/
if (list_empty(&nh->neigh_entry->nexthop_list))
list_del(&nh->neigh_entry->nexthop_neighs_list_node);
neigh_release(neigh_entry->n); neigh_release(neigh_entry->n);
} }
...@@ -1442,6 +1486,7 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp) ...@@ -1442,6 +1486,7 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp)
{ {
int err; int err;
INIT_LIST_HEAD(&mlxsw_sp->router.nexthop_neighs_list);
INIT_LIST_HEAD(&mlxsw_sp->router.nexthop_group_list); INIT_LIST_HEAD(&mlxsw_sp->router.nexthop_group_list);
err = __mlxsw_sp_router_init(mlxsw_sp); err = __mlxsw_sp_router_init(mlxsw_sp);
if (err) if (err)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment