[PATCH] Re: TCP_DEFER_ACCEPT possible bug + documentation patch for tcp.7

From: bert hubert (ahu@ds9a.nl)
Date: Sun Oct 22 2000 - 08:17:20 EST


On Sun, Oct 22, 2000 at 02:03:37PM +0200, bert hubert wrote:

> From a userland perspective, it works very well. It just wastes packets.
>
> > Sorry for advertising it as a working feature.
>
> The fix should be easy. I'm looking in to it.

This patch fixes TCP_DEFER_ACCEPT support. First the patch for the manpage, so we know what it's
all about:

diff -c -r old/tcp.7 new/tcp.7
*** old/tcp.7 Sat Oct 21 20:42:10 2000
--- new/tcp.7 Sat Oct 21 20:41:50 2000
***************
*** 209,214 ****
--- 209,222 ----
  .BR sendfile (2),
  or for throughput optimization. This option cannot be combined with
  .BR TCP_NODELAY .
+ .TP
+ .B TCP_DEFER_ACCEPT
+ Instruct the kernel to do connection preprocessing and not to wake the
+ process until the first packet of real data has arrived. Especially useful
+ for webservers, which needn't pay attention during the time between completion
+ of the TCP handshake and the arrival of the first data packet. The integer value
+ passed is interpreted as the time to wait before the arrival of data before
+ giving up the connection.
  .SH IOCTLS
  These ioctls can be accessed using
  .BR ioctl (2).

The problem was that when waiting for the first packet, the kernel would
emit SYNACKs on the regular retransmit schedule, until the first packet of
data arrived. This is a side effect of the timeout implementation.

The patch is pretty obvious, but it obfuscates an already non-trivial if statement.
The new code, followed by the patch:

tcp_timer.c:
        if ((req->retrans < thresh ||
             (req->acked && req->retrans < max_retries))
            && (tp->defer_accept || !req->class->rtx_syn_ack(sk, req, NULL))) {
                unsigned long timeo;

                if (req->retrans++ == 0)
                        lopt->qlen_young--;
                timeo = min((TCP_TIMEOUT_INIT << req->retrans),
                            TCP_RTO_MAX);
                req->expires = now + timeo;
                reqp = &req->dl_next;
                continue;
        }

--- tcp_timer.c~old Sun Oct 22 13:46:56 2000
+++ tcp_timer.c Sun Oct 22 14:16:27 2000
@@ -670,7 +670,7 @@
                         if ((long)(now - req->expires) >= 0) {
                                 if ((req->retrans < thresh ||
                                      (req->acked && req->retrans < max_retries))
- && !req->class->rtx_syn_ack(sk, req, NULL)) {
+ && (tp->defer_accept || !req->class->rtx_syn_ack(sk, req, NULL))) {
                                         unsigned long timeo;
 
                                         if (req->retrans++ == 0)

Please apply.

Regards,

bert hubert

-- 
PowerDNS                     Versatile DNS Services  
Trilab                       The Technology People   
'SYN! .. SYN|ACK! .. ACK!' - the mating call of the internet
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Mon Oct 23 2000 - 21:00:19 EST