要約

  • 累積ACKは、番号より前の全バイトがそろったことを保証する。途中に穴があれば、その先を受信していても境界は進まない。
  • SACKは接続開始時に利用を合意し、受信済みの飛び地を左右のシーケンス番号で報告する。通常のACKの意味も再送の責任主体も変えない。
  • 報告できる区間数は少なく、受信側が後でデータを捨てる可能性もある。送信側は累積ACKまで原本を保持し、輻輳制御にも従う。

5000の後ろに届いていたもの

次に必要なのがバイト5000だとする。そこを含むセグメントだけが消え、後続の七つは届いて5500から9000まで連続して待っている。TCPヘッダーのACK番号は5000のままだ。これは後続を無視した値ではなく、「5000から先へ連続性を保証できない」という厳密な値である。

ところが送信側には情報が足りない。同じ5000が続いても、一つだけ欠けたのか、後続も多数失われたのかは分からない。全体を送り直せば到着済みデータを重複させる。一つの往復ごとに次の穴を発見すれば、高遅延の経路では回復が遅すぎる。

RFC 793の累積確認は、ACK XX未満の全オクテットを確認し、Xを次の期待値とする。この強い約束が送信バッファを解放できる根拠になった。同時に、穴の先の状態を一つの数値へ入れられないという限界も作った。

RFCになっても使われなかった最初の案

1988年のRFC 1072は二つのTCPオプションを提案した。SYNのSACK-Permittedで利用可能性を伝え、接続後のSACKで不連続な受信ブロックを返す。理解しない相手はオプションを無視し、従来の累積ACKを続けられる設計だった。

それでも、この形式はインターネットに展開されなかった。RFC 2018は、ウィンドウスケールとの併用方法に意見の相違があったと記す。仕様の存在は、相互運用する実装の存在とは別である。文書は候補を残したが、稼働するコードが合意するまで移行は完了しなかった。

1996年版はSYNでの合意を維持し、ブロックを32ビットの完全な左右端で表した。左端は受信済みの最初、右端は最後の直後である。ACK 5000を保ったまま、SACKは[5500, 9000)を示せる。確定済みの連続範囲と、穴の先の観測が別々に表現された。

一枚に描ける島は四つまで

TCPオプション領域は40バイトしかない。SACKは種類と長さに2バイト、各ブロックに8バイトを使うため、単独でも最大4ブロックである。タイムスタンプと併用すれば通常は3ブロックに減る。受信キューの飛び地がそれ以上あっても、全景は一つのACKへ入らない。

そこで最新到着によって変化したブロックを先頭に置き、以前のブロックも繰り返す。戻りのACKも失われるからだ。送信側は複数の短い報告を統合し、内部のscoreboardを更新する。

共通化したのは受信キューそのものではなく、区間を記述する方法だけだった。OSごとにメモリー管理やデータ構造が異なってもよい。相互運用に必要な境界だけを共有した点に、この拡張の節度がある。

SACKは受領証ではない

RFC 2018はSACKをadvisory、すなわち助言的な情報とする。受信側は一度報告したデータを後で捨てることができる。送信側は通常の回復中にSACK済み区間を飛ばせるが、累積ACKが通過するまで元データを解放してはならない。

再送タイマーが切れた場合、過去のSACKを無条件に信じず、左端からの保証へ戻る。観測と最終確定を分けるための後退路である。効率化のための情報が、取り消せない約束へ勝手に昇格しない。

再送キューを持ち、ブロックを統合し、次に送る区間を選ぶのは送信側である。RFC 6675は後にscoreboardとネットワーク内に残るデータ量の推定を用いた保守的な回復手順を示した。受信側は証拠を出すが、送信機の操作権は得ない。

正確な損失情報は送信枠ではない

SACKを使っても輻輳制御は残る。RFC 2018は、単一の順序外ACKだけで回復を始めず、回復中の送信量を制限し、必要なときは輻輳ウィンドウを縮小するよう求める。

1986年の輻輳崩壊対策とは役割が違う。輻輳ウィンドウは経路へ置いてよい量を決める。SACKはその量の中で、どのバイトを再送すべきかを精密にする。穴の位置が分かっても、共有回線の容量は増えない。

2000年のD-SACKは重複到着も報告できるようにした。送信側は並べ替え、ACK損失、複製、早すぎるタイムアウトを推測できる。しかしRFC 2883は一つの対応を命令せず、受信側の報告を必ず信頼できるともしていない。観測能力と指揮権を分けたまま、診断だけを豊かにした。

情報源と証拠の限界

累積ACKの原型はRFC 793、初期案はRFC 1072、改訂されたSACKはRFC 2018にある。RFC 2883がD-SACK、RFC 5681が輻輳制御、RFC 6247が旧案の歴史的位置、RFC 6675が保守的回復を示す。

RFCは仕様と制約を証明するが、全世界の導入日や全経路で同じ性能改善を証明しない。SACKブロックだけでは損失地点も原因も分からず、送信者の身元も保証しない。