4. PAWS -- 防止序列号回绕
4. PAWS: 防止序列号回绕 (Protect Against Wrapped Sequence Numbers)
4.1 简介 (Introduction)
第4.2节描述了一种简单机制来拒绝可能破坏开放TCP连接的旧重复段;我们称这种机制为PAWS (防止序列号回绕)。PAWS在单个TCP连接内运行,使用保存在连接控制块中的状态。第4.3节和附录C讨论了PAWS机制对避免来自同一连接早期实例的旧重复的影响。
4.2 PAWS机制 (The PAWS Mechanism)
PAWS使用与前面描述的RTTM机制相同的TCP时间戳选项,并假设每个接收到的TCP段(包括数据和ACK段)包含一个时间戳SEG.TSval,其值随时间单调非递减。基本思想是,如果接收到的段的时间戳SEG.TSval小于此连接上最近接收到的某个时间戳,则该段可以作为旧重复被丢弃。
在PAWS和RTTM机制中,"时间戳"是模32位空间中的32位无符号整数。因此,"小于"的定义与TCP序列号相同,并且适用相同的实现技术。如果s和t是时间戳值,当0 < (t - s) < 2**31时,s < t(以无符号32位算术计算)。
为此比较保存的传入时间戳的选择必须保证值单调递增。例如,我们可能保存最后推进接收窗口左边缘的段的时间戳,即最近的顺序段。相反,我们选择第3.4节为RTTM机制引入的TS.Recent值,因为对PAWS和RTTM使用公共值简化了两者的实现。如第3.4节所解释的,TS.Recent与最后顺序段的时间戳的不同仅在延迟ACK的情况下,因此相差不到一个窗口。因此,任一选择都将防止序列号回绕。
RTTM以对称方式指定,因此TSval时间戳在数据和ACK段中携带,并在返回的ACK或数据段中携带的TSecr字段中回显。PAWS对所有传入段进行相同的测试,因此防止重复的ACK段以及数据段。(另一种非对称算法将防止旧的重复ACK:数据发送方将拒绝TSecr值小于从最后推进发送窗口左边缘的段保存的TSecr的传入ACK段。这种算法被认为缺乏机制经济性和对称性。)
在{SYN}和{SYN,ACK}段上发送的TSval时间戳用于初始化PAWS。PAWS防止旧的重复非SYN段,以及在有同步连接时接收到的重复SYN段。在没有连接时接收到的重复{SYN}和{SYN,ACK}段将被TCP的正常三次握手和序列号检查丢弃。
建议RST段不携带时间戳,并且RST段无论其时间戳如何都应被接受。旧的重复RST段应该极不可能出现,并且其清理功能应优先于时间戳。
4.2.1 基本PAWS算法 (Basic PAWS Algorithm)
PAWS算法要求对同步连接的所有传入段执行以下处理:
R1) 如果到达段中有时间戳选项,并且SEG.TSval < TS.Recent,并且TS.Recent有效(见后续讨论),则将到达段视为不可接受:
按照RFC-793第69页指定的方式发送确认作为回复并丢弃该段。 注意:有必要发送ACK段以保留TCP用于检测和恢复半开连接的机制。例如,参见RFC-793的图10。
R2) 如果段在窗口外,拒绝它(正常TCP处理)
R3) 如果到达段满足:SEG.SEQ <= Last.ACK.sent(见第3.4节),则在TS.Recent中记录其时间戳。
R4) 如果到达段是顺序的(即在左窗口边缘),则正常接受它。
R5) 否则,将段视为正常的窗口内、乱序TCP段(例如,排队等待稍后传递给用户)。
步骤R2、R4和R5是RFC-793指定的正常TCP处理步骤。
重要的是要注意,时间戳仅在段首次到达接收方时检查,无论它是顺序的还是必须排队以供稍后传递。考虑以下示例。
假设段序列:A.1、B.1、C.1、...、Z.1已被发送,其中字母表示序列号,数字表示时间戳。还假设段B.1已丢失。TS.Recent中的时间戳为1(来自A.1),因此C.1、...、Z.1被认为是可接受的并被排队。当B被重传为段B.2(使用最新时间戳)时,它填充了空洞并导致所有段直到Z被确认并传递给用户。排队段的时间戳此时不再次检查,因为它们已经被接受。当B.2被接受时,TS.Stamp被设置为2。
此规则允许在丢失下的合理性能。完整窗口的数据始终在传输中,并且在丢失后,完整窗口减去一个数据包将乱序出现以在接收方排队(例如,最多约2**30字节的数据);时间戳选项不得导致丢弃此数据。
在某些不太可能的情况下,规则R1-R4的算法可能会不必要地丢弃一些段,如以下示例所示:
再次假设段:A.1、B.1、C.1、...、Z.1已按顺序发送,并且段B.1已丢失。此外,假设C.1、...Z.1中的一些在重传B.2到达接收方之后才被传递。这些延迟的段在到达时将被不必要地丢弃,因为它们的时间戳现在已过时。
这种情况发生的可能性很小。如果重传由超时触发,C.1、...Z.1中的一些段必须已被延迟超过RTO时间。这大概是不太可能的事件,否则会有许多虚假的超时和重传。如果B的重传由"快速重传"算法触发,即由重复ACK触发,则导致这些ACK的排队段必须已经被接收。
即使段被延迟超过RTO,快速重传机制将导致延迟的数据包与B.2同时重传,避免额外的RTT,因此导致非常小的性能损失。
我们不知道有任何具有显著发生概率的情况,其中时间戳会通过不必要地丢弃段而导致性能降低。
4.2.2 时间戳时钟 (Timestamp Clock)
重要的是要理解PAWS算法不需要发送方和接收方之间的时钟同步。发送方的时间戳时钟用于给段加时间戳,发送方使用回显的时间戳来测量RTT。然而,接收方将时间戳简单地视为单调递增的序列号,与其时钟没有必然联系。从接收方的角度来看,时间戳充当序列号高位的逻辑扩展。
接收方算法确实对时间戳时钟的频率提出了一些要求。
(a) 时间戳时钟不能"太慢"。
它必须每发送231字节至少滴答一次。事实上,为了对发送方的往返计时有用,时钟应该每窗口数据至少滴答一次,即使使用RFC-1072窗口扩展,231字节也必须至少是两个窗口。
更定量地说,任何快于1滴答/秒的时钟将拒绝链接速度约8 Gbps的旧重复段。1ms时间戳时钟将在高达8 Tbps (8*10**12 bps) 的链接速度下工作!
(b) 时间戳时钟不能"太快"。
其循环时间必须大于MSL秒。由于时钟(时间戳)是32位,最坏情况MSL为255秒,最大可接受的时钟频率是每59 ns滴答一次。
但是,希望建立更长的循环周期,以便处理空闲连接上的过时时间戳(见第4.2.3节),并放宽防止序列号回绕的MSL要求。使用1 ms时间戳时钟,32位时间戳将在24.8天内回绕其符号位。因此,如果MSL为24.8天或更短,它将拒绝同一连接上的旧重复。这似乎是一个非常安全的数字;网关系统可能假设MSL为24.8天或更长,而不需要通过IP层中的TTL值精确执行MSL。
基于这些考虑,我们选择时间戳时钟频率在每滴答1 ms到1秒的范围内。该范围还符合RTTM机制的要求,该机制不需要比重传定时器粒度更高的分辨率,例如,数十或数百毫秒。
PAWS机制还对发送方的时间戳时钟提出了强单调性要求。满足此要求的时间戳时钟的实现方法取决于系统硬件和软件。
- 一些主机具有保证在硬件重置之间单调的硬件时钟。
- 时钟中断可用于简单地周期性地将二进制整数递增1。
- 时间戳时钟可以从可能突然更改的系统时钟派生,通过添加可变偏移值。此偏移初始化为零。当需要新的时间戳时钟值时,可以根据需要调整偏移,使新值等于或大于先前值(为此目的保存)。
4.2.3 过时的时间戳 (Outdated Timestamps)
如果连接保持空闲时间足够长,以至于另一个TCP的时间戳时钟回绕其符号位,则TS.Recent中保存的值将变得太旧;结果,PAWS机制将导致所有后续段被拒绝,冻结连接(直到时间戳时钟再次回绕其符号位)。
使用所选的时间戳时钟频率范围(1秒到1 ms),回绕符号位的时间将在24.8天到24800天之间。空闲超过24天然后恢复活动的TCP连接极其不寻常。但是,原则上不希望对TCP连接生命周期施加任何限制。
因此,我们要求PAWS的实现包括一种机制,当连接空闲超过24天时"使TS.Recent值无效"。(解决过时时间戳问题的另一种方法是以非常低的速率发送keepalive段,但仍比时间戳的回绕时间更频繁,例如,每天一次。这将施加可忽略的开销。但是,TCP规范从未包括keepalive,因此选择了基于无效化的解决方案。)
注意,TCP不知道另一个TCP的频率,因此也不知道回绕时间,因此必须假设最坏的情况。仅当基本PAWS时间戳检查失败时,即仅当SEG.TSval < TS.Recent时,才需要检查TS.Recent的有效性。如果发现TS.Recent无效,则无论时间戳检查失败,都接受该段,并且规则R3使用新段中的TSval更新TS.Recent。
为了检测连接空闲了多长时间,TCP可能会在每次更新TS.Recent时更新与连接关联的时钟或时间戳值,例如。详细信息将取决于实现。
4.2.4 头部预测 (Header Prediction)
"头部预测"是一种高性能传输协议实现技术,对于高速链路最为重要。该技术针对最常见的情况优化代码,即正确且按顺序接收段。使用头部预测,接收方提出问题:"这个段是下一个顺序段吗?"这个问题可以用比问题"这个段在窗口内吗?"更少的机器指令回答。
将头部预测添加到我们的时间戳过程导致以下推荐的处理到达TCP段的序列:
H1) 检查时间戳(与上面的步骤R1相同)
H2) 进行头部预测:如果段是下一个顺序段,并且没有需要额外处理的特殊条件,则接受该段,记录其时间戳,并跳过H3。
H3) 按RFC-793指定的方式正常处理段。这包括丢弃窗口外的段并可能发送确认,以及排队窗口内、乱序的段。
另一种可能性是交换步骤H1和H2,即首先执行头部预测步骤H2,并且仅当头部预测失败时才执行H1和H3。这可能是性能改进,因为步骤H1中的时间戳检查极不可能失败,并且它需要对有限域进行区间算术,这是相对昂贵的操作。对每个单个段执行此检查违背了头部预测的理念。我们认为这种更改可能会将高速网络上TCP协议处理的CPU时间减少多达5-10%。
但是,将H2放在前面会产生危险:来自2**32字节之前的段可能恰好在错误的时间到达,并被头部预测步骤错误地接受。引入了以下推理来表明此失败的概率可以忽略不计。
如果所有段作为旧重复出现的可能性相同,则旧重复恰好匹配左窗口边缘的概率是最大段大小 (MSS) 除以序列空间的大小。该比率必须小于2**-16,因为MSS必须< 216;例如,对于FDDI链路,它将是(212)/(232) = 2-20。但是,段越旧,在互联网中保留的可能性越小,并且在任何合理的段生命周期模型下,旧重复恰好在左窗口边缘的概率必须远小于2**-16。
16位TCP校验和还允许2**16分之一的基本不可靠性。可靠性超过TCP校验和可靠性的协议机制应被认为是"足够好"的,即它不会显著贡献于总体错误率。因此,我们认为可以忽略在时间戳检查之前进行头部预测而接受旧重复的问题。
但是,这种概率论证并未被普遍接受,目前的共识是性能增益不能证明一般情况下的危险是合理的。因此,建议H2跟随H1。
4.3 来自早期连接实例的重复 (Duplicates from Earlier Incarnations of Connection)
PAWS机制防止由于高速连接上的序列号回绕而导致的错误。来自同一连接早期实例的段也是旧重复错误的潜在原因。在这两种情况下,防止此类错误的TCP机制取决于互联网(IP)层对最大段生命周期(MSL)的执行(有关详细讨论,请参见RFC-1185的附录)。与序列空间回绕的情况不同,防止来自早期实例的旧重复错误所需的MSL不依赖于传输速率。如果IP层执行TCP建议的2分钟MSL,并且遵循TCP规则,则无论网络速度多高,TCP连接都将安全免受早期实例的影响。因此,这种情况不需要PAWS机制。
我们仍然可以问PAWS机制是否可以提供针对来自早期连接的旧重复的额外安全性,允许我们放宽IP层对MSL的执行。附录B探讨了这个问题,表明除了PAWS之外,还需要进一步的假设和/或机制。这不是当前扩展的一部分。