tcp: improve REUSEADDR/NOREUSEADDR cohabitation
inet_csk_get_port() randomization effort tends to spread sockets on all the available range (ip_local_port_range) This is unfortunate because SO_REUSEADDR sockets have less requirements than non SO_REUSEADDR ones. If an application uses SO_REUSEADDR hint, it is to try to allow source ports being shared. So instead of picking a random port number in ip_local_port_range, lets try first in first half of the range. This gives more chances to use upper half of the range for the sockets with strong requirements (not using SO_REUSEADDR) Note this patch does not add a new sysctl, and only changes the way we try to pick port number. Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Marcelo Ricardo Leitner <mleitner@redhat.com> Cc: Flavio Leitner <fbl@redhat.com> Acked-by: Flavio Leitner <fbl@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
f5af1f57a2
commit
946f9eb226
|
@ -99,6 +99,7 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
|
||||||
struct net *net = sock_net(sk);
|
struct net *net = sock_net(sk);
|
||||||
int smallest_size = -1, smallest_rover;
|
int smallest_size = -1, smallest_rover;
|
||||||
kuid_t uid = sock_i_uid(sk);
|
kuid_t uid = sock_i_uid(sk);
|
||||||
|
int attempt_half = (sk->sk_reuse == SK_CAN_REUSE) ? 1 : 0;
|
||||||
|
|
||||||
local_bh_disable();
|
local_bh_disable();
|
||||||
if (!snum) {
|
if (!snum) {
|
||||||
|
@ -106,6 +107,14 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
|
||||||
|
|
||||||
again:
|
again:
|
||||||
inet_get_local_port_range(net, &low, &high);
|
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;
|
remaining = (high - low) + 1;
|
||||||
smallest_rover = rover = prandom_u32() % remaining + low;
|
smallest_rover = rover = prandom_u32() % remaining + low;
|
||||||
|
|
||||||
|
@ -154,6 +163,11 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
|
||||||
snum = smallest_rover;
|
snum = smallest_rover;
|
||||||
goto have_snum;
|
goto have_snum;
|
||||||
}
|
}
|
||||||
|
if (attempt_half == 1) {
|
||||||
|
/* OK we now try the upper half of the range */
|
||||||
|
attempt_half = 2;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
/* OK, here is the one we will use. HEAD is
|
/* OK, here is the one we will use. HEAD is
|
||||||
|
|
Loading…
Reference in New Issue