摘要

  • RFC 1553 可把 30 个八位组的 IPX 报头压为一至七个,把 36 个八位组的 NCP/IPX 报头压为一至八个;省略的字段保存在压缩端与解压端相互对应的槽位中。
  • 普通 IPX 上下文必须先由 Confirmed Initial 与 Confirm 建立,后续压缩包才能依赖它;NCP 只因自身序号与重传能暴露上下文破裂,才有较窄的未确认路径。
  • 连槽位号也省略时,解压器必须获知每次接收错误;一旦发生丢弃,就要拒绝继续使用隐含槽位,直到显式槽位号重新建立同步。

线上越短,历史越长

一个八位组的标志越过广域链路,看起来像其余报头已经不再重要。实际情况相反:发送方在槽位里保存完整旧报头,接收方也保存一份。两端只有把同一槽位理解为同一连接的同一代,短包才有确定含义。

RFC 1553 于 1993 年 12 月按 Standards Track 发布,现标记为 Historic。它把这套机制称为 CIPX。通用方法将 30 个八位组的 IPX 报头压至一至七个;另一种必备方法针对 0x2222 与 0x3333 两类 NCP 请求和应答,把 36 个八位组的 NCP/IPX 报头压至一至八个。其他 NCP 类型仍可使用通用 IPX 压缩。

CIPX 一旦协商完成,哪怕某个 IPX 包以常规未压缩形式发送,也要带 CIPX 标志。它不是每包各自决定的一套缩写,而是一段持续累积状态的对话。

这正是单八位组形式最容易被误读的地方。线上所见越短,并不意味着协议知道得越少;相反,它要求两端在线下保存得更多。短包不是一份自足消息,而是对一段共同历史的引用。只看当前包,就像只保存数据库查询里的行号,却删掉了行号所指向的版本。

文档状态也不能代替运行证据。1993 年的 Standards Track 说明这是一份当时进入标准轨道的规范,今天的 Historic 说明其后续分类;两者都不能证明某台设备实现过 CIPX,更不能证明实现保持了两张表的一致。

被省略的字段其实在引用槽位

压缩器把新报头与发送槽中的旧报头比较,只发变化;解压器把这些变化应用于接收槽,重建完整报头。最短形式只有标志,全部未出现字段都由此前状态补出。

因此,孤立的压缩帧不能证明最后重建了哪些字节。还必须保留槽表、代标识以及把它们带到当前状态的转换。如果同时使用数据压缩,顺序也构成证据:发送先压报头再压数据,接收先解数据再解报头。

顺序还决定观察点。位于数据解压之前的抓包,与报头重建之后的抓包,不是在记录同一对象。如果日志只写“解压成功”,便可能把两个不同动作折叠成一个模糊结论。数据解压成功不证明槽位正确,槽位正确不证明 NCP 交换完成,应用有响应也不反向证明每个被补出的字段都来自正确一代。

常规形式同样没有退出这段状态会话。CIPX 协商之后,未压缩 IPX 也携带标志八位组。它提供的是把更多信息重新放回线路的一条退路,而不是让旧表自动失效的魔法开关。

确认把记忆变成了权威

普通 IPX 报头缺少足以可靠识别首包重传的序号。若设定上下文的首包丢失,发送端可能继续按新槽压缩,而接收端还停在旧含义。RFC 1553 因而要求先发送带槽位号和单八位组 ID 的 Confirmed Initial,收到 Confirm 后才让后续压缩包依赖该关联。

槽位改存另一个报头时,ID 要递增。槽位与 ID 合起来标记一代含义,而非一个永久位置。文档所谓“足够长”的唯一期还取决于链路速度、往返时延和负载。

位置与代是两件事。槽位号回答“去哪一格找”,ID 回答“这一格的哪一次占用才有效”。若没有后一层,旧连接的迟到包只要碰巧引用同一槽位,就可能被新连接接纳。单八位组 ID 最终会回绕,所以它提供的是与速度、时延和复用频率相匹配的时间窗口,并非永久身份。

等待确认也不要求发送端停止一切数据。它可以用同一槽位与 ID 重发属于同一报头的新数据,也可以在 ID 递增后把槽位交给另一报头。设计允许进展,但不允许含义改变而不留下代际区别。

NCP 的 Unconfirmed Initial 是有条件的例外。它的序号与重传可以暴露上下文错位,所以能立即开始压缩;但序号若不是严格加一,就必须重新发 Initial。这里没有取消证据,只是借用了上层协议的恢复信号。

因此,“未确认”不是一种可以普遍复制的快速模式。NCP 获得这条路径,是因为具体请求—应答行为能把断裂暴露出来。若另一类流量没有同样的序号与重传语义,去掉 Confirm 只会保留即时收益,却拿走限制风险的替代信号。

确认本身也只能证明一个窄事实:接收端已经取得某槽位的某一代。它不证明后续包到达,不证明链路错误全被上报,不证明应用接受了恢复结果。把“已协商”“已确认”“已重建”“已成功”合成一个绿色状态,会替前一步虚构后几步的权威。

省掉槽位号,必须看见每一次丢失

槽位号压缩让一个包表示“沿用上一个包的槽位”。若恰好丢掉改变“上一个槽位”的那一包,两端随后的历史便可能分叉。

所以该选项默认关闭,只有 PPP 链路层能把每个错误或丢弃通知解压器时才可启用。收到丢弃通知后,解压器必须继续丢掉所有不带槽位号的包,直到一个显式槽位号抵达。跨层错误可见性不是运维附加项,而是这种省略法成立的前提。

一个本身完好的包也必须丢弃

