我们之前介绍SACK选项的时候说过,SACK可以把接收端系列号空间的洞反映给发送端,因此发送端可以更充分的理解接收端的情况,而进行更好的重传恢复过程。这种过程有时候也叫做advanced loss recovery。

一、数据接收端SACK行为

我们通过一个wireshark示例来说明接收端的SACK行为:

 

如上图,为了方便在info列中查看SACK信息,我把info列中TSopt的信息隐藏了,同时把源地址列和目的地址列一起隐藏了。client依次发送P1(1-6)、P2(25-30)、P3(13-18)、P4(37-42)、P5(49-54)、P6(7-12)、P7(31-36)、P8(19-24)、P9(43-48)其中括号中的数字为相对系列号,接收端SACK行为简述如下(详细的可以参考原始的wireshark文件)

  1. 接收端在接收到P1后回复的No5确认包中不包含SACK信息

  2. 在接收到P2后回复的No7确认包中包含的SACK块为(25-31)

  3. 接收端在接收到P3后回复No9确认包,包含的SACK块为(13-19),(25-31)

  4. 接收端在接收到P4后回复No11确认包,包含的SACK信息为(37-43),(13-19),(25-31)

  5. 接收端在接收到P5后回复No13确认包,包含的SACK信息为(49-55),(37-43),(13-19),上图截图中对应的SACK信息就是这个确认包的信息

  6. 接收端在接收到P6后回复No15确认包,包含的SACK信息为(49-55),(37-43),(25-31)

  7. 接收端在接收到P7后回复No17确认包,包含的SACK信息为(25-43),(49-55)

  8. 接收端在接收到P8后回复No19确认包,包含的SACK信息为(49-55)

  9. 接收端在接收到P9后回复No21确认包,接收端系列号空间中不再存在洞,因为这个确认包中不再包含SACK信息。

上面的每个ACK确认包都会包含一个TSopt的选项,从上面第5点可以看到,在ACK确认包包含有TSopt选项的时候,最后只能包含3个SACK块,此时TCP头长已经到达60bytes的最大值不能在容纳更多的SACK块了。

另外注意就是SACK块是按照最新形成的洞信息倒序排列的。每个ACK报文中可以携带多个SACK块的原因是因为ACK确认包有可能会丢包,但是ACK报文不消耗系列号因此不会进行重传,因此接收端通过多个ACK报文中冗余的SACK块信息来提高SACK信息传输的可靠性。

二、数据发送端SACK行为

TCP连接要利用SACK信息还需要发送端根据接收到的SACK信息执行选择性重传(selective retransmisson或者叫做selective repeat)。首先根据SACK信息来填充洞,然后在传递新数据(RFC6675),但是具体实现上可能会有一些差异。另外按照RFC2018,当TCP初始化一个RTO超时重传的时候需要清空SACK信息,但是RFC6675认为RTO超时保留SACK信息也是有一定必要性的。RFC2018还要求发送端只有收到TCP头中的累计ack number的时候才能释放对应的发送缓存,而不能根据SACK信息释放,原因是接收端有可能先发送一个SACK块,然后后面又不在反馈这个SACK块(SACK reneging)。(实际上按照协议发送端接收到的SACK块可能是接收端已经丢弃的TCP报文,虽然这个报文丢弃了但是特定情况下接收端仍然可以在SACK块中携带这个报文信息,而在实现上如果linux内存不足,那么有可能会丢掉已经收到的乱序TCP报文)。SACK reneging的示例我们后面会在FACK介绍中进行简单介绍。

另外一个需要注意的就是在快速重传的时候dup ACK的定义,RFC6675中对于SACK下dup ACK的定义如下

For the purposes of this specification, we define a "duplicate   acknowledgment" as a segment that arrives carrying a SACK block that   identifies previously unacknowledged and un-SACKed octets between   HighACK and HighData.  Note that an ACK which carries new SACK data   is counted as a duplicate acknowledgment under this definition even if it carries new data, changes the advertised window, or moves the   cumulative acknowledgment point, which is different from the   definition of duplicate acknowledgment in [RFC5681].

其中

"HighACK" is the sequence number of the highest byte of data that has been cumulatively ACKed at a given point.      "HighData" is the highest sequence number transmitted at a given point.

下面我们还是重点关注一下Linux实现上的处理吧。

三、SACK下的重传示例

1、SACK打开但是不携带SACK选项的场景

前面我们介绍快速重传示例的时候,都是把tcp_sack开关设置为0。其中有一个示例如下

其中No12-No14三个数据包是不带有SACK选项的ACK确认包。可以看到server在接收到三个dup ack后触发了快速重传,我们设置tcp_sack为1后重新运行测试程序,抓包如下,可以看到server在接收到三个不带有SACK选项的dup ack后并没有触发快速重传,由此可以看到SACK下对于dup ACK理解上的差异。

2、带有SACK选项的快速重传

下面我们看一个带有SACK的快速重传,下面的测试程序与上面类似,同样打开tcp_sack功能,不同的时候这次在No12确认包中包含17-25的SACK块信息,在No13确认包中包含17-33的SACK块信息,在No14确认包中包含17-41的SACK块信息。No12-No14确认包的ack number都是9,在收到No14确认包后累计收到三个dup ACK,因此触发了快速重传。注意这里对dup ACK的认定并不是因为ack number相同,而是因为SACK块中累计反馈了三个发送出去的数据包。

