RFC 3168 —— ECN:让网络学会“说话”

4 阅读8分钟

1. 核心痛点:传统 TCP 的“暴力美学”

在 ECN 出现之前,TCP 感知拥塞的唯一方式就是 丢包 (Packet Loss)

  • 逻辑:路由器缓冲区满了 -> 丢弃新到的数据包 -> 发送方发现超时或收到 3 个重复 ACK -> 判定网络拥塞 -> 减半拥塞窗口 (Cwnd)

  • 比喻:这就像开车。只有当你撞车(丢包)了,你才知道前面堵车了,然后你才减速。

  • 代价

    1. 延迟飙升:缓冲区填满需要时间,丢包重传更需要时间。
    2. 吞吐量浪费:为了触发丢包信号,必须把缓冲区填满甚至溢出,这意味着部分带宽被用来传输那些最终会被丢弃的“无用数据”。
    3. 实时性差:对于视频流、游戏、VoIP 等对延迟敏感的应用,一次丢包重传带来的卡顿是致命的。

ECN 的愿景:能不能在路由器即将满但还没满的时候,给数据包打个标记?告诉发送方:“前面有点堵,稍微松松油门”,而不是直接撞车?


2. IP 头与 TCP 头的“秘密握手”

ECN 的实现需要 IP 层 和 TCP 层 的紧密配合。它利用了 IP 头部和 TCP 头部中原本保留的位(Bits)。

2.1 IP 头部:ECN 字段 (ToS 字节的一部分)

在 IPv4 头部的 ToS (Type of Service) 字节中,最后 2 位被定义为 ECN 字段:

  • ECT(0) (ECN-Capable Transport, Codepoint 0)10。表示发送方支持 ECN。
  • ECT(1) (ECN-Capable Transport, Codepoint 1)01。表示发送方支持 ECN (RFC 3168 定义,后续 RFC 8311 更新了用法)。
  • CE (Congestion Experienced)11关键标记!  路由器当检测到拥塞时,将 ECT 标记修改为 CE,而不丢包
  • Not-ECT00。表示不支持 ECN。

2.2 TCP 头部:协商与反馈

TCP 头部利用了保留位中的 4 个位(在 TCP Header 的 Flags 区域之后):

  • Nonce Sum (NS) : 1 bit (用于防止接收方欺骗,较少关注)。
  • CWR (Congestion Window Reduced) : 1 bit。发送方告诉接收方:“我已经收到 CE 标记并减小窗口了”。
  • ECE (ECN-Echo) : 1 bit。接收方告诉发送方:“我收到了一个带 CE 标记的包,请你减速”。
  • Reserved: 1 bit.

2.3 工作流程:完美的闭环

A 第一阶段:握手协商 (Three-Way Handshake)

ECN 不是默认开启的,必须在 SYN 阶段协商。

  1. Client -> Server (SYN) :

    • 设置 IP 头 ECT(0) 或 ECT(1)
    • 设置 TCP Flag ECE=1, CWR=1 (表示支持 ECN)。
  2. Server -> Client (SYN-ACK) :

    • 如果服务器也支持,回复 ECE=1, CWR=0
    • 设置 IP 头 ECT(0) 或 ECT(1)
  3. Client -> Server (ACK) :

    • 设置 CWR=1 (确认协商成功)。
    • 此后连接进入 ECN-enabled 状态。

注意:如果任何一方在 SYN 中没设 ECE/CWR,整个连接将回退到传统丢包模式。

B 第二阶段:数据传输与拥塞标记 (The Magic Moment)

假设网络路径上有一个支持 ECN 的路由器 (RED - Random Early Detection 算法)。

  1. 正常传输:发送方发送数据包,IP 头标记为 ECT(0)

  2. 拥塞发生:路由器队列长度超过阈值 minth 但未达到 maxth (还没满)。

    • 传统行为:随机丢包。
    • ECN 行为不丢包!  将 IP 头中的 ECT(0) 改写为 CE (11) ,然后转发。
  3. 接收方反应

    • 收到带 CE 标记的包。
    • 在下一个发出的 ACK 包中,设置 TCP Flag ECE=1
    • (持续发送 ECE=1 直到收到 CWR=1)。
  4. 发送方反应

    • 收到 ECE=1 的 ACK。
    • 动作 A:像处理丢包一样,减半拥塞窗口 (Cwnd = Cwnd / 2)
    • 动作 B:设置下一个发出数据包的 TCP Flag CWR=1,告诉接收方“我已减速”。
  5. 恢复

    • 接收方收到 CWR=1 的包后,停止在 ACK 中设置 ECE。
    • 连接恢复正常,但运行在较低的速率下,避免了真正的丢包。

3. 深度案例实录:ECN vs 传统丢包

让我们模拟一个缓冲区即将溢出的瞬间,对比两种机制的表现。

场景:链路带宽 1Gbps,路由器缓冲区大小 100 个包。当前队列已有 95 个包。发送方以 1.2Gbps 的速度突发发送。

3.1 传统 TCP (Drop Tail)

时间事件路由器动作发送方感知后果
T1新包到达 (第 96-100 个)放入队列。无感知。队列满。
T2新包到达 (第 101 个)丢弃 (Drop)无感知 (包没了)。队列满。
T3新包到达 (第 102-110 个)全部丢弃无感知。大量数据丢失
T4超时/3 Dup ACK(无)检测到丢包Cwnd 减半
T5重传(无)重传第 101-110 号包。延迟增加 1 RTT + 重传耗时
结果丢了 10 个包吞吐量波动大用户体验:卡顿

