Re: [PATCH] Re: Very poor TCP/SACK performance

Vijay G. Bharadwaj (vgb@isr.umd.edu)
Thu, 10 Sep 1998 13:17:18 -0400 (EDT)


I see I made some stupid claims here, let me apologize and clarify...

On Thu, 10 Sep 1998, Savochkin Andrey Vladimirovich wrote:

> I can't comment the first two problems but both the explanation
> and the fix for the third problem is wrong.
> 1. I suppose you don't remember the RFC statements about zero window
> probing at all. TCP of course isn't obliged to always accept one byte of
> data.

RFC 793, page 42, "Managing the window" states that the *sending* TCP
should always accept one byte of new data to send. I ended up suggesting
that the *receiving* TCP should always accept a new byte, which was wrong.
However the problem pointed out in Linux still exists (I have observed it
in the lab on a number of occasions). Here's what happens:

1) Sender sends a lot of data, fills up window
2) Receiver advertises zero window.
3) Sender sends a probe, and the probe has one new octet
4) Receiver accepts this octet, and still advertises zero window (In older
versions, the receive_window wraps and so opens up to 64K, but not in
newer versions, as you observe and as I pointed out)
5) Back to step 3.

This goes on for a long time (does SWS avoidance contribute by not
advertising a window of (MSS-1)? I don't know and I haven't looked)

I first observed this on a fast ethernet to a solaris 2.6 box, with a very
slow app on the linux box.

Another mistake I made - neither RFC 793 nor 1122 states what should be in
a zero window probe. A *keepalive* should contain a garbage octet (but Sun
I think sends a new byte; I remember a flamewar on tcp-impl). So a probe
with one new octet is legal.

Third mistake - related to the first one - I was wrong to say this change
violates any RFC.

> 2. Problem with window wrapping below zero was fixed ages ago.

Agreed. I pointed that out in my mail. However, it doesn't fix the above
problem. Also, with this check in, we may not need that check for (win <
0) in tcp_receive_window() any more (I don't see any other code path that
can cause the wrap)

> 3. The suggested fix wastes CPU cycles in a speed critical part.
> It has no sense to do extra comparisons when we've just checked
> that `TCP_SKB_CB(skb)->seq == tp->rcv_nxt'. And no
> sequence check is required for the bulk sender path.
> The only thing that may have a sense is to move the check
> `!before(TCP_SKB_CB(skb)->seq, tp->rcv_wup + tp->rcv_wnd)'
> just before the socket space check.

I agree with this one. No sequence check is required for the data sender
part. And what you suggest is correct, the check for !before(..) (isn't
this identical to the !tcp_sequence() check?) should be moved to before
the socket space check, because socket space is usually available even if
window is zero, due to the way the offered window is chosen.

But the check is still required, due to the problem outlined above. There
is simply no other check in the code to reject segments received into a
zero window.

Regards,

-Vijay

PS - I got an interesting "TCP stall" with a Linux client in the problem
case I mentioned. The wrapped receive window caused the receiver to
advertize a 64K window, which was not a multiple of MSS. So when this
window filled up, the last remaining chunk was not MSS-sized. When NT4.0
sees an advertized window less than MSS, it waits for an interval equal to
a retransmission timeout before sending a packet...

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/faq.html