4. 转发模式详解:io-forward、mac-forward、flowgen、rxonly、txonly 模式原理与适用场景

testpmd 的转发模式决定了数据包在网卡端口之间的处理与传递方式。理解每种模式的内部数据流、内存操作和 CPU 开销,是进行性能调优和丢包分析的基础。本章将深入剖析五种核心转发模式:io-forward、mac-forward、flowgen、rxonly 和 txonly。

4.1 转发模式总览与选择矩阵

下表从数据流方向、是否修改 MAC、是否生成包、CPU 开销和典型场景五个维度,对五种模式进行横向对比:

模式 数据流方向 MAC 修改 包生成 CPU 开销 典型场景
io-forward RX → TX (同端口/异端口) 不修改 否 低 纯转发性能基准测试
mac-forward RX → TX (异端口) 交换源/目的 MAC 否 中 二层交换机行为模拟
flowgen RX → TX + 软件生成流 按流表修改 是 (控制流) 高 流表压力与老化测试
rxonly RX → 丢弃 不适用 否 最低 纯接收性能、驱动稳定性
txonly 软件生成 → TX 构造时设定 是 低 纯发送性能、线速测试
调优提示: 在测试网卡极限 PPS 时,优先使用 io-forward 或 rxonly/txonly 组合,避免 MAC 地址重写或流表查询带来的额外 CPU 周期开销。

4.2 io-forward:纯 I/O 转发模式

io-forward 是 testpmd 默认且最轻量的转发模式。其核心逻辑是:从 RX 描述符环收到 mbuf,不经任何修改,直接将其送入同一端口或指定端口的 TX 描述符环。

4.2.1 原理与数据流

  • 零拷贝:mbuf 指针直接从 RX 队列传递到 TX 队列,不涉及数据内容拷贝。
  • 无 MAC 重写:以太网帧头保持原样,源 MAC 和目的 MAC 均不修改。
  • 端口映射:支持 --nb-cores 和 --rxq/--txq 配置,每个 lcore 处理一组 RX/TX 队列对。
关键代码路径(简化):
static void pkt_burst_io_forward(struct fwd_stream *fs) {
    uint16_t nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue,
                                       fs->rx_pkts, nb_pkt_per_burst);
    if (unlikely(nb_rx == 0))
        return;
    uint16_t nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue,
                                       fs->rx_pkts, nb_rx);
    /* 处理未成功发送的包(回退或丢弃) */
    if (unlikely(nb_tx < nb_rx))
        fs->fwd_dropped += (nb_rx - nb_tx);
}

4.2.2 内联 SVG:io-forward 数据流架构

io-forward 数据流架构 网卡 RX 端口 testpmd 转发 网卡 TX 端口 mbuf 指针零拷贝传递,不修改帧内容 RX 描述符环 TX 描述符环

4.2.3 适用场景

  • 网卡 PPS 基准测试:消除软件开销,测量网卡和 PCIe 总线的极限吞吐。
  • 驱动稳定性验证:长时间运行 io-forward,观察是否有描述符泄漏或硬件挂死。
  • 多队列负载均衡测试:配合 RSS 配置,验证流量是否均匀分布在多个 RX 队列上。

4.3 mac-forward:二层 MAC 重写转发

mac-forward 模拟二层交换机的行为。它在转发前会交换以太网帧的源 MAC 和目的 MAC 地址,确保对端设备能够正确回复。

4.3.1 原理与数据流

  • MAC 重写:将接收到的帧的源 MAC 写入目的 MAC 字段,将本端口的 MAC 写入源 MAC 字段。
  • 端口隔离:默认只在两个不同端口之间转发(如 port 0 ↔ port 1),避免环路。
  • FDB 查询:可选启用软件 FDB(转发数据库),根据目的 MAC 查找出端口。
性能陷阱: mac-forward 模式下,每个包都需要进行 12 字节的 MAC 地址拷贝(6 字节源 + 6 字节目的),在 64 字节小包场景下,这会增加约 10%-15% 的每包 CPU 开销。如果测试纯转发性能,应使用 io-forward。

4.3.2 内联 SVG:mac-forward MAC 重写流程

mac-forward MAC 地址重写流程 原始以太网帧 DMAC=00:11:22:33:44:55 SMAC=AA:BB:CC:DD:EE:FF 交换 DMAC ↔ SMAC memcpy 12 字节 修改后以太网帧 DMAC=AA:BB:CC:DD:EE:FF SMAC=00:11:22:33:44:55 重写后帧从另一个端口发出,对端设备可正常回复

4.3.3 适用场景

  • 二层转发功能验证:测试 DPDK 应用作为透明网桥或交换机的行为。
  • MAC 学习/老化测试:配合 --eth-peer 参数,验证 FDB 表项的正确性。
  • 环路避免测试:结合 STP(生成树协议)模拟,验证端口阻塞逻辑。

4.4 flowgen:流生成与转发混合模式

flowgen 是一种混合模式,它在接收流量并转发的同时,还会在软件层面主动生成新的数据流,用于测试流表容量和老化机制。

