Re: TCP push sometimes missing under 2.2.5?

Andi Kleen (ak@muc.de)
10 Apr 1999 09:03:40 +0200


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 is like TV. I don't like TV.

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