6. アルゴリズム (Algorithm)
6.1. 初期化ステップ (Initialization Steps)
輻輳制御アルゴリズムによって開始された輻輳制御応答フェーズの開始時に、PRRを使用するデータ送信者はPRR状態を初期化しなければなりません (しなければならない)。
輻輳制御応答フェーズが開始するタイミングは、完全に輻輳制御アルゴリズムによって決定されます。たとえば、高速リカバリフェーズの開始に対応する場合もあれば、失われた再送信または失われた元の送信の検出時に高速リカバリが既に進行中である場合、各ラウンドで削減が実行される場合もあります。
PRR初期化により、輻輳制御アルゴリズムCongCtrlAlg()がssthreshをFlightSize/2以外の値に設定することができます (できる) (例えば、CUBIC [RFC9438]を含む)。
PRR初期化の重要なステップは、リカバリフライトサイズ (Recovery Flight Size, RecoverFS) を計算することです。これは、現在のPRRフェーズ中に配信される可能性のあるバイト数の送信者の推定値です。これは、フェーズの開始時における次の値の合計と考えることができます: インフライト、リカバリをトリガーしたACKで累積的に確認応答されたバイト、リカバリをトリガーしたACKでSACKされたバイト、およびSND.UNAとSND.NXTの間で既に損失としてマークされているバイト。RecoverFSには損失が含まれます。なぜなら、損失はヒューリスティックを使用してマークされるため、リカバリ中に以前に損失としてマークされた一部のパケットが最終的に (再送信を必要とせずに) 配信される可能性があるからです。PRRはRecoverFSを使用して、スムーズな送信レートを計算します。高速リカバリに入ると、PRRはRecoverFSを初期化し、RecoverFSは特定の高速リカバリフェーズ全体を通じて一定のままです。
PRRアルゴリズム初期化ステップの完全なシーケンスは次のとおりです:
ssthresh = CongCtrlAlg() // リカバリ中の目標フライトサイズ
prr_delivered = 0 // リカバリ中に配信された総バイト数
prr_out = 0 // リカバリ中に送信された総バイト数
RecoverFS = SND.NXT - SND.UNA // リカバリに入る前にSACKされたバイト
// リカバリに入る前にSACKされたバイトは、リカバリ中に
// 配信されたものとしてマークされません:
RecoverFS -= (スコアボード内のSACKされたバイト)
// 選択的にACKされたバイトを含める (一般的なケース):
RecoverFS += (新しくSACKされたバイト)
// 累積的に確認応答されたバイトを含める (まれなケース):
RecoverFS += (新しく累積的に確認応答されたバイト)
6.2. ACKごとのステップ (Per-ACK Steps)
高速リカバリの開始時または高速リカバリ中の各ACKで、PRRフェーズを終了するACKを除いて、PRRは次のステップを実行します。
まず、送信者はDeliveredDataを計算します。これは、現在のACKが以前に受信したACK以降に受信者に配信されたことを示す総バイト数に対するデータ送信者の最良の推定値です。SACKを使用すると、DeliveredDataは、SND.UNAの変化に、スコアボード内でSACKされたとマークされたデータ量の符号付き変化を加えたものとして正確に計算できます。したがって、ACKの前後でスコアボード内にSACKされたシーケンス範囲がない特殊なケースでは、DeliveredDataはSND.UNAの変化です。
SACKのないリカバリでは、DeliveredDataは受信した各重複ACKで1 SMSSと推定されます (つまり、SND.UNAは変化していません)。SND.UNAが前進する場合 (つまり、完全または部分ACK)、DeliveredDataはSND.UNAの変化から、先行する各重複ACKの1 SMSSを引いたものです。SACKがない場合、過剰な重複ACKを返す不正な動作をする受信者 ([Savage99]で説明されているように) がDeliveredDataを人為的に膨らませようとする可能性があることに注意してください。緩和策として、SACKが使用されていない場合、PRRフェーズで配信された総バイト数がリカバリに入ったときの推定未処理データ (RecoverFS) を超える場合、PRRはDeliveredDataの増加を許可しません。
次に、送信者はインフライトを計算します。これは、ネットワーク内を飛行している未確認応答バイト数に対するデータ送信者の最良の推定値です。インフライトを計算するために、SACKが有効で[RFC6675]損失検出を使用する接続は、[RFC6675]で指定されている「パイプ」アルゴリズムを使用できます。RACK-TLP損失検出 [RFC8985]または他の損失検出アルゴリズムを使用するSACK対応接続は、SND.NXT - SND.UNAから開始し、スコアボード内のSACKされたバイトを減算し、スコアボード内の損失としてマークされたバイトを減算し、損失としてマークされて以降に再送信されたスコアボードからのバイトを追加することによって、インフライトを計算しなければなりません (しなければならない)。
SACKが有効でない接続の場合、送信者は次を減算しなければなりません (しなければならない): min(RecoverFS, 高速リカバリフェーズの先行する各重複ACKの1 SMSS); RecoverFSとのmin()は、不正な動作をする受信者 [Savage99]から防御するためのものであり、SACKスコアボード内のSACKされたバイトを減算する代わりです。
次に、送信者はSafeACKを計算します。これは、現在のACKが良好な進行を報告していることを示すローカルブール変数です。SafeACKは、ACKが新しいデータを累積的に確認応答し、ACKがさらなる損失を示さない場合にのみtrueです。たとえば、「救助 (rescue)」再送信をトリガーするACK ([RFC6675]のセクション4、NextSeg()条件4) は、さらなる損失を示す可能性があります。これらの両方の条件は、リカバリが順調に進んでいることを示しており、適切であれば送信者はより攻撃的に送信でき、インフライトを増加させることができます。
最後に、送信者は、DeliveredData、インフライト、SafeACK、およびその他のPRR状態を使用してSndCntを計算します。SndCntは、各ACKに応答して何バイト送信すべきかを示すローカル変数であり、その後SndCntを使用してcwndを更新します。
ACKごとのPRRアルゴリズムステップの完全なシーケンスは次のとおりです:
if (DeliveredData is 0)
Return
prr_delivered += DeliveredData
inflight = (推定されるインフライトデータ量)
SafeACK = (SND.UNAが前進し、さらなる損失が示されていない)
if (inflight > ssthresh) {
// 比例速度削減
// これは整数除算を使用し、切り上げます:
#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
out = DIV_ROUND_UP(prr_delivered * ssthresh, RecoverFS)
SndCnt = out - prr_out
} else {
// デフォルトでPRR-CRBを使用
SndCnt = MAX(prr_delivered - prr_out, DeliveredData)
if (SafeACK) {
// リカバリが順調に進んでいるときはPRR-SSRBを使用
SndCnt += SMSS
}
// 許可されている限り追いつこうとする
SndCnt = MIN(ssthresh - inflight, SndCnt)
}
if (prr_out is 0 AND SndCnt is 0) {
// リカバリに入ったときに高速再送信を強制
SndCnt = SMSS
}
cwnd = inflight + SndCnt
送信者がSndCntを計算し、それを使用してcwndを更新した後、送信者はより多くのデータを送信します。どのデータを送信するかの決定 (たとえば、欠落しているデータを再送信するか、より多くの新しいデータを送信するか) は、本文書の範囲外であることに注意してください。
6.3. 送信ごとのステップ (Per-Transmit Steps)
任意のデータ送信または再送信時に、PRRは次を実行します:
prr_out += (送信されたデータ)
6.4. 完了ステップ (Completion Steps)
PRRフェーズは、高速リカバリを完了するとき、または新しい輻輳制御応答フェーズのために新しいPRRフェーズを開始する前に終了します。
PRRフェーズを完了すると、PRRは次を実行します:
cwnd = ssthresh
このcwndをssthreshに設定するステップは、場合によってはネットワークへのセグメントの連続したバーストを許可する可能性があることに注意してください。
実装は、データフローのバースト性を減らすためにペーシング (pacing) を使用することが推奨されます (推奨される)。この推奨は、アイドル状態からの再起動後の送信バーストのペーシングを含む、バースト性を緩和するための現在の実践 (例えば、[PACING]) と一致しています。