摘要

  • 重复通知可以说明某一次重传没有必要,却不能证明同一窗口里的其他数据也都顺利到达。
  • RFC 3708 只有在前一个窗口中所有重传单元都已确认并标记为重复、且没有触发停止条件时,才允许得出可以撤销拥塞状态变化的结论。

最容易误判的情形是这样:发送端重传了 N 和 N+1 两段数据,实际丢失的只有 N;N+1 只是延迟到达。接收端把 N+1 报告为重复,发送端因此知道 N+1 的那次重传是多余的。但它还不知道网络没有丢东西——N 仍然是一次真实丢失。若据此恢复整个窗口原来的拥塞状态,就会抹掉仍然重要的损失证据。

RFC 3708 于 2004 年 2 月以 Experimental 备忘录发布,核心正是这一区分。它讨论如何谨慎利用 TCP 的重复选择确认(DSACK)和 SCTP 的重复传输序列号(TSN)通知。文中给出两类用途:协议栈可以简单计数,用于核算或监测;若发送端要撤销拥塞控制变化,则需要更严格的区分算法。

算法先检查所报告的序列范围或 TSN 是否曾被重传。如果同一窗口内重传超过一次,处理就应停止,不能恢复先前的拥塞状态。如果发送端从未重传过这段数据,重复通知也可能源于网络复制了分组。RFC 3708 随即要求在这条连接余下时间停止使用该算法,因为之后的重复报告更难归因于发送端自身的多余重传。

即使报告确实对应某次重传,也还不够。发送端还要检查前一个数据窗口里的每个重传单元。只有全部单元都已经确认并被标记为重复,算法才认为这些重传都是多余的、该窗口没有丢包。如果仍有一个重传单元没有重复标记,就不能从当前通知得出结论。另一道保护针对 TCP SACK 记分板为空、且 DSACK 左边界等于 SND.UNA 的情况:这与整窗 ACK 都丢失相符,此时继续降低发送速率仍是较保守的做法。

这套判断需要记忆更多状态:除了常规的 SACK 恢复信息,实现还须追踪哪些序列号或 TSN 已被确认并报告为重复。由此得到的是范围受限的推断,并不代表能确定接收端是否诚实,也不代表掌握了路径上的一切。RFC 3708 的安全章节特别指出,接收端可能把乱序到达误标为重复;若当时实际存在丢包,发送端就可能错误地恢复拥塞状态。

RFC 2883 规定接收端如何用 D-SACK 块编码重复数据,但不规定发送端收到后应采取什么动作。RFC 3522 的 Eifel 使用另一种证据:TCP 时间戳能更快识别虚假重传,代价是每个分组都要带时间戳选项。RFC 3708 的方法较慢,却强调两道不同的问题:单次重传是否多余,以及证据是否足以证明整个窗口无损。它检测问题,不替实现选择检测后的动作。

来源:RFC 3708、RFC 3708 状态页、RFC 2883、RFC 3517、RFC 3522、RFC 2960、RFC 4960。