tcp: RACK loss recovery bug fixes
Subsystems (3)
cover tcp: RACK loss recovery bug fixes
This patch set has four minor bug fixes in TCP RACK loss recovery.
Yuchung Cheng (4):
tcp: correctly test congestion state in RACK
tcp: always evaluate losses in RACK upon undo
tcp: fix off-by-one bug in RACK
tcp: evaluate packet losses upon RTT change
net/ipv4/tcp_input.c | 1 + net/ipv4/tcp_recovery.c | 28 +++++++++++++--------------- 2 files changed, 14 insertions(+), 15 deletions(-)
Signature · 1 line
2.15.1.424.g9478a66081-goog
PATCH 1/4 tcp: correctly test congestion state in RACK
RACK does not test the loss recovery state correctly to compute the reordering window. It assumes if lost_out is zero then TCP is not in loss recovery. But it can be zero during recovery before calling tcp_rack_detect_loss(): when an ACK acknowledges all packets marked lost before receiving this ACK, but has not yet to discover new ones by tcp_rack_detect_loss(). The fix is to simply test the congestion state directly.
--- net/ipv4/tcp_recovery.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/ipv4/tcp_recovery.c +2 -1
@@ -55,7 +55,8 @@ static void tcp_rack_detect_loss(struct sock *sk, u32 *reo_timeout)* to queuing or delayed ACKs. */ reo_wnd =1000 ; -if ((tp->rack.reord || !tp->lost_out) && min_rtt != ~0U ) { +if ((tp->rack.reord ||inet_csk (sk)->icsk_ca_state < TCP_CA_Recovery) && + min_rtt != ~0U ) { reo_wnd =max ((min_rtt >>2 ) * tp->rack.reo_wnd_steps, reo_wnd); reo_wnd =min (reo_wnd, tp->srtt_us >>3 ); }
Signature · 1 line
2.15.1.424.g9478a66081-goog
PATCH 2/4 tcp: always evaluate losses in RACK upon undo
In reply to Yuchung ChengWhen sender detects spurious retransmission, all packets marked lost are remarked to be in-flight. However some may be considered lost based on its timestamps in RACK. This patch forces RACK to re-evaluate, which may be skipped previously if the ACK does not advance RACK timestamp.
--- net/ipv4/tcp_input.c | 1 + 1 file changed, 1 insertion(+)
net/ipv4/tcp_input.c +1 -0
@@ -2326,6 +2326,7 @@ static void tcp_undo_cwnd_reduction(struct sock *sk, bool unmark_loss) } tp->snd_cwnd_stamp = tcp_jiffies32; tp->undo_marker =0 ; + tp->rack.advanced =1 ;/* Force RACK to re-exam losses */ }static inline bool tcp_may_undo (const struct tcp_sock *tp)
Signature · 1 line
2.15.1.424.g9478a66081-goog
PATCH 3/4 tcp: fix off-by-one bug in RACK
In reply to Yuchung ChengRACK should mark a packet lost when remaining wait time is zero.
--- net/ipv4/tcp_recovery.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
net/ipv4/tcp_recovery.c +3 -3
@@ -80,12 +80,12 @@ static void tcp_rack_detect_loss(struct sock *sk, u32 *reo_timeout)*/ remaining = tp->rack.rtt_us + reo_wnd -tcp_stamp_us_delta (tp->tcp_mstamp, skb->skb_mstamp); -if (remaining <0 ) { +if (remaining <=0 ) {tcp_rack_mark_skb_lost (sk, skb);list_del_init (&skb->tcp_tsorted_anchor); }else { -/* Record maximum wait time (+1 to avoid 0) */ - *reo_timeout =max_t (u32, *reo_timeout,1 + remaining); +/* Record maximum wait time */ + *reo_timeout =max_t (u32, *reo_timeout, remaining); } } }
Signature · 1 line
2.15.1.424.g9478a66081-goog
PATCH 4/4 tcp: evaluate packet losses upon RTT change
In reply to Yuchung ChengRACK skips an ACK unless it advances the most recently delivered TX timestamp (rack.mstamp). Since RACK also uses the most recent RTT to decide if a packet is lost, RACK should still run the loss detection whenever the most recent RTT changes. For example, an ACK that does not advance the timestamp but triggers the cwnd undo due to reordering, would then use the most recent (higher) RTT measurement to detect further losses.
--- net/ipv4/tcp_recovery.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-)
net/ipv4/tcp_recovery.c +8 -11
@@ -117,13 +117,8 @@ void tcp_rack_advance(struct tcp_sock *tp, u8 sacked, u32 end_seq, {u32 rtt_us; -if (tp->rack.mstamp && - !tcp_rack_sent_after (xmit_time, tp->rack.mstamp, - end_seq, tp->rack.end_seq)) -return ; - rtt_us =tcp_stamp_us_delta (tp->tcp_mstamp, xmit_time); -if (sacked &TCPCB_RETRANS ) { +if (rtt_us <tcp_min_rtt (tp) && (sacked &TCPCB_RETRANS )) {/* If the sacked packet was retransmitted, it's ambiguous * whether the retransmission or the original (or the prior * retransmission) was sacked.
@@ -134,13 +129,15 @@ void tcp_rack_advance(struct tcp_sock *tp, u8 sacked, u32 end_seq,* so it's at least one RTT (i.e., retransmission is at least * an RTT later). */ -if (rtt_us <tcp_min_rtt (tp)) -return ; +return ; } - tp->rack.rtt_us = rtt_us; - tp->rack.mstamp = xmit_time; - tp->rack.end_seq = end_seq; tp->rack.advanced =1 ; + tp->rack.rtt_us = rtt_us; +if (tcp_rack_sent_after (xmit_time, tp->rack.mstamp, + end_seq, tp->rack.end_seq)) { + tp->rack.mstamp = xmit_time; + tp->rack.end_seq = end_seq; + } }/* We have waited long enough to accommodate reordering. Mark the expired
Signature · 1 line
2.15.1.424.g9478a66081-goog
David Miller
maintainerFrom: Yuchung Cheng <[email protected]>
Date: Thu, 7 Dec 2017 11:33:29 -0800
Quoted 1 line
This patch set has four minor bug fixes in TCP RACK loss recovery.
Series applied, thank you.