CLOVER🍀

That was when it all began.

Linuxで現在設定されている(使用可能な)TCP輻輳制御アルゴリズムを見る

これは、なにをしたくて書いたもの?

最近、こちらの本を読んでいるのですが。

TCP技術入門 ――進化を続ける基本プロトコル (WEB+DB PRESS plusシリーズ)

TCP技術入門 ――進化を続ける基本プロトコル (WEB+DB PRESS plusシリーズ)

輻輳制御とそのアルゴリズムについて、いろいろと紹介されています。

このあたりについて、今まであまり意識したことがなかったので、「さて、手元のLinux環境ではどうなっているのか?」ということで
調べてみました。

輻輳制御自体については、こちらあたりを参考に。

第1回 TCPの輻輳制御とは何か:基本から学ぶ TCPと輻輳制御 ……押さえておきたい輻輳制御アルゴリズム|gihyo.jp … 技術評論社

アルゴリズムとしては、Googleが開発したBBRが注目されていたりするようで?

TCPを高速化する新アルゴリズム「BBR」、Googleが開発 - Computerworldニュース:Computerworld

Google Cloud Platform Japan 公式ブログ: 輻輳制御の新アルゴリズム TCP BBR を GCP に導入

【Linux】輻輳制御アルゴリズムの紹介 | アカスブログ

環境

今回の環境は、こちらです。

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 18.04.2 LTS
Release:    18.04
Codename:   bionic


$ uname -a
Linux ikaruga 4.15.0-54-generic #58-Ubuntu SMP Mon Jun 24 10:55:24 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

Ubuntu Linux 18.04 LTS、カーネルは4.15です。

現在のTCP輻輳制御アルゴリズムを見る

これは、カーネルパラメーター「net.ipv4.tcp_congestion_control」を見ればOKです。

$ sudo sysctl -a 2>&1 | grep -i tcp_congestion_control
net.ipv4.tcp_congestion_control = cubic

現在選択されているのは、「cubic」ですね。なお、「congestion」という単語は、輻輳、混雑、渋滞などを表します。

https://github.com/torvalds/linux/blob/v4.15/Documentation/networking/ip-sysctl.txt#L247-L254

tcp_congestion_control - STRING
Set the congestion control algorithm to be used for new
connections. The algorithm "reno" is always available, but
additional choices may be available based on kernel configuration.
Default is set as part of kernel configuration.
For passive connections, the listener congestion control choice
is inherited.
[see setsockopt(listenfd, SOL_TCP, TCP_CONGESTION, "name" ...) ]

「reno」はいつでも使えるよ、デフォルトで設定されるのはカーネルの設定で決まるよ、という感じですね。

あと、このカーネルパラメーターの説明を見ると、システムコールsetsockoptでも指定できそうですね。

Man page of GETSOCKOPT

Man page of TCP

利用可能な輻輳制御アルゴリズムを見る

これは、カーネルパラメーター「net.ipv4.tcp_available_congestion_control」を参照します。

$ sudo sysctl -a 2>&1 | grep -i tcp_available_congestion_control
net.ipv4.tcp_available_congestion_control = reno cubic

「reno」、「cubic」が利用可能ですね。

https://github.com/torvalds/linux/blob/v4.15/Documentation/networking/ip-sysctl.txt#L237-L240

tcp_available_congestion_control - STRING
Shows the available congestion control choices that are registered.
More congestion control algorithms may be available as modules,
but not loaded.

その他のアルゴリズムは?

「net.ipv4.tcp_available_congestion_control」を見ると、利用可能な輻輳制御アルゴリズムは「reno」と「cubic」の2つでした。

先に記載したBBRや、他にもいろいろあるようです。

一覧は、こちら。

TCP congestion control / Algorithms

Linuxカーネルのソースコード上では、「tcp_[アルゴリズム名].c」として実装されています。

https://github.com/torvalds/linux/tree/v4.15/net/ipv4

例えば、CUBICであれば「tcp_cubic.c」、

