Re: TCP push sometimes missing under 2.2.5?

Jens-Uwe Mager (jum@ra.han.de)
Tue, 13 Apr 1999 00:35:41 +0200


On Sat, Apr 10, 1999 at 09:03:40AM +0200, Andi Kleen wrote:
> jum@ra.han.de (Jens-Uwe Mager) writes:
>
> > I am seeing strange performance problems on an application that sends
> > records across a TCP socket using writev (Nagle is turned off). I am using
> > writev with two iovec's, one with a fixed length header and another one
> > with the data payload. Upon sniffing the Ethernet I see that on some of
> > the short writev's the TCP push bit is not set as the client in question
> > (MacOS 8.5.1 with OpenTransport) does delay it's ACK about 50ms if the
> > PUSH bit is not set. Ok, it is a bit strange that the Mac uses the PUSH
> > bit in that way, but I cannot change that.
> >
> > The problem does not appear with 2.0.36, there the PUSH bit is always set
> > on the last packet after all data that belong to one write are sent. I
> > played a bit with the PSH_NEEDED macro and if I always send a PUSH the
> > performance problem with small packets goes away, but larger writev's that
> > need the windows do run much slower due to the many ACK's induced by the
> > PUSH bits. I looked at the logic in tcp.c and I fail to understand why the
> > PUSH bit is not set on some of the packets. Does anybody have any idea?
>
> PSH is not set when a part of the write exceeds the usable window.
> This OpenTransport behaviour is really stupid. Does this small
> patch fix it? It adds some cycles to a fast path, but I see no better
> way.
>
> -Andi
>
> --- linux/net/ipv4/tcp.c.~2~ Wed Mar 24 18:45:04 1999
> +++ linux/net/ipv4/tcp.c Sat Apr 10 09:00:12 1999
> @@ -773,6 +773,7 @@
>
> while(seglen > 0) {
> int copy, tmp, queue_it;
> + int psh;
>
> if (err)
> goto do_fault2;
> @@ -854,9 +855,10 @@
> * being outside the window, it will be queued
> * for later rather than sent.
> */
> + psh = 0;
> copy = tp->snd_wnd - (tp->snd_nxt - tp->snd_una);
> if(copy > (tp->max_window >> 1))
> - copy = min(copy, mss_now);
> + copy = min(copy, mss_now), psh = 1;
> else
> copy = mss_now;
> if(copy > seglen)
> @@ -906,7 +908,7 @@
>
> /* Prepare control bits for TCP header creation engine. */
> TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK |
> - (PSH_NEEDED ?
> + ((PSH_NEEDED || psh) ?
> TCPCB_FLAG_PSH : 0));
> TCP_SKB_CB(skb)->sacked = 0;
> if (flags & MSG_OOB) {
>
>

This patch forks fine. I have tested various scenarios: small transactions
(ping-pong), small transactions intermixed with some with more data so
windowing starts, and long transfers with large windows. There are no
superfluous 50ms delays any more on the Mac side, and no superfluous
ACK's either.

Thanks a lot!

-- 
Jens-Uwe Mager	<pgp-mailto:62CFDB25>

- 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/