web-dev-qa-db-ja.com

TCP輻輳制御-グラフの高速リカバリ

「コンピュータネットワーク:トップダウンアプローチ」という本を読んでいて、理解できない質問に遭遇しました。

私が読んだように、TCP輻輳制御には、スロースタート、輻輳回避、高速復旧の3つの状態があります。スロースタートと輻輳回避はよく理解していますが、高速復旧はかなりあいまいです。この本は、TCPはこのように動作する:(cwnd =輻輳ウィンドウ)と主張しています。 enter image description here
次のグラフを見てみましょう。 Transmission round-Congestion window size graph

ご覧のとおり、ラウンド16で送信者は42セグメントを送信し、輻輳ウィンドウサイズが半分(+3)になっているため、3つの重複ACKがあったと推測できます。この質問に対する答えは、16と22の間のラウンドは輻輳回避状態にあるであると主張しています。しかし、なぜ高速回復ではないのですか?つまり、3つの重複ACKの後TCPは高速リカバリに入り、他のすべての重複ACKは輻輳ウィンドウを増やすはずなので、グラフにそれが表されないのはなぜですか?私が考えることができる唯一の合理的な説明はこのグラフでは、重複したACKは3つしかなく、それ以降に受信されたACKは重複していませんでした。

その場合でも、ACKが3つ以上重複しているとしたら、グラフはどのように見えるでしょうか。 **

上のグラフにFast Recoveryの表現はありますか?なぜ/はい?

**私は長い間その質問に答えるのに苦労してきました。お返事をよろしくお願いします、ありがとうございます!

