万字详文:TCP 拥塞控制详解( 四 )


1.每次收到新的 ACK 后,更新 reo_wnd,其中 rtt_min 为固定时间窗口的 rtt 最小值 。

万字详文:TCP 拥塞控制详解

文章插图
 
2.每当收到一个 ACK 或者 SACK 的时候,更新 rack.xmit_time 。再去遍历发送队列上已经发送但还没有收到确认的数据包(skb),如果满足如下条件,那么标记这个数据包丢了 。
万字详文:TCP 拥塞控制详解

文章插图
 
3.如果没有收到确认,那么就用定时器每个一段时间看看有哪些包丢了,如果满足如下条件,那么把这个 skb 标记为已经丢了:
万字详文:TCP 拥塞控制详解

文章插图
 
注:目前 linux 内核中只实现了第一种判断方法,定时器还没有实现,这样的话就还没有解决对于尾部包丢失的问题 。
3.2.4 乱序检测
乱序检测的目的时探测网络是否发生重排导致的丢包,并以此来更新 dupthresh 值 。只要能收到一个 ACK 或者 SACK,其序列号位于当前已经被 ACK 或 SACK 的数据包最大的序列号之前,就说明网络发生了重排造成了乱序,此时如果涉及的数据包大小大于当前能容忍的网络乱序值,即 dupthresh 值,就说明网络乱序加重了,此时应该更新 dupthresh 值 。之所以保持 dupthresh 的值递增,是考虑其初始值 3 只是一个经验值,既然真实检测到乱序,如果其值比 3 小,并不能说明网络的乱序度估计偏大,同时 TCP 保守地递增乱序度,也是为了让快速重传的进入保持保守的姿态,从而增加友好性 。
万字详文:TCP 拥塞控制详解

文章插图
 
一旦发现 dupthresh 值更新的情形,FACK 的假设便不成立,必须在连接内永久禁用 FACK 算法 。
3.3 Early Retransmit for TCP(ER 机制)要解决的问题: 当无法收到足够的 dupack 时,TCP 标准的 Fast Retransmit 机制无法被触发,只能等待 RTO 超时才能进行丢包的重传 。而 RTO 超时不管是时间等待代价,还是性能损耗代价都很大 。
解决方法: 检测出无法收到足够 dupack 的场景,进而降低 dupack threshold 来触发快速重传 。从而避免等待 RTO 超时重传,对性能造成较大的损耗 。
总结出现 dupack 不够的情况:a. cwnd 较小 b. 发送窗口里大量的数据包都被丢失了 c.在数据发送的尾端发生丢包时
但是,上面各种极端的 case 有共同的特点:m. 无法产生足够的 dupack n.没有新的数据包可以发送进入网络,ER 机制就是在判断条件 m 和 n 都成立后,选择降低触发 Fast Retransmit 的阈值,来避免只能通过 RTO 超时重传的问题 。
3.4 TCP Tail Loss Probe(TLP 算法)ER 算法解决了 dupack 较少时无法触发快速重传的问题,但当发生尾丢包时,由于尾包后没有更多数据包,也就无法触发 dupack 。TLP 算法通过发送一个 loss probe 包,以产生足够的 SACK/FACK 数据包来触发重传 。TLP 算法会在 TCP 还是 Open 态时设置一个 Probetimeout(PTO),当链路中有未被确认的数据包,同时在 PTO 时间内未收到任何 ACK,则会触发 PTO 超时处理机制 。TLP 会选择传输序号最大的一个数据包作为 tail loss probe 包,这个序号最大的包可能是一个可以发送的新的数据包,也可能是一个重传包 。TLP 通过这样一个 tail loss probe 包,如果能够收到相应的 ACK,则会触发 FR 机制,而不是 RTO 机制 。
3.5 伪超时与重传在很多情况下,即使没有出现数据丢失也可能引发重传 。这种不必要的重传称为伪重传,其主要造成原因是伪超时,即过早判定超时,其他因素如包失序、包重复,或 ACK 丢失也可能导致该现象 。在实际 RTT 显著增长,超过当前 RTO 时,可能出现伪超时 。在下层协议性能变化较大的环境中(如无线环境),这种情况出现得比较多 。
TCP 为处理伪超时问题提出了许多方法 。这些方法通常包含检测算法与响应算法 。检测算法用于判断某个超时或基于计时器的重传是否真实,一旦认定出现伪超时则执行响应算法,用于撤销或减轻该超时带来的影响 。检测算法包含 DSACK 、Eifel 检测算法、迁移 RTO 恢复算法(F-RTO) 三种 。
3.5.1 DSACK 扩展DSACK 的主要目的是判断何时的重传是不必要的,并了解网络中的其他事项 。通过 DSACK 发送端至少可以推断是否发生了包失序、 ACK 丢失、包重复或伪重传 。D-SACK 使用了 SACK 的第一个段来做标志,a. 如果 SACK 的第一个段的范围被 ACK 所覆盖,那么就是 D-SACK 。b.如果 SACK 的第一个段的范围被 SACK 的第二个段覆盖,那么就是 D-SACK 。RFC2883]没有具体规定发送端对 DSACK 怎样处理 。[RFC3708]给出了一种实验算法,利用 DSACK 来检测伪重传,响应算法可采用 Eifel 响应算法 。


推荐阅读