]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/ipv4/inet_connection_sock.c
netfilter: fix netns dependencies with conntrack templates
[karo-tx-linux.git] / net / ipv4 / inet_connection_sock.c
index 8976ca423a074447f0d857973ab9ea3bc6bbca7c..60021d0d9326ac691dcef21e1f9c20de5f8fe7c6 100644 (file)
@@ -99,6 +99,7 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
        struct net *net = sock_net(sk);
        int smallest_size = -1, smallest_rover;
        kuid_t uid = sock_i_uid(sk);
+       int attempt_half = (sk->sk_reuse == SK_CAN_REUSE) ? 1 : 0;
 
        local_bh_disable();
        if (!snum) {
@@ -106,6 +107,14 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
 
 again:
                inet_get_local_port_range(net, &low, &high);
+               if (attempt_half) {
+                       int half = low + ((high - low) >> 1);
+
+                       if (attempt_half == 1)
+                               high = half;
+                       else
+                               low = half;
+               }
                remaining = (high - low) + 1;
                smallest_rover = rover = prandom_u32() % remaining + low;
 
@@ -127,11 +136,6 @@ again:
                                            (tb->num_owners < smallest_size || smallest_size == -1)) {
                                                smallest_size = tb->num_owners;
                                                smallest_rover = rover;
-                                               if (atomic_read(&hashinfo->bsockets) > (high - low) + 1 &&
-                                                   !inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb, false)) {
-                                                       snum = smallest_rover;
-                                                       goto tb_found;
-                                               }
                                        }
                                        if (!inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb, false)) {
                                                snum = rover;
@@ -159,6 +163,11 @@ again:
                                snum = smallest_rover;
                                goto have_snum;
                        }
+                       if (attempt_half == 1) {
+                               /* OK we now try the upper half of the range */
+                               attempt_half = 2;
+                               goto again;
+                       }
                        goto fail;
                }
                /* OK, here is the one we will use.  HEAD is