4. 相对于RFC 6937的变更 (Changes Relative to RFC 6937)
自[RFC6937]以来,最大的变更是引入了一个新的启发式方法,该方法使用良好的恢复进展(对于TCP,当最新的ACK推进SND.UNA且不指示先前的快速重传已丢失时)来选择降低边界(PRR-CRB或PRR-SSRB)。
[RFC6937]将降低边界的选择留给实现者自行决定,但建议默认使用PRR-SSRB。对于早期PRR研究中探索的所有环境,新的启发式方法与旧的建议是一致的。
SafeACK启发式方法的引入
论文"互联网范围的流量管制分析"[Flach2016policing]发现了一个之前未探索的关键情况,在该情况下,两种降低边界的性能都很差,但原因不同。
令牌桶管制器的挑战
在许多配置下,令牌桶流量管制器(token bucket traffic policers)可以在令牌耗尽时突然开始丢弃大部分流量,而不向终端系统发出任何警告。传输拥塞控制没有机会测量令牌速率,并根据先前观察到的路径性能设置ssthresh。这个ssthresh值可能导致数据速率远大于令牌补充速率,从而导致高丢包率。
在这些条件下,两种降低边界的性能都很差:
- PRR-CRB过于保守 - 有时导致在比必要更小的窗口下进行非常长时间的恢复
- PRR-SSRB过于激进 - 经常导致多轮重传丢失,两种情况都导致恢复时间延长,严重影响应用延迟和/或吞吐量
SafeACK解决方案
调查这些环境导致开发了"SafeACK"启发式方法来动态切换降低边界:
- 默认使用PRR-CRB - 保守地开始恢复
- 切换到PRR-SSRB的条件 - 仅当ACK指示恢复进展良好时(SND.UNA前进且未检测到任何新的丢包)
SafeACK启发式方法在Google的内容分发网络(CDN)[Flach2016policing]中进行了实验,并自2015年以来在Linux TCP中实现。
应用场景
SafeACK启发式方法仅在以下情况下调用:
- 丢包、应用程序受限行为或其他事件导致当前飞行中数据估计低于ssthresh
- 高丢包率使得启发式方法至关重要,这仅在存在严重丢包时才常见,例如流量管制器[Flach2016policing]
- 在这些环境中,启发式方法的性能优于单独使用任一边界
RecoverFS计算改进
另一个PRR算法变更改进了当发送方在大量序列空间已被SACKed后进入恢复时的发送过程。
这种情况可能发生在发送方先前检测到重新排序时,例如通过使用[RFC8985]。在PRR的先前版本中,RecoverFS没有正确考虑在进入快速恢复之前SACKed的序列范围,这导致PRR最初发送过慢。通过此变更,PRR正确考虑了在进入快速恢复之前SACKed的序列范围。
强制快速重传
另一个变更是在触发恢复的第一个ACK上强制进行快速重传。
以前,根据丢包情况,PRR可能不允许在快速恢复的第一个ACK上进行快速重传(即SndCnt为0)。强制快速重传对于维持ACK时钟和避免潜在的重传超时(RTO)事件很重要。
强制快速重传仅在整个恢复期间发生一次,并且仍然遵循PRR中的包守恒原则。此启发式方法自2011年首个广泛部署的TCP PRR实现[First_TCP_PRR]以来就已实现。
退出恢复时设置cwnd
在另一个变更中,退出恢复时,数据发送方将cwnd设置为ssthresh。这对于稳健的性能很重要。
如果在恢复结束时不将cwnd设置为ssthresh,在应用程序受限的发送方行为和某些丢包模式下,cwnd可能在快速恢复结束时远低于ssthresh,导致性能不佳。在某些情况下,性能可能比[RFC6675]恢复更差,后者只是在恢复开始时将cwnd设置为ssthresh。
这种在恢复结束时将cwnd设置为ssthresh的行为自2011年首个广泛部署的TCP PRR实现[First_TCP_PRR]以来就已实现,并且类似于[RFC6675],后者规定在恢复开始时将cwnd设置为ssthresh。
ECN支持
自[RFC6937]编写以来,PRR还被适配为对非基于丢包的拥塞控制算法执行乘法窗口减少,例如对于[RFC3168]中规定的显式拥塞通知(Explicit Congestion Notification, ECN)。
这可以通过使用丢包恢复状态机的某些部分(特别是来自[RFC6675]的RecoveryPoint)来实现,以便对正好一个往返时间的ACK调用PRR ACK处理。
然而,使用PRR与主动队列管理(Active Queue Management, AQM)和ECN的方法之间可能存在交互;[RFC9743]中提供了拥塞控制机制的开发和评估指南。