aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/udp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/udp.c')
-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)