Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit 718c49f

Browse files
Aananth Vgregkh
authored andcommitted
tcp: new TCP_INFO stats for RTO events
[ Upstream commit 3868ab0 ] The 2023 SIGCOMM paper "Improving Network Availability with Protective ReRoute" has indicated Linux TCP's RTO-triggered txhash rehashing can effectively reduce application disruption during outages. To better measure the efficacy of this feature, this patch adds three more detailed stats during RTO recovery and exports via TCP_INFO. Applications and monitoring systems can leverage this data to measure the network path diversity and end-to-end repair latency during network outages to improve their network infrastructure. The following counters are added to tcp_sock in order to track RTO events over the lifetime of a TCP socket. 1. u16 total_rto - Counts the total number of RTO timeouts. 2. u16 total_rto_recoveries - Counts the total number of RTO recoveries. 3. u32 total_rto_time - Counts the total time spent (ms) in RTO recoveries. (time spent in CA_Loss and CA_Recovery states) To compute total_rto_time, we add a new u32 rto_stamp field to tcp_sock. rto_stamp records the start timestamp (ms) of the last RTO recovery (CA_Loss). Corresponding fields are also added to the tcp_info struct. Signed-off-by: Aananth V <[email protected]> Signed-off-by: Neal Cardwell <[email protected]> Signed-off-by: Yuchung Cheng <[email protected]> Reviewed-by: Eric Dumazet <[email protected]> Signed-off-by: David S. Miller <[email protected]> Stable-dep-of: 27c80ef ("tcp: fix TFO SYN_RECV to not zero retrans_stamp with retransmits out") Signed-off-by: Sasha Levin <[email protected]>
1 parent 04dce9a commit 718c49f

File tree

6 files changed

+63
-2
lines changed

6 files changed

+63
-2
lines changed

include/linux/tcp.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,14 @@ struct tcp_sock {
377377
* Total data bytes retransmitted
378378
*/
379379
u32 total_retrans; /* Total retransmits for entire connection */
380+
u32 rto_stamp; /* Start time (ms) of last CA_Loss recovery */
381+
u16 total_rto; /* Total number of RTO timeouts, including
382+
* SYN/SYN-ACK and recurring timeouts.
383+
*/
384+
u16 total_rto_recoveries; /* Total number of RTO recoveries,
385+
* including any unfinished recovery.
386+
*/
387+
u32 total_rto_time; /* ms spent in (completed) RTO recoveries. */
380388

381389
u32 urg_seq; /* Seq of received urgent pointer */
382390
unsigned int keepalive_time; /* time before keep alive takes place */

include/uapi/linux/tcp.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,18 @@ struct tcp_info {
289289
*/
290290

291291
__u32 tcpi_rehash; /* PLB or timeout triggered rehash attempts */
292+
293+
__u16 tcpi_total_rto; /* Total number of RTO timeouts, including
294+
* SYN/SYN-ACK and recurring timeouts.
295+
*/
296+
__u16 tcpi_total_rto_recoveries; /* Total number of RTO
297+
* recoveries, including any
298+
* unfinished recovery.
299+
*/
300+
__u32 tcpi_total_rto_time; /* Total time spent in RTO recoveries
301+
* in milliseconds, including any
302+
* unfinished recovery.
303+
*/
292304
};
293305

294306
/* netlink attributes types for SCM_TIMESTAMPING_OPT_STATS */

net/ipv4/tcp.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3851,6 +3851,15 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
38513851
info->tcpi_rcv_wnd = tp->rcv_wnd;
38523852
info->tcpi_rehash = tp->plb_rehash + tp->timeout_rehash;
38533853
info->tcpi_fastopen_client_fail = tp->fastopen_client_fail;
3854+
3855+
info->tcpi_total_rto = tp->total_rto;
3856+
info->tcpi_total_rto_recoveries = tp->total_rto_recoveries;
3857+
info->tcpi_total_rto_time = tp->total_rto_time;
3858+
if (tp->rto_stamp) {
3859+
info->tcpi_total_rto_time += tcp_time_stamp_raw() -
3860+
tp->rto_stamp;
3861+
}
3862+
38543863
unlock_sock_fast(sk, slow);
38553864
}
38563865
EXPORT_SYMBOL_GPL(tcp_get_info);

net/ipv4/tcp_input.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2108,6 +2108,10 @@ void tcp_clear_retrans(struct tcp_sock *tp)
21082108
tp->undo_marker = 0;
21092109
tp->undo_retrans = -1;
21102110
tp->sacked_out = 0;
2111+
tp->rto_stamp = 0;
2112+
tp->total_rto = 0;
2113+
tp->total_rto_recoveries = 0;
2114+
tp->total_rto_time = 0;
21112115
}
21122116

