mirror of https://gitee.com/openkylin/linux.git
mlxsw: spectrum_router: Reflect IPv6 neighbours to the device
As with IPv4, listen to NEIGH_UPDATE events from the ndisc table and program relevant neighbours to the device's neighbour table. Note that neighbours with a link-local IP address aren't programmed, as packets with a link-local destination IP are trapped after LPM lookup and never reach the neighbour table. Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com> Signed-off-by: Ido Schimmel <idosch@mellanox.com> Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
6929e50736
commit
d5eb89cf68
|
@ -50,6 +50,8 @@
|
|||
#include <net/fib_rules.h>
|
||||
#include <net/l3mdev.h>
|
||||
#include <net/addrconf.h>
|
||||
#include <net/ndisc.h>
|
||||
#include <net/ipv6.h>
|
||||
|
||||
#include "spectrum.h"
|
||||
#include "core.h"
|
||||
|
@ -1147,6 +1149,32 @@ mlxsw_sp_router_neigh_entry_op4(struct mlxsw_sp *mlxsw_sp,
|
|||
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rauht), rauht_pl);
|
||||
}
|
||||
|
||||
static void
|
||||
mlxsw_sp_router_neigh_entry_op6(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_neigh_entry *neigh_entry,
|
||||
enum mlxsw_reg_rauht_op op)
|
||||
{
|
||||
struct neighbour *n = neigh_entry->key.n;
|
||||
char rauht_pl[MLXSW_REG_RAUHT_LEN];
|
||||
const char *dip = n->primary_key;
|
||||
|
||||
mlxsw_reg_rauht_pack6(rauht_pl, op, neigh_entry->rif, neigh_entry->ha,
|
||||
dip);
|
||||
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rauht), rauht_pl);
|
||||
}
|
||||
|
||||
static bool mlxsw_sp_neigh_ipv6_ignore(struct neighbour *n)
|
||||
{
|
||||
/* Packets with a link-local destination address are trapped
|
||||
* after LPM lookup and never reach the neighbour table, so
|
||||
* there is no need to program such neighbours to the device.
|
||||
*/
|
||||
if (ipv6_addr_type((struct in6_addr *) &n->primary_key) &
|
||||
IPV6_ADDR_LINKLOCAL)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
mlxsw_sp_neigh_entry_update(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_neigh_entry *neigh_entry,
|
||||
|
@ -1155,12 +1183,18 @@ mlxsw_sp_neigh_entry_update(struct mlxsw_sp *mlxsw_sp,
|
|||
if (!adding && !neigh_entry->connected)
|
||||
return;
|
||||
neigh_entry->connected = adding;
|
||||
if (neigh_entry->key.n->tbl == &arp_tbl)
|
||||
if (neigh_entry->key.n->tbl == &arp_tbl) {
|
||||
mlxsw_sp_router_neigh_entry_op4(mlxsw_sp, neigh_entry,
|
||||
mlxsw_sp_rauht_op(adding));
|
||||
else
|
||||
} else if (neigh_entry->key.n->tbl == &nd_tbl) {
|
||||
if (mlxsw_sp_neigh_ipv6_ignore(neigh_entry->key.n))
|
||||
return;
|
||||
mlxsw_sp_router_neigh_entry_op6(mlxsw_sp, neigh_entry,
|
||||
mlxsw_sp_rauht_op(adding));
|
||||
} else {
|
||||
WARN_ON_ONCE(1);
|
||||
}
|
||||
}
|
||||
|
||||
struct mlxsw_sp_neigh_event_work {
|
||||
struct work_struct work;
|
||||
|
@ -1247,7 +1281,7 @@ int mlxsw_sp_router_netevent_event(struct notifier_block *unused,
|
|||
case NETEVENT_NEIGH_UPDATE:
|
||||
n = ptr;
|
||||
|
||||
if (n->tbl != &arp_tbl)
|
||||
if (n->tbl != &arp_tbl && n->tbl != &nd_tbl)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
mlxsw_sp_port = mlxsw_sp_port_lower_dev_hold(n->dev);
|
||||
|
|
Loading…
Reference in New Issue