QUICの損失復旧はACKを基に損失した送信を判定して必要な情報を送り直し、混雑制御は一つの接続内のストリームが共有する送信上限を調整します。

一つのQUIC接続で、あるストリームのパケット損失中も他のストリームのデータ配信が続く概念図

1. QUICのパケット番号と再送される情報

QUICでは暗号化レベルごとに必ず別のパケット番号空間を設けるわけではありません。RFC 9002 §4.1によると、0-RTTとすべての世代の1-RTTパケットはApplication Dataのパケット番号空間を共有し、同じ空間内で番号は重複しません。番号は送信を識別し、その順序を追跡するために使われます。損失したパケットの情報を再び送る必要がある場合、元のパケットを複製するのではなく、必要なフレームを新しい番号のパケットに載せます。ACKの範囲は受信したパケット番号を示します。送信側は新たに確認されたパケットの送信時刻などからRTT標本を計算しますが、ACKだけで経路遅延を完全に把握できるわけではないため、ACK遅延、再並び替え、測定条件も考慮します。

2. 損失の判定とPTOの発火は別の処理

RFC 9002は、ACKに基づく損失判定としてパケット数の閾値と時間の閾値を定めています。推奨されるパケット閾値は3で、時間閾値は最新RTTと平滑RTTの大きい方の9/8を基準にします。ネットワーク上の再並び替えをある程度許容しながら、十分に遅れた未確認パケットを損失と判定するための基準です。

Probe Timeout(PTO)は異なる状況に対応します。確認を促すパケットが飛行中なのにACKが届かない場合、送信側はRTTの推定値と変動幅を使ってPTOを計算し、適用されるときは相手が示した最大ACK遅延も加味します。タイマーが満了すると、応答を促すためACKを要求するプローブパケットを1個または2個送信します。PTOが満了しただけで未確認パケットすべてが損失と判定されるわけではなく、混雑ウィンドウが自動的に1 MSSへ縮小されることもありません。個々のパケットの損失は、その後のACKと閾値処理で判定されます。

3. 混雑制御が調整する送信量

損失復旧と混雑制御は連携しますが、役割は異なります。復旧処理は確認済み・損失と判定された送信を追跡し、必要な情報を再送できるようにします。混雑制御は経路からの信号に応じて、未確認のまま飛行中にできるデータ量を調整します。RFC 9002の付録には、スロースタート、混雑回避、復旧期間を含む実装例の疑似コードがあります。その例では新たな混雑イベントで混雑ウィンドウを縮小し、アプリケーションやフロー制御に制限されていない場合、確認されたデータに応じて再び増加させます。これは例示であり、すべてのQUIC実装に同一の制御方式を要求するものではありません。実際の挙動は実装、設定、経路上で観測されるACKや損失の信号に左右されます。

RFC 9002付録Bの制御例では、新たな損失またはECNの混雑信号が確認されると復旧期間に入り、混雑ウィンドウを縮小します。持続的混雑と判定された場合は最小ウィンドウまで下げます。ACKを受け取るたびに必ずウィンドウを増やすわけではありません。送信側がアプリケーションやフロー制御で制限されている場合、または確認されたパケットが復旧期間に属する場合、例示アルゴリズムは増加を抑えます。これはRFCの制御例の動作であり、すべてのブラウザーやサーバーが同じ値を使うという保証ではありません。

4. 専門家の視点:HTTP/2とHTTP/3で損失が及ぼす範囲

HTTP/2は複数のHTTPストリームを一つのTCP接続上で多重化します。TCPはバイト列の順序を保証するため、途中のバイトが欠けると、その接続上で後から届いたバイトも欠落部分が復旧するまでアプリケーションへ渡せないことがあります。このトランスポート層のヘッドオブラインブロッキングは、同じTCP接続を共有する別のHTTP/2ストリームにも影響し得ます。

HTTP/3はQUICストリームごとにオフセットと順序付き配信を管理します。一つのストリームのデータが欠ければ、そのストリーム内の後続データは待つ場合がありますが、接続全体で一つのバイト順序を保つために別ストリームまで同じ欠落を待つ必要はありません。Cloudflareの「The Road to QUIC」はこの違いを説明し、QUICストリーム間では混雑状態を共有すると明記しています。また、あるストリームの損失が他に影響しないのは「多くの場合」と限定しています。この但し書きが重要です。共有混雑制御や接続レベルのフロー制御は複数ストリームに影響するため、損失の影響が完全に隔離されるわけではなく、すべてのページが必ず速くなるとも限りません。

参考資料