https://github.com/torvalds/linux/blob/v4.15/net/ipv4/tcp_cubic.c

BBRであれば「tcp_bbr.c」です。

https://github.com/torvalds/linux/blob/v4.15/net/ipv4/tcp_bbr.c

「tcp_reno.c」はパッと見ではいないのですが、Reno(正確にはNewReno)は「tcp_cong.c」のようです。

https://github.com/torvalds/linux/blob/v4.15/net/ipv4/tcp_cong.c

NewRenoおよびCUBICは、カーネルのビルド時に指定することで有効化できるようです(「TCP_CONG_[アルゴリズム名])。

https://github.com/torvalds/linux/blob/v4.15/net/ipv4/Makefile#L47-L62

https://github.com/torvalds/linux/blob/v4.15/net/ipv4/Kconfig#L479-L739

NewRenoは無条件に組み込まれるのですが、CUBICについてもデフォルトで組み込まれるようになっています。

https://github.com/torvalds/linux/blob/v4.15/net/ipv4/Kconfig#L493-L499

config TCP_CONG_CUBIC
tristate "CUBIC TCP"
default y
---help---
This is version 2.0 of BIC-TCP which uses a cubic growth function
among other techniques.
See http://www.csc.ncsu.edu/faculty/rhee/export/bitcp/cubic-paper.pdf

BBRは、「default n」ですね。

https://github.com/torvalds/linux/blob/v4.15/net/ipv4/Kconfig#L663-L676

config TCP_CONG_BBR
tristate "BBR TCP"
default n
---help---

BBR (Bottleneck Bandwidth and RTT) TCP congestion control aims to
maximize network utilization and minimize queues. It builds an explicit
model of the the bottleneck delivery rate and path round-trip
propagation delay. It tolerates packet loss and delay unrelated to
congestion. It can operate over LAN, WAN, cellular, wifi, or cable
modem links. It can coexist with flows that use loss-based congestion
control, and can operate with shallow buffers, deep buffers,
bufferbloat, policers, or AQM schemes that do not provide a delay
signal. It requires the fq ("Fair Queue") pacing packet scheduler.

カーネルビルド時に有効にしておくと、組み込まれるみたいです。

ところで、他のアルゴリズムを有効にする設定を見ていると、「default m」みたいなものがあります。

https://github.com/torvalds/linux/blob/v4.15/net/ipv4/Kconfig#L515-L524

config TCP_CONG_HTCP
tristate "H-TCP"
default m
---help---
H-TCP is a send-side only modifications of the TCP Reno
protocol stack that optimizes the performance of TCP
congestion control for high speed network links. It uses a
modeswitch to change the alpha and beta parameters of TCP Reno
based on network conditions and in a way so as to be fair with
other Reno and H-TCP flows.

これは、カーネルモジュールとなるみたいですね…。

実際に、カーネルをビルドしたりするのは、また別の機会にやってみようかなと思います。

このあたり、眺めていてちょっと面白かったです。

Linuxのカーネルパラメーターの説明って、どこを見たらいい?

Linuxにはたくさんのカーネルパラメータがあります。

manでシステムコールの説明を見たり、調べ物をしたりした時に、Linuxのカーネルパラメーターの変更を勧められたり、その意味が説明されて
いたりすることがあると思います。

なんですけど、そもそもその意味ってどうやって知ったらいいんでしょうか?

例えば、手元の環境。Ubuntu Linux 18.04 LTS、カーネルは4.15です。

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 18.04.2 LTS
Release:    18.04
Codename:   bionic


$ uname -a
Linux ikaruga 4.15.0-54-generic #58-Ubuntu SMP Mon Jun 24 10:55:24 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

カーネルパラメーターは、1885個あるようです。

