123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 |
- #ifndef _NET_NEIGHBOUR_H
- #define _NET_NEIGHBOUR_H
- #include <linux/neighbour.h>
- /*
- * 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
- */
- #include <asm/atomic.h>
- #include <linux/netdevice.h>
- #include <linux/skbuff.h>
- #include <linux/rcupdate.h>
- #include <linux/seq_file.h>
- #include <linux/err.h>
- #include <linux/sysctl.h>
- #include <linux/workqueue.h>
- #include <net/rtnetlink.h>
- /*
- * NUD stands for "neighbor unreachability detection"
- */
- #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;
- struct neigh_parms {
- #ifdef CONFIG_NET_NS
- struct net *net;
- #endif
- struct net_device *dev;
- struct neigh_parms *next;
- int (*neigh_setup)(struct neighbour *);
- void (*neigh_cleanup)(struct neighbour *);
- struct neigh_table *tbl;
- 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;
- };
- struct neigh_statistics {
- unsigned long allocs; /* number of allocated neighs */
- unsigned long destroys; /* number of destroyed neighs */
- unsigned long hash_grows; /* number of hash resizes */
- unsigned long res_failed; /* number of failed resolutions */
- 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 */
- unsigned long unres_discards; /* number of unresolved drops */
- };
- #define NEIGH_CACHE_STAT_INC(tbl, field) this_cpu_inc((tbl)->stats->field)
- struct neighbour {
- struct neighbour __rcu *next;
- struct neigh_table *tbl;
- struct neigh_parms *parms;
- unsigned long confirmed;
- unsigned long updated;
- rwlock_t lock;
- atomic_t refcnt;
- struct sk_buff_head arp_queue;
- struct timer_list timer;
- unsigned long used;
- atomic_t probes;
- __u8 flags;
- __u8 nud_state;
- __u8 type;
- __u8 dead;
- seqlock_t ha_lock;
- unsigned char ha[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))];
- struct hh_cache *hh;
- int (*output)(struct sk_buff *skb);
- const struct neigh_ops *ops;
- struct rcu_head rcu;
- struct net_device *dev;
- u8 primary_key[0];
- };
- struct neigh_ops {
- int family;
- void (*solicit)(struct neighbour *, struct sk_buff*);
- void (*error_report)(struct neighbour *, struct sk_buff*);
- int (*output)(struct sk_buff*);
- int (*connected_output)(struct sk_buff*);
- int (*hh_output)(struct sk_buff*);
- int (*queue_xmit)(struct sk_buff*);
- };
- struct pneigh_entry {
- struct pneigh_entry *next;
- #ifdef CONFIG_NET_NS
- struct net *net;
- #endif
- struct net_device *dev;
- u8 flags;
- u8 key[0];
- };
- /*
- * neighbour table manipulation
- */
- struct neigh_hash_table {
- struct neighbour __rcu **hash_buckets;
- unsigned int hash_mask;
- __u32 hash_rnd;
- struct rcu_head rcu;
- };
- struct neigh_table {
- struct neigh_table *next;
- int family;
- int entry_size;
- int key_len;
- __u32 (*hash)(const void *pkey,
- const struct net_device *dev,
- __u32 hash_rnd);
- 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;
- /* HACK. gc_* should follow parms without a gap! */
- int gc_interval;
- int gc_thresh1;
- int gc_thresh2;
- int gc_thresh3;
- unsigned long last_flush;
- struct delayed_work gc_work;
- struct timer_list proxy_timer;
- struct sk_buff_head proxy_queue;
- atomic_t entries;
- rwlock_t lock;
- unsigned long last_rand;
- struct kmem_cache *kmem_cachep;
- struct neigh_statistics __percpu *stats;
- struct neigh_hash_table __rcu *nht;
- struct pneigh_entry **phash_buckets;
- };
- /* 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);
- extern void neigh_table_init_no_netlink(struct neigh_table *tbl);
- 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,
- struct net *net,
- 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);
- extern int neigh_resolve_output(struct sk_buff *skb);
- extern int neigh_connected_output(struct sk_buff *skb);
- extern int neigh_compat_output(struct sk_buff *skb);
- 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);
- static inline
- struct net *neigh_parms_net(const struct neigh_parms *parms)
- {
- return read_pnet(&parms->net);
- }
- 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);
- extern struct pneigh_entry *pneigh_lookup(struct neigh_table *tbl, struct net *net, const void *key, struct net_device *dev, int creat);
- extern struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
- struct net *net,
- const void *key,
- struct net_device *dev);
- extern int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *key, struct net_device *dev);
- static inline
- struct net *pneigh_net(const struct pneigh_entry *pneigh)
- {
- return read_pnet(&pneigh->net);
- }
- extern void neigh_app_ns(struct neighbour *n);
- 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 {
- struct seq_net_private p;
- struct neigh_table *tbl;
- struct neigh_hash_table *nht;
- 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,
- char *p_name,
- proc_handler *proc_handler);
- extern void neigh_sysctl_unregister(struct neigh_parms *p);
- static inline void __neigh_parms_put(struct neigh_parms *parms)
- {
- atomic_dec(&parms->refcnt);
- }
- 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;
- }
- static inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
- {
- unsigned long now = jiffies;
-
- if (neigh->used != now)
- neigh->used = now;
- if (!(neigh->nud_state&(NUD_CONNECTED|NUD_DELAY|NUD_PROBE)))
- return __neigh_event_send(neigh, skb);
- return 0;
- }
- #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
- 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);
- return hh->hh_output(skb);
- }
- 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);
- }
- struct neighbour_cb {
- unsigned long sched_next;
- unsigned int flags;
- };
- #define LOCALLY_ENQUEUED 0x1
- #define NEIGH_CB(skb) ((struct neighbour_cb *)(skb)->cb)
- 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));
- }
- #endif
|