2021 年,某大型云厂商开始在每台服务器的 SmartNIC 上卸载 OVS 流表匹配,服务器 CPU 占用从 30% 降到 5%,多出的计算资源直接变成收入。SmartNIC 和 DPU 正在重新定义数据中心的计算边界。
一、引言:SmartNIC 与 DPU——从软件定义到硬件可编程
在第 10 章:RDMA 与远程直接内存访问中,我们看到 RNIC 硬件如何将传输协议从 CPU 卸载到网卡——远端 CPU 完全不参与数据搬运,延迟从数十微秒降到个位数微秒。但 RDMA 解决的是”传输层卸载”,而数据中心里还有大量工作仍然消耗着宝贵的 CPU 周期:OVS 流表匹配、VXLAN 封装/解封装、ACL 规则过滤、IPsec 加解密、QoS 流量整形……
当软件旁通(DPDK、XDP)已经把单核吞吐推到极限,当 CPU 核心数无法再线性增长,当云厂商发现 30% 的 CPU 时间花在虚拟网络开销上——硬件卸载(Hardware Offload)成为下一个必然的选择。
SmartNIC(智能网卡)和 DPU(Data Processing Unit,数据处理器)正是这一趋势的产物:它们把网络、存储、安全等基础设施任务从主机 CPU 卸载到网卡上的专用处理器,让 CPU 回归业务计算的本质。本章将深入 SmartNIC 与 DPU 的架构、OVS 硬件卸载的完整流程、P4 可编程数据平面入门,以及动手实践。
一、硬件卸载:为什么把工作交给网卡
CPU 贵,ASIC 便宜
在数据中心中,CPU 是最昂贵的资源之一。一颗高端 Xeon 处理器价格数千美元,而一颗网络 ASIC 芯片的成本可能只有其十分之一。更关键的是性能差距:
| 操作 | CPU(软件) | ASIC/FPGA(硬件) | 加速比 |
|---|---|---|---|
| 流表匹配(5 元组) | ~200 ns/条 | ~10 ns/条 | 20× |
| VXLAN 封装 | ~500 ns | ~20 ns | 25× |
| AES-GCM 256 加密 | ~3 μs/1KB | ~50 ns/1KB | 60× |
| CRC32 校验 | ~100 ns | ~5 ns | 20× |
| TCP 校验和 | ~50 ns | ~2 ns | 25× |
以上数据为典型量级,实际性能取决于具体硬件实现和配置。核心结论不变:对于固定模式的重复计算,专用硬件比通用 CPU 快一个数量级以上,且功耗更低。
卸载目标:哪些工作适合交给网卡
并非所有工作都适合硬件卸载。适合卸载的任务具有以下特征:
- 流匹配(Flow Matching):OVS/OpenFlow 的 5 元组或更复杂的匹配规则,硬件 TCAM 可以在单时钟周期内完成查找
- 包修改(Packet Modification):VXLAN 封装/解封装、VLAN 标签插入/剥离、NAT 地址改写——都是固定偏移的字段替换
- 加密/解密(Crypto):IPsec TLS 的对称加密/解密,硬件加密引擎吞吐量可达 100 Gbps+
- TCP 处理(TCP Offload):TCP 校验和计算、分段/重组、TSO/LRO——传统网卡已支持
- 流量整形(QoS/Shaping):令牌桶、限速、优先级队列——硬件可以精确到纳秒级调度
- 计量与统计(Metering/Counting):每流字节数/包数统计,硬件计数器零 CPU 开销
不适合卸载的任务:
- 复杂控制逻辑:路由协议(BGP/OSPF)计算、编排决策
- 需要大量内存的操作:深度包检测(DPI)的规则库可能超过片上 SRAM 容量
- 频繁变化的策略:硬件规则更新有延迟,不适合秒级变化的策略
软件路径 vs 硬件路径
关键差异在于:软件路径中每个包都需要 CPU 参与匹配和动作执行;硬件路径中,命中硬件规则的包完全不需要 CPU 参与,只有未命中的首包需要上送主机计算规则。
硬件卸载的核心收益不是”加速单个包的处理”,而是”让 CPU 完全不参与已卸载流的处理”。当 99% 的流量命中硬件规则时,CPU 可以从网络 I/O 中彻底解放出来。
二、SmartNIC 架构
SmartNIC(Smart Network Interface Card)是在传统网卡基础上增加了可编程处理能力的网络适配器。根据可编程程度,SmartNIC 可以分为三类架构。
固定功能 ASIC(Fixed-Function ASIC)
代表产品:NVIDIA/Mellanox ConnectX 系列(ConnectX-5/6/7)
这类 SmartNIC 内部是硬连线的 ASIC 逻辑,提供预定义的硬件卸载功能:
- RoCE/RDMA 卸载:硬件实现可靠传输协议
- OVS 硬件卸载:通过 ASAP²(Accelerated Switching and Packet Processing)支持
- VXLAN 封装/解封装:硬件隧道引擎
- IPsec 加密:硬件加密引擎
- TCP 拥塞控制:硬件 TSO/LRO
┌──────────────────────────────────────────┐│ ConnectX-7 ASIC ││ ┌─────────┐ ┌──────────┐ ┌──────────┐ ││ │ MAC/PHY │→│ Parser │→│ Match │ ││ │ (100G) │ │ 解析器 │ │ Action │ ││ └─────────┘ └──────────┘ │ Engine │ ││ │ 匹配动作 │ ││ ┌─────────┐ ┌──────────┐ └──────────┘ ││ │ Crypto │ │ Tunnel │ ││ │ Engine │ │ Engine │ ││ │ 加密引擎│ │ 隧道引擎 │ ││ └─────────┘ └──────────┘ ││ ┌─────────────────────────────────────┐ ││ │ PCIe 5.0 x16 │ ││ └─────────────────────────────────────┘ │└──────────────────────────────────────────┘优点:性能极致(线速处理)、功耗低、成熟稳定 缺点:功能固定,无法添加新协议或自定义逻辑;新功能需要等芯片迭代
可编程 FPGA/NPU(Programmable FPGA/NPU)
代表产品:Netronome Agilio CX、Xilinx Alveo
这类 SmartNIC 使用 FPGA 或 NPU(Network Processing Unit) 作为包处理引擎,开发者可以编写自定义逻辑:
- FPGA:通过 Verilog/VHDL 或 HLS(High-Level Synthesis)编程,完全自定义数据平面
- NPU:通过微码(microcode)编程,具有大量并行处理核心(Microengine)
┌──────────────────────────────────────────┐│ FPGA SmartNIC ││ ┌─────────┐ ┌──────────────────────┐ ││ │ MAC/PHY │→│ FPGA Fabric │ ││ │ (100G) │ │ ┌────┐ ┌────┐ │ ││ └─────────┘ │ │ME 0│ │ME 1│ ... │ ││ │ └────┘ └────┘ │ ││ ┌─────────┐ │ ┌──────────────┐ │ ││ │ DDR4 │ │ │ Custom Logic │ │ ││ │ Memory │←→│ 自定义逻辑 │ │ ││ └─────────┘ │ └──────────────┘ │ ││ └──────────────────────┘ ││ ┌─────────────────────────────────────┐││ │ PCIe 4.0 x16 │││ └─────────────────────────────────────┘│└──────────────────────────────────────────┘优点:完全可编程,可以添加新协议、自定义匹配动作 缺点:FPGA 开发门槛高(需要硬件描述语言经验)、编译时间长(数小时)、功耗较高
混合架构:ASIC + CPU(Hybrid ASIC+CPU)
代表产品:NVIDIA BlueField 系列、AMD Pensando
这是当前最主流的 SmartNIC/DPU 架构——在 ASIC 包处理引擎旁边放置一个通用 CPU 子系统,形成”快速路径 + 慢速路径”的分工:
- ASIC 快速路径:处理已知的、高频的包处理逻辑(流表匹配、封装、加密)
- CPU 慢速路径:处理控制面逻辑、异常包、新协议的首次迭代
┌──────────────────────────────────────────────────┐│ Hybrid SmartNIC / DPU ││ ││ ┌────────────────────┐ ┌────────────────────┐ ││ │ ASIC 快速路径 │ │ ARM CPU 子系统 │ ││ │ ┌──────────────┐ │ │ ┌──────────────┐ │ ││ │ │ Parser │ │ │ │ Linux OS │ │ ││ │ │ Match-Action │ │ │ │ OVS / 控制面 │ │ ││ │ │ Tunnel/Crypto│ │ │ │ 管理代理 │ │ ││ │ └──────────────┘ │ │ └──────────────┘ │ ││ │ │ │ │ ││ └────────┬───────────┘ └──────────┬─────────┘ ││ │ 内部高速互连 │ ││ └────────────┬────────────┘ ││ │ ││ ┌─────────────────────┴──────────────────────┐ ││ │ MAC/PHY (100G / 200G) │ ││ └────────────────────────────────────────────┘ ││ ┌────────────────────────────────────────────┐ ││ │ PCIe 4.0/5.0 x16 │ ││ └────────────────────────────────────────────┘ │└──────────────────────────────────────────────────┘优点:兼顾性能与可编程性,ASIC 处理快速路径、CPU 处理慢速路径 缺点:芯片面积大、功耗较高、成本高于纯 ASIC 方案
三种架构对比
| 特性 | 固定功能 ASIC | 可编程 FPGA/NPU | 混合 ASIC+CPU |
|---|---|---|---|
| 性能 | 5/5 | 4/5 | 5/5 |
| 可编程性 | 1/5 | 5/5 | 4/5 |
| 开发门槛 | 1/5(无需编程) | 5/5(HDL/微码) | 3/5(软件为主) |
| 功耗 | 2/5(低) | 4/5(高) | 3/5(中等) |
| 成本 | 2/5(低) | 4/5(高) | 3/5(中等) |
| 功能迭代速度 | 慢(芯片周期) | 中(FPGA 重编程) | 快(软件更新) |
三、DPU:数据处理器
DPU(Data Processing Unit)是 SmartNIC 的演进形态。如果说 SmartNIC 是”网卡 + 一些卸载能力”,那么 DPU 就是”网卡 + CPU + 加速器”——它本质上是一台运行独立操作系统的嵌入式服务器,专门处理基础设施任务(网络、存储、安全),让主机 CPU 专注于业务计算。
NVIDIA BlueField
NVIDIA BlueField 是目前市场份额最大的 DPU 产品,已经迭代到第三代:
BlueField-2
- ARM 核心:8 个 Cortex-A72 核心,运行 Linux(Ubuntu/RHEL)
- 网络:集成 ConnectX-6 Dx 网络控制器,支持 25/50/100 Gbps
- 加速器:加密引擎、正则表达式匹配引擎、数据压缩引擎
- 内存:8/16 GB DDR4
- 存储:支持 NVMe SNAP(NVMe over Fabric 硬件卸载)
BlueField-3
- ARM 核心:16 个 Cortex-A78 核心,性能提升 3×
- 网络:集成 ConnectX-7 网络控制器,支持 200/400 Gbps
- 加速器:增强加密引擎、VirtIO 硬件卸载、OVS ASAP² 升级
- 内存:16/32 GB DDR5
- PCIe:PCIe 5.0 x16,支持 NVMe 直接访问
BlueField 架构框图
AMD Pensando
AMD Pensando DPU 采用P4 可编程 ASIC + ARM CPU 的架构,其核心差异化在于 P4 可编程数据平面:
- P4 ASIC:数据平面完全由 P4 程序定义,支持自定义解析器、匹配动作表
- ARM 核心:6 个 Cortex-A72 核心,运行 Pensando OS
- 性能:100/200 Gbps,支持 100M+ 并发流表
- 特性:硬件 P4 可编程、分布式防火墙、加密、负载均衡
Pensando 的 P4 可编程性意味着:当新协议出现(如新的隧道封装格式),你可以编写 P4 程序定义新的解析和转发逻辑,无需等待芯片迭代。这是与 BlueField 固定功能 ASIC 的关键区别。
Intel IPU(Infrastructure Processing Unit)
Intel 的 IPU 走了一条不同的路线——FPGA + Xeon 的组合:
- FPGA 数据平面:可编程包处理逻辑,支持自定义协议
- Xeon CPU:运行 Linux,处理控制面和管理任务
- 产品线:Intel IPU E2100(FPGA + Xeon-D)、IPU C5000(FPGA + Xeon)
- 差异化:FPGA 提供比 ASIC 更灵活的可编程性,Xeon 提供比 ARM 更强的控制面性能
DPU 产品矩阵对比
| 特性 | NVIDIA BlueField-3 | AMD Pensando DPU | Intel IPU C5000 |
|---|---|---|---|
| 数据平面 | ConnectX-7 ASIC | P4 可编程 ASIC | FPGA |
| 控制面 CPU | ARM Cortex-A78 ×16 | ARM Cortex-A72 ×6 | Intel Xeon-D |
| 网络带宽 | 200/400 Gbps | 100/200 Gbps | 100/200 Gbps |
| 可编程模型 | ASAP²(固定功能 + 规则) | P4(完全可编程) | Verilog/HLS(FPGA) |
| 加密引擎 | AES-GCM 硬件 | AES-GCM 硬件 | AES-GCM 硬件 |
| 内存 | DDR5 16/32 GB | DDR4 8/16 GB | DDR4 16/32 GB |
| 虚拟化卸载 | VirtIO SNAP | VirtIO | VirtIO |
| 生态成熟度 | 5/5 | 4/5 | 3/5 |
| 典型场景 | 云网络、存储、安全 | 云防火墙、负载均衡 | 电信、5G UPF |
三家 DPU 的核心差异在于数据平面的可编程模型:BlueField 使用固定功能 ASIC + 规则配置,Pensando 使用 P4 可编程 ASIC,Intel IPU 使用 FPGA。选择哪种取决于你的场景——如果只需要标准协议的硬件卸载,BlueField 最成熟;如果需要自定义协议,Pensando 的 P4 最灵活;如果需要极致的自定义能力,Intel IPU 的 FPGA 最强大。
DPU 的核心价值:释放主机 CPU
DPU 的商业价值可以用一个简单的公式概括:
DPU 收益 = 释放的 CPU 核心数 × 单核成本 - DPU 成本在典型的云环境中:
- OVS 转发消耗 2-4 个 CPU 核心(每台主机)
- IPsec 加密消耗 2-8 个 CPU 核心(取决于带宽)
- 存储虚拟化消耗 2-4 个 CPU 核心
- 总计:6-16 个 CPU 核心用于基础设施开销
一台 64 核服务器的 10%-25% CPU 资源花在”非业务计算”上。DPU 将这些任务卸载后,主机 CPU 可以全部用于租户虚拟机/容器,直接提升业务收入。
四、OVS 硬件卸载
OVS(Open vSwitch)是云数据中心虚拟网络的核心组件,也是硬件卸载最重要的应用场景。本节深入 OVS 硬件卸载的完整流程。
卸载模型:tc / rte_flow / ASAP²
OVS 硬件卸载有三种主要接口:
| 接口 | 层级 | 适用场景 | 代表产品 |
|---|---|---|---|
| tc(traffic control) | Linux 内核 | 内核 OVS + SmartNIC | ConnectX、Broadcom |
| rte_flow | DPDK | OVS-DPDK + SmartNIC | ConnectX、Netronome |
| ASAP² | Mellanox 私有 | ConnectX/BlueField 专用 | NVIDIA/Mellanox |
tc 卸载的工作原理:
- OVS 内核数据路径将流表规则转换为
tc规则 tc规则通过flower分类器下发到网卡驱动- 网卡驱动将
tc规则转换为硬件流表规则(通过devlink或厂商私有接口) - 后续包在硬件中匹配并执行动作
rte_flow 卸载的工作原理:
- OVS-DPDK 用户态数据路径将流表规则转换为
rte_flow规则 - 通过 DPDK PMD 驱动下发到网卡硬件
- 硬件直接匹配和执行
ASAP²(Accelerated Switching and Packet Processing)是 NVIDIA/Mellanox 的专有卸载框架,在 tc/rte_flow 之上提供了更高效的规则管理和更丰富的卸载能力。
卸载流程:miss → 软件 → 安装硬件规则 → hit → 硬件
OVS 硬件卸载的核心是一个慢速路径到快速路径的迁移过程:
这个流程的关键点:
- 首包必须上送主机:硬件无法自行计算新流表规则,必须由 ovs-vswitchd 决定
- 规则安装有延迟:从首包到硬件规则生效,需要经过 upcall → 用户态处理 → 内核规则 → 硬件规则的完整链路,典型延迟 100μs-1ms
- 后续包零 CPU 开销:一旦硬件规则生效,同流的所有后续包完全在硬件中处理
OVS 硬件卸载配置
启用 tc 卸载(内核 OVS)
# 1. 启用网卡的 hw-tc-offloadethtool -K <interface> hw-tc-offload on
# 2. 启用 OVS 硬件卸载ovs-vsctl set Open_vSwitch . other_config:hw-offload=true
# 3. 重启 OVSsystemctl restart openvswitch-switch
# 4. 验证硬件卸载已启用ovs-vsctl get Open_vSwitch . other_config:hw-offload# 输出: "true"
# 5. 查看硬件卸载的流表规则ovs-dpctl dump-flows -m type=tc启用 rte_flow 卸载(OVS-DPDK)
# 1. 在 OVS-DPDK 配置中启用硬件卸载ovs-vsctl set Open_vSwitch . other_config:hw-offload=trueovs-vsctl set Open_vSwitch . other_config:tc-policy=skip_sw# skip_sw: 尽可能将规则安装到硬件,跳过软件规则
# 2. 重启 OVSsystemctl restart openvswitch-switch
# 3. 创建 DPDK 端口时指定 pf socketovs-vsctl add-port br0 dpdk0 \ -- set Interface dpdk0 type=dpdk \ options:dpdk-devargs=0000:3b:00.0
# 4. 查看卸载状态ovs-appctl dpctl/dump-flows -m type=offloadedtc 命令详解
tc(traffic control)是 Linux 内核的流量控制子系统,也是 OVS 硬件卸载的核心接口。理解 tc 命令对调试硬件卸载至关重要:
# 查看网卡上的 tc 规则(包括硬件卸载的规则)tc filter show dev <interface> root
# 查看 ingress 方向的 tc 规则tc filter show dev <interface> ingress
# 手动添加一条 tc 硬件卸载规则# 匹配:源 IP 10.0.0.1,目的端口 80# 动作:转发到端口 2tc filter add dev <interface> protocol ip parent ffff: \ flower \ src_ip 10.0.0.1 \ dst_port 80 \ ip_proto tcp \ action mirred egress redirect dev <interface2> \ hw_offload 1
# 查看硬件卸载规则的统计tc -s filter show dev <interface> root
# 删除所有 tc 规则tc qdisc del dev <interface> clsact
# 查看网卡支持的 tc 卸载能力ethtool -k <interface> | grep hw-tc-offloadtc flower 规则的语法与 OVS 流表规则不完全对应。OVS 在内部将流表规则转换为 tc flower 格式,某些复杂动作(如多级封装)可能无法直接卸载。使用 ovs-dpctl dump-flows -m 查看规则时,注意 offloaded:yes 标记确认规则已成功卸载到硬件。
卸载规则优先级与限制
硬件流表有容量限制,当规则数超过硬件 TCAM 容量时,需要合理的优先级策略:
# 查看硬件流表容量(以 ConnectX 为例)devlink dev param show pci/0000:3b:00.0 name acl_max
# 设置 OVS 卸载优先级策略ovs-vsctl set Open_vSwitch . other_config:tc-policy=skip_hw# skip_hw: 优先软件规则,硬件规则作为加速# skip_sw: 优先硬件规则,软件规则不安装# none: 两者都安装(默认)| tc-policy | 行为 | 适用场景 |
|---|---|---|
none | 软件 + 硬件都安装规则 | 调试阶段 |
skip_hw | 优先软件,硬件失败不报错 | 规则数超过硬件容量 |
skip_sw | 优先硬件,硬件失败则丢弃 | 追求极致性能 |
五、P4 编程入门
P4(Programming Protocol-Independent Packet Processors)是一种数据平面编程语言,它允许你定义数据包的解析方式、匹配动作表的逻辑,以及包的修改和转发行为。P4 是 SmartNIC/DPU 可编程性的核心——理解 P4,就理解了现代可编程数据平面的设计哲学。
P4 架构模型
P4 的核心架构由四个组件组成:
- Headers(头部定义):定义数据包的头部格式——每个字段的名称、位宽、顺序
- Parser(解析器):状态机,逐层解析数据包头部,提取匹配所需的字段
- Match-Action Tables(匹配动作表):核心处理逻辑——根据字段值匹配,执行对应动作
- Deparser(重组器):将修改后的头部重新组装成数据包输出
P4 只定义数据平面(Data Plane)的行为——“如何处理包”。控制平面(Control Plane)——“往表里填什么规则”——由外部控制器(CPU/SDN 控制器)通过 P4Runtime API 下发。这种分离是 P4 设计哲学的核心。
P4₁₆ 基础语法
P4₁₆ 是 P4 语言的当前版本(2016 年发布),相比 P4₁₄ 增加了类型系统、抽象架构模型等特性。以下是一个完整的 P4₁₆ 程序骨架:
// ============================================// P4₁₆ 程序骨架// ============================================
// 1. 包含核心库#include <core.p4>#include <v1model.p4>
// 2. 定义头部格式header ethernet_t { bit<48> dstAddr; bit<48> srcAddr; bit<16> etherType;}
header ipv4_t { bit<4> version; bit<4> ihl; bit<8> diffserv; bit<16> totalLen; bit<16> identification; bit<3> flags; bit<13> fragOffset; bit<8> ttl; bit<8> protocol; bit<16> hdrChecksum; bit<32> srcAddr; bit<32> dstAddr;}
// 3. 定义元数据结构struct metadata_t { bit<16> ingress_port; bit<16> egress_port;}
// 4. 定义头部集合struct headers_t { ethernet_t ethernet; ipv4_t ipv4;}
// 5. 定义解析器(Parser)parser MyParser(packet_in packet, out headers_t hdr, inout metadata_t meta, inout standard_metadata_t std_meta) { state start { packet.extract(hdr.ethernet); transition select(hdr.ethernet.etherType) { 0x0800: parse_ipv4; default: accept; } }
state parse_ipv4 { packet.extract(hdr.ipv4); transition accept; }}
// 6. 定义动作(Action)action forward(bit<9> port) { std_meta.egress_spec = port;}
action drop() { mark_to_drop(std_meta);}
action set_dst_mac(bit<48> mac) { hdr.ethernet.dstAddr = mac;}
// 7. 定义匹配动作表(Table)table ipv4_lpm_table { key = { hdr.ipv4.dstAddr: lpm; // 最长前缀匹配 } actions = { forward; drop; set_dst_mac; } size = 1024; default_action = drop;}
// 8. 定义控制流(Apply)control MyIngress(inout headers_t hdr, inout metadata_t meta, inout standard_metadata_t std_meta) { apply { ipv4_lpm_table.apply(); }}
// 9. 定义重组器(Deparser)control MyDeparser(packet_out packet, in headers_t hdr) { apply { packet.emit(hdr.ethernet); packet.emit(hdr.ipv4); }}
// 10. 实例化架构(V1Model)V1Switch(MyParser(), MyIngress(), MyIngress(), MyDeparser()) main;P4 关键概念详解
匹配类型
P4 支持多种匹配类型,对应不同的硬件实现:
| 匹配类型 | 语法 | 硬件实现 | 适用场景 |
|---|---|---|---|
| 精确匹配 | exact | 哈希表 | MAC 地址、VLAN ID |
| 最长前缀匹配 | lpm | TCAM / LPM 树 | IP 路由 |
| 三元匹配 | ternary | TCAM | ACL 规则(带掩码) |
| 范围匹配 | range | TCAM | 端口范围 |
动作(Action)
P4 的动作是原子操作——要么全部执行,要么不执行。动作可以包含:
- 修改头部字段:
hdr.ipv4.ttl = hdr.ipv4.ttl - 1 - 添加/删除头部:
hdr.ipv4.setInvalid() - 设置输出端口:
std_meta.egress_spec = port - 标记丢弃:
mark_to_drop(std_meta)
控制流
P4 的控制流通过 apply 块定义,支持条件分支和表串联:
apply { if (hdr.ipv4.isValid()) { switch (ipv4_lpm_table.apply().action_run) { forward: { // 转发成功,继续处理 } drop: { // 丢弃 } } }}P4 + SmartNIC 实践
P4 程序需要编译为特定硬件的目标代码。不同 SmartNIC 有不同的编译后端:
| SmartNIC | P4 编译器 | 目标格式 |
|---|---|---|
| AMD Pensando | P4 Capri Compiler | Capri ASIC 微码 |
| Intel IPU | P4 Studio / P4S | FPGA bitstream |
| NVIDIA BlueField | 不直接支持 P4 | 使用 ASAP² 规则配置 |
NVIDIA BlueField 的 ConnectX ASIC 不直接支持 P4 编程。BlueField 的数据平面通过 ASAP² 框架配置固定功能的匹配动作规则,而不是通过 P4 程序定义。如果你需要 P4 可编程性,应选择 AMD Pensando 或 Intel IPU。
完整示例:L2 转发的 P4 程序
以下是一个完整的 L2 MAC 转发 P4 程序,包含 MAC 学习表和转发逻辑:
#include <core.p4>#include <v1model.p4>
// ============================================// L2 MAC 转发 P4 程序// ============================================
header ethernet_t { bit<48> dstAddr; bit<48> srcAddr; bit<16> etherType;}
struct metadata_t { bit<16> ingress_port;}
struct headers_t { ethernet_t ethernet;}
// ---- Parser ----parser L2Parser(packet_in packet, out headers_t hdr, inout metadata_t meta, inout standard_metadata_t std_meta) { state start { packet.extract(hdr.ethernet); meta.ingress_port = std_meta.ingress_port; transition accept; }}
// ---- Actions ----// 转发到指定端口action forward(bit<9> egress_port) { std_meta.egress_spec = egress_port;}
// 丢弃action drop() { mark_to_drop(std_meta);}
// 学习源 MAC 地址(控制面通过 clone 完成)action learn_src_mac() { // 触发 CPU 学习源 MAC → ingress_port 映射 // 实际由控制面完成 clone3(CloneType.I2E, 0, meta);}
// ---- Tables ----// 目的 MAC 查找表(精确匹配)table dst_mac_table { key = { hdr.ethernet.dstAddr: exact; } actions = { forward; drop; } size = 4096; // 支持 4K MAC 条目 default_action = drop;}
// ---- Ingress Control ----control L2Ingress(inout headers_t hdr, inout metadata_t meta, inout standard_metadata_t std_meta) { apply { // 1. 学习源 MAC(首包触发 CPU 学习) learn_src_mac();
// 2. 查找目的 MAC 转发表 dst_mac_table.apply(); }}
// ---- Egress Control ----control L2Egress(inout headers_t hdr, inout metadata_t meta, inout standard_metadata_t std_meta) { apply { // L2 转发不需要额外 egress 处理 }}
// ---- Deparser ----control L2Deparser(packet_out packet, in headers_t hdr) { apply { packet.emit(hdr.ethernet); }}
// ---- Instantiation ----V1Switch(L2Parser(), L2Ingress(), L2Egress(), L2Deparser()) main;控制面通过 P4Runtime API 下发 MAC 转发表规则:
# 使用 P4Runtime 客户端下发规则示例import p4runtime_pb2 as p4rt
# 添加一条 MAC 转发规则:dst MAC aa:bb:cc:dd:ee:ff → 端口 3entry = p4rt.TableEntry()entry.table_id = dst_mac_table_identry.match.append( p4rt.FieldMatch( field_id=1, # dstAddr exact=p4rt.FieldMatch.Exact( value=b'\xaa\xbb\xcc\xdd\xee\xff' ) ))entry.action.action_id = forward_action_identry.action.params.append( p4rt.Action.Param( param_id=1, # egress_port value=b'\x00\x03' # port 3 ))client.Write(p4rt.WriteRequest( updates=[p4rt.Update(type=1, entity=p4rt.Entity(table_entry=entry))])六、动手实践
本节提供四个实践练习,从查看网卡卸载能力到 P4 编译运行,逐步掌握 SmartNIC/DPU 的核心操作。
实践 1:ethtool 查看网卡卸载能力
# 查看网卡的所有卸载能力ethtool -k <interface>
# 重点关注以下卸载特性:# tcp-segmentation-offload: on # TSO# generic-receive-offload: on # GRO# rx-checksumming: on # RX 校验和卸载# tx-checksumming: on # TX 校验和卸载# hw-tc-offload: on # tc 硬件卸载(OVS 卸载必需)# rx-vlan-offload: on # VLAN 卸载# tx-vlan-offload: on # VLAN 卸载
# 启用/禁用特定卸载sudo ethtool -K <interface> hw-tc-offload onsudo ethtool -K <interface> tso onsudo ethtool -K <interface> gro on
# 查看网卡统计(包括硬件卸载的统计)ethtool -S <interface> | grep -i offload
# 查看 NVIDIA/Mellanox 网卡的加速统计ethtool -S <interface> | grep -i "tc_offload\|rx_steer\|flow"如果 hw-tc-offload 显示为 off 且无法启用,可能是网卡型号不支持或驱动版本过旧。ConnectX-4 以后型号才支持 tc 硬件卸载。
实践 2:OVS 硬件卸载配置与验证
# ===== 环境准备 =====# 确保网卡支持 hw-tc-offloadethtool -k <interface> | grep hw-tc-offload
# 启用网卡的 tc 硬件卸载sudo ethtool -K <interface> hw-tc-offload on
# ===== OVS 配置 =====# 启用 OVS 硬件卸载sudo ovs-vsctl set Open_vSwitch . other_config:hw-offload=true
# 重启 OVS 使配置生效sudo systemctl restart openvswitch-switch
# 创建 OVS 网桥并添加端口sudo ovs-vsctl add-br br0sudo ovs-vsctl add-port br0 <interface>
# ===== 验证 =====# 生成流量后,查看是否有规则被卸载到硬件sudo ovs-dpctl dump-flows -m type=tc
# 输出示例(注意 offloaded:yes):# recirc_id(0),in_port(1),eth(src=aa:bb:cc:dd:ee:ff,dst=11:22:33:44:55:66),# eth_type(0x0800),ipv4(src=10.0.0.1/0.0.0.0,dst=10.0.0.2/0.0.0.0,# proto=6,tos=0/0,ttl=64,frag=no),tcp(src=12345/0,dst=80/0),# packets=1000000,bytes=64000000,offloaded:yes,used:0.001s
# 查看硬件卸载统计sudo ovs-dpctl show -s# 关注 offloads 字段
# ===== 调试 =====# 如果规则没有被卸载,检查 OVS 日志sudo journalctl -u openvswitch-switch | grep -i offload
# 查看网卡上的 tc 规则sudo tc filter show dev <interface> ingress
# 检查规则是否在硬件中sudo tc -s filter show dev <interface> ingress# 如果看到 "in hw" 标记,说明规则已卸载到硬件实践 3:P4 程序编译与模拟
如果没有 SmartNIC 硬件,可以使用 BMv2(Behavioral Model v2)——P4 的软件模拟器来学习和调试 P4 程序:
# ===== 安装 P4 开发工具 =====# 安装依赖sudo apt install cmake g++ git automake libtool libboost-dev \ libboost-filesystem-dev libboost-program-options-dev \ libboost-system-dev libgrpc++-dev libprotobuf-dev \ protobuf-compiler libgmp-dev libpcap-dev
# 编译安装 BMv2git clone https://github.com/p4lang/behavioral-model.gitcd behavioral-modelgit submodule update --init --recursive./autogen.sh./configuremake -j$(nproc)sudo make install
# 编译安装 p4c(P4 编译器)git clone https://github.com/p4lang/p4c.gitcd p4cgit submodule update --init --recursivemkdir build && cd buildcmake ..make -j$(nproc)sudo make install
# ===== 编译 P4 程序 =====# 编译 L2 转发程序为 BMv2 JSONp4c --target bmv2 --arch v1model l2_forward.p4 -o l2_forward.json
# ===== 运行 BMv2 =====# 启动 BMv2 交换机(简单交换机)simple_switch --interface 0@veth0 --interface 1@veth1 \ l2_forward.json &
# 使用 CLI 下发规则simple_switch_CLI# 在 CLI 中:# table_add dst_mac_table forward aa:bb:cc:dd:ee:ff => 1# table_add dst_mac_table forward 11:22:33:44:55:66 => 0
# ===== 发送测试流量 =====# 在 veth0 上发送包sudo python3 send_packet.py --interface veth0 \ --src-mac aa:bb:cc:dd:ee:ff \ --dst-mac 11:22:33:44:55:66
# 在 veth1 上抓包验证sudo tcpdump -i veth1 -nn实践 4:硬件卸载 vs 软件转发性能基准
# ===== 测试环境 =====# 发送端:使用 pktgen-dpdk 或 MoonGen 生成流量# 接收端:运行 OVS(分别测试软件转发和硬件卸载)
# ===== 软件转发基准 =====# 禁用硬件卸载sudo ovs-vsctl set Open_vSwitch . other_config:hw-offload=falsesudo systemctl restart openvswitch-switch
# 生成 64B 小包流量,测量吞吐量# 预期:~2-5 Mpps(取决于 CPU 核心数和频率)
# 记录 CPU 使用率mpstat -P ALL 1 10 > software_cpu.txt
# ===== 硬件卸载基准 =====# 启用硬件卸载sudo ovs-vsctl set Open_vSwitch . other_config:hw-offload=truesudo systemctl restart openvswitch-switch
# 生成相同流量,测量吞吐量# 预期:~50-100 Mpps(线速,取决于网卡型号)
# 记录 CPU 使用率mpstat -P ALL 1 10 > hardware_cpu.txt
# ===== 对比分析 =====# 对比两个场景的:# 1. 吞吐量(Mpps)# 2. CPU 使用率(%)# 3. 延迟(P50/P99)# 4. 功耗(如果可测量)
# 使用 dpdk-procinfo 查看硬件统计dpdk-procinfo -- --stats性能基准测试需要稳定的测试环境:绑核、关闭超线程、固定 CPU 频率(cpupower frequency-set -g performance)、隔离测试网络。否则结果会有较大波动,无法得出可靠结论。
小结
本章从”为什么需要硬件卸载”出发,系统梳理了 SmartNIC 与 DPU 的技术栈:
-
硬件卸载的动机:CPU 贵且慢,ASIC 便宜且快。当软件旁通已经推到极限,硬件卸载是进一步提升性能和降低 CPU 开销的必然选择。适合卸载的任务具有”固定模式、高频重复”的特征——流匹配、包修改、加密、TCP 处理、流量整形。
-
SmartNIC 三种架构:固定功能 ASIC(ConnectX,性能极致但不可编程)、可编程 FPGA/NPU(Netronome/Xilinx,完全可编程但门槛高)、混合 ASIC+CPU(BlueField/Pensando,性能与灵活性的最佳平衡)。
-
DPU 产品矩阵:NVIDIA BlueField(ARM + ConnectX ASIC,生态最成熟)、AMD Pensando(P4 可编程 ASIC + ARM,数据平面最灵活)、Intel IPU(FPGA + Xeon,可编程性最强)。选择取决于场景——标准卸载选 BlueField,自定义协议选 Pensando,极致自定义选 IPU。
-
OVS 硬件卸载:tc/rte_flow/ASAP² 三种接口,miss→软件→安装硬件规则→hit→硬件的完整流程。配置简单(
hw-offload=true),但调试需要理解 tc 命令和硬件规则容量限制。 -
P4 编程:Headers→Parser→Match-Action→Deparser 的架构模型,P4₁₆ 的类型系统和语法,L2 转发的完整 P4 程序示例。P4 是可编程数据平面的核心语言,掌握 P4 就掌握了 SmartNIC/DPU 可编程性的本质。
SmartNIC/DPU 不是万能的。它最适合的场景是:大量重复的包处理逻辑(OVS 转发、ACL 过滤、加密、封装),这些逻辑可以被硬件规则固化。对于需要复杂控制逻辑或频繁策略变化的场景,软件方案(OVS-DPDK、VPP)仍然更灵活。最佳实践是”硬件加速快速路径 + 软件处理慢速路径”的混合架构。
参考资料
规范与标准
- P4₁₆ Language Specification — P4 语言规范,定义语法和语义
- P4Runtime API Specification — P4 控制面 API 规范
- IEEE 802.1Q — VLAN 与网络虚拟化标准
厂商文档
- NVIDIA BlueField DPU Documentation — BlueField DPU 架构与配置指南
- NVIDIA ASAP² Documentation — ASAP² 硬件卸载框架文档
- AMD Pensando DPU — Pensando DPU 产品与 P4 编程指南
- Intel IPU Documentation — Intel IPU 架构与开发文档
开源项目
- P4 Language Consortium — P4 语言社区,包含规范、教程和示例
- p4c — P4 参考编译器
- BMv2 — P4 软件模拟器
- OVS Hardware Offload — OVS 硬件卸载文档
技术论文与博客
- “The Programmable Data Plane: Abstractions, Architectures, Algorithms, and Applications” — P4 可编程数据平面的学术综述
- “BlueField DPU Architecture” — NVIDIA BlueField 架构白皮书
- Brendan Gregg’s Blog: Hardware Offload Performance — 硬件卸载性能分析方法
- NVIDIA Developer Blog: OVS Hardware Offload — OVS 硬件卸载实践详解
延伸阅读
- 第 8 章:XDP 与 eBPF 高性能网络 — XDP 与 SmartNIC 的协作:XDP 处理内核态快速路径,SmartNIC 处理硬件快速路径
- 第 12 章:OVS-DPDK 与虚拟交换 — OVS-DPDK 数据路径与硬件卸载的深度集成
- 第 10 章:RDMA 与远程直接内存访问 — RDMA 是最早的硬件卸载之一,理解 RDMA 有助于理解 SmartNIC 的卸载理念
支持与分享
如果这篇文章对你有帮助,欢迎支持作者或分享给更多人
部分信息可能已经过时






