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

tcp: undo_retrans counter fixes

Fix a bug that undo_retrans is incorrectly decremented when undo_marker is
not set or undo_retrans is already 0. This happens when sender receives
more DSACK ACKs than packets retransmitted during the current
undo phase. This may also happen when sender receives DSACK after
the undo operation is completed or cancelled.

Fix another bug that undo_retrans is incorrectly incremented when
sender retransmits an skb and tcp_skb_pcount(skb) > 1 (TSO). This case
is rare but not impossible.
Signed-off-by: default avatarYuchung Cheng <ycheng@google.com>
Acked-by: default avatarIlpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5f04d506
...@@ -1222,7 +1222,7 @@ static int tcp_check_dsack(struct sock *sk, struct sk_buff *ack_skb, ...@@ -1222,7 +1222,7 @@ static int tcp_check_dsack(struct sock *sk, struct sk_buff *ack_skb,
} }
/* D-SACK for already forgotten data... Do dumb counting. */ /* D-SACK for already forgotten data... Do dumb counting. */
if (dup_sack && if (dup_sack && tp->undo_marker && tp->undo_retrans &&
!after(end_seq_0, prior_snd_una) && !after(end_seq_0, prior_snd_una) &&
after(end_seq_0, tp->undo_marker)) after(end_seq_0, tp->undo_marker))
tp->undo_retrans--; tp->undo_retrans--;
...@@ -1299,7 +1299,8 @@ static u8 tcp_sacktag_one(struct sk_buff *skb, struct sock *sk, ...@@ -1299,7 +1299,8 @@ static u8 tcp_sacktag_one(struct sk_buff *skb, struct sock *sk,
/* Account D-SACK for retransmitted packet. */ /* Account D-SACK for retransmitted packet. */
if (dup_sack && (sacked & TCPCB_RETRANS)) { if (dup_sack && (sacked & TCPCB_RETRANS)) {
if (after(TCP_SKB_CB(skb)->end_seq, tp->undo_marker)) if (tp->undo_marker && tp->undo_retrans &&
after(TCP_SKB_CB(skb)->end_seq, tp->undo_marker))
tp->undo_retrans--; tp->undo_retrans--;
if (sacked & TCPCB_SACKED_ACKED) if (sacked & TCPCB_SACKED_ACKED)
state->reord = min(fack_count, state->reord); state->reord = min(fack_count, state->reord);
......
...@@ -2162,7 +2162,7 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) ...@@ -2162,7 +2162,7 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
if (!tp->retrans_stamp) if (!tp->retrans_stamp)
tp->retrans_stamp = TCP_SKB_CB(skb)->when; tp->retrans_stamp = TCP_SKB_CB(skb)->when;
tp->undo_retrans++; tp->undo_retrans += tcp_skb_pcount(skb);
/* snd_nxt is stored to detect loss of retransmitted segment, /* snd_nxt is stored to detect loss of retransmitted segment,
* see tcp_input.c tcp_sacktag_write_queue(). * see tcp_input.c tcp_sacktag_write_queue().
......
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