Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'tcp-clean-up-syn-ack-rto-code-and-apply-max-rto'

Kuniyuki Iwashima says:

====================
tcp: Clean up SYN+ACK RTO code and apply max RTO.

Patch 1 - 4 are misc cleanup.

Patch 5 applies max RTO to non-TFO SYN+ACK.

Patch 6 adds a test for max RTO of SYN+ACK.
====================

Link: https://patch.msgid.link/20251106003357.273403-1-kuniyu@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+81 -36
+1 -10
include/net/inet_connection_sock.h
··· 267 267 struct sock *inet_csk_reqsk_queue_add(struct sock *sk, 268 268 struct request_sock *req, 269 269 struct sock *child); 270 - bool inet_csk_reqsk_queue_hash_add(struct sock *sk, struct request_sock *req, 271 - unsigned long timeout); 270 + bool inet_csk_reqsk_queue_hash_add(struct sock *sk, struct request_sock *req); 272 271 struct sock *inet_csk_complete_hashdance(struct sock *sk, struct sock *child, 273 272 struct request_sock *req, 274 273 bool own_req); ··· 289 290 290 291 bool inet_csk_reqsk_queue_drop(struct sock *sk, struct request_sock *req); 291 292 void inet_csk_reqsk_queue_drop_and_put(struct sock *sk, struct request_sock *req); 292 - 293 - static inline unsigned long 294 - reqsk_timeout(struct request_sock *req, unsigned long max_timeout) 295 - { 296 - u64 timeout = (u64)req->timeout << req->num_timeout; 297 - 298 - return (unsigned long)min_t(u64, timeout, max_timeout); 299 - } 300 293 301 294 void inet_csk_destroy_sock(struct sock *sk); 302 295 void inet_csk_prepare_for_destroy_sock(struct sock *sk);
-1
include/net/request_sock.h
··· 36 36 struct sk_buff *skb, 37 37 enum sk_rst_reason reason); 38 38 void (*destructor)(struct request_sock *req); 39 - void (*syn_ack_timeout)(const struct request_sock *req); 40 39 }; 41 40 42 41 struct saved_syn {
+8
include/net/tcp.h
··· 841 841 return usecs_to_jiffies((tp->srtt_us >> 3) + tp->rttvar_us); 842 842 } 843 843 844 + static inline unsigned long tcp_reqsk_timeout(struct request_sock *req) 845 + { 846 + u64 timeout = (u64)req->timeout << req->num_timeout; 847 + 848 + return (unsigned long)min_t(u64, timeout, 849 + tcp_rto_max(req->rsk_listener)); 850 + } 851 + 844 852 u32 tcp_delack_max(const struct sock *sk); 845 853 846 854 /* Compute the actual rto_min value */
+9 -10
net/ipv4/inet_connection_sock.c
··· 885 885 sk_tx_queue_clear(req_to_sk(req)); 886 886 req->saved_syn = NULL; 887 887 req->syncookie = 0; 888 - req->timeout = 0; 889 888 req->num_timeout = 0; 890 889 req->num_retrans = 0; 891 890 req->sk = NULL; ··· 912 913 ireq->ireq_state = TCP_NEW_SYN_RECV; 913 914 write_pnet(&ireq->ireq_net, sock_net(sk_listener)); 914 915 ireq->ireq_family = sk_listener->sk_family; 915 - req->timeout = TCP_TIMEOUT_INIT; 916 916 } 917 917 918 918 return req; ··· 1094 1096 young <<= 1; 1095 1097 } 1096 1098 } 1099 + 1097 1100 syn_ack_recalc(req, max_syn_ack_retries, READ_ONCE(queue->rskq_defer_accept), 1098 1101 &expire, &resend); 1099 - req->rsk_ops->syn_ack_timeout(req); 1102 + tcp_syn_ack_timeout(req); 1103 + 1100 1104 if (!expire && 1101 1105 (!resend || 1102 1106 !tcp_rtx_synack(sk_listener, req) || 1103 1107 inet_rsk(req)->acked)) { 1104 1108 if (req->num_timeout++ == 0) 1105 1109 atomic_dec(&queue->young); 1106 - mod_timer(&req->rsk_timer, jiffies + reqsk_timeout(req, TCP_RTO_MAX)); 1110 + mod_timer(&req->rsk_timer, jiffies + tcp_reqsk_timeout(req)); 1107 1111 1108 1112 if (!nreq) 1109 1113 return; ··· 1142 1142 reqsk_put(oreq); 1143 1143 } 1144 1144 1145 - static bool reqsk_queue_hash_req(struct request_sock *req, 1146 - unsigned long timeout) 1145 + static bool reqsk_queue_hash_req(struct request_sock *req) 1147 1146 { 1148 1147 bool found_dup_sk = false; 1149 1148 ··· 1150 1151 return false; 1151 1152 1152 1153 /* The timer needs to be setup after a successful insertion. */ 1154 + req->timeout = tcp_timeout_init((struct sock *)req); 1153 1155 timer_setup(&req->rsk_timer, reqsk_timer_handler, TIMER_PINNED); 1154 - mod_timer(&req->rsk_timer, jiffies + timeout); 1156 + mod_timer(&req->rsk_timer, jiffies + req->timeout); 1155 1157 1156 1158 /* before letting lookups find us, make sure all req fields 1157 1159 * are committed to memory and refcnt initialized. ··· 1162 1162 return true; 1163 1163 } 1164 1164 1165 - bool inet_csk_reqsk_queue_hash_add(struct sock *sk, struct request_sock *req, 1166 - unsigned long timeout) 1165 + bool inet_csk_reqsk_queue_hash_add(struct sock *sk, struct request_sock *req) 1167 1166 { 1168 - if (!reqsk_queue_hash_req(req, timeout)) 1167 + if (!reqsk_queue_hash_req(req)) 1169 1168 return false; 1170 1169 1171 1170 inet_csk_reqsk_queue_added(sk);
+5 -9
net/ipv4/tcp_input.c
··· 7531 7531 sock_put(fastopen_sk); 7532 7532 } else { 7533 7533 tcp_rsk(req)->tfo_listener = false; 7534 - if (!want_cookie) { 7535 - req->timeout = tcp_timeout_init((struct sock *)req); 7536 - if (unlikely(!inet_csk_reqsk_queue_hash_add(sk, req, 7537 - req->timeout))) { 7538 - reqsk_free(req); 7539 - dst_release(dst); 7540 - return 0; 7541 - } 7542 - 7534 + if (!want_cookie && 7535 + unlikely(!inet_csk_reqsk_queue_hash_add(sk, req))) { 7536 + reqsk_free(req); 7537 + dst_release(dst); 7538 + return 0; 7543 7539 } 7544 7540 af_ops->send_synack(sk, dst, &fl, req, &foc, 7545 7541 !want_cookie ? TCP_SYNACK_NORMAL :
-1
net/ipv4/tcp_ipv4.c
··· 1660 1660 .send_ack = tcp_v4_reqsk_send_ack, 1661 1661 .destructor = tcp_v4_reqsk_destructor, 1662 1662 .send_reset = tcp_v4_send_reset, 1663 - .syn_ack_timeout = tcp_syn_ack_timeout, 1664 1663 }; 1665 1664 1666 1665 const struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = {
+3 -2
net/ipv4/tcp_minisocks.c
··· 714 714 * it can be estimated (approximately) 715 715 * from another data. 716 716 */ 717 - tmp_opt.ts_recent_stamp = ktime_get_seconds() - reqsk_timeout(req, TCP_RTO_MAX) / HZ; 717 + tmp_opt.ts_recent_stamp = ktime_get_seconds() - 718 + tcp_reqsk_timeout(req) / HZ; 718 719 paws_reject = tcp_paws_reject(&tmp_opt, th->rst); 719 720 } 720 721 } ··· 754 753 !tcp_rtx_synack(sk, req)) { 755 754 unsigned long expires = jiffies; 756 755 757 - expires += reqsk_timeout(req, TCP_RTO_MAX); 756 + expires += tcp_reqsk_timeout(req); 758 757 if (!fastopen) 759 758 mod_timer_pending(&req->rsk_timer, expires); 760 759 else
+1 -2
net/ipv4/tcp_timer.c
··· 458 458 struct tcp_sock *tp = tcp_sk(sk); 459 459 int max_retries; 460 460 461 - req->rsk_ops->syn_ack_timeout(req); 461 + tcp_syn_ack_timeout(req); 462 462 463 463 /* Add one more retry for fastopen. 464 464 * Paired with WRITE_ONCE() in tcp_sock_set_syncnt() ··· 752 752 753 753 __NET_INC_STATS(net, LINUX_MIB_TCPTIMEOUTS); 754 754 } 755 - EXPORT_IPV6_MOD(tcp_syn_ack_timeout); 756 755 757 756 void tcp_reset_keepalive_timer(struct sock *sk, unsigned long len) 758 757 {
-1
net/ipv6/tcp_ipv6.c
··· 796 796 .send_ack = tcp_v6_reqsk_send_ack, 797 797 .destructor = tcp_v6_reqsk_destructor, 798 798 .send_reset = tcp_v6_send_reset, 799 - .syn_ack_timeout = tcp_syn_ack_timeout, 800 799 }; 801 800 802 801 const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = {
+54
tools/testing/selftests/net/packetdrill/tcp_rto_synack_rto_max.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // 3 + // Test SYN+ACK RTX with 1s RTO. 4 + // 5 + `./defaults.sh 6 + ./set_sysctls.py /proc/sys/net/ipv4/tcp_rto_max_ms=1000` 7 + 8 + // 9 + // Test 1: TFO SYN+ACK 10 + // 11 + 0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3 12 + +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 13 + +0 bind(3, ..., ...) = 0 14 + +0 listen(3, 1) = 0 15 + +0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0 16 + 17 + +0 < S 0:10(10) win 1000 <mss 1460,sackOK,nop,nop,FO TFO_COOKIE,nop,nop> 18 + +0 > S. 0:0(0) ack 11 <mss 1460,nop,nop,sackOK> 19 + 20 + // RTO must be capped to 1s 21 + +1 > S. 0:0(0) ack 11 <mss 1460,nop,nop,sackOK> 22 + +1 > S. 0:0(0) ack 11 <mss 1460,nop,nop,sackOK> 23 + +1 > S. 0:0(0) ack 11 <mss 1460,nop,nop,sackOK> 24 + 25 + +0 < . 11:11(0) ack 1 win 1000 <mss 1460,nop,nop,sackOK> 26 + +0 accept(3, ..., ...) = 4 27 + +0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) != 0, tcpi_options }% 28 + 29 + +0 close(4) = 0 30 + +0 close(3) = 0 31 + 32 + 33 + // 34 + // Test 2: non-TFO SYN+ACK 35 + // 36 + +0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3 37 + +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 38 + +0 bind(3, ..., ...) = 0 39 + +0 listen(3, 1) = 0 40 + 41 + +0 < S 0:0(0) win 1000 <mss 1460,sackOK,nop,nop> 42 + +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK> 43 + 44 + // RTO must be capped to 1s 45 + +1 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK> 46 + +1 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK> 47 + +1 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK> 48 + 49 + +0 < . 1:1(0) ack 1 win 1000 <mss 1460,nop,nop,sackOK> 50 + +0 accept(3, ..., ...) = 4 51 + +0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) == 0, tcpi_options }% 52 + 53 + +0 close(4) = 0 54 + +0 close(3) = 0