Commit d716bfdb authored by Yuchung Cheng's avatar Yuchung Cheng Committed by David S. Miller

tcp: account lost retransmit after timeout

The previous approach for the lost and retransmit bits was to
wipe the slate clean: zero all the lost and retransmit bits,
correspondingly zero the lost_out and retrans_out counters, and
then add back the lost bits (and correspondingly increment lost_out).

The new approach is to treat this very much like marking packets
lost in fast recovery. We don’t wipe the slate clean. We just say
that for all packets that were not yet marked sacked or lost, we now
mark them as lost in exactly the same way we do for fast recovery.

This fixes the lost retransmit accounting at RTO time and greatly
simplifies the RTO code by sharing much of the logic with Fast
Recovery.
Signed-off-by: default avatarYuchung Cheng <ycheng@google.com>
Signed-off-by: default avatarNeal Cardwell <ncardwell@google.com>
Reviewed-by: default avatarEric Dumazet <edumazet@google.com>
Reviewed-by: default avatarSoheil Hassas Yeganeh <soheil@google.com>
Reviewed-by: default avatarPriyaranjan Jha <priyarjha@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6ac06ecd
...@@ -1877,6 +1877,7 @@ void tcp_v4_init(void); ...@@ -1877,6 +1877,7 @@ void tcp_v4_init(void);
void tcp_init(void); void tcp_init(void);
/* tcp_recovery.c */ /* tcp_recovery.c */
void tcp_mark_skb_lost(struct sock *sk, struct sk_buff *skb);
void tcp_newreno_mark_lost(struct sock *sk, bool snd_una_advanced); void tcp_newreno_mark_lost(struct sock *sk, bool snd_una_advanced);
extern void tcp_rack_mark_lost(struct sock *sk); extern void tcp_rack_mark_lost(struct sock *sk);
extern void tcp_rack_advance(struct tcp_sock *tp, u8 sacked, u32 end_seq, extern void tcp_rack_advance(struct tcp_sock *tp, u8 sacked, u32 end_seq,
......
...@@ -1929,7 +1929,6 @@ void tcp_enter_loss(struct sock *sk) ...@@ -1929,7 +1929,6 @@ void tcp_enter_loss(struct sock *sk)
struct sk_buff *skb; struct sk_buff *skb;
bool new_recovery = icsk->icsk_ca_state < TCP_CA_Recovery; bool new_recovery = icsk->icsk_ca_state < TCP_CA_Recovery;
bool is_reneg; /* is receiver reneging on SACKs? */ bool is_reneg; /* is receiver reneging on SACKs? */
bool mark_lost;
/* Reduce ssthresh if it has not yet been made inside this window. */ /* Reduce ssthresh if it has not yet been made inside this window. */
if (icsk->icsk_ca_state <= TCP_CA_Disorder || if (icsk->icsk_ca_state <= TCP_CA_Disorder ||
...@@ -1945,9 +1944,6 @@ void tcp_enter_loss(struct sock *sk) ...@@ -1945,9 +1944,6 @@ void tcp_enter_loss(struct sock *sk)
tp->snd_cwnd_cnt = 0; tp->snd_cwnd_cnt = 0;
tp->snd_cwnd_stamp = tcp_jiffies32; tp->snd_cwnd_stamp = tcp_jiffies32;
tp->retrans_out = 0;
tp->lost_out = 0;
if (tcp_is_reno(tp)) if (tcp_is_reno(tp))
tcp_reset_reno_sack(tp); tcp_reset_reno_sack(tp);
...@@ -1959,21 +1955,13 @@ void tcp_enter_loss(struct sock *sk) ...@@ -1959,21 +1955,13 @@ void tcp_enter_loss(struct sock *sk)
/* Mark SACK reneging until we recover from this loss event. */ /* Mark SACK reneging until we recover from this loss event. */
tp->is_sack_reneg = 1; tp->is_sack_reneg = 1;
} }
tcp_clear_all_retrans_hints(tp);
skb_rbtree_walk_from(skb) { skb_rbtree_walk_from(skb) {
mark_lost = (!(TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED) || if (is_reneg)
is_reneg);
if (mark_lost)
tcp_sum_lost(tp, skb);
TCP_SKB_CB(skb)->sacked &= (~TCPCB_TAGBITS)|TCPCB_SACKED_ACKED;
if (mark_lost) {
TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_ACKED; TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_ACKED;
TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; tcp_mark_skb_lost(sk, skb);
tp->lost_out += tcp_skb_pcount(skb);
}
} }
tcp_verify_left_out(tp); tcp_verify_left_out(tp);
tcp_clear_all_retrans_hints(tp);
/* Timeout in disordered state after receiving substantial DUPACKs /* Timeout in disordered state after receiving substantial DUPACKs
* suggests that the degree of reordering is over-estimated. * suggests that the degree of reordering is over-estimated.
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
#include <linux/tcp.h> #include <linux/tcp.h>
#include <net/tcp.h> #include <net/tcp.h>
static void tcp_rack_mark_skb_lost(struct sock *sk, struct sk_buff *skb) void tcp_mark_skb_lost(struct sock *sk, struct sk_buff *skb)
{ {
struct tcp_sock *tp = tcp_sk(sk); struct tcp_sock *tp = tcp_sk(sk);
...@@ -95,7 +95,7 @@ static void tcp_rack_detect_loss(struct sock *sk, u32 *reo_timeout) ...@@ -95,7 +95,7 @@ static void tcp_rack_detect_loss(struct sock *sk, u32 *reo_timeout)
remaining = tp->rack.rtt_us + reo_wnd - remaining = tp->rack.rtt_us + reo_wnd -
tcp_stamp_us_delta(tp->tcp_mstamp, skb->skb_mstamp); tcp_stamp_us_delta(tp->tcp_mstamp, skb->skb_mstamp);
if (remaining <= 0) { if (remaining <= 0) {
tcp_rack_mark_skb_lost(sk, skb); tcp_mark_skb_lost(sk, skb);
list_del_init(&skb->tcp_tsorted_anchor); list_del_init(&skb->tcp_tsorted_anchor);
} else { } else {
/* Record maximum wait time */ /* Record maximum wait time */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment