TCP/IP卷一:76---TCP超时与重传之(伪超时与重传(重复SACK(DSACK)、Eifel检测算法、迁移RTO恢复算法(F-RTO)、Eifel响应算法))
分类:
文章
•
2022-10-12 17:35:42
一、伪超时与重传概述
- 在很多情况下,即使没有出现数据丢失也可能引发重传。这种不必要的重传称为伪重传,其主要造成原因是伪超时,即过早判定超时,其他因素如包失序、包重复,或ACK丢失也可能导致该现象。在实际RTT显著增长,超过当前RTO时,可能出现伪超时。在下层协议性能变化较大的环境中(如无线环境),这种情况出现得比较多,[KP87]中也提到
- 这里我们仅关注由伪超时导致的伪重传。失序与重复的影响在下面的章节中再讨论
-
为处理伪超时问题提出了许多方法。这些方法通常包含检测算法与响应算法。检测算法用于判断某个超时或基于计时器的重传是否真实,一旦认定出现伪超时则执行响应算法,用于撤销或减轻该超时带来的影响。本章中我们只讨论报文段重传行为。典型的响应算法也涉及拥塞控制变化,会在后面“TCP拥塞控制”介绍
图示(回退“N”行为)
- 下图描述了一个简化的TCP交换过程
- 在报文段8发送完成后ACK链路上出现了延迟高峰导致了一次伪重传。在报文段5超时重传后,原始传输的报文段5 - 8的ACK仍然处于在传状态
- 本图中为简便起见,***和ACK号都基于包而非字节来表示,并且ACK号表示已接收到的包,而非期望接收的下一个包。当这些ACK到达时,发送端继续重传早已接收的其他报文段,从已确认的报文段之后开始。这导致TCP出现了“回退N”的行为模式,并产生了更多的“重复ACK”返回发送端,这时就可能会触发快速重传。 针对这一问题,提出了一些方法来减轻不良影响。下面我们讨论其中比较常用的几种方法
![TCP/IP卷一:76---TCP超时与重传之(伪超时与重传(重复SACK(DSACK)、Eifel检测算法、迁移RTO恢复算法(F-RTO)、Eifel响应算法)) TCP/IP卷一:76---TCP超时与重传之(伪超时与重传(重复SACK(DSACK)、Eifel检测算法、迁移RTO恢复算法(F-RTO)、Eifel响应算法))](/default/index/img?u=aHR0cHM6Ly9waWFuc2hlbi5jb20vaW1hZ2VzLzE4Mi8zNGI3MTljMDUyZjZhNzNhZjM2NGJjMmQ5MzhmOWQzNi5wbmc=)
二、重复SACK(DSACK)扩展
- 在非SACK的TCP中,ACK只能向发送端告知最大的有序报文段。采用SACK则可告知其他的(失序)报文段。基本的SACK机制对接收端收到重复数据段时怎样运作没有规定。 这些重复数据可能是伪重传、网络中的重复或其他原因造成的
DSACK发送端
- 在SACK接收端采用DSACK(或称作D-SACK),即重复SACK[RFC2883],并结合通常的SACK发送端,可在第一个SACK块中告知接收端收到的重复报文段***
- DSACK的主要目的是判断何时的重传是不必要的,并了解网络中的其他事项。因此发送端至少可以推断是否发生了包失序、 ACK丢失、包重复或伪重传
- DSACK相比于传统SACK并不需要额外的协商过程。为使其正常工作,接收端返回的SACK的内容会有所改变,对应的发送端的响应也会随之变化。如果一个非DSACK与DSACK的TCP共用一个连接,它们会交互操作,但非DSACK不能使用DSACK的功能
DSACK接收端
- SACK接收端的变化在于,允许包含***小于(或等于)累积ACK号字段的SACK块。这并非SACK的本意,但这样做能很好地配合该目的。 (在DSACK信息高于累积ACK号字段的情况下,即出现重复的失序报文段时,它也能很好地工作)DSACK信息只包含在单个ACK中,该ACK称为DSACK
- 与通常的SACK信息不同,DSACK信息不会在多个SACK中重复。因此,DSACK较通常的SACK鲁棒性低
- [RFC2883]没有具体规定发送端对DSACK怎样处理。 [RFC3708]给出了一种实验算法,利用DSACK来检测伪重传,但它并没有提供响应算法。它提到可采用Eifel响应算法,我们下面讨论,在此之前我们先介绍一些其他的检测算在法
三、Eifel检测算法
-
概念:
- 在前面,我们讨论了重传二义性问题。实验性的Eifel检测算法[RFC3522]利用了TCP的TSOPT来检测伪重传
- 在发生超时重传后,Eifel算法等待接收下一个ACK,若为针对第一次传输(即原始传输)的确认,则判定该重传是伪重传
-
与DSACK的比较:
- 利用Eifel检测算法能比仅采用DSACK更早检测到伪重传行为,因为它判断伪重传的ACK是在启动丢失恢复之前生成的
- 相反,DSACK只有在重复报文段到达接收端后才能发送,并且在DSACK返回至发送端后才能有所响应
-
及早检测伪重传更为有利,它能使发送端有效避免前面提到的“回退N”行为
Eifel检测算法原理
- Eifel检测算法的机制很简单。它需要使用TCP的TSOPT
-
发送端:当发送一个重传(不论是基于计时器的重传还是快速重传)后,保存其TSV值
-
接收端:当接收到相应分组的ACK后,检查该ACK的TSER部分。若TSER值小于之前存储的TSV值,则可判定该ACK对应的是原始传输分组,即该重传是伪重传
- 这种方法针对ACK丢失也有很好的鲁棒性。如果一个ACK丢失,后续ACK的TSER值仍比存储的重传分组的TSV小。该窗口内的任一ACK的到达都能判断是否出现伪重传,因此单个ACK的丢失不会造成太大问题
- Eifel检测算法可与DSACK结合使用,这样可以解决整个窗口的ACK信息均丢失,但原始传输和重传分组都成功到达接收端的情况。在这种特殊情况下,重传分组的到达会生成一个DSACK。Eifel算法会理所当然地认定出现了伪重传。然而,在出现了如此之多的ACK 丢失的情况下,使得TCP相信该重传不是伪重传是有用的(例如,使其减慢发送速率——采用拥塞控制的后果)。因此,DSACK的到达会使得Eifel算法认定相应的重传不是伪重传
四、迁移RTO恢复算法(F-RTO)
- 前移RTO恢复(Forward-RTO Recovery,F-RTO)[RFC5682]是检测伪重传的标准算法。它不需要任何TCP选项,因此只要在发送端实现该方法后,即使针对不支持TSOPT的接收端也能有效地工作。该算法只检测由重传计时器超时引发的伪重传;对之前提到的其他原因引起的伪重传则无法判断
- 在一次基于计时器的重传之后,F-RTO会对TCP的常用行为做出一定修改。由于这类重传针对的是没有收到ACK信息的最小***,通常情况下,TCP会继续按序发送相邻的分组,这就是前面描述的“回退N”行为
工作原理
- F-RTO会修改TCP的行为,在超时重传后收到第一个ACK时,TCP会发送新(非重传)数据,之后再响应后一个到达的ACK
- 如果其中有一个为重复ACK,则认为此次重传没问题
- 如果这两个都不是重复ACK,则表示该重传是伪重传
-
重复ACK是在接收端收到失序的报文段产生的。这种方法比较直观。如果新数据的传输得到了相应的ACK,就使得接收端窗口前移。如果新数据的发送导致了重复ACK,那么接收端至少有一个或更多的空缺。这两种情况下,接收新数据都不会影响整体数据的传输性能(假设接收端有足够的存储空间)
五、Eifel响应算法
- 一旦判断出现伪重传,则会引发一套标准操作,即Eifel响应算法[RFC4015]。由于响应算法逻辑上与Eifel检测算法分离,所以它可与我们前面讨论的任一种检测方法结合使用。原则上超时重传和快速重传都可使用Eifel响应算法,但目前只针对超时重传做了相关规定
- 尽管Eifel响应算法可结合其他检测算法使用,但根据是否能尽早(如Eifel检测算法或F-RTO)或较迟(如DSACK)检测出伪超时的不同而有所区别。前者称为伪超时,通过检查ACK或原始传输来实现。后者称为迟伪超时,基于由(伪)超时而引 发的重传所返回的ACK来判定
- 响应算法只针对第一种重传事件。若在恢复阶段完成之前再次发生超时,则不会执行响应算法。在重传计时器超时后,它会查看srtt和rttvar的值,并按如下方式记录新的变量sett_prev和rttvar_prev:
![TCP/IP卷一:76---TCP超时与重传之(伪超时与重传(重复SACK(DSACK)、Eifel检测算法、迁移RTO恢复算法(F-RTO)、Eifel响应算法)) TCP/IP卷一:76---TCP超时与重传之(伪超时与重传(重复SACK(DSACK)、Eifel检测算法、迁移RTO恢复算法(F-RTO)、Eifel响应算法))](/default/index/img?u=aHR0cHM6Ly9waWFuc2hlbi5jb20vaW1hZ2VzLzQ3MC8yYTA5N2FlNTM3MWU4ODFmYzhlYTI2YTdlYzhiYTkyNi5wbmc=)
- 在任何一次计时器超时后,都会指定这两个变量,但只有在判定出现伪超时才会使用它们,用于设定新的RTO。在上式中,G代表TCP时钟粒度。srtt_prev设为srtt加上两倍的时钟粒度是由于:srtt的值过小,可能会出现伪超时。如果srtt稍大,就可能不会发生超时。srtt加上2G得到srtt_prev,之后都使用srtt_prev来设置RTO
- 完成srtt_prev和rttvar_prev的存储后,就要触发某种检测算法。运行检测算法后可得到一个特殊的值,称为伪恢复。如果检测到一次伪超时,则将伪恢复置为SPUR_TO。如果检测到迟伪超时,则将其置为LATE_SPUILTO。否则,该次超时为正常超时,TCP继续执行正常的响应行为
- 若伪恢复为SPUR_TO,TCP可在恢复阶段完成之前进行操作。通过将下一个要发送报文段(称为SND.NXT)的***修改为最新的未发送过的报文段(称为SND.MAX)。这就可在首次重传后避免不必要的“回退N”行为。如果检测到一次迟伪超时,此时已生成对首次重传的ACK,则SND.NXT不改变。在以上两种情况中,都要重新设置拥塞控制状态。并且一旦接收到重传计时器超时后发送的报文段的ACK,就要接如下方式更新srtt、 rttvar和RTO的值:
![TCP/IP卷一:76---TCP超时与重传之(伪超时与重传(重复SACK(DSACK)、Eifel检测算法、迁移RTO恢复算法(F-RTO)、Eifel响应算法)) TCP/IP卷一:76---TCP超时与重传之(伪超时与重传(重复SACK(DSACK)、Eifel检测算法、迁移RTO恢复算法(F-RTO)、Eifel响应算法))](/default/index/img?u=aHR0cHM6Ly9waWFuc2hlbi5jb20vaW1hZ2VzLzI2NC9iMmY4NTQ0YzFjZGM1YTEwYTdhMzA2ZWYyMDEwYjgyMC5wbmc=)
- 这里,m是一个RTT样本值,它是基于超时后首个发送数据收到的ACK而计算得到的。进行这些变量更新的目的在于,实际的RTT值可能发生了很大变化,RTT的当前估计值已经不适合用于设置RTO。若路径上的实际RTT突然增大(例如由于无线切换至一个新的基 站),当前的srtt和rttvar就显得过小,应重新设置。而另一方面,RTT的增大可能只是暂时的,这时重设srtt和rttvar的值就不那么明智了,因为它们原先的值可能更为精确
- 在新RTT样本值较大的情况下,上述等式尽力获得上述两种情况的平衡。这样做可以有效地抛弃之前的RTT历史值(和RTT的历史变化情况)。只有在响应算法中srtt和rttvar的值才会增大。若RTT不会增大,则维持估计值不变,这本质上是忽略超时情况的发生。 两种情况中,RTO还是按正常方式进行更新,并针对此次超时设置新的重传计时器值