輻輳制御 — 窓が鋸歯状に伸び縮みする

ネットワークには「1秒に運べる量」の上限があります。送り手が上限を超えて送り込むとルータのバッファがあふれ、パケットが捨てられる。TCP は自分の送信量 cwnd(輻輳ウィンドウ)を刻々と調整し、詰まりを避けながら帯域をめいっぱい使い、しかも複数の通信で公平に分け合う。その独特の 鋸歯(のこぎり)の動きを、動かして体感します。

1. なぜ制御がいるのか — あふれるバッファ

リンクの容量(1秒に送り出せるパケット数)は決まっています。送信レートがそれを超えると、超過分はルータのバッファ(キュー)に溜まっていきます。バッファも有限なので、いっぱいになると新しいパケットはそのまま捨てられます(パケットロス)。下で送信レートを容量より上げてみてください。キューが満杯になった瞬間、赤いロスが噴き出します。

ボトルネックのキュー — あふれるとロスが出る
青=到着するパケット、緑=リンクから送り出せたパケット、赤=あふれて捨てられたロス。リンク容量は 6 パケット/秒 固定。送信レートがこれを超えると、超過分がキューに溜まり、満杯でロスになります。
POINT — 送りすぎは自分の首を絞める ロスが起きると TCP は再送するので、詰まっているのにさらにパケットが増える。全員が遠慮なく送り続けると、実効スループット(届く量)が逆に落ちていく——これが輻輳崩壊。だから各送信者が「今どれだけ送ってよいか」を自分で加減する必要がある。

2. 窓の鋸歯 — スロースタートとAIMD

TCP は送信量の上限を cwnd(何パケット分を返事待ちにできるか)で管理し、次の2つのモードで動かします。まずスロースタート:1 RTT ごとに cwnd を2倍にして一気に立ち上げる(指数的)。しきい値 ssthresh を超えたら輻輳回避に切り替え、1 RTT ごとに+1 だけ慎重に増やす(線形)。そしてロスを検知したら cwnd を半分に折る。増やすときは足し算・減らすときは掛け算——これが AIMD です。

cwnd の時間変化 — 生まれる鋸歯
橙の曲線=スロースタート(指数)、緑の直線=輻輳回避(線形の +1/RTT)、赤い×=ロスで cwnd が半分に。赤い破線がリンク容量(ここに達するとバッファがあふれてロス)、紫の破線が しきい値 ssthresh。容量やロス率を変えると鋸歯の形が変わります。
加算増加: cwnd ← cwnd + 1  (1 RTT ごと)  /  乗算減少: cwnd ← cwnd × ½  (ロス時) AIMD = Additive Increase / Multiplicative Decrease。ゆっくり増やして、危なくなったら大きく引く。この非対称さが安定と公平の鍵

3. AIMD はなぜ「公平」なのか

不思議なのは、AIMD だと複数の通信が自然に帯域を等分していくこと。2つの通信の送信量を x・y 軸にとって動きを追うと理由が見えます。増加は両者に同じ +1 なので差を保ったまま斜め45°に進み、減少は両者を½倍するので差そのものを半分に縮める。増やすたびに容量の線へ近づき、減らすたびに公平の線(y=x)へ寄る——結果、誰が先に始めてもまん中の公平点へ収束します。

2つの通信の綱引き — 公平点への収束
白い軌跡=2通信の状態(横=通信A、縦=通信B)。赤の線=容量いっぱい(x+y=容量)、緑の線=完全に公平(y=x)、★=公平かつ効率的な理想点。斜めに伸び(加算増加)→ 原点向きに折れ(乗算減少)を繰り返し、必ず★へ吸い寄せられます。
注意 — 「速い方が偉い」わけではない もし減少だけ・増加だけ、あるいは両者を掛け算で増やすと、この収束は起きず一方が帯域を独占しうる。足し算で増やし・掛け算で減らすという組み合わせだからこそ、差が縮んで公平になる。AIMD は「みんなで譲り合う」ための最小限の作法。

4. 制御があると何が守られるか — 崩壊の回避

送信量を上げれば上げるほど届く量(グッドプット)も増える——のは容量までの話。制御なしで押し込み続けると、ロスと再送で届く量はむしろ坂を転げ落ちます(輻輳崩壊)。輻輳制御は、みなが容量の手前で歩調を合わせることで、この崩壊を防ぎ、スループットを頂点付近に保ちます。下のスライダーで提供負荷を上げ、制御あり(緑)と制御なし(赤)の運命の違いを見てください。

提供負荷 と グッドプット — 崩壊する曲線/保たれる曲線
横=ネットワークに送り込む量(提供負荷。1.0 が容量ちょうど)、縦=実際に届く量(グッドプット)。緑=輻輳制御あり(容量で頭打ちになり保たれる)、赤=制御なし(容量を超えると再送地獄で崩壊)。縦線が現在の負荷、丸が届く量です。

5. まとめ — 譲り合いのアルゴリズム

一歩先へ — Reno から CUBIC・BBR へ ここで見たのは古典的な TCP Reno の姿。いまの Linux 既定 CUBIC は、ロス後の回復を三次関数の曲線で描いて高速・広帯域リンクでも窓を大きく保つ。さらに Google の BBR は「ロスが出てから引く」のをやめ、往復遅延と帯域を実測してバッファを膨らませない地点を狙う。鋸歯の思想は同じでも、増減のカーブとロスの解釈が進化し続けている。