一、虚假重传

在一些情况下,TCP可能会在没有数据丢失的情况下初始化一个重传,这种重传就叫做虚假重传(Spurious retransmission)。发生虚假重传的原因可能是包传输中重排序、传输中发生包复制、ACK确认包传输中丢失等等。如果由于链路时延变化或者负载变化等因素导致RTT突然变大等原因,TCP的发送端可能还没收到ACK确认包就已经RTO超时而触发重传,这种重传就叫做虚假超时重传(Spurious retransmission timeouts)。虚假超时重传会降低网络性能,其主要由两方面的影响,一个是会导致重传已经发出的但是还没有收到ACK确认的数据,而这部分数据包的ACK报文可能只是延迟到达而已,因此对应的重传是不必要的,另一方面是虚假超时后进入慢启动阶段,每当收到一个ACK确认包的时候可以发出两个数据包,而原来初传的数据包实际上并没有丢失,因此增加了网络负载,违背了包守恒原则。慢启动和包守恒等内容在后续拥塞控制进行介绍。因此有必要进行检测处理。对于虚假超时有几种方法来处理,一般处理方法都是分为两部分一个分是探测(detection)算法,另外一部分是响应(response)算法。当探测算法探测到一个虚假超时后,再调用响应算法撤销之前RTO超时的影响。当前探测算法有FRTO、DSACK、Eifel探测算法等,我们这里主要介绍FRTO和DSACK,以对虚假重传的探测有一定的简单认识。Eifel探测算法则留到后面拥塞控制的时候进行介绍。响应算法一般主要有两部分操作,一个是修正RTO值,第二个是撤销拥塞控制的处理。linux中主要是撤销拥塞控制并不会去修正RTO。拥塞控制相关内容我们后面内容在进行介绍。

二、FRTO简介及linux实现介绍

其中FRTO(Forward RTO-Recovery ,也简称为F-RTO)就是一种发送端的无效RTO超时重传检测方法。在RTO超时重传了第一个数据包之后,FRTO会检测之后收到的ACK报文来判断刚刚的超时重传是否是虚假重传(即对端实际上已经接收到了对应的TCP报文,但是发送端仍然RTO超时进行了重传),然后根据判断结果来决定接下来是接着进行重传还是发送新的未发送数据。在传输链路RTT抖动比较大的场景下(例如无线网络),FRTO可以有效的避免减少后续的虚假重传从而提升TCP性能。相比于Eifel、DSACK探测算法,FRTO不需要任何额外的TCP选项支持,而且不需要修改接收端实现。协议中给出了两种算法一种是基础的FRTO算法,一种是SACK增强的FRTO算法,linux的FRTO代码重构后只实现了SACK增强的FRTO算法(增强算法也可以用于普通场景),当/proc/sys/net/ipv4/tcp_frto设置为非0值的时候表示打开FRTO算法。

我们简单介绍一下linux中FRTO的实现,想深入了解的话请参考RFC5682和linux中的相关代码。这里涉及到大量拥塞控制的相关状态(Open、Disorder、Recovery、Loss等等)可以看完拥塞控制再来看这块。然后我们通过wireshark示例来进一步理解FRTO

先介绍一个概念

RecoveryPoint:在进行RTO超时重传的时候,当前已发送的数据中的最高系列号,例如发送端发出P1(0-9)、P2(10-19)、P3(20-29)三个TCP报文后如果P1超时重传,那么此时RecoveryPoint就是29,实际linux内部使用high_seq状态变量维护记录的是(RecoveryPoint+1),也就是记录的30。

1、在RTO超时的时候,TCP发送端进入Loss状态,判断是否启动FRTO过程,如果tcp_frto开启,当前不是PMTU过程,且不是进入Loss状态前不是Loss状态或者Recovery状态,那么对这次RTO超时开启FRTO检验。接着发送RTO超时重传报文。

2、如果上一步判断对当前RTO超时启动了FRTO过程,那么对于收到的ACK,判断是否带有SACK信息,并且SACK确认了RecoveryPoint之前的数据且SACK确认的数据是没有在第一步重传的数据。那么认为RTO重传是虚假重传,通过两个操作尝试撤销Loss状态的部分影响,一个是尝试更改拥塞窗口cwnd,另外一个是标识先前的数据包为非丢失状态,重传完,进入Open状态,并退出FRTO过程,不在执行下面的其他步骤。因为先前的数据包标记为非lost状态了,接下来回到正常流程就会发送新的数据包。

3、如果上一步判断中没有认定虚假重传,那么如果这个ACK确认包确认的数据超过RecoveryPoint,那么退回到普通的重传恢复状态,不再执行下面的步骤。

4、如果收到的ACK确认包是RTO后的第一个ACK确认包,且ack number确认了新数据,那么把RecoveryPoint更新为当前发送的最高系列号并尝试发送新的未发送数据。如果没有新数据发送,则退出FRTO过程,执行普通的RTO超时重传处理,不在执行接下来的过程。

