前言
dpdk 内部逻辑核线程的创建按照使能的逻辑核掩码进行,dpdk 程序可以通过设定 -c、-l 参数来配置需要使能的逻辑核掩码。在公司内部项目开发时遇到了未指定这两个参数的情况,通过 top 观测到此时 dpdk 程序在每个逻辑核上都创建了线程,于是研究了下这种场景下 dpdk 内部的处理过程,在本文中记录一下。
dpdk 内部逻辑
dpdk 内部在解析用户设置的参数后会调用 eal_adjust_config 来处理如下场景的配置内容:
- 未设定使能的 cpu 核掩码时确定需要使能的逻辑核
- 设定 process_type 为 RTE_PROC_AUTO 时确定进程类型
- 未设定管理核时确定管理核
- 确定控制线程绑定到的 cpu 核
- 确定使用的内存的数量
关键过程代码如下:
..............................................................
if (!core_parsed)
eal_auto_detect_cores(cfg);
if (internal_config.process_type == RTE_PROC_AUTO)
internal_config.process_type = eal_proc_type_detect();
/* default master lcore is the first one */
if (!master_lcore_parsed) {
cfg->master_lcore = rte_get_next_lcore(-1, 0, 0);
if (cfg->master_lcore >= RTE_MAX_LCORE)
return -1;
lcore_config[cfg->master_lcore].core_role = ROLE_RTE;
}
compute_ctrl_threads_cpuset(internal_cfg);
/* if no memory amounts were requested, this will result in 0 and
* will be overridden later, right after eal_hugepage_info_init() */
for (i = 0; i < RTE_MAX_NUMA_NODES; i++)
internal_cfg->memory += internal_cfg->socket_mem[i];
core_parsed、master_lcore_parsed 变量在解析到相应的参数后设置为真,上述代码实际上是在处理缺省时使用的配置。上述代码中,dpdk 调用 eal_auto_detect_cores 函数来自动检测需要使能的逻辑核,其过程如下:
- 调用 pthread_getaffinity_np 函数获取当前线程的 cpu 亲和性设置 affinity_set 中保存当前线程允许被调度到的 cpu 核掩码,当获取失败时此掩码被清零表示关闭所有逻辑核
- 使用此掩码遍历每一个 dpdk 内部逻辑核配置结构,对未使能的 cpu 核设置 ROLE_OFF 标志以禁用
eal_auto_detect_cores 函数关键源码如下:
unsigned int lcore_id;
unsigned int removed = 0;
rte_cpuset_t affinity_set;
if (pthread_getaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
&affinity_set))
CPU_ZERO(&affinity_set);
for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
if (cfg->lcore_role[lcore_id] == ROLE_RTE &&
!CPU_ISSET(lcore_id, &affinity_set)) {
cfg->lcore_role[lcore_id] = ROLE_OFF;
removed++;
}
}
在未指定使能的逻辑核时,dpdk 会获取 rte_eal_init 函数运行线程的 cpu 亲和性设置,此设置由线程所在的 cgroup 组决定,缺省为使能所有 cgroup 组中使能的 cpu 核,这与前言中对现象的描述一致。
其它类似情况
如上文对 eal_adjust_config 函数的描述,除了缺省逻辑核掩码之外,此函数还处理了其它配置的缺省值绑定——如 master_lcore,当未指定时 dpdk 会使用第一个使能的逻辑核,一般都是 0 核,当未指定 master_lcore 参数且程序的管理核并非 0 核时就可能产生问题。
提供缺省值让程序能够在用户未设定某些依赖时仍旧能够正常运行,然而当用户并不清楚这种缺省值而使用不同的内容时也会有潜在的问题。