在TCP的演进过程中,出现了很多优秀的思想和算法,以实现网络传输过程中,在公平竞争性的前提下,尽可能地利用带宽资源。本文介绍TCP发展过程中出现的几种拥塞控制算法。
需要解决的问题:检测、控速、重传
公平性是在发生拥塞时各源端(或同一源端建立的不同TCP连接或UDP数据报)能公平地共享同一网络资源(如带宽、缓存等)。处于相同级别的源端应该得到相同数量的网络资源。产生公平性的根本原因在于拥塞发生必然导致数据包丢失,而数据包丢失会导致各数据流之间为争抢有限的网络资源发生竞争,争抢能力弱的数据流将受到更多损害。因此,没有拥塞,也就没有公平性问题。
TCP层上的公平性问题表现在两方面:
(1)面向连接的TCP和无连接的UDP在拥塞发生时对拥塞指示的不同反应和处理,导致对网络资源的不公平使用问题。在拥塞发生时,有拥塞控制机制的TCP会按拥塞控制步骤进入拥塞避免阶段,从而主动减小发送到网络的数据量。但对无连接的数据报UDP,由于没有端到端的拥塞控制机制,即使网络出现了拥塞,也不会减少向网络发送的数据量。结果遵守拥塞控制的TCP数据流得到的网络资源越来越少,没有拥塞控制的UDP则会得到越来越多的网络资源。
(2)TCP连接之间也存在公平性问题。产生问题的原因在于使用了不同的拥塞控制算法,一些TCP在拥塞前使用了大窗口尺寸,或者它们的RTT较小,或者数据包比其他TCP大,这样它们也会多占带宽。
1)慢启动;2)拥塞避免;3)拥塞发生,快重传;4)快速恢复。
因为Reno等算法是后续算法的基础,这里详细的描述下Reno算法的过程。
(1)慢热启动算法 – Slow Start
(2)拥塞避免算法 – Congestion Avoidance
当cwnd >= ssthresh时,就会进入“拥塞避免算法”。算法如下:
(3)拥塞状态算法 – Fast Retransmit
Tahoe是等RTO超时,FR是在收到3个duplicate ACK时就开启重传,而不用等到RTO超时。拥塞发生时:
(4)快速恢复 – Fast Recovery
Reno算法以其简单、有效和鲁棒性,应用最广泛。该算法所包含的慢启动、拥塞避免和快速重传、快速恢复机制,是现有的众多算法的基础。
从Reno运行机制中很容易看出,为了维持一个动态平衡,必须周期性地产生一定量的丢失,再加上AIMD机制--减少快,增长慢,尤其是在大窗口环境下,由于一个数据报的丢失所带来的窗口缩小要花费很长的时间来恢复,这样,带宽利用率不可能很高且随着网络的链路带宽不断提升,这种弊端将越来越明显。另外,丢包并不一定是网络拥塞,可能是网络常态,但是基于丢包的拥塞控制并不能区分。
vegas通过对RTT的非常重的监控来计算一个基准RTT。然后通过这个基准RTT来估计当前的网络实际带宽,如果实际带宽比我们的期望的带宽要小或是要多的活,那么就开始线性地减少或增加cwnd的大小。
中间路由器缓存数据导致RTT变大,认为发生拥塞;RTT不公平性,当不同的数据流对网络瓶颈带宽进行竞争时,具有较小RTT的TCP数据流的拥塞窗口增加速率将会快于具有大RTT的TCP数据流,从而将会占有更多的网络带宽资源。
在发送端做带宽估计,当探测到丢包时,根据带宽值来设置拥塞窗口、慢启动阈值。 那么,这个算法是怎么测量带宽的?每个RTT时间,会测量一次带宽,测量带宽的公式很简单,就是这段RTT内成功被ACK了多少字节。Westwood会根据RTT变化来判断丢包是否是网络拥塞造成的,还是网络常态的丢包。如果时延变化不明显,就认为是非网络拥塞,此时cwnd减少的比较小。
BIC-TCP是Linux 2.6.18默认拥塞控制算法,依赖丢包条件触发。BIC-TCP认为TCP拥塞窗口调整的本质就是找到最适合当前网络的一个发送窗口,为了找到这个窗口值,TCP采取的方式是(拥塞避免阶段)每RTT加1,缓慢上升,丢包时下降一半,接着再来慢慢上升。BIC-TCP的提出者们看穿了事情的本质,其实这就是一个搜索的过程,而TCP的搜索方式类似于逐个遍历搜索方法,可以认为这个值是在1和一个比较大的数(large_window)之间,既然在这个区间内需要搜索一个最佳值,那么显然最好的方式就是二分搜索思想。
BIC-TCP就是基于这样一个二分思想的:当出现丢包的时候,说明最佳窗口值应该比这个值小,那么BIC就把此时的cwnd设置为max_win,把乘法减小后的值设置为min_win,然后BIC就开始在这两者之间执行二分思想--每次跳到max_win和min_win的中点。
BIC-TCP 算法仿真曲线
BIC也具备RTT的不公平性。RTT小的连接,窗口调整发生的速度越快,因此可能更快的抢占带宽。
CUBIC在设计上简化了BIC-TCP的窗口调整算法,在BIC-TCP的窗口调整中会出现一个凹和凸(这里的凹和凸指的是数学意义上的凹和凸,凹函数/凸函数)的增长曲线,CUBIC使用了一个三次函数(即一个立方函数),在三次函数曲线中同样存在一个凹和凸的部分,该曲线形状和BIC-TCP的曲线图十分相似,于是该部分取代BIC-TCP的增长曲线。另外,CUBIC中最关键的点在于它的窗口增长函数仅仅取决于连续的两次拥塞事件的时间间隔值,从而窗口增长完全独立于网络的时延RTT,使得连接之间保持良好的RRTT公平性。
来看下具体细节:当某次拥塞事件发生时,Wmax设置为此时发生拥塞时的窗口值,然后把窗口进行乘法减小,乘法减小因子设为β,当从快速恢复阶段退出然后进入到拥塞避免阶段,此时CUBIC的窗口增长开始按照“凹”式增长曲线进行增长,该过程一直持续直到窗口再次增长到Wmax,紧接着,该函数转入“凸”式增长阶段。该方式的增长可以使得窗口一直维持在Wmax附近,从而可以达到网络带宽的高利用率和协议本身的稳定性。
CUBIC窗口的增长函数:W(t) = C * (t-K)3 + Wmax, 其中C和β为常量。
t为当前时间距上一次窗口减小的时间差,而K就代表该函数从W增长到Wmax的时间周期。
通俗一点讲,假如我们知道了Wmax,那么CUBIC的核心思想就是需要在连续两次拥塞期间执行完上面的三次函数增长曲线,
BBR通过实时计算带宽和最小RTT来决定发送速率pacing rate和窗口大小cwnd。完全摒弃丢包作为拥塞控制的直接反馈因素。
在不拥塞的前提下提高吞吐量
只有两个状态,慢启动状态slow start(SS),拥塞避免状态congestion avoidance(CA)
一开始的阈值ssthresh默认为64k字节。
过程:
超时和发生三个冗余ACK的操作是基本一样的,区别是超时的话就超时重传超时的段,发生三个冗余ACK的话就快速重传三个冗余ACK的段。
Tahoe算法的问题就是在发生三个冗余ACK时,强制拥塞窗口变成1个mss,代价比较大。因为没有发生超时,说明网络还有通讯能力;而发生三个冗余ACK,代表网络能正常接受丢失的mss的后三个。需要改进,在Tahoe算法基础上增加快速恢复的阶段,就有了Reno算法
三个状态,慢启动状态slow start(SS),拥塞避免状态congestion avoidance(CA),快恢复状态fast recovery(FR)
无论是在慢启动状态(SS)还是拥塞避免状态(CA),只要发生三个冗余ACK,快速重传,cw减半(注意不是变成1了),阈值等于cw,进入快恢复状态,在快恢复状态下有三个情况:
Tahoe和Reno总结和区别
区别
Reno的存在的问题,适合单个段丢失的情况。但是经常性拥塞时,快速重传完后可能会导致后续的段超时,从而进入ss阶段,使得cw降到1。
New Reno算法改进:
New Reno存在的问题:效率低。一个RTT间隙里面发来一个部分确认PACK,那就发送一个丢失的段。
选择性确认,给定一些标记, 一个RTT可以重传丢失段
使用pipe和ScoreBoard,把什么时候发(pipe
TCP是累计确认,没有tcp option的话,tcp头部长度为20B/4=5
SACK选择确认,在tcp option标出乱序被接受的段
因此通过这个方法,接收方可以表述乱序段被接受的情况
发送方接到SACK后,在ScoreBoard计分板中存放需要重发的段的序列,在FR阶段重传(CW允许)
过程:
先重发计分板中丢失的段,再发新段
收到确认分为三种,是否为冗余ACK,是否在SACK选项中,是否为PACK新段得到确认,是否为RACK恢复ACK,组合成5种情况。
有两种情况:
遇到的问题:Reno在CA阶段,线性加1过于保守,不利于吞吐量的提升。(拥塞控制的目的是在在不拥塞的前提下提高吞吐量)
快速定位计算出窗口的最大值
Explicit Congestion Notifacation,网络辅助信息拥塞控制
Tahoe和Reno都是靠事件来判断是否拥塞,比如定时器超时,收到三个冗余ACK。
上述两个算法都是通过端自身来统计和计算信息的。那么能否由网络反馈一些信息,那就需要修改TCP/IP协议。
IP数据报中两个标志位:
TCP段中两个标志位:
过程:
在网络中经过拥塞的路由器:
源主机得到ECE的反馈,降速
ECN存在的问题:
Reno类算法的问题:
事件发生顺序:冗余ACK事件 ->细颗粒度的超时事件 ->3个冗余ACK事件 ->细颗粒度的超时事件
过程:
BaseRTT是最小的RTT
Reno算法在慢启动状态下是一个RTT倍增cw,vegas是两个RTT倍增cw,温和一些
重传的时机
vegas存在的问题,导致互联网使用的不多:
BtlBW(Bottleneck link) and RTT based Congestion Control
模型概述:
模型会出现的三种状态
带宽受限:pipe充满,瓶颈链路占满,有数据段在排队,但是buffer能承受这个队伍长度。出现拥塞。
缓冲受限:pipe充满,buffer充满。出现丢包。
最核心问题:瓶颈链路带宽BtlBW和往返时延RTT不可同时测量。测量RTT时pipe需要处于轻载状态。但是测量BtlBW时pipe需要处于充满状态。
BtlBW,瓶颈链路带宽。RTT,往返时延。BDP
资料参考: