原文 https://datatracker.ietf.org/doc/html/rfc2018 TCP Selective Acknowledgement Options TCP选择确认选项
概述
当多个数据包从一个数据窗口丢失时,TCP 的性能可能会很差。由于累积确认提供的信息有限,TCP 发送方在每个往返时间内只能了解一个丢失的数据包。激进的发送方可以选择提前重新传输数据包,但可能已经成功接收到此类重新传输的数据段。
选择性确认 (SACK) 机制与选择性重复重传策略相结合,可以帮助克服这些限制。接收方 TCP 将 SACK 数据包发送回发送方,通知发送方已收到数据。然后发送方可以仅重传丢失的数据段。
本文提出了 SACK 的实现并讨论了其性能和相关问题。
1. 简介
一个数据窗口中的多个数据包丢失会对 TCP 吞吐量产生灾难性影响。 TCP [Postel81] 使用累积确认方案,其中不确认不在接收窗口左边缘的接收段。这迫使发送方要么等待一个往返时间以找出每个丢失的数据包,要么不必要地重新传输已正确接收的数据段 [Fall95]。对于累积确认方案,多个丢弃的段通常会导致 TCP 丢失其基于 ACK 的时钟,从而降低整体吞吐量。
Selective Acknowledgment (SACK) 是一种策略,可以在面对多个丢弃的段时纠正这种行为。通过选择性确认,数据接收方可以通知发送方所有已成功到达的段,因此发送方只需要重传实际丢失的段。
包括 NETBLT [Clark87]、XTP [Strayer92]、RDP [Velten84]、NADIR [Huitema81] 和 VMTP [Cheriton88] 在内的几种传输协议都使用了选择性确认。有一些经验证据支持选择性确认——简单的 RDP 实验表明,禁用选择性确认工具会大大增加在有损、高延迟 Internet 路径上重传的段数 [Partridge87]。最近由 Kevin Fall 和 Sally Floyd [Fall95] 进行的一项模拟研究证明了 TCP 与 SACK 相比非 SACK Tahoe 和 Reno TCP 实现的优势。
RFC1072 [VJ88] 描述了 TCP 的 SACK 选项的一种可能实现。不幸的是,它从未在 Internet 中部署过,因为对于 SACK 选项应如何与 TCP 窗口移位选项(最初描述为 RFC1072 并在 [Jacobson92] 中修订)结合使用存在分歧。
我们建议对 RFC1072 中提出的 SACK 选项进行轻微修改。具体来说,为最近收到的数据发送选择性确认减少了对长 SACK 选项的需要 [Keshav94, Mathis95]。此外,SACK 选项现在带有完整的 32 位序列号。这两个修改代表了对 RFC1072 中提案的唯一更改。它们使 SACK 更容易实现并解决关于健壮性的问题。
选择性确认扩展使用两个 TCP 选项。第一个是启用选项,“SACK-permitted”,它可以在 SYN 段中发送,以指示一旦建立连接就可以使用 SACK 选项。另一个是 SACK 选项本身,一旦获得 SACK-permit 的许可,它就可以通过已建立的连接发送。
SACK 选项将包含在从接收数据的 TCP 发送到正在发送该数据的 TCP 的段中;我们将这些 TCP 分别称为数据接收方和数据发送方。我们将考虑一个特定的单纯形数据流;任何在同一连接上反向流动的数据都可以独立处理。
2. Sack-Permitted的选项
这个两字节的选项可以在 SYN 中由 TCP 发送,一旦连接打开,该 TCP 已扩展为接收(并可能处理)SACK 选项。它不得在非 SYN 段上发送。

3. Sack Option 格式
SACK 选项用于通过已建立的 TCP 连接将扩展确认信息从接收方传送到发送方。

