靶区;DR
我使用DPDK
以高吞吐量接收UDP数据包。当我尝试释放rte_mbufs
时(UDP数据包)在一个没有运行在DPDK lcore
上的线程上使用rte_pktmbuf_free_bulk()
,实际上没有释放rte_mbuf
,这导致无法接收超过4096个数据包。我是否需要将所有逻辑移动到运行在lcore
上的线程上,还是我还能做些什么来让这一切继续下去
DPDK设置注意事项
我是DPDK的新手,继承了代码的初始化部分,这部分代码太长了,无法在这里包含。我不确定关于配置的哪些具体细节可能是重要的或相关的,但如果有人对DPDK设置有具体问题,我很乐意补充这篇文章。然而,我已经包含了主要的RX循环代码及其描述,如下。
代码说明:
- 主RX循环包含在一个名为
_receive_packets()
的方法中,该方法只能使用rte_eal_remote_launch()
调用,这就是为什么参数是用空指针传递的。 thread_arg
是我定义的一个结构体,用于在使用rte_eal_remote_launch()
调用此函数时传递所需的所有参数。- 由于一些可能与这个问题无关的原因,
_receive_packets()
必须是一个静态类方法,这就是为什么你会看到奇怪的input_arg->ds_instance
表示法。 input_arg->ds_instance->m_active
在应用程序关闭时变为false。BURST_SIZE
是512IO_Job
是一个结构体,我使用它来将数据包发送到另一个(非lcore)线程,并使用rte_ring
进行处理和流式传输到文件。使作业出队的代码在数据包上调用rte_eal_remote_launch()
并删除在_receive_packets()
中创建的任何对象,因此看起来可能存在内存泄漏,但实际上并没有。input_arg->ds_instance->enqueue_io_job()
是一个helper函数,它简单地将一个作业排队到上面提到的rte_ring
。
密码
void Data_Streamer::_receive_packets(void* arg)
{
thread_arg* input_arg = (thread_arg*) arg;
uint16_t port_id = input_arg->port_id;
uint16_t queue_id = input_arg->queue_id;
long long bytes_recorded = 0;
while (input_arg->ds_instance->m_active)
{
// If BURST_SIZE packets not ready, then do nothing this cycle
if (rte_eth_rx_queue_count(port_id, queue_id) < BURST_SIZE) continue;
// Once data is available, get packets as burst
rte_mbuf** packets = new rte_mbuf*[BURST_SIZE];
const uint16_t got_num_packets = rte_eth_rx_burst(port_id, queue_id, packets, BURST_SIZE);
// Package packets into job and enqueue the job
if (got_num_packets)
{
IO_Job* job = new IO_Job;
job->byte_offset = bytes_recorded;
job->packets = packets;
job->num_packets = got_num_packets;
input_arg->ds_instance->enqueue_io_job(job);
}
}
}
故障排除注意事项
- 当我修改代码,使
rte_pktmbuf_free_bulk()
在作业入队后立即从_receive_packets()
调用时,数据包将按预期释放,但是,这会创建一个争用条件,其中数据包中的数据可能会在非lcore
线程上处理之前被新的数据包数据覆盖。 - 我尝试进一步修改代码,以便将数据包缓存在
_receive_packets()
中,直到在非lcore
线程上运行的进程发送一个通知,表明它已使用数据。在这种情况下,行为与在非lcore
线程中释放数据包时的行为类似-数据包不被释放。(就好像只查看非lcore
线程中的数据会阻止它被正确释放一样,即使从lcore
线程中释放也是如此。 - 如果我重复上面的尝试,但是使用
rte_pktmbuf_mtod()
提取我实际想要读取的缓冲区的地址,这样我就不会向非lcore
线程发送指向packets对象的指针,它仍然没有正确地释放rte_mbuf
。
1条答案
按热度按时间hi3rlvi21#
解决方案是在DPDK lcore线程上执行所有使用
mbuf
的代码。没有必要在所有使用rte_pktmbuf_free()
的线程上释放数据包,正如我之前在评论中建议的那样。如果所有线程都在DPDK lcore上运行,那么只需要对rte_pktmbuf_free()
进行一次调用。我以为我可以在没有运行在DPDK lcore上的线程中从mbufs中阅读数据,但显然,如果读取是在运行在DPDK lcore上的线程上执行的,即使读取操作也是线程安全的。