$ sudo sysctl -a | wc -l
sysctl: reading key "net.ipv6.conf.all.stable_secret"
sysctl: reading key "net.ipv6.conf.br-9be47a5bd20b.stable_secret"
sysctl: reading key "net.ipv6.conf.default.stable_secret"
sysctl: reading key "net.ipv6.conf.docker0.stable_secret"
sysctl: reading key "net.ipv6.conf.enp7s0.stable_secret"
sysctl: reading key "net.ipv6.conf.lo.stable_secret"
sysctl: reading key "net.ipv6.conf.virbr0.stable_secret"
sysctl: reading key "net.ipv6.conf.virbr0-nic.stable_secret"
sysctl: reading key "net.ipv6.conf.virbr1.stable_secret"
sysctl: reading key "net.ipv6.conf.virbr1-nic.stable_secret"
sysctl: reading key "net.ipv6.conf.wlp8s0.stable_secret"
1885

「net.core.somaxconn」の値。

$ sudo sysctl -a 2>&1 | grep maxconn
net.core.somaxconn = 128

で、この意味は…というと…。

Linuxソースコードの、ドキュメントを見ると良さそうな気がします。

https://github.com/torvalds/linux/tree/v4.15/Documentation

例えば、ネットワーク関連のパラメーターだと、このあたりを見る感じになりそうです。

https://github.com/torvalds/linux/blob/v4.15/Documentation/networking/ip-sysctl.txt

https://github.com/torvalds/linux/blob/v4.15/Documentation/sysctl/net.txt

先ほどの「net.core.somaxconn」の説明は、こちら。

somaxconn - INTEGER
Limit of socket listen() backlog, known in userspace as SOMAXCONN.
Defaults to 128. See also tcp_max_syn_backlog for additional tuning
for TCP sockets.

https://github.com/torvalds/linux/blob/v4.15/Documentation/networking/ip-sysctl.txt#L196-L199

どんなパラメーターがあるのか、sysctlである程度階層分けして確認しつつ、Documentディレクトリ内を見ていくのがいいのかもしれませんね。

$ sudo sysctl -a 2>&1 | perl -wp -e 's!^(([^.]+\.?){1}).+!$1!' | grep -v 'reading key' | sort | uniq -c | grep -Ev '^ +1 '
      2 debug.
     40 dev.
     38 fs.
    337 kernel.
   1413 net.
      9 user.
     45 vm.


$ sudo sysctl -a 2>&1 | perl -wp -e 's!^(([^.]+\.?){2}).+!$1!' | grep -v 'reading key' | sort | uniq -c | grep -Ev '^ +1 '
     29 dev.cdrom.
      2 dev.i915.
      3 dev.mac_hid.
      2 dev.parport.
      2 dev.raid.
      3 fs.inotify.
      5 fs.mqueue.
      8 fs.quota.
      6 kernel.keys.
      3 kernel.pty.
      7 kernel.random.
    208 kernel.sched_domain.
      2 kernel.seccomp.
      2 kernel.usermodehelper.
      6 net.bridge.
     32 net.core.
    610 net.ipv4.
    705 net.ipv6.
     58 net.netfilter.


$ sudo sysctl -a 2>&1 | perl -wp -e 's!^(([^.]+\.?){3}).+!$1!' | grep -v 'reading key' | sort | uniq -c | grep -Ev '^ +1 '
      3 dev.cdrom.info =
      2 dev.parport.default.
     26 kernel.sched_domain.cpu0.
     26 kernel.sched_domain.cpu1.
     26 kernel.sched_domain.cpu2.
     26 kernel.sched_domain.cpu3.
     26 kernel.sched_domain.cpu4.
     26 kernel.sched_domain.cpu5.
     26 kernel.sched_domain.cpu6.
     26 kernel.sched_domain.cpu7.
    341 net.ipv4.conf.
    144 net.ipv4.neigh.
     15 net.ipv4.route.
    528 net.ipv6.conf.
    144 net.ipv6.neigh.
      9 net.ipv6.route.
     13 net.netfilter.nf_log.

今度から、リポジトリ内のドキュメントの情報も見てみることにしましょう。

ちょっとしたメモでした。

そういや、調べている過程でLinuxカーネルドキュメントがあることも知り。

Linux Kernel Documentation

このあたりの情報、全然知らないなぁと…。