首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >利用DPDK LPM加速VPP ABF:实现DIP网段高效匹配与性能优化

利用DPDK LPM加速VPP ABF:实现DIP网段高效匹配与性能优化

作者头像
dpdk-vpp源码解读
发布2025-11-14 13:51:28
发布2025-11-14 13:51:28
3300
举报
文章被收录于专栏:DPDK VPP源码分析DPDK VPP源码分析
在当前快速发展的网络环境中,数据处理的速度和效率已成为决定系统性能的关键因素。随着网络流量的持续增长,对高性能数据包处理的需求变得尤为迫切。最近,在一个项目开发过程中遇到了这样一个需求:需要导入超过1万条国内网段路由,并确保数据报文的目的IP(DIP)能够准确匹配到这些网段之一,进而指定出口进行转发。

为实现这一目标,我们选择了基于VPP的(ABF)模块。然而,ABF依赖于访问控制列表(ACL)模块来完成报文的匹配工作。ACL模块在首次匹配时采用的是遍历规则的方式,这意味着当面对10,000多条规则时,其处理效率会显著下降。考虑到网段路由集合与最长前缀匹配(LPM)算法之间的天然契合性——LPM算法能够在大量路由表项中迅速找到最佳匹配项,其查找复杂度接近O(1)——我们决定将DPDK中的LPM模块引入到VPP框架中。通过这种方式,不仅能够大幅提高VPP在处理大规模网段路由匹配任务时的性能,还能有效提升数据包的转发效率。

本文将详细介绍如何将DPDK LPM模块集成进VPP环境,以优化基于目的IP地址的网段匹配过程,从而克服传统ACL遍历方式带来的性能瓶颈,为高负载网络环境下的高效数据处理提供强有力的支持。这种整合策略充分利用了LPM算法的优势,实现了从传统线性搜索到快速索引查找的转变,极大地提升了系统的整体响应速度和服务质量。

DPDK LPM(最长前缀匹配,Longest Prefix Match)库是一个专为高性能路由查找设计的组件,目的是在数据包转发过程中高效查询与目标IP地址最佳匹配的路由表项。通过优化查找算法和数据结构,LPM库确保了即使在大规模路由表中也能实现快速且高效的路由决策。

DPDK LPM的特点:高效查找:使用DIR-24-8算法的一个变种来实现高速查找。这个算法将32位IPv4地址分为两部分处理:前24位和后8位。通过这种方式,大多数情况下只需要一次内存访问就能完成查找。空间换时间:为了加快查找速度,该算法牺牲了一定的空间。理论上,每个tbl24条目都可以指向一个tbl8数组,tbl8的数量可以根据用户配置情况指定。

DPDK LPM模块主要由两个层次的数据结构组成:

tbl24:这是一个大小为2^24的数组,用于存储前24位IP地址的索引。每个条目要么直接存储下一跳信息,要么指向一个tbl8组。

tbl8:这是多个大小为2^8的数组,用于存储剩余8位IP地址的索引。只有当路由条目的掩码长度大于24时才会用到这些tbl8组(根据实际情况设置tbl8的使用数量)。

核心数据结构如下(来源于参考文章1)

在这里插入图片描述
在这里插入图片描述

以IP地址36.37.69.38匹配网段36.37.39.0/24为例,当前添加网段时36.37.39.0/24,next_hop=1时,将网段转换为u32数据606,414,592(36<<24+27<<16+39<<8+0)。然后将转换后u32 数据右移8位,便得到了在tlb24下的下标。设置rte_lpm_tbl_entry表1内容。

代码语言:javascript
复制
depth = 24;
valid_group = 0;
valid = 1;
next_hop = 1;

当我们添加36.37.39.16/28,next_hop=2的时候,因为掩码28大于24,需要申请tbl8表的存储资源。需要从tbl8资源中,查询到一块未使用的资源。记录tbl8表资源的起始索引 index;然后将index +0~index+255之前的区域,全部赋值成设置rte_lpm_tbl_entry表1内容。再将tbl24表内容赋值为:

代码语言:javascript
复制
depth = index;  #注意
valid_group = 1;
valid = 1;
next_hop = 1;

然后将index+16~index+31的区域赋值成下表的内容:

