The TCP stack is notified every time userland reads from the TCP socket
authorMatthew Dillon <dillon@dragonflybsd.org>
Tue, 3 Aug 2004 00:25:54 +0000 (00:25 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Tue, 3 Aug 2004 00:25:54 +0000 (00:25 +0000)
commitddb2e271c78b411819c6e45b1ab0db8cc2f0c8fa
treec918c512974d5f06296b1f4630de3bde27d2df40
parent2b1ce38a26291667d9ed98c77d898c34e1aae541
The TCP stack is notified every time userland reads from the TCP socket
buffer, because a pure-window-update ACK might be required.  The previous
code would send a pure window update once the difference between the last
advertised window and the current window exceeded 2 segments and also when it
exceeded 1/2 the high water mark.

On GigE networks this can cause a pure window update to occur once every
8 packets (resulting in 5 acks instead of 4) prior to the TCP t_outputq
commit and once every 8 packets (resulting in 2 acks instead of 1) after
the TCP t_outputq commit.  So on a GigE network servicing a high performance
TCP stream, the result is double the number of acks that are actually
necessary.

Conditionalize the 2 segment test with a sysctl.  The sysctl is
net.inet.tcp.avoid_pure_win_update and is set to 1 by default, meaning
that the 2 segment ack does NOT occur (i.e. we should get higher
performance).  It may be turned off to revert to the prior two-ack
algorithm.

This code is considered experimental but since it involves only a pure
window update and we still have the catch-all case this commit is enabling
the new algorithm.  Further tuning might be required, possibly reducing the
1/2 hiwat test to 1/3 or 1/4 hiwat.

Ideally we want to avoid pure window update acks entirely in the normal
streaming case, which means we want to have a TCP buffer that is large
enough to pipeline the networked stream AND the process consuming the data.
On a GigE network this typically equates to the packet batching that occurs
per interrupt.  This batching is typically 8 1448 byte segments == ~11K,
plus turn around overhead and the 1/2 hiwat test so we want an incoming
socket buffer of at least ~11K * 2 + slop which should come to around ~32K
in order to avoid sending (unnecessary) pure window updates on a high
performance TCP stream.
sys/netinet/tcp_output.c