Linux TCP 最新的 ECN patch:从 ECN nonce 到 Accurate ECN

最新的 Linux kernel TCP 有引入一系列的派驰,比较有趣的是几个 Accurate ECN 相关的:

ECN 是一种网络拥塞控制机制,它允许路由器在遇到拥塞时,不是直接丢弃数据包,而是在 IP 头做个 CE 标记,receiver 收到该标记后,通过 ACK 通知 sender 发生了拥塞,sender 随后会降窗。这就是 ECN 的大致,具体看 RFC3168。

ECN 基于全链路的信任,它假设 receiver 会诚实 echo 它收到的拥塞信号,但一个 “恶意” 或 “自私” 的 receiver 可能会选择不报告该拥塞信号,因为如果它不报告拥塞,发送端就不会降速,从而可能为这个 receiver 维持更高的吞吐,这种行为显然损害了网络公平性。

后面我将提到,这又是一个臆想出来的问题,但却为该问题提供了一个精妙的方案,很可能是先有了如此精妙的方案,然后硬设了一个问题。

来看 rfc3540 的 ECN nonce 如何。

ECN nonce 的设计目标是为 sender 提供一种密码学上的验证手段,使其能够检测 receiver 是否隐瞒了至少一次拥塞。它不是为了防止偶尔的撒谎,而是为了使长期,系统地隐瞒拥塞行为变得非常困难或很容易被发现。我很喜欢 ECN nonce,它是基于概率的,概率即松弛,自然,大道,至简。

它的核心基础设施架构如下:

  • ECN nonce 重新定义了 ECT(1) 和 ECT(0) 的含义,它将 ECT(1) 定义为 “此数据包携带了一个 Nonce 位”;
  • sender 维护一个 nonce 和 NS,每发送一个数据包就将随机 nonce 值 0 或 1 加到 NS 上模 2,即异或运算;
  • 若无拥塞,路由器不会修改数据包的 ECN,receiver 收到的 ECN 就是发送端发出的 ECT(0) 或 ECT(1);
  • 若拥塞,路由器会将数据包的 ECN 字段标记为 CE(11),关键点来了,当数据包被标记为 CE 时,它原始的 nonce 值就丢失了,因为 CE 覆盖了原来的 ECT(0) 或 ECT(1);
  • TCP 头有一个 cwr 标志,ECN nonce 重新利用了该标志作 nonce echo(NE) 位;
  • receiver 对收到的每个非 CE 包都解出其 nonce 值并模 2 累加到本端维护的 nonce 和 NR 上;
  • receiver 回复 ACK 时会将 NR 值填入 NE;
  • 采用模 2 累加是因为 TCP 是积累确认,ACK 与发送数据包并非一一对应;

基于以上基础设施,精妙的点在于 sender 如何校验它收到的 NE:

  • 如果 ACK 的 ECE == 0,说明没有拥塞,如果是 receiver 撒谎,就意味着它必须猜测一个被 CE 覆盖掉的 nonce 值累加到 NR 并回显到 NE,猜对的概率是 50% 相乘的:

    • receiver 撒谎 1 次,成功概率为 50%;
    • receiver 撒谎 5 次,成功概率为 3.1%;
    • receiver 撒谎 10 次,成功概率为 0.09%;
    • 撒谎次数越多,越容易暴露自己在撒谎;
  • 一旦 sender 检测到一次或几次 NS != NE,可采取惩罚措施,例如回退到传统的 AIMD,或更激进地重置连接;

  • 如果 ACK 的 ECE == 1,说明如实汇报拥塞,无需再检测 NS,NE 是否相等;

  • 在 ECE == 1 后再收到 ECE == 0,用该 ACK 的 NE 覆盖 sender 的 NS;
    可如下简单理解:

  • ECE == 0 是个说辞:“我保证我看到了原始 nonce,请严格检查我的 NE 来确认我说的。”

  • ECE == 1 是个承诺:“我遇到拥塞了,nonce 丢了,NE 是猜的,但我回显给你 ECE 了。”