3.2 ECN Enabled (RED + ECN)

表格

时间事件路由器动作发送方感知后果
T1新包到达 (第 96 个)队列 > 阈值。将 IP 头 ECT 改为 CE。转发。无感知 (包到了)。队列维持在高位但未溢出。
T2新包到达 (第 97-100 个)继续标记 CE。转发。无感知。所有数据都到达了。
T3接收方收到 CE 包构造 ACK,设置 ECE=1收到 ECE=1立即 Cwnd 减半
T4发送方减速发送速率降低。设置 CWR=1 告知接收方。队列开始自然下降。
T5恢复队列回落至安全线。停止标记 CE。收到 CWR 确认,停止 ECE。零丢包,平滑过渡
结果0 个包丢失吞吐量平滑用户体验:流畅

核心优势

  • 低延迟:避免了重传带来的 RTT 增加。
  • 高吞吐:没有带宽浪费在重传丢失的数据上。
  • 公平性:ECN 能让所有流更公平地分享带宽,避免“激进”的 TCP 实现占满缓冲区导致其他流饿死。

4. 生产环境实战:为什么 ECN 还没普及?

既然 ECN 这么好,为什么我们在 sysctl 里经常看到它默认关闭,或者抓包很少见到?

4.1 三大拦路虎

4.1.1 中间设备“乱改标记” (The Middlebox Problem)

这是最大的障碍。RFC 3168 发布时,很多老旧的防火墙、NAT 网关、负载均衡器不认识 ECN 位

  • 愚蠢的防火墙:看到 IP 头 ToS 字段非 0,认为是不合法的攻击包,直接丢弃
  • 有状态的 NAT:修改了 IP 地址,却忘记同步更新 ECN 校验和(虽然 ECN 本身不需要校验和,但某些实现逻辑混乱),导致连接中断。
  • 结果:开启 ECN 可能导致连通性下降。这就是著名的 "ECN Blackhole" 问题。

4.1.2 操作系统默认保守

  • Linux: 默认 net.ipv4.tcp_ecn = 2 (仅在新建连接时尝试协商,如果对方 SYN 没回应或中间设备干扰,自动回退)。这是一个非常聪明的折中方案。
  • Windows: 早期版本默认关闭,Windows 10/Server 2016+ 逐渐开放,但仍受组策略控制。
  • iOS/Android: 移动端由于网络环境复杂(各种奇葩基站和 NAT),默认策略较为保守。

4.1.3 路由器配置复杂

  • ECN 需要配合 RED (Random Early Detection)  或 CoDel/FQ-CoDel 队列管理算法才能生效。
  • 很多运营商路由器的默认配置依然是简单的 Drop Tail (满了就丢),根本不会去标记 CE。如果没有路由器的配合,ECN 就是个摆设。

4.2 如何检查和开启 ECN (Linux)

# 查看当前 ECN 策略
sysctl net.ipv4.tcp_ecn

# 输出含义:
# 0 = 完全关闭 ECN
# 1 = 强制开启 ECN (如果中间设备不支持,可能导致连接失败,慎用!)
# 2 = 智能模式 (默认值):发起连接时尝试 ECN,如果握手失败或检测到问题,自动禁用该连接的 ECN。

推荐配置:保持默认的 2。这是最安全的做法。

sysctl -w net.ipv4.tcp_ecn=2

5. 进阶:ECN 与现代拥塞控制 (BBR)

RFC 3168 是基础,但现代网络正在超越它。

  • TCP BBR (Bottleneck Bandwidth and Round-trip propagation time) :

    • Google 开发的新一代拥塞控制算法。
    • BBR 与 ECN 的关系:BBR 极度依赖 ECN。BBR 不通过丢包来判断拥塞,而是通过测量带宽和 RTT。但如果开启了 ECN,BBR 会将 CE 标记作为更强的拥塞信号,更早地降低发送速率,从而获得比纯 BBR 更低的延迟。
    • 现状:在 YouTube、Google 搜索等内部网络,BBR + ECN 是标配,实现了极致的流畅度。
  • Data Center TCP (DCTCP) :

    • 数据中心专用。利用 ECN 标记的比例来精确调整窗口,而不是简单的“减半”。
    • 在微秒级延迟要求的场景下,DCTCP 是绝对的主力。

6. 总结:ECN 的核心价值与未来

特性传统 TCP (Loss-Based)ECN TCP (RFC 3168)
拥塞信号丢包 (隐式,滞后)CE 标记 (显式,实时)
缓冲区状态必须填满甚至溢出维持在阈值附近
延迟表现高 (Bufferbloat + 重传)低 (平滑控制)
带宽利用率有浪费 (重传丢包)极高 (零丢包拥塞控制)
部署难度低 (默认行为)中 (需端到端 + 路由器支持)

“ECN 是 TCP 从‘野蛮生长’走向‘文明驾驶’的关键一步。它让网络基础设施从沉默的‘抛包者’变成了智慧的‘交通指挥员’。”

未来的趋势
随着 IPv6 的普及(IPv6 头部原生设计更友好)和 QUIC (HTTP/3) 的崛起(QUIC 在用户态原生支持 ECN,且不受中间设备 IP 头篡改的影响),ECN 的部署障碍正在被逐个清除。下一代互联网,必然是 ECN 无处不在的网络。