DPDK flow_filtering 虚拟网卡验证与原理深度指南
DPDK flow_filtering 虚拟网卡验证与原理深度指南
DPDK flow_filtering 虚拟网卡验证与原理深度指南
本文档介绍了如何使用虚拟网卡验证 DPDK flow_filtering 示例程序,并深入解析了其中的异步提交机制与底层驱动实现。
1. 验证方案选择:为什么是 net_tap?
在没有物理硬件(如 NVIDIA ConnectX 系列网卡)的情况下,验证 rte_flow 逻辑需要驱动程序支持流规则仿真。
net_pcap:不支持rte_flow,仅能进行简单的包收发。net_tap:支持将rte_flow规则映射到 Linux 内核的 TC (Traffic Control) Flower 分类器。它是验证流规则分流逻辑的最佳虚拟设备。
2. 核心原理补充:postpone 属性
在示例代码的 rte_flow_async_create 调用中,没有显式调用 rte_flow_push,这是由 ops_attr 控制的:
1
struct rte_flow_op_attr ops_attr = { .postpone = 0 };
postpone = 1:操作仅进入软件队列,必须调用rte_flow_push()才会发送给硬件。postpone = 0:驱动程序在接口内部执行隐式提交。对于net_tap或某些硬件驱动,这意味着规则立即生效。
3. 验证步骤
3.1 流量生成脚本 (send_traffic.py)
使用 Python 原始套接字构造匹配与不匹配的数据包。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import socket
import struct
import time
def create_ipv4_packet(dst_ip):
# Ethernet Header (Dst: 02:00:00:00:00:01, Src: 02:00:00:00:00:02)
eth = struct.pack('!6s6sH', b'\x02\x00\x00\x00\x00\x01', b'\x02\x00\x00\x00\x00\x02', 0x0800)
# IPv4 Header (UDP Proto=17)
iph = struct.pack('!BBHHHBBH4s4s', 0x45, 0, 20, 1, 0, 64, 17, 0,
socket.inet_aton('10.0.0.1'), socket.inet_aton(dst_ip))
return eth + iph
def main():
s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW)
s.bind(("dtap0", 0))
print("Sending Match Packet (192.168.1.1)...")
s.send(create_ipv4_packet('192.168.1.1')) # 匹配规则 -> Queue 1
time.sleep(1)
print("Sending Non-Match Packet (192.168.1.2)...")
s.send(create_ipv4_packet('192.168.1.2')) # 不匹配 -> Queue 0
3.2 运行 DPDK 程序
由于 net_tap 暂不支持 Template API,需使用传统模式:
1
2
3
4
5
6
7
# 启动程序 (创建 dtap0 接口)
sudo ./build/examples/dpdk-flow_filtering -l 1 -n 4 \
--vdev=net_tap0,queues=4 -- --non-template
# 在另一个终端启动接口并发送流量
sudo ip link set dtap0 up
sudo python3 send_traffic.py
4. net_tap 底层工作原理
4.1 TC Flower 映射
net_tap 驱动将 rte_flow 转换为 Linux 内核的 TC 过滤器:
- 解析: 将
rte_flow_item(如 IPv4 Dst) 转换为 Netlink 属性TCA_FLOWER_KEY_IPV4_DST。 - 动作: 将
RTE_FLOW_ACTION_TYPE_QUEUE转换为skbedit动作。 - 提交: 通过 Netlink 套接字将规则下发至内核。
4.2 数据路径
数据从内核到 DPDK 的旅程:
- 内核接收: 数据包到达虚拟接口。
- 分流: 内核 TC 子系统执行 Flower 匹配,
skbedit修改数据包的queue_mapping。 - 读取: DPDK PMD 轮询时,通过
readv()系统调用从对应的文件描述符(每个队列一个 FD)中拷贝数据。
5. 总结
- 性能权衡: 虚拟网卡验证虽然由于系统调用和内存拷贝性能较低,但能完美复现流规则逻辑。
- 调试建议: 如果规则未生效,检查内核是否开启了
CONFIG_NET_CLS_FLOWER支持。
This post is licensed under CC BY 4.0 by the author.