TCP系列18—重传—8、FACK及SACK reneging下的重传
一、介绍
FACK的全称是forward acknowledgement,FACK通过记录SACK块中系列号最大(forward-most)的SACK块来推测丢包信息,在linux中使用fackets_out这个状态变量来记录FACK信息。我们之前介绍SACK重传时候说过在SACK下需要3个dup ACK来触发快速重传(3个为默认值),而SACK下的dup ACK的定义与传统的非SACK下定义又略有不同(详细请参考前面的文章和示例)。当使能FACK的时候,实际上我们可以通过一个SACK块信息来推测丢包情况进而触发快速重传。比如server端依次发出P1(0-9)、P2(10-19)、P3(20-29)、P4(30-39)、P5(40-49),假设client端正常收到了P1包并回复了ACK确认包,P2、P3、P4则由于网络拥塞等原因丢失,client在收到P5时候回复一个Ack=10的确认包,并携带P5有SACK块信息(40-50),这样server在收到P1的确认包和P5的dup ACK时候,就可以根据dup ACK中的SACK信息得知client端收到了P1报文和P5报文,计算出P1和P5两个数据包中间间隔了3个数据包,达到了dup ACK门限(默认为3),进而推测出P2报文丢失。
SACK reneging我们在前面SACK中已经介绍了,下面我们通过示例来一起看一下FACK和SACK reneging下的重传。
二、wireshark示例
1、tcp_early_retrans=0,tcp_retrans_collapse=0,tcp_discard_on_port =9877,tcp_sack=1,tcp_fack=1;场景下的重传如下图所示:
server端依次发送No6-No10五个数据包
client收到No6后回复一个不带有SACK选项的ACK确认包(No11),server端正常接收到这个ACK确认包
接着client模拟No7-No9数据包丢包,在收到No10乱序包的时候,回复一个dup ACK,其中包含SACK信息(33-41),
server端收到这个dup ACK后推测处client端已经收到No6和No10报文,中间间隔的报文个数为3个,达到dup ACK门限,进而触发快速重传。
client继续模拟丢包,接着server端RTO超时,进行指数回退过程。
直到No16重传后,client开始回复不带有SACK选项的ACK(partial ACK),但是因为ack number并没有落在33-40之间,此时linux并不会确认发生了SACK reneging。这个ACK触发快速重传(No18)。受限与拥塞控制,这个时候只能发送一个重传包,发送完这个重传报文后根据收到的ACK更新拥塞窗口,拥塞窗口自增1,因此此时可以发送一个新的数据包,但是因为缓存中没有新的待发送数据因此并没有新数据包传出。
接收client回复No19的ACK确认包(partial ACK),这个ACK报文虽然不带有SACK选项,但是linux同样不会确认发生了SACK reneging,server端根据这个partial ACK触发快速重传,在上一步中拥塞窗口已经自增了1,因此实际上快速重传可以重传两个TCP报文但是因为重传完No20后,只剩下一个报文待重传,而这个报文之前又被SACK过,因此快速重传不会重传这个报文
接着client回复不带有SACK选项的No21确认包,Ack=33,注意之前触发FACK快速重传的时候反馈的SACK块信息是(33-41)告诉server端收到了No10数据包,而这个新回复的No21确认包又告诉server没有收到No10确认包。此时就是发生了SACK reneging。在这个ACK确认包触发快速重传时候,就会检测是否发生了SACK seneging,如果发生SACK reneging,linux会初始化一个RTO定时器,定时器的定时时间为RTT/2。快速重传时候检测到了SACK seneging就会直接退出。
接着上一步的RTO定时器超时,触发了No22的RTO超时重传,client回复对应的ACK确认包,整个传输过程结束。

2、tcp_early_retrans=0,tcp_retrans_collapse=0,tcp_discard_on_port =9877,tcp_sack=1,tcp_fack=0;这里我们关闭FACK功能,其他设置不变重新进行类似上面的测试
可以看到这个示例与上面示例的主要差异就是No12的dup ACK虽然同样反馈了No10的SACK信息,但是并没有触发快速重传。其他内容与上面示例基本一致不再重复介绍。

3、tcp_early_retrans=0,tcp_retrans_collapse=0,tcp_discard_on_port =9877,tcp_sack=1,tcp_fack=1;低于dup ACK门限
这个示例和示例1不同的地方在于No12的dup ACK确认包携带的SACK信息为(25-33),也就是通过SACK确认了No9报文,No9与No6报文之间间隔了2个报文没有达到dup ACK的门限,因此并不会触发快速重传。注意server端在收到No19确认包时候触发了快速重传流程,但是快速重传前检测到SACK seneging,重启了RTO定时器并退出快速重传。

