对应路线图:Phase 5 (Day 141-168) | DPDK 24.11.6 LTS | 内核对照 v6.6
代码出处:source/dpdk-stable-24.11.6/lib/ethdev/rte_flow.h、source/linux-stable/net/sched/cls_flower.c
上一篇:P5-04 vDPA | 下一篇:P5-06 DPU 厂商调研
一句话定位
P1-07 学过 rte_flow 的"流与核绑定",本篇回答另一个问题:同一条 flow rule,由网卡硬件执行还是由 CPU 执行? API 完全一样(rte_flow_create),区别在 PMD 的 capability 判断——支持就下发硬件(零 CPU),不支持就回退软件匹配(每包吃 CPU)。DPU 的价值主张"把网络处理卸载进硬件",落到 API 层就是这个开关。
真实源码精读
① 规则三要素:struct rte_flow_attr(lib/ethdev/rte_flow.h:89-129,节选)
struct rte_flow_attr {
// ...省略 group 的长注释 ...
uint32_t group; // :100 规则组(层级树根在 0)
uint32_t priority; // :101 组内优先级
// ...
uint32_t ingress:1; // :105 入向规则
// ...
uint32_t egress:1; // :109 出向规则
// ...省略 transfer 的长注释 ...
uint32_t transfer:1; // :127 转移到设备层(eswitch/representor)
uint32_t reserved:29; // :128
};三个 bit 决定规则贴在哪里:普通 app 用 ingress/egress;DPU/SmartNIC 场景用 transfer:1 把规则下到"设备层"——这就是 OVS 卸载、vDPA 卸载共用的通道。
② pattern 与 action 的枚举(rte_flow.h:153 / :2590)
enum rte_flow_item_type { // :153
// ...
RTE_FLOW_ITEM_TYPE_END, // :162 列表终止符
// ...
RTE_FLOW_ITEM_TYPE_RAW, // :211 任意字节匹配(几乎只能软件做)
// ...
RTE_FLOW_ITEM_TYPE_ETH, // :218
// ...
RTE_FLOW_ITEM_TYPE_VLAN, // :225
// ...
RTE_FLOW_ITEM_TYPE_IPV4, // :232
// ...
RTE_FLOW_ITEM_TYPE_IPV6, // :239
// ...
RTE_FLOW_ITEM_TYPE_UDP, // :253
// ...
RTE_FLOW_ITEM_TYPE_TCP, // :260action 侧(:2590 起):RTE_FLOW_ACTION_TYPE_END(:2597)终止列表,RTE_FLOW_ACTION_TYPE_VOID(:2605)是占位符,往下是 QUEUE/DROP/RSS/COUNT 等。枚举是通用的,能力是各异的——这就是 offload 判断存在的根本原因。
③ 入口签名(rte_flow.h:4694-4699)
struct rte_flow *
rte_flow_create(uint16_t port_id,
const struct rte_flow_attr *attr,
const struct rte_flow_item pattern[],
const struct rte_flow_action actions[],
struct rte_flow_error *error);error 参数是调试神器:PMD 拒绝规则时把原因填进去(哪条 item 不支持、哪条 action 不支持),实测时打印 error->message 就能看到自己网卡的 offload 能力边界。
🐧 内核对照:tc flower 的 offload 判断
内核的对应物是 cls_flower(net/sched/cls_flower.c):fl_change(:2229)处理 tc filter add flower ... 配置,其中 :2369 调用 fl_hw_replace_filter(:452)尝试硬件卸载;卸载失败再走软件分类。和 DPDK 的差别:
| 维度 | tc flower | rte_flow |
|---|---|---|
| 下发入口 | netlink 消息 + tc 命令行 | C API 直接调用(rte_flow.h:4695) |
| 失败语义 | 静默回退软件或返回错误 | rte_flow_error 明细报告 |
| 软件路径 | 内核分类器逐包查 | PMD 软件匹配器(lcore 上) |
| 硬件目标 | 驱动 ndo_setup_tc | PMD flow_ops(如 mlx5 eswitch) |
同一件事:"先试硬件,不行回软件"。内核走配置面 netlink,DPDK 走数据面 API——后者把下发延迟从毫秒级压到微秒级,这正是 DPU 上动态流表需要的。
面试 3 问
- 怎么判断一条规则最终走了硬件还是软件? → 查 PMD capability(
rte_flow_validate提前试错)+rte_flow_create的error明细(rte_flow.h:4694-4699);实验上对比有/无规则时的 lcore CPU 占用,HW 卸载路径 CPU 几乎不动。 transfer:1属性和普通 ingress 规则区别在哪? → ingress/egress 规则作用于"到达本端口的流量",transfer 规则下到设备层端点(eswitch/representor),用于跨物理口/VF 的转发——rte_flow.h:105/109/127 三个 bit 的语义。- 为什么 RAW item 几乎只能走软件路径? → 任意字节匹配不在典型硬件流表能力内(rte_flow.h:211 的 RAW 是"匹配元数据类"item 之一),PMD 无法下发时只能软件逐包比对;5-tuple 类(ETH/IPV4/UDP/TCP,:218/:232/:253/:260)才是硬件卸载的甜区。
🔧 动手实验
本机 82599(ixgbe)offload 能力有限(5-tuple ntuple filter),设计一个"能力边界 + 双路径"实验:
# 1. 起 testpmd,rss 模式跑通
./testpmd -c 0x3 -n 2 -- -i --forward-mode=rxonly
# 2. HW 路径:下发 5-tuple → QUEUE 规则(ixgbe ntuple 能力内)
testpmd> flow create 0 ingress pattern eth / ipv4 src is 10.0.0.1 dst is 10.0.0.2 \
/ udp src is 1234 dst is 5678 / end actions queue index 1 / end
# 观察返回 Flow rule #0 以及 error->message 是否报 unsupported
# 3. SW 路径:换 RAW pattern(ixgbe 不支持硬件匹配)
testpmd> flow create 0 ingress pattern raw relative is 1 pattern is \
ff:ff:ff:ff:ff:ff:08:00 / end actions queue index 1 / end
# 若 PMD 报 unsupported,记录错误文本;用支持 SW 匹配的路径验证
# 4. 打流对比:dperf 或 pktgen 打目标 5-tuple,
# 对比有规则(HW 卸载)/无规则时 testpmd 的 lcore CPU(mpstat)与 PPS
# 5. 加分项:mlx5 或 dperf 侧做 COUNT action 验证硬件计数数据落点:perf-data/P5/05-offload.md(flow create 日志与 error 明细、SW/HW 两路径的 PPS 与 CPU 对比、ixgbe 能力边界清单)。预期:ixgbe 上 5-tuple 规则下发成功且 CPU 占用不升(硬件过滤后只剩匹配流量上 CPU);RAW 规则被明确拒绝——这条"拒绝日志"本身就是能力边界的实证。
评论 (0)