5、如果收到了第二个ACK确认包,如果这个确认包SACK了新的数据或者是dup ACK那么认为是真实重传,退出FRTO过程执行普通的RTO超时重传流程。

三、wireshark示例

1、设置tcp_frto=2,返回SACK确认部分未重传的数据

  • 首先通过一个RTO超时重传(No7和No8)来缩减拥塞窗口,这样server端在收到No9反馈包的时候就只能发出两个数据包了,接着server端写入500bytes的数据,server发出两个数据包No10和No11(设置了MSS为62,减掉12bytp的TSOPT选项后,每个数据包大小最大为50bytes了)

  • client对No9回复一个ACK确认包,server端再次发出两个数据包(No13和No14)

  • No13数据包RTO超时后进行重传,对应No15数据包,此时判断满足启动FRTO的条件

  • client回复No16数据包Ack=109确认了No11数据包,同时通过SACK选项告诉server端client收到了No14报文

  • server端收到No16确认包后发现当前FRTO为启动状态,并且ACK报文满足上面FRTO流程中的第2步,即SACK确认了RecoveryPoint之前的数据且SACK确认的数据是没有在第一步重传的数据,因此认定这个RTO是虚假重传,尝试撤销Loss状态的部分影响,进入open状态(实际上进入open状态后又发现满足了进入Disorder的条件,因此最终实际上进入了Disorder状态),此时FRTO流程结束。

  • 因为上一步已经对No13报文取消了lost标记,因此进入Disorder状态后并不会重传No13而是传输了新的未发送数据即No17报文,接着client回复ACK确认,整个传输过程结束

2、设置tcp_frto=0,返回SACK确认部分未重传的数据

我们重复上面的业务模型,但是这次选择关闭FRTO,如下图所示No1到No14包的流程与前面相同,不同点如下

  • No15包为RTO超时重传包,此时判断开关关闭不对这次RTO超时重传启动FRTO探测

  • server在收到No16包的时候发现当前没有启动对FRTO探测,因此server端仍然处于Loss状态,No16包触发一个慢启动重传(SlowStartRetrans实际上走的就是快速重传流程),接着没有了待重传的数据传输了一个新的未发送数据包No18

  • client端回复对应No17和No18的ACK确认包

3、设置tcp_frto=2,第一个ACK确认了新数据但是没有SACK选项,第二个ACK带有SACK选项。如下图所示

  • No1-No15数据包与示例1相似不再解释

  • client接收到到No15的重传之后,回复一个不带有SACK选项的partial ACK确认收到数据包No11,此时server端还有No13和No14两个数据包没有被ACK确认

  • server端的FRTO流程接收到No16确认包之后,发现满足上面描述的第4点,即“如果收到的ACK确认包是RTO后的第一个ACK确认包,且ack number确认了新数据,那么尝试发送新的未发送数据”,这时候缓存中正好还有一个数据包,因此FRTO流程发出了No17的新数据包。示例1中此处也是发出了新数据包,但是示例1是判断为虚假重传退出了Loss状态和FRTO流程。而这里发出的No17新数据包是在FRTO流程中发出去的,server端仍然处于Loss状态,FRTO流程还需要等待下一个ACK确认包

  • 接着FRTO流程收到No18确认包,包含有确认了No17数据包的SACK信息,满足上面描述的第5点:“如果收到了第二个ACK确认包,如果这个确认包SACK了新的数据或者是dup ACK那么认为是真实重传,退出FRTO过程执行普通的RTO超时重传流程。”FRTO判断本次RTO超时为真实的RTO超时,退出FRTO流程执行普通的RTO超时慢启动流程

  • 接着慢启动重传了No19和No20两个数据包,client回复对应的ACK报文。

补充说明:

1、细心的读者会发现这几个示例中client端的TSopt选项回复的TSECR是有问题的,正常的话实际上会触发Eifel虚假重传探测,后面拥塞控制部分会介绍Eifel探测相关内容。实际上所使用的client端TSopt的实现有两种方式,一种是直接echo最近接收到的TSval,另外一种是按照协议要求实现的。具体选择那种方式可以通过参数选择来设置,注意第一种直接echo最近接收到的TSval是不符合协议的错误的实现。除了后面会介绍到的Eifel探测client端选用了协议标准的实现方式外,其余示例大部分都是使用的第一种方式。