3、SACK下ack number不同的dup ACK

上面我们说过SACK下对于dup ACK的认定并不是因为ack number不同。我们在来看一个例子,从下图可以看到wireshark显示两个dup ack后就触发了快速重传,实际上是因为wireshark对于dup ack的认定只关注ack number导致的。在No11中带有17-25的SACK块信息,No12中带有17-33的SACK块信息,No13中带有17-41的SACK块信息。按照上面SACK下对于dup ACK的定义,server实际上已经接收到了3个dup ACK,因此触发了快速重传。

TCP系列17—重传—7、SACK下的重传的更多相关文章

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

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

  2. TCP系列46—拥塞控制—9、SACK下的快速恢复与Limited transmit

    一.概述 1.SACK下的特殊处理过程 SACK下的拥塞控制处理是linux中拥塞控制的实现依据,再次强调一遍RFC6675的重要性,linux中拥塞控制主体框架的实现是与RFC6675一致的,所以如 ...

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

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

  4. TCP系列54—拥塞控制—17、AQM及ECN

    一.概述 ECN的相关内容是在RFC3168中定义的,这里我简单描述一下RFC3168涉及的主要内容. 1.AQM和RED 目前TCP中多数的拥塞控制算法都是通过缓慢增加拥塞窗口直到检测到丢包来进行慢 ...

  5. TCP系列18—重传—8、FACK及SACK reneging下的重传

    一.介绍 FACK的全称是forward acknowledgement,FACK通过记录SACK块中系列号最大(forward-most)的SACK块来推测丢包信息,在linux中使用fackets ...

  6. TCP系列19—重传—9、thin stream下的重传

    一.介绍 当TCP连续大量的发送数据的时候,当出现丢包的时候可以有足够的dup ACK来触发快速重传.但是internet上还有大量的交互式服务,这类服务一般都是由小包组成,而且一次操作中需要传输的数 ...

  7. TCP系列50—拥塞控制—13、Eifel探测下的拥塞撤销

    一.概述 我们之前在SACK关闭场景下的拥塞撤销那篇文章中提到过Eifel探测算法(Eifel Detection Algorithm),最早在介绍DSACK和FRTO的时候我们就有提到过Eifel探 ...

  8. TCP系列49—拥塞控制—12、DSACK下的拥塞撤销

    一.概述 DSACK下的虚假重传的检测我们之前重传部分的文章已经介绍过了,这里简单说一下拥塞控制部分的实现. linux内部会维护一个undo_retrans状态变量,其值为已经重传的次数减掉被DSA ...

  9. TCP系列44—拥塞控制—7、SACK关闭的快速恢复

    ) return;    delta = ssthresh - in_flight;     prr_delivered += newly_acked_sacked; if (delta < 0 ...

随机推荐

  1. Google+百度,自动识别知名人物的性别

    最近有一个任务,需要采集一批知名学者的性别信息.该任务的难点在于提供学者信息的网站并不会主动标注学者的性别性别,因此只能靠别的方法了. 对一个普通人来说,在网上判断一个人的性别的最快的方式就是看他的照 ...

  2. nodejs的安装配置

    Node.js安装及环境配置   一.安装环境 1.本机系统:Windows 10 Pro(64位)2.Node.js:v6.9.2LTS(64位) 二.安装Node.js步骤 1.下载对应你系统的N ...

  3. laravel-admin 创建数据库并生成控制器

    以user表为例 1. 生成迁移:php artisan make:migration create_users_table 在 database/migration 中生成迁移文件,可对迁移文件进行 ...

  4. Python3练习:对员工信息文件,实现增删改查操作

    1.练习要求: 2.数据文件(data_staff.txt) 1,Alex Li,22,13651054684,运维,2013-02-04 2,Jack Wang,20,13312331232,HR, ...

  5. Qt——父对象、布局

    设置父对象两个好处:(1)加入析构树(2)和父对象一起显示 设置布局后,子控件自动被设置父对象 设置父对象两个好处:(1)加入析构树(2)和父对象一起显示

  6. C#、C++、Java、Python 选择哪个好?

    C#.C++.Java.Python 选择哪个好? 2019年03月06日 16:54:34 编程小火车 阅读数:214   首先排除Python,光动态语言一个理由,就已经万劫不复了.无论有多少所谓 ...

  7. Caliburn.Micro 杰的入门教程1(翻译)

    Caliburn.Micro 杰的入门教程1(原创翻译)Caliburn.Micro 杰的入门教程2 ,了解Data Binding 和 Events(翻译)Caliburn.Micro 杰的入门教程 ...

  8. 深圳Uber优步司机奖励政策(12月28日到1月3日)

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

  9. ORB-SLAM(五)KeyFrame类-最小生成树

    KeyFrame中维护了一个map,保存了与当前帧共视的KeyFrame*与权重(共视MapPonits数量).对关键帧之间关系是用加权有向图来完成的,那么理解其spanning tree生成树的原理 ...

  10. 接口测试工具postman(六)添加变量(参数化)

    1.添加全局变量并引用 2.通过设置请求前置配置变量 3.在Tests里面,把响应数据设置为变量 4.添加外部文件,引用外部文件中的变量和数据,此种场景就可以执行多次请求 1)配置文件,txt或者cs ...