mlxsw: spectrum_router: Don't reflect dead neighs
authorIdo Schimmel <idosch@mellanox.com>
Fri, 23 Dec 2016 08:32:49 +0000 (09:32 +0100)
committerDavid S. Miller <davem@davemloft.net>
Fri, 23 Dec 2016 17:31:19 +0000 (12:31 -0500)
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: a6bf9e933daf ("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>
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c

index 53126bf68ea937e7b2c6951787c25450ec0ebdb5..a0f9742f62dfa7ef250fda763a70e6c0a27145d2 100644 (file)
@@ -942,7 +942,7 @@ static void mlxsw_sp_router_neigh_update_hw(struct work_struct *work)
        char rauht_pl[MLXSW_REG_RAUHT_LEN];
        struct net_device *dev;
        bool entry_connected;
-       u8 nud_state;
+       u8 nud_state, dead;
        bool updating;
        bool removing;
        bool adding;
@@ -953,10 +953,11 @@ static void mlxsw_sp_router_neigh_update_hw(struct work_struct *work)
        dip = ntohl(*((__be32 *) n->primary_key));
        memcpy(neigh_entry->ha, n->ha, sizeof(neigh_entry->ha));
        nud_state = n->nud_state;
+       dead = n->dead;
        dev = n->dev;
        read_unlock_bh(&n->lock);
 
-       entry_connected = nud_state & NUD_VALID;
+       entry_connected = nud_state & NUD_VALID && !dead;
        adding = (!neigh_entry->offloaded) && entry_connected;
        updating = 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 net_device *dev = fib_nh->nh_dev;
        struct neighbour *n;
-       u8 nud_state;
+       u8 nud_state, dead;
 
        /* Take a reference of neigh here ensuring that neigh would
         * 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);
        read_lock_bh(&n->lock);
        nud_state = n->nud_state;
+       dead = n->dead;
        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;
 }