TCP系列51—拥塞控制—14、TLP、ER与拥塞控制
一、概述
这里的重点是介绍TLP、ER与拥塞控制并不是介绍TLP和ER本身,因此TLP和ER的详细内容请翻前文。
在TLP与拥塞控制的交互中有几个点需要注意
1、TLP触发的重传后,TCP仍然处于Open状态,TLP重传也不会更新lost_out等状态变量,TLP重传发出的是探测报文并不是因为当前确定丢包而重传。
2、TLP与ER/FACK是相互组合的,TLP触发的FACK重传与之前介绍的FACK下快速恢复一致。TLP和ER的耦合更深一些,TLP只能触发延迟ER,而ER定时器超时,延迟ER重传将TCP切换到Recovery状态的时候并不会更新cwnd,但是同样会更新prior_ssthresh=max(ssthresh,3/4*cwnd), ssthresh=max(cwnd/2,2),prior_cwnd=cwnd,prr_delivered=0, prr_out=0, high_seq=snd.nxt,cwnd不变。但是随后切换到Recovery状态后cwnd的更新流程就与之前文章介绍的一致了。
我们还要额外说一下TLP的loss dection,在重传部分介绍TLP的时候,提到过TLP的丢包探测,TLP在发出loss probe报文的时候,是假设当前没有发生拥塞的,即没有丢包,TCP的状态继续停留在Open态。因而TLP需要一种方法来检测是否真的发生了丢包,当检测到真的发生了丢包的时候,进行拥塞窗口的调整。当TLP发出的loss probe报文重传的TCP数据包时候,会记录一个状态变量tlp_high_seq=snd.nxt,tlp_high_seq这个字段在TCP进入Recovery、CWR或者RTO超时场景下都会重置为0。当TLP收到ACK确认包的时候,会按照下面的流程进行loss dection:
1、当tlp_high_seq==0,或者acknumber<tlp_high_seq时候,结束处理,不再执行下面其他步骤。
2、如果这个ACK报文带有DSACK信息,那么说明原始报文和TLP重传报文都到达了对端,更新tlp_high_seq=0,结束处理,不再执行下面其他步骤。
3、如果acknumber>tlp_high_seq,说明原始传输的报文或者TLP重传报文有丢包,因此需要调整拥塞窗口。首先先初始化拥塞窗口削减过程,设置tlp_high_seq=0, high_seq=0, cwnd_cnt=0, prr_delivered=0, prr_out=0, ssthresh=max(cwnd/2,2),临时把TCP的拥塞状态设置为CWR然后进行CWR状态下的拥塞削减结束过程,更新cwnd=ssthresh,最后在根据当前sacked_out等情况决定是切换到Open状态或者是Disorder状态,结束处理,不再执行下面其他步骤。
4、如果这个ACK报文没有传输TCP数据(pure ACK),而且ack number或者SACK块没有确认新数据,也不是窗口更新消息,(这个ACK称呼为TLP dup ACK),说明原始报文和TLP重传报文都到达了对端,更新tlp_high_seq=0。
5、如果上面的条件都不满足,那么TLP结束对这个ACK的处理,等待随后的ACK。
如果不理解上面的这个loss dection流程,那么可以参考之前重传部分TLP的文章或者TLP的官方文档,或者参考下面的示例来理解。
二、wireshark示例
1、TLP&增强ER与拥塞控制
在执行本示例前,如下设置TCP参数
******@Inspiron:~$sudo ip route add local 127.0.0.2 dev lo congctl reno initcwnd 3 ssthresh lock 20 #参考本系列destination metric文章
******@Inspiron:~$ sudo ethtool -K lo tso off gso off #关闭tso gso以方便观察cwnd变化
业务场景:server端与client建立连接后,先休眠1000ms,接着以3ms为间隔连续发送5个数据包,其中No10和No11这两个数据包丢失,以触发loss probe及增前ER,client对于收到的每个数据包都会回复一个ACK确认包,最终TCP的交互如wireshark截图所示。
No1-No13:不解释了,最终收到No13确认包后, ssthresh=20, cwnd=6,cwnd_cnt=0, packets_out=2, sacked_out=0, lost_out=0, retrans_out=0, fackets_out=0,server端处于Open状态,PTO定时器定时时间大约为100ms。
No14:PTO定时器超时,触发loss probe,重传最后发出的一个数据包(即No11)。注意这里虽然是tcp重传,但是并不会更新lost_out等参数,server端TCP仍然会停留在Open状态, ssthresh=20, cwnd=6,cwnd_cnt=0, packets_out=2, sacked_out=0, lost_out=0, retrans_out=0, fackets_out=0。重传后设置RTO定时器,RTO超时时间大约为250ms。
No15:No15是client收到No14数据包后回复的ACK确认包,通过SACK选项确认了No14报文,更新sacked_out=1,fackets_out=2。此时packets_out=2<4,且缓存中没有待发送数据,因此满足触发延迟ER的条件,取消RTO定时器并启动ER定时器,定时时间为RTT/4,大约为13ms。接着因为收到dup ACK,server端TCP从Open状态切换到Disorder状态。
No16:ER定时器超时,重传No10报文,server端TCP从Disorder状态切换到Recovery状态,注意这里ER重传触发TCP进入Disorder状态的时候,只会更新prior_ssthresh=max(ssthresh,3/4*cwnd)=20, ssthresh=max(cwnd/2,2)=3, prior_cwnd=cwnd=6,prr_delivered=0, prr_out=0, high_seq=251,而cwnd在触发ER重传的时候并不会更新,这是与之前介绍的FACK、SACK、SACK关闭场景下的触发的快速重传的重要区别。除了ER重传进入Recovery状态时候初始化与之前介绍的快速重传不一样外,在进入Recovery状态后的各种处理都是一样的了。
No17:server端收到对应No16的ACK确认包,同时这个确认包的ack number=251=high_seq,此时SACK处于打开的状态,因此更新cwnd=ssthresh=3,TCP从Recovery状态切换到Open状态,接着进行reno的拥塞避免过程,更新cwnd_cnt=2。
2、TLP Loss Detection与拥塞控制
在执行本示例前,如下设置TCP参数
******@Inspiron:~$sudo ip route add local 127.0.0.2 dev lo congctl reno initcwnd 3 ssthresh lock 20 #参考本系列destination metric文章
******@Inspiron:~$ sudo ethtool -K lo tso off gso off #关闭tso gso以方便观察cwnd变化
业务场景:server端与client建立连接后,先休眠1000ms,接着以3ms为间隔连续发送5个数据包,其中No11数据包丢失,以触发loss probe,接着休眠353ms写入50bytes的数据。client对于收到的每个数据包都会回复一个ACK确认包,最终TCP的交互如wireshark截图所示。
No1-No14:这个过程不解释了,注意No6-No14报文一直在重设TLP定时器,server在收到No14报文后,发现当前packets_out=1,因此更新PTO =max(2*SRTT, 1.5*SRTT+WCDelAckT)≈275,PTO=min(PTO, RTO)≈250,因此No14后设置PTO定时器定时时间约为250ms, ssthresh=20, cwnd=7,cwnd_cnt=0, packets_out=1, sacked_out=0, lost_out=0, retrans_out=0, fackets_out=0,server端TCP处于Open状态。
No15:PTO定时器超时后触发尾包重传,即No15,TLP超时触发的尾包重传是假设当前没有发生网络拥塞的,因此并不会将TCP切换到Loss状态或者Recovery状态,也不会更新lost_out字段,发出No15后, ssthresh=20, cwnd=7,cwnd_cnt=0, packets_out=1, sacked_out=0, lost_out=0, retrans_out=0, fackets_out=0,tlp_high_seq=251,server端TCP处于Open状态。
No16:server端休眠唤醒后,进行一次write操作,写入50bytes的数据,更新packets_out=2。
No17:client收到No15后,回复一个确认包,server收到No17后首先更新packets_out=1。这个确认包的acknumber=251,根据概述里面的流程描述,TLP并不会处理这个ACK确认包,而是会等待下一个ACK。接着进行reno的慢启动处理,更新cwnd=8。最终 ssthresh=20, cwnd=8,cwnd_cnt=0, packets_out=1, sacked_out=0, lost_out=0, retrans_out=0, fackets_out=0,tlp_high_seq=251,server端TCP处于Open状态
No18:client收到No16后回复No18,server端收到No18后更新packets_out=0,TLP收到这个ACK报文后,发现满足概述里面ACK处理流程的第3步骤,因此更新tlp_high_seq=0,ssthresh=max(cwnd/2,2)=4,cwnd=ssthresh=4。最终ssthresh=4, cwnd=4,cwnd_cnt=0, packets_out=0, sacked_out=0, lost_out=0, retrans_out=0, fackets_out=0,tlp_high_seq=0,server端TCP处于Open状态。
这里假如No11没有丢包,而只是RTT时延突然变大导致server端同样触发TLP流程,那么server端应该会首先收到一个类似No17的报文(client对No11的确认包),TLP不处理这个ACK报文,然后会在收到一个TLP dup ACK(client对于No15的确认包),TLP按照概述里面的第4步更新tlp_high_seq=0,因而也就不会触发ssthresh和cwnd的削减过程。
补充说明:
1、延迟ER处理tcp_resume_early_retransmit
2、TLP ACK处理tcp_process_tlp_ack
TCP系列51—拥塞控制—14、TLP、ER与拥塞控制的更多相关文章
- TCP系列24—重传—14、F-RTO虚假重传探测
一.虚假重传 在一些情况下,TCP可能会在没有数据丢失的情况下初始化一个重传,这种重传就叫做虚假重传(Spurious retransmission).发生虚假重传的原因可能是包传输中重排序.传输中发 ...
- TCP系列46—拥塞控制—9、SACK下的快速恢复与Limited transmit
一.概述 1.SACK下的特殊处理过程 SACK下的拥塞控制处理是linux中拥塞控制的实现依据,再次强调一遍RFC6675的重要性,linux中拥塞控制主体框架的实现是与RFC6675一致的,所以如 ...
- TCP系列20—重传—10、早期重传(ER)
一.介绍 在前面介绍thin stream时候我们介绍过有两种场景下可能不会产生足够的dup ACK来触发快速重传,一种是游戏类响应交互式tcp传输,另外一种是传输受到拥塞控制的限制,只能发送少量TC ...
- TCP系列01—概述及协议头格式
一.TCP简单介绍 我们经常听人说TCP是一个面向连接的(connection-oriented).可靠的(reliable).字节流式(byte stream)传输协议, TCP的这三个特性该怎么 ...
- 【图解】你还在为 TCP 重传、滑动窗口、流量控制、拥塞控制发愁吗?看完图解就不愁了
每日一句英语学习,每天进步一点点: 前言 前一篇「硬不硬你说了算!近 40 张图解被问千百遍的 TCP 三次握手和四次挥手面试题」得到了很多读者的认可,在此特别感谢你们的认可,大家都暖暖的. 来了,今 ...
- 【Lucene3.6.2入门系列】第14节_SolrJ操作索引和搜索文档以及整合中文分词
package com.jadyer.solrj; import java.util.ArrayList; import java.util.List; import org.apache.solr. ...
- 深入浅出图解【计算机网络】 之 【TCP可靠传输的实现2: 超时重传+拥塞控制】
[前言]上一篇文章介绍了关于TCP的基础知识,以及建立(释放)连接和滑动窗口的概念. 本篇文章将延续上一篇的思路,继续介绍TCP实现可靠传输的机制. 超时重传 上一篇文章里介绍过TCP采用停止等待协议 ...
- TCP系列05—连接管理—4、TCP连接的ISN、连接建立超时及TCP的长短连接
一.TCP连接的ISN 之前我们说过初始建立TCP连接的时候的系列号(ISN)是随机选择的,那么这个系列号为什么不采用一个固定的值呢?主要有两方面的原因 防止同一个连接的不同实例(di ...
- TCP系列48—拥塞控制—11、FRTO拥塞撤销
一.概述 FRTO虚假超时重传检测我们之前重传章节的文章已经介绍过了,这里不再重复介绍,针对后面的示例在说明两点 1.FRTO只能用于虚假超时重传的探测,不能用于虚假快速重传的探测. 2.延迟ER重传 ...
随机推荐
- Jquery 批量操作标签属性
$("[id*='Custom']").removeAttr("disabled")
- STM32 SIM800C SIM868 连接OneNet 以及远程控制流程详解
Onenet控制继电器教程 本文基于STM32物联网开发版:https://item.taobao.com/item.htm?spm=a1z38n.10677092.0.0.29e71debNLqzW ...
- 20155222 卢梓杰 myod
20155222 卢梓杰 myod 复习c文件处理内容 编写myod.c 用myod XXX实现Linux下od -tx -tc XXX的功能 main与其他分开,制作静态库和动态库 编写Makefi ...
- # 20155236 2016-2017-2 《Java程序设计》第二周学习总结
20155236 2016-2017-2 <Java程序设计>第二周学习总结 教材学习内容总结 对于类型.变量.运算符.流程控制等等的学习.在其中包含着基本的语法元素,还有基本的逻辑语句. ...
- mysql的启动,停止与重启
启动mysql:方式一:sudo /etc/init.d/mysql start 方式二:sudo start mysql方式三:sudo service mysql start 停止mysql:方式 ...
- 【JUC源码解析】ConcurrentLinkedQueue
简介 ConcurrentLinkedQueue是一个基于链表结点的无界线程安全队列. 概述 队列顺序,为FIFO(first-in-first-out):队首元素,是当前排队时间最长的:队尾元素,当 ...
- 查询数据库所有表和字段及其注释(mysql)
#查询某个库所有表 select * from information_schema.TABLES where table_schema = '数据库' #查询某个库所有表的字段 select * f ...
- MyBatis.Net 配置
假设我们现在有这样的需求,要对学生信息进行管理 学生表有要以下要求 字段名称 数据类型 说明 stuNo 字符 学号,该列必填,为主键递增 stuName 字符 学生姓名,该列必填,要考虑姓氏可能是两 ...
- 180727-时序数据库InfluxDB之备份和恢复策略
influxdb 备份与恢复 参考: influxdb backup and restore 环境: influxdb v1.6.0 使用influx自动的控制台进行 I. 备份 备份命令 influ ...
- PHP精确到毫秒秒杀倒计时实例
精确到毫秒秒杀倒计时PHP源码实例,前台js活动展示倒计时,后台计算倒计时时间.每0.1秒定时刷新活动倒计时时间. PHP: // 注意:php的时间是以秒算.js的时间以毫秒算 // 设置时区 da ...