5. DPDK:报文转发

16 阅读9分钟

1. 前言

对于一个从运营商网络进入路由器的报文,最后还能顺利抵达某台服务器,那背后经历的旅程比我们想象得更复杂。它既要快,还得准。整个转发流程就像一条高速生产线:重复性极强、多样性丰富、逻辑复杂、性能要求苛刻。

如果我们不了解每个环节是如何协同处理包,那就很难真正把网络性能挖到极致。想让转发更快,先搞清楚转发框架怎么运作,这就是本章的主角。

2. 网络报文的处理模块如何划分?

从宏观角度看,网络包处理主要分成两大阵营:

  1. 硬件负责加速数据通道
  2. 软件负责策略与调度控制

你可以把它看成高速公路的两个系统: 一个负责修路铺桥(硬件),一个负责红绿灯与交通指挥(软件)。

image.png 标准的数据处理流程可以拆成如下模块:

模块简介
Packet Input收包,从网卡进入系统
Pre-processing粗粒度检查,如过滤与解析
Input Classification精细识别,如流分类
Ingress Queuing进入入口队列,描述符FIFO
Delivery & Scheduling调度包去哪个CPU核心处理
Accelerator硬件卸载,如加解密、压缩、校验
Egress Queueing出口队列,按QoS决定优先级
Post Processing从软件侧做收尾释放资源
Packet Output最终发包到线缆上,奔向下一跳

硬件能做的,软件不要抢;软件做的事,尽量让CPU并行干

硬件卸载能显著提升以下任务性能:

• checksum offload
• RSS分流
• VLAN、VXLAN、MACsec处理
• IPsec加解密等专用引擎
• TSO/LSO、GRO/GSO类分片合并

软件层多依赖算法优化、NUMA亲和性、多核并行等方式追性能

一句“提纲挈领”的总结:

硬件负责“快车道”,软件负责“大脑”。
想拿满性能分数,这两者都得调到最佳状态。

接下来,我们会基于不同网络框架(Linux内核、DPDK)来深入对照:模块如何协作?性能差距从何而来?游戏规则到底变在哪里?

这正是 DPDK 所擅长重新洗牌的地方。

3. 转发框架介绍

网络转发的核心挑战在于既要保证吞吐量,也要保证处理灵活性。传统网络处理器(NP)为此发展出两种经典转发模型:

• Pipeline(流水线模型)
• Run to Completion(运行至终结模型,简称 RTC)

这两种模型的思想,也正是 DPDK 在通用处理器上追求极致性能的理论基础。

3.1 Pipeline 流水线模型

流水线模型借鉴工业制造: 把一个完整的网络报文处理流程拆分为多个阶段,每个阶段由独立的处理引擎负责,通过队列连接。

优点说明
性能强CPU 密集与 I/O 密集任务分离,互不干扰
可扩展阶段数量与核资源可按需扩展
延迟均衡队列调节处理速率,防止堵塞

典型结构如 Ezchip NPA: 多个专用 TOP(Task Optimized Processor)单元依次执行解析、查表、修改等任务,严格流水化。 劣势是顺序固定,灵活性较弱,某些流程倒回会显著降低性能。

3.2 Run to Completion 运行至终结模型(RTC)

与流水线相反,RTC 模型强调:单个 CPU 核从报文进入到发送,完整执行全部处理流程.

AMCC 345x NP 就采用此模型: 多个 NP 核同时处理不同报文,每个核内部运行完整微码,让报文快速“走完一生”。

优点不足
逻辑耦合低、实现简单单核处理能力成为瓶颈
横向扩展容易(多核并行)无法利用更多核提升单报文性能

3.3 DPDK中RTC与Pipeline的融合

在DPDK中,Run to Completion(RTC)Pipeline 并不是孤立存在的,而是根据报文处理的复杂度和性能要求灵活结合使用,形成一个高效的包处理体系。

3.3.1 核心思想

  • RTC模型:一个线程(绑定到CPU核)从报文接收(RX)到发送(TX)处理整个报文生命周期。
    优点:

    • 实现简单,逻辑集中。
    • 利用CPU缓存和硬件指令(如AES-NI、CRC加速)高效完成加解密、校验等操作。
    • 特别适合处理简单、快速路径报文,例如基本的L2/L3转发。
  • Pipeline模型:将报文处理拆分为多个功能模块(Module),每个模块只处理特定事务,通过队列串联形成流水线。
    优点:

    • 可以并行处理多个报文,提高CPU利用率。
    • 适合复杂报文处理,例如ACL匹配、流量计量、路由查表、报文修改。
    • 可以跨多个CPU核分布,提高整体吞吐。

DPDK的创新之处在于:通过合理设计调度和线程绑定,将两种模型结合,兼顾性能与灵活性

