c++linuxmultithreadingdpdk

DPDK rte_mbuf packets not freed properly


TL;DR

I am using DPDK to receive UDP packets at a high throughput. When I try to free rte_mbufs (UDP packets) using rte_pktmbuf_free_bulk() on a thread not running on a DPDK lcore, the rte_mbufs are not actually freed, which leads to the inability to receive more than 4096 packets. Do I need to move all my logic onto threads running on lcores, or is there something else I can do to make this work?

Note about the DPDK setup

I am new to DPDK and inherited the initialization part of the code, which is entirely too long to include here. I am not sure which specific details about the configuration might be important or relevant, but will be happy to supplement this post if anyone has specific questions about the DPDK setup. However, I have included the main RX loop code and a description of it, below.

Notes about the code:

The code

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);
        }
    }
}

Troubleshooting notes


Solution

  • The solution was to execute ALL code that makes use of mbufs on DPDK lcore threads. There is no need to free the packets with rte_pktmbuf_free() on all threads that use the packets, as I had previously suggested in my comments. If all threads are running on DPDK lcores, then only a single call to rte_pktmbuf_free() is required.

    I thought I could get away with reading data from the mbufs in threads not running on DPDK lcores, but apparently even read operations are only thread safe if the reads are performed on threads running on DPDK lcores.