这条规则违反一种直觉:既然后续包没有校验错误,为什么不先尝试解压?因为它缺少的不是自身完整性,而是“上一个槽位”这个词的共同指向。发送端见过改变槽位的包,接收端没有;同一个无槽位号包便会在两端引用不同历史。

猜测有时会碰巧正确,但协议不能把碰巧变成证据。接收端选择继续丢弃,直到显式槽位抵达,相当于承认:当上下文不可知时,可见损失比静默误构更安全。被丢弃的字节也许毫无损坏,它们只是没有携带足够信息来恢复唯一含义。

这让 PPP 层的错误通知成为报文格式的一部分。事后一个总丢包数不够;维护“上一槽位”的解压器必须在正确时序里知道哪一环断了。如果通知路径漏掉一次,隐含槽位选项就不只是监控较差,而是失去了设计前提。

恢复耗时也由显式包何时出现决定。若发送端长期继续使用隐含槽位,接收端会持续丢弃看似正常的流量。因此运维判断不能只看压缩比例,还要把错误之后的丢弃数量、恢复时间与应用重传放在一起。

重启与扩展不能默默污染状态

保留的首八位组让 CIPX 与以传统 0xFFFF 校验和开头的普通 IPX 报头可以区分。对端重启并恢复发送普通 IPX 时,接收方应识别并重新协商,而不是套用旧槽。Reject 包则指出不认识的包型或依赖标志,使扩展不匹配表现为可见拒绝;必要时仍可使用常规形式。

PPP 路径中的 IPXCP 选项按接收方向申请能力,双向压缩需要两端分别请求。IPX-WAN 路径则得到对称配置,两向采用相同槽数与被接受的选项子集。算法和槽数谈妥,并不能证明某个 Initial 已确认、两张表一致或应用已经成功。

两种协商几何留下两种收据

PPP 是方向性的。A 能向 B 发送压缩包,只说明 B 在该方向请求并接受了接收能力;它不能自动证明 B 向 A 的反向也成立。双向运行需要保存两次请求与各自结果,否则一个“CIPX 已开启”字段会把半条链路写成整条链路。

IPX-WAN 的结果则是对称的:两向共享槽数,并采用双方接受选项的子集。对称参数让最终配置更整齐,却没有越过状态建立过程。即使双方同意相同数值,某次 Initial 仍可能丢失,某一代仍可能不一致,应用仍可能没有恢复。

协商、上下文建立、报头重建和业务结果属于不同层。每层都有自己的执行者、失败方式与证据。若运维界面把它们压缩成一个状态,管理系统便重复了协议最危险的诱惑:在线上省略信息之后,又在记录里省略了恢复其含义所需的边界。

二比一是算式,不是现场曲线

RFC 给出的约二比一压缩比,是以 26 个八位组数据、30 个原报头和两个压缩报头为假设的算例,不是实测部署结果。文档还说 CIPX 不会显著改变 IPX 的基本安全状况;这只是当时文档的范围判断,不是对所有实现、畸形输入或后续环境的保证。

算式本身清楚:原来 26 加 30 等于 56,后来 26 加 2 等于 28。它没有包含真实流量中报头尺寸的分布,也没有计算完整 Initial、Confirm、Reject、常规回退与槽位换代的频率。错误之后因等待显式槽位而丢弃的短包,在线路统计里依然十分“高效”,对应用却没有贡献。

要把这个模型升级为运行结论,至少需要说明流量样本、测量位置、观察周期、丢包条件以及何谓有效结果。还要把 CPU、重传、恢复延迟与应用完成率纳入。同一条链路可以同时出现更短的平均报头和更差的用户结果,这两句话并不矛盾。

安全段落也有同样边界。规范作者对 IPX 基本安全性的判断,只能作为 1993 年文档的有限陈述。它没有评估所有后来实现、畸形输入、跨层组合或现代威胁。把“未显著改变”扩大成安全保证,会把缺少证据误当成证据。

本组冻结来源没有给出具名 CIPX 部署、安装规模、流量样本、互操作测试、事故或用户结果。它们证明协议规则与文档沿革,却不能说明单八位组形式实际出现过多少次,或某个产品是否正确恢复。

短报头需要更长的证据链

一次可复现判断首先要保存谁在什么方向发起协商、接受了哪些选项、共有多少槽位。然后记录槽位分配者、代 ID、完整 Initial,以及普通 IPX 路径里必需的 Confirm;若走 NCP 未确认路径,则要保存使这一例外成立的序号与重传证据。

链路错误通知、接收顺序、显式或隐含槽位选择决定了解压器当时是否有权使用那张表。长度与校验和的来源需要区分线路字段、变化量与旧状态。重建结果最好带哈希,之后再分别记录解压动作、传输恢复和应用结果。

只保存最后的完整包,会把推断伪装成收到。两次相同的重建可能来自不同证据链;同一个单八位组也可能在两张不同的表上产生不同报头。一旦旧代被覆盖、错误时序被丢弃,后来再正确重算也无法证明当时用了哪份历史。

这才是不可逆之处。算法可以升级,选项可以关闭,链路可以重新协商;被删除的状态来源却不能事后补写。凡是把信息从消息里拿走的优化,都必须在信息迁入的位置保存更清楚的收据。

完整收据应包括:协商责任方与方向、选项与槽数、槽位分配者及代 ID、完整 Initial、必要的 Confirm、链路错误通知、已接受的包序列、显式或隐含槽位、长度与校验和来源、重建报头哈希、解压动作、传输恢复和应用结果。CIPX 从线上拿走字节,只是把证明义务移到了状态里。

来源