ECN 用 IP 头里的两位表示拥塞,路由器因此可以标记,而不必先丢掉这个包。截至 2026 年 10 月,这两位能否穿过 VPN,取决于隧道有没有把它们抄到外层,并在拆包时把 CE 合回内层。外层被清成 Not-ECT 时,隧道这一段的拥塞仍只表现为丢包或排队。

两位分别表示什么

一个可独立引用的定义句:显式拥塞通知(ECN,RFC 3168)是 IP 头里的两位字段。支持 ECN 的传输把包标成 ECT,路由器在拥塞时可以把 ECT 改成 CE,而不是丢弃。

IPv4 原先的 TOS 字节和 IPv6 的流量类别,都是这八位。高六位是差分服务码点,低两位才是 ECN。四个码点是:

二进制名称表示什么
00Not-ECT这段传输不使用 ECN
10ECT(0)支持 ECN,当前没有被标成拥塞
01ECT(1)在 RFC 3168 里同样表示支持 ECN;另有后来的读法,见下文
11CE路径上某一跳已经把拥塞写进这个包

名称里的数字和二进制的左右顺序并不对应:ECT(0) 是 10,ECT(1) 是 01。路由器可以把 ECT(0) 或 ECT(1) 改成 CE。它不该把 Not-ECT 改成 CE,因为不支持 ECN 的传输只把丢包当成拥塞信号。

一个可独立引用的结论句:CE 表示这个包已经到达,并且路径报告了拥塞。它同时留下了这个包,供接收方继续使用。

端点怎样把标记用起来

TCP 在握手时协商。据 RFC 3168,同时带有 ECE 和 CWR 的 SYN,表示这一端支持 ECN。协商成功之后,数据段可以带着 ECT 发出。接收方见到 CE,就在随后的确认里置上 ECE,直到收到发送方用 CWR 表明已经对这次拥塞作出反应。

发送方把这一轮 ECE 当作一次拥塞信号,减小还可以在途的数据量。被标成 CE 的那个段已经到达,接收方不必只因为它带了 CE 就等待重传。窗口具体怎么减,由这条连接的拥塞控制决定,见 拥塞控制。

QUIC 不使用 TCP 的这两个标志。据 RFC 9000,确认帧里报告收到的 ECT(0)、ECT(1) 和 CE 各有多少。发送方校验这些计数;校验失败时,停止在这条路径上使用 ECN,之后改靠丢包判断拥塞。QUIC 与隧道的其他关系见 HTTP/3 与 QUIC。

两个都叫 ECT 的码点,读法要分开。RFC 3168 把 ECT(0) 和 ECT(1) 都定义为支持 ECN、尚未被标成拥塞。RFC 6040 在合并隧道两侧的字段时,把严重程度从高到低写成 CE、ECT(1)、ECT(0)、Not-ECT,并写明这是为了给当时讨论的预拥塞通知留位置,也允许把两种 ECT 看成同一严重程度。据 RFC 9331,希望获得 L4S 待遇的发送方必须把 ECN 字段设为 ECT(1)。这里的 ECT(1) 是低延迟队列的标识。CE 仍然表示已经经历拥塞。

隧道上的合并规则仍以 RFC 6040 为准。RFC 9331 第 6.1 节写明,它不要求改这些规则。L4S 改变的是端点和队列如何理解 ECT(1)。正常模式的入口原样抄这两位,因此不会把 ECT(0) 抄成 ECT(1)。某一段路径上有没有 L4S 队列,本文没有测量。

进隧道和出隧道各改哪一层

一个可独立引用的定义句:据 RFC 6040,无论哪种封装模式,入口都不得改写内层那两位。正常模式把内层的两位原样抄到外层,兼容模式把外层写成 Not-ECT。

中间路由器只看得见外层,拥塞标记写在外层上。拆包端再按内层和外层的组合,决定出去的那个包带哪一个码点。

情形外层拆包之后
正常模式,内层是 ECT,途中没有标记与内层相同的 ECT仍是那个 ECT
正常模式,外层被改成 CE,内层原本是 ECTCE出去的包带 CE,内层传输才能看见
兼容模式Not-ECT外层没有 CE 可以合回。内层原有的码点还在,隧道这一段的拥塞没有写成 CE
内层是 Not-ECT,外层却是 CE正常入口不该造出这种组合据 RFC 6040,必须丢弃,不能把 CE 写进不支持 ECN 的内层

最后一行里的丢弃,对不支持 ECN 的传输来说,仍然是它认得的那种信号:包没有到。把 CE 写进内层再送出去,对方不会按 ECN 来理解。

据 RFC 6040,符合 RFC 4301 的 IPsec 入口使用正常模式,也就是把两位抄到外层。拆包端要按 RFC 6040 的表把外层的 CE 合回去。某一台设备的固件是否已经按 2010 年的这张表实现,本文没有测量。兼容模式是为了迁就不会传播 ECN 的旧拆包端。它表示外层声明自己不使用 ECN。

和丢包、排队各看什么

缓冲区膨胀 描述的是包在瓶颈队列里等候。ECN 是队列在溢出之前就可以发出的显式信号,前提是这一跳确实会标记,而且标记没有在隧道里被清掉。只有排队、没有标记时,发送方要等到延迟升高或开始丢包才减速。

TCP 与 UDP 决定外层用哪一种传输。ECN 写在 IP 头上,不代替这个选择。外层是 TCP 时,内外两层仍各自做重传。外层那两位被清掉,只说明显式标记没穿过。

据 RFC 9331 第 6.1 节,不传播 ECN 的隧道里,L4S 流量仍可穿过,但在隧道内部,外层头呈现为经典流量,不带 L4S 标识。路径上的低延迟队列若只看外层,在这一段就分不出 ECT(1)。

第 6.2 节写的是重放保护:同一条安全关联里如果混有 L4S 和经典流量,出口的重放窗口可能把排队更久的那一类当成过旧的包丢掉。窗口和乱序的一般关系见 重放保护。该节把窗口加大到能容纳这种延迟差列为优先办法。本文不讨论放宽或关闭重放保护的配置。

一个可独立引用的结论句:隧道图标亮着,既不表示 ECN 已经协商成功,也不表示 CE 能从服务器这一侧回到应用。

现象对照

现象更可能先看什么
只有丢包才会降速,路径上从未出现 CE端点没协商 ECN,或外层被写成了 Not-ECT
QUIC 开始用过 ECN,随后不再使用计数校验失败,发送方停用了这条路径上的 ECN
队列变深之后才靠丢包恢复这一跳没有在溢出前标记,或标记没有合回内层
内层是 Not-ECT,拆包处仍丢包外层若是 CE,RFC 6040 要求丢弃。其他丢包原因可以同时存在
经典流量和低延迟流量走同一条隧道,一类被窗口丢掉重放窗口把延迟差当成了过旧报文

核对清单

  1. 先看内层传输有没有协商 ECN:没有 ECT,就没有 CE 可以合回;
  2. 再看外层是抄来的两位,还是 Not-ECT:兼容模式和清位都会让隧道这一段写不上 CE;
  3. 把 CE 和丢包分开记:CE 表示包已经到达;Not-ECT 配上外层 CE 时,拆包端按规范应当丢弃;
  4. ECT(1) 按场合读:在 L4S 里它是队列标识,拥塞仍由 CE 表示;隧道合并仍用 RFC 6040;
  5. 重放窗口造成的丢包另记:那是编号落在窗口外,不是 ECN 码点本身。