3.1. スロースタートと輻輳回避
TCP送信側しなければならない (MUST) スロースタートと輻輳回避アルゴリズムを使用して、ネットワークに注入される未処理データの量を制御します。
状態変数
これらのアルゴリズムを実装するために、TCP接続ごとの状態に2つの変数が追加されます:
- 輻輳ウィンドウ (Congestion Window, cwnd): 確認応答(ACK)を受信する前に送信側がネットワークに送信できるデータ量に対する送信側の制限
- 受信側通知ウィンドウ (Receiver's Advertised Window, rwnd): 未処理データ量に対する受信側の制限
cwndとrwndの最小値がデータ送信を制御します。
別の状態変数であるスロースタート閾値 (Slow Start Threshold, ssthresh) は、データ送信を制御するためにスロースタートアルゴリズムと輻輳回避アルゴリズムのどちらを使用するかを決定するために使用されます。
スロースタートの目的
未知の条件のネットワークへの送信開始には、不適切に大きなデータバーストでネットワークを輻輳させることを避けるために、TCPがネットワークをゆっくりと探索して利用可能な容量を決定する必要があります。スロースタートアルゴリズムは次の目的で使用されます:
- 転送の開始時
- 再送信タイマーによって検出された損失を修復した後
スロースタートは、TCP送信側がスロースタート、輻輳回避、および損失回復アルゴリズムでネットワークにデータを解放するために使用する「ACKクロック」を開始する役割も果たします。
初期ウィンドウ (IW)
IW、つまりcwndの初期値は、上限として次のガイドラインを使用して設定しなければならない (MUST):
SMSS > 2190バイトの場合:
IW = 2 * SMSSバイトで、2セグメントを超えてはならない
(SMSS > 1095バイト) かつ (SMSS <= 2190バイト)の場合:
IW = 3 * SMSSバイトで、3セグメントを超えてはならない
SMSS <= 1095バイトの場合:
IW = 4 * SMSSバイトで、4セグメントを超えてはならない
[RFC3390]で規定されているように、SYN/ACKとSYN/ACKの確認応答は輻輳ウィンドウのサイズを増加させてはならない (MUST NOT)。さらに、SYNまたはSYN/ACKが失われた場合、正しく送信されたSYNの後に送信側が使用する初期ウィンドウは、最大SMSSバイトからなる1セグメントでなければならない (MUST)。
IW設定の詳細な根拠と議論は[RFC3390]で提供されています。
初期ssthresh値
ssthreshの初期値は任意に高く設定すべきである (SHOULD) (例えば、可能な最大通知ウィンドウのサイズに設定)が、ssthreshは輻輳に応じて減少しなければならない (MUST)。
ssthreshをできるだけ高く設定することで、任意のホスト制限ではなくネットワーク条件が送信レートを決定できるようになります。
アルゴリズムの選択
cwnd < ssthreshの場合、スロースタートアルゴリズムを使用cwnd > ssthreshの場合、輻輳回避アルゴリズムを使用cwndとssthreshが等しい場合、送信側はスロースタートまたは輻輳回避のいずれかを使用できる
スロースタートアルゴリズム
スロースタート中、TCPは新しいデータを累積的に確認応答する受信したACKごとに、cwndを最大SMSSバイト増加します。スロースタートは次の場合に終了します:
- cwndがssthreshを超える(または、上記のように、オプションでそれに達する)場合、または
- 輻輳が観測された場合
推奨されるcwnd増加方法
従来、TCP実装は新しいデータをカバーするACKを受信すると正確にSMSSバイトだけcwndを増加してきましたが、次の方法でcwndを増加することを推奨します (RECOMMEND):
cwnd += min (N, SMSS) (式 2)
ここで、Nは受信したACKで確認応答された以前に未確認応答のバイト数です。
この調整は適切バイト計数(Appropriate Byte Counting)[RFC3465]の一部であり、「ACK分割」[SCWA99]と呼ばれるメカニズムを使用して送信側にcwndを人為的に膨張させようとする不正な受信側に対する堅牢性を提供します。
輻輳回避アルゴリズム
輻輳回避中、cwndは1ラウンドトリップ時間(RTT)ごとに約1フルサイズセグメント増加します。輻輳回避は輻輳が検出されるまで続きます。
cwnd増加のガイドライン
輻輳回避中のcwnd増加の基本ガイドラインは:
- cwndをSMSSバイト増加してもよい (MAY)
- RTTごとに1回、式(2)に従ってcwndを増加すべきである (SHOULD)
- cwndをSMSSバイト以上増加してはならない (MUST NOT)
推奨される実装
輻輳回避中にcwndを増加する推奨される (RECOMMENDED) 方法は、新しいデータのACKによって確認応答されたバイト数を数えることです。確認応答されたバイト数がcwndに達すると、cwndを最大SMSSバイトまで増加できます。
輻輳回避中、cwndはRTTごとにSMSSバイトを超えて増加してはならない (MUST NOT) ことに注意してください。
損失への応答
TCP送信側が再送信タイマーを使用してセグメント損失を検出し、指定されたセグメントがまだ再送信タイマーによって再送信されていない場合、ssthreshの値は式(4)で与えられる値以下に設定しなければならない (MUST):
ssthresh = max (FlightSize / 2, 2*SMSS) (式 4)
ここで、上記のように、FlightSizeはネットワーク内の未処理データの量です。
さらに、タイムアウト時([RFC2988]で規定)、cwndは損失ウィンドウLW以下に設定しなければならない (MUST)。LWは1フルサイズセグメントに等しくなります(IWの値に関係なく)。
したがって、ドロップされたセグメントを再送信した後、TCP送信側はスロースタートアルゴリズムを使用して、ウィンドウを1フルサイズセグメントからssthreshの新しい値まで増加させ、その時点で輻輳回避が再び引き継ぎます。