Bug 240827 - ftp(1) is slower than fetch(1)
Summary: ftp(1) is slower than fetch(1)
Status: In Progress
Alias: None
Product: Base System
Classification: Unclassified
Component: bin (show other bugs)
Version: CURRENT
Hardware: Any Any
: --- Affects Some People
Assignee: Hiroki Sato
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-09-26 01:43 UTC by Yuichiro NAITO
Modified: 2020-02-27 19:50 UTC (History)
1 user (show)

See Also:
koobs: mfc-stable12?
koobs: mfc-stable11?


Attachments
ftp.patch (1.77 KB, patch)
2019-09-26 01:43 UTC, Yuichiro NAITO
no flags Details | Diff
Patch to prevent SO_SNDBUF and SO_RCVBUF from configuring when auto tuning enabled (2.69 KB, patch)
2019-12-14 19:22 UTC, Hiroki Sato
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Yuichiro NAITO 2019-09-26 01:43:41 UTC
Created attachment 207828 [details]
ftp.patch

Of course this problem depends on network environment,
I can see this problem in my home network only.

In my home network,
the bandwidth of the internet connection is 100Mbps.
Fetch(1) downloads in mostly full speed of the bandwidth.
But ftp(1) seems about half speed of fetch(1).

I have tried to download FreeBSD iso image file
from the fastest mirror from my home.
The results are shown below.

```
$ fetch ftp://ftp.jp.freebsd.org/pub/FreeBSD/releases/ISO-IMAGES/12.0/FreeBSD-12.0-RELEASE-amd64-disc1.iso
FreeBSD-12.0-RELEASE-amd64-disc1.iso                   851 MB   10 MBps 01m20s
```

```
$ ftp ftp://ftp.jp.freebsd.org/pub/FreeBSD/releases/ISO-IMAGES/12.0/FreeBSD-12.0-RELEASE-amd64-disc1.iso
Trying 2405:f000:202:2598:210:231:212:2:21 ...
Connected to ftp.lab.bbtower.net.
220- Welcome to ftp.lab.BBTower.net,
220-            Located in Tokyo, Japan.
220-
220- This server maintenanced by BroadBand Tower, Inc.
220-
220-             BBTower Web site is at
220-             http://www.bbtower.co.jp/
220-
220- If you have any problem, please contact ftp-contact@bbtower.co.jp.
220 FTP server ready.
331 Guest login ok, send your email address as password.
230 Guest login ok, access restrictions apply.
Remote system type is UNKNOWN.
200 Type set to I.
250 CWD command successful.
250 CWD command successful.
250 CWD command successful.
250 CWD command successful.
250 CWD command successful.
local: FreeBSD-12.0-RELEASE-amd64-disc1.iso remote: FreeBSD-12.0-RELEASE-amd64-disc1.iso
229 Entering Extended Passive Mode (|||63019|)
150 Opening BINARY mode data connection for 'FreeBSD-12.0-RELEASE-amd64-disc1.iso' (892467200 bytes).
100% |***********************************|   851 MiB    5.14 MiB/s    00:00 ETA
226 Transfer complete.
892467200 bytes received in 02:45 (5.14 MiB/s)
221 Goodbye.
```

This is because socket buffer size is not large enough to ftp(1).
Ftp(1) always set the buffer size to the default value.
It prevents FreeBSD kernel from increasing socket buffer size automatically.

So setting `sysctl net.inet.tcp.recvspace=131072` speeds up the ftp download
for workaround.

```
$ sudo sysctl net.inet.tcp.recvspace=131072
Password:
net.inet.tcp.recvspace: 65536 -> 131072
$ ftp ftp://ftp.jp.freebsd.org/pub/FreeBSD/releases/ISO-IMAGES/12.0/FreeBSD-12.0-RELEASE-amd64-disc1.iso
Trying 2405:f000:202:2598:210:231:212:2:21 ...
Connected to ftp.lab.bbtower.net.
220- Welcome to ftp.lab.BBTower.net,
220-            Located in Tokyo, Japan.
220-
220- This server maintenanced by BroadBand Tower, Inc.
220-
220-             BBTower Web site is at
220-             http://www.bbtower.co.jp/
220-
220- If you have any problem, please contact ftp-contact@bbtower.co.jp.
220 FTP server ready.
331 Guest login ok, send your email address as password.
230 Guest login ok, access restrictions apply.
Remote system type is UNKNOWN.
200 Type set to I.
250 CWD command successful.
250 CWD command successful.
250 CWD command successful.
250 CWD command successful.
250 CWD command successful.
local: FreeBSD-12.0-RELEASE-amd64-disc1.iso remote: FreeBSD-12.0-RELEASE-amd64-disc1.iso
229 Entering Extended Passive Mode (|||59743|)
150 Opening BINARY mode data connection for 'FreeBSD-12.0-RELEASE-amd64-disc1.iso' (892467200 bytes).
100% |***********************************|   851 MiB    9.67 MiB/s    00:00 ETA
226 Transfer complete.
892467200 bytes received in 01:27 (9.67 MiB/s)
221 Goodbye.
```

Basically ftp(1) should allow FreeBSD kernel to adjust socket buffer size.
I suggest the attached patch that prevents ftp(1) from setting socket buffer size
unless user input 'rcvbuf' or 'sndbuf' command.
Comment 1 Hiroki Sato freebsd_committer 2019-09-26 04:09:58 UTC
Take.
Comment 2 Yuichiro NAITO 2019-10-10 00:54:03 UTC
Two weeks have been passed.
Are there any problem in my patch?
Or are you busy now?
Comment 3 Hiroki Sato freebsd_committer 2019-12-14 19:22:42 UTC
Created attachment 209950 [details]
Patch to prevent SO_SNDBUF and SO_RCVBUF from configuring when auto tuning enabled

Sorry for the delay getting back to you.  I created a modified patch to check net.inet.tcp.{send,recv}buf_auto sysctls because they are knobs where one can change this behavior.  Please try it and see if it works as expected.
Comment 4 Yuichiro NAITO 2019-12-15 13:46:47 UTC
(In reply to Hiroki Sato from comment #3)

Thanks for your patch.
I confirmed that your patch solved this problem.
I can see that your patch follows kernel mode explicitly.
I think it's good way to record what I'm trying to do.

But I have one question.
You patched about auto_sendbuf in following lines.
                       ^^^^

```
+#ifdef __FreeBSD__
+	DPRINTF("auto_rcvbuf = %d\n", auto_rcvbuf);
+	if (auto_sndbuf == 0)
+#endif
```

DRPINTF message shows auto_rcvbuf value.
                           ^^^
Is it typo?
Comment 5 Hiroki Sato freebsd_committer 2019-12-15 20:05:49 UTC
(In reply to Yuichiro NAITO from comment #4)

Yes, it was a typo.  I thought I fixed it in my local tree but I mistakenly sent a previous version.

I will send this patch for review and commit it if there is no big objection.
Comment 6 Yuichiro NAITO 2019-12-16 00:41:31 UTC
(In reply to Hiroki Sato from comment #5)
>I will send this patch for review and commit it if there is no big objection.

No problem to me.
Thank you.
Comment 7 Hiroki Sato freebsd_committer 2020-02-17 19:08:17 UTC
Sorry for the delay.  Staged at https://reviews.freebsd.org/D23732
Comment 8 commit-hook freebsd_committer 2020-02-27 19:50:53 UTC
A commit references this bug:

Author: hrs
Date: Thu Feb 27 19:50:00 UTC 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

Changes:
  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