补充说明:
1、SACK seneging的检测和RTO定时器的设置参考linux内核tcp_check_sack_reneging函数
TCP系列18—重传—8、FACK及SACK reneging下的重传的更多相关文章
- TCP系列13—重传—3、协议中RTO计算和RTO定时器维护
从上一篇示例中我们可以看到在TCP中有一个重要的过程就是决定何时进行超时重传,也就是RTO的计算更新.由于网络状况可能会受到路由变化.网络负载等因素的影响,因此RTO也必须跟随网络状况动态更新.如果T ...
- TCP系列45—拥塞控制—8、SACK关闭的拥塞撤销与虚假快速重传
一.概述 这篇文章介绍一下TCP从Recovery状态恢复到Open状态的时候cwnd的更新.我们在tcp重传部分的文章中曾经介绍过虚假重传的概念,Linux在探测到虚假重传的时候就会执行拥塞撤销操作 ...
- TCP系列17—重传—7、SACK下的重传
我们之前介绍SACK选项的时候说过,SACK可以把接收端系列号空间的洞反映给发送端,因此发送端可以更充分的理解接收端的情况,而进行更好的重传恢复过程.这种过程有时候也叫做advanced loss r ...
- TCP系列46—拥塞控制—9、SACK下的快速恢复与Limited transmit
一.概述 1.SACK下的特殊处理过程 SACK下的拥塞控制处理是linux中拥塞控制的实现依据,再次强调一遍RFC6675的重要性,linux中拥塞控制主体框架的实现是与RFC6675一致的,所以如 ...
- TCP系列52—拥塞控制—15、前向重传与RACK重传拥塞控制处理对比
一.概述 这里主要简单分析一个丢包重传并恢复的场景,通过不同的设置让这个相同的场景分别触发RACK重传和前向重传,通过对比说明以下问题: Forward Retransmit可以产生只有重传标记的数据 ...
- TCP系列47—拥塞控制—10、FACK下的快速恢复与PRR
一.概述 FACK下的重传我们在之前的重传部分已经进行了介绍,这里简单介绍一下随着FACK提出的拥塞控制算法的改进及随后的进一步改进. 从我们之前介绍的RFC2582和RFC5681中可以看到,快速恢 ...
- TCP系列24—重传—14、F-RTO虚假重传探测
一.虚假重传 在一些情况下,TCP可能会在没有数据丢失的情况下初始化一个重传,这种重传就叫做虚假重传(Spurious retransmission).发生虚假重传的原因可能是包传输中重排序.传输中发 ...
- TCP系列22—重传—12、Forward Retransmit
一.概述 forward retransmit相关的内容在RFC6675中有描述,可以参考RFC6675 section 4中NextSeg ()的定义.forward retransmit中文名可以 ...
- TCP系列21—重传—11、TLP
一.介绍 Tail Loss Probe (TLP)是同样是一个发送端算法,主要目的是使用快速重传取代RTO超时重传来处理尾包丢失场景.在一些WEB业务中,如果TCP尾包丢失,如果依靠RTO超时进行重 ...
随机推荐
- nginx通过upstream实现负载均衡
随着业务和用户不断增加,单台服务器无法满足业务需求,产生服务器集群的场景.为了能充分利用服务器集群,最理想的方式就是整个集群的利用率都很平均且稳定在理想值范围内. 负载均衡(Load Balance) ...
- 视频网站数据MapReduce清洗及Hive数据分析
一.需求描述 利用MapReduce清洗视频网站的原数据,用Hive统计出各种TopN常规指标: 视频观看数 Top10 视频类别热度 Top10 视频观看数 Top20 所属类别包含这 Top20 ...
- python 基础练习题, 陆续添加中
判定用户输入数字是否为闰年 闰年的定义:能够被4整除的年份 #input是自定义输入内容的函数 year = input("请输入年份数字:") #xxx.isdigit方法是检测 ...
- Java两个线程实现交替运行-以交替打印奇偶数为例
本文旨在两个线程交替运行,不多哔哔直接看代码吧 public class Work2 { static final Object object = new Object(); public stati ...
- Shell--cut用法
cut是以每一行为一个处理对象的,这种机制和sed一样. cut接受三个定位方法: 1)byte: -b 2)characters: -c 3)fields: -d eg:提取第3,4,5,9的字节: ...
- python--模块之基本
模块的概念: 在计算机程序开发过程中,随着程序代码越来越多,在一个文件里代码就会越来越长,不利于维护.为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样每个文件包含的代码就相对较少. ...
- Codecraft-18 and Codeforces Round #458:D,Bash and a Tough Math Puzzle
题目传送门 题目大意:Bash喜欢对数列进行操作.第一种操作是询问l~r区间内的gcd值是否几乎为x,几乎为表示能否至多修改一个数达到.第二种操作是将ai修改为x.总共Q个询问,N个数. Soluti ...
- 食物链_KEY
食物链 (eat.pas/c/cpp) [ 问题描述] 动物王国中有三类动物 A,B,C, 这三类动物的食物链构成了有趣的环形. A 吃 B, B 吃C, C 吃 A.现有 N 个动物, 以 1-N ...
- linux (rm指令) 及误删除解决
今天在群里看见这一幕: 看到这儿,我们学习一下 这个RM指令 rm命令可以删除一个目录中的一个或多个文件或目录,也可以将某个目录及其下属的所有文件及其子目录均删除掉.对于链接文件,只是删除整个链接文件 ...
- MAC 更新brew 镜像源
mac 更新brew镜像源 cd "$(brew --repo)/Library/Taps/homebrew/homebrew-core" git remote set-url o ...