TS.Recent存放着按序达到的所有TCP数据包的最晚的一个时间戳,即只有在
SEG.SEQ <= Last.ACK.sent < SEG.SEG + SEG.LEN(有新的数据被按序确认了)时,
才会去更新TS.Recent的值。
1 2 3 4 5 6 7 8 9 10 11
假设三个数据包的*第一次*发送时间分别是A,B和C(A < B < C),但A和C含有相同的序列号。 而A数据包由于某种原因,在阻塞在了网络中,因此发送方进行了重传,重传时间为A2 PAWS要解决的主要问题就是: 当接收端在接收到A2后,又接着确认到了数据包B,下一个想接收的数据是数据包C 此时如果收到了数据包A(A从阻塞中恢复过来了,但并未真的丢失), 由于A与C的序列号是相同的。如果没有别的保护措施就会出现数据紊乱,没有做到可靠传输 PAWS的做法就是,如果收到的一个TCP数据包的timestamp值小于TS.Recnt,则会丢弃该数据包。 因此数据包A到达接收方后,接收方的TS.Recent应该是数据包B中的timestamp 而A < B,故A包就会被丢弃。而真正有效的数据C到达接收后,由于B < C,因此能被正常接收
PAWS的更多细节
1 2 3 4 5 6 7 8 9 10 11
1. It is recommended that RST segments NOT carry timestamps, and that RST segments be acceptable regardless of their timestamp. 2. PAWS is defined strictly within a single connection; the last timestamp is TS.Recent is kept in the connection control block, anddiscarded when a connection is closed. 3. An additional mechanism could be added to the TCP, a per-host cache of the last timestamp received from any connection. This value could then be used in the PAWS mechanism to reject old duplicate segments from earlier incarnations of theconnection, if the timestamp clock can be guaranteed to have ticked at least once since the old connection was open.
从第三点可以看到,如果针对per-host的使用PAWS中的机制,则会解决TIME-WAIT中考虑的上一个流
的数据包在下一条流中被当做有效数据包的情况,这样就没有必要等待2*MSL来结束TIME-WAIT了。
只要等待足够的RTO,解决好需要重传最后一个ACK的情况就可以了。
因此Linux就实现了这样一种机制:
1 2
当timestamp和tw_recycle两个选项同时开启的情况下,开启per-host的PAWS机制。 从而能快速回收处于TIME-WAIT状态的TCP流。
但这样真的就能完美的解决令无数人头疼的TIME-WAIT吗?答案是否定的!
因为公网中存在太多的NAT设置,当使用per-host的PAWS机制时,是无法保证timestamp是线性递增这一假设的。因为使用同一个NAT地址的两个真实的机器,他们的timestamp是不能保证同步的(其实一致也没有用,NAT就是per-host PAWS机制的死敌)。
关于这个问题也会在以后的一篇介绍TIME-WAIT的wiki中进一步详细介绍。
1 2 3
timestamp为TCP/IP协议栈提供了两个功能: a. 更加准确的RTT测量数据,尤其是有丢包时 -- RTTM b. 保证了在极端情况下,TCP的可靠性 -- PAWS