Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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/c584ef7e-6897-01f3-5b80-12b53f7b4bf4@kernel.org/

Signed-off-by: Nicolas Escande <nico.escande@gmail.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Link: https://patch.msgid.link/20250617141334.3724863-1-nico.escande@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Nicolas Escande and committed by
Jakub Kicinski
c7d78566 7399ef98

+10 -3
+1
include/net/neighbour.h
··· 182 182 netdevice_tracker dev_tracker; 183 183 u32 flags; 184 184 u8 protocol; 185 + bool permanent; 185 186 u32 key[]; 186 187 }; 187 188
+9 -3
net/core/neighbour.c
··· 54 54 u32 pid); 55 55 static void neigh_update_notify(struct neighbour *neigh, u32 nlmsg_pid); 56 56 static int pneigh_ifdown_and_unlock(struct neigh_table *tbl, 57 - struct net_device *dev); 57 + struct net_device *dev, 58 + bool skip_perm); 58 59 59 60 #ifdef CONFIG_PROC_FS 60 61 static const struct seq_operations neigh_stat_seq_ops; ··· 424 423 { 425 424 write_lock_bh(&tbl->lock); 426 425 neigh_flush_dev(tbl, dev, skip_perm); 427 - pneigh_ifdown_and_unlock(tbl, dev); 426 + pneigh_ifdown_and_unlock(tbl, dev, skip_perm); 428 427 pneigh_queue_purge(&tbl->proxy_queue, dev ? dev_net(dev) : NULL, 429 428 tbl->family); 430 429 if (skb_queue_empty_lockless(&tbl->proxy_queue)) ··· 804 803 } 805 804 806 805 static int pneigh_ifdown_and_unlock(struct neigh_table *tbl, 807 - struct net_device *dev) 806 + struct net_device *dev, 807 + bool skip_perm) 808 808 { 809 809 struct pneigh_entry *n, **np, *freelist = NULL; 810 810 u32 h; ··· 813 811 for (h = 0; h <= PNEIGH_HASHMASK; h++) { 814 812 np = &tbl->phash_buckets[h]; 815 813 while ((n = *np) != NULL) { 814 + if (skip_perm && n->permanent) 815 + goto skip; 816 816 if (!dev || n->dev == dev) { 817 817 *np = n->next; 818 818 n->next = freelist; 819 819 freelist = n; 820 820 continue; 821 821 } 822 + skip: 822 823 np = &n->next; 823 824 } 824 825 } ··· 1988 1983 pn = pneigh_lookup(tbl, net, dst, dev, 1); 1989 1984 if (pn) { 1990 1985 pn->flags = ndm_flags; 1986 + pn->permanent = !!(ndm->ndm_state & NUD_PERMANENT); 1991 1987 if (protocol) 1992 1988 pn->protocol = protocol; 1993 1989 err = 0;