TCP/IP协议栈中的TimeStamp选项

原文转自:http://www.cnblogs.com/lovemyspring/articles/4271716.html

TCP应该是以太网协议族中被应用最为广泛的协议之一,这里就聊一聊TCP协议中的TimeStamp选项。这个选项是由RFC 1323引入的,该C建议提交于1992年,到今天已经足足有20个年头。不过相信大部分程序猿对这个建议还是相当陌生。
要理解为啥需要用TimeStamp选项,还需要从TCP协议的几个基本设计说起。

TCP协议的几个设计初衷,以及引发的问题:
1. 协议规定收端不需要响应每一个收到的数据报文,只需要收到N个报文后,向发端回复一个ack报文即可。
    这样的规定是为了提高通讯的效率,但是也引入了几个问题:
    A. 发端发出报文后,到底多久能够收到ack是不确定的。
    B. 万一ack报文丢失了,判断需要重发的timeout时间也很难确定。
2. TCP报文中,标示Sequence号的地址长度为32位。
    这就限制了发端最多一次发送2^30长度的数据,就必须等待ack信号。为啥呢?在这个链接里有一些详细的讨论。
    然而对于超高速以太网(1000M以至于10G),这样会影响TCP连接的转发效率。 


为解决上面提到的问题,TimeStamp选项主要有两个用途:
1. 测量TCP连接两端通讯的延迟(Round Trip Time Measurement)
    有了RTTM机制,TCP的两端可以很容易的判断出线路上报文的延迟情况,从而制定出一个优化的发包间隔和报文TimeOut时间,从而解决了第一个问题。
2. 处理Sequence号反转的问题(Protect Against Wrapped Sequence Numbers)。
    TCP收端收到一个数据报文后,会先比较本次收到报文的TimeStamp和上次收到报文的TimeStamp。如果本次的比较新,那么可以直接判断本次收到的报文是新的报文,不需要进行复杂的Sequence Number Window Scale计算,从而解决了第二个问题。

然而,RFC1323建议还存在一些隐患。
建议中定义TimeStamp增加的间隔可以使1ms-1s。如果设备按照1ms的速度增加TimeStamp,那么只要一个TCP连接连续24.8天(1ms*2^31)没有通讯,再发送报文,收端比较本次报文和上次报文TimeStamp的动作就会出错。(问题1)
(注:TCP协议中并没有定义KeepAlive。如果应用层代码不定义超时机制,TCP连接就永远不会中断,所以连续24.8天不通讯的情况是却有可能发生的。)
引用Linux相关代码:((s32)(tp->rx_opt.rcv_tsval - tp->rx_opt.ts_recent) < 0)
比如 tp->rx_opt.rcv_tsval = 0x80000020,       tp->rx_opt.ts_recent = 0x10
 ((s32)(tp->rx_opt.rcv_tsval - tp->rx_opt.ts_recent) = (s32)0x80000010,是一个负数,必然小于0。

如果解决问题1呢?
已知按照RFC1323的规定,按照最快TimeStamp增加的速度,也需要24.8天TImeStamp才有可能发生反转。
如果((s32)(tp->rx_opt.rcv_tsval - tp->rx_opt.ts_recent) < 0)判断成立,还可以再用本地收到报文的本地TimeStamp减去上一次收到报文的本地TimeStamp。如果时间大于24.8天,那么就是TimeStamp发生了反转;否则就不是反转的情况。这样做是不是就万无一失了呢?不一定!

别忘了本地TimeStamp的计数器也是个32位,也可能会翻转的。(问题2)
举个极端的例子:假设TCP两端设备的TimeStamp增加间隔不一致,A为1ms,B为10ms。TCP连接连续248天没有通讯;这个时候B向A发送了一个数据报文。 
此时B发送给A的TCP报文中的TimeStamp,正好发生了翻转。然而由于A的计数器是每1ms加一的,248天时间,A的计数器已经归零过5次了。这时候再用本地TimeStamp做判断还是错的。

 

比较保险的做法是:
如果TCP连接的速度不那么快(2^32/s),本地TimeStamp用最大间隔时间1S。从而规避了(问题2)
如果TCP连接速度非常快,1S的TimeStamp间隔就有些不合时宜了,可以选小一级,如100ms。如果这时候还会发生连续24800天(为啥是24800天呢)不通讯的情况,除了骂娘以外,我也没办法了。

 

原文转自:http://blog.csdn.net/zhangskd/article/details/7195795

Description

        Protocol suite: TCP/IP.

        Protocol type: Transport layer protocol.

        Option length: 10 bytes. 

The TCP Timestamp option obsoletes the TCP Echo request and Echo reply options.

RFC 1323:

        The timestamps are used for two distinct mechanisms: RTTM (Round Trip Time Measurement)

and PAWS (Protected Against Wrapped Squences).

 

结构图


 

Kind. 8 bits. Set to 8. 

Length. 8 bits. Set to 10.

Timestamp Value (TSval). 32 bits.

This field contains the current value of the timestamp clock of the TCP sending the option.

TImestamp Echo Reply (TSecr). 32 bits.

This field only valid if the ACK bit is set in the TCP header. If it is valid, it echos a timestamp value

that was sent by the remote TCP in the TSval field of a Timestamps option. When TSecr is not valid,

its value must be zero. The TSecr value will generally be from the most recent Timestamp option

that was received; however, there are exceptions that are explained below. A TCP may send the

Timestamp option in an initial SYN segment(i.e., segment containing a SYN bit and no ACK bit), and

may send a TSopt in other segments only if it received a TSopt in the initial SYN segment for the

connection.

Linux内核中的使用

如果支持Timestamp选项,那么可以用此选项来计算RTT。

[java] view plain copy
 
  1. static void tcp_ack_saw_tstamp(struct sock *sk , int flag)  
  2. {  
  3.         /* RTTM Rule: A TSecr value received in a segment is used to 
  4.          * update the averaged RTT measurement only if the segment 
  5.          * acknowledges some new data, i.e., only if it advances the 
  6.          * left edge of the send window. 
  7.          *  
  8.          * Changed: reset backoff as soon as we see the first valid 
  9.          * sample. If we do not, we get strongly overestimated rto. 
  10.          * With timestamps samples are accepted even from very 
  11.          * old segments: f.e., when rtt=1 increases to 8, we retransmit 
  12.          * 5 times and after 8 seconds delayed answer arrives rto 
  13.          * becomes 120 seconds!  
  14.          */  
  15.          struct tcp_sock *tp = tcp_sk(sk);  
  16.          tcp_valid_rtt_meas(sk, tcp_time_stamp - tp->rx_opt.rcv_tsecr);  
  17. }  

 

rtt即等于现在的时间tcp_time_stamp减去Timestamp Echo Reply,即tp->rx_opt.rcv_tsecr。

 

TCP timestamp option的作用:

1)allow more accurate round-trip time measurements for deriving the retransmission

timeout estimator.

2)protect against old segments from the previous incarnations of the TCP connection.

3)allow detection of unnecessary retransmissions.

posted @ 2016-05-07 09:55  yyxxzz22  阅读(3038)  评论(1编辑  收藏  举报