仮想ネットワーク、ルーティング、キュー

このページの目次

小さなパケットは通過できるが、少し大きくなると詰まる;veth にはトラフィックがあるのに物理インターフェースにはない。仮想デバイス、レイヤー 2 ドメイン、ルーティング、カプセル化、キューイングは、同じ実際のパスに沿って階層的に説明する必要がある。

参照目標読書位置
bridge、VLAN、bond第 1~2 節
カプセル化サイズとポリシーベースルーティング第 3~4 節
キューイング、namespace、TUN/TAP第 5~7 節
同じパケットが複数の仮想デバイスを通過できる コンテナ / VM 独立したネットワークビュー veth / TAP 接続エンドポイント bridge / VLAN レイヤー 2 ドメインと転送 ルーティング / 出口 レイヤー 3 とキュー FDB で宛先 MAC を検索;FIB で IP プレフィックスを検索;qdisc がキューを管理 各レイヤーが解決する問題は異なる。インターフェースを作成しただけでは、パス全体が接続されたわけではない。 これは一例の組み合わせであり、コンテナネットワークは直接ルーティング、他のインターフェース、または BPF データパスを採用することもできる。

1. Bridge:FDB はルーティングテーブルではない

bridge はソース MAC アドレスに基づいてポートを学習し、宛先 MAC アドレスに対応する FDB エントリを照会する。既知のユニキャストは対応するポートに転送され、未知のユニキャスト、ブロードキャスト、マルチキャストは設定に応じてフレッド、マルチキャストリスニングなどの処理が行われる。IP の最長プレフィックスに基づいて次のホップを選択することはない。

VM A と B が br0 の 2 つの TAP ポートに接続され、同じレイヤー 2 ドメインにあると仮定する。A はまず ARP/NDP を介して B のリンク層アドレスを取得し、次に宛先 MAC が B のフレームを送信する。bridge の学習と転送には、br0 自体に IP アドレスを持たせる必要はない。br0 に IP を割り当てるのは、ホストもそのレイヤー 3 ネットワークに参加させるためであり、ブリッジ機能を有効にするための必須条件ではない。

レイヤー 2 のループはブロードキャストストームを引き起こす可能性があるため、正しいトポロジと STP などのメカニズムが必要である。VLAN フィルタリングを有効にすると、ポートメンバー、PVID、タグ付き/タグなしの出口ルールが組み合わさって転送ドメインを決定する。VLAN ID を作成しただけでは、すべてのポートでその VLAN が許可されるわけではない。bridge ドキュメント を参照。

2. VLAN と bonding は同じ能力を追加するものではない

VLAN は共有物理リンク上で論理的なレイヤー 2 ドメインを区別する。VLAN サブインターフェースは通常、上位レイヤーに独立した net_device として見える。ハードウェアオフロードでは、タグがメタデータに保存されるか、ハードウェアによって挿入/除去されるため、パケットキャプチャでタグが見えるかどうかは位置による。

bonding は複数の下位リンクを 1 つの論理インターフェースとしてまとめる:

モード典型的な用途制限
active-backupリンク切替単一フローのスループットを複数のリンクの合計に重ね合わせるものではない
balance-xorハッシュによる分散相手側の正しい設定が必要。ハッシュフィールドが均衡に影響する
802.3adLACP による凝集スイッチのサポート、メンバー条件、ハッシュが一致する必要がある
balance-rrラウンドロビン方式で送信を割り当てパケットの順序入れ替えを引き起こす可能性があり、一般的な最適解ではない

10 Gbit/s のリンク 2 本で LACP を構成しても、単一の TCP 接続が必ず 20 Gbit/s に達するわけではない。順序保持のため、同じフローは通常 1 つのメンバーリンクにマッピングされる。リンクの検知は、エンドツーエンドのサービス健全性検知とは異なる。bonding ドキュメント を参照。

3. トンネリング:まずカプセル化を計算し、次に MTU を設定する

IPIP は IP を外側 IP に格納する;GRE は GRE ヘッダーを追加し、対応するプロトコルを運ぶことができる;VXLAN は通常、レイヤー 2 フレームを UDP/IP にカプセル化し、VNI が論理ネットワークを識別する。VNI は VLAN ID よりも大きい値を持つが、暗号化やアクセス認証を提供するわけではない。

アンダーレイの IPv4 MTU が 1500 で、VXLAN に追加オプションがないと仮定する:

カプセル化内容バイト数
外側 IPv420
UDP8
VXLAN8
内側 Ethernet14
合計50
内側 IP パケットに割り当て1500 − 50 = 1450

外側を IPv6 ベースヘッダーに変更する場合、通常 20 バイトとなり、結果は約 1430 になる。内側の VLAN や追加ヘッダーもさらに計算に含める必要がある。

これは明確なカプセル化に基づいて計算された上限であり、すべての VXLAN の固定 MTU ではない。アンダーレイ MTU はその IP ペイロードの境界によって定義され、上記の計算では外側 Ethernet ヘッダーは再度控除されていない。階層を混在させると、控除しすぎたり控除不足になったりする。

パス内の MTU の不一致や、ICMP Packet Too Big などがフィルタリングされると、小さなパケットは正常だが大きなパケットが詰まるという現象が発生する可能性がある。トンネルのキー/VNI、リモートアドレス、FDB/制御プレーン、および戻りパスも正しく設定する必要がある必要がある。WireGuard などは暗号化トンネルを提供するが、それらのセキュリティ属性は平文の VXLAN とは異なる。VXLAN ドキュメント を参照。

