一.概述 这里主要简单分析一个丢包重传并恢复的场景,通过不同的设置让这个相同的场景分别触发RACK重传和前向重传,通过对比说明以下问题: Forward Retransmit可以产生只有重传标记的数据包,也可以产生同时具有重传标记和SACK标记的数据包,注意这里说的这些数据包是没有Lost标记的,这是前向重传与之前介绍的快速重传及其变种的差异,进而会对in_flight的统计产生影响. Recovery状态,FACK会利用一个dup ACK来前向标记丢失的数据包. RACK可以利用重传在时间域来…
一.DSACK介绍 RFC2883通过指定使用SACK来指示接收端的重复包(duplicate packet)扩展了RFC2018对SACK选项的定义(SACK选项的介绍和示例参考前面内容).RFC2883建议在收到重复报文的时候,SACK选项的第一个块(这个块也叫做DSACK块)可以用来传递触发这个ACK确认包的系列号,这个就是DSACK(duplicate-SACK)功能.这样允许TCP发送端根据SACK选项来推测不必要的重传.进而利用这些信息在乱序传输的环境中执行更健壮的操作.这个DSAC…
一.虚假重传 在一些情况下,TCP可能会在没有数据丢失的情况下初始化一个重传,这种重传就叫做虚假重传(Spurious retransmission).发生虚假重传的原因可能是包传输中重排序.传输中发生包复制.ACK确认包传输中丢失等等.如果由于链路时延变化或者负载变化等因素导致RTT突然变大等原因,TCP的发送端可能还没收到ACK确认包就已经RTO超时而触发重传,这种重传就叫做虚假超时重传(Spurious retransmission timeouts).虚假超时重传会降低网络性能,其主要由…
一.概述 DSACK下的虚假重传的检测我们之前重传部分的文章已经介绍过了,这里简单说一下拥塞控制部分的实现. linux内部会维护一个undo_retrans状态变量,其值为已经重传的次数减掉被DSACK检测到的虚假重传的次数,例如当前总共重传了5个数据包,DSACK检测到3个虚假重传,那么undo_retrans即为2.undo_retrans初始化为-1,当发生重传的时候,如果undo_retrans为-1那么就更新undo_retrans=1,否则更新undo_retrans=undo_r…
一.概述 这篇文章介绍一下TCP从Recovery状态恢复到Open状态的时候cwnd的更新.我们在tcp重传部分的文章中曾经介绍过虚假重传的概念,Linux在探测到虚假重传的时候就会执行拥塞撤销操作.所谓的拥塞撤销是指撤销虚假的快速重传或者RTO超时重传对拥塞窗口的影响.有多种方法可能会触发拥塞撤销如前面介绍的DSACK和FRTO以及后面要介绍的Eifel算法以及本文介绍的SACK关闭场景下的拥塞撤销,本文先介绍一种SACK关闭场景下的拥塞撤销.首先在介绍几个新的linux状态变量 undo_…
一.RACK概述 RACK(Recent ACKnowledgment)是一种新的基于时间的丢包探测算法,RACK的目的是取代传统的基于dupthresh门限的各种快速重传及其变种.前面介绍的各种基于dup ACK的快速重传算法及其变种通过修改dupthresh门限等手段,有些可以迅速的探测到丢包,有些可以精确的探测丢包,但是没有能同时达到迅速和精确两个目标的算法. RACK基本思想:如果发送端收到的确认包中的SACK选项确认收到了一个数据包,那么在这个数据包之前发送的数据包要么是在传输过程中发…
一.介绍 Tail Loss Probe (TLP)是同样是一个发送端算法,主要目的是使用快速重传取代RTO超时重传来处理尾包丢失场景.在一些WEB业务中,如果TCP尾包丢失,如果依靠RTO超时进行重传会带来比较大的延迟,进而影响用户体验.如果一个TCP连接没有在一段时间内没有收到ACK报文,TLP会强制传输还没有收到ACK确认的报文里面的最后一个报文或者未发送的新报文(传输的这个报文就叫做loss probe).这里强制传输是指loss probe的发送不受到拥塞控制的限制但是同样收到对方通告…
一.介绍 在TCP重传的时候,并没有限制TCP只能重传与初传完全相同的报文段大小,TCP允许执行重组包(repacketization),发送一个更大的TCP报文段,进而增加性能.TCP在重传时候允许重组包同时提供了一种判别虚假重传的方法.在linux中参数/proc/sys/net/ipv4/tcp_retrans_collapse为非0值的时候打开重传重组包功能,为0的时候关闭重传重组包功能. 二.wireshark示例 我们来看两个wireshark示例,这次我们在ubuntu16.04的…
一.概述 forward retransmit相关的内容在RFC6675中有描述,可以参考RFC6675 section 4中NextSeg ()的定义.forward retransmit中文名可以叫做前向重传,我这里简单说一下linux实现上的前向重传 在快速重传(包括快速重传的各种变种)到达Recovery point之前,都会尝试重传标记为lost的数据包,当把标记为lost的数据包重传完毕后,如果同时满足下面几个条件: 1.当前拥塞控制处于Recovery状态,且在尝试重传数据包的时候…
我们之前介绍SACK选项的时候说过,SACK可以把接收端系列号空间的洞反映给发送端,因此发送端可以更充分的理解接收端的情况,而进行更好的重传恢复过程.这种过程有时候也叫做advanced loss recovery. 一.数据接收端SACK行为 我们通过一个wireshark示例来说明接收端的SACK行为:   如上图,为了方便在info列中查看SACK信息,我把info列中TSopt的信息隐藏了,同时把源地址列和目的地址列一起隐藏了.client依次发送P1(1-6).P2(25-30).P3…
一.快速重传介绍 按照TCP协议,RTO超时重传是一个非常重要的事件,当RTO超时的时候,TCP会同时通过两种方式非常谨慎的降低发送数据包的速率,一种是基于拥塞控制削减发送窗口的大小,另外一个是通过指数回退增加每次RTO超时的时间(即karn算法的第二部分).所以RTO超时后有可能会导致网络容量的利用不足. 最开始我们介绍tcp重传的时候就介绍过TCP还有另外一种重传方式--快速重传.快速重传是RFC5681定一个的一个过程.快速重传不依赖定时器的超时,而是依靠ACK确认包来进行重传.使用快速重…
一.Karn算法 在RTT采样测量过程中,如果一个数据包初传后,RTO超时重传,接着收到这个数据包的ACK报文,那么这个ACK报文是对应初传TCP报文还是对应重传TCP报文呢?这个问题就是retransmission ambiguity problem.当没有使用TSOPT选项,单纯的ACK报文并不会指示对应初传包还是重传包,因此就会发生这个问题. Karn算法指出,当RTO超时重传发生时候,我们不能依据这个TCP报文的ACK信息来更新RTT估计值.这是Karn算法的第一部分,如之前所说这个是R…
从上一篇示例中我们可以看到在TCP中有一个重要的过程就是决定何时进行超时重传,也就是RTO的计算更新.由于网络状况可能会受到路由变化.网络负载等因素的影响,因此RTO也必须跟随网络状况动态更新.如果TCP过早重传,则可能会向网络中注入很多重复报文,如果过晚重传,则在丢包时候则会影响滑窗前行可能会降低网络利用率.因为TCP在接收到数据后会发送累计的ACK number,因此TCP发送某个系列号的报文后,在接收到覆盖此系列号的ACK报文的时候,测量发送和接收之间的时间,这个测量就叫做RTT采样(RT…
一.介绍 在前面介绍thin stream时候我们介绍过有两种场景下可能不会产生足够的dup ACK来触发快速重传,一种是游戏类响应交互式tcp传输,另外一种是传输受到拥塞控制的限制,只能发送少量TCP报文.针对这种场景提出了一个快速重传的改进算法即早期重传(early retransmit,简称ER).按照RFC5827,ER有两种形式一种是基于字节的,一种是基于包的,基于包的ER精度要高于基于字节的ER,linux实现的是基于TCP包的ER,因此我们这里只介绍基于包的ER. ER是在没有新数…
传输数据 在TCP的数据传送状态.非常多重要的机制保证了TCP的可靠性和强壮性.它们包括:使用序号.对收到的TCP报文段进行排序以及检測反复的数据:使用校验和来检測报文段的错误.使用确认和计时器来检測和纠正丢包或延时. 在TCP的连接创建状态,两个主机的TCP层间要交换初始序号(ISN:initial sequence number).这些序号用于标识字节流中的数据,而且还是相应用层的数据字节进行记数的整数.通常在每个TCP报文段中都有一对序号和确认号.TCP报文发送者觉得自己的字节编号为序号,…
[前言]上一篇文章介绍了关于TCP的基础知识,以及建立(释放)连接和滑动窗口的概念. 本篇文章将延续上一篇的思路,继续介绍TCP实现可靠传输的机制. 超时重传 上一篇文章里介绍过TCP采用停止等待协议,即在收到接收方的确认信息后才继续发送下面的数据. 那么如果(在一段时间内)发送方没有收到确认信息,我们便可以认为数据在传输的过程中出了差错,没有顺利传送到接收方.这种情况下,就需要一个"超时重传"的机制了. TCP 每发送一个报文段,就对这个报文段设置一次计时器.只要计时器设置的重传时间…
一.概述 我们之前在SACK关闭场景下的拥塞撤销那篇文章中提到过Eifel探测算法(Eifel Detection Algorithm),最早在介绍DSACK和FRTO的时候我们就有提到过Eifel探测算法.Eifel探测算法是基于TSopt选项中TSV的单调非减特性设计的.简单介绍一下Linux中Eifel探测算法的实现,Linux会在TCP进行第一次重传的时候把重传数据包的TSV记录在状态变量retrans_stamp中,当收到partial ACK的时候,或者收到的Ack报文的ack nu…
一.概述 FRTO虚假超时重传检测我们之前重传章节的文章已经介绍过了,这里不再重复介绍,针对后面的示例在说明两点 1.FRTO只能用于虚假超时重传的探测,不能用于虚假快速重传的探测. 2.延迟ER重传触发的进入Recovery状态时候,并不会立即更新cwnd. 本篇在演示FRTO的同时,还会涉及到ER超时重传.TLP探测.SACK关闭场景下的拥塞撤销,后面或者前面都会有针对这些场景的专门介绍文章. 一.wireshark示例 1.FRTO与ER 我们通过一个示例看一下关闭SACK时候,tcp_s…
一.概述 ECN的相关内容是在RFC3168中定义的,这里我简单描述一下RFC3168涉及的主要内容. 1.AQM和RED 目前TCP中多数的拥塞控制算法都是通过缓慢增加拥塞窗口直到检测到丢包来进行慢启动的,这就会导致数据包在路由器缓存队列堆积,当路由器没有复杂的调度和缓存管理策略的时候,路由器一般简单的按照先进先出(FIFO)方式处理数据包,并在缓存队列满的时候就会丢弃新数据包(drop tail),这种FIFO/drop tail的路由器称为passive路由器,会导致多个TCP流同时检测到…
一.概述 这里的重点是介绍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重传将…
一.概述 1.SACK下的特殊处理过程 SACK下的拥塞控制处理是linux中拥塞控制的实现依据,再次强调一遍RFC6675的重要性,linux中拥塞控制主体框架的实现是与RFC6675一致的,所以如果要理解linux中拥塞控制的实现,强烈建议看一下RFC6675.我这里给出RFC6675中SACK处理的2个关键点,下面的描述实际上不太严谨,严谨定义请参考RFC6675. 1.SACK下对于dup ACK的定义简单说是指反馈了新的SACK信息,也就是说SACK下ack number不同的ACK报…
) return;    delta = ssthresh - in_flight;     prr_delivered += newly_acked_sacked; if (delta < 0) {  //注意下面的除法要向下取整 sndcnt = (ssthresh * prr_delivered + prior_cwnd - 1)/prior_cwnd - prr_out } else if (ack number新确认了之前重传的数据且RACK没有标记重传报文丢失) { sndcnt =…
一.TCP简单介绍 我们经常听人说TCP是一个面向连接的(connection-oriented).可靠的(reliable).字节流式(byte stream)传输协议,  TCP的这三个特性该怎么理解呢? 面向连接:在应用TCP协议进行通信之前双方通常需要通过三次握手来建立TCP连接,连接建立后才能进行正常的数据传输,因此广播和多播不会承载在TCP协议上.(谷歌提交了一个RFC文档,建议在TCP三次握手的过程允许SYN数据包中带数据,即 TFO(TCP Fast Open),目前ubuntu…
在本篇中我们继续上一篇文章wireshark的示例讲解,上一篇介绍了一个综合示例后,本篇介绍一些简单的示例,在读本篇前建议先把上一篇读完,为了节省篇幅,本篇只针对一些特殊的场景点报文进行讲解,不会像上一篇一样对每个报文都进行讲解并随报文更新相关状态变量的值了. 一.wireshark示例 本篇示例的TCP测试仍然设置初始拥塞窗口为3,并关闭TSO.GSO等功能.同时设置wireshark使其不在info列显示TSopt的信息. ******@Inspiron:~$ sudo ip route a…
一.Linux中的慢启动和拥塞避免 Linux中采用了Google论文的建议把IW初始化成了10了.在linux中一般有三种场景会触发慢启动过程 1.连接初始建立发送数据的时候,此时cwnd初始化为10,ssthresh初始化为0x7fffffff,因此会触发慢启动.但是当路由表中有对应的设置的时候,cwnd和ssthresh会被路由表中的设置的值覆盖,有可能连接建立后直接进入拥塞避免阶段. 2.RTO超时进入Loss状态后,此时cwnd初始化为1,ssthresh的值会调用具体拥塞控制算法的回…
在本篇中我们继续上一篇文章wireshark的示例讲解,上一篇介绍了一个综合示例后,本篇介绍一些简单的示例,在读本篇前建议先把上一篇读完,为了节省篇幅,本篇只针对一些特殊的场景点报文进行讲解,不会像上一篇一样对每个报文都进行讲解并随报文更新相关状态变量的值了. 一.wireshark示例 本篇示例的TCP测试仍然设置初始拥塞窗口为3,并关闭TSO.GSO等功能.同时设置wireshark使其不在info列显示TSopt的信息. ******@Inspiron:~$ sudo ip route a…
在这篇文章中我们看一下server端在接收到异常数据系列时的处理,主要目的是通过wireshark示例对这些异常数据系列的处理有一个直观的认识,感兴趣的自行阅读相关代码和协议,这里不再进行详细介绍 在进行下面的测试前,首先如下设置相关的参数,其中window参数指定了到127.0.0.2的tcp连接的最大接收窗口. root@Inspiron:/home/******/tcp12# ip route change local 127.0.0.2 dev lo window 40 一.wiresh…
一.TCP连接的ISN         之前我们说过初始建立TCP连接的时候的系列号(ISN)是随机选择的,那么这个系列号为什么不采用一个固定的值呢?主要有两方面的原因 防止同一个连接的不同实例(different instantiations/incarnations of the same connection)的数据包混淆. 同一个连接的不同实例是怎么回事呢?之前我们说过(源IP.源端口号.目的地址.目的端口号)这个四元组唯一标识一个TCP连接,当一个TCP连接在经历四次挥手关闭时,假如有…
package com.jadyer.solrj; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrServer; import org.apache.solr.client.solrj.SolrServerException;…
Maven学习系列二(1-5) 本文转自 QuantSeven 博客,讲解精炼易懂,适合入门,链接及截图如下 http://www.cnblogs.com/quanyongan/category/471332.html…