3.3.2 结合方法

  1. 快速路径走RTC

    • 对于普通报文或无需复杂处理的报文,直接由一个worker线程全程处理(RX→解析→TX),即RTC模式。
    • 每个核可独立处理多个流,通过轮询队列(poll mode)避免中断开销。
    • RTC线程充分利用CPU本地缓存,减少跨核通信,提高简单报文的转发速率。
  2. 复杂路径走Pipeline

    • 对于需要执行多级处理(如ACL、LPM查表、报文修改、加解密)的报文,经过 Pipeline分发 到不同模块:

      • Module A:解析报文、提取元数据
      • Module B:ACL/路由查表
      • Module C:修改报文头或执行QoS动作
      • Module D:发送到目标端口
    • 每个模块可部署在不同核上,并行处理不同报文,提高吞吐。

  3. 融合策略

    • 使用 Packet Distributor 将报文分发到RTC线程或Pipeline模块:

      • 简单报文 → RTC线程
      • 复杂报文 → Pipeline模块
    • Distributor依据报文特征(如流标识、协议类型、长度)进行智能调度。

    • 处理完的Pipeline报文可返回RTC线程做最终发送或进入另一个Pipeline阶段,形成灵活的多级处理链。

3.3.3 举例说明

假设有一个包含以下功能的网络应用:

  1. L2/L3转发
  2. ACL匹配
  3. 路由查表(LPM)
  4. 报文修改(NAT/修改VLAN)

DPDK可这样处理:

  • RTC线程:快速处理普通的L2/L3报文,直接接收并发送。

  • Pipeline模块:复杂报文经过分发:

    • Module 1:ACL匹配
    • Module 2:LPM查表
    • Module 3:报文修改
  • 最后返回RTC线程发送。

这样一条报文只需在Pipeline中经过相关模块,而无需RTC线程处理每一步,保证高吞吐同时保持低延迟。

4. 转发算法

在高速报文转发中,仅有框架是不够的,核心在于如何快速识别和匹配报文中的字段,从而决定报文的处理和转发策略。DPDK提供了一整套算法体系,包括精确匹配(Exact Match)、最长前缀匹配(Longest Prefix Matching, LPM)、ACL规则,以及多核报文分发(Packet Distributor)。这些算法结合前面讲到的 RTC和Pipeline模型,形成了高性能的数据平面处理链路。

4.1 精确匹配(Exact Match)

精确匹配是最直观的匹配方式:报文字段必须完全匹配才算命中。为了保证高速查找,DPDK采用了 哈希表

  1. 原理

    • 对每个需要匹配的字段计算哈希值(数字签名),快速定位对应条目。
    • 哈希性能受负载因子 L=n/k 控制,L过大容易冲突,过小浪费空间。
  2. 冲突解决

    • 分离链表:冲突条目用链表串起来,查找时遍历链表。
    • 开放地址:冲突条目顺序放入下一个空桶,减少链表操作,但连续冲突可能增加延迟。
  3. CRC加速

    • DPDK支持 CRC32 作为哈希签名。CRC检验本质上是对数据做 多项式模2运算(异或) ,附加校验码确保数据正确性。

    • 示例:

      10011011 + 11001010 = 01010001
      
    • 生成多项式约定了CRC规则,例如CRC32的多项式:

      X32 + X26 + X23 + X22 + X16 + X12 + X11 + X10 + X8 + X7 + X5 + X4 + X2 + X1 + 1
      
    • DPDK对CRC做了优化:

      1. 支持8字节/4字节单位处理。
      2. 利用硬件SSE4.2指令 crc32q / crc32l 加速。
      3. 查表法优化,空间换时间。
    • 支持并行查找函数 rte_hash_lookup_multi,可同时处理多条报文,提高吞吐。

4.2 最长前缀匹配(LPM)

LPM主要用于IP路由表查找。目标是找到与目的地址匹配的最长子网前缀

  • DPDK实现用 两级表

    1. 前24位在 tbl24 查找。
    2. 若需要扩展,用后8位在 tbl8 查找下一跳。
  • 特点:

    • 大部分查找只需一次内存访问(命中tbl24)。
    • 空间换时间,兼顾性能与大规模路由表。
struct rte_lpm_tbl24_entry {
    union { uint8_t next_hop; uint8_t tbl8_gindex; };
    uint8_t valid :1;
    uint8_t ext_entry :1;
    uint8_t depth :6;
};
struct rte_lpm_tbl8_entry {
    uint8_t next_hop;
    uint8_t valid :1;
    uint8_t valid_group :1;
    uint8_t depth :6;
};

4.3 ACL算法

ACL(Access Control List)通过 N元组匹配 对报文进行策略分类,实现防火墙、流量控制等功能:

  • 支持创建上下文、添加规则、分类报文、销毁资源。
  • 匹配字段通过 rte_acl_field_def 定义:
struct rte_acl_field_def {
    uint8_t type;       // 字段类型
    uint8_t size;       // 字节长度
    uint8_t field_index;
    uint8_t input_index;
    uint32_t offset;    // 偏移
};

  • 每条规则可定义优先级和类别掩码。内部用 多层Tier结构 匹配每个字节,最终确定命中路径。

  • 这种结构类似“决策树”,多核Pipeline中可以并行处理多个ACL查询。

4.4 报文分发(Packet Distributor)

DPDK的报文分发模块用于 多核环境下高效调度

  • 一个 distributor 将报文分发到多个 worker 核上处理。

  • Mbuf的tag可由硬件或软件提供,用于保证同一流的报文总是分配给同一个worker。

  • 核心API:

    • rte_distributor_process:分发报文,处理backlog。
    • rte_distributor_get_pkt:worker获取报文。
  • 可结合 ordering 库保证报文顺序。