Skip to content

Commit cecbbe3

Browse files
committed
Merge: CNB: net: add support for managed neighbor entries
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/2472 Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2193175 Tested: Manually as described in BZ (comment #2 and #3) Commits: ``` 3dc20f4 ("net, neigh: Enable state migration between NUD_PERMANENT and NTF_USE") 2c611ad ("net, neigh: Extend neigh->flags to 32 bit to allow for extensions") 7482e38 ("net, neigh: Add NTF_MANAGED flag for managed neighbor entries") 507c2f1 ("net, neigh: Add build-time assertion to avoid neigh->flags overflow") 30fc7ef ("net, neigh: Reject creating NUD_PERMANENT with NTF_MANAGED entries") 4177d5b ("net, neigh: Fix crash in v6 module initialization error path") 4a81f6d ("net, neigh: Do not trigger immediate probes on NUD_FAILED from neigh_managed_work") ``` Signed-off-by: Ivan Vecera <ivecera@redhat.com> Approved-by: Íñigo Huguet <ihuguet@redhat.com> Approved-by: Hangbin Liu <haliu@redhat.com> Signed-off-by: Jan Stancek <jstancek@redhat.com>
2 parents 1cf5981 + 28006e6 commit cecbbe3

File tree

3 files changed

+211
-81
lines changed

3 files changed

+211
-81
lines changed

include/net/neighbour.h

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -145,17 +145,18 @@ struct neighbour {
145145
struct timer_list timer;
146146
unsigned long used;
147147
atomic_t probes;
148-
__u8 flags;
149-
__u8 nud_state;
150-
__u8 type;
151-
__u8 dead;
148+
u8 nud_state;
149+
u8 type;
150+
u8 dead;
152151
u8 protocol;
152+
u32 flags;
153153
seqlock_t ha_lock;
154154
unsigned char ha[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))] __aligned(8);
155155
struct hh_cache hh;
156156
int (*output)(struct neighbour *, struct sk_buff *);
157157
const struct neigh_ops *ops;
158158
struct list_head gc_list;
159+
struct list_head managed_list;
159160
struct rcu_head rcu;
160161
struct net_device *dev;
161162
netdevice_tracker dev_tracker;
@@ -175,7 +176,7 @@ struct pneigh_entry {
175176
possible_net_t net;
176177
struct net_device *dev;
177178
netdevice_tracker dev_tracker;
178-
u8 flags;
179+
u32 flags;
179180
u8 protocol;
180181
u8 key[];
181182
};
@@ -219,11 +220,13 @@ struct neigh_table {
219220
int gc_thresh3;
220221
unsigned long last_flush;
221222
struct delayed_work gc_work;
223+
struct delayed_work managed_work;
222224
struct timer_list proxy_timer;
223225
struct sk_buff_head proxy_queue;
224226
atomic_t entries;
225227
atomic_t gc_entries;
226228
struct list_head gc_list;
229+
struct list_head managed_list;
227230
rwlock_t lock;
228231
unsigned long last_rand;
229232
struct neigh_statistics __percpu *stats;
@@ -253,12 +256,21 @@ static inline void *neighbour_priv(const struct neighbour *n)
253256
}
254257

255258
/* flags for neigh_update() */
256-
#define NEIGH_UPDATE_F_OVERRIDE 0x00000001
257-
#define NEIGH_UPDATE_F_WEAK_OVERRIDE 0x00000002
258-
#define NEIGH_UPDATE_F_OVERRIDE_ISROUTER 0x00000004
259-
#define NEIGH_UPDATE_F_EXT_LEARNED 0x20000000
260-
#define NEIGH_UPDATE_F_ISROUTER 0x40000000
261-
#define NEIGH_UPDATE_F_ADMIN 0x80000000
259+
#define NEIGH_UPDATE_F_OVERRIDE BIT(0)
260+
#define NEIGH_UPDATE_F_WEAK_OVERRIDE BIT(1)
261+
#define NEIGH_UPDATE_F_OVERRIDE_ISROUTER BIT(2)
262+
#define NEIGH_UPDATE_F_USE BIT(3)
263+
#define NEIGH_UPDATE_F_MANAGED BIT(4)
264+
#define NEIGH_UPDATE_F_EXT_LEARNED BIT(5)
265+
#define NEIGH_UPDATE_F_ISROUTER BIT(6)
266+
#define NEIGH_UPDATE_F_ADMIN BIT(7)
267+
268+
/* In-kernel representation for NDA_FLAGS_EXT flags: */
269+
#define NTF_OLD_MASK 0xff
270+
#define NTF_EXT_SHIFT 8
271+
#define NTF_EXT_MASK (NTF_EXT_MANAGED)
272+
273+
#define NTF_MANAGED (NTF_EXT_MANAGED << NTF_EXT_SHIFT)
262274

