Skip to content

Commit ed08495

Browse files
yuchungchengdavem330
authored andcommitted
tcp: use RTT from SACK for RTO
If RTT is not available because Karn's check has failed or no new packet is acked, use the RTT measured from SACK to estimate the RTO. The sender can continue to estimate the RTO during loss recovery or reordering event upon receiving non-partial ACKs. This also changes when the RTO is re-armed. Previously it is only re-armed when some data is cummulatively acknowledged (i.e., SND.UNA advances), but now it is re-armed whenever RTT estimator is updated. This feature is particularly useful to reduce spurious timeout for buffer bloat including cellular carriers [1], and RTT estimation on reordering events. [1] "An In-depth Study of LTE: Effect of Network Protocol and Application Behavior on Performance", In Proc. of SIGCOMM 2013 Signed-off-by: Yuchung Cheng <ycheng@google.com> Acked-by: Neal Cardwell <ncardwell@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 59c9af4 commit ed08495

File tree

1 file changed

+14
-9
lines changed

1 file changed

+14
-9
lines changed

net/ipv4/tcp_input.c

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2800,8 +2800,8 @@ static void tcp_fastretrans_alert(struct sock *sk, const int acked,
28002800
tcp_xmit_retransmit_queue(sk);
28012801
}
28022802

2803-
static inline void tcp_ack_update_rtt(struct sock *sk, const int flag,
2804-
s32 seq_rtt)
2803+
static inline bool tcp_ack_update_rtt(struct sock *sk, const int flag,
2804+
s32 seq_rtt, s32 sack_rtt)
28052805
{
28062806
const struct tcp_sock *tp = tcp_sk(sk);
28072807

@@ -2813,6 +2813,9 @@ static inline void tcp_ack_update_rtt(struct sock *sk, const int flag,
28132813
if (flag & FLAG_RETRANS_DATA_ACKED)
28142814
seq_rtt = -1;
28152815

2816+
if (seq_rtt < 0)
2817+
seq_rtt = sack_rtt;
2818+
28162819
/* RTTM Rule: A TSecr value received in a segment is used to
28172820
* update the averaged RTT measurement only if the segment
28182821
* acknowledges some new data, i.e., only if it advances the
@@ -2823,13 +2826,14 @@ static inline void tcp_ack_update_rtt(struct sock *sk, const int flag,
28232826
seq_rtt = tcp_time_stamp - tp->rx_opt.rcv_tsecr;
28242827

28252828
if (seq_rtt < 0)
2826-
return;
2829+
return false;
28272830

28282831
tcp_rtt_estimator(sk, seq_rtt);
28292832
tcp_set_rto(sk);
28302833

28312834
/* RFC6298: only reset backoff on valid RTT measurement. */
28322835
inet_csk(sk)->icsk_backoff = 0;
2836+
return true;
28332837
}
28342838

28352839
/* Compute time elapsed between (last) SYNACK and the ACK completing 3WHS. */
@@ -2840,7 +2844,7 @@ static void tcp_synack_rtt_meas(struct sock *sk, struct request_sock *req)
28402844

28412845
if (tp->lsndtime && !tp->total_retrans)
28422846
seq_rtt = tcp_time_stamp - tp->lsndtime;
2843-
tcp_ack_update_rtt(sk, FLAG_SYN_ACKED, seq_rtt);
2847+
tcp_ack_update_rtt(sk, FLAG_SYN_ACKED, seq_rtt, -1);
28442848
}
28452849

28462850
static void tcp_cong_avoid(struct sock *sk, u32 ack, u32 in_flight)
@@ -2929,7 +2933,7 @@ static u32 tcp_tso_acked(struct sock *sk, struct sk_buff *skb)
29292933
* arrived at the other end.
29302934
*/
29312935
static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
2932-
u32 prior_snd_una)
2936+
u32 prior_snd_una, s32 sack_rtt)
29332937
{
29342938
struct tcp_sock *tp = tcp_sk(sk);
29352939
const struct inet_connection_sock *icsk = inet_csk(sk);
@@ -3019,6 +3023,10 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
30193023
if (skb && (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED))
30203024
flag |= FLAG_SACK_RENEGING;
30213025

3026+
if (tcp_ack_update_rtt(sk, flag, seq_rtt, sack_rtt) ||
3027+
(flag & FLAG_ACKED))
3028+
tcp_rearm_rto(sk);
3029+
30223030
if (flag & FLAG_ACKED) {
30233031
const struct tcp_congestion_ops *ca_ops
30243032
= inet_csk(sk)->icsk_ca_ops;
@@ -3028,9 +3036,6 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
30283036
tcp_mtup_probe_success(sk);
30293037
}
30303038

3031-
tcp_ack_update_rtt(sk, flag, seq_rtt);
3032-
tcp_rearm_rto(sk);
3033-
30343039
if (tcp_is_reno(tp)) {
30353040
tcp_remove_reno_sacks(sk, pkts_acked);
30363041
} else {
@@ -3339,7 +3344,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
33393344

33403345
/* See if we can take anything off of the retransmit queue. */
33413346
acked = tp->packets_out;
3342-
flag |= tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una);
3347+
flag |= tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una, sack_rtt);
33433348
acked -= tp->packets_out;
33443349

33453350
if (tcp_ack_is_dubious(sk, flag)) {

0 commit comments

Comments
 (0)