ECN nonce 的聪明之处在于,它利用接收端的 “诚实报告”(ECE = 1) 作豁免条件,专门惩罚那些 “既想隐瞒拥塞(ECE = 0),又想蒙混过关” 的撒谎行为。通过这种精巧设计,ECN nonce 在不增加过多开销的情况下,为 ECN 提供了强大的反欺骗能力,维护了拥塞控制的公平性。

但如此精妙的设计,后来并没有大规模部署,在 rfc8311 成为历史,直到近期 TCP 相关字段再次被 Accurate TCP-ECN 重载。其根本原因在于假想的问题并没有证据证明其大量存在,其背后的原因从非技术视角简直一目了然:

  • ECN 本就部署有限,靠 CE 隐瞒获得那一点点吞吐,缺乏实测证据;
  • 有证据表明一般的激进的侵略行为都发生在 sender,而不是 receiver;

为一些莫须有的问题,引入协议复杂性以及处理协议僵化问题的代价是巨大的,如此会让 TCP 不再实用,反而充满了自导自演的故事,为想象的问题制造解法,就像现在好多大厂并不太懂网络的经理们制造的数据中心传输协议一样。

Accurate ECN 的 draft 在 More Accurate Explicit Congestion Notification (ECN) Feedback in TCP,挺有意思的,与 ECN nonce 一样,Accurate ECN 亦只描述了信息反馈的机制,独立于 sender 如何使用该信息,本文不再赘述。其风格迎合了现状,以更精确的信息换取更精细的控制,以同时降低 “拥塞控制效率和公平性的开销”,这也是我一贯的主张。

但另一方面,也可以看到对 TCP 协议的任何扩展是多么得拧巴,只能重载实验性的单独一个 bit,只因为它 “曾经” 被标准化,而 Reserved 3-bit 由于没有任何 draft 给予时间来应对协议僵化而不敢使用,因此只能在少得可怜几个 bit 以及 option 里抠用法,用时间换空间。

这让人怀疑带来的收益能否抵消引入的复杂性开销,TCP 已经足够适应了,但也正因为它的适应性才能承受如此风格的修补,正因如此,40 年来不断地类似的修补让 TCP 变得越来越复杂。

说起协议扩展,点一下 ECN 这个主题,回到最初,为什么会有 ECT(0),ECT(1) 两个 codepoint,而不是特定的一个,核心原因就是为未来扩展预留空间。

RFC3168 明确指出了这一点,协议设计者非常清楚,一旦协议被固化(如在硬件中),再想修改就很困难,因此他们习惯于预留一些 “冗余” 或 “未定义” 状态,以备未来之需。如果只定义一个 ECT 状态,比如只用 10,那么 01 就变成了一个永久 “保留位”,这看起来是一种浪费。

通过定义两个在功能上完全等价的 ECT 状态,在当前两个状态可互换使用,都表示支持 ECN,在未来其中一个状态比如 ECT(1) 可被重定义,用于携带新语义而不会与现有的部署产生破坏性冲突。虽未成功,ECN nonce 正是上述 “未来扩展” 的第一个也是最重要的现实探索案例,参见 rfc8311 Abstract:

This memo also records the conclusion of the ECN nonce experiment in RFC 3540 and provides the rationale for reclassification of RFC 3540 from Experimental to Historic; this reclassification enables new experimental use of the ECT(1) codepoint.

在 ECN 设计的早期,还有一些更初步的想法,认为这两个代码点或许可用来指示不同类型的流量,或期望路由器,receiver 做出不同反应。但这些想法最终都没成为 rfc3168 的标准部分,因为过早定义差异会限制未来的可能性。保持它们初始的等价性是最灵活的。

浙江温州皮鞋湿,下雨进水不会胖。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值