运行DPDK23.11 eventdev_pipeline样例程序崩溃问题
发表于 2025/04/28
0
作者|王陈星宇
问题描述
- DPDK服务器为鲲鹏 + Openeuler22.03 OS 。使用以下命令启动eventdev_pipeline样例程序会程序崩溃,核心已转储 :
./dpdk-eventdev_pipeline -l 0-48 --vdev event_sw0 -- -r1 -t1 -e1 -w ff0 -s5 -n0 -c32 -W1000 -D
- X86服务器 + Openeuler22.03 OS 可复现该问题
问题分析
函数调用栈分析
问题场景的调用栈如下图所示。可以看到挂死的原因是访问了异常指针地址。
分析报错代码
eventdev_pipeline样例程序的报错代码如下图所示。该地址是来自queue结构体保存的tx_buf地址,queue结构体是通过对queue数组作偏移得到的。挂死函数需要对这个tx_buf进行读写。

触发报错代码验证分析
经维测打印排查,未发现queue数组的基地址存在异常,用作偏移量的queue明显大于queue结构体中描述queue队列长度的nb_queues数值。
进一步分析代码发现,这里的queue来自mbuf.hash.txadapter.txq,这个值在问题场景代码流程中没有进行过赋值操作和值校验。而其他eventdev_pipeline样例程序(app/eventdev_pipeline)中,在first stages中对其进行了赋值操作。
解决方案与验证
方案一 :在发送前对queue做值范围保护
程序崩溃根因是错误偏移量导致的踩内存,可以考虑在计算queue地址前添加queue < nb_queues
的保护作为临时解决方案一。该方案能适配发送队列不为1的业务场景,但是触发该问题的数据包会丢失。- 修改方法 :将
\dpdk-23.11\dpdk-23.11\lib\eventdev\rte_event_eth_tx_adapter.c
文件txa_service_tx
函数定义中的第624行
tqi = txa_service_queue(txa, port, queue);
替换成
if (likely(queue < txa->txa_ethdev[port].nb_queues)) {
tqi = txa_service_queue(txa, port, queue);
} else {
tqi = NULL;
}

方案二 :在pipeline的第一个stage对txq进行赋值
由于其他样例程序在处理流程中对queue进行了赋值,且当前的程序仅有一个发包队列,因此可以在eventdev_pipeline程序里添加这个赋值,作为临时解决方案二。该方案不会导致数据包丢失,但是会让所有的数据包会进入同一个发送队列,若业务中存在多个发送队列时,需要自行适配。- 修改方法 :将
\dpdk-23.11\examples\eventdev_pipeline\pipeline_worker_generic.c
文件worker_generic_burst
函数定义中的第100行
if (events[i].queue_id == cdata.qid[0])
及其if代码块替换成
if (events[i].queue_id == cdata.qid[0]) {
events[i].flow_id = events[i].mbuf->hash.rss
% cdata.num_fids;
rte_event_eth_tx_adapter_txq_set(events[i].mbuf, 0);
}
问题总结
- 方案验证中的两种方案在鲲鹏、x86环境中均进行了验证,方案修改后均未复现挂死现象。方案一会丢弃问题数据包,方案二在多发送队列场景下需要自行适配调度策略。对于挂死问题可根据业务实际需求,任选一种方案进行修改后即可修复。
- 方案二已提交DPDK社区,Patch地址 : https://mails.dpdk.org/archives/dev/2024-August/298848.html