aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv4/udp.c56
1 files changed, 12 insertions, 44 deletions
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 85f8e8e10b1b..67d8430b4a2a 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -155,55 +155,23 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum,
155 write_lock_bh(&udp_hash_lock); 155 write_lock_bh(&udp_hash_lock);
156 156
157 if (!snum) { 157 if (!snum) {
158 int i, low, high, remaining; 158 int low, high, remaining;
159 unsigned rover, best, best_size_so_far; 159 unsigned rand;
160 unsigned short first;
160 161
161 inet_get_local_port_range(&low, &high); 162 inet_get_local_port_range(&low, &high);
162 remaining = (high - low) + 1; 163 remaining = (high - low) + 1;
163 164
164 best_size_so_far = UINT_MAX; 165 rand = net_random();
165 best = rover = net_random() % remaining + low; 166 snum = first = rand % remaining + low;
166 167 rand |= 1;
167 /* 1st pass: look for empty (or shortest) hash chain */ 168 while (__udp_lib_lport_inuse(net, snum, udptable)) {
168 for (i = 0; i < UDP_HTABLE_SIZE; i++) { 169 do {
169 int size = 0; 170 snum = snum + rand;
170 171 } while (snum < low || snum > high);
171 head = &udptable[udp_hashfn(net, rover)]; 172 if (snum == first)
172 if (hlist_empty(head)) 173 goto fail;
173 goto gotit;
174
175 sk_for_each(sk2, node, head) {
176 if (++size >= best_size_so_far)
177 goto next;
178 }
179 best_size_so_far = size;
180 best = rover;
181 next:
182 /* fold back if end of range */
183 if (++rover > high)
184 rover = low + ((rover - low)
185 & (UDP_HTABLE_SIZE - 1));
186
187
188 }
189
190 /* 2nd pass: find hole in shortest hash chain */
191 rover = best;
192 for (i = 0; i < (1 << 16) / UDP_HTABLE_SIZE; i++) {
193 if (! __udp_lib_lport_inuse(net, rover, udptable))
194 goto gotit;
195 rover += UDP_HTABLE_SIZE;
196 if (rover > high)
197 rover = low + ((rover - low)
198 & (UDP_HTABLE_SIZE - 1));
199 } 174 }
200
201
202 /* All ports in use! */
203 goto fail;
204
205gotit:
206 snum = rover;
207 } else { 175 } else {
208 head = &udptable[udp_hashfn(net, snum)]; 176 head = &udptable[udp_hashfn(net, snum)];
209 177