3.2. Fast Retransmit/Fast Recovery
Receiver 行为
当 out-of-order segment 到达时, TCP receiver 应该立即发送 duplicate ACK. 此 ACK 的目的是告知 sender 收到了乱序 segment, 以及期望的 sequence number.
Duplicate ACK 的成因
从 sender 的角度看, duplicate ACKs 可能由多种网络问题造成:
- Dropped segments: dropped segment 之后的所有 segments 都会触发 duplicate ACKs, 直到丢失被修复
- 网络对 data segments 进行 re-ordering (在某些网络路径上并不罕见 [Pax97])
- 网络对 ACK 或 data segments 进行 replication
用于填补间隙的 ACK
此外, 当 incoming segment 填补 sequence space 中的全部或部分 gap 时, TCP receiver 应该立即发送 ACK. 这会为通过 retransmission timeout, fast retransmit 或高级 loss recovery 算法从丢失中恢复的 sender 生成更及时的信息, 如 section 4.3 所概述.
Fast Retransmit 算法
TCP sender 应该基于 incoming duplicate ACKs 使用 "fast retransmit" 算法检测并修复丢失.
fast retransmit 算法将 3 个 duplicate ACKs 的到达 (按 section 2 定义, 中间没有任何推进 SND.UNA 的 ACK) 作为 segment 已丢失的指示. 收到 3 个 duplicate ACKs 后, TCP 会重传看似缺失的 segment, 而不等待 retransmission timer 过期.
Fast Recovery 算法
fast retransmit 算法发送看似缺失的 segment 后, "fast recovery" 算法控制新数据传输, 直到 non-duplicate ACK 到达.
理由
不执行 slow start 的原因是, 收到 duplicate ACKs 不仅表示某个 segment 已丢失, 还表示 segments 很可能正在离开网络 (尽管网络中的大量 segment duplication 可能使这一结论失效).
换言之, 由于 receiver 只能在某个 segment 已到达时生成 duplicate ACK, 该 segment 已离开网络并位于 receiver 的缓冲区中, 因此我们知道它不再消耗网络资源. 此外, 由于 ACK "clock" [Jac88] 得以保留, TCP sender 可以继续传输新 segments (尽管传输必须继续使用降低后的 cwnd, 因为丢失是拥塞的指示).
Fast Retransmit 和 Fast Recovery 实现
fast retransmit 和 fast recovery 算法按如下方式一起实现:
1. 第一个和第二个 Duplicate ACK
sender 收到第一个和第二个 duplicate ACKs 时, 如果满足以下条件, TCP 应该按 [RFC3042] 发送一个此前未发送数据的 segment:
- receiver 的 advertised window 允许
- 总 FlightSize 将保持小于或等于 cwnd 加 2*SMSS
- 有新数据可供传输
此外, TCP sender 不得改变 cwnd 以反映这两个 segments [RFC3042].
Note: 使用 SACK [RFC2018] 的 sender 不得发送新数据, 除非 incoming duplicate acknowledgment 包含新的 SACK 信息.
2. 第三个 Duplicate ACK
收到第三个 duplicate ACK 时, TCP 必须将 ssthresh 设置为不超过 equation (4) 给出的值. 使用 [RFC3042] 时, limited transmit 中发送的额外数据不得纳入此计算.
3. 重传并膨胀 Window
从 SND.UNA 开始的 lost segment 必须被重传, 且 cwnd 设置为 ssthresh 加 3*SMSS. 这会按已经离开网络并由 receiver 缓冲的 segments 数量 (三个) 人为 "inflates" congestion window.
4. 额外 Duplicate ACKs
对于收到的每个额外 duplicate ACK (第三个之后), cwnd 必须增加 SMSS. 这会人为膨胀 congestion window, 以反映已经离开网络的额外 segment.
关于伪造 Duplicate ACKs 的说明
Note: [SCWA99] 讨论了一种基于 receiver 的攻击, 即向 data sender 发送许多 bogus duplicate ACKs, 以人为膨胀 cwnd 并导致使用高于适当水平的发送速率. 因此, TCP 可以将 loss recovery 期间 cwnd 被人为膨胀的次数限制为 outstanding segments 的数量 (或其近似值).
关于 FlightSize 膨胀的说明
Note: 未使用高级 loss recovery 机制 (如 section 4.3 所概述) 时, FlightSize 的这种增加可能导致 equation (4) 轻微膨胀 cwnd 和 ssthresh, 因为 SND.UNA 与 SND.NXT 之间的一些 segments 被假定已离开网络, 但仍反映在 FlightSize 中.
5. 发送此前未发送的数据
当此前未发送的数据可用, 且 cwnd 新值和 receiver 的 advertised window 允许时, TCP 应该发送 1*SMSS 字节的此前未发送数据.
6. 收缩 Window
当下一个确认此前未确认数据的 ACK 到达时, TCP 必须将 cwnd 设置为 ssthresh (step 2 中设置的值). 这称为 "deflating" window.
此 ACK 应是 step 3 中重传所引发的 acknowledgment, 在重传一个 RTT 后到达 (不过在 receiver 处存在显著 data segments 乱序交付时, 它可能更早到达).
此外, 如果 lost segment 与收到第三个 duplicate ACK 之间发送的所有中间 segments 均未丢失, 此 ACK 应确认所有这些中间 segments.
限制
Note: 已知该算法通常无法从单个 flight of packets 中的多次丢失高效恢复 [FF96]. 下文 section 4.3 处理这类情况.