From: David Ahern <dsahern@kernel.org>
To: netdev@vger.kernel.org
Cc: davem@davemloft.net, roopa@cumulusnetworks.com,
David Ahern <dsahern@gmail.com>
Subject: [PATCH net-next 5/5] neighbor: Remove externally learned entries from gc_list
Date: Tue, 11 Dec 2018 18:57:25 -0700 [thread overview]
Message-ID: <20181212015725.12297-6-dsahern@kernel.org> (raw)
In-Reply-To: <20181212015725.12297-1-dsahern@kernel.org>
From: David Ahern <dsahern@gmail.com>
Externally learned entries are similar to PERMANENT entries in the
sense they are managed by userspace and can not be garbage collected.
As such remove them from the gc_list, remove the flags check from
neigh_forced_gc and skip threshold checks in neigh_alloc. As with
PERMANENT entries, this allows unlimited number of NTF_EXT_LEARNED
entries.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
net/core/neighbour.c | 49 ++++++++++++++++++++++++++++---------------------
1 file changed, 28 insertions(+), 21 deletions(-)
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 2401040f799b..42b413774370 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -129,21 +129,22 @@ static void neigh_mark_dead(struct neighbour *n)
static void neigh_update_gc_list(struct neighbour *n)
{
- bool on_gc_list, new_is_perm;
+ bool on_gc_list, exempt_from_gc;
write_lock_bh(&n->tbl->lock);
write_lock(&n->lock);
- /* remove from the gc list if new state is permanent;
- * add to the gc list if new state is not permanent
+ /* remove from the gc list if new state is permanent or if neighbor
+ * is externally learned; otherwise entry should be on the gc list
*/
- new_is_perm = n->nud_state & NUD_PERMANENT;
+ exempt_from_gc = n->nud_state & NUD_PERMANENT ||
+ n->flags & NTF_EXT_LEARNED;
on_gc_list = !list_empty(&n->gc_list);
- if (new_is_perm && on_gc_list) {
+ if (exempt_from_gc && on_gc_list) {
list_del_init(&n->gc_list);
atomic_dec(&n->tbl->gc_entries);
- } else if (!new_is_perm && !on_gc_list) {
+ } else if (!exempt_from_gc && !on_gc_list) {
/* add entries to the tail; cleaning removes from the front */
list_add_tail(&n->gc_list, &n->tbl->gc_list);
atomic_inc(&n->tbl->gc_entries);
@@ -153,13 +154,14 @@ static void neigh_update_gc_list(struct neighbour *n)
write_unlock_bh(&n->tbl->lock);
}
-static void neigh_update_ext_learned(struct neighbour *neigh, u32 flags,
+static bool neigh_update_ext_learned(struct neighbour *neigh, u32 flags,
int *notify)
{
+ bool rc = false;
u8 ndm_flags;
if (!(flags & NEIGH_UPDATE_F_ADMIN))
- return;
+ return rc;
ndm_flags = (flags & NEIGH_UPDATE_F_EXT_LEARNED) ? NTF_EXT_LEARNED : 0;
if ((neigh->flags ^ ndm_flags) & NTF_EXT_LEARNED) {
@@ -167,8 +169,11 @@ static void neigh_update_ext_learned(struct neighbour *neigh, u32 flags,
neigh->flags |= NTF_EXT_LEARNED;
else
neigh->flags &= ~NTF_EXT_LEARNED;
+ rc = true;
*notify = 1;
}
+
+ return rc;
}
static bool neigh_del(struct neighbour *n, struct neighbour __rcu **np,
@@ -219,7 +224,6 @@ static int neigh_forced_gc(struct neigh_table *tbl)
{
int max_clean = atomic_read(&tbl->gc_entries) - tbl->gc_thresh2;
unsigned long tref = jiffies - 5 * HZ;
- u8 flags = NTF_EXT_LEARNED;
struct neighbour *n, *tmp;
int shrunk = 0;
@@ -233,7 +237,7 @@ static int neigh_forced_gc(struct neigh_table *tbl)
write_lock(&n->lock);
if ((n->nud_state == NUD_FAILED) ||
- (!(n->flags & flags) && time_after(tref, n->updated)))
+ time_after(tref, n->updated))
remove = true;
write_unlock(&n->lock);
@@ -371,13 +375,13 @@ EXPORT_SYMBOL(neigh_ifdown);
static struct neighbour *neigh_alloc(struct neigh_table *tbl,
struct net_device *dev,
- bool permanent)
+ bool exempt_from_gc)
{
struct neighbour *n = NULL;
unsigned long now = jiffies;
int entries;
- if (permanent)
+ if (exempt_from_gc)
goto do_alloc;
entries = atomic_inc_return(&tbl->gc_entries) - 1;
@@ -419,7 +423,7 @@ static struct neighbour *neigh_alloc(struct neigh_table *tbl,
return n;
out_entries:
- if (!permanent)
+ if (!exempt_from_gc)
atomic_dec(&tbl->gc_entries);
goto out;
}
@@ -566,9 +570,9 @@ EXPORT_SYMBOL(neigh_lookup_nodev);
static struct neighbour *___neigh_create(struct neigh_table *tbl,
const void *pkey,
struct net_device *dev,
- bool permanent, bool want_ref)
+ bool exempt_from_gc, bool want_ref)
{
- struct neighbour *n1, *rc, *n = neigh_alloc(tbl, dev, permanent);
+ struct neighbour *n1, *rc, *n = neigh_alloc(tbl, dev, exempt_from_gc);
u32 hash_val;
unsigned int key_len = tbl->key_len;
int error;
@@ -634,7 +638,7 @@ static struct neighbour *___neigh_create(struct neigh_table *tbl,
}
n->dead = 0;
- if (!permanent)
+ if (!exempt_from_gc)
list_add_tail(&n->gc_list, &n->tbl->gc_list);
if (want_ref)
@@ -1210,6 +1214,7 @@ static int __neigh_update(struct neighbour *neigh, const u8 *lladdr,
u8 new, u32 flags, u32 nlmsg_pid,
struct netlink_ext_ack *extack)
{
+ bool ext_learn_change = false;
u8 old;
int err;
int notify = 0;
@@ -1230,7 +1235,7 @@ static int __neigh_update(struct neighbour *neigh, const u8 *lladdr,
goto out;
}
- neigh_update_ext_learned(neigh, flags, ¬ify);
+ ext_learn_change = neigh_update_ext_learned(neigh, flags, ¬ify);
if (!(new & NUD_VALID)) {
neigh_del_timer(neigh);
@@ -1376,7 +1381,7 @@ static int __neigh_update(struct neighbour *neigh, const u8 *lladdr,
neigh_update_is_router(neigh, flags, ¬ify);
write_unlock_bh(&neigh->lock);
- if ((new ^ old) & NUD_PERMANENT)
+ if (((new ^ old) & NUD_PERMANENT) || ext_learn_change)
neigh_update_gc_list(neigh);
if (notify)
@@ -1881,14 +1886,16 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh,
neigh = neigh_lookup(tbl, dst, dev);
if (neigh == NULL) {
+ bool exempt_from_gc;
+
if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
err = -ENOENT;
goto out;
}
- neigh = ___neigh_create(tbl, dst, dev,
- ndm->ndm_state & NUD_PERMANENT,
- true);
+ exempt_from_gc = ndm->ndm_state & NUD_PERMANENT ||
+ ndm->ndm_flags & NTF_EXT_LEARNED;
+ neigh = ___neigh_create(tbl, dst, dev, exempt_from_gc, true);
if (IS_ERR(neigh)) {
err = PTR_ERR(neigh);
goto out;
--
2.11.0
next prev parent reply other threads:[~2018-12-12 1:57 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-12-12 1:57 [PATCH net-next 0/5] neighbor: More gc_list changes David Ahern
2018-12-12 1:57 ` [PATCH net-next 1/5] neighbor: Fix locking order for " David Ahern
2018-12-12 1:57 ` [PATCH net-next 2/5] neighbor: Fix state check in neigh_forced_gc David Ahern
2018-12-12 1:57 ` [PATCH net-next 3/5] neighbor: Remove state and flags arguments to neigh_del David Ahern
2018-12-12 1:57 ` [PATCH net-next 4/5] neighbor: Move neigh_update_ext_learned to core file David Ahern
2018-12-12 1:57 ` David Ahern [this message]
2018-12-14 23:45 ` [PATCH net-next 0/5] neighbor: More gc_list changes David Miller
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20181212015725.12297-6-dsahern@kernel.org \
--to=dsahern@kernel.org \
--cc=davem@davemloft.net \
--cc=dsahern@gmail.com \
--cc=netdev@vger.kernel.org \
--cc=roopa@cumulusnetworks.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).