TCP的FRTO理解
本文主要描述内核4.9.4中的TCP丢包处理与frto相关的操作,主要覆盖使用sack的场景。
0. 参考文档
[1] RFC-5682
[2] linuxtcp.ps
[3] frto.pdf
1. FRTO要解决的问题
FRTO主要是用来处理在DSACK生效时,突发的延迟触发RTO超时后,不必要的延迟和重传报文的ack造成了DSACK而产生非必要的快速重传[1]。
传统的基于DSACK的RTO超时会有如下问题:
- 1) 在16.5s和17s中间最后一个ack到来之前一直处于慢启动阶段,指数发送数据,
- 2) 18s虚假RTO触发,其实只是延迟,但是这时候RTO工作,重传丢失的报文。
- 3) 19s的时候延迟包的ack到达,注意到此时ack的数据序列号是大于重传报文的序列号。
- 4) 延迟的ack使发送端继续重传之后延迟的ack之后的数据(这部分数据之前已经发送过))(19s到19.5s之间的重传)。
- 5) 在19.8s,之前发送的最大序列号报文被确认,接着由于4中的重传报文陆续到达,接收端发送了一系列以最大序列号报文为ack的Duplicate SACK。
- 6) 发送端收到这些重复的DSACK后,触发了快速重传,降低了传输性能。
使用FRTO后的效果:
- 1) 同上
- 2) 同上
- 3) 同上
- 4) 由于延迟包的ack更新了snd_una,因此这里不重传其余数据,而是发送两个新的分片。
- 5) 延迟包的ack陆续到达,此时由于未重传的包收到了对应的ack,因此可以判断当前是一个虚假的RTO,继续发送新的数据。
1. FRTO rfc解释
这里主要针对sack的场景,即rfc-5682的section 3。
|
|
注1: RecoveryPoint为tcp中的high_seq,后称恢复点。
注2: snd_nxt为下一个将要发送的包的包号。
- 3.1: 当重传定时器超时了,首先重传第一个未确认的分片,同时设置SpuriousRecovery为false,并重置sack的计分板。
如果恢复点大于等于下一个要发的包(好像基本不可能,最多等于),则将恢复点设置为当前发送的最大包。进入常规恢复。否则进入step 2。 - 3.2: 等待重传数据的ack到来。如果重复的ack比新的ack更早到达,则更新相应的sack计分板,同时留在第二步,等待新的ack到来。如果重传定时器再次超时,回到第一步。当新的ack到来后,更新恢复点。
- a) 如果到来的ack中包括了恢复点,但不超过恢复点,撤销至普通恢复,同时拥塞窗口设置不大于2倍MSS。不进入第三步。
- b) 如果到来的ack中不包含恢复点,但是收到的包超过未确认包,发送两个新的分片,并进入步骤3。如果当前发送端无法发送新报文(接收窗口限制或者没有新的应用层数据),这里建议不要进入步骤3,而是使用恢复步骤。
-3.3: 下一个ack到来,除了新的ack或者是重复ack,其他ack在这个步骤中都被忽略。 - a) 如果新的ack包含了恢复点,则设置拥塞窗口不超过3倍MSS大小并执行恢复操作,重传未确认分片。这个分支也处理重复ack但是没有确认任何新块的场景。
- b) 如果新的ack或者sack信息中没有包含恢复点,且确认的数据是之前没有确认的,则认为这个超时是一个奇怪的超时,并设置SpuriousRecovery为SPUR_TO。这个重传被标记为奇怪的,因为这个分片在超时前被确认了。
其实论文中的图比rfc这段(恢复点的几个判断理解费力。。)更好理解,也更契合代码,为了识别出虚假的RTO:
- 超时后先只重发丢失的一个包(3.1)。
- 判断重传后的第一个新的ack是否更新了snd_una,如果更新了snd_una,就发送新的数据,在判断虚假RTO之前不重传数据(3.2.b)
- 如果没重传就已经收到数据,尝试撤销本次RTO,如果撤销成功,这就是一个虚假RTO,进入恢复流程(3.3.b)。如果还是重复ack,则认为这是一个丢包事件(3.3.a)。
2. 4.9.4中的代码
这里主要分析tcp_process_loss函数。
|
|
3. 简单流程图
3.1 常规frto流程
- 1) RTO超时,发送新分片
- 2) 收到一个ack,进入tcp_process_loss处理,此时frto开启,如果延迟的ack更新了una,则直接恢复loss状态。如果刚好等于重传包,这时候先发送新分片。
- 3) 又一个新的ack到来,这时候由于没有重传包,延迟的ack会更新una,直接撤销丢包处理,离开LOSS状态。
3.2 frto恢复失败流程
- 1) RTO超时,发送新分片
- 2) 收到一个ack,进入tcp_process_loss处理,此时frto开启,如上发送新分片。
- 3) 又一个新的ack到来,这时候由于丢包,不更新对应的una,因此关闭frto,进入重传流程。