引言
流水线式多阶段软件架构具备传统的“运行至完成 (RTC)”模型所不具备的可调整性。鉴于网卡 (NIC) 队列或由单核处理的端口有可能成为限制应用单数据流处理速率的瓶颈,要实现可调整性,可将应用分成多个可并行执行的阶段,由队列和仲裁器 (Arbiter) 将流水线的各个阶段连接起来,并执行复杂的调度和负载均衡任务。在这种情况下,可以将英特尔® DLB 作为硬件队列管理器兼负载均衡器,承担原本由软件执行的队列管理和调度任务。
本文围绕 DPDK IPsec 网关示例应用,对上述概念予以说明。之所以选择该应用,是因为在出现高带宽通道时,该应用的性能会因使用 RTC 模型而受到限制。该应用经修改,可通过支持流水线设计来实现可调整性,并由 DPDK Eventdev 库来管理队列和调度任务。这一实现方案在软件事件设备和英特尔® DLB 上均做了测试。
调整能力与性能方面的挑战
图 1 所示为多引擎 RTC IPsec 实现方案的简单示意图。在该示意图中,两端是 IO 设备,中间有多个工作线程 (Worker),用于处理 IPsec 工作负载。IO 设备在可用的处理引擎(本地内核/工作线程)间分配负载时有几种选择。通常情况下,此类分配借助网卡的接收端调整 (RSS) 功能来实现——根据生成的哈希值(通常使用数据包报头中的字段计算得出)分配流量。网卡在映射至处理引擎的多个接收队列间进行流量分配。在这一策略下,网络数据流始终会映射到同一引擎,从而保证分配过程不被线程调度机制打断,实现原子操作。高吞吐量 IPsec 工作负载面临的主要挑战是如何高效调整及合理分配负载。
大象流
大象流是一种高带宽网络数据流,会消耗单个线程很大一部分处理能力,有时甚至会超出其处理能力1。这类数据流的数量可能有限,但却会占用非常大的网络带宽。
IPsec 调整
应用必须在传入流量中信息熵足够的前提下,才能使用基于哈希算法的静态分配机制来高效分配流量。此外,使用单核来分配流量会成为每个数据流可实现最大吞吐量的瓶颈。如果采用流水线模型,就可以将处理任务分配到多个阶段,甚至在信息熵不足或出现高带宽大象流时也可以进行调整。
对于流水线模型而言,入站和出站的要求各不相同。
DPDK Eventdev 库
DPDK 与 Ethdev 及 Cryptodev API 类似,也有可支持事件驱动型编程模型的事件设备 (Eventdev) 库,为应用提供多核间自动调整、动态负载均衡、流水线操作、保持入站数据包顺序和实现同步等服务,进而简化应用数据包处理工作。
通过引入事件驱动型编程模型,DPDK 可同时支持直接轮询(无需使用 Eventdev)和事件驱动型编程模型两种数据包处理办法。应用可自由选择更适合自身需求的模型,或者二者并用。
举例来说,借助 Eventdev 的顺序调度功能,应用无需在内部启用任何同步机制,便可在保持入站数据包顺序的同时实现任务并行处理。而 Eventdev 的原子调度功能则会向特定内核发送事件流,无需加锁即可保持数据流顺序,使软件实现原子操作。此外,该功能还会在数据流未得到及时有效处理时,将其发送给其他内核,从而实现负载均衡。
Eventdev 与 Ethdev 及 Cryptodev 库类似,也采用了轮询模式驱动程序 (PMD) 架构。Eventdev 可以是个硬件设备,这种情况下 PMD 会对该设备编程;也可以是一种软件实现,这种情况下 PMD 会实现事件调度逻辑。由于 Eventdev API 是适用于各种 Eventdev PMD 的通用接口,因此 Eventdev 应用可在众多平台间移植。有关 Eventdev 库的更多详情,请参阅 DPDK 程序员指南的事件设备库部分2。
Eventdev 应用
基于 Eventdev 架构的应用使用的是流水线模型(如图 2 所示)。当网卡无法直接向 Eventdev 发送流量时,需设置生产者 (Producer) 和消费者 (Consumer) 阶段。流水线的处理阶段则由各个工作线程进行补充。这一架构并非固定不变,而是可根据系统吞吐量要求随时增减工作线程数量。生产者负责处理从网卡接口接收的数据包,并将其加入 Eventdev 队列,以便调整负载,达到平衡。消费者是流水线的最终阶段,它会汇总来自各个工作线程的流量并传送给网卡。图 2 所示为该架构及两个流水线阶段的逻辑示意图。通常情况下,实现多流水线阶段的是同一套工作线程。
硬件 Eventdev
英特尔推出的英特尔® DLB 是一款可从 CPU 卸载多核数据包调度和负载均衡任务的硬件加速器,支持各种所需的 DPDK Eventdev 特性及其他功能。从 DPDK 20.11 版起,面向英特尔® DLB 的 Eventdev PMD 已成为 DPDK 的一部分,并符合 Eventdev API 的要求。
英特尔® DLB 是一种硬件实现方案,内有一个连接事件生产者和消费者的队列和仲裁器系统。英特尔® DLB 属于 CPU 封装中的 PCIe 设备,可与内核上运行的软件以及可能需要的其他设备交互。英特尔® DLB 的负载均衡特性包括:
- 多生产者/多消费者的无锁通信。
- 针对不断变化的流量类型的多重优先级。
- 支持原子调度、顺序调度和并行调度等多种调度类型。
有关英特尔® DLB 的更多详情,请参阅基于英特尔® 架构的队列管理和负载均衡白皮书3。
IPsec 网关应用
在本概念验证 (PoC) 中,数据包出站和入站处理均分为三个阶段。出站处理分为分类、序列号分配以及加密与路由阶段。每个安全关联 (SA) 步骤中,序列号分配必须采用原子操作方式,而其他阶段则应依次序进行。入站处理分为入站数据包分类与防重放攻击检查、解密与路由,以及防重放参数更新三个阶段。由于在每个安全关联步骤中,序列号检查和窗口更新需以原子操作方式进行,因此防重放攻击检查与参数更新阶段均具有原子操作性。解密与路由阶段依次序进行。加密阶段和解密阶段均利用负载均衡功能来实现流水线设计带来的调整能力。
选择以上述方式完成各阶段工作可大幅减少跨核监听。例如,流水线设计将分类阶段与加密/解密阶段分离开来。分类阶段仅处理数据包报头,不触及实际数据包有效负载,而加密和解密阶段则会进行实际包数据的处理。上述这些阶段分别对数据包各个部分进行处理,并尽可能避免访问相同的缓存行,以减少跨核监听。
应用可在加解密阶段利用负载均衡功能分配流量,同时确保序列号分配阶段具有原子操作性。与之相似,防重放攻击检查和参数更新阶段也与解密阶段分开。
IPsec 流水线通过 Eventdev API 来使用英特尔® DLB。在设置时,每个工作线程都分配一个 Eventdev 端口。每个工作线程端口都连接至所有事件队列。其中,每个事件队列都代表一个有着各自队列类型的流水线阶段,其队列类型视其馈送的(原子操作、顺序操作)阶段而定。工作线程可处理入站流水线和出站流水线各个阶段的数据包。在针对来自端口的一批数据包进行出队操作后,工作线程将根据其流水线阶段 ID(由相关事件队列 ID 表示)对数据包进行归类,并根据流水线阶段 ID 处理每组数据包。完成后,工作线程会将整批数据包加入 Eventdev 队列,这样,各个数据包会被送至所属的下一个处理阶段。
IPsec 数据路径流水线
如图 3 所示,出站和入站数据路径划分成三个阶段。RTC 模型会在同一个内核中按顺序执行所有阶段,而流水线模型则可在不同内核中并行处理这些阶段。
生产者/消费者阶段
服务于网卡接收端和发送端接口的生产者和消费者阶段是数据包的单一入口点和出口点。因此,应仔细设计这两个阶段,避免其成为整个流水线的瓶颈。生产者应能按自身的处理速率从网卡为流水线输送数据包,消费者则应能按相同的速率将数据包传回网卡。为此,生产者和消费者阶段只承担极少量的处理任务。生产者一次处理的数据量往往更大,而消费者负载则会因前一阶段已执行路由操作且相关结果已保存在数据包缓冲区而得以降低。
将生产者和消费者线程作为共享同一个物理内核的超线程运行时,由于二者共享 L2 缓存,因此性能会提升。
数据流排序(原子操作/顺序操作)阶段
基于原子操作的队列类型会保证每个基于原子操作的数据流 ID 每次都由同一个内核处理,并保持数据包顺序。由于 IPsec 需要在安全关联层面保证操作的原子性,因此在本文的实现方案中,基于原子操作的各个阶段均使用安全关联值作为基于原子操作的数据流的 ID。
此外,PoC 还使用 mbuf 报头在流水线不同阶段之间传输安全关联 ID、路由信息和序列号等内容供后续阶段使用而无需重新计算。
顺序处理阶段可在多个工作线程间实现数据包的负载均衡。这些数据包经过并行处理并恢复原本加入队列时的顺序后才会发送至下一阶段。在软件中对数据流重新排序成本高昂,会消耗大量的 CPU 周期。而由英特尔® DLB 提供支持的顺序队列类型是在硬件中完成重新排序,因此可减少 CPU 周期成本。
跨核数据传输
与 RTC 模型相比,跨核监听是流水线设计面临的主要挑战。PoC 中的流水线设计旨在通过避免不同阶段访问相同缓存行做到尽量减少跨核监听。英特尔® VTune™ 软件可识别热点,英特尔® Cache Line Demote (cldemote) 和预先提取指令可用来大幅降低对性能的影响。
系统配置
测试设置
图 4 所示为 PoC 所使用的测试设置。测试中使用了两台测试设备 (DUT)。这些设备均运行内置英特尔® DLB 的非量产英特尔® 至强® 可扩展处理器(代号 Sapphire Rapids),并通过 100 Gbps 的以太网链路实现互联。使用配备 100 Gbps 端口的 IXIA 流量生成器生成明文流量。测试设备 1 对来自 IXIA 端口 1 的流量进行加密,并将其发送至 IPsec 通道内的测试设备 2。测试设备 2 在对流量解密后再将其转发回 IXIA 端口 2。从 IXIA 端口 2 传输至 IXIA 端口 1 的流量使用相似的路径。测试中流量始终为双向。
DPDK IPsec 安全网关示例应用
采用流水线设计的 IPsec 应用是对 DPDK 20.08 版中 ipsec-secgw 应用的升级。应用经修改可使用 DPDK Eventdev API 来连接不同的流水线阶段,并利用修改后的 DPDK IPsec 库为多阶段操作提供支持。该安全网关示例应用并非可量产的实现方案,且仅用于展示内核数据路径组件,不支持控制路径集成。
流量测试配置
单个数据流流量测试
单个数据流流量测试旨在测试采用单个高带宽 IPsec 安全关联的 IPsec 实现方案的可调整性。一直以来,单个高带宽 IPsec 安全关联都是 IPsec 实现方案性能上的瓶颈。
64B 大小的单个数据包的性能测试结果会从架构可支持的每秒数据包处理量角度展示该实现方案在协议处理、分类和转发方面的可调整性。IPsec 安全关联的大数据包(大于 1 KB)性能测试结果则会从吞吐量角度展示该实现方案在处理加解密工作负载扩展方面的能力。
多数据流流量测试
针对多个带宽占用高的大流量数据流进行的测试展示了所实现的架构在处理 IPsec 工作负载时的数据流分配能力。鉴于数据流多就会易于分配这种情况,本测试主要针对数据流很少的情况(少于 32 个),这也是静态负载分配机制难以实现负载均衡的场景之一。
性能
本节描述了既定 IPsec 数据路径参考架构的性能特征,重点突出相对性能和限制,同时也展示了英特尔® DLB 在支持高效负载均衡和调整 IPsec 工作负载方面的价值。
运行至完成
原 DPDK 示例的“运行至完成”设计会在较低的数据包传输速率下早早达到饱和,具体取决于单核的处理能力。
流水线模型(基于事件)
作为 PoC 实现的流水线模型是本文讨论的主要架构,它使用 SQM(软件 Eventdev 轮询模式驱动程序)和英特尔® DLB 轮询模式驱动程序(PCIe 设备)进行测试。使用 SQM 时,需额外增加一个内核,用于运行 SQM 调度程序。在采用这一设置时,SQM 调度程序每秒最多可执行 1500 万次调度决策。
结论
在 RTC 模型中,可处理的最大数据流带宽取决于单核的处理能力。本 PoC 展示了如何使用多阶段流水线来解决这一问题。流水线设计需要使用队列连接不同阶段,执行复杂的调度任务,并实现负载均衡。在软件中实现时,这是一种开销并且常常会在较低的带宽下达到饱和。本 PoC 表明这一问题可通过使用英特尔® DLB 硬件加速器来解决。DPDK Eventdev 库是经过验证且易于操作的多阶段连接管理方式,可轻松集成多种软硬件加速器。