Skip to content

Commit 41b5c20

Browse files
nscndNipaLocal
authored andcommitted
neighbour: add support for NUD_PERMANENT proxy entries
As discussesd before in [0] proxy entries (which are more configuration than runtime data) should stay when the link (carrier) goes does down. This is what happens for regular neighbour entries. So lets fix this by: - storing in proxy entries the fact that it was added as NUD_PERMANENT - not removing NUD_PERMANENT proxy entries when the carrier goes down (same as how it's done in neigh_flush_dev() for regular neigh entries) [0]: https://lore.kernel.org/netdev/[email protected]/ Signed-off-by: Nicolas Escande <[email protected]> Reviewed-by: Kuniyuki Iwashima <[email protected]> Signed-off-by: NipaLocal <nipa@local>
1 parent 59deadd commit 41b5c20

File tree

2 files changed

+10
-3
lines changed

2 files changed

+10
-3
lines changed

include/net/neighbour.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ struct pneigh_entry {
182182
netdevice_tracker dev_tracker;
183183
u32 flags;
184184
u8 protocol;
185+
bool permanent;
185186
u32 key[];
186187
};
187188

net/core/neighbour.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ static void __neigh_notify(struct neighbour *n, int type, int flags,
5454
u32 pid);
5555
static void neigh_update_notify(struct neighbour *neigh, u32 nlmsg_pid);
5656
static int pneigh_ifdown_and_unlock(struct neigh_table *tbl,
57-
struct net_device *dev);
57+
struct net_device *dev,
58+
bool skip_perm);
5859

5960
#ifdef CONFIG_PROC_FS
6061
static const struct seq_operations neigh_stat_seq_ops;
@@ -423,7 +424,7 @@ static int __neigh_ifdown(struct neigh_table *tbl, struct net_device *dev,
423424
{
424425
write_lock_bh(&tbl->lock);
425426
neigh_flush_dev(tbl, dev, skip_perm);
426-
pneigh_ifdown_and_unlock(tbl, dev);
427+
pneigh_ifdown_and_unlock(tbl, dev, skip_perm);
427428
pneigh_queue_purge(&tbl->proxy_queue, dev ? dev_net(dev) : NULL,
428429
tbl->family);
429430
if (skb_queue_empty_lockless(&tbl->proxy_queue))
@@ -803,20 +804,24 @@ int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey,
803804
}
804805

805806
static int pneigh_ifdown_and_unlock(struct neigh_table *tbl,
806-
struct net_device *dev)
807+
struct net_device *dev,
808+
bool skip_perm)
807809
{
808810
struct pneigh_entry *n, **np, *freelist = NULL;
809811
u32 h;
810812

811813
for (h = 0; h <= PNEIGH_HASHMASK; h++) {
812814
np = &tbl->phash_buckets[h];
813815
while ((n = *np) != NULL) {
816+
if (skip_perm && n->permanent)
817+
goto skip;
814818
if (!dev || n->dev == dev) {
815819
*np = n->next;
816820
n->next = freelist;
817821
freelist = n;
818822
continue;
819823
}
824+
skip:
820825
np = &n->next;
821826
}
822827
}
@@ -1983,6 +1988,7 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh,
19831988
pn = pneigh_lookup(tbl, net, dst, dev, 1);
19841989
if (pn) {
19851990
pn->flags = ndm_flags;
1991+
pn->permanent = !!(ndm->ndm_state & NUD_PERMANENT);
19861992
if (protocol)
19871993
pn->protocol = protocol;
19881994
err = 0;

0 commit comments

Comments
 (0)