4.4.1 原理与数据流

  • 双路径:一路处理 RX 收到的包(类似 mac-forward),另一路周期性地从软件构造新包注入 TX。
  • 流表操作:每个生成的流对应一个唯一的 5 元组,可配置流表大小和老化时间。
  • CPU 密集型:需要维护定时器、流表哈希表和包构造逻辑,CPU 开销显著高于其他模式。
启动示例:
./dpdk-testpmd -l 0-3 -n 4 -- -i --forward-mode=flowgen \
    --flowgen-rxq=2 --flowgen-txq=2 \
    --flowgen-flows=1024 --flowgen-rate=1000

上述命令启动 1024 条流,每条流每秒发送 1000 个包。

4.4.2 内联 SVG:flowgen 双路径架构

flowgen 双路径架构 RX 接收 MAC 重写 TX 发送 流生成器 (定时器驱动) 流表 (1024 条目) 路径1:处理外部真实流量;路径2:构造新流测试流表容量与老化 两条路径共享同一个 TX 队列,通过优先级或轮询调度

4.4.3 适用场景

  • 流表容量压力测试:验证硬件或软件流表在满载时的转发性能。
  • 老化机制验证:配置短老化时间,观察流表条目是否被正确回收。
  • 控制面与数据面交互测试:模拟控制面下发流表,数据面按流表转发。

4.5 rxonly:纯接收模式

rxonly 模式只从网卡接收数据包,然后立即释放 mbuf,不进行任何转发或发送操作。

4.5.1 原理与数据流

  • 接收即释放:调用 rte_eth_rx_burst 后,遍历所有收到的 mbuf 并调用 rte_pktmbuf_free。
  • 无 TX 路径:不初始化 TX 队列,节省内存和 PCIe 带宽。
  • 统计计数:仅累加接收计数和字节数,不进行任何协议解析。
调试技巧: 当怀疑丢包发生在 TX 侧时,使用 rxonly 模式可以隔离问题。如果 rxonly 下接收计数与发包器一致,说明 RX 路径正常,问题出在 TX 或转发逻辑。

5.5.2 适用场景

  • 网卡接收性能极限测试:测量网卡在无软件处理开销下的最大接收 PPS。
  • 驱动 RX 路径稳定性测试:长时间运行,检查描述符泄漏或 RX 中断异常。
  • 丢包问题定位:作为对比基准,判断丢包是发生在 RX 还是 TX 阶段。

4.6 txonly:纯发送模式

txonly 模式不接收任何数据包,完全由软件构造数据包并通过 TX 队列发送出去。

4.6.1 原理与数据流

  • 包构造:在转发循环中,调用 rte_pktmbuf_alloc 分配 mbuf,然后填充以太网头、IP 头、UDP 头等。
  • 速率控制:支持 --txonly-multi-flow 和 --txonly-pps 参数控制发送速率和流数量。
  • 无 RX 路径:不初始化 RX 队列,减少中断和 DMA 开销。
构造包示例(UDP 包):
struct rte_mbuf *pkt = rte_pktmbuf_alloc(mpool);
if (pkt) {
    pkt->data_len = 64;  // 64 字节小包
    pkt->pkt_len  = 64;
    char *data = rte_pktmbuf_mtod(pkt, char *);
    /* 填充以太网头 */
    memcpy(data, ð_hdr, sizeof(eth_hdr));
    /* 填充 IP 头 */
    memcpy(data + sizeof(eth_hdr), &ip_hdr, sizeof(ip_hdr));
    /* 填充 UDP 头 */
    memcpy(data + sizeof(eth_hdr) + sizeof(ip_hdr), &udp_hdr, sizeof(udp_hdr));
}

4.6.2 内联 SVG:txonly 包构造与发送流程

txonly 包构造与发送流程 分配 mbuf rte_pktmbuf_alloc 填充帧头 ETH + IP + UDP 速率整形 --txonly-pps TX 发送 rte_eth_tx_burst 无 RX 路径,所有包由软件构造,用于测试网卡发送线速 支持多流模式,通过修改 IP 头中的源/目的地址生成不同流

4.6.3 适用场景

  • 网卡发送性能极限测试:测量网卡在无接收干扰下的最大发送 PPS。
  • 线速测试:配合流量分析仪,验证网卡是否能够达到线速(如 10G/25G/100G)。
  • 包构造逻辑验证:测试不同包大小、协议组合下的发送稳定性。

4.7 模式选择决策树

在实际调试中,可以根据以下决策树快速选择正确的转发模式:

转发模式选择决策树 测试目标是什么? 纯接收性能 rxonly 纯发送性能 txonly 转发性能 需要 MAC 重写? 否 → io-forward 是 → mac-forward

4.8 本章小结

  • io-forward 是最轻量的纯转发模式,适合性能基准测试。
  • mac-forward 模拟二层交换机,适合功能验证。
  • flowgen 是混合模式,用于流表压力和老化测试。
  • rxonly 和 txonly 分别用于隔离接收和发送路径的问题。
  • 选择模式时,应根据测试目标(性能/功能/稳定性)和是否需要修改包内容来决定。
常见误区: 不要使用 mac-forward 或 flowgen 来测量网卡的极限 PPS,它们的额外 CPU 开销会掩盖硬件性能。始终使用 io-forward 或 rxonly/txonly