各レイヤーのオーバーヘッドを同じ長さの軸に戻す:外側 IP、UDP、VXLAN、内側 Ethernet ヘッダー、アプリケーションデータはすべて予算を占有する。外側 IPv4/IPv6 や VLAN を変更すると、収容できるデータの上限随之に移動する。

MTU は外側 IP パケットから計算され、H_tunnel には外側 IP/UDP/VXLAN と内側 Ethernet ヘッダーが含まれる。外側 Ethernet ヘッダーは IP MTU には含まれない。

図を準備しています
ヘッダーが 1 層追加されるごとに、内側にはどれくらい収まるか?

VXLAN の外側 IP、UDP、VXLAN、内側 Ethernet はすべてアンダーレイ IP MTU を占有する。内側 IP/TCP ヘッダーも内側データ予算をさらに占有する。

4. ポリシーベースルーティング:まずルールを選択し、次に該当テーブルを照会する

ルーティングポリシーデータベースは、rule の優先度に基づいてソースアドレス、mark、インターフェースなどの条件をチェックし、テーブル参照などのアクションを実行する。選択されたルックアップルールが終了結果を得られない場合、後続のルールが続く可能性がある。最初の一致条件で無条件に停止するわけではない。

同じテーブル内では、ルーティングは通常最長プレフィックスを優先し、次に候補属性に基づいて選択される。10.2.3.9 は 10.0.0.0/8 と 10.2.0.0/16 の両方に一致するが、他の条件が正常であれば、後者の方がより具体的である。IPv4 FIB が trie を使用しているからといって、あらゆる負荷下で厳密な O(log n) を約束するものではない。

from ipaddress import ip_address, ip_network

address = ip_address('10.2.3.9')
routes = [ip_network(s) for s in ('0.0.0.0/0', '10.0.0.0/8', '10.2.0.0/16')]
best = max((r for r in routes if address in r), key=lambda r: r.prefixlen)
assert str(best) == '10.2.0.0/16'
print(best)

この例は 1 つのテーブルでのプレフィックスマッチングのみを示しており、policy rule、ECMP、ルーティングタイプ、およびネイバー解決はシミュレートしていない。ip route get も、問題に関連するソースアドレス、mark、またはインターフェース情報を含めることで、実際の検索条件に近づける。ip-rule を参照。

5. qdisc:キューイング、スケジューリング、シェーピング、AQM

機能コアアクション
キューイング送信できない skb を一時的に保存
スケジューリングキューから次のパケットを選択
シェーピング送信を遅延させてレート制御
ポリシング条件を超えるパケットの破棄またはアクション
AQMキュー状態に基づいて早期破棄または ECN マーキングを行い、輻輳をフィードバック

これらを組み合わせることができるが、1 つのインターフェースが自動的にすべての機能を提供するわけではない。

fq_codel はフローキューと CoDel を組み合わせ、CAKE はシェーピング、公平性、キュー管理を組み合わせ、HTB は階層型帯域幅割り当てをサポートする。システムのデフォルト qdisc は設定とデバイスによって影響を受けるため、fq_codel が常にデフォルトであると一概に言うことはできない。

キュー位置の制御:ローカル AQM はすべてのリモートバッファを管理できない

実際のボトルネックがモデム/プロバイダのバッカーにある場合、ホストローカルのキューは常に短く、ローカル AQM はリモートキューを直接制御できない。制御可能なシェーピングレートを適切なボトルネックの前に設定することで、キューを管理下の位置で発生させる機会を得られるが、具体的なレートはリンクオーバーヘッドと変化を測定する必要がある。

ingress/clsact は入力フィルタリングの位置を提供するが、通常の長期キューイング可能な受信シェーピングキューではない。キューイングシェーピングが必要な場合は、IFB などの方法と組み合わせて使用する。BQL はドライバ層のオーバードライブバイトを調整し、その役割はフローレベルの輻輳制御や qdisc AQM とは異なる。

6. Namespace、veth、TUN/TAP

network namespace はデバイスリスト、ルーティング、ポートバインドなどのネットワーク状態を分離する。同じカーネルを共有するが、出口、DNS サービス、帯域幅保証を自動的に作成するものではない。通常の net_device はある時点で 1 つの namespace に属し、veth ペアの両端を異なる namespace に配置できる。

veth はペアになったカーネルネットワークエンドポイントを提供する;TUN/TAP はユーザー空間がファイル記述子を介してネットワークデータを読み書きする。TUN はレイヤー 3 パケットを提供し、TAP はレイヤー 2 フレームを提供する。ユーザー空間が fd から読み取ると、カーネルからそのインターフェースへ送られたデータが得られ、fd に書き込むと、受信データをカーネルに注入する。方向はこの視点に従って理解する必要がある。

追加の packet information や virtio-net ヘッダーがデータに含まれるかどうかは flags に依存し、常に最初のバイトが IP/Ethernetヘッダーであるわけではない。VM では TAP が一般的に使用され、一部のユーザー空間 VPN では TUN が使用される。メインラインカーネルの WireGuard は独自に net_device を実装しており、すべての WireGuard が /dev/net/tun に依存すると一概に言うことはできない。TUN/TAP を参照。

7. 完全なパスを参照のみで確認する

ip -d link show
ip rule show
ip route show table all
bridge link show
bridge vlan show
tc -s qdisc show

まずデバイスと namespace を確認し、次にレイヤー 2 ドメイン、アドレス、ルーティングをチェックし、その後 MTU、フィルタルール、キューを確認する。トラフィックが veth にはあるが物理口にはない場合、それが直接パケット損失を意味するわけではない。ローカルで配信されたか、ブリッジ内で転送されたか、別の出口にカプセル化されたか、または事前にポリシーによって拒否された可能性がある。

関連読書:プロトコルスタック概要、Netfilter と BPF/XDP。