Author: hrs
Date: Thu Feb 27 19:49:59 2020
New Revision: 358405
URL: https://svnweb.freebsd.org/changeset/base/358405

Log:
  Fix poor performance of ftp(1) due to small SO_SNDBUF and SO_RCVBUF.
  
  ftp(1) from vendor/tnftp always tried the following for
  every TCP connection:
  
  1. Get the current buffer length of SO_SNDBUF and SO_RCVBUF
     by getsockopt(2).
  
  2. Invoke setsockopt(2) to set them to the same values
     after checking if they are in a range between 8 KiB to 8 MiB.
  
  This behavior broke dynamic buffer sizing enabled by
  default (net.inet.tcp.{recv,send}buf_auto sysctls) and
  led to a very poor transfer rate.  The fetch(1) utility
  does not have this problem.
  
  This change prevents SO_SNDBUF and SO_RCVBUF from configuring
  when the buffer auto-sizing is enabled unless the buffer sizes are
  explicitly specified.
  
  PR:           240827
  Spotted by:   Yuichiro NAITO
  MFC after:    3 days
  Differential Revision:        https://reviews.freebsd.org/D23732

Modified:
  head/contrib/tnftp/src/cmds.c
  head/contrib/tnftp/src/ftp_var.h
  head/contrib/tnftp/src/main.c
  head/contrib/tnftp/src/util.c

Modified: head/contrib/tnftp/src/cmds.c
==============================================================================
--- head/contrib/tnftp/src/cmds.c       Thu Feb 27 19:40:29 2020        
(r358404)
+++ head/contrib/tnftp/src/cmds.c       Thu Feb 27 19:49:59 2020        
(r358405)
@@ -2653,10 +2653,14 @@ setxferbuf(int argc, char *argv[])
                goto usage;
        }
 
-       if (dir & RATE_PUT)
+       if (dir & RATE_PUT) {
                sndbuf_size = size;
-       if (dir & RATE_GET)
+               auto_sndbuf = 0;
+       }
+       if (dir & RATE_GET) {
                rcvbuf_size = size;
+               auto_rcvbuf = 0;
+       }
        fprintf(ttyout, "Socket buffer sizes: send %d, receive %d.\n",
            sndbuf_size, rcvbuf_size);
        code = 0;

Modified: head/contrib/tnftp/src/ftp_var.h
==============================================================================
--- head/contrib/tnftp/src/ftp_var.h    Thu Feb 27 19:40:29 2020        
(r358404)
+++ head/contrib/tnftp/src/ftp_var.h    Thu Feb 27 19:49:59 2020        
(r358405)
@@ -298,6 +298,8 @@ GLOBAL      int     options;        /* used during socket 
creation */
 
 GLOBAL int     sndbuf_size;    /* socket send buffer size */
 GLOBAL int     rcvbuf_size;    /* socket receive buffer size */
+GLOBAL int     auto_sndbuf;    /* flag: if != 0 then use auto sndbuf size */
+GLOBAL int     auto_rcvbuf;    /* flag: if != 0 then use auto rcvbuf size */
 
 GLOBAL int     macnum;         /* number of defined macros */
 GLOBAL struct macel macros[16];

Modified: head/contrib/tnftp/src/main.c
==============================================================================
--- head/contrib/tnftp/src/main.c       Thu Feb 27 19:40:29 2020        
(r358404)
+++ head/contrib/tnftp/src/main.c       Thu Feb 27 19:49:59 2020        
(r358405)
@@ -127,6 +127,9 @@ __RCSID(" NetBSD: main.c,v 1.117 2009/07/13 19:05:41 r
 #include <locale.h>
 
 #endif /* tnftp */
+#ifdef __FreeBSD__
+#include <sys/sysctl.h>
+#endif
 
 #define        GLOBAL          /* force GLOBAL decls in ftp_var.h to be 
declared */
 #include "ftp_var.h"
@@ -509,6 +512,13 @@ main(int volatile argc, char **volatile argv)
        (void)xsignal(SIGUSR1, crankrate);
        (void)xsignal(SIGUSR2, crankrate);
        (void)xsignal(SIGWINCH, setttywidth);
+
+       auto_rcvbuf = ((sysctlbyname("net.inet.tcp.recvbuf_auto",
+           &auto_rcvbuf, &(size_t []){[0] = sizeof(int)}[0], NULL, 0) == 0) &&
+           auto_rcvbuf == 1);
+       auto_sndbuf = ((sysctlbyname("net.inet.tcp.sendbuf_auto",
+           &auto_sndbuf, &(size_t []){[0] = sizeof(int)}[0], NULL, 0) == 0) &&
+           auto_sndbuf == 1);
 
        if (argc > 0) {
                if (isupload) {

Modified: head/contrib/tnftp/src/util.c
==============================================================================
--- head/contrib/tnftp/src/util.c       Thu Feb 27 19:40:29 2020        
(r358404)
+++ head/contrib/tnftp/src/util.c       Thu Feb 27 19:49:59 2020        
(r358405)
@@ -1087,13 +1087,27 @@ setupsockbufsize(int sock)
                    sndbuf_size);
        }
 
+#ifdef __FreeBSD__
+       DPRINTF("auto_rcvbuf = %d\n", auto_rcvbuf);
+       if (auto_sndbuf == 0) {
+#endif
        if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF,
            (void *)&sndbuf_size, sizeof(sndbuf_size)) == -1)
                warn("Unable to set sndbuf size %d", sndbuf_size);
+#ifdef __FreeBSD__
+       }
+#endif
 
+#ifdef __FreeBSD__
+       DPRINTF("auto_sndbuf = %d\n", auto_sndbuf);
+       if (auto_rcvbuf == 0) {
+#endif
        if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
            (void *)&rcvbuf_size, sizeof(rcvbuf_size)) == -1)
                warn("Unable to set rcvbuf size %d", rcvbuf_size);
+#ifdef __FreeBSD__
+       }
+#endif
 }
 
 /*
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to