mlxsw: spectrum_router: Don't reflect dead neighs

When a neighbour is considered to be dead, we should remove it from the
device's table regardless of its NUD state.

Without this patch, after setting a port to be administratively down we
get the following errors when we periodically try to update the kernel
about neighbours activity:

[  461.947268] mlxsw_spectrum 0000:03:00.0 sw1p3: Failed to find
matching neighbour for IP=192.168.100.2

Fixes: a6bf9e933d ("mlxsw: spectrum_router: Offload neighbours based on NUD state change")
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:
Ido Schimmel 2016-12-23 09:32:49 +01:00 коммит произвёл David S. Miller
Родитель 53f800e3ba
Коммит 93a87e5e79
1 изменённых файлов: 6 добавлений и 4 удалений

Просмотреть файл

@ -942,7 +942,7 @@ static void mlxsw_sp_router_neigh_update_hw(struct work_struct *work)
char rauht_pl[MLXSW_REG_RAUHT_LEN]; char rauht_pl[MLXSW_REG_RAUHT_LEN];
struct net_device *dev; struct net_device *dev;
bool entry_connected; bool entry_connected;
u8 nud_state; u8 nud_state, dead;
bool updating; bool updating;
bool removing; bool removing;
bool adding; bool adding;
@ -953,10 +953,11 @@ static void mlxsw_sp_router_neigh_update_hw(struct work_struct *work)
dip = ntohl(*((__be32 *) n->primary_key)); dip = ntohl(*((__be32 *) n->primary_key));
memcpy(neigh_entry->ha, n->ha, sizeof(neigh_entry->ha)); memcpy(neigh_entry->ha, n->ha, sizeof(neigh_entry->ha));
nud_state = n->nud_state; nud_state = n->nud_state;
dead = n->dead;
dev = n->dev; dev = n->dev;
read_unlock_bh(&n->lock); read_unlock_bh(&n->lock);
entry_connected = nud_state & NUD_VALID; entry_connected = nud_state & NUD_VALID && !dead;
adding = (!neigh_entry->offloaded) && entry_connected; adding = (!neigh_entry->offloaded) && entry_connected;
updating = neigh_entry->offloaded && entry_connected; updating = neigh_entry->offloaded && entry_connected;
removing = neigh_entry->offloaded && !entry_connected; removing = neigh_entry->offloaded && !entry_connected;
@ -1351,7 +1352,7 @@ static int mlxsw_sp_nexthop_init(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_neigh_entry *neigh_entry; struct mlxsw_sp_neigh_entry *neigh_entry;
struct net_device *dev = fib_nh->nh_dev; struct net_device *dev = fib_nh->nh_dev;
struct neighbour *n; struct neighbour *n;
u8 nud_state; u8 nud_state, dead;
/* Take a reference of neigh here ensuring that neigh would /* Take a reference of neigh here ensuring that neigh would
* not be detructed before the nexthop entry is finished. * not be detructed before the nexthop entry is finished.
@ -1383,8 +1384,9 @@ static int mlxsw_sp_nexthop_init(struct mlxsw_sp *mlxsw_sp,
list_add_tail(&nh->neigh_list_node, &neigh_entry->nexthop_list); list_add_tail(&nh->neigh_list_node, &neigh_entry->nexthop_list);
read_lock_bh(&n->lock); read_lock_bh(&n->lock);
nud_state = n->nud_state; nud_state = n->nud_state;
dead = n->dead;
read_unlock_bh(&n->lock); read_unlock_bh(&n->lock);
__mlxsw_sp_nexthop_neigh_update(nh, !(nud_state & NUD_VALID)); __mlxsw_sp_nexthop_neigh_update(nh, !(nud_state & NUD_VALID && !dead));
return 0; return 0;
} }