Inside TCP: Spurious RTO 问题

2130阅读 0评论2015-04-09 platinum
分类:LINUX

针对于未确认的数据TCP使用重传机制。重传的超时时长基于在这个TCP连接上观察到的RTT时间。在大多数情况下,发生超时就意味着包丢失了,这会启动TCP的丢失恢复过程:开始慢启动,拥塞窗口设为0。但RTT的突然波动(拥塞、handoff)并不一定意味着包丢失了, Forward RTO-recovery 就是一种隔离Spurious RTO 负面影响的机制。 

Forward RTO Recovery (F-RTO)

F-RTO的基本思路是判断RTO是否正常,从而决定是否需要触发丢失恢复过程。方法是观察RTO之后的两个ACK。如果ACK不是重复ACK,并且确认的包不是重传的,会认为RTOSpurious的。F-RTO可以只在TCP的发送端实现,不需要对端TCP协议栈的任何参与。


能否使用F-RTO算法 ()

RTO后能否使用F-RTO:

  1. sysctl 变量 sysctl_tcp_frto 激活F-RTO

  2. F-RTO 只能在发生RTO之后,有新数据可以发送时。因此需要检查有新数据,并且可以发送 (处在发送窗口之内)

  3. 如果满足以上两个条件,初始化F-RTO


初始化F-RTO ()
  1. 如果连接正在丢包状态中恢复,减半snd_ssthresh,但不能小于2

  2. 初始化跟踪F-RTO状态的相关变量:

  3. 重传包的计数器 retrans_out 复位为0.

  4. 做标记:将进入F-RTO时最新确认的字节序号(snd_una),保存于 undo_marker

  5. 复位在“undo_marker标记”之后重传的计数器:undo_retrans

  6. 所有在队列中没有确认的数据包,都标识为没有重传过。

  7. 设置拥塞避免状态ca_stateTCP_CA_OPEN

  8. 做标记:将frto_highmark设置为,进入F-RTO后要发送的新segment的起始字节序号(发送窗口左边沿,snd_nxt

  9. RTO后,得到处理的ACK数量 frto_counter ,设为1


RTO之后重传数据 ( tcp_retransmit_skb ) 

在进入FRTO之后处理ACK ()

在进入F-RTO之后,使用接收到的ACK,按以下方法判断RTO合理与否:

  1. 进入F-RTO并且重传RTO的数据之后,接收到的ACK可能是:

  2. 重复ACK:接收到重复ACK说明包确实丢失了。

  3. 不是重复ACK,但确认了直到(或者其后) frto_highmark 的数据。这说明重传的数据很可能是填充了“空隙”,即其后数据包已经接收到了。也就是说,第一次发送的数据(被重传)确实是丢失了。

(以下两段原文似有笔误,我纠正过来了)

在认为RTOspurious的情况下,如果第一个ACK并没有指明重传确实是需要的,就再允许再发送两个未发送的数据包出去。注意,正常的恢复方法也会如此处理,因此即使之后到达的ACK指明确实是丢失了数据包,我们也能按正常的恢复方法继续处理。此时,frto_counter加一。在第二个ACK时,也作类似的检查。

如果确实丢失了数据,就说明发生了阻塞,进入拥塞避免状态。在处理完第二个ACK之后,frto_counter被复位为0,这意味着之后的ACK不再由F-RTO算法处理了


使用F-RTO进入丢失状态 () 

确实发生RTO时:
  1. 如果没有相应的SACK记录,就把 frto_highmark 之前数据包标记为丢失。

  2. 根据RTO之后接收后的ACK数量,设置拥塞窗口为2或者3:这与通常丢失恢复算法的行为符合。

  3. ca_state设置为 TCP_CA_Loss


原文地址:

维护: 

翻译: raise.sail@gmail.com



上一篇:Inside TCP:TCP确认机制
下一篇:Inside TCP:显式拥塞控制