aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/udp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/udp.c')
-rw-r--r--net/ipv4/udp.c25
1 files changed, 19 insertions, 6 deletions
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index ffc837643a04..af72de1c8690 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -138,13 +138,14 @@ static int udp_lib_lport_inuse(struct net *net, __u16 num,
138 sk_nulls_for_each(sk2, node, &hslot->head) 138 sk_nulls_for_each(sk2, node, &hslot->head)
139 if (net_eq(sock_net(sk2), net) && 139 if (net_eq(sock_net(sk2), net) &&
140 sk2 != sk && 140 sk2 != sk &&
141 (bitmap || sk2->sk_hash == num) && 141 (bitmap || udp_sk(sk2)->udp_port_hash == num) &&
142 (!sk2->sk_reuse || !sk->sk_reuse) && 142 (!sk2->sk_reuse || !sk->sk_reuse) &&
143 (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if 143 (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if
144 || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && 144 || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
145 (*saddr_comp)(sk, sk2)) { 145 (*saddr_comp)(sk, sk2)) {
146 if (bitmap) 146 if (bitmap)
147 __set_bit(sk2->sk_hash >> log, bitmap); 147 __set_bit(udp_sk(sk2)->udp_port_hash >> log,
148 bitmap);
148 else 149 else
149 return 1; 150 return 1;
150 } 151 }
@@ -215,7 +216,8 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum,
215 } 216 }
216found: 217found:
217 inet_sk(sk)->inet_num = snum; 218 inet_sk(sk)->inet_num = snum;
218 sk->sk_hash = snum; 219 udp_sk(sk)->udp_port_hash = snum;
220 udp_sk(sk)->udp_portaddr_hash ^= snum;
219 if (sk_unhashed(sk)) { 221 if (sk_unhashed(sk)) {
220 sk_nulls_add_node_rcu(sk, &hslot->head); 222 sk_nulls_add_node_rcu(sk, &hslot->head);
221 hslot->count++; 223 hslot->count++;
@@ -238,8 +240,19 @@ static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
238 inet1->inet_rcv_saddr == inet2->inet_rcv_saddr)); 240 inet1->inet_rcv_saddr == inet2->inet_rcv_saddr));
239} 241}
240 242
243static unsigned int udp4_portaddr_hash(struct net *net, __be32 saddr,
244 unsigned int port)
245{
246 return jhash_1word(saddr, net_hash_mix(net)) ^ port;
247}
248
241int udp_v4_get_port(struct sock *sk, unsigned short snum) 249int udp_v4_get_port(struct sock *sk, unsigned short snum)
242{ 250{
251 /* precompute partial secondary hash */
252 udp_sk(sk)->udp_portaddr_hash =
253 udp4_portaddr_hash(sock_net(sk),
254 inet_sk(sk)->inet_rcv_saddr,
255 0);
243 return udp_lib_get_port(sk, snum, ipv4_rcv_saddr_equal); 256 return udp_lib_get_port(sk, snum, ipv4_rcv_saddr_equal);
244} 257}
245 258
@@ -249,7 +262,7 @@ static inline int compute_score(struct sock *sk, struct net *net, __be32 saddr,
249{ 262{
250 int score = -1; 263 int score = -1;
251 264
252 if (net_eq(sock_net(sk), net) && sk->sk_hash == hnum && 265 if (net_eq(sock_net(sk), net) && udp_sk(sk)->udp_port_hash == hnum &&
253 !ipv6_only_sock(sk)) { 266 !ipv6_only_sock(sk)) {
254 struct inet_sock *inet = inet_sk(sk); 267 struct inet_sock *inet = inet_sk(sk);
255 268
@@ -360,7 +373,7 @@ static inline struct sock *udp_v4_mcast_next(struct net *net, struct sock *sk,
360 struct inet_sock *inet = inet_sk(s); 373 struct inet_sock *inet = inet_sk(s);
361 374
362 if (!net_eq(sock_net(s), net) || 375 if (!net_eq(sock_net(s), net) ||
363 s->sk_hash != hnum || 376 udp_sk(s)->udp_port_hash != hnum ||
364 (inet->inet_daddr && inet->inet_daddr != rmt_addr) || 377 (inet->inet_daddr && inet->inet_daddr != rmt_addr) ||
365 (inet->inet_dport != rmt_port && inet->inet_dport) || 378 (inet->inet_dport != rmt_port && inet->inet_dport) ||
366 (inet->inet_rcv_saddr && 379 (inet->inet_rcv_saddr &&
@@ -1050,7 +1063,7 @@ void udp_lib_unhash(struct sock *sk)
1050 if (sk_hashed(sk)) { 1063 if (sk_hashed(sk)) {
1051 struct udp_table *udptable = sk->sk_prot->h.udp_table; 1064 struct udp_table *udptable = sk->sk_prot->h.udp_table;
1052 struct udp_hslot *hslot = udp_hashslot(udptable, sock_net(sk), 1065 struct udp_hslot *hslot = udp_hashslot(udptable, sock_net(sk),
1053 sk->sk_hash); 1066 udp_sk(sk)->udp_port_hash);
1054 1067
1055 spin_lock_bh(&hslot->lock); 1068 spin_lock_bh(&hslot->lock);
1056 if (sk_nulls_del_node_init_rcu(sk)) { 1069 if (sk_nulls_del_node_init_rcu(sk)) {