aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_input.c
diff options
context:
space:
mode:
authorYuchung Cheng <ycheng@google.com>2013-10-24 11:59:27 -0400
committerDavid S. Miller <davem@davemloft.net>2013-10-27 16:50:06 -0400
commit2f715c1dde6e1760f3101358dc26f8c9489be0bf (patch)
treeb77474cc9f3e97000404dab09bde3429d62192ff /net/ipv4/tcp_input.c
parent2909d874f34eae157aecab0af27c6dc4a1751f8f (diff)
tcp: do not rearm RTO when future data are sacked
Patch ed08495c3 "tcp: use RTT from SACK for RTO" always re-arms RTO upon obtaining a RTT sample from newly sacked data. But technically RTO should only be re-armed when the data sent before the last (re)transmission of write queue head are (s)acked. Otherwise the RTO may continue to extend during loss recovery on data sent in the future. Note that RTTs from ACK or timestamps do not have this problem, as the RTT source must be from data sent before. The new RTO re-arm policy is 1) Always re-arm RTO if SND.UNA is advanced 2) Re-arm RTO if sack RTT is available, provided the sacked data was sent before the last time write_queue_head was sent. Signed-off-by: Larry Brakmo <brakmo@google.com> Signed-off-by: Yuchung Cheng <ycheng@google.com> Acked-by: Neal Cardwell <ncardwell@google.com> Acked-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_input.c')
-rw-r--r--net/ipv4/tcp_input.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 6ffe41a82c00..068c8fb0d158 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -2987,6 +2987,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
2987 s32 seq_rtt = -1; 2987 s32 seq_rtt = -1;
2988 s32 ca_seq_rtt = -1; 2988 s32 ca_seq_rtt = -1;
2989 ktime_t last_ackt = net_invalid_timestamp(); 2989 ktime_t last_ackt = net_invalid_timestamp();
2990 bool rtt_update;
2990 2991
2991 while ((skb = tcp_write_queue_head(sk)) && skb != tcp_send_head(sk)) { 2992 while ((skb = tcp_write_queue_head(sk)) && skb != tcp_send_head(sk)) {
2992 struct tcp_skb_cb *scb = TCP_SKB_CB(skb); 2993 struct tcp_skb_cb *scb = TCP_SKB_CB(skb);
@@ -3063,14 +3064,13 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
3063 if (skb && (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)) 3064 if (skb && (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED))
3064 flag |= FLAG_SACK_RENEGING; 3065 flag |= FLAG_SACK_RENEGING;
3065 3066
3066 if (tcp_ack_update_rtt(sk, flag, seq_rtt, sack_rtt) || 3067 rtt_update = tcp_ack_update_rtt(sk, flag, seq_rtt, sack_rtt);
3067 (flag & FLAG_ACKED))
3068 tcp_rearm_rto(sk);
3069 3068
3070 if (flag & FLAG_ACKED) { 3069 if (flag & FLAG_ACKED) {
3071 const struct tcp_congestion_ops *ca_ops 3070 const struct tcp_congestion_ops *ca_ops
3072 = inet_csk(sk)->icsk_ca_ops; 3071 = inet_csk(sk)->icsk_ca_ops;
3073 3072
3073 tcp_rearm_rto(sk);
3074 if (unlikely(icsk->icsk_mtup.probe_size && 3074 if (unlikely(icsk->icsk_mtup.probe_size &&
3075 !after(tp->mtu_probe.probe_seq_end, tp->snd_una))) { 3075 !after(tp->mtu_probe.probe_seq_end, tp->snd_una))) {
3076 tcp_mtup_probe_success(sk); 3076 tcp_mtup_probe_success(sk);
@@ -3109,6 +3109,13 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
3109 3109
3110 ca_ops->pkts_acked(sk, pkts_acked, rtt_us); 3110 ca_ops->pkts_acked(sk, pkts_acked, rtt_us);
3111 } 3111 }
3112 } else if (skb && rtt_update && sack_rtt >= 0 &&
3113 sack_rtt > (s32)(now - TCP_SKB_CB(skb)->when)) {
3114 /* Do not re-arm RTO if the sack RTT is measured from data sent
3115 * after when the head was last (re)transmitted. Otherwise the
3116 * timeout may continue to extend in loss recovery.
3117 */
3118 tcp_rearm_rto(sk);
3112 } 3119 }
3113 3120
3114#if FASTRETRANS_DEBUG > 0 3121#if FASTRETRANS_DEBUG > 0