21132117
static inline void tcp_init_undo(struct tcp_sock *tp)
@@ -2899,6 +2903,14 @@ void tcp_enter_recovery(struct sock *sk, bool ece_ack)
28992903
tcp_set_ca_state(sk, TCP_CA_Recovery);
29002904
}
29012905

2906+
static void tcp_update_rto_time(struct tcp_sock *tp)
2907+
{
2908+
if (tp->rto_stamp) {
2909+
tp->total_rto_time += tcp_time_stamp(tp) - tp->rto_stamp;
2910+
tp->rto_stamp = 0;
2911+
}
2912+
}
2913+
29022914
/* Process an ACK in CA_Loss state. Move to CA_Open if lost data are
29032915
* recovered or spurious. Otherwise retransmits more on partial ACKs.
29042916
*/
@@ -3103,6 +3115,8 @@ static void tcp_fastretrans_alert(struct sock *sk, const u32 prior_snd_una,
31033115
break;
31043116
case TCP_CA_Loss:
31053117
tcp_process_loss(sk, flag, num_dupack, rexmit);
3118+
if (icsk->icsk_ca_state != TCP_CA_Loss)
3119+
tcp_update_rto_time(tp);
31063120
tcp_identify_packet_loss(sk, ack_flag);
31073121
if (!(icsk->icsk_ca_state == TCP_CA_Open ||
31083122
(*ack_flag & FLAG_LOST_RETRANS)))
@@ -6541,6 +6555,7 @@ static void tcp_rcv_synrecv_state_fastopen(struct sock *sk)
65416555
tcp_try_undo_recovery(sk);
65426556

65436557
/* Reset rtx states to prevent spurious retransmits_timed_out() */
6558+
tcp_update_rto_time(tp);
65446559
tp->retrans_stamp = 0;
65456560
inet_csk(sk)->icsk_retransmits = 0;
65466561

net/ipv4/tcp_minisocks.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,10 @@ struct sock *tcp_create_openreq_child(const struct sock *sk,
560560
newtp->undo_marker = treq->snt_isn;
561561
newtp->retrans_stamp = div_u64(treq->snt_synack,
562562
USEC_PER_SEC / TCP_TS_HZ);
563+
newtp->total_rto = req->num_timeout;
564+
newtp->total_rto_recoveries = 1;
565+
newtp->total_rto_time = tcp_time_stamp_raw() -
566+
newtp->retrans_stamp;
563567
}
564568
newtp->tsoffset = treq->ts_off;
565569
#ifdef CONFIG_TCP_MD5SIG

net/ipv4/tcp_timer.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,19 @@ abort: tcp_write_err(sk);
411411
}
412412
}
413413

414+
static void tcp_update_rto_stats(struct sock *sk)
415+
{
416+
struct inet_connection_sock *icsk = inet_csk(sk);
417+
struct tcp_sock *tp = tcp_sk(sk);
418+
419+
if (!icsk->icsk_retransmits) {
420+
tp->total_rto_recoveries++;
421+
tp->rto_stamp = tcp_time_stamp(tp);
422+
}
423+
icsk->icsk_retransmits++;
424+
tp->total_rto++;
425+
}
426+
414427
/*
415428
* Timer for Fast Open socket to retransmit SYNACK. Note that the
416429
* sk here is the child socket, not the parent (listener) socket.
@@ -443,7 +456,7 @@ static void tcp_fastopen_synack_timer(struct sock *sk, struct request_sock *req)
443456
*/
444457
inet_rtx_syn_ack(sk, req);
445458
req->num_timeout++;
446-
icsk->icsk_retransmits++;
459+
tcp_update_rto_stats(sk);
447460
if (!tp->retrans_stamp)
448461
tp->retrans_stamp = tcp_time_stamp(tp);
449462
inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
@@ -586,7 +599,7 @@ void tcp_retransmit_timer(struct sock *sk)
586599

587600
tcp_enter_loss(sk);
588601

589-
icsk->icsk_retransmits++;
602+
tcp_update_rto_stats(sk);
590603
if (tcp_retransmit_skb(sk, tcp_rtx_queue_head(sk), 1) > 0) {
591604
/* Retransmission failed because of local congestion,
592605
* Let senders fight for local resources conservatively.

0 commit comments

Comments
 (0)