diff options
| author | Eric Dumazet <edumazet@google.com> | 2012-07-18 08:11:12 +0000 | 
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2012-07-18 11:28:46 -0700 | 
| commit | ddbe503203855939946430e39bae58de11b70b69 (patch) | |
| tree | 1605a8d3b14a92819eb8ed47ae5a84c1b66e12f8 /net/sunrpc/svcauth_unix.c | |
| parent | dc9059512c09d09b99de6cd3a8bc842507934cbb (diff) | |
| download | olio-linux-3.10-ddbe503203855939946430e39bae58de11b70b69.tar.xz olio-linux-3.10-ddbe503203855939946430e39bae58de11b70b69.zip  | |
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/svcauth_unix.c')
| -rw-r--r-- | net/sunrpc/svcauth_unix.c | 22 | 
1 files changed, 4 insertions, 18 deletions
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 2777fa89664..4d012920373 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)  	kfree(im);  } -#if IP_HASHBITS == 8 -/* hash_long on a 64 bit machine is currently REALLY BAD for - * IP addresses in reverse-endian (i.e. on a little-endian machine). - * So use a trivial but reliable hash instead - */ -static inline int hash_ip(__be32 ip) -{ -	int hash = (__force u32)ip ^ ((__force u32)ip>>16); -	return (hash ^ (hash>>8)) & 0xff; -} -#endif -static inline int hash_ip6(struct in6_addr ip) +static inline int hash_ip6(const struct in6_addr *ip)  { -	return (hash_ip(ip.s6_addr32[0]) ^ -		hash_ip(ip.s6_addr32[1]) ^ -		hash_ip(ip.s6_addr32[2]) ^ -		hash_ip(ip.s6_addr32[3])); +	return hash_32(ipv6_addr_hash(ip), IP_HASHBITS);  }  static int ip_map_match(struct cache_head *corig, struct cache_head *cnew)  { @@ -301,7 +287,7 @@ static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class,  	ip.m_addr = *addr;  	ch = sunrpc_cache_lookup(cd, &ip.h,  				 hash_str(class, IP_HASHBITS) ^ -				 hash_ip6(*addr)); +				 hash_ip6(addr));  	if (ch)  		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,  	ip.h.expiry_time = expiry;  	ch = sunrpc_cache_update(cd, &ip.h, &ipm->h,  				 hash_str(ipm->m_class, IP_HASHBITS) ^ -				 hash_ip6(ipm->m_addr)); +				 hash_ip6(&ipm->m_addr));  	if (!ch)  		return -ENOMEM;  	cache_put(ch, cd);  |