Linuxのqdisc(Queueing DISCipline:キューイング規則)でデフォルトで使用されるpfifi_fastを調べていたら、IPv4ヘッダのTOSフィールドに設定されている値によって挙動が変わるという仕様でした。そこでTOSの値を変えながら、色々と測定してみました。
pfifo_fast
pfifo_fastは、以下のリンク先にもある通り、FIFOで3つのバンドを持ちます(バンド0、バンド1、バンド2)。各バンドにはFIFOが適用されますが、バンド0に待ちパケットがあるとバンド1は処理されず、バンド1に待ちパケットがあるとバンド2は処理されないという仕様のようです。
カーネルは各パケットのIPv4ヘッダのTOSフィールドを参照し、「最小遅延」パケットをバンド0に入れるみたいです。
他のフィールドの意味は、以下のリンク先の内容が参考になります。
他にも、「最大スループット」はバンド2へ、「最大信頼性」はバンド1へ、何もなければバンド1へといった規則があります。
では、実際のパケットのTOSの値を変えた場合、Linuxではどのような挙動を示すのでしょうか。それを確認するため、いくつかの条件で測定して結果を見てみようというのが今回の目的です。
iperf3
iperf3はネットワークにTCPやUDPのトラフィックを流し、パフォーマンスを測定できるアプリケーションです。また、素晴らしいことに、”-S n”というオプションを使用すると、nとしてTOSの値が設定できます。よって今回は、iperf3を使いました。
https://iperf.fr/iperf-download.php
測定環境
1GbEで接続されたクライアントとサーバ上で、iperf3をポートを変えつつ2プロセス起動させ、それぞれ1GbpsのUDPトラフィックをサーバに投げさせました。片方のプロセスはTOSの値は変えずにデフォルトのまま。もう片方のプロセスのTOSの値を、変更なし、最小遅延、最大スループット、最大信頼性に変えてみました。
2プロセスの実行開始はできる限り同じにしたかったのですが、測定の主目的ではないため、多少の誤差(<1sec)は大目にみてください。実行開始は、TOSを変えないプロセスを実行した後、TOSを変えるプロセスを実行しました。
結果
変更なし
変えない側のプロセス
$ sudo iperf3 -c 192.168.1.173 -u -b 1G -p 5201 Connecting to host 192.168.1.173, port 5201 [ 4] local 192.168.1.120 port 45708 connected to 192.168.1.173 port 5201 [ ID] Interval Transfer Bandwidth Total Datagrams [ 4] 0.00-1.00 sec 99.3 MBytes 833 Mbits/sec 12715 [ 4] 1.00-2.00 sec 56.7 MBytes 476 Mbits/sec 7257 [ 4] 2.00-3.00 sec 56.6 MBytes 475 Mbits/sec 7251 [ 4] 3.00-4.00 sec 56.6 MBytes 475 Mbits/sec 7251 [ 4] 4.00-5.00 sec 56.7 MBytes 475 Mbits/sec 7253 [ 4] 5.00-6.00 sec 56.6 MBytes 475 Mbits/sec 7250 [ 4] 6.00-7.00 sec 56.7 MBytes 475 Mbits/sec 7254 [ 4] 7.00-8.00 sec 56.6 MBytes 475 Mbits/sec 7251 [ 4] 8.00-9.00 sec 56.6 MBytes 475 Mbits/sec 7249 [ 4] 9.00-10.00 sec 56.6 MBytes 475 Mbits/sec 7249 - - - - - - - - - - - - - - - - - - - - - - - - - [ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams [ 4] 0.00-10.00 sec 609 MBytes 511 Mbits/sec 0.018 ms 1226/77977 (1.6%) [ 4] Sent 77977 datagrams
変える側のプロセス(変更なし条件なので変えない)
$ sudo iperf3 -c 192.168.1.173 -u -b 1G -p 5202 Connecting to host 192.168.1.173, port 5202 [ 4] local 192.168.1.120 port 59428 connected to 192.168.1.173 port 5202 [ ID] Interval Transfer Bandwidth Total Datagrams [ 4] 0.00-1.00 sec 51.0 MBytes 428 Mbits/sec 6533 [ 4] 1.00-2.00 sec 56.7 MBytes 476 Mbits/sec 7257 [ 4] 2.00-3.00 sec 56.7 MBytes 476 Mbits/sec 7256 [ 4] 3.00-4.00 sec 56.7 MBytes 475 Mbits/sec 7253 [ 4] 4.00-5.00 sec 56.7 MBytes 476 Mbits/sec 7258 [ 4] 5.00-6.00 sec 56.7 MBytes 475 Mbits/sec 7255 [ 4] 6.00-7.00 sec 56.7 MBytes 476 Mbits/sec 7256 [ 4] 7.00-8.00 sec 56.7 MBytes 476 Mbits/sec 7259 [ 4] 8.00-9.00 sec 56.7 MBytes 476 Mbits/sec 7261 [ 4] 9.00-10.00 sec 105 MBytes 880 Mbits/sec 13429 - - - - - - - - - - - - - - - - - - - - - - - - - [ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams [ 4] 0.00-10.00 sec 610 MBytes 511 Mbits/sec 0.125 ms 806/78016 (1%) [ 4] Sent 78016 datagrams
競合状態になった場合、同じくらいの送信量になりました。
最小遅延
変えない側のプロセス
$ sudo iperf3 -c 192.168.1.173 -u -b 1G -p 5201 Connecting to host 192.168.1.173, port 5201 [ 4] local 192.168.1.120 port 59717 connected to 192.168.1.173 port 5201 [ ID] Interval Transfer Bandwidth Total Datagrams [ 4] 0.00-1.00 sec 79.5 MBytes 667 Mbits/sec 10176 [ 4] 1.00-2.00 sec 30.2 MBytes 253 Mbits/sec 3860 [ 4] 2.00-3.00 sec 30.2 MBytes 253 Mbits/sec 3863 [ 4] 3.00-4.00 sec 30.2 MBytes 253 Mbits/sec 3864 [ 4] 4.00-5.00 sec 33.6 MBytes 282 Mbits/sec 4307 [ 4] 5.00-6.00 sec 34.5 MBytes 289 Mbits/sec 4415 [ 4] 6.00-7.00 sec 34.0 MBytes 285 Mbits/sec 4352 [ 4] 7.00-8.00 sec 32.6 MBytes 273 Mbits/sec 4172 [ 4] 8.00-9.00 sec 31.7 MBytes 266 Mbits/sec 4061 [ 4] 9.00-10.00 sec 31.4 MBytes 263 Mbits/sec 4017 - - - - - - - - - - - - - - - - - - - - - - - - - [ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams [ 4] 0.00-10.00 sec 368 MBytes 309 Mbits/sec 0.101 ms 1229/47087 (2.6%) [ 4] Sent 47087 datagrams
変える側のプロセス
$ sudo iperf3 -c 192.168.1.173 -u -b 1G -p 5202 -S 16 Connecting to host 192.168.1.173, port 5202 [ 4] local 192.168.1.120 port 53699 connected to 192.168.1.173 port 5202 [ ID] Interval Transfer Bandwidth Total Datagrams [ 4] 0.00-1.00 sec 74.9 MBytes 628 Mbits/sec 9586 [ 4] 1.00-2.00 sec 83.2 MBytes 698 Mbits/sec 10646 [ 4] 2.00-3.00 sec 83.2 MBytes 698 Mbits/sec 10645 [ 4] 3.00-4.00 sec 81.6 MBytes 685 Mbits/sec 10448 [ 4] 4.00-5.00 sec 78.3 MBytes 657 Mbits/sec 10027 [ 4] 5.00-6.00 sec 79.3 MBytes 665 Mbits/sec 10151 [ 4] 6.00-7.00 sec 80.0 MBytes 671 Mbits/sec 10243 [ 4] 7.00-8.00 sec 81.4 MBytes 683 Mbits/sec 10420 [ 4] 8.00-9.00 sec 81.9 MBytes 687 Mbits/sec 10482 [ 4] 9.00-10.00 sec 102 MBytes 853 Mbits/sec 13013 - - - - - - - - - - - - - - - - - - - - - - - - - [ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams [ 4] 0.00-10.00 sec 825 MBytes 692 Mbits/sec 0.127 ms 0/105658 (0%) [ 4] Sent 105658 datagrams
最小遅延を設定したプロセスの方で、多くのデータが送信されるという結果になりました。
もっと偏るのではないかと予想していたのですが、変えない側のプロセスでもある程度のデータが送信されました。
最大スループット
変えない側のプロセス
$ sudo iperf3 -c 192.168.1.173 -u -b 1G -p 5201 Connecting to host 192.168.1.173, port 5201 [ 4] local 192.168.1.120 port 38351 connected to 192.168.1.173 port 5201 [ ID] Interval Transfer Bandwidth Total Datagrams [ 4] 0.00-1.00 sec 90.6 MBytes 760 Mbits/sec 11596 [ 4] 1.00-2.00 sec 83.2 MBytes 698 Mbits/sec 10648 [ 4] 2.00-3.00 sec 80.6 MBytes 676 Mbits/sec 10314 [ 4] 3.00-4.00 sec 79.6 MBytes 668 Mbits/sec 10189 [ 4] 4.00-5.00 sec 81.4 MBytes 682 Mbits/sec 10413 [ 4] 5.00-6.00 sec 82.2 MBytes 690 Mbits/sec 10528 [ 4] 6.00-7.00 sec 83.2 MBytes 698 Mbits/sec 10648 [ 4] 7.00-8.00 sec 83.2 MBytes 698 Mbits/sec 10648 [ 4] 8.00-9.00 sec 83.2 MBytes 698 Mbits/sec 10649 [ 4] 9.00-10.00 sec 83.2 MBytes 698 Mbits/sec 10648 - - - - - - - - - - - - - - - - - - - - - - - - - [ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams [ 4] 0.00-10.00 sec 830 MBytes 697 Mbits/sec 0.003 ms 1233/106279 (1.2%) [ 4] Sent 106279 datagrams
変える側のプロセス
$ sudo iperf3 -c 192.168.1.173 -u -b 1G -p 5202 -S 8 Connecting to host 192.168.1.173, port 5202 [ 4] local 192.168.1.120 port 48346 connected to 192.168.1.173 port 5202 [ ID] Interval Transfer Bandwidth Total Datagrams [ 4] 0.00-1.00 sec 27.2 MBytes 228 Mbits/sec 3483 [ 4] 1.00-2.00 sec 30.3 MBytes 254 Mbits/sec 3874 [ 4] 2.00-3.00 sec 35.3 MBytes 296 Mbits/sec 4523 [ 4] 3.00-4.00 sec 32.0 MBytes 268 Mbits/sec 4095 [ 4] 4.00-5.00 sec 32.0 MBytes 268 Mbits/sec 4094 [ 4] 5.00-6.00 sec 30.2 MBytes 253 Mbits/sec 3860 [ 4] 6.00-7.00 sec 30.2 MBytes 253 Mbits/sec 3860 [ 4] 7.00-8.00 sec 30.1 MBytes 253 Mbits/sec 3859 [ 4] 8.00-9.00 sec 30.1 MBytes 253 Mbits/sec 3859 [ 4] 9.00-10.00 sec 73.4 MBytes 616 Mbits/sec 9396 - - - - - - - - - - - - - - - - - - - - - - - - - [ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams [ 4] 0.00-10.00 sec 351 MBytes 294 Mbits/sec 0.132 ms 811/44900 (1.8%) [ 4] Sent 44900 datagrams
最大スループットのパケットは、バンド2に入れられるため、先程と逆の結果になりました。
最大信頼性
変えない側のプロセス
$ sudo iperf3 -c 192.168.1.173 -u -b 1G -p 5201 Connecting to host 192.168.1.173, port 5201 [ 4] local 192.168.1.120 port 48531 connected to 192.168.1.173 port 5201 [ ID] Interval Transfer Bandwidth Total Datagrams [ 4] 0.00-1.00 sec 92.6 MBytes 776 Mbits/sec 11849 [ 4] 1.00-2.00 sec 56.7 MBytes 476 Mbits/sec 7263 [ 4] 2.00-3.00 sec 56.7 MBytes 476 Mbits/sec 7263 [ 4] 3.00-4.00 sec 56.7 MBytes 476 Mbits/sec 7256 [ 4] 4.00-5.00 sec 56.7 MBytes 476 Mbits/sec 7260 [ 4] 5.00-6.00 sec 56.8 MBytes 476 Mbits/sec 7265 [ 4] 6.00-7.00 sec 56.7 MBytes 476 Mbits/sec 7260 [ 4] 7.00-8.00 sec 56.7 MBytes 476 Mbits/sec 7258 [ 4] 8.00-9.00 sec 56.8 MBytes 476 Mbits/sec 7268 [ 4] 9.00-10.00 sec 56.7 MBytes 476 Mbits/sec 7257 - - - - - - - - - - - - - - - - - - - - - - - - - [ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams [ 4] 0.00-10.00 sec 603 MBytes 506 Mbits/sec 0.073 ms 1231/77198 (1.6%) [ 4] Sent 77198 datagrams
変える側のプロセス
$ sudo iperf3 -c 192.168.1.173 -u -b 1G -p 5202 -S 4 Connecting to host 192.168.1.173, port 5202 [ 4] local 192.168.1.120 port 53602 connected to 192.168.1.173 port 5202 [ ID] Interval Transfer Bandwidth Total Datagrams [ 4] 0.00-1.00 sec 51.0 MBytes 428 Mbits/sec 6529 [ 4] 1.00-2.00 sec 56.6 MBytes 475 Mbits/sec 7243 [ 4] 2.00-3.00 sec 56.6 MBytes 475 Mbits/sec 7250 [ 4] 3.00-4.00 sec 56.6 MBytes 475 Mbits/sec 7247 [ 4] 4.00-5.00 sec 56.6 MBytes 475 Mbits/sec 7246 [ 4] 5.00-6.00 sec 56.6 MBytes 475 Mbits/sec 7247 [ 4] 6.00-7.00 sec 56.6 MBytes 475 Mbits/sec 7250 [ 4] 7.00-8.00 sec 56.6 MBytes 475 Mbits/sec 7241 [ 4] 8.00-9.00 sec 56.6 MBytes 475 Mbits/sec 7246 [ 4] 9.00-10.00 sec 98.1 MBytes 823 Mbits/sec 12562 - - - - - - - - - - - - - - - - - - - - - - - - - [ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams [ 4] 0.00-10.00 sec 602 MBytes 505 Mbits/sec 0.121 ms 0/77060 (0%) [ 4] Sent 77060 datagrams
変更なしの条件と同様、どちらのプロセスでも同じくらいの送信量になりました。
まとめ
Linuxのpfifo_fastを使用している場合、パケットのTOSの値を変えることで、パケットのキューイング先のバンドが変わり、バンドが小さい程、優先して送信されることが確認できました。
裏で大量のデータが送信されている環境で、システムの重要なデータを送る際などに最小遅延を設定しておくと、届きやすくなる可能性があります。
以上。