Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 946f9eb2 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller
Browse files

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: default avatarEric Dumazet <edumazet@google.com>
Cc: Marcelo Ricardo Leitner <mleitner@redhat.com>
Cc: Flavio Leitner <fbl@redhat.com>
Acked-by: default avatarFlavio Leitner <fbl@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f5af1f57
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -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;

@@ -154,6 +163,11 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
				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