aboutsummaryrefslogtreecommitdiffstats
path: root/include/net
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2015-03-03 18:10:44 -0500
committerDavid S. Miller <davem@davemloft.net>2015-03-04 00:23:23 -0500
commit60395a20ffd74166ea373ea91418d6f98fa7fdfb (patch)
treec4ed2b51ec4f179a48018d86660e6f2bb5b8bd81 /include/net
parent2f56f6be47dbc6883e28107edfe2f9f98f4d5a24 (diff)
neigh: Factor out ___neigh_lookup_noref
While looking at the mpls code I found myself writing yet another version of neigh_lookup_noref. We currently have __ipv4_lookup_noref and __ipv6_lookup_noref. So to make my work a little easier and to make it a smidge easier to verify/maintain the mpls code in the future I stopped and wrote ___neigh_lookup_noref. Then I rewote __ipv4_lookup_noref and __ipv6_lookup_noref in terms of this new function. I tested my new version by verifying that the same code is generated in ip_finish_output2 and ip6_finish_output2 where these functions are inlined. To get to ___neigh_lookup_noref I added a new neighbour cache table function key_eq. So that the static size of the key would be available. I also added __neigh_lookup_noref for people who want to to lookup a neighbour table entry quickly but don't know which neibhgour table they are going to look up. Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/net')
-rw-r--r--include/net/arp.h19
-rw-r--r--include/net/ndisc.h19
-rw-r--r--include/net/neighbour.h52
3 files changed, 57 insertions, 33 deletions
diff --git a/include/net/arp.h b/include/net/arp.h
index 21ee1860abbc..5e0f891d476c 100644
--- a/include/net/arp.h
+++ b/include/net/arp.h
@@ -9,28 +9,17 @@
9 9
10extern struct neigh_table arp_tbl; 10extern struct neigh_table arp_tbl;
11 11
12static inline u32 arp_hashfn(u32 key, const struct net_device *dev, u32 hash_rnd) 12static inline u32 arp_hashfn(const void *pkey, const struct net_device *dev, u32 *hash_rnd)
13{ 13{
14 u32 key = *(const u32 *)pkey;
14 u32 val = key ^ hash32_ptr(dev); 15 u32 val = key ^ hash32_ptr(dev);
15 16
16 return val * hash_rnd; 17 return val * hash_rnd[0];
17} 18}
18 19
19static inline struct neighbour *__ipv4_neigh_lookup_noref(struct net_device *dev, u32 key) 20static inline struct neighbour *__ipv4_neigh_lookup_noref(struct net_device *dev, u32 key)
20{ 21{
21 struct neigh_hash_table *nht = rcu_dereference_bh(arp_tbl.nht); 22 return ___neigh_lookup_noref(&arp_tbl, neigh_key_eq32, arp_hashfn, &key, dev);
22 struct neighbour *n;
23 u32 hash_val;
24
25 hash_val = arp_hashfn(key, dev, nht->hash_rnd[0]) >> (32 - nht->hash_shift);
26 for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
27 n != NULL;
28 n = rcu_dereference_bh(n->next)) {
29 if (n->dev == dev && *(u32 *)n->primary_key == key)
30 return n;
31 }
32
33 return NULL;
34} 23}
35 24
36static inline struct neighbour *__ipv4_neigh_lookup(struct net_device *dev, u32 key) 25static inline struct neighbour *__ipv4_neigh_lookup(struct net_device *dev, u32 key)
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index 6bbda34d5e59..b3a7751251b4 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -156,24 +156,7 @@ static inline u32 ndisc_hashfn(const void *pkey, const struct net_device *dev, _
156 156
157static inline struct neighbour *__ipv6_neigh_lookup_noref(struct net_device *dev, const void *pkey) 157static inline struct neighbour *__ipv6_neigh_lookup_noref(struct net_device *dev, const void *pkey)
158{ 158{
159 struct neigh_hash_table *nht; 159 return ___neigh_lookup_noref(&nd_tbl, neigh_key_eq128, ndisc_hashfn, pkey, dev);
160 const u32 *p32 = pkey;
161 struct neighbour *n;
162 u32 hash_val;
163
164 nht = rcu_dereference_bh(nd_tbl.nht);
165 hash_val = ndisc_hashfn(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
166 for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
167 n != NULL;
168 n = rcu_dereference_bh(n->next)) {
169 u32 *n32 = (u32 *) n->primary_key;
170 if (n->dev == dev &&
171 ((n32[0] ^ p32[0]) | (n32[1] ^ p32[1]) |
172 (n32[2] ^ p32[2]) | (n32[3] ^ p32[3])) == 0)
173 return n;
174 }
175
176 return NULL;
177} 160}
178 161
179static inline struct neighbour *__ipv6_neigh_lookup(struct net_device *dev, const void *pkey) 162static inline struct neighbour *__ipv6_neigh_lookup(struct net_device *dev, const void *pkey)
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 9f912e4d4232..14e3f017966b 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -197,6 +197,7 @@ struct neigh_table {
197 __u32 (*hash)(const void *pkey, 197 __u32 (*hash)(const void *pkey,
198 const struct net_device *dev, 198 const struct net_device *dev,
199 __u32 *hash_rnd); 199 __u32 *hash_rnd);
200 bool (*key_eq)(const struct neighbour *, const void *pkey);
200 int (*constructor)(struct neighbour *); 201 int (*constructor)(struct neighbour *);
201 int (*pconstructor)(struct pneigh_entry *); 202 int (*pconstructor)(struct pneigh_entry *);
202 void (*pdestructor)(struct pneigh_entry *); 203 void (*pdestructor)(struct pneigh_entry *);
@@ -247,6 +248,57 @@ static inline void *neighbour_priv(const struct neighbour *n)
247#define NEIGH_UPDATE_F_ISROUTER 0x40000000 248#define NEIGH_UPDATE_F_ISROUTER 0x40000000
248#define NEIGH_UPDATE_F_ADMIN 0x80000000 249#define NEIGH_UPDATE_F_ADMIN 0x80000000
249 250
251
252static inline bool neigh_key_eq16(const struct neighbour *n, const void *pkey)
253{
254 return *(const u16 *)n->primary_key == *(const u16 *)pkey;
255}
256
257static inline bool neigh_key_eq32(const struct neighbour *n, const void *pkey)
258{
259 return *(const u32 *)n->primary_key == *(const u32 *)pkey;
260}
261
262static inline bool neigh_key_eq128(const struct neighbour *n, const void *pkey)
263{
264 const u32 *n32 = (const u32 *)n->primary_key;
265 const u32 *p32 = pkey;
266
267 return ((n32[0] ^ p32[0]) | (n32[1] ^ p32[1]) |
268 (n32[2] ^ p32[2]) | (n32[3] ^ p32[3])) == 0;
269}
270
271static inline struct neighbour *___neigh_lookup_noref(
272 struct neigh_table *tbl,
273 bool (*key_eq)(const struct neighbour *n, const void *pkey),
274 __u32 (*hash)(const void *pkey,
275 const struct net_device *dev,
276 __u32 *hash_rnd),
277 const void *pkey,
278 struct net_device *dev)
279{
280 struct neigh_hash_table *nht = rcu_dereference_bh(tbl->nht);
281 struct neighbour *n;
282 u32 hash_val;
283
284 hash_val = hash(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
285 for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
286 n != NULL;
287 n = rcu_dereference_bh(n->next)) {
288 if (n->dev == dev && key_eq(n, pkey))
289 return n;
290 }
291
292 return NULL;
293}
294
295static inline struct neighbour *__neigh_lookup_noref(struct neigh_table *tbl,
296 const void *pkey,
297 struct net_device *dev)
298{
299 return ___neigh_lookup_noref(tbl, tbl->key_eq, tbl->hash, pkey, dev);
300}
301
250void neigh_table_init(int index, struct neigh_table *tbl); 302void neigh_table_init(int index, struct neigh_table *tbl);
251int neigh_table_clear(int index, struct neigh_table *tbl); 303int neigh_table_clear(int index, struct neigh_table *tbl);
252struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey, 304struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,