Message ID | alpine.DEB.2.00.0912071532080.7024@wel-95.cs.helsinki.fi |
---|---|
State | Accepted, archived |
Delegated to: | David Miller |
Headers | show |
Le Mon, 7 Dec 2009 16:01:53 +0200 (EET), "Ilpo Järvinen" <ilpo.jarvinen@helsinki.fi> a écrit : > On Sat, 5 Dec 2009, Damian Lukowski wrote: > > > Could you please make another test and unplug the cable or drop > > [...] > After taking some more look into this, this is partly a red herring. > It looks like that because of the place of the printk that was still > in the end of the function. You can see the full trace of what > happens in .13., they come from independent incarnations of RTO > recovery (when finally no error happens in tcp_retransmit_skb). Doh ! Sorry :( > However, the problem itself could occur. Here's the patch which > should prevent that (I'm rather convinced that this really isn't > stable worthy but net-next or net-2.6 would be fine): > > -- > [PATCH] tcp: fix retrans_stamp advancing in error cases > [...] Tonight, I made 2 more tests : .20 and .21 . The first with latest damian patch from today. Added the printk (This time I doubled checked ;). Start the copy, wait 20s, disconnect cable 20s, reconnect. The second try was identical, but I added your patch. The copy was slower comparing to the first try. I didn't took time to understand tcp retransmission timeout and read the code. So, I'm not sure the printk is at the good place and usefull.
Trimmed Ccs. On Mon, 7 Dec 2009, Frederic Leroy wrote: > Le Mon, 7 Dec 2009 16:01:53 +0200 (EET), > "Ilpo Järvinen" <ilpo.jarvinen@helsinki.fi> a écrit : > > > On Sat, 5 Dec 2009, Damian Lukowski wrote: > > > > > Could you please make another test and unplug the cable or drop > > > [...] > > After taking some more look into this, this is partly a red herring. > > It looks like that because of the place of the printk that was still > > in the end of the function. You can see the full trace of what > > happens in .13., they come from independent incarnations of RTO > > recovery (when finally no error happens in tcp_retransmit_skb). > > Doh ! Sorry :( Now I think we have had just too many testcases and are all confused :-). I was referring to the case .11. (the same case as Damian did) ...Not something too newish you did, sorry about that. > > However, the problem itself could occur. Here's the patch which > > should prevent that (I'm rather convinced that this really isn't > > stable worthy but net-next or net-2.6 would be fine): > > > > -- > > [PATCH] tcp: fix retrans_stamp advancing in error cases > > [...] > > Tonight, I made 2 more tests : .20 and .21 . > > The first with latest damian patch from today. > Added the printk (This time I doubled checked ;). > Start the copy, wait 20s, disconnect cable 20s, reconnect. > > The second try was identical, but I added your patch. > The copy was slower comparing to the first try. The losses you are getting are somewhat random process, so it is usually the main explination on different transfer rates. One thing leads to another and therefore one case suffers more than other. > I didn't took time to understand tcp retransmission timeout and read > the code. So, I'm not sure the printk is at the good place and usefull. Thanks anyway for all testing so far. I'll try to come up with the other debug patch tomorrow to get some information on that -EAGAIN. Unless you want to do it yourself and printk all the variables involved in this check (in tcp_output.c): /* Do not sent more than we queued. 1/4 is reserved for possible * copying overhead: fragmentation, tunneling, mangling etc. */ if (atomic_read(&sk->sk_wmem_alloc) > min(sk->sk_wmem_queued + (sk->sk_wmem_queued >> 2), sk->sk_sndbuf)) return -EAGAIN; ...better to print them before the check it regardless of the actual result of the comparison. ...So far only the Damian's patch is clearly required for stable (but I suppose DaveM will handle the stable submissions as usual, hopefully it won't take too long though as some other people might start reporting this same issue once some time has passed and they notice that something is wrong with TCP of their new and shiny 2.6.32 :-)).
From: "Ilpo Järvinen" <ilpo.jarvinen@helsinki.fi> Date: Mon, 7 Dec 2009 16:01:53 +0200 (EET) > [PATCH] tcp: fix retrans_stamp advancing in error cases Applied to net-2.6 Not queued to -stable, let me know if that becomes necessary. Thanks! -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index d86784b..5608691 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -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) @@ -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); @@ -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) { @@ -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)