19

我一直在阅读《计算机网络:一种自顶向下的方法》一书,遇到了一个我似乎不明白的问题。

正如我所读到的,TCP 拥塞控制具有三种状态:慢启动、拥塞避免和快速恢复。我很了解慢启动和拥塞避免,但快速恢复非常模糊。这本书声称 TCP 的行为方式是这样的:(cwnd=拥塞窗口) 在此处输入图像描述
让我们看下图: 传输轮-拥塞窗口大小图

正如我们所看到的,在第 16 轮,发送方发送了 42 个段,并且由于拥塞窗口大小已减半(+3),我们可以推断出有 3 个 Duplicate-ACK。这个问题的答案声称 第 16 到 22 轮之间的轮次处于拥塞避免状态。但为什么不快速恢复?我的意思是,在三个重复的 ACK 之后,TCP 进入快速恢复并且每隔一个重复的 ACK 应该会增加拥塞窗口。为什么图表没有表示这一点?我能想到的唯一合理的解释是,在这张图中,只有三个重复的 ACK,并且此后收到的 ACK 都不是重复的。

即使是这样,如果有超过 3 个重复的 ACK,图表会是什么样子?**

上图中是否有快速恢复的表示?为什么不/是?

** 很长一段时间以来,我一直在努力回答这个问题。我会很高兴得到任何答复,谢谢!

更新这里的图像。我认为一轮定义为当窗口中的所有段都被确认时。在照片中,圆形显示为圆形。 在此处输入图像描述 为什么 cwnd 在 Fast Recovery 状态下会呈指数增长?(在我不小心写成权宜之计而不是指数级的图像中)

4

2 回答 2

18

更新:我原来的答案同意解决方案,但经过仔细考虑,我认为解决方案是错误的。这个答案是从头开始重写的;请仔细阅读。我展示了为什么在时间 T=16 进入快速恢复以及为什么协议一直保留到 T=22。图表中的数据支持我的理论,所以我非常肯定解决方案是完全错误的。

让我们先明确一点:慢启动呈指数增长;拥塞避免线性增长,快速恢复线性增长,即使它使用与慢启动相同的公式来更新 的值cwnd

请允许我澄清一下。

为什么我们说慢启动cwnd呈指数增长?

请注意,接收到的每个 ACKcwnd​​ 都会增加MSS字节数。

让我们看一个例子。假设cwnd初始化为 1 个 MSS(MSS 的值通常为 1460 字节,因此在实践中这意味着cwnd初始化为 1460)。此时,由于拥塞窗口大小只能容纳 1 个数据包,因此 TCP 将不会发送新数据,直到该数据包被确认。假设 ACK 没有丢失,这意味着大约每 RTT 秒传输一个新数据包(回想一下 RTT 是往返时间),因为我们需要 (1/2)*RTT 来发送数据包,并且 ( 1/2)*RTT 用于 ACK 到达。

因此,这导致发送速率大致为 MSS/RTT bps。现在,请记住,对于每个ACKcwnd都会增加MSS。因此,一旦第一个ACK到达,cwnd就变成2*MSS,所以现在我们可以发送 2 个数据包。当这两个数据包被确认时,我们增加cwnd 两次,所以现在cwnd4*MSS。伟大的!我们可以发送 4 个数据包。这 4 个数据包被确认,所以我们要增加cwnd4 倍!所以我们有cwnd = 8*MSS. 然后我们得到cwnd = 16*MSS. 我们基本上cwnd每 RTT 秒翻一番(这也解释了为什么cwnd = cwnd+MSS*(MSS/cwnd)在拥塞避免中导致线性增长)

是的,这很棘手,这个公式cwnd = cwnd+MSS很容易让我们相信它是线性的——这是一个常见的误解,因为人们经常忘记它适用于每个确认的数据包。

请注意,在现实世界中,传输 4 个数据包不一定会产生 4 个 ACK​​。它可能只生成 1 个ACK,但由于 TCP 使用累积 ACK,因此该单个ACK仍然确认 4 个数据包。

为什么快速恢复是线性的?

cwnd = cwnd+MSS公式适用于慢启动和拥塞避免。人们会认为这会导致两种状态都引发指数增长。但是,快速恢复在不同的上下文中应用该公式:接收到重复的 ACK 时。区别就在这里:在慢启动中,一个 RTT 确认了一大堆段,并且每个确认的段为 的新值贡献了 +1MSS cwnd,而在快速恢复中,重复的 ACK 浪费了一个 RTT 来确认丢失了一个单个段,因此我们不是在cwnd每个 RTT 秒内更新 N 次(其中 N 是传输的段数),而是为丢失的段更新cwnd 一次。所以我们只用一个段“浪费”了一次往返,所以我们只增加cwnd1。

关于拥塞避免——我将在下面分析图表时解释这一点。

分析图表

好的,让我们逐轮看看该图中发生了什么。你的照片在某种程度上是正确的。让我先澄清一些事情:

  1. 当我们说慢启动和快速恢复呈指数增长时,这意味着它逐轮呈指数增长,正如您在图片中显示的那样。所以,这是正确的。您正确识别了带有蓝色圆圈的圆形:注意 1、2、4、8、16 cwnd、...
  2. 你的图片好像是说Slow Start后,协议进入Fast Recovery。这不是发生的事情。如果它从慢启动进入快速恢复,我们会看到cwnd减半。这不是图表所显示的:cwnd从 T=6 到 T=7 的值不会减少到一半。