SACK 选项将由数据接收方发送,以通知数据发送方已接收并排队的非连续数据块。数据接收器等待数据的接收(可能通过重传)以填充接收块之间序列空间的间隙。当接收到丢失的数据段时,数据接收方通过在 TCP 报头的确认编号字段中将左窗口边缘前进来正常确认数据。 SACK 选项不会更改确认编号字段的含义。
此选项包含一些连续序列空间块的列表,这些块已被接收并在窗口内排队的数据占用。
在数据接收器排队的每个连续数据块在 SACK 选项中由两个 32 位无符号整数以网络字节顺序定义:
* 块的左边缘
这是该块的第一个序列号。
*块的右边缘
这是紧跟在该块的最后一个序列号之后的序列号。
每个块代表接收到的连续和隔离的数据字节; 也就是说,块正下方(块的左边缘 - 1)和块正上方(块的右边缘)的字节尚未被接收。
指定 n 个块的 SACK 选项的长度为 8*n+2 字节,因此 TCP 选项可用的 40 个字节最多可以指定 4 个块。预计 SACK 将经常与用于 RTTM [Jacobson92] 的 Timestamp 选项结合使用,这需要额外的 10 个字节(加上两个字节的填充);因此在这种情况下最多允许 3 个 SACK 块。
SACK 选项是建议性的,因为它通知数据发送方数据接收方已收到指示的段,数据接收方允许稍后丢弃已在 SACK 选项中报告的数据。下面第 8 节讨论了建议 SACK 的后果,特别是数据接收器可能会反悔或丢弃已经 SACK 的数据。
4. 生成 Sack 选项:数据接收器行为
如果数据接收者在 SYN 上收到了一个 SACK-Permitted 选项,数据接收者可以选择生成 SACK 选项,如下所述。如果数据接收方在任何情况下生成 SACK 选项,它应该在所有允许的情况下生成它们。如果数据接收方没有收到给定连接的 SACK-Permitted 选项,它不得在该连接上发送 SACK 选项。
如果发送,SACK 选项应该包含在所有不确认数据接收方队列中最高序列号的 ACK 中。在这种情况下,网络丢失或错误排序数据,从而接收器在其队列中保存不连续的数据。 RFC 1122 的第 4.2.2.21 节讨论了接收方发送 ACK 以响应在此状态下接收到的附加段的原因。接收者应该为每个到达的包含新数据的有效段发送一个 ACK,并且这些“重复”ACK 中的每一个都应该带有一个 SACK 选项。
如果数据接收方选择发送 SACK 选项,则适用以下规则:
* 第一个 SACK 块(即,紧跟在选项中的种类和长度字段之后的那个)必须指定包含触发此 ACK 的段的连续数据块,除非该段提前了报头中的确认编号字段。这确保了带有 SACK 选项的 ACK 反映了数据接收器缓冲区队列中的最新变化。
* 数据接收方应该在 SACK 选项中包含尽可能多的不同 SACK 块。请注意,最大可用选项空间可能不足以报告接收器队列中存在的所有块。
* SACK 选项应该通过重复最近报告的 SACK 块(基于先前 SACK 选项中的第一个 SACK 块)来填充,这些 SACK 块不是已包含在正在构造的 SACK 选项中的 SACK 块的子集。这确保在正常操作中,数据接收器持有的非连续数据块的任何剩余部分在至少三个连续的 SACK 选项中报告,即使对于大窗口 TCP 实现 [RFC1323])。在第一个 SACK 块之后,SACK 选项中的以下 SACK 块可以按任意顺序列出。
SACK 选项始终报告包含最近收到的段的块非常重要,因为这为发送方提供了有关网络状态和数据接收方队列的最新信息。
5. 解释 Sack 选项和重传策略:数据发送者行为
当接收到包含 SACK 选项的 ACK 时,数据发送方应该记录选择性确认以供将来参考。假设数据发送方有一个重传队列,其中包含已传输但尚未确认的段,按序列号顺序排列。如果数据发送方在重传前进行重包,其接收到的SACK选项中的块边界可能不会落在重传队列中的段边界上;然而,这对发件人来说并不构成严重的困难。
发送者行为的一种可能实现如下。让我们假设,对于重传队列中的每个段,都有一个(新)标志位“SACKed”,用于指示该特定段已在 SACK 选项中报告。
当包含 SACK 选项的确认段到达时,数据发送方将打开已被选择性确认的段的 SACK 位。更具体地说,对于 SACK 选项中的每个块,数据发送方将为重传队列中完全包含在该块中的所有段打开 SACKed 标志。这需要直接的序列号比较。
在 SACKed 位打开后(作为处理接收到的 SACK 选项的结果),数据发送方将在以后的任何重传期间跳过该段。任何 SACK 位关闭且小于最高 SACK 段的段都可用于重传。
在重传超时后,数据发送方应该关闭所有 SACKed 位,因为超时可能表明数据接收方已经反悔。数据发送方必须在重传超时后在窗口的左边缘重传该段,无论该段的 SACKed 位是否打开。一个段将不会出列并释放其缓冲区,直到左窗口边缘前进到它为止。
5.1 拥塞控制问题
本文档不试图详细说明 TCP with SACK 实现的拥塞控制算法。然而,必须保留事实上的标准 TCP 实现中存在的拥塞控制算法 [Stevens94]。特别是,为了在存在由网络重新排序的数据包的情况下保持健壮性,恢复不是由单个 ACK 报告接收器处的无序数据包触发的。此外,在恢复期间,数据发送方会限制响应每个 ACK 发送的段数。现有的实现将数据发送方限制为在 Reno 式快速恢复期间发送一个段,或在慢启动期间发送两个段 [Jacobson88]。拥塞控制的其他方面,例如响应拥塞而减少拥塞窗口,也必须类似地保留。
SACK 选项没有改变使用超时作为检测丢弃数据包的回退机制。由于允许数据接收方丢弃 SACK 数据,当发生重传超时时,数据发送方在确定重传哪些数据时必须忽略先前的 SACK 信息。
未来对拥塞控制算法的研究可能会利用 SACK 提供的附加信息。未来研究的一个此类领域涉及对无线或卫星环境中 TCP 的修改,其中数据包丢失不一定表示拥塞。
6. 效率和最坏情况行为
如果携带 ACK 和 SACK 选项的返回路径是无损的,则每个 SACK 选项数据包一个块总是足够的。当数据接收器保存不连续数据时到达的每个段将导致数据接收器发送带有 SACK 选项的 ACK,其中包含接收器队列中的一个更改块。因此,数据发送方能够通过采用所有第一个 SACK 块的联合来构建接收方队列的精确副本。
由于返回路径不是无损的,SACK 选项被定义为在单个数据包中包含多个 SACK 块。 SACK 选项数据包中的冗余块增加了在丢失 ACK 的情况下 SACK 传递的鲁棒性。对于同样使用时间戳选项 [Jacobson92] 的接收器,SACK 选项有空间包含三个 SACK 块。因此,每个SACK块通常将重复至少三次,如果需要,在三个连续ACK分组中的每一个中重复一次。然而,如果报告特定 SACK 块的所有 ACK 数据包都被丢弃,则发送方可能会假设尚未收到该 SACK 块中的数据,并不必要地重新传输这些段。
其他 TCP 选项的部署可能会将可用 SACK 块的数量减少到 2 个甚至 1 个。这将减少存在丢失 ACK 时 SACK 传递的冗余。即便如此,在不必要的数据包重传方面,TCP SACK 的暴露程度严格小于 TCP 的当前实现的暴露程度。发送方不必要地重新传输数据所需的最坏情况在单独的文档 [Floyd96] 中进行了更详细的讨论。
在与支持 SACK 的 TCP 竞争时,没有 SACK 选项的旧 TCP 实现不会受到不公平的不利影响。这个问题在 [Floyd96] 中有更详细的讨论。
7. Sack选项示例
以下示例试图演示数据接收器生成 SACK 的正确行为。
假设左窗口边缘是 5000 并且数据发送器发送 8 个段的突发,每个段包含 500 个数据字节。
情况 1:接收前 4 个分段,但丢弃最后 4 个分段。
数据接收方将返回一个正常的 TCP ACK 段,确认序列号 7000,没有 SACK 选项。
情况 2:第一个分段被丢弃,但其余 7 个分段被接收。
在收到最后七个数据包中的每一个后,数据接收器将返回一个 TCP ACK 段,该段确认序列号 5000 并包含一个 SACK 选项,指定一个排队数据块:

