DPDK流规则未作用于UDP流量问题排查求助
问题描述
我尝试使用DPDK流规则根据UDP目的端口将接收的UDP数据包路由至不同队列。调用rte_flow_validate()验证流规则时已通过,但无论目的端口如何,所有设备上的数据包仍全部进入队列0,仿佛流规则未配置。请问流规则未按预期生效的原因是什么?
代码实现
以下是配置流规则的函数,目前在设备配置并启动后立即调用(已尝试在其他位置调用,无效果,详情见排查部分):
rte_flow * configure_udp_flow(uint16_t device_id, uint16_t udp_dst_port, uint16_t queue_id) { rte_flow *flow = NULL; rte_flow_attr attr; rte_flow_item pattern[5]; rte_flow_action action[5]; rte_flow_action_queue queue; struct rte_flow_item_eth eth_spec; rte_flow_item_ipv4 ip_spec; rte_flow_item_udp udp_spec; rte_flow_item_udp udp_mask; memset(&attr, 0, sizeof(rte_flow_attr)); memset(pattern, 0, sizeof(pattern)); memset(action, 0, sizeof(action)); memset(&queue, 0, sizeof(rte_flow_action_queue)); memset(ð_spec, 0, sizeof(rte_flow_item_eth)); memset(&ip_spec, 0, sizeof(rte_flow_item_ipv4)); memset(&udp_spec, 0, sizeof(rte_flow_item_udp)); memset(&udp_mask, 0, sizeof(rte_flow_item_udp)); attr.ingress = 1; // First level pattern, ETH, apply no actions pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH; pattern[0].spec = ð_spec; // Second level pattern, IP, apply no actions pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4; pattern[1].spec = &ip_spec; // Third level, UDP, match UDP destination port pattern[2].type = RTE_FLOW_ITEM_TYPE_UDP; udp_spec.hdr.dst_port = htons(udp_dst_port); pattern[2].spec = &udp_spec; udp_mask.hdr.dst_port = 0xffff; pattern[2].mask = &udp_mask; // Set pattern end pattern[3].type = RTE_FLOW_ITEM_TYPE_END; // Set action to move packet to queue action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE; queue.index = queue_id; action[0].conf = &queue; action[1].type = RTE_FLOW_ACTION_TYPE_END; // Validate and create rte_flow_error flow_error; int res = rte_flow_validate(device_id, &attr, pattern, action, &flow_error); if (res < 0) { spdlog::error("Could not configure flow rule: {0}", flow_error.message); return flow; } flow = rte_flow_create(device_id, &attr, pattern, action, &flow_error); return flow; }
排查操作
已尝试以下操作:
- 为UDP规则应用多种掩码:
- 全1
- 全0
- 仅目的端口字段为全1,其余位设为0
- 仅目的端口字段为全0,其余位设为1
- 调整
configure_udp_flow()函数的调用位置:- 每个设备配置开始时
- 配置结束后、启动每个设备前
- 启动每个设备后立即调用
- 使用不同字节序设置端口:
- 网络字节序
- 主机字节序
- 故意配置无效流规则验证校验步骤:
- 校验步骤正常,控制台已输出错误信息
- 验证入站UDP数据包的报头中包含预期的目的端口值
可能的原因及解决方法
ETH/IP层匹配逻辑缺失掩码
当前代码中ETH和IP层的spec被初始化为全0,但未设置对应的掩码。部分DPDK网卡驱动会将无掩码的全0spec解析为严格匹配全0的报头,而非通配匹配。需要为ETH和IP层添加全1掩码,明确表示匹配任意ETH/IP报文:// 新增ETH层掩码 struct rte_flow_item_eth eth_mask; memset(ð_mask, 0xff, sizeof(eth_mask)); pattern[0].mask = ð_mask; // 新增IP层掩码 rte_flow_item_ipv4 ip_mask; memset(&ip_mask, 0xff, sizeof(ip_mask)); pattern[1].mask = &ip_mask;流规则创建失败未被捕获
代码中调用rte_flow_create()后未检查返回值,可能存在“验证通过但实际创建失败”的情况。添加错误检查逻辑:flow = rte_flow_create(device_id, &attr, pattern, action, &flow_error); if (flow == NULL) { spdlog::error("Failed to create flow rule: {0}", flow_error.message); return NULL; }RSS分流机制与流规则冲突
若网卡同时开启了RSS(接收端缩放),部分网卡会优先使用RSS规则分流,导致rte_flow规则被忽略。可尝试关闭RSS:
在网卡初始化时,将rte_eth_conf.rxmode.mq_mode设置为ETH_MQ_NONE,或确保流规则的优先级高于RSS。网卡对复杂规则组合的支持限制
即使rte_flow_validate()返回成功,部分低端网卡可能不支持ETH+IP+UDP的多层匹配。可先简化规则,比如直接匹配IP+UDP,或仅匹配UDP目的端口,测试是否能生效。队列索引超出有效范围
确认传入的queue_id未超出网卡配置的接收队列数量。若队列索引无效,规则会被忽略,报文默认进入队列0。
内容的提问来源于stack exchange,提问作者Smitch