[〜#〜] update [〜#〜]これが画像です。ラウンドは、ウィンドウ内のすべてのセグメントがACKされているときと定義されていると思います。写真では、丸が丸で示されています。 enter image description hereFast Recovery状態のときにcwndが指数関数的に成長するのはなぜですか?(画像では、指数関数的ではなく、誤って適切に書き込んだ)

18

[〜#〜] update [〜#〜]:私の元の答えは解決策に同意しましたが、慎重に検討した結果、解決策は間違っていると思います。この答えは最初から書き直されました。よくお読みください。時間T = 16で高速リカバリが開始される理由と、プロトコルがT = 22までそこにとどまる理由を示します。グラフのデータは私の理論を裏付けているので、私は解決策が明らかに間違っていることをかなり確信しています。

まず、何かをまっすぐに設定してみましょう。スロースタートは指数関数的に増加します。 cwndの値を更新するためにスロースタートと同じ式を使用している場合でも、輻輳回避は直線的に増加し、高速リカバリは直線的に増加します。

はっきりさせておきます。

スロースタートが指数関数的にcwnd成長すると言うのはなぜですか?

cwndは、受信したACKごとにMSSバイトずつ増加することに注意してください

例を見てみましょう。 cwndが1MSSに初期化されているとします(MSSの値は通常1460バイトであるため、実際にはcwndは1460に初期化されます)。この時点で、輻輳ウィンドウサイズは1パケットしか保持できないため、TCPは、このパケットが確認されるまで新しいデータを送信しません。ACKが失われていないと仮定すると、これは約1パケットを意味します。パケットを送信するには(1/2)* RTTが必要であり、ACKが到着するには(1/2)* RTTが必要なため、新しいパケットはRTT秒ごとに転送されます(RTTはラウンドトリップ時間であることを思い出してください)。

したがって、この結果、送信レートはおおよそMSS/RTT bpsになります。ここで、ACKごとに、cwndMSSずつインクリメントされることに注意してください。したがって、最初のACKが到着すると、cwndは_2*MSS_になるので、2つのパケットを送信できます。これらの2つのパケットが確認されると、cwndtwiceが増加するため、cwndは_4*MSS_になります。すごい! 4パケット送信できます。これらの4つのパケットは確認応答されるため、cwndを4回インクリメントします。つまり、_cwnd = 8*MSS_があります。そして、_cwnd = 16*MSS_を取得します。基本的に、RTT秒ごとにcwndを2倍にします(これにより、輻輳回避のcwnd = cwnd+MSS*(MSS/cwnd)が線形成長につながる理由も説明されます)

はい、注意が必要です。式_cwnd = cwnd+MSS_を使用すると、線形であると簡単に信じられます。これは、確認済みの各パケットに適用されることを忘れがちなため、よくある誤解です。

現実の世界では、4つのパケットを送信しても必ずしも4つのACKが生成されるとは限らないことに注意してください。これは1つのACKのみを生成する可能性がありますが、TCPは累積ACKを使用するため、その単一のACKはまだ4つのパケットを確認しています。

高速復旧が線形である理由

_cwnd = cwnd+MSS_式は、スロースタートと輻輳回避の両方に適用されます。これにより、両方の州が指数関数的成長を引き起こすと考えられます。ただし、高速リカバリでは、重複するACKを受信した場合など、別のコンテキストでその式が適用されます。ここに違いがあります。スロースタートでは、1つのRTTが一連のセグメント全体を確認し、確認された各セグメントが+ 1MSSでcwndの新しい値に寄与しましたが、高速リカバリでは、重複ACKがRTTを浪費して単一のセグメントであるため、RTT秒ごとにcwndをN回更新する代わりに(Nは送信されたセグメントの数)、LOSTであったセグメントのcwndonceを更新します。したがって、1つのセグメントだけで1つのラウンドトリップを「無駄にした」ので、cwndを1だけインクリメントします。

輻輳回避について-これはグラフを分析するときに以下で説明します。

グラフの分析

では、そのグラフで何が起こっているかを正確に見ていきましょう。あなたの写真はある程度正しいです。最初にいくつかのことをクリアしましょう:

  1. スロースタートとファストリカバリが指数関数的に成長すると言うとき、それはあなたがあなたの写真に示すように、それが指数関数的にラウンドごとに成長することを意味します。だから、それは正しいです。青い円でラウンドを正しく識別しました。cwndの値が1つの円から次の円に指数関数的に増加することに注目してください-1、2、4、8、16、.. ..
  2. あなたの写真は、スロースタートの後、プロトコルが高速リカバリに入ったと言っているようです。これは起こりません。スロースタートから高速リカバリに移行した場合、cwndが半分になります。これはグラフが示すものではありません。cwndの値はT = 6からT = 7まで半分に減少しません。

では、各ラウンドで何が起こるかを正確に見てみましょう。グラフの時間単位はラウンドであることに注意してください。したがって、時間T = XでNセグメントを送信する場合、時間T = X + 1でこれらのNセグメントがACKされたと想定されます(もちろん、それらは失われなかったと仮定します)。

また、グラフを見るだけでssthreshの値を確認する方法にも注意してください。 T = 6で、cwndは指数関数的に増加しなくなり、直線的に増加し始めます。その値は減少しません。スロースタートからcwndの減少を伴わない別の状態への唯一の可能な移行は、輻輳ウィンドウサイズがssthreshに等しい場合に発生する輻輳回避への移行です。グラフを見ると、これはcwndが32のときに発生することがわかります。したがって、ssthreshが32MSSに初期化されていることがすぐにわかります。この本は276ページ(図3.53)に非常によく似たグラフを示しており、著者は同様の結論を出している。

enter image description here

通常の状態では、これが発生します-TCPがウィンドウのサイズを縮小せずに指数関数的成長から線形成長に初めて切り替わるとき、それは常にしきい値に達して切り替わったためです輻輳回避に。

最後に、MSSが少なくとも1460バイトであると仮定します(イーサネットはMTU = 1500バイトであり、TCP + IPヘッダーのサイズを考慮する必要があるため、通常は1460バイトです) cwndの単位はssthreshであり、cwndはバイトで表されるため、これはMSSssthreshを超える場合に確認することが重要です。

だからここに行きます:

T = 1

cwnd = 1 MSS; ssthresh = 32 kB

1セグメントを送信

T = 2

1つのセグメントが確認されました

cwnd + = 1; ssthresh = 32 kB

Cwndの新しい値:2

2つのセグメントを送信します

T =

2つのセグメントが承認されました

cwnd + = 2; ssthresh = 32 kB

Cwndの新しい値:4

4つのセグメントを送信します

T = 4

4つのセグメントが承認されました

cwnd + = 4; ssthresh = 32 kB

Cwndの新しい値:8

8セグメントを送信

T = 5

承認された8つのセグメント

cwnd + = 8; ssthresh = 32 kB

Cwndの新しい値:16

16セグメントを送信

T = 6

承認された16セグメント

cwnd + = 16; ssthresh = 32 kB

Cwndの新しい値:32

32セグメントを送信

さて、今何が起こるか見てみましょう。 cwndssthreshに達しました(32 * 1460 = 46720バイト、32000より大きい)。混雑回避に切り替える時が来ました。確認された各パケットが1 MSSでcwndの新しい値に寄与し、送信されたすべてのパケットが次のラウンドで確認されるため、cwndの値がラウンド間で指数関数的に増加することに注意してください。

輻輳回避への切り替え

これで、各cwndが1つのMSSに寄与しなくなるため、ACKは指数関数的に増加しなくなります。代わりに、各ACKMSS*(MSS/cwnd)で貢献します。したがって、たとえば、MSSが1460バイトで、cwndが14600バイトの場合(したがって、各ラウンドの開始時に10セグメントを送信します)、各ACK(セグメントごとに1つのACKを想定)はcwndを_1/10_ MSSずつ増やします。 (146バイト)。 10個のセグメントを送信し、ラウンドの終了時にすべてのセグメントが確認応答されたと想定するため、ラウンドの終了時にcwndを_10 * 1/10 = 1_増やしました。言い換えると、各セグメントはcwndにわずかな割合を与えるため、ラウンドごとにcwndを1MSSずつインクリメントします。そのため、各ラウンドは、転送/確認されたセグメントの数ではなく、cwndを1ずつインクリメントします。

何らかの損失が検出されるまで(3つの重複ACKまたはタイムアウトのいずれか)、輻輳回避を維持します。

さあ、時計を再開しましょう...

T = 7

32セグメントが承認されました

cwnd + = 1; ssthresh = 32 kB

Cwndの新しい値:33

33セグメントを送信

32個のセグメントが確認されたにもかかわらず、cwndが32から33にどのように変化したかに注意してください(したがって、各ACKは1/32に寄与します)。 T = 6のようにスロースタートの場合、_cwnd += 32_になります。このcwndの新しい値は、時刻T = 7でグラフに表示されるものとも一致します。

T = 8

33セグメントが承認されました

cwnd + = 1; ssthresh = 32 kB

Cwndの新しい値:34

34セグメントを送信

T = 9

34セグメントが承認されました

cwnd + = 1; ssthresh = 32 kB

Cwndの新しい値:35

35セグメントを送信

これはグラフと一致していることに注意してください。T= 9の場合、_cwnd = 35_になります。これはT = 16まで起こり続けます...

T = 1

35セグメントが承認されました

cwnd + = 1; ssthresh = 32 kB

Cwndの新しい値:36

36セグメントを送信

T = 11

36セグメントが承認されました

cwnd + = 1; ssthresh = 32 kB

Cwndの新しい値:37

37セグメントを送信

T = 12

37セグメントが承認されました

cwnd + = 1; ssthresh = 32 kB

Cwndの新しい値:38

38セグメントを送信

T = 1

承認された38セグメント

cwnd + = 1; ssthresh = 32 kB

Cwndの新しい値:39

39セグメントを送信

T = 14

39セグメントが承認されました

cwnd + = 1; ssthresh = 32 kB

Cwndの新しい値:40

40セグメントを送信

T = 15

40セグメントが承認されました

cwnd + = 1; ssthresh = 32 kB

Cwndの新しい値:41

41セグメントを送信

T = 16

承認された41セグメント

cwnd + = 1; ssthresh = 32 kB

Cwndの新しい値:42

42セグメントを送信

[〜#〜]一時停止[〜#〜]

今、何が起きた?グラフは、輻輳ウィンドウのサイズがそのサイズの約半分に減少し、その後、ラウンド全体で再び直線的に増加することを示しています。唯一の可能性は、3つの重複ACKがあり、プロトコルが高速リカバリに切り替わったことです。グラフは、[〜#〜] not [〜#〜]がスロースタートに切り替わらないことを示しています。これは、cwndが1に下がるためです。したがって、可能な遷移は高速にすることだけです。回復。

高速リカバリを入力すると、_ssthresh = cwnd/2_が得られます。 cwndの単位はMSSであり、ssthreshはバイト単位であることを覚えておいてください。したがって、新しい値は_ssthresh = cwnd*MSS/2 = 42*1460/2 = 30660_です。

繰り返しますが、これはグラフと一致しています。 ssthreshが30よりわずかに小さい場合、近い将来cwndがヒットすることに注意してください(MSS = 1460では、比率が正確に1:1ではないことを思い出してください。そのため、輻輳ウィンドウのサイズが30をわずかに下回っていても、しきい値に達します。 )。

輻輳回避への切り替えにより、cwndの新しい値も_ssthresh+3MSS = 21+3 = 24_になります(ssthreshの値はMSSでカウントされるため、ここではcwndを再度MSSに変換しました)。

現在、T = 17、_ssthresh = 30660 bytes_および_cwnd = 24_を使用して、輻輳を回避しています。

T = 18に入ると、2つのことが起こります。重複したACKを受け取るか、受け取らないかのどちらかです。そうしないと(つまり、新しいACKになります)、輻輳回避に移行します。しかし、これにより、cwndssthreshの値(21)に下がります。これはグラフと一致しません。グラフは、cwndが直線的に増加し続けることを示しています。また、cwndが1に低下するため、スロースタートに切り替わりません。これは、高速リカバリが残っておらず、ACKが重複していることを意味します。これは時間T = 22まで発生します。

T = 18

重複したACKが到着しました

cwnd + = 1; ssthresh = 30660バイト

Cwndの新しい値:25

T = 19

重複したACKが到着しました

cwnd + = 1; ssthresh = 30660バイト

Cwndの新しい値:26

T = 2

重複したACKが到着しました

cwnd + = 1; ssthresh = 30660バイト

Cwndの新しい値:27

T = 21

重複したACKが到着しました

cwnd + = 1; ssthresh = 30660バイト

Cwndの新しい値:28

T = 22

重複したACKが到着しました

cwnd + = 1; ssthresh = 30660バイト

Cwndの新しい値:29

**一時停止**

まだ高速リカバリ中ですが、突然cwndが1に下がりました。これは、再びスロースタートに入ったことを示しています。 ssthreshの新しい値は_29*1460/2 = 21170_、および_cwnd = 1_になります。また、セグメントを再送信するための努力にもかかわらず、タイムアウトが発生したことを意味します。

T = 2

cwnd = 1; ssthresh = 21170バイト

1セグメントを送信

T = 24

1つのセグメントが確認されました

cwnd + = 1; ssthresh = 21170バイト

Cwndの新しい値:2

2つのセグメントを送信します

T = 25

2つのセグメントが承認されました

cwnd + = 2; ssthresh = 21170バイト

Cwndの新しい値:4

4つのセグメントを送信します

T = 26

4つのセグメントが承認されました

cwnd + = 4; ssthresh = 21170バイト

Cwndの新しい値:8

8セグメントを送信

...

それが明らかになることを願っています。

14

TCP RenoFast Recoveryを含むTCPのバージョン)では、cwnd(輻輳ウィンドウ)グラフは次のようになります。

enter image description here

Slow StartCongestion Avoidanceの間の1つのRTT時間のみがFast Recoveryです。 「コンピュータネットワーク:トップダウンアプローチ」の本のグラフのように、T16の直線を使用して、Fast Recoveryプロセスを表します。 、次にT17cwnd21になります(21 + 3)MSSの代わりのMSS、なぜならFast RecoveryからCongestion Avoidanceに移行すると、cwndssthreshの値になります。したがって、本のグラフは間違っています。また、@ FilipeGonçalvesの答えも間違っています。

送信者と受信者のタイムライントレースの観点からの別のグラフがあります。これは、Fast Recoveryプロセスの理解にも役立つ場合があります。 another example of Fast Recovery

参照:

1 . http://www.ijcse.com/docs/INDJCSE17-08-03-113.pdf 2 . https://www.isi.edu/nsnam/DIRECTED_RESEARCH/ DR_WANIDA/DR/JavisInActionFastRecoveryFrame.html

0
toggler