neighbour: skip NTF_EXT_LEARNED entries during forced gc
authorRoopa Prabhu <roopa@cumulusnetworks.com>
Wed, 13 Jun 2018 04:26:10 +0000 (21:26 -0700)
committerDavid S. Miller <davem@davemloft.net>
Fri, 15 Jun 2018 16:37:33 +0000 (09:37 -0700)
Commit 9ce33e46531d ("neighbour: support for NTF_EXT_LEARNED flag")
added support for NTF_EXT_LEARNED for neighbour entries.
NTF_EXT_LEARNED entries are neigh entries managed by control
plane (eg: Ethernet VPN implementation in FRR routing suite).
Periodic gc already excludes these entries. This patch extends
it to forced gc which the earlier patch missed.

Fixes: 9ce33e46531d ("neighbour: support for NTF_EXT_LEARNED flag")
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/core/neighbour.c

index a7a9c3d738ba8c3309fa17cfb85dae81d0d9a095..8e3fda9e725cba97973ed2ce85ebe6f2e926e7cf 100644 (file)
@@ -119,13 +119,14 @@ unsigned long neigh_rand_reach_time(unsigned long base)
 EXPORT_SYMBOL(neigh_rand_reach_time);
 
 
-static bool neigh_del(struct neighbour *n, __u8 state,
+static bool neigh_del(struct neighbour *n, __u8 state, __u8 flags,
                      struct neighbour __rcu **np, struct neigh_table *tbl)
 {
        bool retval = false;
 
        write_lock(&n->lock);
-       if (refcount_read(&n->refcnt) == 1 && !(n->nud_state & state)) {
+       if (refcount_read(&n->refcnt) == 1 && !(n->nud_state & state) &&
+           !(n->flags & flags)) {
                struct neighbour *neigh;
 
                neigh = rcu_dereference_protected(n->next,
@@ -157,7 +158,7 @@ bool neigh_remove_one(struct neighbour *ndel, struct neigh_table *tbl)
        while ((n = rcu_dereference_protected(*np,
                                              lockdep_is_held(&tbl->lock)))) {
                if (n == ndel)
-                       return neigh_del(n, 0, np, tbl);
+                       return neigh_del(n, 0, 0, np, tbl);
                np = &n->next;
        }
        return false;
@@ -185,7 +186,8 @@ static int neigh_forced_gc(struct neigh_table *tbl)
                         * - nobody refers to it.
                         * - it is not permanent
                         */
-                       if (neigh_del(n, NUD_PERMANENT, np, tbl)) {
+                       if (neigh_del(n, NUD_PERMANENT, NTF_EXT_LEARNED, np,
+                                     tbl)) {
                                shrunk = 1;
                                continue;
                        }