代码语言:javascript
复制
depth = 28;
valid_group = 0;
valid = 1;
next_hop = 2;
代码语言:javascript
复制
__extension__
struct rte_lpm_tbl_entry {
uint32_t depth       :6;
uint32_t valid_group :1;
uint32_t valid       :1;
uint32_t next_hop    :24;

};
valid:表示此节点是否有效。 1:表示命中,0:表示未命中。未命中直接退出。
valid_group:表示当前存在tbl8节点,next_hop存储 tbl8 节点起始索引。
next_hop: 当valid_group=0时,存储下一跳索引 next_hop,否则存储tbl8数据
         起始节点索引。
depth:存储掩码。

在实际使用过程中,还遇到了一些问题或可优化的点。例如,DPDK 库默认以插件形式加载,而插件之间的函数默认不可见的。 LPM(Longest Prefix Match)相关接口如何被其他插件安全、高效地调用?VPP 代码中为此提供了两种实现方式:

1、dlsym函数动态加载函数符号表

vlib_get_plugin_symbol 是 VPP(Vector Packet Processing)框架中用于从动态加载的插件(.so 共享库)中获取符号地址的辅助函数。其核心依赖于 POSIX 标准中的 dlsym 函数,后者负责在运行时从已加载的动态库中查找并返回指定符号(如函数或全局变量)的地址。其中在abf插件中调用acl插件的函数接口就使用这种方法。

2、注册钩子函数方法。

在 VPP 中,当使用 DPDK 作为底层数据包 I/O 驱动时,其线程模型必须与 DPDK的CPU核心管理机制紧密协同。为此,VPP 通过注册 vlib_thread_callbacks_t 回调函数,将线程启动逻辑委托给 DPDK 实现。

具体而言,VPP 使用 rte_eal_remote_launch 启动工作线程,是因为 DPDK 在初始化时已对指定的逻辑核(lcore)实施独占控制——包括绑定 CPU 亲和性、禁用内核调度等。只有通过 DPDK 提供的线程启动机制,才能确保 VPP 工作线程运行在正确的执行上下文中,从而安全、高效地访问 DPDK 的内存池、PMD 驱动等高性能数据路径组件。

核心代码在vpp/src/plugins/dpdk/thread.c文件中,通过调用vlib模块提供的注册函数实现:

代码语言:javascript
复制
static clib_error_t *
dpdk_launch_thread (void *fp, vlib_worker_thread_t * w, unsigned lcore_id)
{
  int r;
  r = rte_eal_remote_launch (fp, (void *) w, lcore_id);
  if (r)
    return clib_error_return (0, "Failed to launch thread %u", lcore_id);
  return 0;
}

static clib_error_t *
dpdk_thread_set_lcore (u32 thread, u16 lcore)
{
  return 0;
}

static vlib_thread_callbacks_t callbacks = {
  .vlib_launch_thread_cb = &dpdk_launch_thread,
  .vlib_thread_set_lcore_cb = &dpdk_thread_set_lcore,
};

static clib_error_t *
dpdk_thread_init (vlib_main_t * vm)
{
  vlib_thread_cb_register (vm, &callbacks);
  return 0;
}

VLIB_INIT_FUNCTION (dpdk_thread_init);

为此,我们参考上述线程创建的示例,在 vnet 模块中新增一个名为 dpdk_lpm_lib 的库模块,用于封装并提供 DPDK 相关的注册与初始化功能。这样,其他插件便可便捷地调用该库,灵活使用 DPDK 函数实现各自的业务逻辑。各位,如何有更优的方案,欢迎加群讨论。

另外在使用dpdk lpm模块时,还有下面几个点需要注意:dpdk lpm模块内存默认使用的大页内存,创建一个lpm 实例大概需要占用40M左右内存资源。另外在导入域名列表的时候,为了提高导入的性能,需要对网段进行基于掩码从小到大的排序处理(这里看一下代码实现就可以)。

实际测试结果,导入1W条网段路由数据,仅占用0.1s的时间。在ip地址命中查询复杂度接近0(1)。

参考文章:

1、https://blog.csdn.net/Jmilk/article/details/129673463

2、https://doc.dpdk.org/guides/prog_guide/lpm_lib.html

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-11-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DPDK VPP源码分析 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档