aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2009-11-08 05:17:30 -0500
committerDavid S. Miller <davem@davemloft.net>2009-11-08 23:53:05 -0500
commitd4cada4ae1c012815f95fa507eb86a0ae9d607d7 (patch)
tree23cdfb3763c9140ae095bf8095c3e6b16f7b48f3 /net/ipv6
parentfdcc8aa953a1123a289791dd192090651036d593 (diff)
udp: split sk_hash into two u16 hashes
Union sk_hash with two u16 hashes for udp (no extra memory taken) One 16 bits hash on (local port) value (the previous udp 'hash') One 16 bits hash on (local address, local port) values, initialized but not yet used. This second hash is using jenkin hash for better distribution. Because the 'port' is xored later, a partial hash is performed on local address + net_hash_mix(net) Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/udp.c27
1 files changed, 25 insertions, 2 deletions
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 5bc7cdbf030a..1e5fadd997b7 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -81,8 +81,30 @@ int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2)
81 return 0; 81 return 0;
82} 82}
83 83
84static unsigned int udp6_portaddr_hash(struct net *net,
85 const struct in6_addr *addr6,
86 unsigned int port)
87{
88 unsigned int hash, mix = net_hash_mix(net);
89
90 if (ipv6_addr_any(addr6))
91 hash = jhash_1word(0, mix);
92 else if (ipv6_addr_type(addr6) == IPV6_ADDR_MAPPED)
93 hash = jhash_1word(addr6->s6_addr32[3], mix);
94 else
95 hash = jhash2(addr6->s6_addr32, 4, mix);
96
97 return hash ^ port;
98}
99
100
84int udp_v6_get_port(struct sock *sk, unsigned short snum) 101int udp_v6_get_port(struct sock *sk, unsigned short snum)
85{ 102{
103 /* precompute partial secondary hash */
104 udp_sk(sk)->udp_portaddr_hash =
105 udp6_portaddr_hash(sock_net(sk),
106 &inet6_sk(sk)->rcv_saddr,
107 0);
86 return udp_lib_get_port(sk, snum, ipv6_rcv_saddr_equal); 108 return udp_lib_get_port(sk, snum, ipv6_rcv_saddr_equal);
87} 109}
88 110
@@ -94,7 +116,7 @@ static inline int compute_score(struct sock *sk, struct net *net,
94{ 116{
95 int score = -1; 117 int score = -1;
96 118
97 if (net_eq(sock_net(sk), net) && sk->sk_hash == hnum && 119 if (net_eq(sock_net(sk), net) && udp_sk(sk)->udp_port_hash == hnum &&
98 sk->sk_family == PF_INET6) { 120 sk->sk_family == PF_INET6) {
99 struct ipv6_pinfo *np = inet6_sk(sk); 121 struct ipv6_pinfo *np = inet6_sk(sk);
100 struct inet_sock *inet = inet_sk(sk); 122 struct inet_sock *inet = inet_sk(sk);
@@ -415,7 +437,8 @@ static struct sock *udp_v6_mcast_next(struct net *net, struct sock *sk,
415 if (!net_eq(sock_net(s), net)) 437 if (!net_eq(sock_net(s), net))
416 continue; 438 continue;
417 439
418 if (s->sk_hash == num && s->sk_family == PF_INET6) { 440 if (udp_sk(s)->udp_port_hash == num &&
441 s->sk_family == PF_INET6) {
419 struct ipv6_pinfo *np = inet6_sk(s); 442 struct ipv6_pinfo *np = inet6_sk(s);
420 if (inet->inet_dport) { 443 if (inet->inet_dport) {
421 if (inet->inet_dport != rmt_port) 444 if (inet->inet_dport != rmt_port)