4. TCP拥塞控制
4.1. 源算法
| 拥塞控制源算法 | 描述 |
|---|---|
| Tahoe-TCP | 慢启动、拥塞避免、快速重传三算法.(早期较为普遍采用的版本)paper: congest avoid.pdf |
| Reno-TCP | RFC5681加上快速恢复. |
| NewReno-TCP | 引入了部分确认和全部确认的概念. |
| SACK-TCP | 规范了TCP中带选择的确认消息. |
| Vegas-TCP | 采用带宽估计,缩短了慢启动阶段的时间,源拥塞避免 /net/ipv4/tcp_vegas.h, /net/ipv4/tcp_vegas.c |
4.1.1. 三个拥塞控制机制
慢启动
加法式增加/乘法式减少拥塞窗口
快速重发和快速恢复
4.1.1.1. 慢启动
线性增加发送量
对网络接近满载来说是一个正确的方法;
但对从零开始起步的连接来说时间又太长;
- Congestion Window是发送方设置的一个变量
- 指数式增加CW,而不是线性。
- 开始,源把CW置为1(一个包);
- 然后每收到一个ACK,将CW*2
- 当该包的ACK到达后,TCP可以发2个包;
- 当收到2个ACK后,CW*2,发4个包,故每个RTT内包数翻一倍
- 如果发生丢包后,,源端再次进入慢启动;当超过一个发送方设置的阈值:ssthresh(slowstart threshold),CW会变为线性增加,这其实是一种拥塞避免
4.1.1.2. 拥塞窗口和可发送窗口
Congestion Window (CW)
源端TCP为每个连接维护的一个状态变量;
限制在给定时间内容许传输的数据量,慢启动的最大值也受到CongestionWindow影响
容许的最大未确认字节数就是现在的CongestionWindow和AdvertisedWindow小的那个
MaxWindow = MIN(CongestionWindow, AdvertisedWindow)
可以发送的窗口大小,为可能新增的未确认字节数:
EffectiveWindow = MaxWindow - (LastByte - LastByteAcked)
但发生拥塞的时候一般CW < EffectiveWindow
4.1.1.3. 加法式增加/乘法式减少拥塞窗口
TCP源慢启动之后:
如果超过ssthresh,可能会导致当拥塞程度上升就线性CW
当拥塞程度下降(收到ACK)时,就增加CW
上述二者合在一起就叫:加法式增加/乘法式减少 AIMD
4.1.1.4. 拥塞感知
观察主要原因:
包未交付,并导致duplicated ACK或超时,判定为拥塞丢包!
由于传输错误丢包是很少的!
TCP把收到1)duplicated ACK(对已经确认的字节再次确认),2)超时 两种现象解释为拥塞的信号
Tahoe TCP不区分这两种情况
sshthresh = cwnd /2
cwnd 重置为 1
进入慢启动过程
这就是乘法减少机制的一部分
Reno TCP超时的策略不变,但是面对duplicated ACK的实现是:
进入拥塞避免
cwnd = cwnd /2
ssthresh = cwnd
进入快速恢复算法——Fast Recovery
4.1.1.5. 快速重传和快速恢复
Tahoe引入快速重传,Reno引入快速恢复
每次接收方收一个数据包
接收方响应一个ACK;(早先规定,后来优化)
当包到达失序,TCP因为较早的数据还没有到达,也不能应答含有这些包的数据;
TCP发送它上次发送了的那个相同的ACK
相同ACK的第二次发送称着Duplicate ACK,
当发送方看到重复ACK,知道对方收到了一个失序包,这说明这个ACK序号后面的包丢失了
实际情况中
发送方TCP等到3个Duplicate ACK后就重发丢失的包;即快速重传,比等待报文超时要快
4.1.1.5.1. 快速恢复
当快速重传同时快速恢复(Duplicated ACK)
Fast Recovery算法如下:
- 把ssthresh设置为cwnd的一半
- 把cwnd再设置为等于ssthresh的值,不再从1开始(具体实现有些为ssthresh+3,因为三个重复的ACK,表示有三个报文离开网络了,可以新增三个)
- 重新进入拥塞避免阶段,再收到重复ACK,拥塞窗口+1(不会加剧拥塞,因为有ACK报文,说明可以增加发送)
- 收到新的报文ACK时候,ssthresh变为第一步的大小(说明所有丢失的报文都收到了,可以快速恢复)
5. 拥塞避免
5.1. DECbit
基本思想:
把拥塞任务更均匀分担在路由器和端节点之间
每个路由器监视它正在经历的负载,在拥塞将要发生时明确地通告端节点
通过设置流过路由器包中的二进制拥塞位来实现,目端把这拥塞位拷贝进ACK报文并返送回源端
源端调整自己的发送速率以避免拥塞,设置标志位告诉接收方,已经处理了拥塞
且平均队列长度大于或等于1时,路由器就设置包头中的拥塞位
测量平均队列长度的时间间隔是最近的忙期+空闲期+当前忙期(R传输时为忙,不传输时为闲) 路由器计算曲线下面积并除以时间间隔得到平均队列长度
源主机的工作
记录有多少包导致其在路由器中记下拥塞位
维护一个拥塞窗口,并观察最近等价窗口值导致设置拥塞的比例,
若比例<50%,源增加拥塞窗口1个包
若比例>=50%,源减拥塞窗口至原值0.875倍
5.2. ECN显式拥塞控制
一种拥塞通知方式;
标记包而不是丢弃包,减少超时长度和重传次数
算法1:源观察到随R中包队列增大,后继包的RTT都会增加,如每隔2个RTT,检测当前RTT是否大于迄今所测RTT的最大最小的平均值,若大则把拥塞窗口减少1/8
算法2:是否改变当前拥塞窗口根据RTT和窗口2个因素的变化而决定,每隔2个RTT,计算(CurrentWindow-OldWindow)* (CurrenRTT-OldRTT),若>0 则窗口减少1/8,若≤0 则窗口加1最大包长,每次调整使其围绕最佳点震动
算法3:拥塞前发送率接近平缓.每个RTT内将窗口加1个包,同时将获得的吞吐量与加1个包前的吞吐量比较:若差小于只有1个包传输时所得吞吐量的1/2,吞吐量增加不明显,说明有可能发生拥塞,则窗口减1.通过计算未发完字节数/RTT得吞吐量
5.3. TCP Vegas
类似算法3查看吞吐率或发送率的变化,不同的是,它将测量的吞吐量变化率与理想吞吐量变化率比较。
5.4. 随机早检测-RED
Random Early Detecation
与DECbit相似,都是在每个Router上监视自己队列长度
Early
R在其缓冲被完全填满前就丢少量包,使源方减慢发率
RED与DECbit的不同
RED不明确发送拥塞通知到源,而是通过丢弃一个包来隐含已发生拥塞。源会被随后的超时或重复ACK所提示,这可与TCP配合使用
决定何时丢弃及丢弃哪个包的细节上不同,对FIFO,不是等队列完全排满后将每个刚到达包丢弃,而是当队列超过某阈值时按某概率丢弃到达包