diff options
Diffstat (limited to 'include/net/ndisc.h')
-rw-r--r-- | include/net/ndisc.h | 45 |
1 files changed, 36 insertions, 9 deletions
diff --git a/include/net/ndisc.h b/include/net/ndisc.h index 62beeb97c4b1..e3133c23980e 100644 --- a/include/net/ndisc.h +++ b/include/net/ndisc.h | |||
@@ -79,6 +79,42 @@ struct nd_opt_hdr { | |||
79 | __u8 nd_opt_len; | 79 | __u8 nd_opt_len; |
80 | } __packed; | 80 | } __packed; |
81 | 81 | ||
82 | static inline u32 ndisc_hashfn(const void *pkey, const struct net_device *dev, __u32 *hash_rnd) | ||
83 | { | ||
84 | const u32 *p32 = pkey; | ||
85 | |||
86 | return (((p32[0] ^ dev->ifindex) * hash_rnd[0]) + | ||
87 | (p32[1] * hash_rnd[1]) + | ||
88 | (p32[2] * hash_rnd[2]) + | ||
89 | (p32[3] * hash_rnd[3])); | ||
90 | } | ||
91 | |||
92 | static inline struct neighbour *__ipv6_neigh_lookup(struct neigh_table *tbl, struct net_device *dev, const void *pkey) | ||
93 | { | ||
94 | struct neigh_hash_table *nht; | ||
95 | const u32 *p32 = pkey; | ||
96 | struct neighbour *n; | ||
97 | u32 hash_val; | ||
98 | |||
99 | rcu_read_lock_bh(); | ||
100 | nht = rcu_dereference_bh(tbl->nht); | ||
101 | hash_val = ndisc_hashfn(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift); | ||
102 | for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]); | ||
103 | n != NULL; | ||
104 | n = rcu_dereference_bh(n->next)) { | ||
105 | u32 *n32 = (u32 *) n->primary_key; | ||
106 | if (n->dev == dev && | ||
107 | ((n32[0] ^ p32[0]) | (n32[1] ^ p32[1]) | | ||
108 | (n32[2] ^ p32[2]) | (n32[3] ^ p32[3])) == 0) { | ||
109 | if (!atomic_inc_not_zero(&n->refcnt)) | ||
110 | n = NULL; | ||
111 | break; | ||
112 | } | ||
113 | } | ||
114 | rcu_read_unlock_bh(); | ||
115 | |||
116 | return n; | ||
117 | } | ||
82 | 118 | ||
83 | extern int ndisc_init(void); | 119 | extern int ndisc_init(void); |
84 | 120 | ||
@@ -145,13 +181,4 @@ int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl, | |||
145 | extern void inet6_ifinfo_notify(int event, | 181 | extern void inet6_ifinfo_notify(int event, |
146 | struct inet6_dev *idev); | 182 | struct inet6_dev *idev); |
147 | 183 | ||
148 | static inline struct neighbour * ndisc_get_neigh(struct net_device *dev, const struct in6_addr *addr) | ||
149 | { | ||
150 | |||
151 | if (dev) | ||
152 | return __neigh_lookup_errno(&nd_tbl, addr, dev); | ||
153 | |||
154 | return ERR_PTR(-ENODEV); | ||
155 | } | ||
156 | |||
157 | #endif | 184 | #endif |