| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | 
|---|
| 2 | #ifndef _NET_NEIGHBOUR_H | 
|---|
| 3 | #define _NET_NEIGHBOUR_H | 
|---|
| 4 |  | 
|---|
| 5 | #include <linux/neighbour.h> | 
|---|
| 6 |  | 
|---|
| 7 | /* | 
|---|
| 8 | *	Generic neighbour manipulation | 
|---|
| 9 | * | 
|---|
| 10 | *	Authors: | 
|---|
| 11 | *	Pedro Roque		<roque@di.fc.ul.pt> | 
|---|
| 12 | *	Alexey Kuznetsov	<kuznet@ms2.inr.ac.ru> | 
|---|
| 13 | * | 
|---|
| 14 | * 	Changes: | 
|---|
| 15 | * | 
|---|
| 16 | *	Harald Welte:		<laforge@gnumonks.org> | 
|---|
| 17 | *		- Add neighbour cache statistics like rtstat | 
|---|
| 18 | */ | 
|---|
| 19 |  | 
|---|
| 20 | #include <linux/atomic.h> | 
|---|
| 21 | #include <linux/refcount.h> | 
|---|
| 22 | #include <linux/netdevice.h> | 
|---|
| 23 | #include <linux/skbuff.h> | 
|---|
| 24 | #include <linux/rcupdate.h> | 
|---|
| 25 | #include <linux/seq_file.h> | 
|---|
| 26 | #include <linux/bitmap.h> | 
|---|
| 27 |  | 
|---|
| 28 | #include <linux/err.h> | 
|---|
| 29 | #include <linux/sysctl.h> | 
|---|
| 30 | #include <linux/workqueue.h> | 
|---|
| 31 | #include <net/rtnetlink.h> | 
|---|
| 32 | #include <net/neighbour_tables.h> | 
|---|
| 33 |  | 
|---|
| 34 | /* | 
|---|
| 35 | * NUD stands for "neighbor unreachability detection" | 
|---|
| 36 | */ | 
|---|
| 37 |  | 
|---|
| 38 | #define NUD_IN_TIMER	(NUD_INCOMPLETE|NUD_REACHABLE|NUD_DELAY|NUD_PROBE) | 
|---|
| 39 | #define NUD_VALID	(NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE|NUD_PROBE|NUD_STALE|NUD_DELAY) | 
|---|
| 40 | #define NUD_CONNECTED	(NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE) | 
|---|
| 41 |  | 
|---|
| 42 | struct neighbour; | 
|---|
| 43 |  | 
|---|
| 44 | enum { | 
|---|
| 45 | NEIGH_VAR_MCAST_PROBES, | 
|---|
| 46 | NEIGH_VAR_UCAST_PROBES, | 
|---|
| 47 | NEIGH_VAR_APP_PROBES, | 
|---|
| 48 | NEIGH_VAR_MCAST_REPROBES, | 
|---|
| 49 | NEIGH_VAR_RETRANS_TIME, | 
|---|
| 50 | NEIGH_VAR_BASE_REACHABLE_TIME, | 
|---|
| 51 | NEIGH_VAR_DELAY_PROBE_TIME, | 
|---|
| 52 | NEIGH_VAR_INTERVAL_PROBE_TIME_MS, | 
|---|
| 53 | NEIGH_VAR_GC_STALETIME, | 
|---|
| 54 | NEIGH_VAR_QUEUE_LEN_BYTES, | 
|---|
| 55 | NEIGH_VAR_PROXY_QLEN, | 
|---|
| 56 | NEIGH_VAR_ANYCAST_DELAY, | 
|---|
| 57 | NEIGH_VAR_PROXY_DELAY, | 
|---|
| 58 | NEIGH_VAR_LOCKTIME, | 
|---|
| 59 | #define NEIGH_VAR_DATA_MAX (NEIGH_VAR_LOCKTIME + 1) | 
|---|
| 60 | /* Following are used as a second way to access one of the above */ | 
|---|
| 61 | NEIGH_VAR_QUEUE_LEN, /* same data as NEIGH_VAR_QUEUE_LEN_BYTES */ | 
|---|
| 62 | NEIGH_VAR_RETRANS_TIME_MS, /* same data as NEIGH_VAR_RETRANS_TIME */ | 
|---|
| 63 | NEIGH_VAR_BASE_REACHABLE_TIME_MS, /* same data as NEIGH_VAR_BASE_REACHABLE_TIME */ | 
|---|
| 64 | /* Following are used by "default" only */ | 
|---|
| 65 | NEIGH_VAR_GC_INTERVAL, | 
|---|
| 66 | NEIGH_VAR_GC_THRESH1, | 
|---|
| 67 | NEIGH_VAR_GC_THRESH2, | 
|---|
| 68 | NEIGH_VAR_GC_THRESH3, | 
|---|
| 69 | NEIGH_VAR_MAX | 
|---|
| 70 | }; | 
|---|
| 71 |  | 
|---|
| 72 | struct neigh_parms { | 
|---|
| 73 | possible_net_t net; | 
|---|
| 74 | struct net_device *dev; | 
|---|
| 75 | netdevice_tracker dev_tracker; | 
|---|
| 76 | struct list_head list; | 
|---|
| 77 | int	(*neigh_setup)(struct neighbour *); | 
|---|
| 78 | struct neigh_table *tbl; | 
|---|
| 79 |  | 
|---|
| 80 | void	*sysctl_table; | 
|---|
| 81 |  | 
|---|
| 82 | int dead; | 
|---|
| 83 | refcount_t refcnt; | 
|---|
| 84 | struct rcu_head rcu_head; | 
|---|
| 85 |  | 
|---|
| 86 | int	reachable_time; | 
|---|
| 87 | u32	qlen; | 
|---|
| 88 | int	data[NEIGH_VAR_DATA_MAX]; | 
|---|
| 89 | DECLARE_BITMAP(data_state, NEIGH_VAR_DATA_MAX); | 
|---|
| 90 | }; | 
|---|
| 91 |  | 
|---|
| 92 | static inline void neigh_var_set(struct neigh_parms *p, int index, int val) | 
|---|
| 93 | { | 
|---|
| 94 | set_bit(nr: index, addr: p->data_state); | 
|---|
| 95 | p->data[index] = val; | 
|---|
| 96 | } | 
|---|
| 97 |  | 
|---|
| 98 | #define NEIGH_VAR(p, attr) ((p)->data[NEIGH_VAR_ ## attr]) | 
|---|
| 99 |  | 
|---|
| 100 | /* In ndo_neigh_setup, NEIGH_VAR_INIT should be used. | 
|---|
| 101 | * In other cases, NEIGH_VAR_SET should be used. | 
|---|
| 102 | */ | 
|---|
| 103 | #define NEIGH_VAR_INIT(p, attr, val) (NEIGH_VAR(p, attr) = val) | 
|---|
| 104 | #define NEIGH_VAR_SET(p, attr, val) neigh_var_set(p, NEIGH_VAR_ ## attr, val) | 
|---|
| 105 |  | 
|---|
| 106 | static inline void neigh_parms_data_state_setall(struct neigh_parms *p) | 
|---|
| 107 | { | 
|---|
| 108 | bitmap_fill(dst: p->data_state, NEIGH_VAR_DATA_MAX); | 
|---|
| 109 | } | 
|---|
| 110 |  | 
|---|
| 111 | static inline void neigh_parms_data_state_cleanall(struct neigh_parms *p) | 
|---|
| 112 | { | 
|---|
| 113 | bitmap_zero(dst: p->data_state, NEIGH_VAR_DATA_MAX); | 
|---|
| 114 | } | 
|---|
| 115 |  | 
|---|
| 116 | struct neigh_statistics { | 
|---|
| 117 | unsigned long allocs;		/* number of allocated neighs */ | 
|---|
| 118 | unsigned long destroys;		/* number of destroyed neighs */ | 
|---|
| 119 | unsigned long hash_grows;	/* number of hash resizes */ | 
|---|
| 120 |  | 
|---|
| 121 | unsigned long res_failed;	/* number of failed resolutions */ | 
|---|
| 122 |  | 
|---|
| 123 | unsigned long lookups;		/* number of lookups */ | 
|---|
| 124 | unsigned long hits;		/* number of hits (among lookups) */ | 
|---|
| 125 |  | 
|---|
| 126 | unsigned long rcv_probes_mcast;	/* number of received mcast ipv6 */ | 
|---|
| 127 | unsigned long rcv_probes_ucast; /* number of received ucast ipv6 */ | 
|---|
| 128 |  | 
|---|
| 129 | unsigned long periodic_gc_runs;	/* number of periodic GC runs */ | 
|---|
| 130 | unsigned long forced_gc_runs;	/* number of forced GC runs */ | 
|---|
| 131 |  | 
|---|
| 132 | unsigned long unres_discards;	/* number of unresolved drops */ | 
|---|
| 133 | unsigned long table_fulls;      /* times even gc couldn't help */ | 
|---|
| 134 | }; | 
|---|
| 135 |  | 
|---|
| 136 | #define NEIGH_CACHE_STAT_INC(tbl, field) this_cpu_inc((tbl)->stats->field) | 
|---|
| 137 |  | 
|---|
| 138 | struct neighbour { | 
|---|
| 139 | struct hlist_node	hash; | 
|---|
| 140 | struct hlist_node	dev_list; | 
|---|
| 141 | struct neigh_table	*tbl; | 
|---|
| 142 | struct neigh_parms	*parms; | 
|---|
| 143 | unsigned long		confirmed; | 
|---|
| 144 | unsigned long		updated; | 
|---|
| 145 | rwlock_t		lock; | 
|---|
| 146 | refcount_t		refcnt; | 
|---|
| 147 | unsigned int		arp_queue_len_bytes; | 
|---|
| 148 | struct sk_buff_head	arp_queue; | 
|---|
| 149 | struct timer_list	timer; | 
|---|
| 150 | unsigned long		used; | 
|---|
| 151 | atomic_t		probes; | 
|---|
| 152 | u8			nud_state; | 
|---|
| 153 | u8			type; | 
|---|
| 154 | u8			dead; | 
|---|
| 155 | u8			protocol; | 
|---|
| 156 | u32			flags; | 
|---|
| 157 | seqlock_t		ha_lock; | 
|---|
| 158 | unsigned char		ha[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))] __aligned(8); | 
|---|
| 159 | struct hh_cache		hh; | 
|---|
| 160 | int			(*output)(struct neighbour *, struct sk_buff *); | 
|---|
| 161 | const struct neigh_ops	*ops; | 
|---|
| 162 | struct list_head	gc_list; | 
|---|
| 163 | struct list_head	managed_list; | 
|---|
| 164 | struct rcu_head		rcu; | 
|---|
| 165 | struct net_device	*dev; | 
|---|
| 166 | netdevice_tracker	dev_tracker; | 
|---|
| 167 | u8			primary_key[]; | 
|---|
| 168 | } __randomize_layout; | 
|---|
| 169 |  | 
|---|
| 170 | struct neigh_ops { | 
|---|
| 171 | int			family; | 
|---|
| 172 | void			(*solicit)(struct neighbour *, struct sk_buff *); | 
|---|
| 173 | void			(*error_report)(struct neighbour *, struct sk_buff *); | 
|---|
| 174 | int			(*output)(struct neighbour *, struct sk_buff *); | 
|---|
| 175 | int			(*connected_output)(struct neighbour *, struct sk_buff *); | 
|---|
| 176 | }; | 
|---|
| 177 |  | 
|---|
| 178 | struct pneigh_entry { | 
|---|
| 179 | struct pneigh_entry	__rcu *next; | 
|---|
| 180 | possible_net_t		net; | 
|---|
| 181 | struct net_device	*dev; | 
|---|
| 182 | netdevice_tracker	dev_tracker; | 
|---|
| 183 | union { | 
|---|
| 184 | struct list_head	free_node; | 
|---|
| 185 | struct rcu_head		rcu; | 
|---|
| 186 | }; | 
|---|
| 187 | u32			flags; | 
|---|
| 188 | u8			protocol; | 
|---|
| 189 | bool			permanent; | 
|---|
| 190 | u32			key[]; | 
|---|
| 191 | }; | 
|---|
| 192 |  | 
|---|
| 193 | /* | 
|---|
| 194 | *	neighbour table manipulation | 
|---|
| 195 | */ | 
|---|
| 196 |  | 
|---|
| 197 | #define NEIGH_NUM_HASH_RND	4 | 
|---|
| 198 |  | 
|---|
| 199 | struct neigh_hash_table { | 
|---|
| 200 | struct hlist_head	*hash_heads; | 
|---|
| 201 | unsigned int		hash_shift; | 
|---|
| 202 | __u32			hash_rnd[NEIGH_NUM_HASH_RND]; | 
|---|
| 203 | struct rcu_head		rcu; | 
|---|
| 204 | }; | 
|---|
| 205 |  | 
|---|
| 206 |  | 
|---|
| 207 | struct neigh_table { | 
|---|
| 208 | int			family; | 
|---|
| 209 | unsigned int		entry_size; | 
|---|
| 210 | unsigned int		key_len; | 
|---|
| 211 | __be16			protocol; | 
|---|
| 212 | __u32			(*hash)(const void *pkey, | 
|---|
| 213 | const struct net_device *dev, | 
|---|
| 214 | __u32 *hash_rnd); | 
|---|
| 215 | bool			(*key_eq)(const struct neighbour *, const void *pkey); | 
|---|
| 216 | int			(*constructor)(struct neighbour *); | 
|---|
| 217 | int			(*pconstructor)(struct pneigh_entry *); | 
|---|
| 218 | void			(*pdestructor)(struct pneigh_entry *); | 
|---|
| 219 | void			(*proxy_redo)(struct sk_buff *skb); | 
|---|
| 220 | int			(*is_multicast)(const void *pkey); | 
|---|
| 221 | bool			(*allow_add)(const struct net_device *dev, | 
|---|
| 222 | struct netlink_ext_ack *extack); | 
|---|
| 223 | char			*id; | 
|---|
| 224 | struct neigh_parms	parms; | 
|---|
| 225 | struct list_head	parms_list; | 
|---|
| 226 | int			gc_interval; | 
|---|
| 227 | int			gc_thresh1; | 
|---|
| 228 | int			gc_thresh2; | 
|---|
| 229 | int			gc_thresh3; | 
|---|
| 230 | unsigned long		last_flush; | 
|---|
| 231 | struct delayed_work	gc_work; | 
|---|
| 232 | struct delayed_work	managed_work; | 
|---|
| 233 | struct timer_list 	proxy_timer; | 
|---|
| 234 | struct sk_buff_head	proxy_queue; | 
|---|
| 235 | atomic_t		entries; | 
|---|
| 236 | atomic_t		gc_entries; | 
|---|
| 237 | struct list_head	gc_list; | 
|---|
| 238 | struct list_head	managed_list; | 
|---|
| 239 | rwlock_t		lock; | 
|---|
| 240 | unsigned long		last_rand; | 
|---|
| 241 | struct neigh_statistics	__percpu *stats; | 
|---|
| 242 | struct neigh_hash_table __rcu *nht; | 
|---|
| 243 | struct mutex		phash_lock; | 
|---|
| 244 | struct pneigh_entry	__rcu **phash_buckets; | 
|---|
| 245 | }; | 
|---|
| 246 |  | 
|---|
| 247 | static inline int neigh_parms_family(struct neigh_parms *p) | 
|---|
| 248 | { | 
|---|
| 249 | return p->tbl->family; | 
|---|
| 250 | } | 
|---|
| 251 |  | 
|---|
| 252 | #define NEIGH_PRIV_ALIGN	sizeof(long long) | 
|---|
| 253 | #define NEIGH_ENTRY_SIZE(size)	ALIGN((size), NEIGH_PRIV_ALIGN) | 
|---|
| 254 |  | 
|---|
| 255 | static inline void *neighbour_priv(const struct neighbour *n) | 
|---|
| 256 | { | 
|---|
| 257 | return (char *)n + n->tbl->entry_size; | 
|---|
| 258 | } | 
|---|
| 259 |  | 
|---|
| 260 | /* flags for neigh_update() */ | 
|---|
| 261 | #define NEIGH_UPDATE_F_OVERRIDE			BIT(0) | 
|---|
| 262 | #define NEIGH_UPDATE_F_WEAK_OVERRIDE		BIT(1) | 
|---|
| 263 | #define NEIGH_UPDATE_F_OVERRIDE_ISROUTER	BIT(2) | 
|---|
| 264 | #define NEIGH_UPDATE_F_USE			BIT(3) | 
|---|
| 265 | #define NEIGH_UPDATE_F_MANAGED			BIT(4) | 
|---|
| 266 | #define NEIGH_UPDATE_F_EXT_LEARNED		BIT(5) | 
|---|
| 267 | #define NEIGH_UPDATE_F_ISROUTER			BIT(6) | 
|---|
| 268 | #define NEIGH_UPDATE_F_ADMIN			BIT(7) | 
|---|
| 269 | #define NEIGH_UPDATE_F_EXT_VALIDATED		BIT(8) | 
|---|
| 270 |  | 
|---|
| 271 | /* In-kernel representation for NDA_FLAGS_EXT flags: */ | 
|---|
| 272 | #define NTF_OLD_MASK		0xff | 
|---|
| 273 | #define NTF_EXT_SHIFT		8 | 
|---|
| 274 | #define NTF_EXT_MASK		(NTF_EXT_MANAGED | NTF_EXT_EXT_VALIDATED) | 
|---|
| 275 |  | 
|---|
| 276 | #define NTF_MANAGED		(NTF_EXT_MANAGED << NTF_EXT_SHIFT) | 
|---|
| 277 | #define NTF_EXT_VALIDATED	(NTF_EXT_EXT_VALIDATED << NTF_EXT_SHIFT) | 
|---|
| 278 |  | 
|---|
| 279 | extern const struct nla_policy nda_policy[]; | 
|---|
| 280 |  | 
|---|
| 281 | #define neigh_for_each_in_bucket(pos, head) hlist_for_each_entry(pos, head, hash) | 
|---|
| 282 | #define neigh_for_each_in_bucket_rcu(pos, head) \ | 
|---|
| 283 | hlist_for_each_entry_rcu(pos, head, hash) | 
|---|
| 284 | #define neigh_for_each_in_bucket_safe(pos, tmp, head) \ | 
|---|
| 285 | hlist_for_each_entry_safe(pos, tmp, head, hash) | 
|---|
| 286 |  | 
|---|
| 287 | static inline bool neigh_key_eq32(const struct neighbour *n, const void *pkey) | 
|---|
| 288 | { | 
|---|
| 289 | return *(const u32 *)n->primary_key == *(const u32 *)pkey; | 
|---|
| 290 | } | 
|---|
| 291 |  | 
|---|
| 292 | static inline bool neigh_key_eq128(const struct neighbour *n, const void *pkey) | 
|---|
| 293 | { | 
|---|
| 294 | const u32 *n32 = (const u32 *)n->primary_key; | 
|---|
| 295 | const u32 *p32 = pkey; | 
|---|
| 296 |  | 
|---|
| 297 | return ((n32[0] ^ p32[0]) | (n32[1] ^ p32[1]) | | 
|---|
| 298 | (n32[2] ^ p32[2]) | (n32[3] ^ p32[3])) == 0; | 
|---|
| 299 | } | 
|---|
| 300 |  | 
|---|
| 301 | static inline struct neighbour *___neigh_lookup_noref( | 
|---|
| 302 | struct neigh_table *tbl, | 
|---|
| 303 | bool (*key_eq)(const struct neighbour *n, const void *pkey), | 
|---|
| 304 | __u32 (*hash)(const void *pkey, | 
|---|
| 305 | const struct net_device *dev, | 
|---|
| 306 | __u32 *hash_rnd), | 
|---|
| 307 | const void *pkey, | 
|---|
| 308 | struct net_device *dev) | 
|---|
| 309 | { | 
|---|
| 310 | struct neigh_hash_table *nht = rcu_dereference(tbl->nht); | 
|---|
| 311 | struct neighbour *n; | 
|---|
| 312 | u32 hash_val; | 
|---|
| 313 |  | 
|---|
| 314 | hash_val = hash(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift); | 
|---|
| 315 | neigh_for_each_in_bucket_rcu(n, &nht->hash_heads[hash_val]) | 
|---|
| 316 | if (n->dev == dev && key_eq(n, pkey)) | 
|---|
| 317 | return n; | 
|---|
| 318 |  | 
|---|
| 319 | return NULL; | 
|---|
| 320 | } | 
|---|
| 321 |  | 
|---|
| 322 | static inline struct neighbour *__neigh_lookup_noref(struct neigh_table *tbl, | 
|---|
| 323 | const void *pkey, | 
|---|
| 324 | struct net_device *dev) | 
|---|
| 325 | { | 
|---|
| 326 | return ___neigh_lookup_noref(tbl, key_eq: tbl->key_eq, hash: tbl->hash, pkey, dev); | 
|---|
| 327 | } | 
|---|
| 328 |  | 
|---|
| 329 | static inline void neigh_confirm(struct neighbour *n) | 
|---|
| 330 | { | 
|---|
| 331 | if (n) { | 
|---|
| 332 | unsigned long now = jiffies; | 
|---|
| 333 |  | 
|---|
| 334 | /* avoid dirtying neighbour */ | 
|---|
| 335 | if (READ_ONCE(n->confirmed) != now) | 
|---|
| 336 | WRITE_ONCE(n->confirmed, now); | 
|---|
| 337 | } | 
|---|
| 338 | } | 
|---|
| 339 |  | 
|---|
| 340 | void neigh_table_init(int index, struct neigh_table *tbl); | 
|---|
| 341 | int neigh_table_clear(int index, struct neigh_table *tbl); | 
|---|
| 342 | struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey, | 
|---|
| 343 | struct net_device *dev); | 
|---|
| 344 | struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey, | 
|---|
| 345 | struct net_device *dev, bool want_ref); | 
|---|
| 346 | static inline struct neighbour *neigh_create(struct neigh_table *tbl, | 
|---|
| 347 | const void *pkey, | 
|---|
| 348 | struct net_device *dev) | 
|---|
| 349 | { | 
|---|
| 350 | return __neigh_create(tbl, pkey, dev, want_ref: true); | 
|---|
| 351 | } | 
|---|
| 352 | void neigh_destroy(struct neighbour *neigh); | 
|---|
| 353 | int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb, | 
|---|
| 354 | const bool immediate_ok); | 
|---|
| 355 | int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, u32 flags, | 
|---|
| 356 | u32 nlmsg_pid); | 
|---|
| 357 | void __neigh_set_probe_once(struct neighbour *neigh); | 
|---|
| 358 | bool neigh_remove_one(struct neighbour *ndel); | 
|---|
| 359 | void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev); | 
|---|
| 360 | int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev); | 
|---|
| 361 | int neigh_carrier_down(struct neigh_table *tbl, struct net_device *dev); | 
|---|
| 362 | int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb); | 
|---|
| 363 | int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb); | 
|---|
| 364 | int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb); | 
|---|
| 365 | struct neighbour *neigh_event_ns(struct neigh_table *tbl, | 
|---|
| 366 | u8 *lladdr, void *saddr, | 
|---|
| 367 | struct net_device *dev); | 
|---|
| 368 |  | 
|---|
| 369 | struct neigh_parms *neigh_parms_alloc(struct net_device *dev, | 
|---|
| 370 | struct neigh_table *tbl); | 
|---|
| 371 | void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms); | 
|---|
| 372 |  | 
|---|
| 373 | static inline | 
|---|
| 374 | struct net *neigh_parms_net(const struct neigh_parms *parms) | 
|---|
| 375 | { | 
|---|
| 376 | return read_pnet(pnet: &parms->net); | 
|---|
| 377 | } | 
|---|
| 378 |  | 
|---|
| 379 | unsigned long neigh_rand_reach_time(unsigned long base); | 
|---|
| 380 |  | 
|---|
| 381 | void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p, | 
|---|
| 382 | struct sk_buff *skb); | 
|---|
| 383 | struct pneigh_entry *pneigh_lookup(struct neigh_table *tbl, struct net *net, | 
|---|
| 384 | const void *key, struct net_device *dev); | 
|---|
| 385 | int pneigh_create(struct neigh_table *tbl, struct net *net, const void *key, | 
|---|
| 386 | struct net_device *dev, u32 flags, u8 protocol, | 
|---|
| 387 | bool permanent); | 
|---|
| 388 | int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *key, | 
|---|
| 389 | struct net_device *dev); | 
|---|
| 390 |  | 
|---|
| 391 | static inline struct net *pneigh_net(const struct pneigh_entry *pneigh) | 
|---|
| 392 | { | 
|---|
| 393 | return read_pnet(pnet: &pneigh->net); | 
|---|
| 394 | } | 
|---|
| 395 |  | 
|---|
| 396 | void neigh_app_ns(struct neighbour *n); | 
|---|
| 397 | void neigh_for_each(struct neigh_table *tbl, | 
|---|
| 398 | void (*cb)(struct neighbour *, void *), void *cookie); | 
|---|
| 399 | void __neigh_for_each_release(struct neigh_table *tbl, | 
|---|
| 400 | int (*cb)(struct neighbour *)); | 
|---|
| 401 | int neigh_xmit(int fam, struct net_device *, const void *, struct sk_buff *); | 
|---|
| 402 |  | 
|---|
| 403 | struct neigh_seq_state { | 
|---|
| 404 | struct seq_net_private p; | 
|---|
| 405 | struct neigh_table *tbl; | 
|---|
| 406 | struct neigh_hash_table *nht; | 
|---|
| 407 | void *(*neigh_sub_iter)(struct neigh_seq_state *state, | 
|---|
| 408 | struct neighbour *n, loff_t *pos); | 
|---|
| 409 | unsigned int bucket; | 
|---|
| 410 | unsigned int flags; | 
|---|
| 411 | #define NEIGH_SEQ_NEIGH_ONLY	0x00000001 | 
|---|
| 412 | #define NEIGH_SEQ_IS_PNEIGH	0x00000002 | 
|---|
| 413 | #define NEIGH_SEQ_SKIP_NOARP	0x00000004 | 
|---|
| 414 | }; | 
|---|
| 415 | void *neigh_seq_start(struct seq_file *, loff_t *, struct neigh_table *, | 
|---|
| 416 | unsigned int); | 
|---|
| 417 | void *neigh_seq_next(struct seq_file *, void *, loff_t *); | 
|---|
| 418 | void neigh_seq_stop(struct seq_file *, void *); | 
|---|
| 419 |  | 
|---|
| 420 | int neigh_proc_dointvec(const struct ctl_table *ctl, int write, | 
|---|
| 421 | void *buffer, size_t *lenp, loff_t *ppos); | 
|---|
| 422 | int neigh_proc_dointvec_jiffies(const struct ctl_table *ctl, int write, | 
|---|
| 423 | void *buffer, | 
|---|
| 424 | size_t *lenp, loff_t *ppos); | 
|---|
| 425 | int neigh_proc_dointvec_ms_jiffies(const struct ctl_table *ctl, int write, | 
|---|
| 426 | void *buffer, size_t *lenp, loff_t *ppos); | 
|---|
| 427 |  | 
|---|
| 428 | int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p, | 
|---|
| 429 | proc_handler *proc_handler); | 
|---|
| 430 | void neigh_sysctl_unregister(struct neigh_parms *p); | 
|---|
| 431 |  | 
|---|
| 432 | static inline void __neigh_parms_put(struct neigh_parms *parms) | 
|---|
| 433 | { | 
|---|
| 434 | refcount_dec(r: &parms->refcnt); | 
|---|
| 435 | } | 
|---|
| 436 |  | 
|---|
| 437 | static inline struct neigh_parms *neigh_parms_clone(struct neigh_parms *parms) | 
|---|
| 438 | { | 
|---|
| 439 | refcount_inc(r: &parms->refcnt); | 
|---|
| 440 | return parms; | 
|---|
| 441 | } | 
|---|
| 442 |  | 
|---|
| 443 | /* | 
|---|
| 444 | *	Neighbour references | 
|---|
| 445 | */ | 
|---|
| 446 |  | 
|---|
| 447 | static inline void neigh_release(struct neighbour *neigh) | 
|---|
| 448 | { | 
|---|
| 449 | if (refcount_dec_and_test(r: &neigh->refcnt)) | 
|---|
| 450 | neigh_destroy(neigh); | 
|---|
| 451 | } | 
|---|
| 452 |  | 
|---|
| 453 | static inline struct neighbour * neigh_clone(struct neighbour *neigh) | 
|---|
| 454 | { | 
|---|
| 455 | if (neigh) | 
|---|
| 456 | refcount_inc(r: &neigh->refcnt); | 
|---|
| 457 | return neigh; | 
|---|
| 458 | } | 
|---|
| 459 |  | 
|---|
| 460 | #define neigh_hold(n)	refcount_inc(&(n)->refcnt) | 
|---|
| 461 |  | 
|---|
| 462 | static __always_inline int neigh_event_send_probe(struct neighbour *neigh, | 
|---|
| 463 | struct sk_buff *skb, | 
|---|
| 464 | const bool immediate_ok) | 
|---|
| 465 | { | 
|---|
| 466 | unsigned long now = jiffies; | 
|---|
| 467 |  | 
|---|
| 468 | if (READ_ONCE(neigh->used) != now) | 
|---|
| 469 | WRITE_ONCE(neigh->used, now); | 
|---|
| 470 | if (!(READ_ONCE(neigh->nud_state) & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))) | 
|---|
| 471 | return __neigh_event_send(neigh, skb, immediate_ok); | 
|---|
| 472 | return 0; | 
|---|
| 473 | } | 
|---|
| 474 |  | 
|---|
| 475 | static inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb) | 
|---|
| 476 | { | 
|---|
| 477 | return neigh_event_send_probe(neigh, skb, immediate_ok: true); | 
|---|
| 478 | } | 
|---|
| 479 |  | 
|---|
| 480 | #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) | 
|---|
| 481 | static inline int neigh_hh_bridge(struct hh_cache *hh, struct sk_buff *skb) | 
|---|
| 482 | { | 
|---|
| 483 | unsigned int seq, hh_alen; | 
|---|
| 484 |  | 
|---|
| 485 | do { | 
|---|
| 486 | seq = read_seqbegin(&hh->hh_lock); | 
|---|
| 487 | hh_alen = HH_DATA_ALIGN(ETH_HLEN); | 
|---|
| 488 | memcpy(skb->data - hh_alen, hh->hh_data, ETH_ALEN + hh_alen - ETH_HLEN); | 
|---|
| 489 | } while (read_seqretry(&hh->hh_lock, seq)); | 
|---|
| 490 | return 0; | 
|---|
| 491 | } | 
|---|
| 492 | #endif | 
|---|
| 493 |  | 
|---|
| 494 | static inline int neigh_hh_output(const struct hh_cache *hh, struct sk_buff *skb) | 
|---|
| 495 | { | 
|---|
| 496 | unsigned int hh_alen = 0; | 
|---|
| 497 | unsigned int seq; | 
|---|
| 498 | unsigned int hh_len; | 
|---|
| 499 |  | 
|---|
| 500 | do { | 
|---|
| 501 | seq = read_seqbegin(sl: &hh->hh_lock); | 
|---|
| 502 | hh_len = READ_ONCE(hh->hh_len); | 
|---|
| 503 | if (likely(hh_len <= HH_DATA_MOD)) { | 
|---|
| 504 | hh_alen = HH_DATA_MOD; | 
|---|
| 505 |  | 
|---|
| 506 | /* skb_push() would proceed silently if we have room for | 
|---|
| 507 | * the unaligned size but not for the aligned size: | 
|---|
| 508 | * check headroom explicitly. | 
|---|
| 509 | */ | 
|---|
| 510 | if (likely(skb_headroom(skb) >= HH_DATA_MOD)) { | 
|---|
| 511 | /* this is inlined by gcc */ | 
|---|
| 512 | memcpy(to: skb->data - HH_DATA_MOD, from: hh->hh_data, | 
|---|
| 513 | HH_DATA_MOD); | 
|---|
| 514 | } | 
|---|
| 515 | } else { | 
|---|
| 516 | hh_alen = HH_DATA_ALIGN(hh_len); | 
|---|
| 517 |  | 
|---|
| 518 | if (likely(skb_headroom(skb) >= hh_alen)) { | 
|---|
| 519 | memcpy(to: skb->data - hh_alen, from: hh->hh_data, | 
|---|
| 520 | len: hh_alen); | 
|---|
| 521 | } | 
|---|
| 522 | } | 
|---|
| 523 | } while (read_seqretry(sl: &hh->hh_lock, start: seq)); | 
|---|
| 524 |  | 
|---|
| 525 | if (WARN_ON_ONCE(skb_headroom(skb) < hh_alen)) { | 
|---|
| 526 | kfree_skb(skb); | 
|---|
| 527 | return NET_XMIT_DROP; | 
|---|
| 528 | } | 
|---|
| 529 |  | 
|---|
| 530 | __skb_push(skb, len: hh_len); | 
|---|
| 531 | return dev_queue_xmit(skb); | 
|---|
| 532 | } | 
|---|
| 533 |  | 
|---|
| 534 | static inline int neigh_output(struct neighbour *n, struct sk_buff *skb, | 
|---|
| 535 | bool skip_cache) | 
|---|
| 536 | { | 
|---|
| 537 | const struct hh_cache *hh = &n->hh; | 
|---|
| 538 |  | 
|---|
| 539 | /* n->nud_state and hh->hh_len could be changed under us. | 
|---|
| 540 | * neigh_hh_output() is taking care of the race later. | 
|---|
| 541 | */ | 
|---|
| 542 | if (!skip_cache && | 
|---|
| 543 | (READ_ONCE(n->nud_state) & NUD_CONNECTED) && | 
|---|
| 544 | READ_ONCE(hh->hh_len)) | 
|---|
| 545 | return neigh_hh_output(hh, skb); | 
|---|
| 546 |  | 
|---|
| 547 | return READ_ONCE(n->output)(n, skb); | 
|---|
| 548 | } | 
|---|
| 549 |  | 
|---|
| 550 | static inline struct neighbour * | 
|---|
| 551 | __neigh_lookup(struct neigh_table *tbl, const void *pkey, struct net_device *dev, int creat) | 
|---|
| 552 | { | 
|---|
| 553 | struct neighbour *n = neigh_lookup(tbl, pkey, dev); | 
|---|
| 554 |  | 
|---|
| 555 | if (n || !creat) | 
|---|
| 556 | return n; | 
|---|
| 557 |  | 
|---|
| 558 | n = neigh_create(tbl, pkey, dev); | 
|---|
| 559 | return IS_ERR(ptr: n) ? NULL : n; | 
|---|
| 560 | } | 
|---|
| 561 |  | 
|---|
| 562 | static inline struct neighbour * | 
|---|
| 563 | __neigh_lookup_errno(struct neigh_table *tbl, const void *pkey, | 
|---|
| 564 | struct net_device *dev) | 
|---|
| 565 | { | 
|---|
| 566 | struct neighbour *n = neigh_lookup(tbl, pkey, dev); | 
|---|
| 567 |  | 
|---|
| 568 | if (n) | 
|---|
| 569 | return n; | 
|---|
| 570 |  | 
|---|
| 571 | return neigh_create(tbl, pkey, dev); | 
|---|
| 572 | } | 
|---|
| 573 |  | 
|---|
| 574 | struct neighbour_cb { | 
|---|
| 575 | unsigned long sched_next; | 
|---|
| 576 | unsigned int flags; | 
|---|
| 577 | }; | 
|---|
| 578 |  | 
|---|
| 579 | #define LOCALLY_ENQUEUED 0x1 | 
|---|
| 580 |  | 
|---|
| 581 | #define NEIGH_CB(skb)	((struct neighbour_cb *)(skb)->cb) | 
|---|
| 582 |  | 
|---|
| 583 | static inline void neigh_ha_snapshot(char *dst, const struct neighbour *n, | 
|---|
| 584 | const struct net_device *dev) | 
|---|
| 585 | { | 
|---|
| 586 | unsigned int seq; | 
|---|
| 587 |  | 
|---|
| 588 | do { | 
|---|
| 589 | seq = read_seqbegin(sl: &n->ha_lock); | 
|---|
| 590 | memcpy(to: dst, from: n->ha, len: dev->addr_len); | 
|---|
| 591 | } while (read_seqretry(sl: &n->ha_lock, start: seq)); | 
|---|
| 592 | } | 
|---|
| 593 |  | 
|---|
| 594 | static inline void neigh_update_is_router(struct neighbour *neigh, u32 flags, | 
|---|
| 595 | int *notify) | 
|---|
| 596 | { | 
|---|
| 597 | u8 ndm_flags = 0; | 
|---|
| 598 |  | 
|---|
| 599 | ndm_flags |= (flags & NEIGH_UPDATE_F_ISROUTER) ? NTF_ROUTER : 0; | 
|---|
| 600 | if ((neigh->flags ^ ndm_flags) & NTF_ROUTER) { | 
|---|
| 601 | if (ndm_flags & NTF_ROUTER) | 
|---|
| 602 | neigh->flags |= NTF_ROUTER; | 
|---|
| 603 | else | 
|---|
| 604 | neigh->flags &= ~NTF_ROUTER; | 
|---|
| 605 | *notify = 1; | 
|---|
| 606 | } | 
|---|
| 607 | } | 
|---|
| 608 | #endif | 
|---|
| 609 |  | 
|---|