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 硬件加速特性。
l3fwd 功能模块与对应 DPDK 组件
功能模块 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 独立运行一个转发线程,线程内部依次执行接收、查找、转发三个阶段。整体架构如下图所示:

l3fwd 软件架构图 物理网卡 (NIC) Port 0 / Port 1 / Port 2 / Port 3 RSS 硬件分流 (多队列) RX Queue 0 RX Queue 1 RX Queue N lcore 0 rx_burst() lpm_lookup() tx_burst() lcore 1 rx_burst() lpm_lookup() tx_burst() lcore N rx_burst() lpm_lookup() tx_burst() LPM 转发表 TX Queue 0 TX Queue 1 TX Queue N

架构要点说明:

  • NIC 多队列:每个物理端口配置多个接收队列,RSS 根据 IP 五元组将数据流哈希到不同队列。
  • lcore 与队列绑定:每个 lcore 绑定一个或多个接收队列,避免锁竞争,实现无锁数据面。
  • 转发表共享:所有 lcore 共享同一个 LPM 转发表(只读),查找操作无锁。
  • 发送队列:每个 lcore 对应一个发送队列,转发时直接写入对应端口的 TX 队列。
性能关键:l3fwd 的性能瓶颈通常不在 CPU 查找,而在内存访问延迟和 NIC 收发描述符环的填充效率。批量收发(burst size = 32 或 64)是发挥 DPDK 性能的关键。

2.3 l3fwd 命令行参数解析

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 识别问题。