
This patch implements SendBufferSize, a directive to set the size of
the TCP send-buffer.  On many systems the default send-buffer size is
too small to support full-rate transfer over high
bandwidth-delay-product networks (such as cross-US Internet traffic).
For example, a 100ms round-trip time (typical cross-US latency) and a
4kB default buffer size (common to many OSes such as SunOS) limit
transfer rate to 40kB/s.

Much better cross-US transfer rates are possible between
well-connected hosts if the send buffer size is increased.  A patch at
<http://www.isi.edu/~johnh/SOFTWARE/APACHE/apache_1.1.1_isi_set_sndbuf.patch>
[this patch] implements the SendBufferSize directive to allow Apache
to have a configurable buffer size.

A complete description of this directive is in the file
send_buffer_size.html which accompanies the patch.  For a pointer to
other patches, see <http://www.isi.edu/~johnh/SOFTWARE/APACHE>.  For
descriptions of the problems motivating these patches, see
<http://www.isi.edu/~johnh/PAPERS/Heidemann94b.html>.

   -John Heidemann
    USC/ISI
    28-Oct-96

----------------------------------------------------------------------

Index: send_buffer_size.html
diff -c /dev/null lsam/apache/src/send_buffer_size.html:1.2
*** /dev/null	Mon Oct 28 15:27:27 1996
--- lsam/apache/src/send_buffer_size.html	Mon Oct 28 15:24:36 1996
***************
*** 0 ****
--- 1,33 ----
+ 
+ <!--
+   -- This documentation for SendBufferSize should go in core.html.
+   -- -johnh, 25-Oct-96
+   -->
+ 
+ <A name="sendbuffersize"><h2>SendBufferSize directive</h2></A>
+ <!--%plaintext &lt;?INDEX {\tt SendBufferSize} directive&gt; -->
+ <strong>Syntax:</strong> SendBufferSize <em>number</em><br>
+ <strong>Default:</strong> system dependent, often 4kB to 16kB<br>
+ <strong>Context:</strong> server config<br>
+ <strong>Status:</strong> core<p>
+ 
+ The SendBufferSize directive sets the size of the TCP send buffer
+   as specified in bytes.
+ 
+ To send data over high bandwidth-delay connections at full
+ speed we must the TCP window to open wide enough to keep the
+ pipe full.  Default the default window size on many systems
+ is only 4kB.  Cross-country WAN connections of 100ms
+ at 1Mb/s are not impossible for well connected sites in 1995.
+ If we assume 100ms cross-country latency,
+ a 4kB buffer limits throughput to 40kB/s.
+ 
+ The default is system dependent, often 4kB to 16kB.
+ Setting it larger than the default consumes more kernel memory
+ per connection but allows better performance for wide-area connections.
+ A value of 16384 is probably good for most networks;
+   8kB is good if you're connected by less than a T1 link.
+  
+ This value is Apache-wide, not per-virtual server.
+ 
+ 
Index: http_config.c
diff -c lsam/apache/src/http_config.c:1.1.1.2 lsam/apache/src/http_config.c:1.2
*** lsam/apache/src/http_config.c:1.1.1.2	Thu Jul 18 10:13:38 1996
--- lsam/apache/src/http_config.c	Fri Oct 25 16:39:48 1996
***************
*** 705,710 ****
--- 705,715 ----
  
  	if (virt->keep_alive == -1)
  	    virt->keep_alive = main_server->keep_alive;
+ 
+ #ifdef ISI_SET_SNDBUF
+ 	if (virt->send_buffer_size == 0)
+ 		virt->send_buffer_size = main_server->send_buffer_size;
+ #endif /* ISI_SET_SNDBUF */
      }
  }
  
Index: http_core.c
diff -c lsam/apache/src/http_core.c:1.3 lsam/apache/src/http_core.c:1.4
*** lsam/apache/src/http_core.c:1.3	Thu Jul 18 11:12:34 1996
--- lsam/apache/src/http_core.c	Fri Oct 25 16:39:49 1996
***************
*** 637,642 ****
--- 637,653 ----
      return NULL;
  }
  
