分类: LINUX
2011-09-27 15:51:21
google有一帮人对TCP的建立连接时的三次握手传进行了统计,大概有2%的重传率。
并且为了这2%的重传率,对tcp协议进行了优化:将RTO时间从3秒改为了1秒。
我觉得中国的网络不比美国的好,所以,在实际中重传率应该比2%高很多。
优化之后有什么好处呢:
1) 对于3次握手有重传的情况,缩短超时时间,能够更快的完成3次连接。
2) 在一个拥塞的网络,减少了拥塞窗口值,降低拥塞的恶化。
相关资源:
1. 原始的Patch:
2. 一篇博文:
rfc 2988是描述tcp如何计算定时器的一个rfc,是2000年发布的,而最近2988 已经被更新:
并且google的jerry chu(2988bis的作者之一)最近在内核提交一个patch,主要是用来修改3次握手时的初始化rto的值(以及rfc 2988bis的一些改变),当前的内核默认是3,而patch修改这个值为1,主要的修改依据是rfc2988.
在net-next-2.6的分支,我们git log可以看到对应的提交log:
Author: Jerry Chu
Date: Wed Jun 8 11:08:38 2011 +0000tcp: RFC2988bis + taking RTT sample from 3WHS for the passive open side
This patch lowers the default initRTO from 3secs to 1sec per
RFC2988bis. It falls back to 3secs if the SYN or SYN-ACK packet
has been retransmitted, AND the TCP timestamp option is not on.It also adds support to take RTT sample during 3WHS on the passive
open side, just like its active open counterpart, and uses it, if
valid, to seed the initRTO for the data transmission phase.The patch also resets ssthresh to its initial default at the
beginning of the data transmission phase, and reduces cwnd to 1 if
there has been MORE THAN ONE retransmission during 3WHS per RFC5681.
可以
git show 9ad7c049f0f79c418e293b1b68cf10d68f54fcdb
来看对应的patch。有兴趣的话,可以看看这个patch.
接下来我主要是简要的介绍下这个rfc。
1 首先发送者应当设置rto初始值为 1(以前默认值是3) .
将三次握手时的rto初始值由3降低为1,是由于下面几个原因的:
1.1 三次握手时的rto的初始值为3,是在RFC 1122中定义的,而rfc1122是1989年发表的,
现在的网络比当 初的网络要快太多了。
1.2 google的统计显示大多数的(97.5%)的连接的RTT都是小于1秒的.
1.3 并且统计也显示在三次握手期间的重传率也就只有2%左右.
可是依然有2.5%的连接的RTT是大于1秒的,如果是这些连接,
则将会在连接建立的期间引发一个重传,这时就需要将初始化的RTO再次重置为3,
不过此时如果tcp头里面包含timestamps域,则不需要将RTO重置为3,
因为协议栈此时可以通过timestamps来计算对应的rto.
2 RTO的值必须大于等于1,如果小于1,则向上取整为1。
3 tcp必须使用karn算法,来进行定时器退避策略.
4 如果存在timestamp option,则每次ack都会重新计算rtt.
然后就是核心的定时器管理部分:
1 发送数据时(包括重传),需要启动重传定时器,当所有发送未确认数据被ack,则删除定时器.
2 如果定时器超时,则重传最早的还没有被receiver ack的段,并且host必须设置RTO = RTO *2 (karn, 定时器退避),而rto的最大值也必需有一个限制(linux下是120秒).
3 当三次握手期间定时器超时,并且初始rto是1,此时RTO必须重新设置为3
URL: