[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20240816153204.93787-1-kerneljasonxing@gmail.com>
Date: Fri, 16 Aug 2024 23:32:04 +0800
From: Jason Xing <kerneljasonxing@...il.com>
To: davem@...emloft.net,
edumazet@...gle.com,
kuba@...nel.org,
pabeni@...hat.com,
dsahern@...nel.org,
ncardwell@...gle.com
Cc: netdev@...r.kernel.org,
Jason Xing <kernelxing@...cent.com>
Subject: [PATCH net-next] tcp: change source port selection at bind() time
From: Jason Xing <kernelxing@...cent.com>
This is a follow-up patch to an eariler commit 207184853dbd ("tcp/dccp:
change source port selection at connect() time").
This patch extends the use of IP_LOCAL_PORT_RANGE option, so that we
don't need to iterate every two ports which means only favouring odd
number like the old days before 2016, which can be good for some
users who want to keep in consistency with IP_LOCAL_PORT_RANGE in
connect().
Signed-off-by: Jason Xing <kernelxing@...cent.com>
---
net/ipv4/inet_connection_sock.c | 22 +++++++++++++---------
1 file changed, 13 insertions(+), 9 deletions(-)
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 64d07b842e73..6eb509832c90 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -333,19 +333,20 @@ inet_csk_find_open_port(const struct sock *sk, struct inet_bind_bucket **tb_ret,
struct inet_bind_hashbucket **head2_ret, int *port_ret)
{
struct inet_hashinfo *hinfo = tcp_or_dccp_get_hashinfo(sk);
- int i, low, high, attempt_half, port, l3mdev;
+ int i, low, high, attempt_half, port, l3mdev, step;
struct inet_bind_hashbucket *head, *head2;
+ bool local_ports, relax = false;
struct net *net = sock_net(sk);
struct inet_bind2_bucket *tb2;
struct inet_bind_bucket *tb;
u32 remaining, offset;
- bool relax = false;
l3mdev = inet_sk_bound_l3mdev(sk);
ports_exhausted:
attempt_half = (sk->sk_reuse == SK_CAN_REUSE) ? 1 : 0;
other_half_scan:
- inet_sk_get_local_port_range(sk, &low, &high);
+ local_ports = inet_sk_get_local_port_range(sk, &low, &high);
+ step = local_ports ? 1 : 2;
high++; /* [32768, 60999] -> [32768, 61000[ */
if (high - low < 4)
attempt_half = 0;
@@ -358,18 +359,19 @@ inet_csk_find_open_port(const struct sock *sk, struct inet_bind_bucket **tb_ret,
low = half;
}
remaining = high - low;
- if (likely(remaining > 1))
+ if (!local_ports && remaining > 1)
remaining &= ~1U;
offset = get_random_u32_below(remaining);
/* __inet_hash_connect() favors ports having @low parity
* We do the opposite to not pollute connect() users.
*/
- offset |= 1U;
+ if (!local_ports)
+ offset |= 1U;
other_parity_scan:
port = low + offset;
- for (i = 0; i < remaining; i += 2, port += 2) {
+ for (i = 0; i < remaining; i += step, port += step) {
if (unlikely(port >= high))
port -= remaining;
if (inet_is_local_reserved_port(net, port))
@@ -400,9 +402,11 @@ inet_csk_find_open_port(const struct sock *sk, struct inet_bind_bucket **tb_ret,
cond_resched();
}
- offset--;
- if (!(offset & 1))
- goto other_parity_scan;
+ if (!local_ports) {
+ offset--;
+ if (!(offset & 1))
+ goto other_parity_scan;
+ }
if (attempt_half == 1) {
/* OK we now try the upper half of the range */
--
2.37.3
Powered by blists - more mailing lists