在过去的几周里,我们一直在探讨协议报文头的设计,因此今天我想应用一些所学知识,来阐述一种新协议头的设计。这种协议被称为纵向扩展网络头(Scale-Up Network Header),简称 SUNH。它是一种网络层(即第 3 层)协议头,专为性能至关重要的场景设计,尤其如其名所示,用于人工智能的纵向扩展网络。SUNH 是一个非常简单的协议头,总共只有 8 字节,但在这 8 字节中,蕴含了我们一直在讨论的许多协议设计模式和原则。
新型网络层协议的必要性
人工智能和机器学习将网络性能要求推到了天文数字级别。这在为 AI 量身定制的高性能互连即纵向扩展网络中尤其如此。纵向扩展网络由紧密耦合的 GPU 集群,或更广义的 XPU 集群组成。节点数量可能达到数千个,网络拓扑通常是扁平的,任意两个节点之间最多只有一到两跳。纵向扩展网络的性能要求可能达到数Tbit的吞吐量和数十纳秒的延迟。
纵向扩展网络。一个单级纵向扩展网络的示例,连接了四个 XPU,并通过四个交换机形成一个具有多路径的全互联网络。
纵向扩展网络的需求和工作负载与我们以往处理的任何情况都截然不同,因此我们需要从根本上重新思考许多方面(我这么说并非轻率)。其中之一就是网络层协议。
大小很重要!……对于协议头而言
协议头,如 IPv4 和 IPv6 头,属于数据包开销。协议头的每一个字节都可能是导致应用数据带宽下降的一个字节,而每个协议字段都可能需要一定数量的 CPU 指令来处理。迄今为止,我们实际上并不需要过分担心这些开销。历史上,数据中心的平均数据包大小相当大,超过一千字节,因此协议头多几个字节的开销并不被认为是大事。例如,许多公司毅然从 IPv4 迁移到 IPv6,尽管这使网络层头部的规模翻了一番(从 20 字节增加到 40 字节)。
但时代在变。AI 应用的流量模式截然不同。在纵向扩展网络中,我们不能假设存在良好的流量混合来分摊数据包头部的成本。例如,在 AI 中,带有 KV 缓存的数据包平均大小可能为 256 字节或更小。对于像 IPv4 和 IPv6 这样的传统网络协议,网络头部开始占据可观的开销。例如,IPv4 的 20 字节头部在 256 字节的数据包中约占 8% 的开销,而 IPv6 的 40 字节头部则约占 16% 的开销。在 AI 出现之前,这些百分比或许可以容忍,但现在对于纵向扩展网络来说,这个开销太高了。
大小很重要!……对于网络层地址而言
当 IPv6 出现并解决了迫在眉睫的地址耗尽问题时,全世界(在某种程度上)欢欣鼓舞。IPv6 将 IPv4 地址的大小扩大了四倍,以确保在接下来的 200 年里(可能只是随口一说,但重点是 IPv6 拥有巨大的地址空间!)拥有近乎无限的地址数量和可扩展性。更大地址的缺点在于,我们需要在数据包头部中使用更多比特,需要更多内存来存储地址。但另一个问题是进行路由或在表查找中匹配地址时的地址查找成本。长地址需要更昂贵的 CAM、TCAM 或树机制,这会增加延迟和功耗。
问题在于,在纵向扩展网络中,我们不需要数百万个地址,因为我们可能只有几千台主机。此外,这些网络往往是封闭系统,节点仅在其内部通信,因此我们甚至不需要可路由的地址。所以我们真的不需要 IPv6 的 128 位地址,即使是 IPv4 的 32 位地址也似乎有些过度。
SUE AI 转发头?……
我们之前提到过纵向扩展以太网(Scale-Up Ethernet,简称 SUE),作为针对纵向扩展网络的一种新以太网协议提案。SUE 的一个有趣特性是 AI 转发头(AI Forwarding Headers,简称 AFH)。其想法是将以太网头部转换为一个准网络层头部,以减少数据包开销。AFH 第 1 代使用标准的以太网头部格式,但交换仅基于以太网地址的低 16 位进行。AFH 第 2 代重新利用了整个以太网头部,方便包含 16 位地址或 32 位"XPU 地址"以及网络层字段。
SUE AFH 第 2 代头部。这与规范的以太网头部有很大不同。其解释取决于前 8 位,这 8 位指示了一种特殊的"本地地址"格式。
AI 头部格式方法的根本问题在于它们与已部署的交换机不兼容。为了正确转发 AFH 数据包,交换机必须专门更新以具备新功能。这些修改是侵入性的,因为交换机需要从根本上重新解释以太网头部。这意味着要使用 AHF,你将需要新的交换机(可能还有网卡)。正如我的一位同事沉思道:"如果你彻底修改了整个以太网头部并且需要更换硬件,那它还真的是以太网吗?"(注:这就是ESUN成立的重要原因吧:OCP重磅推出AI纵向网络项目ESUN:以太网的天是晴朗的天!)
SUNH 简介
纵向扩展网络头(Scale-Up Network Header,简称 SUNH)最恰当的描述是 IPv4 或 IPv6 的压缩网络报头。它是一种"纵向扩展协议",因为其预期用例是受限域,例如 AI 的纵向扩展网络,在这些场景中,减少数据包开销和头部复杂度有利于提升性能。
SUE 的 AFH 格式与 SUNH 的主要区别在于,SUNH 是一个恰到好处的网络层头部。除了新的以太类型(EtherType)外,SUNH 对以太网报头是透明的。这意味着 SUNH 与现有已部署的以太网交换机兼容。二层交换在 SUNH 下"照常工作",因为交换机只考虑以太网地址且这些地址未被修改。三层交换的工作方式与交换机基于 IP 地址交换 IP 数据包的方式相同。一个三层交换机可以通过以太类型识别 SUNH 数据包,解析 SUNH 头部,对 SUNH 目的地址执行路由查找,然后根据跳数限制、流量类别和流标签字段转发数据包。
SUNH 地址
对于 SUNH,我们选择了 16 位地址。这似乎是能将纵向扩展网络扩展到几千个 XPU 的甜点区。16 位地址也便于使用高效的地址查找机制。
SUNH 仅在一个称为 SUNH 域的受限域 [RFC8799] 内工作。在 SUNH 域内,定义了一个 SUNH 前缀-这是 SUNH 格式中主机地址所隐含的 IPv4 或 IPv6 前缀。SUNH 地址则是完整 IPv4 或 IPv6 地址的 16 位主机部分。SUNH 域中的所有参与节点都配置了公共的 SUNH 前缀,并知晓 SUNH 头部是压缩的 IPv4 还是 IPv6 头部。通过将 SUNH 地址附加到 SUNH 前缀之后,可以将 SUNH 地址扩展为完整的 IPv4 或 IPv6 地址。
由于 SUNH 地址是 16 位的,在 SUNH 域中,可以从一个较小的范围分配地址。这有可能简化基于地址的路由查找。例如,如果所有地址都从一个 10 位的主机部分分配,即分配的 SUNH 地址在 0 到 1023 的范围内,那么路由查找可以通过一个简单的数组来实现,其中使用 SUNH 地址作为数组的索引。这个数组可以很容易地放在 SRAM 中,使得路由查找简化为快速的索引内存加载。
我们将 SUNH 地址写作 <byte>'<byte>。例如,如果 SUNH IPv4 前缀是 10.22.0.0/16,那么 10.22.16.7 对应的压缩 SUNH 地址就是 16'7。如果 2001:db8:abcd::1234:0000/112 是 SUNH IPv6 前缀,那么 2001:db8:abcd::1234:0122 的 SUNH 地址是 1'22。
使用 SUNH 寻址的纵向扩展网络。有四个主机,其 SUNH 地址从前缀为 10.23.0.0/16 的 SUNH IPv4 域分配。每个交换机都有一个路由表,该表仅仅是 SRAM 中的一个数组,通过 SUNH 地址进行索引以找到用于转发的输出端口。
SUNH 协议格式
SUNH 头部包含一个 16 位的源地址和目的地址。还有另外四个字段,是从 IPv6 和 IPv4 中借鉴来的最实用的字段。一个 8 位的流量类别字段用于 QoS,本质上与 IPv6 的流量类别字段相同(包括将这 8 位划分为 Diffserv 和 ECN 字段)。下一个头是 SUNH 头之后下一个协议的协议类型;这类似于 IPv6 的下一个头字段或 IPv4 中的协议字段,并且可以使用相同的 IP 协议号。跳数限制与 IPv6 的跳数限制字段相同,只是位数更少——跳数限制用于在存在路由环路时防止数据包被无限转发。流标签字段类似于 IPv6 的流标签,但位数更少-流标签用于 ECMP 等场景。
SUNH 协议头。
SUNH 数据包将被封装在以太网中,因此需要为 SUNH 分配一个以太类型。SUNH 头部不包含 IP 版本号,因此任何将 SUNH 头部解释为压缩的 IPv4 或 IPv6 头部的操作都是由 SUNH 域中的节点隐式完成的。与 IPv4 头部相比,SUNH 头部节省了 12 字节;与 IPv6 头部相比,节省了 32 字节。
比较 SUNH 网络头与 IPv4 和 IPv6。左侧显示的是 SUNH 中的 UDP,右侧是 IPv4(顶部)和 IPv6(底部)中的 UDP。
设计考量
根据我们的头部字段类型分类,SUNH 有四个 Type I 字段、一个 Type III 字段和一个 Type IV 字段。如果将流量类别视为两个字段(Diffserv 和 ECN),那么还会多两个 Type III 字段。Type IV 字段是流标签,这是一个 12 位的字段,跨越了一个字节边界,使得在小端序机器上访问它需要额外的工作。为了解决这个问题,我们可以将跳数限制和流标签合并为一个字段。对于面向连接的通信,发送方可以从其协议控制块中的一个值来设置这个组合字段。对于 ECMP,路由器可以将组合字段用作流熵值,因为在一个流中到达路由器的数据包,其跳数限制很可能相同。
跳数限制是 4 位,而在 IPv6 中是 8 位,因此使用 SUNH 的数据包最多可以经过 15 跳,而 IPv6 是 256 跳。这不是一个大问题,因为纵向扩展网络本质上是扁平拓扑,最多可能只有几跳。类似的理由也可以用来证明使用更小的流标签是合理的(SUNH 中是 12 位,而 IPv6 中是 20 位),因为我们不期望在纵向扩展网络中的两台主机之间存在大量不同的路径或如此多的流。
下一个头字段很有意思。我们选择了一个 8 位的协议字段,这有利于快速查找,因为协议查找可以通过索引一个 256 项数组来完成(16 位的值则需要更昂贵的 CAM 进行查找)。我们可以为此字段使用 IP 协议号,如 TCP=6 和 UDP=17,但我们可能也希望在这里有一些独立性,以便能够定义特定于纵向扩展网络的定制协议(如下一节我们将提到的 SUPERp)。从 IANA 获取官方协议号分配可能很困难,因为他们倾向于严格管理号码空间,因为它相对较小(例如 IP 协议号是 8 位,而 UDP 端口号是 16 位)。另一种方案是创建一个新的协议号空间,借用 IANA IP 协议号空间的值——我们将拭目以待……
消除 UDP 头部
我们提到过,大多数新的传输协议都被封装在 UDP 中。对于大多数协议来说,这是一个不错的解决方案,但在纵向扩展网络中,UDP 头的 8 个字节将被视为无益的开销。如果能消除 UDP 头部就太好了。解决方案是为 SUNH 定义一个新的协议号,并消除没有价值的 UDP 头部。没有 UDP 头部,SUNH 相比 IPv4/UDP 节省了 20 字节,相比 IPv6/UDP 节省了 40 字节。
为新传输协议消除 UDP 头部。左侧是封装在 SUNH 中的 SUPERp 头部,右侧是封装在 UDP/IPv4 中的 SUPERp。我们将讨论 SUPERp。
让我们谈谈代码
对 SUNH 的基础支持已在 XDP2 中实现。这包括头部格式的数据结构定义、示例数据包以及解析转储中的支持。这项工作也是与 SUPERp 协同完成的,SUPERp 是一种用于纵向扩展的新型传输协议,我们稍后会讨论。
structsunh_hdr {
union {
__u8 traffic_class;
struct {
#if defined(__BIG_ENDIAN_BITFIELD)
__u8 diff_serv: 5;
__u8 ecn: 3;
#elif defined(__LITTLE_ENDIAN_BITFIELD)
__u8 ecn: 3;
__u8 diff_serv: 5;
#else
#error"Please fix bitfield endianness"
#endif
};
};
__u8 next_header;
union {
__be16 hoplim_flow_label;
struct {
#if defined(__BIG_ENDIAN_BITFIELD)
__u16 hop_limit: 4;
__u16 flow_label: 12;
#else
__u16 flow_label_high: 4;
__u16 hop_limit: 4;
__u16 flow_label_low: 8;
#endif
};
};
__be16 saddr;
__be16 daddr;
} __packed;
unh_hdr
有几点需要注意。我们对 traffic_class 字段使用了联合体,以分离出 ecn 和 diff_serv 位。跳数限制和流标签字段被合并到 hoplim_flow_label 字段作为一个联合体,以简化对我们上面描述的流标签的访问。
SUNH 头部的一个巧妙特性是创建元组哈希非常容易。步骤如下(假设使用 64 位寄存器):
将 8 字节的 SUN 头部加载到寄存器中
将流量类别字段与全 1 进行"或"运算(例如,在 RISC-V 中是
ori a0, a0, 0xff)对寄存器运行哈希函数(可能是一条加速器指令)
此过程的结果是生成一个基于地址、流标签、下一个头和跳数限制的哈希值。即使在普通 CPU 上,这个序列也只需要几条指令。
相关文档交流移步汗牛充栋知识星球。
相关阅读:
P4可编程SDN交换机
P4教程 P4应用 P4论文
Tofino1 | Tifino 2 |国产P4交换机

