Search code examples
clinuxnetwork-programmingdpdk

Using DPDK ring with primary and secondary processes


I want to have 2 DPDK processes, primary and secondary.
The primary opens a ring using rte_ring_create() with the name myring.
Now, the secondary should be able to open the other side of that ring using rte_ring_lookup() as written here
26.1.2.2. How the Application Works

if (rte_eal_process_type() == RTE_PROC_PRIMARY){
    send_ring = rte_ring_create(_PRI_2_SEC, ring_size, rte_socket_id(), flags);
    recv_ring = rte_ring_create(_SEC_2_PRI, ring_size, rte_socket_id(), flags);
    message_pool = rte_mempool_create(_MSG_POOL, pool_size,
            STR_TOKEN_SIZE, pool_cache, priv_data_sz,
            NULL, NULL, NULL, NULL,
            rte_socket_id(), flags);
} else {
    recv_ring = rte_ring_lookup(_PRI_2_SEC);
    send_ring = rte_ring_lookup(_SEC_2_PRI);
    message_pool = rte_mempool_lookup(_MSG_POOL);
}

But, I want to be able to make the secondary process use the ring as if it was a regular interface device.
What I mean is, with DPDK params you're able to define physical ports and vdev ports using -a and --vdev=....

I want to give the ring myring as DPDK parameter as written here:

./dpdk-testpmd -l 1-3 -n 4 --vdev=net_ring0 --vdev=net_ring1 -- -i

Just, using --vdev=net_ringmyring.
I also tried calling the ring when creating it, in the primary process: net_ring_myring.

Nothing seem to work.
On the secondary process I get errors such as:

Device net_ring_myring is not driven by the primary process
rte_pmd_ring_probe(): Failed to probe net_ring_myring
vdev_probe(): failed to initialize net_ring_myring device
EAL: Bus (vdev) probe failed.

Solution

  • By the looks of it, the error being observed at the secondary process may come from rte_eth_dev_attach_secondary, which suggests that it might not be correct to create a ring device at the secondary process: that can only attach to an ethdev created at the primary one.

    Also, it is most likely wrong to assume that --vdev=net_ringmyring can be used to pass some actual ring name in place of that myring part: that is an indivisible name that has been assigned to the device which the secondary process is trying to attach to.

    As a quick suggestion, perhaps it pays to create the ring device at the primary process as follows

    struct rte_ring *r_0, *r_1;
    unsigned int flags = 0;
    unsigned int sz = 1024;
    int port_id;
    
    r_0 = rte_ring_create("r_0", sz, rte_socket_id(), flags);
    r_1 = rte_ring_create("r_1", sz, rte_socket_id(), flags);
    
    port_id = rte_eth_from_rings("net_ring0", &r_0, 1, &r_1, 1, rte_socket_id());
    
    /* (configure and start the port) */
    

    and, also at the primary process, implement all of the logic that directly interacts with the rings, at the OP's discretion, whilst, at the secondary process, attach to the device and leverage regular ethdev APIs (such as rte_eth_rx_burst or rte_eth_tx_burst) to interact with traffic:

    uint16_t port_id;
    
    (void)rte_eal_hotplug_add("vdev", "net_ring0", "");
    (void)rte_eth_dev_get_port_by_name("net_ring0", &port_id);
    
    /* (interact with packet receive and transmit APIs, etc) */
    

    For the secondary process, it might also be possible to use some existing tool (like test-pmd) and attach by means of passing the EAL argument (--vdev, as already described in the OP). That is worthwhile checking also.