TCP系列25—重传—15、DSACK虚假重传探测
一、DSACK介绍
RFC2883通过指定使用SACK来指示接收端的重复包(duplicate packet)扩展了RFC2018对SACK选项的定义(SACK选项的介绍和示例参考前面内容)。RFC2883建议在收到重复报文的时候,SACK选项的第一个块(这个块也叫做DSACK块)可以用来传递触发这个ACK确认包的系列号,这个就是DSACK(duplicate-SACK)功能。这样允许TCP发送端根据SACK选项来推测不必要的重传。进而利用这些信息在乱序传输的环境中执行更健壮的操作。这个DSACK扩展是与原有的SACK选项的实现相互兼容的。DSACK的使用也不需要TCP连接的双方额外协商(只要之前协商了SACK选项即可)。当TCP的发送方不理解DSACK扩展的时候会简单的丢弃DSACK块并继续处理SACK选项中的其他块。
当DSACK使能的时候,总结起来如下
一个DSACK块只用来传递一个接收端最近接收到的重复报文的系列号,每个SACK选项中最多有一个DSACK块
接收端每个重复包最多在一个DSACK块中上报一次。如果接收端依次发送了两个带有相同DSACK块信息的ACK报文,则表示接收端接收了两次重复包,因此带有DSACK块信息的ACK确认包传输丢失的时候重复包信息也会丢失。
和普通的SACK块一样,DSACK块左边指定重复包的第一个字节的系列号,右边指定重复包最后一个字节的下一个系列号
如果收到重复报文,第一个SACK块应该应该指定触发这个ACK确认包的系列号(这个SACK块也叫做DSACK块)。如果这个重复报文是一个大的不连续块的一部分,那么接下来的这个SACK块应该指定这个大的不连续块,额外的SACK块应该按照RFC2018指定的顺序排列。
另外还有一种部分重复段(partial duplicate segment)的上报场景,我们会在示例中展示说明。注意按照上面的描述,DSACK块有可能处于ack number之前。接收端在接收到SACK报文的时候,应该把第一个SACK块与这个ACK报文的ack number比较(而不是和当前已经接收到的最大的ack number比较),如果小于等于ack number则说明是DSACK块,如果大于ack number则应该与第二个SACK块比较,如果第二个SACK块包含第一个SACK块,则说明第一个SACK块为DSACK块,如果上面两个条件都不满足说明第一个SACK块是普通的SACK块。
在linux中/proc/sys/net/ipv4/tcp_dsack控制发出的报文中是否携带DSACK信息,但是不管该参数设置为何值,对于接收的TCP报文,linux总是会执行DSACK块的检测处理。当linux检测到DSACK块信息的时候会尝试撤销拥塞控制对于拥塞窗口的作用。另外在TLP丢包探测中也可以用来做loss probe的丢包探测。
二、wireshark示例
1、tcp_dsack=1,接收到ack number之前的数据包
如下图所示,client和server三次握手后,依次发送No4(1-6)、No6(7-13)、No8(7-13)、No10(14-20)四个数据包,server端接收到No8时候发现是一个重复包,因此回复一个带有DSACK的ACK确认包(No9),其中DSACK块信息为(7-14),表示收到了一个系列号为(7-13)的重复包。
2、tcp_dsack=1,接收到ack number之后的数据包
client端分别发送No4(1-6)和No6(7-13),server端正常回复不带有SACK选项的ACK确认包
接着client发送No8(21-27),模拟系列号(14-20)的报文在由client向server传输的过程中丢包
server端回复一个带有SACK选项的ACK确认包(No9),其中包含一个SACK块(21-28)
client端继续发送No10(24-34),server端回复No11的ACK确认包,包含一个SACK块(21-35)
接着client发送No12(42-48),模拟系列号为(35-41)的报文传输过程中发生丢失
server端回复No13的ACK报文,带有两个SACK块,依次为(42-49)和(21-35)
client端发送No14(28-34),这个数据包与No10数据包系列号相同
server端收到No14的重复包之后,回复No15确认包,带有一个DSACK块(28-35)和两个额外的SACK块,这两个SACK块依次为(21-35)(42-49)
接着client发送No16(14-20),server端回复No17确认包,带有一个SACK块(42-49)。
client发送No18(35-41),server端回复No19确认包,不带有SACK信息,整个传输过程结束
3、tcp_dsack=1,接收到ack number之后的部分重传段
此处不在罗嗦叙述过程,此处仅把SACK的信息文字补充描述一下,其他信息请自行下载对应的wireshark文件
其中No9、No11、No13、No15包含SACK信息,No9包含一个SACK块(28-35),No11包含一个SACK块(28-42),No13包含两个SACK块信息(49-56)、(28-42),No15包含一个DSACK块(28-42)和一个额外的SACK块(21-56),注意此处No14(21-55)与之前的两个SACK块(49-56)、(28-42)都是重复包,着一个TCP包与前面的三个包内容重复还发送了新的数据,这种同时带有新数据和重复数据的tcp报文就叫做部分重传段,当部分重传段中同时带有多个重复段的时候,协议规定DSACK块值反馈第一个重复端的系列号范围。可以看到此时linux的处理是符合协议的。
4、tcp_dsack=1,接收到ack number之前的部分重传段
此处同样仅用文字描述一下SACK信息,No9带有一个SACK块(21-28),No11带有一个SACK块(21-35),No13带有两个SACK块(42-49)和(21-35),No15数据包带有一个DSACK块(21-56)。注意这里与上面同样是带有两个重复段大的部分重传段,但是linux反馈的DSACK信息却把两个重复段都包含了,而且还扩展到了最新发送的55系列号(DSACK块中的56表示55系列号的后一个系列号)。RFC2883协议中的对这种场景的描述是:
When the SACK option is used for reporting partial duplicate segments, the first D-SACK block reports the first duplicate sub-segment. If the data packet being acknowledged contains multiple partial duplicate sub-segments, then only the first such duplicate sub-segment is reported in the SACK option.
而linux的处理则是,如果当前接收到的数据包的系列号与待接收的连续系列号相同,那么回复的DSACK块的起始系列号则为乱序队列中的最小系列号,终止系列号则为新收到的数据包的最大系列号加1。显然linux的处理与协议要求不符合,而且与DSACK扩展功能的预期不相符,具体原因我也没查到(不过并不是所有不符合协议的实现都是bug,有些实现可能会在协议的基础上做一些扩展)。
补充信息:
1、示例4场景中描述的linux的DSACK处理逻辑位于函数tcp_ofo_queue中
TCP系列25—重传—15、DSACK虚假重传探测的更多相关文章
- TCP系列52—拥塞控制—15、前向重传与RACK重传拥塞控制处理对比
一.概述 这里主要简单分析一个丢包重传并恢复的场景,通过不同的设置让这个相同的场景分别触发RACK重传和前向重传,通过对比说明以下问题: Forward Retransmit可以产生只有重传标记的数据 ...
- TCP系列24—重传—14、F-RTO虚假重传探测
一.虚假重传 在一些情况下,TCP可能会在没有数据丢失的情况下初始化一个重传,这种重传就叫做虚假重传(Spurious retransmission).发生虚假重传的原因可能是包传输中重排序.传输中发 ...
- TCP系列49—拥塞控制—12、DSACK下的拥塞撤销
一.概述 DSACK下的虚假重传的检测我们之前重传部分的文章已经介绍过了,这里简单说一下拥塞控制部分的实现. linux内部会维护一个undo_retrans状态变量,其值为已经重传的次数减掉被DSA ...
- TCP系列45—拥塞控制—8、SACK关闭的拥塞撤销与虚假快速重传
一.概述 这篇文章介绍一下TCP从Recovery状态恢复到Open状态的时候cwnd的更新.我们在tcp重传部分的文章中曾经介绍过虚假重传的概念,Linux在探测到虚假重传的时候就会执行拥塞撤销操作 ...
- TCP系列23—重传—13、RACK重传
一.RACK概述 RACK(Recent ACKnowledgment)是一种新的基于时间的丢包探测算法,RACK的目的是取代传统的基于dupthresh门限的各种快速重传及其变种.前面介绍的各种基于 ...
- TCP系列21—重传—11、TLP
一.介绍 Tail Loss Probe (TLP)是同样是一个发送端算法,主要目的是使用快速重传取代RTO超时重传来处理尾包丢失场景.在一些WEB业务中,如果TCP尾包丢失,如果依靠RTO超时进行重 ...
- TCP系列26—重传—16、重组包
一.介绍 在TCP重传的时候,并没有限制TCP只能重传与初传完全相同的报文段大小,TCP允许执行重组包(repacketization),发送一个更大的TCP报文段,进而增加性能.TCP在重传时候允许 ...
- TCP系列22—重传—12、Forward Retransmit
一.概述 forward retransmit相关的内容在RFC6675中有描述,可以参考RFC6675 section 4中NextSeg ()的定义.forward retransmit中文名可以 ...
- TCP系列17—重传—7、SACK下的重传
我们之前介绍SACK选项的时候说过,SACK可以把接收端系列号空间的洞反映给发送端,因此发送端可以更充分的理解接收端的情况,而进行更好的重传恢复过程.这种过程有时候也叫做advanced loss r ...
随机推荐
- JavaScript6里出现了哪些新语法、新特征?
ES5是2009年就出来的,目前来说在我写这篇文章的时候基本上ES6在浏览器上面还没有普及,不过Google浏览器是支持ES6语法的,谁让Google是美国生产的呢... ES6现在使用的地方其实还是 ...
- Struts2+EasyUI+Hibernate小实例
概述 这个实例主要是前台数据到后台数据的传递和后台数据到前台数据的传递,完成数据的新增,以及对新增数据的展示.下面是详细的过程: Hibernate(数据库部分) 这里只是数据库的连接和数据库实体与物 ...
- c语言实现通讯录管理系统(c课程设计)
工具:Visual C++6.0 说明: 本系统基于C语言实现班级通讯录管理系统,为大一时学习C语言刚入门所做的课程设计.功能包括增.删.查.改等,非常适合初学者练手.通讯录包括的个人信息有姓名.学号 ...
- 计算阶乘的和v2.0(4分)
题目内容: 假设有这样一个三位数m,其百位.十位和个位数字分别是a.b.c,如果m= a!+b!+c!,则这个三位数就称为三位阶乘和数(约定0!=1).请编程计算并输出所有的三位阶乘和数. 函数原型: ...
- gp与 pg 查询进程
select now()-query_start as cost_time,* from pg_stat_activity where current_query not in ( '<IDLE ...
- 日期插件Mobiscroll
http://mobiscroll.com/ http://www.cnblogs.com/hxling/archive/2012/12/12/2814207.html http://www.wglo ...
- AS 3.1 项目打包成jar或aar
1.首先明白一个道理. Android Studio编译的时候会自动将项目生成jar和aar的,我一开始以为jar需要自己单独生成,其实AS已经自动生成了,网上找的很多资料都是一个复制的过程而已. 只 ...
- Luogu P1802 5倍经验日_KEY
题目传送门 ·背包 这可以说是一道背包的变形. 首先需要考虑到的是如何将ta转换为一个正常 的背包. 这些数据有一个让我们都十分不爽的地方就是有两个值. 所以我们就设置一个基准值,将失败的经验值当做基 ...
- 成都Uber优步司机奖励政策(1月25日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- OKVIS(一)初始化流程及代码结构
OKVIS代码结构: okvis_apps: your own app okvis_ceres: backend main code, estimator, error term; okvis_co ...