Blame view
include/net/neighbour.h
10.7 KB
1da177e4c
|
1 2 |
#ifndef _NET_NEIGHBOUR_H #define _NET_NEIGHBOUR_H |
9067c722c
|
3 |
#include <linux/neighbour.h> |
1da177e4c
|
4 5 6 7 8 9 10 11 12 13 14 15 |
/* * Generic neighbour manipulation * * Authors: * Pedro Roque <roque@di.fc.ul.pt> * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> * * Changes: * * Harald Welte: <laforge@gnumonks.org> * - Add neighbour cache statistics like rtstat */ |
60063497a
|
16 |
#include <linux/atomic.h> |
1da177e4c
|
17 |
#include <linux/netdevice.h> |
14c850212
|
18 |
#include <linux/skbuff.h> |
1da177e4c
|
19 20 21 22 23 |
#include <linux/rcupdate.h> #include <linux/seq_file.h> #include <linux/err.h> #include <linux/sysctl.h> |
e4c4e448c
|
24 |
#include <linux/workqueue.h> |
c8822a4e0
|
25 |
#include <net/rtnetlink.h> |
1da177e4c
|
26 |
|
39971554d
|
27 28 29 |
/* * NUD stands for "neighbor unreachability detection" */ |
1da177e4c
|
30 31 32 33 34 |
#define NUD_IN_TIMER (NUD_INCOMPLETE|NUD_REACHABLE|NUD_DELAY|NUD_PROBE) #define NUD_VALID (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE|NUD_PROBE|NUD_STALE|NUD_DELAY) #define NUD_CONNECTED (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE) struct neighbour; |
fd2c3ef76
|
35 |
struct neigh_parms { |
57da52c1e
|
36 |
#ifdef CONFIG_NET_NS |
426b5303e
|
37 |
struct net *net; |
57da52c1e
|
38 |
#endif |
c7fb64db0
|
39 |
struct net_device *dev; |
1da177e4c
|
40 41 |
struct neigh_parms *next; int (*neigh_setup)(struct neighbour *); |
ecbb41693
|
42 |
void (*neigh_cleanup)(struct neighbour *); |
1da177e4c
|
43 |
struct neigh_table *tbl; |
1da177e4c
|
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
void *sysctl_table; int dead; atomic_t refcnt; struct rcu_head rcu_head; int base_reachable_time; int retrans_time; int gc_staletime; int reachable_time; int delay_probe_time; int queue_len; int ucast_probes; int app_probes; int mcast_probes; int anycast_delay; int proxy_delay; int proxy_qlen; int locktime; }; |
fd2c3ef76
|
66 |
struct neigh_statistics { |
1da177e4c
|
67 68 69 |
unsigned long allocs; /* number of allocated neighs */ unsigned long destroys; /* number of destroyed neighs */ unsigned long hash_grows; /* number of hash resizes */ |
9a6d276e8
|
70 |
unsigned long res_failed; /* number of failed resolutions */ |
1da177e4c
|
71 72 73 74 75 76 77 78 79 |
unsigned long lookups; /* number of lookups */ unsigned long hits; /* number of hits (among lookups) */ unsigned long rcv_probes_mcast; /* number of received mcast ipv6 */ unsigned long rcv_probes_ucast; /* number of received ucast ipv6 */ unsigned long periodic_gc_runs; /* number of periodic GC runs */ unsigned long forced_gc_runs; /* number of forced GC runs */ |
9a6d276e8
|
80 81 |
unsigned long unres_discards; /* number of unresolved drops */ |
1da177e4c
|
82 |
}; |
4ea7334b6
|
83 |
#define NEIGH_CACHE_STAT_INC(tbl, field) this_cpu_inc((tbl)->stats->field) |
1da177e4c
|
84 |
|
fd2c3ef76
|
85 |
struct neighbour { |
767e97e1e
|
86 |
struct neighbour __rcu *next; |
1da177e4c
|
87 88 |
struct neigh_table *tbl; struct neigh_parms *parms; |
1da177e4c
|
89 90 |
unsigned long confirmed; unsigned long updated; |
46b13fc5c
|
91 |
rwlock_t lock; |
367e5e376
|
92 |
atomic_t refcnt; |
e37ef961e
|
93 94 95 |
struct sk_buff_head arp_queue; struct timer_list timer; unsigned long used; |
1da177e4c
|
96 |
atomic_t probes; |
46b13fc5c
|
97 98 99 100 |
__u8 flags; __u8 nud_state; __u8 type; __u8 dead; |
0ed8ddf40
|
101 |
seqlock_t ha_lock; |
d924424aa
|
102 |
unsigned char ha[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))]; |
f6b72b621
|
103 |
struct hh_cache hh; |
8f40b161d
|
104 |
int (*output)(struct neighbour *, struct sk_buff *); |
89d69d2b7
|
105 |
const struct neigh_ops *ops; |
767e97e1e
|
106 |
struct rcu_head rcu; |
e37ef961e
|
107 |
struct net_device *dev; |
1da177e4c
|
108 109 |
u8 primary_key[0]; }; |
fd2c3ef76
|
110 |
struct neigh_ops { |
1da177e4c
|
111 |
int family; |
8f40b161d
|
112 113 114 115 |
void (*solicit)(struct neighbour *, struct sk_buff *); void (*error_report)(struct neighbour *, struct sk_buff *); int (*output)(struct neighbour *, struct sk_buff *); int (*connected_output)(struct neighbour *, struct sk_buff *); |
1da177e4c
|
116 |
}; |
fd2c3ef76
|
117 |
struct pneigh_entry { |
1da177e4c
|
118 |
struct pneigh_entry *next; |
57da52c1e
|
119 |
#ifdef CONFIG_NET_NS |
426b5303e
|
120 |
struct net *net; |
57da52c1e
|
121 |
#endif |
426b5303e
|
122 |
struct net_device *dev; |
62dd93181
|
123 |
u8 flags; |
1da177e4c
|
124 125 126 127 128 129 |
u8 key[0]; }; /* * neighbour table manipulation */ |
d6bf78171
|
130 |
struct neigh_hash_table { |
767e97e1e
|
131 |
struct neighbour __rcu **hash_buckets; |
cd0893369
|
132 |
unsigned int hash_shift; |
d6bf78171
|
133 134 135 |
__u32 hash_rnd; struct rcu_head rcu; }; |
1da177e4c
|
136 |
|
fd2c3ef76
|
137 |
struct neigh_table { |
1da177e4c
|
138 139 140 141 |
struct neigh_table *next; int family; int entry_size; int key_len; |
d6bf78171
|
142 143 144 |
__u32 (*hash)(const void *pkey, const struct net_device *dev, __u32 hash_rnd); |
1da177e4c
|
145 146 147 148 149 150 |
int (*constructor)(struct neighbour *); int (*pconstructor)(struct pneigh_entry *); void (*pdestructor)(struct pneigh_entry *); void (*proxy_redo)(struct sk_buff *skb); char *id; struct neigh_parms parms; |
787a34456
|
151 |
/* HACK. gc_* should follow parms without a gap! */ |
1da177e4c
|
152 153 154 155 156 |
int gc_interval; int gc_thresh1; int gc_thresh2; int gc_thresh3; unsigned long last_flush; |
e4c4e448c
|
157 |
struct delayed_work gc_work; |
1da177e4c
|
158 159 160 161 162 |
struct timer_list proxy_timer; struct sk_buff_head proxy_queue; atomic_t entries; rwlock_t lock; unsigned long last_rand; |
367e5e376
|
163 |
struct kmem_cache *kmem_cachep; |
7d720c3e4
|
164 |
struct neigh_statistics __percpu *stats; |
d6bf78171
|
165 |
struct neigh_hash_table __rcu *nht; |
1da177e4c
|
166 |
struct pneigh_entry **phash_buckets; |
1da177e4c
|
167 168 169 170 171 172 173 174 175 176 |
}; /* flags for neigh_update() */ #define NEIGH_UPDATE_F_OVERRIDE 0x00000001 #define NEIGH_UPDATE_F_WEAK_OVERRIDE 0x00000002 #define NEIGH_UPDATE_F_OVERRIDE_ISROUTER 0x00000004 #define NEIGH_UPDATE_F_ISROUTER 0x40000000 #define NEIGH_UPDATE_F_ADMIN 0x80000000 extern void neigh_table_init(struct neigh_table *tbl); |
bd89efc53
|
177 |
extern void neigh_table_init_no_netlink(struct neigh_table *tbl); |
1da177e4c
|
178 179 180 181 182 |
extern int neigh_table_clear(struct neigh_table *tbl); extern struct neighbour * neigh_lookup(struct neigh_table *tbl, const void *pkey, struct net_device *dev); extern struct neighbour * neigh_lookup_nodev(struct neigh_table *tbl, |
426b5303e
|
183 |
struct net *net, |
1da177e4c
|
184 185 186 187 188 189 190 191 192 193 |
const void *pkey); extern struct neighbour * neigh_create(struct neigh_table *tbl, const void *pkey, struct net_device *dev); extern void neigh_destroy(struct neighbour *neigh); extern int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb); extern int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, u32 flags); extern void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev); extern int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev); |
8f40b161d
|
194 195 196 197 |
extern int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb); extern int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb); extern int neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb); extern int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb); |
1da177e4c
|
198 199 200 201 202 203 |
extern struct neighbour *neigh_event_ns(struct neigh_table *tbl, u8 *lladdr, void *saddr, struct net_device *dev); extern struct neigh_parms *neigh_parms_alloc(struct net_device *dev, struct neigh_table *tbl); extern void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms); |
57da52c1e
|
204 205 206 207 |
static inline struct net *neigh_parms_net(const struct neigh_parms *parms) { |
e42ea986e
|
208 |
return read_pnet(&parms->net); |
57da52c1e
|
209 |
} |
1da177e4c
|
210 211 212 213 |
extern unsigned long neigh_rand_reach_time(unsigned long base); extern void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p, struct sk_buff *skb); |
426b5303e
|
214 |
extern struct pneigh_entry *pneigh_lookup(struct neigh_table *tbl, struct net *net, const void *key, struct net_device *dev, int creat); |
fa86d322d
|
215 216 217 218 |
extern struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl, struct net *net, const void *key, struct net_device *dev); |
426b5303e
|
219 |
extern int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *key, struct net_device *dev); |
1da177e4c
|
220 |
|
57da52c1e
|
221 222 223 |
static inline struct net *pneigh_net(const struct pneigh_entry *pneigh) { |
e42ea986e
|
224 |
return read_pnet(&pneigh->net); |
57da52c1e
|
225 |
} |
1da177e4c
|
226 |
extern void neigh_app_ns(struct neighbour *n); |
1da177e4c
|
227 228 229 230 231 |
extern void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie); extern void __neigh_for_each_release(struct neigh_table *tbl, int (*cb)(struct neighbour *)); extern void pneigh_for_each(struct neigh_table *tbl, void (*cb)(struct pneigh_entry *)); struct neigh_seq_state { |
425084614
|
232 |
struct seq_net_private p; |
1da177e4c
|
233 |
struct neigh_table *tbl; |
d6bf78171
|
234 |
struct neigh_hash_table *nht; |
1da177e4c
|
235 236 237 238 239 240 241 242 243 244 245 246 247 248 |
void *(*neigh_sub_iter)(struct neigh_seq_state *state, struct neighbour *n, loff_t *pos); unsigned int bucket; unsigned int flags; #define NEIGH_SEQ_NEIGH_ONLY 0x00000001 #define NEIGH_SEQ_IS_PNEIGH 0x00000002 #define NEIGH_SEQ_SKIP_NOARP 0x00000004 }; extern void *neigh_seq_start(struct seq_file *, loff_t *, struct neigh_table *, unsigned int); extern void *neigh_seq_next(struct seq_file *, void *, loff_t *); extern void neigh_seq_stop(struct seq_file *, void *); extern int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p, |
1da177e4c
|
249 |
char *p_name, |
f8572d8f2
|
250 |
proc_handler *proc_handler); |
1da177e4c
|
251 252 253 254 255 256 |
extern void neigh_sysctl_unregister(struct neigh_parms *p); static inline void __neigh_parms_put(struct neigh_parms *parms) { atomic_dec(&parms->refcnt); } |
1da177e4c
|
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 |
static inline struct neigh_parms *neigh_parms_clone(struct neigh_parms *parms) { atomic_inc(&parms->refcnt); return parms; } /* * Neighbour references */ static inline void neigh_release(struct neighbour *neigh) { if (atomic_dec_and_test(&neigh->refcnt)) neigh_destroy(neigh); } static inline struct neighbour * neigh_clone(struct neighbour *neigh) { if (neigh) atomic_inc(&neigh->refcnt); return neigh; } #define neigh_hold(n) atomic_inc(&(n)->refcnt) static inline void neigh_confirm(struct neighbour *neigh) { if (neigh) neigh->confirmed = jiffies; } |
1da177e4c
|
287 288 |
static inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb) { |
ef22b7b65
|
289 |
unsigned long now = jiffies; |
0ed8ddf40
|
290 291 292 |
if (neigh->used != now) neigh->used = now; |
1da177e4c
|
293 294 295 296 |
if (!(neigh->nud_state&(NUD_CONNECTED|NUD_DELAY|NUD_PROBE))) return __neigh_event_send(neigh, skb); return 0; } |
e179e6322
|
297 298 299 300 301 302 303 304 305 306 307 308 309 |
#ifdef CONFIG_BRIDGE_NETFILTER static inline int neigh_hh_bridge(struct hh_cache *hh, struct sk_buff *skb) { unsigned seq, hh_alen; do { seq = read_seqbegin(&hh->hh_lock); hh_alen = HH_DATA_ALIGN(ETH_HLEN); memcpy(skb->data - hh_alen, hh->hh_data, ETH_ALEN + hh_alen - ETH_HLEN); } while (read_seqretry(&hh->hh_lock, seq)); return 0; } #endif |
3644f0cee
|
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 |
static inline int neigh_hh_output(struct hh_cache *hh, struct sk_buff *skb) { unsigned seq; int hh_len; do { int hh_alen; seq = read_seqbegin(&hh->hh_lock); hh_len = hh->hh_len; hh_alen = HH_DATA_ALIGN(hh_len); memcpy(skb->data - hh_alen, hh->hh_data, hh_alen); } while (read_seqretry(&hh->hh_lock, seq)); skb_push(skb, hh_len); |
b23b5455b
|
325 |
return dev_queue_xmit(skb); |
3644f0cee
|
326 |
} |
05e3aa094
|
327 328 329 |
static inline int neigh_output(struct neighbour *n, struct sk_buff *skb) { struct hh_cache *hh = &n->hh; |
b23b5455b
|
330 |
if ((n->nud_state & NUD_CONNECTED) && hh->hh_len) |
05e3aa094
|
331 332 |
return neigh_hh_output(hh, skb); else |
8f40b161d
|
333 |
return n->output(n, skb); |
05e3aa094
|
334 |
} |
1da177e4c
|
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 |
static inline struct neighbour * __neigh_lookup(struct neigh_table *tbl, const void *pkey, struct net_device *dev, int creat) { struct neighbour *n = neigh_lookup(tbl, pkey, dev); if (n || !creat) return n; n = neigh_create(tbl, pkey, dev); return IS_ERR(n) ? NULL : n; } static inline struct neighbour * __neigh_lookup_errno(struct neigh_table *tbl, const void *pkey, struct net_device *dev) { struct neighbour *n = neigh_lookup(tbl, pkey, dev); if (n) return n; return neigh_create(tbl, pkey, dev); } |
a61bbcf28
|
358 359 360 361 362 363 364 365 |
struct neighbour_cb { unsigned long sched_next; unsigned int flags; }; #define LOCALLY_ENQUEUED 0x1 #define NEIGH_CB(skb) ((struct neighbour_cb *)(skb)->cb) |
1da177e4c
|
366 |
|
0ed8ddf40
|
367 368 369 370 371 372 373 374 375 376 |
static inline void neigh_ha_snapshot(char *dst, const struct neighbour *n, const struct net_device *dev) { unsigned int seq; do { seq = read_seqbegin(&n->ha_lock); memcpy(dst, n->ha, dev->addr_len); } while (read_seqretry(&n->ha_lock, seq)); } |
1da177e4c
|
377 |
#endif |