162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef _NET_NEIGHBOUR_H 362306a36Sopenharmony_ci#define _NET_NEIGHBOUR_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include <linux/neighbour.h> 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci/* 862306a36Sopenharmony_ci * Generic neighbour manipulation 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Authors: 1162306a36Sopenharmony_ci * Pedro Roque <roque@di.fc.ul.pt> 1262306a36Sopenharmony_ci * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * Changes: 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * Harald Welte: <laforge@gnumonks.org> 1762306a36Sopenharmony_ci * - Add neighbour cache statistics like rtstat 1862306a36Sopenharmony_ci */ 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#include <linux/atomic.h> 2162306a36Sopenharmony_ci#include <linux/refcount.h> 2262306a36Sopenharmony_ci#include <linux/netdevice.h> 2362306a36Sopenharmony_ci#include <linux/skbuff.h> 2462306a36Sopenharmony_ci#include <linux/rcupdate.h> 2562306a36Sopenharmony_ci#include <linux/seq_file.h> 2662306a36Sopenharmony_ci#include <linux/bitmap.h> 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#include <linux/err.h> 2962306a36Sopenharmony_ci#include <linux/sysctl.h> 3062306a36Sopenharmony_ci#include <linux/workqueue.h> 3162306a36Sopenharmony_ci#include <net/rtnetlink.h> 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci/* 3462306a36Sopenharmony_ci * NUD stands for "neighbor unreachability detection" 3562306a36Sopenharmony_ci */ 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#define NUD_IN_TIMER (NUD_INCOMPLETE|NUD_REACHABLE|NUD_DELAY|NUD_PROBE) 3862306a36Sopenharmony_ci#define NUD_VALID (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE|NUD_PROBE|NUD_STALE|NUD_DELAY) 3962306a36Sopenharmony_ci#define NUD_CONNECTED (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE) 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cistruct neighbour; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cienum { 4462306a36Sopenharmony_ci NEIGH_VAR_MCAST_PROBES, 4562306a36Sopenharmony_ci NEIGH_VAR_UCAST_PROBES, 4662306a36Sopenharmony_ci NEIGH_VAR_APP_PROBES, 4762306a36Sopenharmony_ci NEIGH_VAR_MCAST_REPROBES, 4862306a36Sopenharmony_ci NEIGH_VAR_RETRANS_TIME, 4962306a36Sopenharmony_ci NEIGH_VAR_BASE_REACHABLE_TIME, 5062306a36Sopenharmony_ci NEIGH_VAR_DELAY_PROBE_TIME, 5162306a36Sopenharmony_ci NEIGH_VAR_INTERVAL_PROBE_TIME_MS, 5262306a36Sopenharmony_ci NEIGH_VAR_GC_STALETIME, 5362306a36Sopenharmony_ci NEIGH_VAR_QUEUE_LEN_BYTES, 5462306a36Sopenharmony_ci NEIGH_VAR_PROXY_QLEN, 5562306a36Sopenharmony_ci NEIGH_VAR_ANYCAST_DELAY, 5662306a36Sopenharmony_ci NEIGH_VAR_PROXY_DELAY, 5762306a36Sopenharmony_ci NEIGH_VAR_LOCKTIME, 5862306a36Sopenharmony_ci#define NEIGH_VAR_DATA_MAX (NEIGH_VAR_LOCKTIME + 1) 5962306a36Sopenharmony_ci /* Following are used as a second way to access one of the above */ 6062306a36Sopenharmony_ci NEIGH_VAR_QUEUE_LEN, /* same data as NEIGH_VAR_QUEUE_LEN_BYTES */ 6162306a36Sopenharmony_ci NEIGH_VAR_RETRANS_TIME_MS, /* same data as NEIGH_VAR_RETRANS_TIME */ 6262306a36Sopenharmony_ci NEIGH_VAR_BASE_REACHABLE_TIME_MS, /* same data as NEIGH_VAR_BASE_REACHABLE_TIME */ 6362306a36Sopenharmony_ci /* Following are used by "default" only */ 6462306a36Sopenharmony_ci NEIGH_VAR_GC_INTERVAL, 6562306a36Sopenharmony_ci NEIGH_VAR_GC_THRESH1, 6662306a36Sopenharmony_ci NEIGH_VAR_GC_THRESH2, 6762306a36Sopenharmony_ci NEIGH_VAR_GC_THRESH3, 6862306a36Sopenharmony_ci NEIGH_VAR_MAX 6962306a36Sopenharmony_ci}; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_cistruct neigh_parms { 7262306a36Sopenharmony_ci possible_net_t net; 7362306a36Sopenharmony_ci struct net_device *dev; 7462306a36Sopenharmony_ci netdevice_tracker dev_tracker; 7562306a36Sopenharmony_ci struct list_head list; 7662306a36Sopenharmony_ci int (*neigh_setup)(struct neighbour *); 7762306a36Sopenharmony_ci struct neigh_table *tbl; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci void *sysctl_table; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci int dead; 8262306a36Sopenharmony_ci refcount_t refcnt; 8362306a36Sopenharmony_ci struct rcu_head rcu_head; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci int reachable_time; 8662306a36Sopenharmony_ci u32 qlen; 8762306a36Sopenharmony_ci int data[NEIGH_VAR_DATA_MAX]; 8862306a36Sopenharmony_ci DECLARE_BITMAP(data_state, NEIGH_VAR_DATA_MAX); 8962306a36Sopenharmony_ci}; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_cistatic inline void neigh_var_set(struct neigh_parms *p, int index, int val) 9262306a36Sopenharmony_ci{ 9362306a36Sopenharmony_ci set_bit(index, p->data_state); 9462306a36Sopenharmony_ci p->data[index] = val; 9562306a36Sopenharmony_ci} 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci#define NEIGH_VAR(p, attr) ((p)->data[NEIGH_VAR_ ## attr]) 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci/* In ndo_neigh_setup, NEIGH_VAR_INIT should be used. 10062306a36Sopenharmony_ci * In other cases, NEIGH_VAR_SET should be used. 10162306a36Sopenharmony_ci */ 10262306a36Sopenharmony_ci#define NEIGH_VAR_INIT(p, attr, val) (NEIGH_VAR(p, attr) = val) 10362306a36Sopenharmony_ci#define NEIGH_VAR_SET(p, attr, val) neigh_var_set(p, NEIGH_VAR_ ## attr, val) 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistatic inline void neigh_parms_data_state_setall(struct neigh_parms *p) 10662306a36Sopenharmony_ci{ 10762306a36Sopenharmony_ci bitmap_fill(p->data_state, NEIGH_VAR_DATA_MAX); 10862306a36Sopenharmony_ci} 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_cistatic inline void neigh_parms_data_state_cleanall(struct neigh_parms *p) 11162306a36Sopenharmony_ci{ 11262306a36Sopenharmony_ci bitmap_zero(p->data_state, NEIGH_VAR_DATA_MAX); 11362306a36Sopenharmony_ci} 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_cistruct neigh_statistics { 11662306a36Sopenharmony_ci unsigned long allocs; /* number of allocated neighs */ 11762306a36Sopenharmony_ci unsigned long destroys; /* number of destroyed neighs */ 11862306a36Sopenharmony_ci unsigned long hash_grows; /* number of hash resizes */ 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci unsigned long res_failed; /* number of failed resolutions */ 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci unsigned long lookups; /* number of lookups */ 12362306a36Sopenharmony_ci unsigned long hits; /* number of hits (among lookups) */ 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci unsigned long rcv_probes_mcast; /* number of received mcast ipv6 */ 12662306a36Sopenharmony_ci unsigned long rcv_probes_ucast; /* number of received ucast ipv6 */ 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci unsigned long periodic_gc_runs; /* number of periodic GC runs */ 12962306a36Sopenharmony_ci unsigned long forced_gc_runs; /* number of forced GC runs */ 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci unsigned long unres_discards; /* number of unresolved drops */ 13262306a36Sopenharmony_ci unsigned long table_fulls; /* times even gc couldn't help */ 13362306a36Sopenharmony_ci}; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci#define NEIGH_CACHE_STAT_INC(tbl, field) this_cpu_inc((tbl)->stats->field) 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_cistruct neighbour { 13862306a36Sopenharmony_ci struct neighbour __rcu *next; 13962306a36Sopenharmony_ci struct neigh_table *tbl; 14062306a36Sopenharmony_ci struct neigh_parms *parms; 14162306a36Sopenharmony_ci unsigned long confirmed; 14262306a36Sopenharmony_ci unsigned long updated; 14362306a36Sopenharmony_ci rwlock_t lock; 14462306a36Sopenharmony_ci refcount_t refcnt; 14562306a36Sopenharmony_ci unsigned int arp_queue_len_bytes; 14662306a36Sopenharmony_ci struct sk_buff_head arp_queue; 14762306a36Sopenharmony_ci struct timer_list timer; 14862306a36Sopenharmony_ci unsigned long used; 14962306a36Sopenharmony_ci atomic_t probes; 15062306a36Sopenharmony_ci u8 nud_state; 15162306a36Sopenharmony_ci u8 type; 15262306a36Sopenharmony_ci u8 dead; 15362306a36Sopenharmony_ci u8 protocol; 15462306a36Sopenharmony_ci u32 flags; 15562306a36Sopenharmony_ci seqlock_t ha_lock; 15662306a36Sopenharmony_ci unsigned char ha[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))] __aligned(8); 15762306a36Sopenharmony_ci struct hh_cache hh; 15862306a36Sopenharmony_ci int (*output)(struct neighbour *, struct sk_buff *); 15962306a36Sopenharmony_ci const struct neigh_ops *ops; 16062306a36Sopenharmony_ci struct list_head gc_list; 16162306a36Sopenharmony_ci struct list_head managed_list; 16262306a36Sopenharmony_ci struct rcu_head rcu; 16362306a36Sopenharmony_ci struct net_device *dev; 16462306a36Sopenharmony_ci netdevice_tracker dev_tracker; 16562306a36Sopenharmony_ci u8 primary_key[]; 16662306a36Sopenharmony_ci} __randomize_layout; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistruct neigh_ops { 16962306a36Sopenharmony_ci int family; 17062306a36Sopenharmony_ci void (*solicit)(struct neighbour *, struct sk_buff *); 17162306a36Sopenharmony_ci void (*error_report)(struct neighbour *, struct sk_buff *); 17262306a36Sopenharmony_ci int (*output)(struct neighbour *, struct sk_buff *); 17362306a36Sopenharmony_ci int (*connected_output)(struct neighbour *, struct sk_buff *); 17462306a36Sopenharmony_ci}; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_cistruct pneigh_entry { 17762306a36Sopenharmony_ci struct pneigh_entry *next; 17862306a36Sopenharmony_ci possible_net_t net; 17962306a36Sopenharmony_ci struct net_device *dev; 18062306a36Sopenharmony_ci netdevice_tracker dev_tracker; 18162306a36Sopenharmony_ci u32 flags; 18262306a36Sopenharmony_ci u8 protocol; 18362306a36Sopenharmony_ci u32 key[]; 18462306a36Sopenharmony_ci}; 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci/* 18762306a36Sopenharmony_ci * neighbour table manipulation 18862306a36Sopenharmony_ci */ 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci#define NEIGH_NUM_HASH_RND 4 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistruct neigh_hash_table { 19362306a36Sopenharmony_ci struct neighbour __rcu **hash_buckets; 19462306a36Sopenharmony_ci unsigned int hash_shift; 19562306a36Sopenharmony_ci __u32 hash_rnd[NEIGH_NUM_HASH_RND]; 19662306a36Sopenharmony_ci struct rcu_head rcu; 19762306a36Sopenharmony_ci}; 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_cistruct neigh_table { 20162306a36Sopenharmony_ci int family; 20262306a36Sopenharmony_ci unsigned int entry_size; 20362306a36Sopenharmony_ci unsigned int key_len; 20462306a36Sopenharmony_ci __be16 protocol; 20562306a36Sopenharmony_ci __u32 (*hash)(const void *pkey, 20662306a36Sopenharmony_ci const struct net_device *dev, 20762306a36Sopenharmony_ci __u32 *hash_rnd); 20862306a36Sopenharmony_ci bool (*key_eq)(const struct neighbour *, const void *pkey); 20962306a36Sopenharmony_ci int (*constructor)(struct neighbour *); 21062306a36Sopenharmony_ci int (*pconstructor)(struct pneigh_entry *); 21162306a36Sopenharmony_ci void (*pdestructor)(struct pneigh_entry *); 21262306a36Sopenharmony_ci void (*proxy_redo)(struct sk_buff *skb); 21362306a36Sopenharmony_ci int (*is_multicast)(const void *pkey); 21462306a36Sopenharmony_ci bool (*allow_add)(const struct net_device *dev, 21562306a36Sopenharmony_ci struct netlink_ext_ack *extack); 21662306a36Sopenharmony_ci char *id; 21762306a36Sopenharmony_ci struct neigh_parms parms; 21862306a36Sopenharmony_ci struct list_head parms_list; 21962306a36Sopenharmony_ci int gc_interval; 22062306a36Sopenharmony_ci int gc_thresh1; 22162306a36Sopenharmony_ci int gc_thresh2; 22262306a36Sopenharmony_ci int gc_thresh3; 22362306a36Sopenharmony_ci unsigned long last_flush; 22462306a36Sopenharmony_ci struct delayed_work gc_work; 22562306a36Sopenharmony_ci struct delayed_work managed_work; 22662306a36Sopenharmony_ci struct timer_list proxy_timer; 22762306a36Sopenharmony_ci struct sk_buff_head proxy_queue; 22862306a36Sopenharmony_ci atomic_t entries; 22962306a36Sopenharmony_ci atomic_t gc_entries; 23062306a36Sopenharmony_ci struct list_head gc_list; 23162306a36Sopenharmony_ci struct list_head managed_list; 23262306a36Sopenharmony_ci rwlock_t lock; 23362306a36Sopenharmony_ci unsigned long last_rand; 23462306a36Sopenharmony_ci struct neigh_statistics __percpu *stats; 23562306a36Sopenharmony_ci struct neigh_hash_table __rcu *nht; 23662306a36Sopenharmony_ci struct pneigh_entry **phash_buckets; 23762306a36Sopenharmony_ci}; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_cienum { 24062306a36Sopenharmony_ci NEIGH_ARP_TABLE = 0, 24162306a36Sopenharmony_ci NEIGH_ND_TABLE = 1, 24262306a36Sopenharmony_ci NEIGH_DN_TABLE = 2, 24362306a36Sopenharmony_ci NEIGH_NR_TABLES, 24462306a36Sopenharmony_ci NEIGH_LINK_TABLE = NEIGH_NR_TABLES /* Pseudo table for neigh_xmit */ 24562306a36Sopenharmony_ci}; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_cistatic inline int neigh_parms_family(struct neigh_parms *p) 24862306a36Sopenharmony_ci{ 24962306a36Sopenharmony_ci return p->tbl->family; 25062306a36Sopenharmony_ci} 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci#define NEIGH_PRIV_ALIGN sizeof(long long) 25362306a36Sopenharmony_ci#define NEIGH_ENTRY_SIZE(size) ALIGN((size), NEIGH_PRIV_ALIGN) 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_cistatic inline void *neighbour_priv(const struct neighbour *n) 25662306a36Sopenharmony_ci{ 25762306a36Sopenharmony_ci return (char *)n + n->tbl->entry_size; 25862306a36Sopenharmony_ci} 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci/* flags for neigh_update() */ 26162306a36Sopenharmony_ci#define NEIGH_UPDATE_F_OVERRIDE BIT(0) 26262306a36Sopenharmony_ci#define NEIGH_UPDATE_F_WEAK_OVERRIDE BIT(1) 26362306a36Sopenharmony_ci#define NEIGH_UPDATE_F_OVERRIDE_ISROUTER BIT(2) 26462306a36Sopenharmony_ci#define NEIGH_UPDATE_F_USE BIT(3) 26562306a36Sopenharmony_ci#define NEIGH_UPDATE_F_MANAGED BIT(4) 26662306a36Sopenharmony_ci#define NEIGH_UPDATE_F_EXT_LEARNED BIT(5) 26762306a36Sopenharmony_ci#define NEIGH_UPDATE_F_ISROUTER BIT(6) 26862306a36Sopenharmony_ci#define NEIGH_UPDATE_F_ADMIN BIT(7) 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci/* In-kernel representation for NDA_FLAGS_EXT flags: */ 27162306a36Sopenharmony_ci#define NTF_OLD_MASK 0xff 27262306a36Sopenharmony_ci#define NTF_EXT_SHIFT 8 27362306a36Sopenharmony_ci#define NTF_EXT_MASK (NTF_EXT_MANAGED) 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci#define NTF_MANAGED (NTF_EXT_MANAGED << NTF_EXT_SHIFT) 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ciextern const struct nla_policy nda_policy[]; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_cistatic inline bool neigh_key_eq32(const struct neighbour *n, const void *pkey) 28062306a36Sopenharmony_ci{ 28162306a36Sopenharmony_ci return *(const u32 *)n->primary_key == *(const u32 *)pkey; 28262306a36Sopenharmony_ci} 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_cistatic inline bool neigh_key_eq128(const struct neighbour *n, const void *pkey) 28562306a36Sopenharmony_ci{ 28662306a36Sopenharmony_ci const u32 *n32 = (const u32 *)n->primary_key; 28762306a36Sopenharmony_ci const u32 *p32 = pkey; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci return ((n32[0] ^ p32[0]) | (n32[1] ^ p32[1]) | 29062306a36Sopenharmony_ci (n32[2] ^ p32[2]) | (n32[3] ^ p32[3])) == 0; 29162306a36Sopenharmony_ci} 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_cistatic inline struct neighbour *___neigh_lookup_noref( 29462306a36Sopenharmony_ci struct neigh_table *tbl, 29562306a36Sopenharmony_ci bool (*key_eq)(const struct neighbour *n, const void *pkey), 29662306a36Sopenharmony_ci __u32 (*hash)(const void *pkey, 29762306a36Sopenharmony_ci const struct net_device *dev, 29862306a36Sopenharmony_ci __u32 *hash_rnd), 29962306a36Sopenharmony_ci const void *pkey, 30062306a36Sopenharmony_ci struct net_device *dev) 30162306a36Sopenharmony_ci{ 30262306a36Sopenharmony_ci struct neigh_hash_table *nht = rcu_dereference(tbl->nht); 30362306a36Sopenharmony_ci struct neighbour *n; 30462306a36Sopenharmony_ci u32 hash_val; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci hash_val = hash(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift); 30762306a36Sopenharmony_ci for (n = rcu_dereference(nht->hash_buckets[hash_val]); 30862306a36Sopenharmony_ci n != NULL; 30962306a36Sopenharmony_ci n = rcu_dereference(n->next)) { 31062306a36Sopenharmony_ci if (n->dev == dev && key_eq(n, pkey)) 31162306a36Sopenharmony_ci return n; 31262306a36Sopenharmony_ci } 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci return NULL; 31562306a36Sopenharmony_ci} 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_cistatic inline struct neighbour *__neigh_lookup_noref(struct neigh_table *tbl, 31862306a36Sopenharmony_ci const void *pkey, 31962306a36Sopenharmony_ci struct net_device *dev) 32062306a36Sopenharmony_ci{ 32162306a36Sopenharmony_ci return ___neigh_lookup_noref(tbl, tbl->key_eq, tbl->hash, pkey, dev); 32262306a36Sopenharmony_ci} 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_cistatic inline void neigh_confirm(struct neighbour *n) 32562306a36Sopenharmony_ci{ 32662306a36Sopenharmony_ci if (n) { 32762306a36Sopenharmony_ci unsigned long now = jiffies; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci /* avoid dirtying neighbour */ 33062306a36Sopenharmony_ci if (READ_ONCE(n->confirmed) != now) 33162306a36Sopenharmony_ci WRITE_ONCE(n->confirmed, now); 33262306a36Sopenharmony_ci } 33362306a36Sopenharmony_ci} 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_civoid neigh_table_init(int index, struct neigh_table *tbl); 33662306a36Sopenharmony_ciint neigh_table_clear(int index, struct neigh_table *tbl); 33762306a36Sopenharmony_cistruct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey, 33862306a36Sopenharmony_ci struct net_device *dev); 33962306a36Sopenharmony_cistruct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey, 34062306a36Sopenharmony_ci struct net_device *dev, bool want_ref); 34162306a36Sopenharmony_cistatic inline struct neighbour *neigh_create(struct neigh_table *tbl, 34262306a36Sopenharmony_ci const void *pkey, 34362306a36Sopenharmony_ci struct net_device *dev) 34462306a36Sopenharmony_ci{ 34562306a36Sopenharmony_ci return __neigh_create(tbl, pkey, dev, true); 34662306a36Sopenharmony_ci} 34762306a36Sopenharmony_civoid neigh_destroy(struct neighbour *neigh); 34862306a36Sopenharmony_ciint __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb, 34962306a36Sopenharmony_ci const bool immediate_ok); 35062306a36Sopenharmony_ciint neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, u32 flags, 35162306a36Sopenharmony_ci u32 nlmsg_pid); 35262306a36Sopenharmony_civoid __neigh_set_probe_once(struct neighbour *neigh); 35362306a36Sopenharmony_cibool neigh_remove_one(struct neighbour *ndel, struct neigh_table *tbl); 35462306a36Sopenharmony_civoid neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev); 35562306a36Sopenharmony_ciint neigh_ifdown(struct neigh_table *tbl, struct net_device *dev); 35662306a36Sopenharmony_ciint neigh_carrier_down(struct neigh_table *tbl, struct net_device *dev); 35762306a36Sopenharmony_ciint neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb); 35862306a36Sopenharmony_ciint neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb); 35962306a36Sopenharmony_ciint neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb); 36062306a36Sopenharmony_cistruct neighbour *neigh_event_ns(struct neigh_table *tbl, 36162306a36Sopenharmony_ci u8 *lladdr, void *saddr, 36262306a36Sopenharmony_ci struct net_device *dev); 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_cistruct neigh_parms *neigh_parms_alloc(struct net_device *dev, 36562306a36Sopenharmony_ci struct neigh_table *tbl); 36662306a36Sopenharmony_civoid neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms); 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_cistatic inline 36962306a36Sopenharmony_cistruct net *neigh_parms_net(const struct neigh_parms *parms) 37062306a36Sopenharmony_ci{ 37162306a36Sopenharmony_ci return read_pnet(&parms->net); 37262306a36Sopenharmony_ci} 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ciunsigned long neigh_rand_reach_time(unsigned long base); 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_civoid pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p, 37762306a36Sopenharmony_ci struct sk_buff *skb); 37862306a36Sopenharmony_cistruct pneigh_entry *pneigh_lookup(struct neigh_table *tbl, struct net *net, 37962306a36Sopenharmony_ci const void *key, struct net_device *dev, 38062306a36Sopenharmony_ci int creat); 38162306a36Sopenharmony_cistruct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl, struct net *net, 38262306a36Sopenharmony_ci const void *key, struct net_device *dev); 38362306a36Sopenharmony_ciint pneigh_delete(struct neigh_table *tbl, struct net *net, const void *key, 38462306a36Sopenharmony_ci struct net_device *dev); 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_cistatic inline struct net *pneigh_net(const struct pneigh_entry *pneigh) 38762306a36Sopenharmony_ci{ 38862306a36Sopenharmony_ci return read_pnet(&pneigh->net); 38962306a36Sopenharmony_ci} 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_civoid neigh_app_ns(struct neighbour *n); 39262306a36Sopenharmony_civoid neigh_for_each(struct neigh_table *tbl, 39362306a36Sopenharmony_ci void (*cb)(struct neighbour *, void *), void *cookie); 39462306a36Sopenharmony_civoid __neigh_for_each_release(struct neigh_table *tbl, 39562306a36Sopenharmony_ci int (*cb)(struct neighbour *)); 39662306a36Sopenharmony_ciint neigh_xmit(int fam, struct net_device *, const void *, struct sk_buff *); 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_cistruct neigh_seq_state { 39962306a36Sopenharmony_ci struct seq_net_private p; 40062306a36Sopenharmony_ci struct neigh_table *tbl; 40162306a36Sopenharmony_ci struct neigh_hash_table *nht; 40262306a36Sopenharmony_ci void *(*neigh_sub_iter)(struct neigh_seq_state *state, 40362306a36Sopenharmony_ci struct neighbour *n, loff_t *pos); 40462306a36Sopenharmony_ci unsigned int bucket; 40562306a36Sopenharmony_ci unsigned int flags; 40662306a36Sopenharmony_ci#define NEIGH_SEQ_NEIGH_ONLY 0x00000001 40762306a36Sopenharmony_ci#define NEIGH_SEQ_IS_PNEIGH 0x00000002 40862306a36Sopenharmony_ci#define NEIGH_SEQ_SKIP_NOARP 0x00000004 40962306a36Sopenharmony_ci}; 41062306a36Sopenharmony_civoid *neigh_seq_start(struct seq_file *, loff_t *, struct neigh_table *, 41162306a36Sopenharmony_ci unsigned int); 41262306a36Sopenharmony_civoid *neigh_seq_next(struct seq_file *, void *, loff_t *); 41362306a36Sopenharmony_civoid neigh_seq_stop(struct seq_file *, void *); 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ciint neigh_proc_dointvec(struct ctl_table *ctl, int write, 41662306a36Sopenharmony_ci void *buffer, size_t *lenp, loff_t *ppos); 41762306a36Sopenharmony_ciint neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write, 41862306a36Sopenharmony_ci void *buffer, 41962306a36Sopenharmony_ci size_t *lenp, loff_t *ppos); 42062306a36Sopenharmony_ciint neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write, 42162306a36Sopenharmony_ci void *buffer, size_t *lenp, loff_t *ppos); 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ciint neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p, 42462306a36Sopenharmony_ci proc_handler *proc_handler); 42562306a36Sopenharmony_civoid neigh_sysctl_unregister(struct neigh_parms *p); 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_cistatic inline void __neigh_parms_put(struct neigh_parms *parms) 42862306a36Sopenharmony_ci{ 42962306a36Sopenharmony_ci refcount_dec(&parms->refcnt); 43062306a36Sopenharmony_ci} 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_cistatic inline struct neigh_parms *neigh_parms_clone(struct neigh_parms *parms) 43362306a36Sopenharmony_ci{ 43462306a36Sopenharmony_ci refcount_inc(&parms->refcnt); 43562306a36Sopenharmony_ci return parms; 43662306a36Sopenharmony_ci} 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci/* 43962306a36Sopenharmony_ci * Neighbour references 44062306a36Sopenharmony_ci */ 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_cistatic inline void neigh_release(struct neighbour *neigh) 44362306a36Sopenharmony_ci{ 44462306a36Sopenharmony_ci if (refcount_dec_and_test(&neigh->refcnt)) 44562306a36Sopenharmony_ci neigh_destroy(neigh); 44662306a36Sopenharmony_ci} 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_cistatic inline struct neighbour * neigh_clone(struct neighbour *neigh) 44962306a36Sopenharmony_ci{ 45062306a36Sopenharmony_ci if (neigh) 45162306a36Sopenharmony_ci refcount_inc(&neigh->refcnt); 45262306a36Sopenharmony_ci return neigh; 45362306a36Sopenharmony_ci} 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci#define neigh_hold(n) refcount_inc(&(n)->refcnt) 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_cistatic __always_inline int neigh_event_send_probe(struct neighbour *neigh, 45862306a36Sopenharmony_ci struct sk_buff *skb, 45962306a36Sopenharmony_ci const bool immediate_ok) 46062306a36Sopenharmony_ci{ 46162306a36Sopenharmony_ci unsigned long now = jiffies; 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci if (READ_ONCE(neigh->used) != now) 46462306a36Sopenharmony_ci WRITE_ONCE(neigh->used, now); 46562306a36Sopenharmony_ci if (!(READ_ONCE(neigh->nud_state) & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))) 46662306a36Sopenharmony_ci return __neigh_event_send(neigh, skb, immediate_ok); 46762306a36Sopenharmony_ci return 0; 46862306a36Sopenharmony_ci} 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_cistatic inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb) 47162306a36Sopenharmony_ci{ 47262306a36Sopenharmony_ci return neigh_event_send_probe(neigh, skb, true); 47362306a36Sopenharmony_ci} 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) 47662306a36Sopenharmony_cistatic inline int neigh_hh_bridge(struct hh_cache *hh, struct sk_buff *skb) 47762306a36Sopenharmony_ci{ 47862306a36Sopenharmony_ci unsigned int seq, hh_alen; 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci do { 48162306a36Sopenharmony_ci seq = read_seqbegin(&hh->hh_lock); 48262306a36Sopenharmony_ci hh_alen = HH_DATA_ALIGN(ETH_HLEN); 48362306a36Sopenharmony_ci memcpy(skb->data - hh_alen, hh->hh_data, ETH_ALEN + hh_alen - ETH_HLEN); 48462306a36Sopenharmony_ci } while (read_seqretry(&hh->hh_lock, seq)); 48562306a36Sopenharmony_ci return 0; 48662306a36Sopenharmony_ci} 48762306a36Sopenharmony_ci#endif 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_cistatic inline int neigh_hh_output(const struct hh_cache *hh, struct sk_buff *skb) 49062306a36Sopenharmony_ci{ 49162306a36Sopenharmony_ci unsigned int hh_alen = 0; 49262306a36Sopenharmony_ci unsigned int seq; 49362306a36Sopenharmony_ci unsigned int hh_len; 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci do { 49662306a36Sopenharmony_ci seq = read_seqbegin(&hh->hh_lock); 49762306a36Sopenharmony_ci hh_len = READ_ONCE(hh->hh_len); 49862306a36Sopenharmony_ci if (likely(hh_len <= HH_DATA_MOD)) { 49962306a36Sopenharmony_ci hh_alen = HH_DATA_MOD; 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci /* skb_push() would proceed silently if we have room for 50262306a36Sopenharmony_ci * the unaligned size but not for the aligned size: 50362306a36Sopenharmony_ci * check headroom explicitly. 50462306a36Sopenharmony_ci */ 50562306a36Sopenharmony_ci if (likely(skb_headroom(skb) >= HH_DATA_MOD)) { 50662306a36Sopenharmony_ci /* this is inlined by gcc */ 50762306a36Sopenharmony_ci memcpy(skb->data - HH_DATA_MOD, hh->hh_data, 50862306a36Sopenharmony_ci HH_DATA_MOD); 50962306a36Sopenharmony_ci } 51062306a36Sopenharmony_ci } else { 51162306a36Sopenharmony_ci hh_alen = HH_DATA_ALIGN(hh_len); 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci if (likely(skb_headroom(skb) >= hh_alen)) { 51462306a36Sopenharmony_ci memcpy(skb->data - hh_alen, hh->hh_data, 51562306a36Sopenharmony_ci hh_alen); 51662306a36Sopenharmony_ci } 51762306a36Sopenharmony_ci } 51862306a36Sopenharmony_ci } while (read_seqretry(&hh->hh_lock, seq)); 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci if (WARN_ON_ONCE(skb_headroom(skb) < hh_alen)) { 52162306a36Sopenharmony_ci kfree_skb(skb); 52262306a36Sopenharmony_ci return NET_XMIT_DROP; 52362306a36Sopenharmony_ci } 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci __skb_push(skb, hh_len); 52662306a36Sopenharmony_ci return dev_queue_xmit(skb); 52762306a36Sopenharmony_ci} 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_cistatic inline int neigh_output(struct neighbour *n, struct sk_buff *skb, 53062306a36Sopenharmony_ci bool skip_cache) 53162306a36Sopenharmony_ci{ 53262306a36Sopenharmony_ci const struct hh_cache *hh = &n->hh; 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci /* n->nud_state and hh->hh_len could be changed under us. 53562306a36Sopenharmony_ci * neigh_hh_output() is taking care of the race later. 53662306a36Sopenharmony_ci */ 53762306a36Sopenharmony_ci if (!skip_cache && 53862306a36Sopenharmony_ci (READ_ONCE(n->nud_state) & NUD_CONNECTED) && 53962306a36Sopenharmony_ci READ_ONCE(hh->hh_len)) 54062306a36Sopenharmony_ci return neigh_hh_output(hh, skb); 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci return READ_ONCE(n->output)(n, skb); 54362306a36Sopenharmony_ci} 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_cistatic inline struct neighbour * 54662306a36Sopenharmony_ci__neigh_lookup(struct neigh_table *tbl, const void *pkey, struct net_device *dev, int creat) 54762306a36Sopenharmony_ci{ 54862306a36Sopenharmony_ci struct neighbour *n = neigh_lookup(tbl, pkey, dev); 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci if (n || !creat) 55162306a36Sopenharmony_ci return n; 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci n = neigh_create(tbl, pkey, dev); 55462306a36Sopenharmony_ci return IS_ERR(n) ? NULL : n; 55562306a36Sopenharmony_ci} 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_cistatic inline struct neighbour * 55862306a36Sopenharmony_ci__neigh_lookup_errno(struct neigh_table *tbl, const void *pkey, 55962306a36Sopenharmony_ci struct net_device *dev) 56062306a36Sopenharmony_ci{ 56162306a36Sopenharmony_ci struct neighbour *n = neigh_lookup(tbl, pkey, dev); 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci if (n) 56462306a36Sopenharmony_ci return n; 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci return neigh_create(tbl, pkey, dev); 56762306a36Sopenharmony_ci} 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_cistruct neighbour_cb { 57062306a36Sopenharmony_ci unsigned long sched_next; 57162306a36Sopenharmony_ci unsigned int flags; 57262306a36Sopenharmony_ci}; 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci#define LOCALLY_ENQUEUED 0x1 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci#define NEIGH_CB(skb) ((struct neighbour_cb *)(skb)->cb) 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_cistatic inline void neigh_ha_snapshot(char *dst, const struct neighbour *n, 57962306a36Sopenharmony_ci const struct net_device *dev) 58062306a36Sopenharmony_ci{ 58162306a36Sopenharmony_ci unsigned int seq; 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci do { 58462306a36Sopenharmony_ci seq = read_seqbegin(&n->ha_lock); 58562306a36Sopenharmony_ci memcpy(dst, n->ha, dev->addr_len); 58662306a36Sopenharmony_ci } while (read_seqretry(&n->ha_lock, seq)); 58762306a36Sopenharmony_ci} 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_cistatic inline void neigh_update_is_router(struct neighbour *neigh, u32 flags, 59062306a36Sopenharmony_ci int *notify) 59162306a36Sopenharmony_ci{ 59262306a36Sopenharmony_ci u8 ndm_flags = 0; 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci ndm_flags |= (flags & NEIGH_UPDATE_F_ISROUTER) ? NTF_ROUTER : 0; 59562306a36Sopenharmony_ci if ((neigh->flags ^ ndm_flags) & NTF_ROUTER) { 59662306a36Sopenharmony_ci if (ndm_flags & NTF_ROUTER) 59762306a36Sopenharmony_ci neigh->flags |= NTF_ROUTER; 59862306a36Sopenharmony_ci else 59962306a36Sopenharmony_ci neigh->flags &= ~NTF_ROUTER; 60062306a36Sopenharmony_ci *notify = 1; 60162306a36Sopenharmony_ci } 60262306a36Sopenharmony_ci} 60362306a36Sopenharmony_ci#endif 604