好的,现在让我们看看每一轮到底发生了什么。请注意,图中的时间单位是一轮。因此,如果在时间 T=X 我们传输 N 个段,那么假设在时间 T=X+1 这 N 个段已被确认(当然,假设它们没有丢失)。

还要注意我们如何ssthresh仅通过查看图表来判断 的值。在 T=6 时,cwnd停止指数增长并开始线性增长,并且其值不会减少。从慢启动到另一个不涉及减少cwnd的状态的唯一可能转换是到拥塞避免的转换,这发生在拥塞窗口大小等于 时ssthresh。我们可以在图中看到,这发生在cwnd32 时。因此,我们立即知道它ssthresh被初始化为 32 MSS。这本书在第 276 页显示了一个非常相似的图表(图 3.53),其中作者得出了类似的结论:

在此处输入图像描述

在正常情况下,会发生这种情况——当 TCP 第一次从指数增长切换到线性增长而不减小窗口大小时,总是因为它达到阈值并切换到拥塞避免。

最后,假设它MSS至少是 1460 字节(通常是 1460 字节,因为以太网的 MTU = 1500 字节,我们需要考虑 TCP + IP 标头的大小,它们总共需要 40 字节)。这对于查看何时cwnd超过很重要ssthresh,因为cwnd' 的单位是MSS并且ssthresh以字节表示。

所以我们开始:

T = 1

cwnd = 1 MSS;ssthresh = 32 kB

传输 1 段

T = 2

1 个段已确认

cwnd += 1; ssthresh = 32 kB

cwnd 的新值:2

传输 2 段

T = 3

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 段

好的,让我们看看现在会发生什么。cwnd达到ssthresh(32*1460 = 46720 字节,大于 32000)。是时候切换到拥塞避免了。注意 的值是如何cwnd在轮次中呈指数增长的,因为每个确认的数据包都会为 的新值贡献 1 个 MSS cwnd,并且每个发送的数据包都会在下一轮得到确认。

切换到拥塞避免

现在,cwnd不会以指数方式增加,因为每个ACK人都不会再贡献 1 个 MSS。相反,每个人都有ACK贡献MSS*(MSS/cwnd)。因此,例如,如果MSS是 1460 字节并且cwnd是 14600 字节(所以在每一轮开始时我们发送 10 个段),那么每个ACK(假设ACK每个段一个)将增加cwndMSS 1/10(146 字节)。由于我们发送了 10 个段,并且在一轮结束时我们假设每个段都被确认,那么在一轮结束时我们增加cwnd10 * 1/10 = 1. 换句话说,每个段只贡献一小部分,cwnd因此我们cwnd每轮只增加 1 个 MSS。所以现在每一轮都会递增cwnd1 而不是传输/确认的段数。

我们将保持拥塞避免,直到检测到一些丢失(3 个重复的 ACK 或超时)。

现在,让时钟恢复...

T = 7

已确认 32 段

cwnd += 1; ssthresh = 32 kB

cwnd 的新值:33

传输 33 段

请注意cwnd即使确认了 32 个段(ACK因此每个段贡献 1/32),从 32 到 33 是​​如何变化的。如果我们处于慢启动状态,例如 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 = 10

已确认 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 = 13

已确认 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 并且协议切换到快速恢复。该图显示它不会切换到慢启动,因为这会cwnd降低到 1。所以唯一可能的转换是快速恢复。

通过进入快速恢复,我们得到ssthresh = cwnd/2. 请记住,cwnd的单位是字节MSSssthresh我们必须小心。因此,新值为ssthresh = cwnd*MSS/2 = 42*1460/2 = 30660

同样,这与图表一致;请注意,ssthresh当 略小于 30 时,将在不久的将来被击中cwnd(回想一下,当 MSS = 1460 时,该比率不完全是 1:1,这就是为什么即使拥塞窗口大小略低于 30,我们也达到了阈值)。

切换到拥塞避免也会导致新的值cwndssthresh+3MSS = 21+3 = 24(记住要小心单位,这里我ssthresh再次转换为MSS,因为我们的值cwnd计入MSS)。

截至目前,我们处于拥塞避免状态,T=17,ssthresh = 30660 bytes并且cwnd = 24

输入 T=18 后,可能会发生两件事:要么我们收到重复的 ACK,要么没有。如果我们不这样做(所以这是一个新的 ACK),我们将过渡到拥塞避免。但这会cwnd降低 的值ssthresh,即 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 = 20

重复的 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

** 暂停 **

我们还在Fast recovery,现在突然cwnd下降到1,说明又进入了slow start。的新值ssthresh将是29*1460/2 = 21170cwnd = 1。这也意味着尽管我们努力重新传输该段,但还是出现了超时。

T = 23

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段

...

我希望这能说清楚。

于 2015-06-13T18:36:43.393 回答
2

TCP Reno(涉及的 TCP 版本Fast Recovery)中,cwnd(拥塞窗口)图应如下所示:

在此处输入图像描述

Slow StartCongestion Avoidance之间只有一个 RTT 时间Fast Recovery如果像《Computer Networking: A Top Down Approach》一书中的图,只用T16中的一条直线来表示Fast Recovery过程,那么T17cwnd中的应该是21 MSS 而不是(21+3) MSS,因为当它从到,将值降到。所以书中的图表是错误的。而且,@Filipe Gonçalves的回答也是错误的。Fast RecoveryCongestion Avoidancecwndssthresh

从发送者和接收者的时间线轨迹的角度来看,还有另一个图表,它也可以帮助你理解这个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

于 2020-03-29T12:25:05.320 回答