一、基础算法
经典算法
-
慢启动
IW = 1 SMSS,每接收到一个好的ACK响应,会以min(N, SMSS)来增加cwnd值,这里的N是指在未经确认的传输数据中能通过这一“好的ACK”确认的字节数,这使得cwnd呈指数增长。 -
拥塞避免
新的cwnd = cwnd + SMSS * SMSS / cwnd,这使得cwnd呈线性增长。 -
慢启动和拥塞避免的选择
当cwnd < ssthresh,使用慢启动;当cwnd > ssthresh,使用拥塞避免。
ssthresh记住上一次“最好的”操作窗口估计值,也就是TCP最有窗口估计值的下界。
ssthresh初始值可以设置为任意;
当超时重传或快速重传发生时,ssthresh发生如下改变:
ssthresh = max(FlightSize / 2, 2 * SMSS) 或
ssthresh = max(min(cwnd, awnd)/ 2, 2 * SMSS) -
标准TCP(Tahoe、Reno)
cwnd = IW (初始,ssthresh至少为awnd)
cwnd += SMSS (慢启动)
cwnd += SMSS * SMSS / cwnd (cwnd > ssthresh时,拥塞避免)快速重传和快速恢复:
(1)ssthrsh更新为在外数数据或cwnd的一半;
(2)将cwnd设为(ssthresh + 3 * SMSS);
(3)每收到一个重复ACK,cwnd值暂时增加1 SMSS;
(4)收到一个好的ACK(区别于New Reno,这里好的指局部ACK),将cwnd设置为ssthresh。
NewReno(RFC2581)
-
经典算法的问题:当一个传输窗口出现多个数据包丢失时,一旦其中一个重传成功,收到Partial ACK,快速恢复就会停止,拥塞窗口停止膨胀,并将其减小为特定值,这种做法可能导致在重传计时器超时前,传输通道处于空闲,因为网络中没有足够的包在传,无法触发快速重传。
-
解决方式:
(1)对快速恢复作出改进,记录上一个数据传输窗口的最高序列号为恢复点,从而减少重传超时的发生。
(2)每接收一个ACK,cwnd值暂时增加1 SMSS,而非必须是重复ACK。
SACK算法(RFC6675)
-
定义:
HighACK:累计ACK确认的最大序列号。HighData:已发送的最大序列号。
HighRxt:重传的最大序列号。
Pipe:对在外数据的估计值。
IsLost(SeqNum):如果DupThresh个比SeqNum高的不连续SACK到达发送端,或者DupThresh*SMSS字节比SeqNum高的SACK到达发送端,则证明SeqNum已经丢失。
SetPipe():该函数遍历HighAck和HighData之间的序列号区间,根据下列原则确认在外数据的数量:
(1)如果IsLost返回false,即该报文段未丢失,则Pipe增加;
(2)如果SeqNum <= HignRxt,则Pipe增加,即当发生重传时,Pipe需要被增加;
(3)已被SACK的序