TCP系列17—重传—7、SACK下的重传
我们之前介绍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文件)
接收端在接收到P1后回复的No5确认包中不包含SACK信息
在接收到P2后回复的No7确认包中包含的SACK块为(25-31)
接收端在接收到P3后回复No9确认包,包含的SACK块为(13-19),(25-31)
接收端在接收到P4后回复No11确认包,包含的SACK信息为(37-43),(13-19),(25-31)
接收端在接收到P5后回复No13确认包,包含的SACK信息为(49-55),(37-43),(13-19),上图截图中对应的SACK信息就是这个确认包的信息
接收端在接收到P6后回复No15确认包,包含的SACK信息为(49-55),(37-43),(25-31)
接收端在接收到P7后回复No17确认包,包含的SACK信息为(25-43),(49-55)
接收端在接收到P8后回复No19确认包,包含的SACK信息为(49-55)
接收端在接收到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下的重传的更多相关文章
- TCP系列52—拥塞控制—15、前向重传与RACK重传拥塞控制处理对比
一.概述 这里主要简单分析一个丢包重传并恢复的场景,通过不同的设置让这个相同的场景分别触发RACK重传和前向重传,通过对比说明以下问题: Forward Retransmit可以产生只有重传标记的数据 ...
- TCP系列46—拥塞控制—9、SACK下的快速恢复与Limited transmit
一.概述 1.SACK下的特殊处理过程 SACK下的拥塞控制处理是linux中拥塞控制的实现依据,再次强调一遍RFC6675的重要性,linux中拥塞控制主体框架的实现是与RFC6675一致的,所以如 ...
- TCP系列45—拥塞控制—8、SACK关闭的拥塞撤销与虚假快速重传
一.概述 这篇文章介绍一下TCP从Recovery状态恢复到Open状态的时候cwnd的更新.我们在tcp重传部分的文章中曾经介绍过虚假重传的概念,Linux在探测到虚假重传的时候就会执行拥塞撤销操作 ...
- TCP系列54—拥塞控制—17、AQM及ECN
一.概述 ECN的相关内容是在RFC3168中定义的,这里我简单描述一下RFC3168涉及的主要内容. 1.AQM和RED 目前TCP中多数的拥塞控制算法都是通过缓慢增加拥塞窗口直到检测到丢包来进行慢 ...
- TCP系列18—重传—8、FACK及SACK reneging下的重传
一.介绍 FACK的全称是forward acknowledgement,FACK通过记录SACK块中系列号最大(forward-most)的SACK块来推测丢包信息,在linux中使用fackets ...
- TCP系列19—重传—9、thin stream下的重传
一.介绍 当TCP连续大量的发送数据的时候,当出现丢包的时候可以有足够的dup ACK来触发快速重传.但是internet上还有大量的交互式服务,这类服务一般都是由小包组成,而且一次操作中需要传输的数 ...
- TCP系列50—拥塞控制—13、Eifel探测下的拥塞撤销
一.概述 我们之前在SACK关闭场景下的拥塞撤销那篇文章中提到过Eifel探测算法(Eifel Detection Algorithm),最早在介绍DSACK和FRTO的时候我们就有提到过Eifel探 ...
- TCP系列49—拥塞控制—12、DSACK下的拥塞撤销
一.概述 DSACK下的虚假重传的检测我们之前重传部分的文章已经介绍过了,这里简单说一下拥塞控制部分的实现. linux内部会维护一个undo_retrans状态变量,其值为已经重传的次数减掉被DSA ...
- TCP系列44—拥塞控制—7、SACK关闭的快速恢复
) return; delta = ssthresh - in_flight; prr_delivered += newly_acked_sacked; if (delta < 0 ...
随机推荐
- [Codefroces401D]Roman and Numbers(状压+数位DP)
题意:给定一个数,求将该数重新排列后mod m==0的方案数 重新排列就考虑到用到哪些数,以及此时mod m的值 于是dp[i][j]表示状态i中mod m==j的方案数 注意:转移的时候只要找到一种 ...
- python--模块之collection
collection模块: 在内置数据类型(dict.list.set.tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter.deque.defaultdict. ...
- SpaceVim 语言模块 lua
原文连接: https://spacevim.org/cn/layers/lang/lua/ 模块简介 启用模块 快捷键 交互式编程 运行当前脚本 模块简介 这一模块为在 SpaceVim 中进行 l ...
- Understanding Delegated JavaScript Events
While I ended up using a CSS-only implementation for this pen, I started by writing it mostly using ...
- python中通过datetime获取UTC时间ISO格式
一个热点统计需求,需要限定一个时间范围,计算出该范围内的热点事件,相关数据则以UTC标准时间的ISO时间格式存在mongodb中,和服务器设置的时区UTC+8并不一致. 为了解决这个问题,直觉反应是在 ...
- 【BZOJ1564】【NOI2009】二叉查找树(动态规划)
[BZOJ1564][NOI2009]二叉查找树(动态规划) 题面 BZOJ 洛谷 题目描述 已知一棵特殊的二叉查找树.根据定义,该二叉查找树中每个结点的数据值都比它左儿子结点的数据值大,而比它右儿子 ...
- Docker - 常用命令集
启动容器 docker run -d -p 58080:8080 -p 58000:8000 --name mytomcat1.0 -v /root/webapps/:/opt/apache-tomc ...
- 转:asp.net mvc ef 性能监控调试工具 MiniProfiler
MiniProfiler官网:http://miniprofiler.com/ MiniProfiler的一个特别有用的功能是它与数据库框架的集成.除了.NET原生的 DbConnection类,Mi ...
- 「专题训练」Hard problem(Codeforces Round #367 Div. 2 C)
题意与分析 题意:给出\(n\)个字符串,可以反转任意串,反转每个串都有其对应的花费\(c_i\).经过操作后是否能满足字符串\(\forall i \in [1,n] \text{且} i \in ...
- centos下php环境安装redis
一.安装redis(仅可在服务器使用,尚不能通过浏览器访问) (1)首先下载redis:wget http://download.redis.io/releases/redis-4.0.9.tar.g ...