TCP拥塞控制快速恢复

779 阅读3分钟

TCP的拥塞控制算法乍一看蛮简单的,最近复习的时候,却发现了两张相悖的图。暂时无法辨别。特此把资料记录一下,留待以后确认。

首先给出链接RFC-wiki:

Fast Retransmit/Fast Recovery

不想看英文的观众可以看看这个:

TCP 的那些事儿(下)

这是小林coding V3.0中给出的cwnd变化图: 快速重传.png

这是一张流传很广的图,也是我最初学习的版本。

快速恢复算法.png

这是RFC-wiki的快速恢复流程,详见上文链接。

  1. When the third duplicate ACK is received, set ssthresh to no more
   than the value given in equation 3.
  1. Retransmit the lost segment and set cwnd to ssthresh plus 3*SMSS.
   This artificially "inflates" the congestion window by the number
   of segments (three) that have left the network and which the
   receiver has buffered.
  1. For each additional duplicate ACK received, increment cwnd by
   SMSS.  This artificially inflates the congestion window in order
   to reflect the additional segment that has left the network.
  1. Transmit a segment, if allowed by the new value of cwnd and the
   receiver's advertised window.
  1. When the next ACK arrives that acknowledges new data, set cwnd to
   ssthresh (the value set in step 1).  This is termed "deflating"
   the window.

也就是说,在三次收到重复ACK后,开启快速重传。

  1. 重设了ssthresh和cwnd。

  2. cwnd确实先变为一半,紧接着加3(因为此时已经有3个包离开了网络到达了发送端)。

  3. 此时如果仍收到重复ACK,同理则cwnd持续加1。

    如果收到新的ACK,则表示重传成功,将cwnd设为ssthresh并进入拥塞控制阶段。

个人认为

一般来说,重传应该在一个RTT中成功,cwnd先变为一半,再加3,和加1之后。在下一个RTT时应变回原来的一半。

即,发生快速重传前为12,一个RTT的过程中,cwnd的变化为:

12 -> 6 -> 9 -> 若干 +1 ->6

也就是说,虽然Reno算法在重传过程中变化了不少,但是cwnd应当在下一个RRT时变为一半,并进入拥塞避免。即第二张图片正确。

如果超过一个RTT重传仍不成功,即未收到新的ACK,可能收到或多次收到重复的ACK。 由于RTO应略大于RTT,不再收到ACK必定触发超时重传和慢启动,不会出现图一的情况。 仍受到重复的ACK,此时不会退出快速恢复算法,cwnd窗口持续加1,不会进入拥塞避免,也就不会出现图一的情况。

更新

小林老师回复了我的问题,最新的版本已经更新在他的网站上。 所以上面的分析基本是吻合的,但是轮次的地方依然有点疑问,附上最新的图片和网址。

在我的理解中,TCP窗口中的所有包,应该在一个轮次中发出,这样可以保证窗口的持续前进。所以触发重传后,当收到新的确认前,窗口会被卡在未被确认的位置,发送窗口中相距最远的数据包也不该在3个轮次后才返回造成重复确认,所以快速恢复 cwnd 的 “+ 1 过程” 画成直线是不严谨的。所以图中,快速恢复阶段,每个轮次CWND增长1,我不是很认同,个人认为,快速回复在一个轮次中完成可能更加符合实际。也就是:

微信图片_20220512222000.jpg

网站链接 image.png