TCP-IP详解: RTT和RTO的计算方法

时间:2022-03-04 21:14:14

参考教材:TCP-IP Guide

基本概念

RTT: 发送一个数据包到收到对应的ACK,所花费的时间

RTO: 发送数据包,启动重传定时器,重传定时器到期所花费的时间,称为RTO

对于segment的重传,重传的时间RTO设定是非常重要的,如果设置太短,可能会导致并没有丢包而重传,如果设置太长了,可能因为等待ACK而浪费掉很多时间,牺牲传输的效率。从思想上来讲,其实我们还是希望重传的时间需要稍稍的大于RTT就可以了。但是这个RTT没有什么可以使用的定值,他是不断变化的。

我们只能动态的进行设置,所以RTO只能是更加RTT来进行动态的设置,看下前辈们研究的RTT的计算方法

经典的算法 RFC793

1. 首先计算一个平滑的RTT称置为SRTT, alpha是一个平滑因子,取值为0.8或者0.9

SRTT = ( ALPHA * SRTT ) + ((1-ALPHA) * RTT)

2. 基于SRTT,计算出对应的RTO

     RTO = min[UBOUND,max[LBOUND,(BETA*SRTT)]

其中UBOUND是最大值,一般情况下为120s,LBOUND是最小重传值,一般情况下为1s,Beta取值为1.3~2.0. [RFC793]

其实这个算法,在目前Linux系统协议栈的实现中并没有使用了,原因是存在着一些不足之处,具体弊端没有认真研究,有文章指出不明确是使用第一次发送ACK的时间,还是使用重传ACK的时间采样RTT, 也有文章指出在RTT变化比较大的网络,性能表现非常不好... 总之有缺点

Jacobaon/Karels 算法

1988年,Van Jacobson和Karels在Congestion Avoidance and Control这篇论文中提出一种新的算法[RFC6298],

第一次RTO计算方法, 假设RTT = R

1.  SRTT = R

2.  RTTVAR = R/2

3.  RTO = SRTT + max(G, K*RTTVAR) , K = 4

后续的RTO计算,假设当前的RTT为R'

         RTTVAR = (1 - beta)*RTTVAR + beta*|SRTT - R'|    *计算平滑RTT和真实RTT的差距,切记这个地方的SRTT是上一次的SRTT*

SRTT = (1 - alpha)*SRTT + alpha*R' * 计算平滑RTT* 

 RTO = SRTT + max(G, K*RTTVAR)

alpha = 1/8  beta = 1/4,  值得指出的是这个算法在目前的Linux协议栈中应用,多么伟大的一件事情。

趣味考题

在阅读各种资料中,竟然看到一份考题,让计算RTO,现在果真是细节决定成败啊,不过记忆公式那真是学生时代的事情了...先看题目:

 假定TCP在开始建立连接时,发送方设定超时重传时间是RTO=6s。 (1)当发送方接到对方的连接确认报文段时,测量出RTT样本值为1.5s。试计算现在的RTO值。 (2)当发送方发送数据报文段并接收到确认时,测量出RTT样本值为2.5s。试计算现在的RTO值。

【答案】 根据RFC6298

RTT(1) = 1.5s

SRTT(1) = RTT(1) = 1.5s

RTTVAR(1) = 1.5/2 = 0.75

RTO = 1.5 + 4*0.75 = 4.5s    所以现在RTO的值为4.5s

接着计算第二步 RTT (2) = 2.5

RTTVAR(2) = 3/4 * 0.75 + 1/4 * |1.5 - 2.5|  = 13/16

SRTT(2) = 7/8 *1.5 + 1/8*2.5 = 1.625

RTO = 1.625 + 4 * 13/16 = 4.875 

Note: RFC6298 还有关于采样RTT和管理RTO定时器的topic,可以参考,后续可能会增加,相关部分!