aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp.c
diff options
context:
space:
mode:
authorJason Xing <[email protected]>2025-03-17 12:03:13 +0000
committerJakub Kicinski <[email protected]>2025-03-25 11:27:19 +0000
commitf38805c5d26fe4af97837c10d58074a7496638bf (patch)
treed19c016a9c6069ab703e7c2d7d64abcd95952674 /net/ipv4/tcp.c
parentMerge branch 'mlxsw-add-vxlan-to-the-same-hardware-domain-as-physical-bridge-... (diff)
downloadkernel-f38805c5d26fe4af97837c10d58074a7496638bf.tar.gz
kernel-f38805c5d26fe4af97837c10d58074a7496638bf.zip
tcp: support TCP_RTO_MIN_US for set/getsockopt use
Support adjusting/reading RTO MIN for socket level by using set/getsockopt(). This new option has the same effect as TCP_BPF_RTO_MIN, which means it doesn't affect RTAX_RTO_MIN usage (by using ip route...). Considering that bpf option was implemented before this patch, so we need to use a standalone new option for pure tcp set/getsockopt() use. When the socket is created, its icsk_rto_min is set to the default value that is controlled by sysctl_tcp_rto_min_us. Then if application calls setsockopt() with TCP_RTO_MIN_US flag to pass a valid value, then icsk_rto_min will be overridden in jiffies unit. This patch adds WRITE_ONCE/READ_ONCE to avoid data-race around icsk_rto_min. Signed-off-by: Jason Xing <[email protected]> Reviewed-by: Eric Dumazet <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
Diffstat (limited to 'net/ipv4/tcp.c')
-rw-r--r--net/ipv4/tcp.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index fde56d28f586..a8a1370d642e 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -3352,7 +3352,7 @@ int tcp_disconnect(struct sock *sk, int flags)
icsk->icsk_probes_out = 0;
icsk->icsk_probes_tstamp = 0;
icsk->icsk_rto = TCP_TIMEOUT_INIT;
- icsk->icsk_rto_min = TCP_RTO_MIN;
+ WRITE_ONCE(icsk->icsk_rto_min, TCP_RTO_MIN);
icsk->icsk_delack_max = TCP_DELACK_MAX;
tp->snd_ssthresh = TCP_INFINITE_SSTHRESH;
tcp_snd_cwnd_set(tp, TCP_INIT_CWND);
@@ -3833,6 +3833,14 @@ int do_tcp_setsockopt(struct sock *sk, int level, int optname,
return -EINVAL;
WRITE_ONCE(inet_csk(sk)->icsk_rto_max, msecs_to_jiffies(val));
return 0;
+ case TCP_RTO_MIN_US: {
+ int rto_min = usecs_to_jiffies(val);
+
+ if (rto_min > TCP_RTO_MIN || rto_min < TCP_TIMEOUT_MIN)
+ return -EINVAL;
+ WRITE_ONCE(inet_csk(sk)->icsk_rto_min, rto_min);
+ return 0;
+ }
}
sockopt_lock_sock(sk);
@@ -4672,6 +4680,9 @@ zerocopy_rcv_out:
case TCP_RTO_MAX_MS:
val = jiffies_to_msecs(tcp_rto_max(sk));
break;
+ case TCP_RTO_MIN_US:
+ val = jiffies_to_usecs(READ_ONCE(inet_csk(sk)->icsk_rto_min));
+ break;
default:
return -ENOPROTOOPT;
}