摘要

  • RFC 3208 不要求每位接收者对每个数据包作肯定应答,而让发现序列缺口的接收者发出 NAK;网络节点合并同一损失的反馈,并记录需要修复的下游接口。
  • NAK Confirmation 只确认负向请求在这一跳得到处理。它既不是丢失数据本身,也不证明源端仍可修复、RDATA 已穿过正确分支,或未知成员都已恢复。

可靠传输最诱人的数字,往往是“已确认”。在点到点连接里,它很容易被理解为对端已经收到某件东西。到了组播树,这个词必须先回答另一个问题:究竟确认了什么,又是谁有资格作证?

PGM 面对的是一对多分发。若每发一个数据包,成千上万的接收者都返回 ACK,反馈流本身就可能淹没源端与网络。这不是偶发的性能瑕疵,而是规模结构造成的确认爆炸。

RFC 3208 因而把正常状态设为安静。源端发送带序列号的 Original Data,也就是 ODATA。每个接收者自行观察序列;只有看见缺口,才以选择性的 negative acknowledgement 请求修复。协议把正向成功收据换成负向异常证据。

这个选择同时放弃了全局成员账本。PGM 没有组成员模型,源端并不知道谁在听、谁刚加入、谁已经离开。它不适合要求“已知名单中每个人都确认收货”的应用,也不向多源应用提供一个统一的全序。

因此,PGM 的可靠性从接收者一侧表达:只要数据仍在适用的传输窗口内,接收者要么取得原始或修复数据,要么能够发现不可恢复的损失。这里没有一张由源端签署的全体成功清单。

发现缺口后,接收者并不直接把 NAK 广播给整个组,而是以单播送往数据来路上的最后一个 PGM 网络节点。它会重试,直到在对应接口听见 NAK Confirmation,简称 NCF。

网络节点收到 NAK 后,向下游接口发出 NCF,同时把请求转发给上游的下一台 PGM 邻居。上游节点也以同样方式确认与转发,直至请求抵达源端。确认被刻意限制在一跳之内;路由节点不会把某个 NCF 当成端到端收据继续传播。

这使 NCF 的语义非常具体:此处已经处理了这项负向请求。它没有携带丢失的数据,不表明源端仍在缓存相应序列,也不表明某个本地修复者已经响应,更不表明修复穿过了所有需要它的分支。

收到请求时,节点会建立 repair state。状态以传输会话和丢失序列为关键线索,并记录 NAK 从哪些下游接口而来。NAK 得到确认后,原始请求报文可以消失;之后真正控制修复路径的是这份状态,而不是保存下来的 NAK,也不是 NCF。

当 Repair Data,也就是 RDATA,沿树返回时,节点只向状态中登记的接口转发。这样,修复不会再次泛洪整个组,而只进入报告过缺失的子树。如果没有匹配状态,默认行为是丢弃 RDATA。

于是,正确的修复包与允许它通过的状态成为两件不同的事实。源端可能确实发出了正确序列,但某条分支若没有成功安装状态,仍然收不到它。某一跳确认 NAK,也不能证明反向请求路径和正向修复路径都已经闭合。

Source Path Message,SPM,为 NAK 建立反向方向。源端把 SPM 穿插在数据流中,沿途节点更新上游路径地址,接收者由此知道请求应送向谁。NAK 所走的,是原始分发树的逆向线索。

SPM 还公布传输窗口边界。窗口后沿说明最老的可修复序列。如果接收者察觉缺口时,目标包已经落到后沿之外,再多一次请求也无法让不存在的缓存重新出现。协议承诺的结果可能只是明确知道损失不可恢复。

由于 NAK 是修复的唯一触发器,PGM 不能让一项请求轻易无声消失。即使近期没有 ODATA,周期性的 SPM 也会促使接收者重新检查缺口。接收者分别管理“等待 NCF”和“等待 RDATA”的定时器;听见确认,不会自动终止对实际修复的等待。

同一次链路丢包可能影响许多接收者。它们不会立即同时发言,而是各自等待随机退避。如果在等待期间听见匹配的 NAK 或 NCF,就压制自己的 NAK,把别人的请求当作同一缺口已经有人报告的信号。

路由节点也会合并重复请求。若相同会话与序列的修复状态已经存在,节点可以把新的下游接口加入列表,却不再向上游转发另一个 NAK。理想情况下,数百个受影响接收者最终只让源端看见一项请求。

这正是扩展性的来源,也是计数信息消失的地方。抵达源端的单个 NAK 不会报告有多少接收者因抑制而保持沉默;下游的一个 NCF 不列出谁仍在等待;状态中的一个接口也不说明其后有几个主机以及它们是否仍在组内。

修复数据甚至不一定由原始源端物理发送。Designated Local Repairer,DLR,可以保存数据并就近响应。它产生的 RDATA 仍使用原传输会话标识,使修复落入正确的序列空间。会话身份保持连续,并不等于字节一定由最初源端发出。

选择 DLR、宣告它可用、再把 NAK 重定向过去,都是独立步骤。可用宣告不证明 DLR 还保存着所需序列;重定向不证明请求抵达;相同的会话标识也不证明接收者接受了返回结果。

传输窗口同时是一项策略。数据驱动的窗口前移可以因边缘序列仍有待修 NAK 而放慢,让完整性多获得时间,却增加延迟。时间驱动的窗口则可在修复尚未结束时继续前进,保护时效性,却允许旧损失永久越界。

两种策略都可能生成完全相同的 NCF。只看确认报文,无法知道源端会把数据保留多久,也不能推断运营者选择了完整性还是节奏。必须把窗口轨迹与确认轨迹分别记录。

Forward Error Correction 改变的是修复材料,不是证据边界。RDATA 可以是原包副本,也可以是用于重建的奇偶数据。对 FEC 请求的 NCF 仍只确认某个数量的修复符号被请求;接收者还得真正收到足够片段,并成功解码。

RFC 3208 被列为 Experimental,这个限定不可省略。文档的适用性说明把拥塞控制、路由辅助、本地重传和编程接口都描述为仍需实践的领域。RFC 2357 提供了评价可靠组播方案的标准,而 RFC 3208 给出一套可实验的协议机制,并非对部署规模或性能效果的事后证明。

安全分析也沿着状态链展开。伪造 SPM 可以改写上游路径;伪造 NAK 可以耗尽路由状态;伪造 NCF 可以让请求过早停止上行;伪造 RDATA 则可能先拆除合法修复状态,使真正修复随后无路可走。

攻击者未必需要伪造应用内容。只要操纵那些决定路径的表示——谁看似在上游、哪个接口看似丢包、请求是否仍然存活、哪份修复可以关闭状态——就可能改变结果。对源端、接收者、DLR 与路由节点的全面认证,不在基础机制的简洁承诺之内。

RFC 3208 留下的历史教训不是“确认没有用”。恰恰相反,NCF 让唯一的修复请求不至于悄然丢失。它之所以可靠,是因为它只说一件有限的事:这个位置听见了 NAK。若把这句话升级成“修复已到达”,协议为规模所做的压缩就会被管理系统误写成并不存在的交付事实。