svn commit: r358405 - head/contrib/tnftp/src

Hiroki Sato hrs at FreeBSD.org
Thu Feb 27 19:50:02 UTC 2020


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


More information about the svn-src-all mailing list