aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2012-07-18 04:11:12 -0400
committerDavid S. Miller <davem@davemloft.net>2012-07-18 14:28:46 -0400
commitddbe503203855939946430e39bae58de11b70b69 (patch)
tree1605a8d3b14a92819eb8ed47ae5a84c1b66e12f8 /net/sunrpc
parentdc9059512c09d09b99de6cd3a8bc842507934cbb (diff)
ipv6: add ipv6_addr_hash() helper
Introduce ipv6_addr_hash() helper doing a XOR on all bits of an IPv6 address, with an optimized x86_64 version. Use it in flow dissector, as suggested by Andrew McGregor, to reduce hash collision probabilities in fq_codel (and other users of flow dissector) Use it in ip6_tunnel.c and use more bit shuffling, as suggested by David Laight, as existing hash was ignoring most of them. Use it in sunrpc and use more bit shuffling, using hash_32(). Use it in net/ipv6/addrconf.c, using hash_32() as well. As a cleanup, use it in net/ipv4/tcp_metrics.c Signed-off-by: Eric Dumazet <edumazet@google.com> Reported-by: Andrew McGregor <andrewmcgr@gmail.com> Cc: Dave Taht <dave.taht@gmail.com> Cc: Tom Herbert <therbert@google.com> Cc: David Laight <David.Laight@ACULAB.COM> Cc: Joe Perches <joe@perches.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sunrpc')
-rw-r--r--net/sunrpc/svcauth_unix.c22
1 files changed, 4 insertions, 18 deletions
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 2777fa896645..4d0129203733 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -104,23 +104,9 @@ static void ip_map_put(struct kref *kref)
104 kfree(im); 104 kfree(im);
105} 105}
106 106
107#if IP_HASHBITS == 8 107static inline int hash_ip6(const struct in6_addr *ip)
108/* hash_long on a 64 bit machine is currently REALLY BAD for
109 * IP addresses in reverse-endian (i.e. on a little-endian machine).
110 * So use a trivial but reliable hash instead
111 */
112static inline int hash_ip(__be32 ip)
113{
114 int hash = (__force u32)ip ^ ((__force u32)ip>>16);
115 return (hash ^ (hash>>8)) & 0xff;
116}
117#endif
118static inline int hash_ip6(struct in6_addr ip)
119{ 108{
120 return (hash_ip(ip.s6_addr32[0]) ^ 109 return hash_32(ipv6_addr_hash(ip), IP_HASHBITS);
121 hash_ip(ip.s6_addr32[1]) ^
122 hash_ip(ip.s6_addr32[2]) ^
123 hash_ip(ip.s6_addr32[3]));
124} 110}
125static int ip_map_match(struct cache_head *corig, struct cache_head *cnew) 111static int ip_map_match(struct cache_head *corig, struct cache_head *cnew)
126{ 112{
@@ -301,7 +287,7 @@ static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class,
301 ip.m_addr = *addr; 287 ip.m_addr = *addr;
302 ch = sunrpc_cache_lookup(cd, &ip.h, 288 ch = sunrpc_cache_lookup(cd, &ip.h,
303 hash_str(class, IP_HASHBITS) ^ 289 hash_str(class, IP_HASHBITS) ^
304 hash_ip6(*addr)); 290 hash_ip6(addr));
305 291
306 if (ch) 292 if (ch)
307 return container_of(ch, struct ip_map, h); 293 return container_of(ch, struct ip_map, h);
@@ -331,7 +317,7 @@ static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm,
331 ip.h.expiry_time = expiry; 317 ip.h.expiry_time = expiry;
332 ch = sunrpc_cache_update(cd, &ip.h, &ipm->h, 318 ch = sunrpc_cache_update(cd, &ip.h, &ipm->h,
333 hash_str(ipm->m_class, IP_HASHBITS) ^ 319 hash_str(ipm->m_class, IP_HASHBITS) ^
334 hash_ip6(ipm->m_addr)); 320 hash_ip6(&ipm->m_addr));
335 if (!ch) 321 if (!ch)
336 return -ENOMEM; 322 return -ENOMEM;
337 cache_put(ch, cd); 323 cache_put(ch, cd);