TCP系列24—重传—14、F-RTO虚假重传探测的更多相关文章

  1. TCP系列25—重传—15、DSACK虚假重传探测

    一.DSACK介绍 RFC2883通过指定使用SACK来指示接收端的重复包(duplicate packet)扩展了RFC2018对SACK选项的定义(SACK选项的介绍和示例参考前面内容).RFC2 ...

  2. TCP系列51—拥塞控制—14、TLP、ER与拥塞控制

    一.概述 这里的重点是介绍TLP.ER与拥塞控制并不是介绍TLP和ER本身,因此TLP和ER的详细内容请翻前文. 在TLP与拥塞控制的交互中有几个点需要注意 1.TLP触发的重传后,TCP仍然处于Op ...

  3. TCP系列52—拥塞控制—15、前向重传与RACK重传拥塞控制处理对比

    一.概述 这里主要简单分析一个丢包重传并恢复的场景,通过不同的设置让这个相同的场景分别触发RACK重传和前向重传,通过对比说明以下问题: Forward Retransmit可以产生只有重传标记的数据 ...

  4. TCP系列16—重传—6、基础快速重传(Fast Retransmit)

    一.快速重传介绍 按照TCP协议,RTO超时重传是一个非常重要的事件,当RTO超时的时候,TCP会同时通过两种方式非常谨慎的降低发送数据包的速率,一种是基于拥塞控制削减发送窗口的大小,另外一个是通过指 ...

  5. TCP系列20—重传—10、早期重传(ER)

    一.介绍 在前面介绍thin stream时候我们介绍过有两种场景下可能不会产生足够的dup ACK来触发快速重传,一种是游戏类响应交互式tcp传输,另外一种是传输受到拥塞控制的限制,只能发送少量TC ...

  6. TCP系列45—拥塞控制—8、SACK关闭的拥塞撤销与虚假快速重传

    一.概述 这篇文章介绍一下TCP从Recovery状态恢复到Open状态的时候cwnd的更新.我们在tcp重传部分的文章中曾经介绍过虚假重传的概念,Linux在探测到虚假重传的时候就会执行拥塞撤销操作 ...

  7. TCP系列14—重传—4、Karn算法和TSOPT的RTTM

    一.Karn算法 在RTT采样测量过程中,如果一个数据包初传后,RTO超时重传,接着收到这个数据包的ACK报文,那么这个ACK报文是对应初传TCP报文还是对应重传TCP报文呢?这个问题就是retran ...

  8. TCP系列13—重传—3、协议中RTO计算和RTO定时器维护

    从上一篇示例中我们可以看到在TCP中有一个重要的过程就是决定何时进行超时重传,也就是RTO的计算更新.由于网络状况可能会受到路由变化.网络负载等因素的影响,因此RTO也必须跟随网络状况动态更新.如果T ...

  9. TCP系列23—重传—13、RACK重传

    一.RACK概述 RACK(Recent ACKnowledgment)是一种新的基于时间的丢包探测算法,RACK的目的是取代传统的基于dupthresh门限的各种快速重传及其变种.前面介绍的各种基于 ...

随机推荐

  1. 企业IT架构转型之道 读后感

    放假三天,用部分时间阅读了企业IT架构转型之道这本书.第一遍潦草读完,就感觉收益颇多.这本书值得多读几遍,适合精度. 作为银行IT开发人员,在央企IT成本部门的大背景下,开发过程中遇到的诸多疑惑.困惑 ...

  2. 我的Tmux学习笔记

    0. 修改指令前缀 // ~/.tmux.conf ubind C-b set -g prefix C-a 1. 新建会话 tmux tmux new -s session-name // 可以设置会 ...

  3. STM32F407+STemwin学习笔记之STemwin移植补充Touch

    原文地址:http://www.cnblogs.com/NickQ/p/8857213.html 环境:keil5.20  STM32F407ZGT6  LCD(320*240)  STemwin:S ...

  4. 解决 Node.js 错误 Error:listen EADDRINUSE

    第一次尝试 node.js 中的 express 框架,写了第一个 js 文件之后,在 WebStorm 运行,到游览器刷新,成功运行. 又创建一个 js 文件,写的是静态路由的访问,结果出现了 Er ...

  5. Codeforces Round #482 (Div. 2) :B - Treasure Hunt

    题目链接:http://codeforces.com/contest/979/problem/B 解题心得: 这个题题意就是三个人玩游戏,每个人都有一个相同长度的字符串,一共有n轮游戏,每一轮三个人必 ...

  6. 天津市人民优步Uber司机奖励政策(9月14日~9月20日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  7. ORB-SLAM(十)LoopClosing

    构造函数 LoopClosing(Map* pMap, KeyFrameDatabase* pDB, ORBVocabulary* pVoc,const bool bFixScale); 主要分两部分 ...

  8. spring源码-事件&监听3.6

    一.spring中的发布与监听模式,是我们最常用的一种观察者模式.spring在其中做了很多优化,目的就是让用户更好的使用事件与监听的过程. 二.常用的事件与监听中涉及到的接口和类为:Applicat ...

  9. PHP中URL字符串与关联数组的互相转换

    转换PHP数组为查询字符串放到URL中 $data = array( 'apikey'=>'xg6tr7k', 'user'=>'abcd', 'email'=>'root@exam ...

  10. yarn 原理

    产生背景 直接源于MRv1在几个方面的缺陷 扩展性受限(NameNode,JobTracker设计为单一节点,内存容量有限) 单点故障 难以支持MR之外的计算 slot数目无法动态修改,Map slo ...