tcp: provide better locality for retransmit timer
Subsystems (9)
cover tcp: provide better locality for retransmit timer
TCP stack uses three timers per flow, currently spread this way:
- sk->sk_timer : keepalive timer
- icsk->icsk_retransmit_timer : retransmit timer
- icsk->icsk_delack_timer : delayed ack timer
This series moves the retransmit timer to sk->sk_timer location, to increase data locality in TX paths.
keepalive timers are not often used, this change should be neutral for them.
After the series we have following fields:
- sk->tcp_retransmit_timer : retransmit timer, in sock_write_tx group
- icsk->icsk_delack_timer : delayed ack timer
- icsk->icsk_keepalive_timer : keepalive timer
Moving icsk_delack_timer in a beter location would also be welcomed.
Eric Dumazet (4):
tcp: rename icsk_timeout() to tcp_timeout_expires()
net: move sk_dst_pending_confirm and sk_pacing_status to sock_read_tx
group
tcp: introduce icsk->icsk_keepalive_timer
tcp: remove icsk->icsk_retransmit_timer
.../net_cachelines/inet_connection_sock.rst | 2 +- include/net/inet_connection_sock.h | 20 ++++++++------ include/net/sock.h | 13 ++++++--- net/core/sock.c | 4 +-- net/ipv4/inet_connection_sock.c | 12 ++++----- net/ipv4/inet_diag.c | 8 +++--- net/ipv4/tcp_ipv4.c | 8 +++--- net/ipv4/tcp_timer.c | 23 ++++++++-------- net/ipv6/tcp_ipv6.c | 8 +++--- net/mptcp/protocol.c | 27 +++++++++---------- net/mptcp/protocol.h | 2 +- .../selftests/bpf/progs/bpf_iter_tcp4.c | 8 +++--- .../selftests/bpf/progs/bpf_iter_tcp6.c | 8 +++--- 13 files changed, 74 insertions(+), 69 deletions(-)
Signature · 1 line
2.52.0.460.gd25c4c69ec-goog
PATCH 1/4 tcp: rename icsk_timeout() to tcp_timeout_expires()
In preparation of sk->tcp_timeout_timer introduction, rename icsk_timeout() helper and change its argument to plain 'const struct sock *sk'.
--- include/net/inet_connection_sock.h | 5 ++--- net/ipv4/inet_diag.c | 4 ++-- net/ipv4/tcp_ipv4.c | 4 ++-- net/ipv4/tcp_timer.c | 6 +++--- net/ipv6/tcp_ipv6.c | 4 ++-- net/mptcp/protocol.c | 2 +- 6 files changed, 12 insertions(+), 13 deletions(-)
include/net/inet_connection_sock.h +2 -3
@@ -184,10 +184,9 @@ static inline void inet_csk_delack_init(struct sock *sk)memset (&inet_csk (sk)->icsk_ack,0 ,sizeof (inet_csk (sk)->icsk_ack)); } -static inline unsigned long -icsk_timeout (const struct inet_connection_sock *icsk) +static inline unsigned long tcp_timeout_expires (const struct sock *sk) { -return READ_ONCE (icsk->icsk_retransmit_timer.expires); +return READ_ONCE (inet_csk (sk)->icsk_retransmit_timer.expires); } static inline unsigned long
net/ipv4/inet_diag.c +2 -2
@@ -287,12 +287,12 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, r->idiag_timer =1 ; r->idiag_retrans =READ_ONCE (icsk->icsk_retransmits); r->idiag_expires = -jiffies_delta_to_msecs (icsk_timeout (icsk) - jiffies); +jiffies_delta_to_msecs (tcp_timeout_expires (sk) - jiffies); }else if (icsk_pending ==ICSK_TIME_PROBE0 ) { r->idiag_timer =4 ; r->idiag_retrans =READ_ONCE (icsk->icsk_probes_out); r->idiag_expires = -jiffies_delta_to_msecs (icsk_timeout (icsk) - jiffies); +jiffies_delta_to_msecs (tcp_timeout_expires (sk) - jiffies); }else if (timer_pending (&sk->sk_timer)) { r->idiag_timer =2 ; r->idiag_retrans =READ_ONCE (icsk->icsk_probes_out);
net/ipv4/tcp_ipv4.c +2 -2
@@ -2869,10 +2869,10 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i) icsk_pending == ICSK_TIME_REO_TIMEOUT || icsk_pending == ICSK_TIME_LOSS_PROBE) { timer_active =1 ; - timer_expires =icsk_timeout (icsk); + timer_expires =tcp_timeout_expires (sk); } else if (icsk_pending == ICSK_TIME_PROBE0) { timer_active =4 ; - timer_expires =icsk_timeout (icsk); + timer_expires =tcp_timeout_expires (sk); } else if (timer_pending(&sk->sk_timer)) { timer_active =2 ; timer_expires = sk->sk_timer.expires;
net/ipv4/tcp_timer.c +3 -3
@@ -510,7 +510,7 @@ static bool tcp_rtx_probe0_timed_out(const struct sock *sk,* and tp->rcv_tstamp might very well have been written recently. * rcv_delta can thus be negative. */ - rcv_delta =icsk_timeout (icsk) - tp->rcv_tstamp; + rcv_delta =tcp_timeout_expires (sk) - tp->rcv_tstamp;if (rcv_delta <= timeout)return false;
@@ -697,9 +697,9 @@ void tcp_write_timer_handler(struct sock *sk) !icsk->icsk_pending)return ; -if (time_after (icsk_timeout (icsk), jiffies)) { +if (time_after (tcp_timeout_expires (sk), jiffies)) {sk_reset_timer (sk, &icsk->icsk_retransmit_timer, -icsk_timeout (icsk)); +tcp_timeout_expires (sk));return ; }tcp_mstamp_refresh (tcp_sk (sk));
net/ipv6/tcp_ipv6.c +2 -2
@@ -2163,10 +2163,10 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) icsk_pending == ICSK_TIME_REO_TIMEOUT || icsk_pending == ICSK_TIME_LOSS_PROBE) { timer_active =1 ; - timer_expires =icsk_timeout (icsk); + timer_expires =tcp_timeout_expires (sp); } else if (icsk_pending == ICSK_TIME_PROBE0) { timer_active =4 ; - timer_expires =icsk_timeout (icsk); + timer_expires =tcp_timeout_expires (sp); } else if (timer_pending(&sp->sk_timer)) { timer_active =2 ; timer_expires = sp->sk_timer.expires;
net/mptcp/protocol.c +1 -1
@@ -524,7 +524,7 @@ static long mptcp_timeout_from_subflow(const struct mptcp_subflow_context *subflconst struct sock *ssk =mptcp_subflow_tcp_sock (subflow);return inet_csk (ssk)->icsk_pending && !subflow->stale_count ? -icsk_timeout (inet_csk (ssk)) - jiffies :0 ; +tcp_timeout_expires (ssk) - jiffies :0 ; }static void mptcp_set_timeout (struct sock *sk)
Signature · 1 line
2.52.0.460.gd25c4c69ec-goog
Re: [PATCH net-next 1/4] tcp: rename icsk_timeout() to tcp_timeout_expires()
Quoted 6 lines · Eric Dumazet
In preparation of
sk->tcp_timeout_timerintroduction, renameicsk_timeout()helper and change its argument to plain 'const struct sock *sk'.Signed-off-by Eric Dumazet <[email protected]>
PATCH 2/4 net: move sk_dst_pending_confirm and sk_pacing_status to sock_read_tx group
In reply to Eric DumazetThese two fields are mostly read in TCP tx path, move them in an more appropriate group for better cache locality.
--- include/net/sock.h | 4 ++-- net/core/sock.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-)
include/net/sock.h +2 -2
@@ -481,8 +481,6 @@ struct sock {struct rb_root tcp_rtx_queue; };struct sk_buff_head sk_write_queue; -u32 sk_dst_pending_confirm; -u32 sk_pacing_status;/* see enum sk_pacing */ struct page_frag sk_frag;struct timer_list sk_timer;
@@ -493,6 +491,8 @@ struct sock {__cacheline_group_end (sock_write_tx);__cacheline_group_begin (sock_read_tx); +u32 sk_dst_pending_confirm; +u32 sk_pacing_status;/* see enum sk_pacing */ unsigned long sk_max_pacing_rate;long sk_sndtimeo;u32 sk_priority;
net/core/sock.c +2 -2
@@ -4501,14 +4501,14 @@ static int __init sock_struct_check(void) CACHELINE_ASSERT_GROUP_MEMBER(struct sock, sock_write_tx, sk_send_head); CACHELINE_ASSERT_GROUP_MEMBER(struct sock, sock_write_tx, sk_write_queue); CACHELINE_ASSERT_GROUP_MEMBER(struct sock, sock_write_tx, sk_write_pending); - CACHELINE_ASSERT_GROUP_MEMBER(struct sock, sock_write_tx, sk_dst_pending_confirm); - CACHELINE_ASSERT_GROUP_MEMBER(struct sock, sock_write_tx, sk_pacing_status); CACHELINE_ASSERT_GROUP_MEMBER(struct sock, sock_write_tx, sk_frag); CACHELINE_ASSERT_GROUP_MEMBER(struct sock, sock_write_tx, sk_timer); CACHELINE_ASSERT_GROUP_MEMBER(struct sock, sock_write_tx, sk_pacing_rate); CACHELINE_ASSERT_GROUP_MEMBER(struct sock, sock_write_tx, sk_zckey); CACHELINE_ASSERT_GROUP_MEMBER(struct sock, sock_write_tx, sk_tskey); + CACHELINE_ASSERT_GROUP_MEMBER(struct sock, sock_read_tx, sk_dst_pending_confirm); + CACHELINE_ASSERT_GROUP_MEMBER(struct sock, sock_read_tx, sk_pacing_status); CACHELINE_ASSERT_GROUP_MEMBER(struct sock, sock_read_tx, sk_max_pacing_rate); CACHELINE_ASSERT_GROUP_MEMBER(struct sock, sock_read_tx, sk_sndtimeo); CACHELINE_ASSERT_GROUP_MEMBER(struct sock, sock_read_tx, sk_priority);
Signature · 1 line
2.52.0.460.gd25c4c69ec-goog
Re: [PATCH net-next 2/4] net: move sk_dst_pending_confirm and sk_pacing_status to sock_read_tx group
Quoted 5 lines · Eric Dumazet
These two fields are mostly read in TCP tx path, move them in an more appropriate group for better cache locality.
Signed-off-by Eric Dumazet <[email protected]>
PATCH 3/4 tcp: introduce icsk->icsk_keepalive_timer
In reply to Eric Dumazetsk->sk_timer has been used for TCP keepalives.
Keepalive timers are not in fast path, we want to use sk->sk_timer storage for retransmit timers, for better cache locality.
Create icsk->icsk_keepalive_timer and change keepalive code to no longer use sk->sk_timer.
Added space is reclaimed in the following patch.
This includes changes to MPTCP, which was also using sk_timer.
Alias icsk->mptcp_tout_timer and icsk->icsk_keepalive_timer for inet_sk_diag_fill() sake.
--- .../net_cachelines/inet_connection_sock.rst | 1 + include/net/inet_connection_sock.h | 11 +++++++++-- net/ipv4/inet_connection_sock.c | 6 +++--- net/ipv4/inet_diag.c | 4 ++-- net/ipv4/tcp_ipv4.c | 4 ++-- net/ipv4/tcp_timer.c | 9 +++++---- net/ipv6/tcp_ipv6.c | 4 ++-- net/mptcp/protocol.c | 10 ++++++---- net/mptcp/protocol.h | 2 +- tools/testing/selftests/bpf/progs/bpf_iter_tcp4.c | 4 ++-- tools/testing/selftests/bpf/progs/bpf_iter_tcp6.c | 4 ++-- 11 files changed, 35 insertions(+), 24 deletions(-)
Documentation/networking/net_cachelines/inet_connection_sock.rst +1 -0
@@ -14,6 +14,7 @@ struct inet_bind_bucket icsk_bind_hash read_mostly struct inet_bind2_bucket icsk_bind2_hash read_mostly tcp_set_state,inet_put_port struct timer_list icsk_retransmit_timer read_write inet_csk_reset_xmit_timer,tcp_connect struct timer_list icsk_delack_timer read_mostly inet_csk_reset_xmit_timer,tcp_connect +struct timer_list icsk_keepalive_timer u32 icsk_rto read_write tcp_cwnd_validate,tcp_schedule_loss_probe,tcp_connect_init,tcp_connect,tcp_write_xmit,tcp_push_one u32 icsk_rto_min u32 icsk_rto_max read_mostly tcp_reset_xmit_timer
include/net/inet_connection_sock.h +9 -2
@@ -57,6 +57,9 @@ struct inet_connection_sock_af_ops {* @icsk_bind_hash: Bind node * @icsk_bind2_hash: Bind node in the bhash2 table * @icsk_retransmit_timer: Resend (no ack) +* @icsk_delack_timer: Delayed ACK timer +* @icsk_keepalive_timer: Keepalive timer +* @mptcp_tout_timer: mptcp timer * @icsk_rto: Retransmit timeout * @icsk_pmtu_cookie Last pmtu seen by socket * @icsk_ca_ops Pluggable congestion control hook
@@ -81,8 +84,12 @@ struct inet_connection_sock {struct request_sock_queue icsk_accept_queue;struct inet_bind_bucket *icsk_bind_hash;struct inet_bind2_bucket *icsk_bind2_hash; -struct timer_list icsk_retransmit_timer; -struct timer_list icsk_delack_timer; +struct timer_list icsk_retransmit_timer; +struct timer_list icsk_delack_timer; +union { +struct timer_list icsk_keepalive_timer; +struct timer_list mptcp_tout_timer; + };__u32 icsk_rto;__u32 icsk_rto_min;u32 icsk_rto_max;
net/ipv4/inet_connection_sock.c +3 -3
@@ -739,7 +739,7 @@ void inet_csk_init_xmit_timers(struct sock *sk,timer_setup (&icsk->icsk_retransmit_timer, retransmit_handler,0 );timer_setup (&icsk->icsk_delack_timer, delack_handler,0 ); -timer_setup (&sk->sk_timer, keepalive_handler,0 ); +timer_setup (&icsk->icsk_keepalive_timer, keepalive_handler,0 ); icsk->icsk_pending = icsk->icsk_ack.pending =0 ; }
@@ -752,7 +752,7 @@ void inet_csk_clear_xmit_timers(struct sock *sk)sk_stop_timer (sk, &icsk->icsk_retransmit_timer);sk_stop_timer (sk, &icsk->icsk_delack_timer); -sk_stop_timer (sk, &sk->sk_timer); +sk_stop_timer (sk, &icsk->icsk_keepalive_timer); }void inet_csk_clear_xmit_timers_sync (struct sock *sk)
@@ -767,7 +767,7 @@ void inet_csk_clear_xmit_timers_sync(struct sock *sk)sk_stop_timer_sync (sk, &icsk->icsk_retransmit_timer);sk_stop_timer_sync (sk, &icsk->icsk_delack_timer); -sk_stop_timer_sync (sk, &sk->sk_timer); +sk_stop_timer_sync (sk, &icsk->icsk_keepalive_timer); } struct dst_entry *inet_csk_route_req(const struct sock *sk,
net/ipv4/inet_diag.c +2 -2
@@ -293,11 +293,11 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, r->idiag_retrans =READ_ONCE (icsk->icsk_probes_out); r->idiag_expires =jiffies_delta_to_msecs (tcp_timeout_expires (sk) - jiffies); - }else if (timer_pending (&sk->sk_timer)) { + }else if (timer_pending (&icsk->icsk_keepalive_timer)) { r->idiag_timer =2 ; r->idiag_retrans =READ_ONCE (icsk->icsk_probes_out); r->idiag_expires = -jiffies_delta_to_msecs (sk->sk_timer.expires - jiffies); +jiffies_delta_to_msecs (icsk->icsk_keepalive_timer.expires - jiffies); }if ((ext & (1 << (INET_DIAG_INFO -1 ))) && handler->idiag_info_size) {
net/ipv4/tcp_ipv4.c +2 -2
@@ -2873,9 +2873,9 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i) }else if (icsk_pending ==ICSK_TIME_PROBE0 ) { timer_active =4 ; timer_expires =tcp_timeout_expires (sk); - }else if (timer_pending (&sk->sk_timer)) { + }else if (timer_pending (&icsk->icsk_keepalive_timer)) { timer_active =2 ; - timer_expires = sk->sk_timer.expires; + timer_expires = icsk->icsk_keepalive_timer.expires; }else { timer_active =0 ; timer_expires = jiffies;
net/ipv4/tcp_timer.c +5 -4
@@ -755,12 +755,12 @@ void tcp_syn_ack_timeout(const struct request_sock *req)void tcp_reset_keepalive_timer (struct sock *sk,unsigned long len) { -sk_reset_timer (sk, &sk->sk_timer, jiffies + len); +sk_reset_timer (sk, &inet_csk (sk)->icsk_keepalive_timer, jiffies + len); }static void tcp_delete_keepalive_timer (struct sock *sk) { -sk_stop_timer (sk, &sk->sk_timer); +sk_stop_timer (sk, &inet_csk (sk)->icsk_keepalive_timer); }void tcp_set_keepalive (struct sock *sk,int val)
@@ -777,8 +777,9 @@ EXPORT_IPV6_MOD_GPL(tcp_set_keepalive);static void tcp_keepalive_timer (struct timer_list *t) { -struct sock *sk =timer_container_of (sk, t, sk_timer); -struct inet_connection_sock *icsk =inet_csk (sk); +struct inet_connection_sock *icsk = +timer_container_of (icsk, t, icsk_keepalive_timer); +struct sock *sk = &icsk->icsk_inet.sk;struct tcp_sock *tp =tcp_sk (sk);u32 elapsed;
net/ipv6/tcp_ipv6.c +2 -2
@@ -2167,9 +2167,9 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) }else if (icsk_pending ==ICSK_TIME_PROBE0 ) { timer_active =4 ; timer_expires =tcp_timeout_expires (sp); - }else if (timer_pending (&sp->sk_timer)) { + }else if (timer_pending (&icsk->icsk_keepalive_timer)) { timer_active =2 ; - timer_expires = sp->sk_timer.expires; + timer_expires = icsk->icsk_keepalive_timer.expires; }else { timer_active =0 ; timer_expires = jiffies;
net/mptcp/protocol.c +6 -4
@@ -2326,7 +2326,9 @@ static void mptcp_retransmit_timer(struct timer_list *t)static void mptcp_tout_timer (struct timer_list *t) { -struct sock *sk =timer_container_of (sk, t, sk_timer); +struct inet_connection_sock *icsk = +timer_container_of (icsk, t, mptcp_tout_timer); +struct sock *sk = &icsk->icsk_inet.sk;mptcp_schedule_work (sk);sock_put (sk);
@@ -2750,7 +2752,7 @@ void mptcp_reset_tout_timer(struct mptcp_sock *msk, unsigned long fail_tout)*/ timeout =inet_csk (sk)->icsk_mtup.probe_timestamp ? close_timeout : fail_tout; -sk_reset_timer (sk, &sk->sk_timer, timeout); +sk_reset_timer (sk, &inet_csk (sk)->mptcp_tout_timer, timeout); }static void mptcp_mp_fail_no_response (struct mptcp_sock *msk)
@@ -2875,7 +2877,7 @@ static void __mptcp_init_sock(struct sock *sk)/* re-use the csk retrans timer for MPTCP-level retrans */ timer_setup (&msk->sk.icsk_retransmit_timer, mptcp_retransmit_timer,0 ); -timer_setup (&sk->sk_timer, mptcp_tout_timer,0 ); +timer_setup (&msk->sk.mptcp_tout_timer, mptcp_tout_timer,0 ); }static void mptcp_ca_reset (struct sock *sk)
@@ -3077,7 +3079,7 @@ static void __mptcp_destroy_sock(struct sock *sk)might_sleep ();mptcp_stop_rtx_timer (sk); -sk_stop_timer (sk, &sk->sk_timer); +sk_stop_timer (sk, &inet_csk (sk)->mptcp_tout_timer); msk->pm.status =0 ;mptcp_release_sched (msk);
net/mptcp/protocol.h +1 -1
@@ -847,7 +847,7 @@ static inline void mptcp_stop_tout_timer(struct sock *sk)if (!inet_csk (sk)->icsk_mtup.probe_timestamp)return ; -sk_stop_timer (sk, &sk->sk_timer); +sk_stop_timer (sk, &inet_csk (sk)->mptcp_tout_timer);inet_csk (sk)->icsk_mtup.probe_timestamp =0 ; }
tools/testing/selftests/bpf/progs/bpf_iter_tcp4.c +2 -2
@@ -103,9 +103,9 @@ static int dump_tcp_sock(struct seq_file *seq, struct tcp_sock *tp, }else if (icsk->icsk_pending ==ICSK_TIME_PROBE0 ) { timer_active =4 ; timer_expires = icsk->icsk_retransmit_timer.expires; - }else if (timer_pending (&sp->sk_timer)) { + }else if (timer_pending (&icsk->icsk_keepalive_timer)) { timer_active =2 ; - timer_expires = sp->sk_timer.expires; + timer_expires = icsk->icsk_keepalive_timer.expires; }else { timer_active =0 ; timer_expires =bpf_jiffies64 ();
tools/testing/selftests/bpf/progs/bpf_iter_tcp6.c +2 -2
@@ -103,9 +103,9 @@ static int dump_tcp6_sock(struct seq_file *seq, struct tcp6_sock *tp, }else if (icsk->icsk_pending ==ICSK_TIME_PROBE0 ) { timer_active =4 ; timer_expires = icsk->icsk_retransmit_timer.expires; - }else if (timer_pending (&sp->sk_timer)) { + }else if (timer_pending (&icsk->icsk_keepalive_timer)) { timer_active =2 ; - timer_expires = sp->sk_timer.expires; + timer_expires = icsk->icsk_keepalive_timer.expires; }else { timer_active =0 ; timer_expires =bpf_jiffies64 ();
Signature · 1 line
2.52.0.460.gd25c4c69ec-goog
Re: [PATCH net-next 3/4] tcp: introduce icsk->icsk_keepalive_timer
Quoted 9 lines · Eric Dumazet
sk->sk_timerhas been used for TCP keepalives.Keepalive timers are not in fast path, we want to use
sk->sk_timerstorage for retransmit timers, for better cache locality.Create
icsk->icsk_keepalive_timerand change keepalive code to no longer usesk->sk_timer.
Quoted 8 lines
Added space is reclaimed in the following patch.
This includes changes to MPTCP, which was also using
sk_timer.Alias
icsk->mptcp_tout_timerandicsk->icsk_keepalive_timerforinet_sk_diag_fill()sake.Signed-off-by Eric Dumazet <[email protected]>
PATCH 4/4 tcp: remove icsk->icsk_retransmit_timer
In reply to Eric DumazetNow sk->sk_timer is no longer used by TCP keepalive, we can use its storage for TCP and MPTCP retransmit timers for better cache locality.
--- .../net_cachelines/inet_connection_sock.rst | 1 - include/net/inet_connection_sock.h | 8 +++----- include/net/sock.h | 9 +++++++-- net/ipv4/inet_connection_sock.c | 6 +++--- net/ipv4/tcp_timer.c | 8 +++----- net/mptcp/protocol.c | 15 +++++---------- tools/testing/selftests/bpf/progs/bpf_iter_tcp4.c | 4 ++-- tools/testing/selftests/bpf/progs/bpf_iter_tcp6.c | 4 ++-- 8 files changed, 25 insertions(+), 30 deletions(-)
Documentation/networking/net_cachelines/inet_connection_sock.rst +0 -1
@@ -12,7 +12,6 @@ struct inet_sock icsk_inet read_mostly r struct request_sock_queue icsk_accept_queue struct inet_bind_bucket icsk_bind_hash read_mostly tcp_set_state struct inet_bind2_bucket icsk_bind2_hash read_mostly tcp_set_state,inet_put_port -struct timer_list icsk_retransmit_timer read_write inet_csk_reset_xmit_timer,tcp_connect struct timer_list icsk_delack_timer read_mostly inet_csk_reset_xmit_timer,tcp_connect struct timer_list icsk_keepalive_timer u32 icsk_rto read_write tcp_cwnd_validate,tcp_schedule_loss_probe,tcp_connect_init,tcp_connect,tcp_write_xmit,tcp_push_one
include/net/inet_connection_sock.h +3 -5
@@ -56,7 +56,6 @@ struct inet_connection_sock_af_ops {* @icsk_accept_queue: FIFO of established children * @icsk_bind_hash: Bind node * @icsk_bind2_hash: Bind node in the bhash2 table -* @icsk_retransmit_timer: Resend (no ack) * @icsk_delack_timer: Delayed ACK timer * @icsk_keepalive_timer: Keepalive timer * @mptcp_tout_timer: mptcp timer
@@ -84,7 +83,6 @@ struct inet_connection_sock {struct request_sock_queue icsk_accept_queue;struct inet_bind_bucket *icsk_bind_hash;struct inet_bind2_bucket *icsk_bind2_hash; -struct timer_list icsk_retransmit_timer;struct timer_list icsk_delack_timer;union {struct timer_list icsk_keepalive_timer;
@@ -193,7 +191,7 @@ static inline void inet_csk_delack_init(struct sock *sk)static inline unsigned long tcp_timeout_expires (const struct sock *sk) { -return READ_ONCE (inet_csk (sk)->icsk_retransmit_timer.expires); +return READ_ONCE (sk->tcp_retransmit_timer.expires); } static inline unsigned long
@@ -209,7 +207,7 @@ static inline void inet_csk_clear_xmit_timer(struct sock *sk, const int what)if (what ==ICSK_TIME_RETRANS || what ==ICSK_TIME_PROBE0 ) {smp_store_release (&icsk->icsk_pending,0 );#ifdef INET_CSK_CLEAR_TIMERS -sk_stop_timer (sk, &icsk->icsk_retransmit_timer); +sk_stop_timer (sk, &sk->tcp_retransmit_timer);#endif }else if (what ==ICSK_TIME_DACK ) {smp_store_release (&icsk->icsk_ack.pending,0 );
@@ -241,7 +239,7 @@ static inline void inet_csk_reset_xmit_timer(struct sock *sk, const int what,if (what ==ICSK_TIME_RETRANS || what ==ICSK_TIME_PROBE0 || what ==ICSK_TIME_LOSS_PROBE || what ==ICSK_TIME_REO_TIMEOUT ) {smp_store_release (&icsk->icsk_pending, what); -sk_reset_timer (sk, &icsk->icsk_retransmit_timer, when); +sk_reset_timer (sk, &sk->tcp_retransmit_timer, when); }else if (what ==ICSK_TIME_DACK ) {smp_store_release (&icsk->icsk_ack.pending, icsk->icsk_ack.pending |ICSK_ACK_TIMER );
include/net/sock.h +7 -2
@@ -305,6 +305,8 @@ struct sk_filter;* @sk_txrehash: enable TX hash rethink * @sk_filter: socket filtering instructions * @sk_timer: sock cleanup timer +* @tcp_retransmit_timer: tcp retransmit timer +* @mptcp_retransmit_timer: mptcp retransmit timer * @sk_stamp: time stamp of last packet received * @sk_stamp_seq: lock for accessing sk_stamp on 32 bit architectures only * @sk_tsflags: SO_TIMESTAMPING flags
@@ -482,8 +484,11 @@ struct sock { };struct sk_buff_head sk_write_queue;struct page_frag sk_frag; -struct timer_list sk_timer; - +union { +struct timer_list sk_timer; +struct timer_list tcp_retransmit_timer; +struct timer_list mptcp_retransmit_timer; + };unsigned long sk_pacing_rate;/* bytes per second */ atomic_t sk_zckey;atomic_t sk_tskey;
net/ipv4/inet_connection_sock.c +3 -3
@@ -737,7 +737,7 @@ void inet_csk_init_xmit_timers(struct sock *sk, {struct inet_connection_sock *icsk =inet_csk (sk); -timer_setup (&icsk->icsk_retransmit_timer, retransmit_handler,0 ); +timer_setup (&sk->tcp_retransmit_timer, retransmit_handler,0 );timer_setup (&icsk->icsk_delack_timer, delack_handler,0 );timer_setup (&icsk->icsk_keepalive_timer, keepalive_handler,0 ); icsk->icsk_pending = icsk->icsk_ack.pending =0 ;
@@ -750,7 +750,7 @@ void inet_csk_clear_xmit_timers(struct sock *sk)smp_store_release (&icsk->icsk_pending,0 );smp_store_release (&icsk->icsk_ack.pending,0 ); -sk_stop_timer (sk, &icsk->icsk_retransmit_timer); +sk_stop_timer (sk, &sk->tcp_retransmit_timer);sk_stop_timer (sk, &icsk->icsk_delack_timer);sk_stop_timer (sk, &icsk->icsk_keepalive_timer); }
@@ -765,7 +765,7 @@ void inet_csk_clear_xmit_timers_sync(struct sock *sk)smp_store_release (&icsk->icsk_pending,0 );smp_store_release (&icsk->icsk_ack.pending,0 ); -sk_stop_timer_sync (sk, &icsk->icsk_retransmit_timer); +sk_stop_timer_sync (sk, &sk->tcp_retransmit_timer);sk_stop_timer_sync (sk, &icsk->icsk_delack_timer);sk_stop_timer_sync (sk, &icsk->icsk_keepalive_timer); }
net/ipv4/tcp_timer.c +3 -5
@@ -698,7 +698,7 @@ void tcp_write_timer_handler(struct sock *sk)return ;if (time_after (tcp_timeout_expires (sk), jiffies)) { -sk_reset_timer (sk, &icsk->icsk_retransmit_timer, +sk_reset_timer (sk, &sk->tcp_retransmit_timer,tcp_timeout_expires (sk));return ; }
@@ -725,12 +725,10 @@ void tcp_write_timer_handler(struct sock *sk)static void tcp_write_timer (struct timer_list *t) { -struct inet_connection_sock *icsk = -timer_container_of (icsk, t, icsk_retransmit_timer); -struct sock *sk = &icsk->icsk_inet.sk; +struct sock *sk =timer_container_of (sk, t, tcp_retransmit_timer);/* Avoid locking the socket when there is no pending event. */ -if (!smp_load_acquire (&icsk->icsk_pending)) +if (!smp_load_acquire (&inet_csk (sk)->icsk_pending)) goto out;bh_lock_sock (sk);
net/mptcp/protocol.c +5 -10
@@ -416,9 +416,7 @@ static bool __mptcp_move_skb(struct sock *sk, struct sk_buff *skb)static void mptcp_stop_rtx_timer (struct sock *sk) { -struct inet_connection_sock *icsk =inet_csk (sk); - -sk_stop_timer (sk, &icsk->icsk_retransmit_timer); +sk_stop_timer (sk, &sk->mptcp_retransmit_timer);mptcp_sk (sk)->timer_ival =0 ; }
@@ -926,12 +924,11 @@ static void __mptcp_flush_join_list(struct sock *sk, struct list_head *join_liststatic bool mptcp_rtx_timer_pending (struct sock *sk) { -return timer_pending (&inet_csk (sk)->icsk_retransmit_timer); +return timer_pending (&sk->mptcp_retransmit_timer); }static void mptcp_reset_rtx_timer (struct sock *sk) { -struct inet_connection_sock *icsk =inet_csk (sk);unsigned long tout;/* prevent rescheduling on close */
@@ -939,7 +936,7 @@ static void mptcp_reset_rtx_timer(struct sock *sk)return ; tout =mptcp_sk (sk)->timer_ival; -sk_reset_timer (sk, &icsk->icsk_retransmit_timer, jiffies + tout); +sk_reset_timer (sk, &sk->mptcp_retransmit_timer, jiffies + tout); }bool mptcp_schedule_work (struct sock *sk)
@@ -2306,9 +2303,7 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,static void mptcp_retransmit_timer (struct timer_list *t) { -struct inet_connection_sock *icsk =timer_container_of (icsk, t, - icsk_retransmit_timer); -struct sock *sk = &icsk->icsk_inet.sk; +struct sock *sk =timer_container_of (sk, t, mptcp_retransmit_timer);struct mptcp_sock *msk =mptcp_sk (sk);bh_lock_sock (sk);
@@ -2876,7 +2871,7 @@ static void __mptcp_init_sock(struct sock *sk)spin_lock_init (&msk->fallback_lock);/* re-use the csk retrans timer for MPTCP-level retrans */ -timer_setup (&msk->sk.icsk_retransmit_timer, mptcp_retransmit_timer,0 ); +timer_setup (&sk->mptcp_retransmit_timer, mptcp_retransmit_timer,0 );timer_setup (&msk->sk.mptcp_tout_timer, mptcp_tout_timer,0 ); }
tools/testing/selftests/bpf/progs/bpf_iter_tcp4.c +2 -2
@@ -99,10 +99,10 @@ static int dump_tcp_sock(struct seq_file *seq, struct tcp_sock *tp, icsk->icsk_pending == ICSK_TIME_REO_TIMEOUT || icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) { timer_active =1 ; - timer_expires = icsk->icsk_retransmit_timer.expires; + timer_expires = sp->tcp_retransmit_timer.expires; } else if (icsk->icsk_pending == ICSK_TIME_PROBE0) { timer_active =4 ; - timer_expires = icsk->icsk_retransmit_timer.expires; + timer_expires = sp->tcp_retransmit_timer.expires; } else if (timer_pending(&icsk->icsk_keepalive_timer)) { timer_active =2 ; timer_expires = icsk->icsk_keepalive_timer.expires;
tools/testing/selftests/bpf/progs/bpf_iter_tcp6.c +2 -2
@@ -99,10 +99,10 @@ static int dump_tcp6_sock(struct seq_file *seq, struct tcp6_sock *tp, icsk->icsk_pending == ICSK_TIME_REO_TIMEOUT || icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) { timer_active =1 ; - timer_expires = icsk->icsk_retransmit_timer.expires; + timer_expires = sp->tcp_retransmit_timer.expires; } else if (icsk->icsk_pending == ICSK_TIME_PROBE0) { timer_active =4 ; - timer_expires = icsk->icsk_retransmit_timer.expires; + timer_expires = sp->tcp_retransmit_timer.expires; } else if (timer_pending(&icsk->icsk_keepalive_timer)) { timer_active =2 ; timer_expires = icsk->icsk_keepalive_timer.expires;
Signature · 1 line
2.52.0.460.gd25c4c69ec-goog
Re: [PATCH net-next 4/4] tcp: remove icsk->icsk_retransmit_timer
Quoted 6 lines · Eric Dumazet
Now
sk->sk_timeris no longer used by TCP keepalive, we can use its storage for TCP and MPTCP retransmit timers for better cache locality.Signed-off-by Eric Dumazet <[email protected]>
Thanks!
This series was applied to netdev/net-next.git (main) by Jakub Kicinski <[email protected]>:
Hello:
This series was applied to netdev/net-next.git (main) by Jakub Kicinski <[email protected]>:
Quoted 10 lines · On Mon, 24 Nov 2025 17:50:09 +0000 you wrote:
TCP stack uses three timers per flow, currently spread this way:
-
sk->sk_timer: keepalive timer
-icsk->icsk_retransmit_timer: retransmit timer
-icsk->icsk_delack_timer: delayed ack timerThis series moves the retransmit timer to
sk->sk_timerlocation, to increase data locality in TX paths.[...]
Here is the summary with links:
- [net-next,1/4] tcp: rename icsk_timeout() to tcp_timeout_expires()
https://git.kernel.org/netdev/net-next/c/3a6e8fd0bf40 - [net-next,2/4] net: move sk_dst_pending_confirm and sk_pacing_status to sock_read_tx group https://git.kernel.org/netdev/net-next/c/27e8257a8651 - [net-next,3/4] tcp: introduce icsk->icsk_keepalive_timer https://git.kernel.org/netdev/net-next/c/08dfe370239e - [net-next,4/4] tcp: remove icsk->icsk_retransmit_timer https://git.kernel.org/netdev/net-next/c/9a5e5334adc0
You are awesome, thank you!
Signature · 2 lines
Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html
Hi Eric,
Quoted 11 lines · Eric Dumazet
TCP stack uses three timers per flow, currently spread this way:
-
sk->sk_timer: keepalive timer
-icsk->icsk_retransmit_timer: retransmit timer
-icsk->icsk_delack_timer: delayed ack timerThis series moves the retransmit timer to
sk->sk_timerlocation, to increase data locality in TX paths.keepalive timers are not often used, this change should be neutral for them.
Quoted 7 lines
After the series we have following fields:
-
sk->tcp_retransmit_timer: retransmit timer, insock_write_txgroup
-icsk->icsk_delack_timer: delayed ack timer
-icsk->icsk_keepalive_timer: keepalive timerMoving
icsk_delack_timerin a beter location would also be welcomed.
Sorry for the delay, I didn't manage to look at it yesterday. I just wanted to say thank you for this series, and for having adapted MPTCP as well!
Just in case, even if the series has already been applied:
Cheers,
Matt
Signature · 1 line
Sponsored by the NGI0 Core fund.
Quoted 23 lines · Matthieu Baerts
Hi Eric,
Quoted 11 lines · Eric Dumazet
TCP stack uses three timers per flow, currently spread this way:
-
sk->sk_timer: keepalive timer
-icsk->icsk_retransmit_timer: retransmit timer
-icsk->icsk_delack_timer: delayed ack timerThis series moves the retransmit timer to
sk->sk_timerlocation, to increase data locality in TX paths.keepalive timers are not often used, this change should be neutral for them.
Quoted 7 lines
After the series we have following fields:
-
sk->tcp_retransmit_timer: retransmit timer, insock_write_txgroup
-icsk->icsk_delack_timer: delayed ack timer
-icsk->icsk_keepalive_timer: keepalive timerMoving
icsk_delack_timerin a beter location would also be welcomed.
Quoted 7 lines
Sorry for the delay, I didn't manage to look at it yesterday. I just wanted to say thank you for this series, and for having adapted MPTCP as well!
Just in case, even if the series has already been applied:
Thanks for checking the series !