TCPペーシング

OSカーネルのコードを読むときに意識しておくべきことは、どのコンテキストで動作しているか。特にネットワークスタックやファイルシステムなど、IOに関係するときには重要で、初学者は見落としがちである。コンテキストには、システムコールの延長線上で実行されるプロセスコンテキストと、割り込みの延長で実行される(ハードウェア or ソフトウェア)割り込みコンテキストの2種類が存在する。

Linuxのネットワークスタックだと、ユーザコンテキストと割り込みコンテキストをつなぐデータ構造がQDisc(Queueing Discipline)となる。諸々端折って言うと、ソケットにデータを書き込むと、対応するsk_buffをQDiscにキューイングして、デバイスドライバに送信要求を出してシステムコールを抜ける。ここまでがユーザコンテキスト。送信完了割込みがあったら割り込みコンテキストにてsk_buffを開放する。一方、パケットを受信したときは、割り込みコンテキストでsk_buffがQDiscにキューイングされ、ユーザコンテキストでソケットを読むと、そのsk_buffからデータがずるずるっと取り出される。

前回、Earliest Departure Time (EDT)とかTCPペーシングという話になったが、EDTに踏み込む前に、TCPペーシングが取り込まれていった経緯を追っかけてみる。時期はさかのぼることバージョン3.12の頃。

commit 95bd09eb27507691520d39ee1044d6ad831c1168
Author: Eric Dumazet <edumazet@google.com>
Date:   Tue Aug 27 05:46:32 2013 -0700

   tcp: TSO packets automatic sizing

TSO(TCP Segmentation Offload)は、ネットワークスタックやデバドラでパケット毎の処理をするのはCPUに負荷がかかるので、仮想的に64KBのパケットとして扱いましょうという仕組み。しかし副作用もあって、64KB単位でパケットがバースト的に送信される(「マイクロバースト」と呼ぶ)ので、スイッチやルータに優しくない。そこで、送信レートに合わせて、TSOパケットのサイジングをしましょうというのが、このパッチ。(CWND * MSS / SRTT) * 2をペーシングレート(sk_pacing_rate)に設定してる。なぜ2倍するのかは謎。

commit afe4fd062416b158a8a8538b23adc1930a9b88dc
Author: Eric Dumazet <edumazet@google.com>
Date:   Thu Aug 29 15:49:55 2013 -0700

   pkt_sched: fq: Fair Queue packet scheduler

さらにsk_pacing_rateを利用してペーシングを実現するパケットスケジューラがFair Queue (FQ)パケットスケジューラ。これは前述したQDiscとして実装されている。送信パケット間隔を制御するために、sk_buffをdequeueする際に適切な遅延が入る。

62748f32d501 net: introduce SO_MAX_PACING_RATE
commit 62748f32d501f5d3712a7c372bbb92abc7c62bc7
Author: Eric Dumazet <edumazet@google.com>
Date:   Tue Sep 24 08:20:52 2013 -0700

   net: introduce SO_MAX_PACING_RATE

ソケットオプションでsk_pacing_rateの上限を設定できるようになった。このオプションの使い方を調べたければ、iperf3を見るのがよさそう。

commit 43e122b014c955a33220fabbd09c4b5e4f422c3c
Author: Eric Dumazet <edumazet@google.com>
Date:   Fri Aug 21 17:38:02 2015 -0700

   tcp: refine pacing rate determination

sk_pacing_rateをスロースタートフェーズと輻輳回避フェーズで変える。具体的には輻輳回避フェーズは2倍ではなく1.2倍に抑制するというもの。Googleでの経験則らしいが、これも謎である。そもそもTCP/IP周りは昔からこの数字だとなんとなく上手くいくという経験則に基づくマジックナンバーが多い。

commit 218af599fa635b107cfe10acf3249c4dfe5e4123
Author: Eric Dumazet <edumazet@google.com>
Date:   Tue May 16 04:24:36 2017 -0700

   tcp: internal implementation for pacing

TCP BBRにはTCPペーシングが必須なので、sch_sqに依存することになる。しかし、sch_fq以外のパケットスケジューラを使いたい場合もあるので、fallbackするためのペーシング実装を作ったというもの。

commit 73a6bab5aa2a83cb7df85805e08bc03b4065aea7
Author: Eric Dumazet <edumazet@google.com>
Date:   Thu May 10 14:59:43 2018 -0700

   tcp: switch pacing timer to softirq based hrtimer

バージョン4.18から高解像度タイマhrtimerが、ハードウェア割り込みコンテキストだけではなく、ソフトウェア割り込みコンテキストでも動作するようになった。これを受けて、後者のモードにリプレースされた。

ということで、TSO使用時のマイクロバースト抑制にはじまり、TCP BBRの要素技術としても、TCPペーシングが利用されるようになってきた。

この記事が気に入ったらサポートをしてみませんか?