diff options
| author | Eric W. Biederman <ebiederm@xmission.com> | 2015-03-03 18:10:44 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2015-03-04 00:23:23 -0500 |
| commit | 60395a20ffd74166ea373ea91418d6f98fa7fdfb (patch) | |
| tree | c4ed2b51ec4f179a48018d86660e6f2bb5b8bd81 /include | |
| parent | 2f56f6be47dbc6883e28107edfe2f9f98f4d5a24 (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')
| -rw-r--r-- | include/net/arp.h | 19 | ||||
| -rw-r--r-- | include/net/ndisc.h | 19 | ||||
| -rw-r--r-- | include/net/neighbour.h | 52 |
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 | ||
| 10 | extern struct neigh_table arp_tbl; | 10 | extern struct neigh_table arp_tbl; |
| 11 | 11 | ||
| 12 | static inline u32 arp_hashfn(u32 key, const struct net_device *dev, u32 hash_rnd) | 12 | static 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 | ||
| 19 | static inline struct neighbour *__ipv4_neigh_lookup_noref(struct net_device *dev, u32 key) | 20 | static 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 | ||
| 36 | static inline struct neighbour *__ipv4_neigh_lookup(struct net_device *dev, u32 key) | 25 | static 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 | ||
| 157 | static inline struct neighbour *__ipv6_neigh_lookup_noref(struct net_device *dev, const void *pkey) | 157 | static 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 | ||
| 179 | static inline struct neighbour *__ipv6_neigh_lookup(struct net_device *dev, const void *pkey) | 162 | static 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 | |||
| 252 | static 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 | |||
| 257 | static 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 | |||
| 262 | static 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 | |||
| 271 | static 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 | |||
| 295 | static 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 | |||
| 250 | void neigh_table_init(int index, struct neigh_table *tbl); | 302 | void neigh_table_init(int index, struct neigh_table *tbl); |
| 251 | int neigh_table_clear(int index, struct neigh_table *tbl); | 303 | int neigh_table_clear(int index, struct neigh_table *tbl); |
| 252 | struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey, | 304 | struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey, |