263275
extern const struct nla_policy nda_policy[];
264276

@@ -327,7 +339,8 @@ static inline struct neighbour *neigh_create(struct neigh_table *tbl,
327339
return __neigh_create(tbl, pkey, dev, true);
328340
}
329341
void neigh_destroy(struct neighbour *neigh);
330-
int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb);
342+
int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb,
343+
const bool immediate_ok);
331344
int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, u32 flags,
332345
u32 nlmsg_pid);
333346
void __neigh_set_probe_once(struct neighbour *neigh);
@@ -437,17 +450,24 @@ static inline struct neighbour * neigh_clone(struct neighbour *neigh)
437450

438451
#define neigh_hold(n) refcount_inc(&(n)->refcnt)
439452

440-
static inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
453+
static __always_inline int neigh_event_send_probe(struct neighbour *neigh,
454+
struct sk_buff *skb,
455+
const bool immediate_ok)
441456
{
442457
unsigned long now = jiffies;
443-
458+
444459
if (READ_ONCE(neigh->used) != now)
445460
WRITE_ONCE(neigh->used, now);
446-
if (!(neigh->nud_state&(NUD_CONNECTED|NUD_DELAY|NUD_PROBE)))
447-
return __neigh_event_send(neigh, skb);
461+
if (!(neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE)))
462+
return __neigh_event_send(neigh, skb, immediate_ok);
448463
return 0;
449464
}
450465

466+
static inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
467+
{
468+
return neigh_event_send_probe(neigh, skb, true);
469+
}
470+
451471
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
452472
static inline int neigh_hh_bridge(struct hh_cache *hh, struct sk_buff *skb)
453473
{

include/uapi/linux/neighbour.h

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ enum {
3131
NDA_PROTOCOL, /* Originator of entry */
3232
NDA_NH_ID,
3333
NDA_FDB_EXT_ATTRS,
34+
NDA_FLAGS_EXT,
3435
__NDA_MAX
3536
};
3637

@@ -40,14 +41,16 @@ enum {
4041
* Neighbor Cache Entry Flags
4142
*/
4243

43-
#define NTF_USE 0x01
44-
#define NTF_SELF 0x02
45-
#define NTF_MASTER 0x04
46-
#define NTF_PROXY 0x08 /* == ATF_PUBL */
47-
#define NTF_EXT_LEARNED 0x10
48-
#define NTF_OFFLOADED 0x20
49-
#define NTF_STICKY 0x40
50-
#define NTF_ROUTER 0x80
44+
#define NTF_USE (1 << 0)
45+
#define NTF_SELF (1 << 1)
46+
#define NTF_MASTER (1 << 2)
47+
#define NTF_PROXY (1 << 3) /* == ATF_PUBL */
48+
#define NTF_EXT_LEARNED (1 << 4)
49+
#define NTF_OFFLOADED (1 << 5)
50+
#define NTF_STICKY (1 << 6)
51+
#define NTF_ROUTER (1 << 7)
52+
/* Extended flags under NDA_FLAGS_EXT: */
53+
#define NTF_EXT_MANAGED (1 << 0)
5154

5255
/*
5356
* Neighbor Cache Entry States.
@@ -65,12 +68,22 @@ enum {
6568
#define NUD_PERMANENT 0x80
6669
#define NUD_NONE 0x00
6770

68-
/* NUD_NOARP & NUD_PERMANENT are pseudostates, they never change
69-
* and make no address resolution or NUD.
70-
* NUD_PERMANENT also cannot be deleted by garbage collectors.
71+
/* NUD_NOARP & NUD_PERMANENT are pseudostates, they never change and make no
72+
* address resolution or NUD.
73+
*
74+
* NUD_PERMANENT also cannot be deleted by garbage collectors. This holds true
75+
* for dynamic entries with NTF_EXT_LEARNED flag as well. However, upon carrier
76+
* down event, NUD_PERMANENT entries are not flushed whereas NTF_EXT_LEARNED
77+
* flagged entries explicitly are (which is also consistent with the routing
78+
* subsystem).
79+
*
7180
* When NTF_EXT_LEARNED is set for a bridge fdb entry the different cache entry
7281
* states don't make sense and thus are ignored. Such entries don't age and
7382
* can roam.
83+
*
84+
* NTF_EXT_MANAGED flagged neigbor entries are managed by the kernel on behalf
85+
* of a user space control plane, and automatically refreshed so that (if
86+
* possible) they remain in NUD_REACHABLE state.
7487
*/
7588

7689
struct nda_cacheinfo {

0 commit comments

Comments
 (0)