TCP timestamp 相关知识

tcp_timestamps是在RFC 1323中定义的一个TCP选项。
这篇wiki介绍一下timestamps的设计目的和相关原理,尤其强调一些比较tricky的地方。

关于RFC1323

这是一篇介绍针对High-bandwidth, Long delay链路设计的一些TCP扩展选项的资料。强烈推荐阅读!
但这篇RFC其实已经被RFC7323所取代,不过RFC1323对于了解timestamp相关的基本概念来说还是足够了的。关于RFC7323也会在后续的wiki中详细的介绍。

High-bandiwidth, Long delay链路面临的性能问题

1

2

3

4

5

6

7

8

9

10

11

 

a. Window Size limit 

TCP头部仅16字节用于存放receive window,这在高BDP的链路中往往是不够用的 

解决办法就是引入window scale选项,然后real_rcv_wnd = rcv_wnd_in_tcp_header * (2^win_scale) 

  

b. Recovery from Losses 

当BDP很大时,意味着需要更大的cwnd来充分利用带宽。如果发生网络丢包,则对这类链路的影响是巨大的。 

优化办法(真的不能说解决T_T)就是引入[SACK](https://tools.ietf.org/html/rfc2018)机制,来为发送方重传提供更加准确的信息。 

  

c. Round-Trip Measurement 

TCP作为可靠的传输协议,一个重要的机制就是超时重传。因此如何计算一个准确(合适)的

RTO对于TCP性能有着重要的影响。而tcp_timestamp选项正是*主要*为此而设计的。

 

上一句话强调”主要”是因为tcp_timestamp还被用于PAWS机制,而这一重要用途却时常被忽略。
作为一个可靠的传输协议,TCP除了考虑如何应对性能问题,还需要考虑可靠性问题。
即使这些问题发生的概率较低,PAWS就是其中一个例子。
PAWS(Protect Against Wrapped Sequence numbers)一句话解释如下,后面会详细介绍

1

2

 

在高带宽下,TCP序列号可能在较短的时间内就被重复使用(recycle/wrapped)

就可能导致同一条TCP流在短时间内出现序号一样的两个合法的数据包及其确认包!

 

补充一句:什么用wrapped形容序列号被重复使用?因为压圈了呀 :)

tcp_timestamps 的设计

tcp_timestamps的本质是记录数据包的发送时间。基本的步骤如下

1

2

3

 

1. 发送方在发送数据时,将一个timestamp(表示发送时间)放在包里面

2. 接收方在收到数据包后,在对应的ACK包中将收到的timestamp返回给发送方(echo back)

3. 发送发收到ACK包后,用当前时刻now - ACK包中的timestamp就能得到准确的RTT

 

当然实际运用中要考虑到RTT的波动,因此有了后续的(Round-Trip Time Measurement)RTTM机制

TCP Timestamps Option (TSopt)具体设计如下

1

2

3

4

5

6

 

Kind: 8             // 标记唯一的选项类型,比如window scale是3

Length: 10 bytes    // 标记Timestamps选项的字节数

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

| Kind=8 | Length=10 | TS Value (TSval) | TS ECho Reply (TSecr) |

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    1          1             4                       4

 

timestamps一个双向的选项,当一方不开启时,两方都将停用timestamps。
比如client端发送的SYN包中带有timestamp选项,但server端并没有开启该选项。
则回复的SYN-ACK将不带timestamp选项,同时client后续回复的ACK也不会带有timestamp选项。
当然,如果client发送的SYN包中就不带timestamp,双向都将停用timestamp。

为什么需要timestamp

如果没有timestamp,RTT的计算会怎样?

1

2

 

1. TCP层在发送出一个SKB时,使用skb->when记录发送出去的时间

2. TCP层在收到SKB数据包的确认时,使用now - skb->when来计算RTT

 

但上面的机制在丢包发生时会有问题,比如

1

2

 

1. TCP层第一次发送SKB的时间是send_time1, TCP层重传一个数据包的时间是send_time2

2. 当TCP层收到SKB的确认包的时间是recv_time

 

但是RTT应该是 (recv_time - send_time1)呢,还是(recv_time - send_time2)呢?

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/fc127940c2f9ef86bbf21dd582ac25c6.html