Commit 60f040ca authored by Arkadi Sharshevsky's avatar Arkadi Sharshevsky Committed by David S. Miller

mlxsw: spectrum_router: Periodically dump active IPv6 neighbours

In addition to IPv4, periodically dump IPv6 neighbours and update the
kernel about them.
Signed-off-by: default avatarArkadi Sharshevsky <arkadis@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 72e8ebe1
...@@ -968,6 +968,36 @@ static void mlxsw_sp_router_neigh_ent_ipv4_process(struct mlxsw_sp *mlxsw_sp, ...@@ -968,6 +968,36 @@ static void mlxsw_sp_router_neigh_ent_ipv4_process(struct mlxsw_sp *mlxsw_sp,
neigh_release(n); neigh_release(n);
} }
static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp *mlxsw_sp,
char *rauhtd_pl,
int rec_index)
{
struct net_device *dev;
struct neighbour *n;
struct in6_addr dip;
u16 rif;
mlxsw_reg_rauhtd_ent_ipv6_unpack(rauhtd_pl, rec_index, &rif,
(char *) &dip);
if (!mlxsw_sp->router->rifs[rif]) {
dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Incorrect RIF in neighbour entry\n");
return;
}
dev = mlxsw_sp->router->rifs[rif]->dev;
n = neigh_lookup(&nd_tbl, &dip, dev);
if (!n) {
netdev_err(dev, "Failed to find matching neighbour for IP=%pI6c\n",
&dip);
return;
}
netdev_dbg(dev, "Updating neighbour with IP=%pI6c\n", &dip);
neigh_event_send(n, NULL);
neigh_release(n);
}
static void mlxsw_sp_router_neigh_rec_ipv4_process(struct mlxsw_sp *mlxsw_sp, static void mlxsw_sp_router_neigh_rec_ipv4_process(struct mlxsw_sp *mlxsw_sp,
char *rauhtd_pl, char *rauhtd_pl,
int rec_index) int rec_index)
...@@ -991,6 +1021,15 @@ static void mlxsw_sp_router_neigh_rec_ipv4_process(struct mlxsw_sp *mlxsw_sp, ...@@ -991,6 +1021,15 @@ static void mlxsw_sp_router_neigh_rec_ipv4_process(struct mlxsw_sp *mlxsw_sp,
} }
static void mlxsw_sp_router_neigh_rec_ipv6_process(struct mlxsw_sp *mlxsw_sp,
char *rauhtd_pl,
int rec_index)
{
/* One record contains one entry. */
mlxsw_sp_router_neigh_ent_ipv6_process(mlxsw_sp, rauhtd_pl,
rec_index);
}
static void mlxsw_sp_router_neigh_rec_process(struct mlxsw_sp *mlxsw_sp, static void mlxsw_sp_router_neigh_rec_process(struct mlxsw_sp *mlxsw_sp,
char *rauhtd_pl, int rec_index) char *rauhtd_pl, int rec_index)
{ {
...@@ -1000,7 +1039,8 @@ static void mlxsw_sp_router_neigh_rec_process(struct mlxsw_sp *mlxsw_sp, ...@@ -1000,7 +1039,8 @@ static void mlxsw_sp_router_neigh_rec_process(struct mlxsw_sp *mlxsw_sp,
rec_index); rec_index);
break; break;
case MLXSW_REG_RAUHTD_TYPE_IPV6: case MLXSW_REG_RAUHTD_TYPE_IPV6:
WARN_ON_ONCE(1); mlxsw_sp_router_neigh_rec_ipv6_process(mlxsw_sp, rauhtd_pl,
rec_index);
break; break;
} }
} }
...@@ -1025,22 +1065,20 @@ static bool mlxsw_sp_router_rauhtd_is_full(char *rauhtd_pl) ...@@ -1025,22 +1065,20 @@ static bool mlxsw_sp_router_rauhtd_is_full(char *rauhtd_pl)
return false; return false;
} }
static int mlxsw_sp_router_neighs_update_rauhtd(struct mlxsw_sp *mlxsw_sp) static int
__mlxsw_sp_router_neighs_update_rauhtd(struct mlxsw_sp *mlxsw_sp,
char *rauhtd_pl,
enum mlxsw_reg_rauhtd_type type)
{ {
char *rauhtd_pl; int i, num_rec;
u8 num_rec; int err;
int i, err;
rauhtd_pl = kmalloc(MLXSW_REG_RAUHTD_LEN, GFP_KERNEL);
if (!rauhtd_pl)
return -ENOMEM;
/* Make sure the neighbour's netdev isn't removed in the /* Make sure the neighbour's netdev isn't removed in the
* process. * process.
*/ */
rtnl_lock(); rtnl_lock();
do { do {
mlxsw_reg_rauhtd_pack(rauhtd_pl, MLXSW_REG_RAUHTD_TYPE_IPV4); mlxsw_reg_rauhtd_pack(rauhtd_pl, type);
err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(rauhtd), err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(rauhtd),
rauhtd_pl); rauhtd_pl);
if (err) { if (err) {
...@@ -1054,6 +1092,27 @@ static int mlxsw_sp_router_neighs_update_rauhtd(struct mlxsw_sp *mlxsw_sp) ...@@ -1054,6 +1092,27 @@ static int mlxsw_sp_router_neighs_update_rauhtd(struct mlxsw_sp *mlxsw_sp)
} while (mlxsw_sp_router_rauhtd_is_full(rauhtd_pl)); } while (mlxsw_sp_router_rauhtd_is_full(rauhtd_pl));
rtnl_unlock(); rtnl_unlock();
return err;
}
static int mlxsw_sp_router_neighs_update_rauhtd(struct mlxsw_sp *mlxsw_sp)
{
enum mlxsw_reg_rauhtd_type type;
char *rauhtd_pl;
int err;
rauhtd_pl = kmalloc(MLXSW_REG_RAUHTD_LEN, GFP_KERNEL);
if (!rauhtd_pl)
return -ENOMEM;
type = MLXSW_REG_RAUHTD_TYPE_IPV4;
err = __mlxsw_sp_router_neighs_update_rauhtd(mlxsw_sp, rauhtd_pl, type);
if (err)
goto out;
type = MLXSW_REG_RAUHTD_TYPE_IPV6;
err = __mlxsw_sp_router_neighs_update_rauhtd(mlxsw_sp, rauhtd_pl, type);
out:
kfree(rauhtd_pl); kfree(rauhtd_pl);
return err; return 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