情况 3:丢弃第 2、第 4、第 6 和第 8(最后)段。
数据接收方正常确认第一个数据包。 第三个、第五个和第七个数据包触发 SACK 选项如下:

假设此时,第 4 个数据包被乱序接收。 (这可能是因为数据在网络中被严重乱序,或者因为第 2 个数据包被重传并丢失,然后第 4 个数据包被重传)。 此时,数据接收方只有两个 SACK 块要报告。 数据接收方回复以下选择性确认:

假设此时,接收到第 2 个分段。 然后数据接收器回复以下选择性确认:

8. 数据接收器叛变
请注意,允许数据接收方丢弃其队列中尚未向数据发送方确认的数据,即使该数据已在 SACK 选项中报告。不鼓励这样丢弃 SACK 数据包,但如果接收器耗尽缓冲区空间,则可以使用。
数据接收者可以选择不保留它在 SACK 选项中报告的数据。在这种情况下,接收器 SACK 生成额外限定:
* 第一个 SACK 块必须反映最新的段。即使最新的段将被丢弃并且接收器已经丢弃了相邻的段,第一个 SACK 块必须至少报告最新段的左右边缘。
* 除最新段外,所有 SACK 块不得报告任何不再由接收器实际持有的旧数据。
由于数据接收方稍后可能会丢弃在 SACK 选项中报告的数据,因此发送方在数据被 TCP 报头中的确认编号字段确认之前不得丢弃数据。
9. 安全考虑
本文档既没有加强也没有削弱 TCP 当前的安全特性。
TCP的SACK(选择性确认)机制通过允许数据接收方告知发送方哪些数据段已成功接收,提高了在多包丢失情况下的性能。本文档详细介绍了SACK的工作原理,包括SACK选项的格式、生成及数据发送者和接收者的处理策略,讨论了其在拥塞控制和效率方面的影响,并提供了一些示例。
1783

被折叠的 条评论
为什么被折叠?



