Skip to content

Commit d26fa62

Browse files
nscndNipaLocal
authored andcommitted
neighbour: add support for NUD_PERMANENT proxy entries
As discussesd in [0] proxy entries (which are more configuration than runtime data) should stay when the link goes does down (carrier wise). This is what happens for regular neighbour entries added manually. So lets fix this by: - storing in the proxy entries the mdn_state (only NUD_PERMANENT for now) - not removing NUD_PERMANENT proxy entries on carrier down by adding a skip_perm arg to pneigh_ifdown_and_unlock() (same as how it's done in neigh_flush_dev() for regular non-proxy entries) Link: https://lore.kernel.org/netdev/[email protected]/ [0] Signed-off-by: Nicolas Escande <[email protected]> Signed-off-by: NipaLocal <nipa@local>
1 parent 94e8679 commit d26fa62

File tree

2 files changed

+11
-3
lines changed

2 files changed

+11
-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+
u8 state;
185186
u32 key[];
186187
};
187188

net/core/neighbour.c

Lines changed: 10 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->state & NUD_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
}
@@ -1972,6 +1977,7 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh,
19721977
if (tb[NDA_PROTOCOL])
19731978
protocol = nla_get_u8(tb[NDA_PROTOCOL]);
19741979
if (ndm_flags & NTF_PROXY) {
1980+
u8 state = ndm->ndm_state & NUD_PERMANENT;
19751981
struct pneigh_entry *pn;
19761982

19771983
if (ndm_flags & NTF_MANAGED) {
@@ -1983,6 +1989,7 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh,
19831989
pn = pneigh_lookup(tbl, net, dst, dev, 1);
19841990
if (pn) {
19851991
pn->flags = ndm_flags;
1992+
pn->state = state;
19861993
if (protocol)
19871994
pn->protocol = protocol;
19881995
err = 0;

0 commit comments

Comments
 (0)