Honnappa Nagarahalli Principal Software Engineer Arm A case for Queue APIs Honnappa Nagarahalli Principal Software Engineer Arm
Agenda Motivation Queue APIs/driver design APIs Problem we are trying to solve – Why do we need Queue APIs and driver framework? How do Queue APIs and driver framework solve the problem If time permits – discuss the RFC. RFC will be on the mailing list to review further. This discussion will touch upon thinking behind the APIs and few important features/fields.
Motivation DPDK supports Pipeline Model Uses rte_ring to exchange packets between cores rte_event_ring APIs - are backed with software implementation Even on a platform that supports HW queues, SW implementation is used Separation of the APIs and implementation is required DPDK supports pipeline model of packet processing. In this model, different parts of packet processing logic runs on dedicated cores. Each core, after processing the packets, hands over the packets to the next core/processing block in the pipeline. Many applications exist today that make use of this model. DPDK documentation clearly describes some of the advantages of this model. This model uses rte_ring to exchange packets between the cores. rte_ring is a software implementation of queue. DPDK also have rte_event_ring APIs as a means to exchange events between cores. However, these APIs are again tied to the software implementation (rte_ring) Essentially, rte_ring is the only way to do core-core communication currently in the pipeline model. Even when these applications are run on SoCs with queues implemented in hardware, they still continue to use rte_ring, instead of using hardware implementations. Hence the APIs and implementation need to be separated.
Queue APIs and Driver Framework Follow already established API and driver model Allows for separation of APIs and devices/drivers Allows for choosing the device depending on the platform Device is represented as a ‘Queue Manager’ for allocation/freeing of queues After queue allocation – Enqueue and Dequeue operations can happen on the queue Separate the APIs and queue implementation using the well established API and driver model used by other devices like crypto. This will allow implementation of multiple queue drivers which can be enabled depending on the underlying platform. The device itself is represented as a ‘Queue Manager’ which can allocate and free the queues. Once the queues are allocated, the queue handle can be used to enqueue and dequeue objects.
APIs Should support application portability DPDK application should be portable across different platforms Should address the needs of both software and hardware implementations struct rte_queue *rte_queue_create(struct rte_queue_ctx *instance, const char *name, unsigned int count, int socket_id, unsigned int flags); void rte_queue_free(struct rte_queue_ctx *instance, struct rte_queue *q) struct rte_queue { union { void *private_data; /**< Queue implementation pvt data */ uintptr_t queue_handle; /**< Queue handle */ } }; Key to making the applications portable. RTE_QUEUE_SP_ENQ /**< single-producer */ RTE_QUEUE_SC_DEQ /**< single-consumer */ RTE_QUEUE_NON_BLOCKING /**< non-blocking */ struct rte_queue_ctx { void *device; /**< Queue device attached */ const struct rte_queue_ops *ops; /**< Queue ops for the device */ }; Application portability is important. Customers would like to have a single application that can run across different platforms. Platforms may use software algorithms or hardware implementations. To guarantee seamless portability, where possible, it is important to make sure different implementations behave the same. If not, the characteristics of the implementations should be brought out clearly in the APIs. This will help the application writer aware of differing characteristics and help choose the right characteristics required. The APIs for Queue address the needs of both software and hardware implementations. Currently, I have added just the basic APIs.
APIs unsigned int rte_queue_enqueue_burst(struct rte_queue_ctx *instance, struct rte_queue *q, void * const *obj_table, unsigned int n) unsigned int rte_queue_dequeue_burst(struct rte_queue_ctx *instance, struct rte_queue *q, void * const *obj_table, unsigned int n) unsigned int rte_queue_get_size(struct rte_queue_ctx *instance, const struct rte_queue *q); unsigned int rte_queue_get_capacity(struct rte_queue_ctx *instance, const struct rte_queue *q); Removed ‘free_space’ Removed ‘available’
Q & A