7. 輻輳制御 (Congestion Control)
SCTPは、ネットワーク輻輳を回避し、ネットワークリソースの公平な共有を確保するために、TCPと類似した輻輳制御メカニズムを使用します。
7.1. SCTPとTCP輻輳制御の違い (SCTP Differences from TCP Congestion Control)
SCTPの輻輳制御はTCPのメカニズムに基づいていますが、以下の重要な違いがあります:
7.1.1. マルチホームとマルチパス
SCTPはマルチホームエンドポイントをサポートし、各宛先トランスポートアドレスは独立した輻輳制御パラメータを維持します:
- 宛先ごとのcwnd: 各パスは独自の輻輳ウィンドウを持つ
- 宛先ごとのssthresh: 各パスは独自のスロースタート閾値を持つ
- 宛先ごとのRTO: 各パスは独自の再送信タイムアウトを持つ
これにより、SCTPは異なるパス上で独立して輻輳制御を実行できます。
7.1.2. TSNベースの確認応答
SCTPは、バイトシーケンス番号ではなくTSNを使用して確認応答します。これは次のことを意味します:
- 輻輳ウィンドウはバイト単位で維持される
- SACKはTSN範囲を確認する
- cwnd更新は、TSN数ではなく確認されたバイト数に基づく
7.1.3. マルチストリーム送信
SCTPの複数のストリームは、同じアソシエーションの輻輳制御パラメータを共有します。ストリーム間に個別の輻輳制御はなく、これにより以下が保証されます:
- すべてのストリームが帯域幅を公平に共有
- 単一のストリームがリソースを独占することを防ぐ
7.2. SCTPスロースタートと輻輳回避 (SCTP Slow-Start and Congestion Avoidance)
SCTPの輻輳制御アルゴリズムは、TCPのスロースタートと輻輳回避の原則に従います。
7.2.1. 初期化と再起動
アソシエーションが最初に確立されたとき、またはパスがアイドル後に再起動したとき:
cwnd = min(4*MTU, max(2*MTU, 4380バイト))
ssthresh = ピアのa_rwnd
注意: 初期cwndの計算は、少なくとも2つの完全なパケットを送信できることを保証しますが、4つのMTUサイズのパケットを超えません。
7.2.2. スロースタートフェーズ
スロースタート中(cwnd <= ssthresh):
新しいデータのSACKを受信したとき:
cwnd = cwnd + min(確認されたバイト数, MTU)
ルール:
- cwndは一度に最大1つのMTUずつ増加
- すべての確認されたデータが現在のcwnd下で送信された場合にのみ増加
- cwndがssthreshに達するか超えると、輻輳回避フェーズに入る
7.2.3. 輻輳回避フェーズ
cwnd > ssthreshのとき:
適切なバイトカウンティング (Appropriate Byte Counting, ABC) を使用:
RTTごとに:
partial_bytes_acked = partial_bytes_acked + 確認されたバイト数
partial_bytes_acked >= cwnd のとき:
cwnd = cwnd + MTU
partial_bytes_acked = partial_bytes_acked - cwnd
目標: RTTごとにcwndを約1 MTU増加させる。
7.2.4. 輻輳検出と応答
輻輳の信号:
- 再送信タイムアウト (RTOの期限切れ)
- 高速再送信 (4つの重複SACKを受信)
RTOタイムアウトへの応答:
ssthresh = max(cwnd/2, 4*MTU)
cwnd = 1*MTU
partial_bytes_acked = 0
高速再送信への応答:
ssthresh = max(cwnd/2, 4*MTU)
cwnd = ssthresh
partial_bytes_acked = 0
7.2.5. アイドル期間後の処理
宛先がRTO期間内にデータ送信がない場合(アイドル):
オプション1 (推奨):
cwnd = max(cwnd/2, 4*MTU)
オプション2 (保守的):
cwnd = min(4*MTU, max(2*MTU, 4380バイト))
これにより、長いアイドル期間の後に突然大量のデータを送信することを防ぎます。
7.3. パスMTU発見 (Path MTU Discovery)
SCTPエンドポイントは、パスMTU発見([RFC4821]で定義されたPacketization Layer PMTUD)を使用すべきです (SHOULD):
- 宛先への最大利用可能MTUを決定
- IP断片化を回避
- データ転送効率を最適化
7.3.1. PMTU発見プロセス
-
初期MTU: 保守的な初期値を使用(通常、IPv4では576バイト、IPv6では1280バイト)
-
より大きなMTUを探索:
- "Don't Fragment"フラグを設定したパケットを送信
- 成功した場合、より大きなMTUを試す
- 失敗した場合(ICMP "Packet Too Big"を受信)、より小さいMTUを使用
-
定期的な再探索: パスの変化に適応するために、定期的により大きなMTUを試す
7.3.2. MTU更新が輻輳制御に与える影響
PMTUが増加したとき:
cwnd = (cwnd / 旧MTU) * 新MTU
ssthresh = (ssthresh / 旧MTU) * 新MTU
PMTUが減少したとき:
cwnd = (cwnd / 旧MTU) * 新MTU
ssthresh = (ssthresh / 旧MTU) * 新MTU
partial_bytes_acked = min(partial_bytes_acked, cwnd)
これにより、輻輳制御パラメータがMTUサイズと一貫した関係を維持することが保証されます。
7.3.3. 失敗処理
PMTU発見が失敗または利用できない場合:
- 保守的なMTU値を使用
- "Don't Fragment"フラグを使用しない
- IP層による断片化を許可
まとめ
SCTPの輻輳制御設計は、以下の重要な要素を考慮しています:
- マルチパスサポート: パスごとの独立した輻輳制御
- TCP親和性: TCPとのネットワーク帯域幅の公平な共有
- マルチストリーム効率: 輻輳制御を維持しながらヘッドオブラインブロッキングを回避
- パス適応: PMTU発見による送信の最適化
これらのメカニズムにより、SCTPはネットワークリソースを効率的に利用しながら、他のトラフィックと公平に共存できます。