バンド幅遅延積とウィンドウスケーリングの数理
太い回線が遅い理由が数式で腑に落ちる。BDPで必要な送信窓とバッファ量を見積もり、Long Fat Networkを頭打ちにせず使い切る勘所をつかめる。
- 1.BDP(帯域×RTT)は回線を満たすのに常時飛んでいるべきデータ量。送信窓がBDP未満だとACK待ちで停止し、帯域は使い切れない。
- 2.16ビットの窓欄は最大64KBで高BDP路に全く足りない。ウィンドウスケールで左シフトし、送受のソケットバッファをBDP以上に確保して初めて全速が出る。
- 3.Long Fat Networkでは窓を広げるほど未確認データが増え、損失1発の影響も再送量も増える。BDP相当のバッファとロス耐性のある輻輳制御が両輪。
BDP:回線に「常時飛んでいるべき」データ量
長距離の高速回線が、帯域は太いのに遅い。この一見矛盾した現象の核心が 帯域遅延積(BDP, Bandwidth-Delay Product) です。定義は単純です。
BDP = 帯域(bit/s) × RTT(s) … 単位は bit、8で割れば byte
BDPは「リンクをちょうど満たすために、いつでも経路上を飛んでいなければならないデータ量」を表します。なぜ積になるのか。送信側が1ビット送り、その確認(ACK)が返るまでには最低でも1往復(RTT)かかります。その間も帯域を遊ばせないためには、ACKを待たずに次々と送り続ける必要があり、待ち時間RTTの間に流せる量がちょうど 帯域 × RTT だからです。これは管に水を通すたとえと同じで、BDPは管の太さ(帯域)と長さ(RTT)で決まる「管の容積」に相当します。帯域とレイテンシが独立した別物であることは 帯域・レイテンシ・スループット の通りで、BDPはその2つの積として現れます。
例1: 1Gbps × 100ms = 1e9 × 0.1 / 8 ≒ 12.5 MB
例2: 10Gbps × 80ms(大陸間) = 1e10 × 0.08 / 8 = 100 MB
例3: 100Mbps × 600ms(静止衛星) = 1e8 × 0.6 / 8 = 7.5 MB
スループットは「窓 ÷ RTT」で頭打ちになる
ここで効いてくるのが、TCPが一度に送れる未確認データ量(in-flight)の上限、すなわち 送信ウィンドウ です。窓がBDPより小さいと、窓いっぱい送った時点でACK待ちに入り、回線が空いていても停止します。達成できるスループットは次の上限に縛られます。
最大スループット = 送信ウィンドウ ÷ RTT
窓が固定なら、RTTが伸びるほどスループットは反比例で落ちる。これが「遠い回線ほど遅い」の数理的な正体です。窓がBDPに達して初めて BDP ÷ RTT = 帯域 となり、回線を使い切れます。
BDPが12.5MBの経路で送信窓が64KBしか取れない場合、最大スループットは 65535B ÷ 0.1s ≒ 5.2Mbps。1Gbpsのリンクの 約0.5% しか使えません。帯域を10倍にしても、窓が同じならスループットは1ビットも増えません。ボトルネックは回線ではなく窓です。
送信窓の実体は受信窓(rwnd)と輻輳窓(cwnd)の最小値で、そのうち受信側を守る側の仕組みは TCPのフロー制御とウィンドウスケーリング、ネットワーク側を守る側は AIMDと輻輳制御の数理 を参照してください。本稿はその「窓をBDPまで広げるには何が必要か」という量の設計に踏み込みます。
16ビットの壁とウィンドウスケーリング
TCPヘッダの窓欄は 16ビット、つまり最大65,535バイト(約64KB)しか表現できません。BDPが数MB〜数百MBになる現代の高速・長距離路では、これは桁違いに不足します。これを救うのが ウィンドウスケールオプション(RFC 7323) です。原理は、広告する窓の値に左シフト量(スケールファクタ)を掛けて解釈させるだけです。
実際の窓 = ヘッダのウィンドウ値 << スケールファクタ
スケールファクタは 0〜14。最大で 65535 << 14 ≒ 1GB まで拡張
| 観点 | スケーリングなし | ウィンドウスケーリングあり |
|---|---|---|
| 最大窓 | 65,535バイト(約64KB) | 65535 << 14 ≒ 1GB |
| 有効ビット数 | 16ビット | 実質30ビット(14ビット左シフト) |
| 交渉のタイミング | なし | SYN/SYN-ACKでのみ。確立後は変更不可 |
| スケールファクタ | — | 0〜14、片方向ごとに独立した値 |
| 高BDP路での結果 | 窓不足で帯域を遊ばせる | 窓をBDPまで広げ全速を狙える |
決定的に重要なのは、スケールファクタは 3ウェイハンドシェイクのSYN/SYN-ACKでしか交渉できない ことです。SYNとSYN-ACKの両方にオプションが載って初めて双方向で有効になり、確立後の途中変更はできません。
古いファイアウォールやNATがSYNのウィンドウスケールオプションを削ると、片側がシフト前提・片側がシフトなしで窓を解釈し、実窓が桁違いにずれます。症状は「コネクションは張れるのに転送が極端に遅い/止まる」という再現性の低い障害で、原因の特定が難しい典型例です。スケールが効いているかは確立時のSYNをキャプチャし、両方向に wscale N が出ているかで確認します。
バッファをBDPに合わせる:OSの自動チューニング
窓を広げられても、それを裏打ちする ソケットバッファ が小さければ意味がありません。送信側は未確認データをACKが返るまで送信バッファに保持し続ける必要があり、受信側はアプリが読み出すまで受信バッファに溜める。したがって実効の窓は次で頭打ちになります。
実効窓 ≦ min(送信バッファ, 受信バッファ, 交渉した最大窓)
→ いずれかが BDP 未満なら、そこがボトルネック
つまり全速を出す条件は、送受双方のバッファをBDP以上に確保することです。現代のLinuxは固定値ではなく、RTTの実測から必要量を推定してバッファを自動拡大する 受信バッファ自動チューニング(autotuning) を持ち、上限の範囲内で動的に窓を伸ばします。
# 受信/送信バッファの自動チューニング上限(最小 デフォルト 最大)
sysctl net.ipv4.tcp_rmem # 例: 4096 131072 6291456
sysctl net.ipv4.tcp_wmem # 例: 4096 16384 4194304
sysctl net.core.rmem_max net.core.wmem_max # autotuning の天井
# BDP が上限を超える超長距離・超高速路では天井を引き上げる
# 例: BDP=100MB の路なら *_max を 100MB 以上へ
pingで RTT を測る。2) 回線の帯域を確認する。3)BDP = 帯域 × RTTを byte で計算する。4)tcp_rmem/tcp_wmemとrmem_max/wmem_maxがそのBDP以上か確認する。低めの天井で頭打ちなら、BDPの2倍程度を上限に設定すると、再送中もパイプを維持しやすくなります。バッファとゼロコピーの内部は ソケットバッファとゼロコピー を参照。
Long Fat Network:広い窓には固有のリスクがある
BDPが大きい回線、すなわち帯域が太く(fat)遅延が大きい(long)経路を Long Fat Network(LFN、エルファン) と呼びます。LFNでは窓をBDPまで広げる必要がある一方、広い窓そのものが新たな問題を生みます。RFC 7323 が定義する対策は、窓拡張だけではありません。
| LFN固有の問題 | なぜ起きるか | 対策 |
|---|---|---|
| 窓が64KBで頭打ち | 16ビット窓 < BDP | ウィンドウスケールで最大1GBへ |
| シーケンス番号の周回(PAWS) | 高速だと32bit seqが1RTT内に1周し古い重複と区別不能 | TCPタイムスタンプで新旧を判定(PAWS) |
| RTT測定が粗くなる | 窓内に多数のセグメントがあり一部しかRTTを測れない | タイムスタンプで全セグメントのRTTを測定 |
| 損失1発の打撃が大きい | in-flightが巨大なため失われ得る量も巨大 | SACKで穴だけ選択再送、ロス耐性ある輻輳制御 |
とくに見落とされがちなのが、窓を広げるほど 未確認データが増え、パケット損失1発で再送すべき量も増える という構造です。古典的なReno系は損失のたびに窓を半減させるため、BDPの大きい路では一度の損失で回復に何十RTTもかかり、平均スループットが大きく落ちます。LFNでロスがある路では、損失に強い輻輳制御(CUBICやBBR)と、穴だけを選んで送り直す SACK(選択的確認応答) が前提になります。再送の選択ロジックは TCPの再送制御 を参照してください。
バッファをBDPより大きく取りすぎ、かつ経路上のキューも深いと、損失が起きる前にパケットがキューに溜まり込み、RTTが膨張します。窓は「RTTを膨らませず帯域を満たす」点で止めるのが理想で、ただ大きくすればよいわけではありません。経路キューが原因の遅延膨張は バッファブロートとAQM で扱う別問題で、エンドのバッファ拡大とは切り分けて考える必要があります。
設計のまとめ
LFNを使い切るには、3つの量を同時にBDPへ合わせます。第一に 交渉した最大窓 をウィンドウスケールでBDP以上に。第二に 送受のソケットバッファ を autotuning の上限ごとBDP以上に。第三に 輻輳窓 がBDPまで育つよう、損失耐性のある輻輳制御とSACK/タイムスタンプを有効に。このどれか1つでもBDP未満なら、そこがボトルネックになって帯域は遊びます。
「BDPの定義と意味」→ 帯域×RTT、回線を満たすのに常時飛ぶべきデータ量。「窓とスループットの関係」→ スループット ≦ 窓 ÷ RTT、窓がBDP未満なら帯域を使い切れない。「64KBの壁の理由と解法」→ 16ビット窓、ウィンドウスケールで左シフトし最大1GB、交渉はSYN/SYN-ACKのみ。「LFNでタイムスタンプが要る理由」→ PAWSによるseq周回対策と精密なRTT測定。「窓を広げる以外に要るもの」→ BDP以上のソケットバッファとSACK、損失耐性ある輻輳制御。
ネットワーク Article
バンド幅遅延積とウィンドウスケーリングの数理を実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
TCP
比較で見る軸
難易度: advanced / カテゴリ: ネットワーク / タグ数: 6
導入後に効く点
16ビットの窓欄は最大64KBで高BDP路に全く足りない。ウィンドウスケールで左シフトし、送受のソケットバッファをBDP以上に確保して初めて全速が出る。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- ネットワーク
- タグ数
- 6
判断チェックリスト
- 自社の用途が「TCP / BDP」に近いか確認する。
- 強みである「BDP(帯域×RTT)は回線を満たすのに常時飛んでいるべきデータ量。送信窓がBDP未満だとACK待ちで停止し、帯域は使い切れない。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。