2. l3fwd 应用简介
l3fwd 是 DPDK 官方提供的第 3 层转发示例应用,用于演示如何基于 DPDK 数据平面开发套件实现高速 IP 路由转发。它从网卡接收数据包,根据 IPv4 目的地址查找转发表(LPM 或 Exact Match),然后将数据包从匹配的端口转发出去。l3fwd 是学习 DPDK 路由转发、多队列、RSS 和硬件卸载功能的经典起点。
核心定位:l3fwd 不是生产级路由器,而是 DPDK 路由转发功能的参考实现,用于验证 DPDK 数据面性能、转发表查找算法和 NIC 硬件分流能力。
2.1 l3fwd 功能
l3fwd 实现以下核心功能:
- 数据包接收:通过 DPDK PMD 驱动从物理网卡或虚拟设备接收以太网帧。
- 协议解析:解析 Ethernet、IPv4 头部,提取目的 IP 地址。
- 转发表查找:支持 LPM(最长前缀匹配)和 Exact Match(精确匹配)两种查找算法。
- 数据包转发:根据查找结果修改 Ethernet MAC 地址(源/目的),将数据包从指定端口发送。
- 多队列支持:利用 RSS(Receive Side Scaling)将数据流分发到多个接收队列,实现多核并行处理。
- 硬件卸载:支持 IP 校验和卸载、TCP/UDP 校验和卸载等 NIC 硬件加速特性。
| 功能模块 | DPDK 组件/API | 说明 |
|---|---|---|
| 数据包接收 | rte_eth_rx_burst() | 从 NIC 接收队列批量收取数据包 |
| 协议解析 | rte_ether.h / rte_ip.h | 解析 Ethernet 和 IPv4 头部结构 |
| 转发表查找 | rte_lpm / rte_hash | LPM 库或哈希库实现路由查找 |
| 数据包发送 | rte_eth_tx_burst() | 将数据包批量发送到目标端口 |
| 多队列分流 | RSS / rte_eth_dev_rss_reta_update() | 硬件 RSS 将流分发到不同队列 |
| 校验和卸载 | rte_net.h / mbuf ol_flags | 硬件计算并插入 IP/TCP/UDP 校验和 |
2.2 l3fwd 架构
l3fwd 采用典型的“运行到完成”(Run-to-Completion)模型,每个 lcore 独立运行一个转发线程,线程内部依次执行接收、查找、转发三个阶段。整体架构如下图所示:
架构要点说明:
- NIC 多队列:每个物理端口配置多个接收队列,RSS 根据 IP 五元组将数据流哈希到不同队列。
- lcore 与队列绑定:每个 lcore 绑定一个或多个接收队列,避免锁竞争,实现无锁数据面。
- 转发表共享:所有 lcore 共享同一个 LPM 转发表(只读),查找操作无锁。
- 发送队列:每个 lcore 对应一个发送队列,转发时直接写入对应端口的 TX 队列。
性能关键:l3fwd 的性能瓶颈通常不在 CPU 查找,而在内存访问延迟和 NIC 收发描述符环的填充效率。批量收发(burst size = 32 或 64)是发挥 DPDK 性能的关键。
2.3 l3fwd 命令行参数解析
l3fwd 支持丰富的命令行参数,用于配置端口、队列、转发模式、转发表规则等。以下为常用参数及其说明:
| 参数 | 格式 | 说明 | 示例 |
|---|---|---|---|
-p |
PORTMASK | 端口掩码,指定启用哪些物理端口(十六进制) | -p 0x3 启用 Port 0 和 Port 1 |
-P |
无参数 | 启用混杂模式(接收所有数据包) | -P |
-E |
无参数 | 使用 Exact Match(哈希)模式替代默认的 LPM 模式 | -E |
-L |
无参数 | 显式指定使用 LPM 模式(默认) | -L |
-q |
NQ | 每个端口分配的接收队列数量 | -q 4 每个端口 4 个 RX 队列 |
-l |
CORELIST | 指定使用的 lcore 列表(DPDK 标准格式) | -l 0-3 使用 lcore 0~3 |
--config |
(port,queue,lcore)[,...] | 精细配置端口/队列与 lcore 的绑定关系 | --config="(0,0,0),(1,0,1)" |
--rule_ipv4 |
FILEPATH | 从文件加载 IPv4 转发表规则 | --rule_ipv4="rules.txt" |
--eth-dest |
PORT,MAC | 指定端口对应的目的 MAC 地址(用于重写) | --eth-dest=0,00:11:22:33:44:55 |
--parse-ptype |
无参数 | 在软件中解析数据包类型(当 NIC 不支持硬件 ptype 时) | --parse-ptype |
2.3.1 典型启动示例
以下为 l3fwd 的典型启动命令,使用 4 个 lcore、2 个端口、每个端口 2 个队列:
./build/l3fwd -l 0-3 -n 4 -- -p 0x3 -P -q 2 \
--config="(0,0,0),(0,1,1),(1,0,2),(1,1,3)" \
--eth-dest=0,00:1a:2b:3c:4d:5e \
--eth-dest=1,00:1a:2b:3c:4d:5f
参数解析:
-l 0-3:使用 lcore 0、1、2、3 处理数据包。-n 4:每个 CPU socket 分配 4 个内存通道(与硬件匹配)。-p 0x3:启用 Port 0 和 Port 1(二进制 0b11)。-P:启用混杂模式,接收所有数据包。-q 2:每个端口创建 2 个接收队列。--config:将 Port 0 Queue 0 绑定到 lcore 0,Port 0 Queue 1 绑定到 lcore 1,Port 1 Queue 0 绑定到 lcore 2,Port 1 Queue 1 绑定到 lcore 3。--eth-dest:指定转发时重写的目的 MAC 地址。
注意事项:l3fwd 默认使用 LPM 模式,转发表规则需要在代码中硬编码或通过
--rule_ipv4 文件加载。如果不加载任何规则,l3fwd 将不会转发任何数据包。在实际课程实验中,我们将手动构建转发表并注入规则。
2.3.2 转发表规则文件格式
当使用 --rule_ipv4 参数时,规则文件格式如下:
# 格式:目的IP/掩码 下一跳端口
10.0.1.0/24 0
10.0.2.0/24 1
192.168.1.0/24 0
172.16.0.0/16 1
每行包含一个路由条目:目的网络(CIDR 格式)和对应的输出端口号。l3fwd 启动时将这些规则插入 LPM 转发表。
2.3.3 运行时统计与调试
l3fwd 在运行时会周期性地打印统计信息,包括每个端口的接收/发送数据包计数、丢包数等。通过 --parse-ptype 参数可以启用软件 ptype 解析,帮助调试 NIC 硬件 ptype 识别问题。