+ #ifdef ISI_SET_SNDBUF
+ char *set_send_buffer_size (cmd_parms *cmd, void *dummy, char *arg) {
+     int s = atoi (arg);
+     if (s < 512 && s != 0) {
+ 	return "SendBufferSize must be >= 512 bytes, or 0 for system default.";
+     }
+     cmd->server->send_buffer_size = s;
+     return NULL;
+ }
+ #endif /* ISI_SET_SNDBUF */
+ 
  char *set_user (cmd_parms *cmd, void *dummy, char *arg) {
      user_name = pstrdup (cmd->pool, arg);
      user_id = uname2id (user_name);
***************
*** 847,852 ****
--- 858,866 ----
    "'*', a numeric IP address, or the name of a host with a unique IP address"},
  { "Listen", set_listener, NULL, RSRC_CONF, TAKE1,
        "a port number or a numeric IP address and a port number"},
+ #ifdef ISI_SET_SNDBUF
+ { "SendBufferSize", set_send_buffer_size, NULL, RSRC_CONF, TAKE1, "send buffer size in bytes"},
+ #endif /* ISI_SET_SNDBUF */
  { "<VirtualHost", virtualhost_section, NULL, RSRC_CONF, RAW_ARGS, NULL },
  { "</VirtualHost>", end_virtualhost_section, NULL, RSRC_CONF, NO_ARGS, NULL },
  { NULL },
Index: http_main.c
diff -c lsam/apache/src/http_main.c:1.7 lsam/apache/src/http_main.c:1.9
*** lsam/apache/src/http_main.c:1.7	Thu Jul 18 18:14:36 1996
--- lsam/apache/src/http_main.c	Mon Oct 28 15:24:34 1996
***************
*** 1394,1399 ****
--- 1394,1428 ----
      }
  #endif  /* NEED_LINGER */
  
+ #ifdef ISI_SET_SNDBUF
+     /*
+      * To send data over high bandwidth-delay connections at full
+      * speed we must the TCP window to open wide enough to keep the
+      * pipe full.  Default the default window size on many systems
+      * is only 4kB.  Cross-country WAN connections of 100ms
+      * at 1Mb/s are not impossible for well connected sites in 1995.
+      * If we assume 100ms cross-country latency,
+      * a 4kB buffer limits throughput to 40kB/s.
+      *
+      * To avoid this problem I've added the SendBufferSize directive
+      * to allow the web master to configure send buffer size.
+      *
+      * The trade-off of larger buffers is that more kernel memory
+      * is consumed.  YMMV, know your customers and your network!
+      *
+      * -John Heidemann <johnh@isi.edu> 25-Oct-96
+      *
+      *
+      * If no size is specified, use the kernel default.
+      */
+     if (server_conf->send_buffer_size) {
+         if((setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char*)&server_conf->send_buffer_size, sizeof(int))) < 0) {
+ 	    perror("setsockopt(SO_SNDBUF), using default buffer size"); 
+ 	    /* Fail soft. */
+ 	}
+     }
+ #endif /* ISI_SET_SNDBUF */
+ 
      if(bind(s, (struct sockaddr *)server,sizeof(struct sockaddr_in)) == -1)
      {
          perror("bind");
Index: httpd.h
diff -c lsam/apache/src/httpd.h:1.5 lsam/apache/src/httpd.h:1.6
*** lsam/apache/src/httpd.h:1.5	Thu Jul 18 11:12:44 1996
--- lsam/apache/src/httpd.h	Fri Oct 25 16:39:54 1996
***************
*** 500,505 ****
--- 500,508 ----
    int timeout;			/* Timeout, in seconds, before we give up */
    int keep_alive_timeout;	/* Seconds we'll wait for another request */
    int keep_alive;		/* Maximum requests per connection */
+ #ifdef ISI_SET_SNDBUF
+   int send_buffer_size;         /* size of TCP send buffer (in bytes) */
+ #endif /* ISI_SET_SNDBUF */
  
    char *path;			/* Pathname for ServerPath */
    int pathlen;			/* Length of path */
