7. Port Queue Group Library

7.1. Introduction

Port queue group is a fast path library that facilitates each core to iterate over list of [port, queue] groups for polling.

In a typical rte_graph application various source nodes (nodes registered with RTE_NODE_SOURCE_F) are created for calling rte_eth_rx_burst() on each [port, queue]. Assume there are 2 ethdev ports and each port has 8 queues assigned to each core in a system. Two source nodes (rte_node_t) would be needed on each core for polling [port-0, queue-Cx] and [port-1, queue-Cx], where Cx indicates core_id

Port queue library facilitates to create single source node (rte_node_t) on a core capable of polling multiple [port, queue] combinations. Thereby optimally utilizing ICACHE benefits by having small code foot print. It also allows run time addition/deletion of [port, queue] combination from a port queue group

7.2. Programming model

7.2.1. Initializing Port queue group library

Port queue group library must be first initialized using dao_portq_group_init(int num_port_queue_groups) before calling any of other APIs. num_port_queue_groups represents how many port queue groups are required by applications to be supported by library

7.2.2. Creating a Port queue group

dao_portq_group_create(char *name, int num_cores, int num_ports, dao_portq_group_t *) creates a port queue group object which supports to accommodate num_ports on num_cores. API returns port queue group handle dao_portq_group_t

7.2.3. Assigning [port, queue] to a core within Port queue group

dao_portq_group_portq_add (dao_portq_group_t, int core_id, dao_portq_t, int *index) assigns dao_portq_t (aka [port, queue]) to a core of port queue group. On successful addition, returned index can be used to get next dao_portq_t via dao_portq_group_portq_get_next())

Example of adding [port, queue] to a port queue group:

#include <dao_portq_group.h>

dao_portq_group_t portq_handle = DAO_PORTQ_GROUP_INITIALIZER;
dao_portq_t portq;
int num_workers = 8;
int num_ports = 2;
int32_t index;

dao_portq_group_create("sample_portq", num_workers, num_ports, &portq_handle);

for(i=0; i< num_workers; i++){
    for(j=0; j< num_ports, j++){
        portq.port_id = j;
        portq.rq_id = i;
        dao_portq_group_portq_add(portq_handle, i, &portq, &index);
    }
}

7.2.4. Number of [port, queue] in Port queue group

See dao_portq_group_portq_get_num()

7.2.5. Port queue group lookup by name

dao_portq_group_get_by_name (char *name, dao_portq_group_t *handle) returns port queue group handle of already created port queue group with name as name

7.2.6. Iterating over Port queue group on fast path core

Use fast path macro DAO_PORTQ_GROUP_FOREACH_CORE on each polling core as follows

#include <dao_portq_group.h>

source_node_process_func(...)
{
   dao_portq_group_t pg = DAO_PORTQ_GROUP_INITIALIZER;
   struct rte_mbuf *num_bufs[256];
   dao_portq_t portq;
   int32_t index;

   /* Lookup portq group that we created above */
   if(dao_portq_group_get_by_name("sample_portq", &pg)<0)
       return -1;

   /* Iterate over all [port, queue] assigned to this core */
   DAO_PORT_GROUP_FOREACH_PORT(pg, &portq, index) {
       rte_eth_rx_burst(portq.port_id, portq.rq_id, num_bufs, 256);

       /* process mbufs here */
   }
}

7.2.7. Deleting port from Port queue group

See dao_portq_group_portq_delete()

7.2.8. Destroying a Port queue group

See dao_portq_group_destroy()