本文档的Copyleft归yfydz所有,使用GPL发布,可以自由拷贝,转载,转载时请保持文档的完整性,严禁用于任何商业用途。
msn: [email protected]
来源:http://yfydz.cublog.cn
参考文献: RFC3782,2582
1. 前言 在RFC2581中已经定义了TCP的快速重传(fast retransmit)和快速恢复(fast recovery)算法,也称基本Reno算法,但是该算法的启用仅仅导致一个数据包的重传。因此,当多个数据包从一个数据窗口中丢失并且触发快速重传和快速恢复算法时,问题就会产生。在这种情况下,如果SACK选项可用,TCP发送端在快速恢复期间就有足够的信息来决定重传哪个数据包,不重传哪个数据包。而本文的算法是对不支持使用TCP选择确认(SACK)选项的TCP连接适用。 该算法先在RFC2582中定义,后来在RFC3782中重新定义。 2. 算法描述 在一个窗口内的多个包丢失的情况下,发送方会收到接收方对重传的数据确认(此时已经进入快速重传算法),如果是一个包丢失,接收方确认的是重传算法启动前的所有包,而如果是多个包丢失,则不会确认重传前的所有包,此情况称为部分确认。 NewReno算法和RFC2581中的算法的差异在于在步骤1中引入“恢复(recover)”变量;步骤5中对于部分确认或新的确认;以及在步骤1和步骤6的附加部分中避免多次快速重传处理。 recover变量的初始化值为初始的发送序列号。 NewReno算法处理步骤: 1) 三个重复的ACK确认 第3个重复的ACK确认到达而且发送方未进入快速恢复处理时,检查累计的确认值是否大于 recover变量, 是则转步骤1A,否则转1B: 1A) 调用快速重传: 设置慢启动阈值(slow start threshold, ssthresh)为: ssthresh = max (FlightSize / 2, 2*SMSS) 其中FlightSize表示已经发送但还没有被确认的数据量 然后将发送在最大序列号值保存在recover变量中,转步骤2; 1B) 不调用快速重传: 不进入快速重传和快速恢复处理,不改变ssthresh,不用执行步骤2,3 2) 进入快速重传 重传丢失的包然后设置拥塞窗口cwnd=ssthresh + 3*SMSS,扩大拥塞窗口; 3) 快速恢复 在快速恢复阶段,对于所接收到的每个重复的ACK包,拥塞窗口递增SMSS,扩大拥塞窗口; 4) 快速恢复继续 发送一个数据段,如果新的cwnd和接收端的通知窗口的值允许的话 5) 当一个确认新数据的ACK到达时,此ACK可能是由步骤2中的重传引发的确认,或者是由稍后 的一次重传引起的,分完整确认和部分确认两种情况: 完整确认: 此ACK确认了所有数据的序列号括了recover记录的序列号,则此ACK确认了所有中间丢失的数据 包,此时调整cwnd或者为(1) min(ssthresh, FlightSize + SMSS);或者(2) ssthresh 来缩小 cwnd,结束快速恢复。 部分确认: 如果这个ACK不确认所有并包含到“recover”的数据的话,就产生一个部分ACK。在此种情况 下,重传第一个没有确认的数据段。按确认的新数据量来减小拥塞窗口,如果这个部分确认确认 了至少一个MSS的新数据,则加回一个MSS。如果cwnd的新值允许的话,发送一个新数据段。这个 “部分窗口缩减”试图确定当快速恢复最终结束时,大约ssthresh数量的数据还在向网络中传 送。此情况下不退出快速恢复过程。 对在快速恢复期间第一个到达的部分ACK,也要重设重传定时器。 6) 重传超时 重传超时后,将发送的最大序列号保存在recover变量中,结束快速恢复过程。 3. 结论 NewReno算法的前提是用于不支持SACK的TCP实现,效果比基本Reno算法会好一些,但现在不支持SACK的TCP实现已经很少了,因此显得意义也不是很大了。