Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 175546
b: refs/heads/master
c: 77722b1
h: refs/heads/master
v: v3
  • Loading branch information
Ilpo Järvinen authored and David S. Miller committed Dec 9, 2009
1 parent a06144e commit 2e8aa42
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 4 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 2f7de5710a4d394920405febc2a9937c69e16dda
refs/heads/master: 77722b177a1606669c0b95dde03347e37d13b8fe
35 changes: 32 additions & 3 deletions trunk/net/ipv4/tcp_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -2717,6 +2717,35 @@ static void tcp_try_undo_dsack(struct sock *sk)
}
}

/* We can clear retrans_stamp when there are no retransmissions in the
* window. It would seem that it is trivially available for us in
* tp->retrans_out, however, that kind of assumptions doesn't consider
* what will happen if errors occur when sending retransmission for the
* second time. ...It could the that such segment has only
* TCPCB_EVER_RETRANS set at the present time. It seems that checking
* the head skb is enough except for some reneging corner cases that
* are not worth the effort.
*
* Main reason for all this complexity is the fact that connection dying
* time now depends on the validity of the retrans_stamp, in particular,
* that successive retransmissions of a segment must not advance
* retrans_stamp under any conditions.
*/
static int tcp_any_retrans_done(struct sock *sk)
{
struct tcp_sock *tp = tcp_sk(sk);
struct sk_buff *skb;

if (tp->retrans_out)
return 1;

skb = tcp_write_queue_head(sk);
if (unlikely(skb && TCP_SKB_CB(skb)->sacked & TCPCB_EVER_RETRANS))
return 1;

return 0;
}

/* Undo during fast recovery after partial ACK. */

static int tcp_try_undo_partial(struct sock *sk, int acked)
Expand All @@ -2729,7 +2758,7 @@ static int tcp_try_undo_partial(struct sock *sk, int acked)
/* Plain luck! Hole if filled with delayed
* packet, rather than with a retransmit.
*/
if (tp->retrans_out == 0)
if (!tcp_any_retrans_done(sk))
tp->retrans_stamp = 0;

tcp_update_reordering(sk, tcp_fackets_out(tp) + acked, 1);
Expand Down Expand Up @@ -2788,7 +2817,7 @@ static void tcp_try_keep_open(struct sock *sk)
struct tcp_sock *tp = tcp_sk(sk);
int state = TCP_CA_Open;

if (tcp_left_out(tp) || tp->retrans_out || tp->undo_marker)
if (tcp_left_out(tp) || tcp_any_retrans_done(sk) || tp->undo_marker)
state = TCP_CA_Disorder;

if (inet_csk(sk)->icsk_ca_state != state) {
Expand All @@ -2803,7 +2832,7 @@ static void tcp_try_to_open(struct sock *sk, int flag)

tcp_verify_left_out(tp);

if (!tp->frto_counter && tp->retrans_out == 0)
if (!tp->frto_counter && !tcp_any_retrans_done(sk))
tp->retrans_stamp = 0;

if (flag & FLAG_ECE)
Expand Down

0 comments on commit 2e8aa42

Please sign in to comment.