[dpdk-dev] [RFC] [PATCH v2] libeventdev: event driven programming model framework for DPDK
Eads, Gage
gage.eads at intel.com
Fri Oct 14 17:00:57 CEST 2016
Thanks Jerin, this looks good. I've put a few notes/questions inline.
Thanks,
Gage
> -----Original Message-----
> From: Jerin Jacob [mailto:jerin.jacob at caviumnetworks.com]
> Sent: Tuesday, October 11, 2016 2:30 PM
> To: dev at dpdk.org
> Cc: thomas.monjalon at 6wind.com; Richardson, Bruce
> <bruce.richardson at intel.com>; Vangati, Narender
> <narender.vangati at intel.com>; hemant.agrawal at nxp.com; Eads, Gage
> <gage.eads at intel.com>; Jerin Jacob <jerin.jacob at caviumnetworks.com>
> Subject: [dpdk-dev] [RFC] [PATCH v2] libeventdev: event driven programming
> model framework for DPDK
>
> Thanks to Intel and NXP folks for the positive and constructive feedback
> I've received so far. Here is the updated RFC(v2).
>
> I've attempted to address as many comments as possible.
>
> This series adds rte_eventdev.h to the DPDK tree with
> adequate documentation in doxygen format.
>
> Updates are also available online:
>
> Related draft header file (this patch):
> https://rawgit.com/jerinjacobk/libeventdev/master/rte_eventdev.h
>
> PDF version(doxgen output):
> https://rawgit.com/jerinjacobk/libeventdev/master/librte_eventdev_v2.pdf
>
> Repo:
> https://github.com/jerinjacobk/libeventdev
>
> v1..v2
>
> - Added Cavium, Intel, NXP copyrights in header file
>
> - Changed the concept of flow queues to flow ids.
> This is avoid dictating a specific structure to hold the flows.
> A s/w implementation can do atomic load balancing on multiple
> flow ids more efficiently than maintaining each event in a specific flow queue.
>
> - Change the scheduling group to event queue.
> A scheduling group is more a stream of events, so an event queue is a better
> abstraction.
>
> - Introduced event port concept, Instead of trying eventdev access to the lcore,
> a higher level of abstraction called event port is needed which is the
> application i/f to the eventdev to dequeue and enqueue the events.
> One or more event queues can be linked to single event port.
> There can be more than one event port per lcore allowing multiple lightweight
> threads to have their own i/f into eventdev, if the implementation supports it.
> An event port will be bound to a lcore or a lightweight thread to keep
> portable application workflow.
> An event port abstraction also encapsulates dequeue depth and enqueue depth
> for
> a scheduler implementations which can schedule multiple events at a time and
> output events that can be buffered.
>
> - Added configuration options with event queue(nb_atomic_flows,
> nb_atomic_order_sequences, single consumer etc)
> and event port(dequeue_queue_depth, enqueue_queue_depth etc) to define
> the
> limits on the resource usage.(Useful for optimized software implementation)
>
> - Introduced RTE_EVENT_DEV_CAP_QUEUE_QOS and
> RTE_EVENT_DEV_CAP_EVENT_QOS
> schemes of priority handling
>
> - Added event port to event queue servicing priority.
> This allows two event ports to connect to the same event queue with
> different priorities.
>
> - Changed the workflow as schedule/dequeue/enqueue.
> An implementation is free to define schedule as NOOP.
> A distributed s/w scheduler can use this to schedule events;
> also a centralized s/w scheduler can make this a NOOP on non-scheduler cores.
>
> - Removed Cavium HW specific schedule_from_group API
>
> - Removed Cavium HW specific ctxt_update/ctxt_wait APIs.
> Introduced a more generic "event pinning" concept. i.e
> If the normal workflow is a dequeue -> do work based on event type ->
> enqueue,
> a pin_event argument to enqueue
> where the pinned event is returned through the normal dequeue)
> allows application workflow to remain the same whether or not an
> implementation supports it.
>
> - Added dequeue() burst variant
>
> - Added the definition of a closed/open system - where open system is memory
> backed and closed system eventdev has limited capacity.
> In such systems, it is also useful to denote per event port how many packets
> can be active in the system.
> This can serve as a threshold for ethdev like devices so they don't overwhelm
> core to core events.
>
> - Added the option to specify maximum amount of time(in ns) application needs
> wait on dequeue()
>
> - Removed the scheme of expressing the number of flows in log2 format
>
> Open item or the item needs improvement.
> ----------------------------------------
> - Abstract the differences in event QoS management with different priority
> schemes
> available in different HW or SW implementations with portable application
> workflow.
>
> Based on the feedback, there three different kinds of QoS support available in
> three different HW or SW implementations.
> 1) Priority associated with the event queue
> 2) Priority associated with each event enqueue
> (Same flow can have two different priority on two separate enqueue)
> 3) Priority associated with the flow(each flow has unique priority)
>
> In v2, The differences abstracted based on device capability
> (RTE_EVENT_DEV_CAP_QUEUE_QOS for the first scheme,
> RTE_EVENT_DEV_CAP_EVENT_QOS for the second and third scheme).
> This scheme would call for different application workflow for
> nontrivial QoS-enabled applications.
>
> Looking forward to getting comments from both application and driver
> implementation perspective.
>
> /Jerin
>
> ---
> doc/api/doxy-api-index.md | 1 +
> doc/api/doxy-api.conf | 1 +
> lib/librte_eventdev/rte_eventdev.h | 1204
> ++++++++++++++++++++++++++++++++++++
> 3 files changed, 1206 insertions(+)
> create mode 100644 lib/librte_eventdev/rte_eventdev.h
>
> diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
> index 6675f96..28c1329 100644
> --- a/doc/api/doxy-api-index.md
> +++ b/doc/api/doxy-api-index.md
> @@ -40,6 +40,7 @@ There are many libraries, so their headers may be
> grouped by topics:
> [ethdev] (@ref rte_ethdev.h),
> [ethctrl] (@ref rte_eth_ctrl.h),
> [cryptodev] (@ref rte_cryptodev.h),
> + [eventdev] (@ref rte_eventdev.h),
> [devargs] (@ref rte_devargs.h),
> [bond] (@ref rte_eth_bond.h),
> [vhost] (@ref rte_virtio_net.h),
> diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
> index 9dc7ae5..9841477 100644
> --- a/doc/api/doxy-api.conf
> +++ b/doc/api/doxy-api.conf
> @@ -41,6 +41,7 @@ INPUT = doc/api/doxy-api-index.md \
> lib/librte_cryptodev \
> lib/librte_distributor \
> lib/librte_ether \
> + lib/librte_eventdev \
> lib/librte_hash \
> lib/librte_ip_frag \
> lib/librte_jobstats \
> diff --git a/lib/librte_eventdev/rte_eventdev.h
> b/lib/librte_eventdev/rte_eventdev.h
> new file mode 100644
> index 0000000..f60e461
> --- /dev/null
> +++ b/lib/librte_eventdev/rte_eventdev.h
> @@ -0,0 +1,1204 @@
> +/*
> + * BSD LICENSE
> + *
> + * Copyright 2016 Cavium.
> + * Copyright 2016 Intel Corporation.
> + * Copyright 2016 NXP.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + *
> + * * Redistributions of source code must retain the above copyright
> + * notice, this list of conditions and the following disclaimer.
> + * * Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in
> + * the documentation and/or other materials provided with the
> + * distribution.
> + * * Neither the name of Cavium nor the names of its
> + * contributors may be used to endorse or promote products derived
> + * from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> CONTRIBUTORS
> + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
> NOT
> + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
> FITNESS FOR
> + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
> COPYRIGHT
> + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
> INCIDENTAL,
> + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> NOT
> + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
> OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
> AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
> TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
> THE USE
> + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
> DAMAGE.
> + */
> +
> +#ifndef _RTE_EVENTDEV_H_
> +#define _RTE_EVENTDEV_H_
> +
> +/**
> + * @file
> + *
> + * RTE Event Device API
> + *
> + * The Event Device API is composed of two parts:
> + *
> + * - The application-oriented Event API that includes functions to setup
> + * an event device (configure it, setup its queues, ports and start it), to
> + * establish the link between queues to port and to receive events, and so on.
> + *
> + * - The driver-oriented Event API that exports a function allowing
> + * an event poll Mode Driver (PMD) to simultaneously register itself as
> + * an event device driver.
> + *
> + * Event device components:
> + *
> + * +-----------------+
> + * | +-------------+ |
> + * +-------+ | | flow 0 | |
> + * |Packet | | +-------------+ |
> + * |event | | +-------------+ |
> + * | | | | flow 1 | |event_port_link(port0, queue0)
> + * +-------+ | +-------------+ | | +--------+
> + * +-------+ | +-------------+ o-----v-----o |dequeue +------+
> + * |Crypto | | | flow n | | | event +------->|Core 0|
> + * |work | | +-------------+ o----+ | port 0 | | |
> + * |done ev| | event queue 0 | | +--------+ +------+
> + * +-------+ +-----------------+ |
> + * +-------+ |
> + * |Timer | +-----------------+ | +--------+
> + * |expiry | | +-------------+ | +------o |dequeue +------+
> + * |event | | | flow 0 | o-----------o event +------->|Core 1|
> + * +-------+ | +-------------+ | +----o port 1 | | |
> + * Event enqueue | +-------------+ | | +--------+ +------+
> + * o-------------> | | flow 1 | | |
> + * enqueue( | +-------------+ | |
> + * queue_id, | | | +--------+ +------+
> + * flow_id, | +-------------+ | | | |dequeue |Core 2|
> + * sched_type, | | flow n | o-----------o event +------->| |
> + * event_type, | +-------------+ | | | port 2 | +------+
> + * subev_type, | event queue 1 | | +--------+
> + * event) +-----------------+ | +--------+
> + * | | |dequeue +------+
> + * +-------+ +-----------------+ | | event +------->|Core n|
> + * |Core | | +-------------+ o-----------o port n | | |
> + * |(SW) | | | flow 0 | | | +--------+ +--+---+
> + * |event | | +-------------+ | | |
> + * +-------+ | +-------------+ | | |
> + * ^ | | flow 1 | | | |
> + * | | +-------------+ o------+ |
> + * | | +-------------+ | |
> + * | | | flow n | | |
> + * | | +-------------+ | |
> + * | | event queue n | |
> + * | +-----------------+ |
> + * | |
> + * +-----------------------------------------------------------+
> + *
> + *
> + *
> + * Event device: A hardware or software-based event scheduler.
> + *
> + * Event: A unit of scheduling that encapsulates a packet or other datatype
> + * like SW generated event from the core, Crypto work completion
> notification,
> + * Timer expiry event notification etc as well as metadata.
> + * The metadata includes flow ID, scheduling type, event priority, event_type,
> + * sub_event_type etc.
> + *
> + * Event queue: A queue containing events that are scheduled by the event
> dev.
> + * An event queue contains events of different flows associated with
> scheduling
> + * types, such as atomic, ordered, or parallel.
> + *
> + * Event port: An application's interface into the event dev for enqueue and
> + * dequeue operations. Each event port can be linked with one or more
> + * event queues for dequeue operations.
> + *
> + * By default, all the functions of the Event Device API exported by a PMD
> + * are lock-free functions which assume to not be invoked in parallel on
> + * different logical cores to work on the same target object. For instance,
> + * the dequeue function of a PMD cannot be invoked in parallel on two logical
> + * cores to operates on same event port. Of course, this function
> + * can be invoked in parallel by different logical cores on different ports.
> + * It is the responsibility of the upper level application to enforce this rule.
> + *
> + * In all functions of the Event API, the Event device is
> + * designated by an integer >= 0 named the device identifier *dev_id*
> + *
> + * At the Event driver level, Event devices are represented by a generic
> + * data structure of type *rte_event_dev*.
> + *
> + * Event devices are dynamically registered during the PCI/SoC device probing
> + * phase performed at EAL initialization time.
> + * When an Event device is being probed, a *rte_event_dev* structure and
> + * a new device identifier are allocated for that device. Then, the
> + * event_dev_init() function supplied by the Event driver matching the probed
> + * device is invoked to properly initialize the device.
> + *
> + * The role of the device init function consists of resetting the hardware or
> + * software event driver implementations.
> + *
> + * If the device init operation is successful, the correspondence between
> + * the device identifier assigned to the new device and its associated
> + * *rte_event_dev* structure is effectively registered.
> + * Otherwise, both the *rte_event_dev* structure and the device identifier are
> + * freed.
> + *
> + * The functions exported by the application Event API to setup a device
> + * designated by its device identifier must be invoked in the following order:
> + * - rte_event_dev_configure()
> + * - rte_event_queue_setup()
> + * - rte_event_port_setup()
> + * - rte_event_port_link()
> + * - rte_event_dev_start()
> + *
> + * Then, the application can invoke, in any order, the functions
> + * exported by the Event API to schedule events, dequeue events, enqueue
> events,
> + * change event queue(s) to event port [un]link establishment and so on.
> + *
> + * Application may use rte_event_[queue/port]_default_conf_get() to get the
> + * default configuration to set up an event queue or event port by
> + * overriding few default values.
> + *
> + * If the application wants to change the configuration (i.e. call
> + * rte_event_dev_configure(), rte_event_queue_setup(), or
> + * rte_event_port_setup()), it must call rte_event_dev_stop() first to stop the
> + * device and then do the reconfiguration before calling rte_event_dev_start()
> + * again. The schedule, enqueue and dequeue functions should not be invoked
> + * when the device is stopped.
> + *
> + * Finally, an application can close an Event device by invoking the
> + * rte_event_dev_close() function.
> + *
> + * Each function of the application Event API invokes a specific function
> + * of the PMD that controls the target device designated by its device
> + * identifier.
> + *
> + * For this purpose, all device-specific functions of an Event driver are
> + * supplied through a set of pointers contained in a generic structure of type
> + * *event_dev_ops*.
> + * The address of the *event_dev_ops* structure is stored in the
> *rte_event_dev*
> + * structure by the device init function of the Event driver, which is
> + * invoked during the PCI/SoC device probing phase, as explained earlier.
> + *
> + * In other words, each function of the Event API simply retrieves the
> + * *rte_event_dev* structure associated with the device identifier and
> + * performs an indirect invocation of the corresponding driver function
> + * supplied in the *event_dev_ops* structure of the *rte_event_dev*
> structure.
> + *
> + * For performance reasons, the address of the fast-path functions of the
> + * Event driver is not contained in the *event_dev_ops* structure.
> + * Instead, they are directly stored at the beginning of the *rte_event_dev*
> + * structure to avoid an extra indirect memory access during their invocation.
> + *
> + * RTE event device drivers do not use interrupts for enqueue or dequeue
> + * operation. Instead, Event drivers export Poll-Mode enqueue and dequeue
> + * functions to applications.
> + *
> + * An event driven based application has following typical workflow on
> fastpath:
> + * \code{.c}
> + * while (1) {
> + *
> + * rte_event_schedule(dev_id);
> + *
> + * rte_event_dequeue(...);
> + *
> + * (event processing)
> + *
> + * rte_event_enqueue(...);
> + * }
> + * \endcode
> + *
> + * The *schedule* operation is intended to do event scheduling, and the
> + * *dequeue* operation returns the scheduled events. An implementation
> + * is free to define the semantics between *schedule* and *dequeue*. For
> + * example, a system based on a hardware scheduler can define its
> + * rte_event_schedule() to be an NOOP, whereas a software scheduler can use
> + * the *schedule* operation to schedule events.
> + *
> + * The events are injected to event device through *enqueue* operation by
> + * event producers in the system. The typical event producers are ethdev
> + * subsystem for generating packet events, core(SW) for generating events
> based
> + * on different stages of application processing, cryptodev for generating
> + * crypto work completion notification etc
> + *
> + * The *dequeue* operation gets one or more events from the event ports.
> + * The application process the events and send to downstream event queue
> through
> + * rte_event_enqueue() if it is an intermediate stage of event processing, on
> + * the final stage, the application may send to different subsystem like ethdev
> + * to send the packet/event on the wire using ethdev rte_eth_tx_burst() API.
> + *
> + */
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +#include <rte_pci.h>
> +#include <rte_dev.h>
> +#include <rte_devargs.h>
> +#include <rte_errno.h>
> +
> +/**
> + * Get the total number of event devices that have been successfully
> + * initialised.
> + *
> + * @return
> + * The total number of usable event devices.
> + */
> +extern uint8_t
> +rte_event_dev_count(void);
> +
> +/**
> + * Get the device identifier for the named event device.
> + *
> + * @param name
> + * Event device name to select the event device identifier.
> + *
> + * @return
> + * Returns event device identifier on success.
> + * - <0: Failure to find named event device.
> + */
> +extern uint8_t
> +rte_event_dev_get_dev_id(const char *name);
This return type should be int8_t, or some signed type, to support the failure case.
> +
> +/**
> + * Return the NUMA socket to which a device is connected.
> + *
> + * @param dev_id
> + * The identifier of the device.
> + * @return
> + * The NUMA socket id to which the device is connected or
> + * a default of zero if the socket could not be determined.
> + * - -1: dev_id value is out of range.
> + */
> +extern int
> +rte_event_dev_socket_id(uint8_t dev_id);
> +
> +/* Event device capability bitmap flags */
> +#define RTE_EVENT_DEV_CAP_QUEUE_QOS (1 << 0)
> +/**< Event scheduling prioritization is based on the priority associated with
> + * each event queue.
> + *
> + * \see rte_event_queue_setup(), RTE_EVENT_QUEUE_PRIORITY_NORMAL
> + */
> +#define RTE_EVENT_DEV_CAP_EVENT_QOS (1 << 1)
> +/**< Event scheduling prioritization is based on the priority associated with
> + * each event. Priority of each event is supplied in *rte_event* structure
> + * on each enqueue operation.
> + *
> + * \see rte_event_enqueue()
> + */
> +
> +/**
> + * Event device information
> + */
> +struct rte_event_dev_info {
> + const char *driver_name; /**< Event driver name */
> + struct rte_pci_device *pci_dev; /**< PCI information */
> + uint32_t min_dequeue_wait_ns;
> + /**< Minimum supported global dequeue wait delay(ns) by this device
> */
> + uint32_t max_dequeue_wait_ns;
> + /**< Maximum supported global dequeue wait delay(ns) by this device
> */
> + uint32_t dequeue_wait_ns;
> + /**< Configured global dequeue wait delay(ns) for this device */
> + uint8_t max_event_queues;
> + /**< Maximum event_queues supported by this device */
> + uint32_t max_event_queue_flows;
> + /**< Maximum supported flows in an event queue by this device*/
> + uint8_t max_event_queue_priority_levels;
> + /**< Maximum number of event queue priority levels by this device.
> + * Valid when the device has RTE_EVENT_DEV_CAP_QUEUE_QOS
> capability
> + */
> + uint8_t nb_event_queues;
> + /**< Configured number of event queues for this device */
> + uint8_t max_event_priority_levels;
> + /**< Maximum number of event priority levels by this device.
> + * Valid when the device has RTE_EVENT_DEV_CAP_EVENT_QOS
> capability
> + */
> + uint8_t max_event_ports;
> + /**< Maximum number of event ports supported by this device */
> + uint8_t nb_event_ports;
> + /**< Configured number of event ports for this device */
> + uint8_t max_event_port_dequeue_queue_depth;
> + /**< Maximum dequeue queue depth for any event port.
> + * Implementations can schedule N events at a time to an event port.
> + * A device that does not support bulk dequeue will set this as 1.
> + * \see rte_event_port_setup()
> + */
> + uint32_t max_event_port_enqueue_queue_depth;
> + /**< Maximum enqueue queue depth for any event port.
> Implementations
> + * can batch N events at a time to enqueue through event port
> + * \see rte_event_port_setup()
> + */
> + int32_t max_num_events;
> + /**< A *closed system* event dev has a limit on the number of events
> it
> + * can manage at a time. An *open system* event dev does not have a
> + * limit and will specify this as -1.
> + */
> + uint32_t event_dev_cap;
> + /**< Event device capabilities(RTE_EVENT_DEV_CAP_)*/
> +};
> +
> +/**
> + * Retrieve the contextual information of an event device.
> + *
> + * @param dev_id
> + * The identifier of the device.
> + *
> + * @param[out] dev_info
> + * A pointer to a structure of type *rte_event_dev_info* to be filled with the
> + * contextual information of the device.
> + *
> + */
> +extern void
> +rte_event_dev_info_get(uint8_t dev_id, struct rte_event_dev_info
> *dev_info);
I'm wondering if this return type should be int, so we can return an error if the dev_id is invalid.
> +
> +/* Event device configuration bitmap flags */
> +#define RTE_EVENT_DEV_CFG_PER_DEQUEUE_WAIT (1 << 0)
> +/**< Override the global *dequeue_wait_ns* and use per dequeue wait in ns.
> + * \see rte_event_dequeue_wait_time(), rte_event_dequeue()
> + */
> +
> +/** Event device configuration structure */
> +struct rte_event_dev_config {
> + uint32_t dequeue_wait_ns;
> + /**< rte_event_dequeue() wait for *dequeue_wait_ns* ns on this
> device.
> + * This value should be in the range of *min_dequeue_wait_ns* and
> + * *max_dequeue_wait_ns* which previously provided in
> + * rte_event_dev_info_get()
> + * \see RTE_EVENT_DEV_CFG_PER_DEQUEUE_WAIT
> + */
> + int32_t nb_events_limit;
> + /**< Applies to *closed system* event dev only. This field indicates a
> + * limit to ethdev-like devices to limit the number of events injected
> + * into the system to not overwhelm core-to-core events.
> + * This value cannot exceed the *max_num_events* which previously
> + * provided in rte_event_dev_info_get()
> + */
> + uint8_t nb_event_queues;
> + /**< Number of event queues to configure on this device.
> + * This value cannot exceed the *max_event_queues* which previously
> + * provided in rte_event_dev_info_get()
> + */
> + uint8_t nb_event_ports;
> + /**< Number of event ports to configure on this device.
> + * This value cannot exceed the *max_event_ports* which previously
> + * provided in rte_event_dev_info_get()
> + */
> + uint32_t event_dev_cfg;
> + /**< Event device config flags(RTE_EVENT_DEV_CFG_)*/
> +};
> +
> +/**
> + * Configure an event device.
> + *
> + * This function must be invoked first before any other function in the
> + * API. This function can also be re-invoked when a device is in the
> + * stopped state.
> + *
> + * The caller may use rte_event_dev_info_get() to get the capability of each
> + * resources available for this event device.
> + *
> + * @param dev_id
> + * The identifier of the device to configure.
> + * @param config
> + * The event device configuration structure.
> + *
> + * @return
> + * - 0: Success, device configured.
> + * - <0: Error code returned by the driver configuration function.
> + */
> +extern int
> +rte_event_dev_configure(uint8_t dev_id, struct rte_event_dev_config
> *config);
> +
> +
> +/* Event queue specific APIs */
> +
> +#define RTE_EVENT_QUEUE_PRIORITY_HIGHEST 0
> +/**< Highest event queue priority */
> +#define RTE_EVENT_QUEUE_PRIORITY_NORMAL 128
> +/**< Normal event queue priority */
> +#define RTE_EVENT_QUEUE_PRIORITY_LOWEST 255
> +/**< Lowest event queue priority */
> +
> +/* Event queue configuration bitmap flags */
> +#define RTE_EVENT_QUEUE_CFG_SINGLE_CONSUMER (1 << 0)
> +/**< This event queue links only to a single event port.
> + *
> + * \see rte_event_port_setup(), rte_event_port_link()
> + */
> +
> +/** Event queue configuration structure */
> +struct rte_event_queue_conf {
> + uint32_t nb_atomic_flows;
> + /**< The maximum number of active flows this queue can track at any
> + * given time. The value must be in the range of
> + * [1 - max_event_queue_flows)] which previously supplied
> + * to rte_event_dev_configure().
> + */
> + uint32_t nb_atomic_order_sequences;
> + /**< The maximum number of outstanding events waiting to be
> (egress-)
> + * reordered by this queue. In other words, the number of entries in
> + * this queue’s reorder buffer.The value must be in the range of
> + * [1 - max_event_queue_flows)] which previously supplied
> + * to rte_event_dev_configure().
> + */
> + uint32_t event_queue_cfg; /**< Queue config
> flags(EVENT_QUEUE_CFG_) */
> + uint8_t priority;
> + /**< Priority for this event queue relative to other event queues.
> + * The requested priority should in the range of
> + * [RTE_EVENT_QUEUE_PRIORITY_HIGHEST,
> RTE_EVENT_QUEUE_PRIORITY_LOWEST].
> + * The implementation shall normalize the requested priority to
> + * event device supported priority value.
> + * Valid when the device has RTE_EVENT_DEV_CAP_QUEUE_QOS
> capability
> + */
> +};
> +
> +/**
> + * Retrieve the default configuration information of an event queue
> designated
> + * by its *queue_id* from the event driver for an event device.
> + *
> + * This function intended to be used in conjunction with
> rte_event_queue_setup()
> + * where caller needs to set up the queue by overriding few default values.
> + *
> + * @param dev_id
> + * The identifier of the device.
> + * @param queue_id
> + * The index of the event queue to get the configuration information.
> + * The value must be in the range [0, nb_event_queues - 1]
> + * previously supplied to rte_event_dev_configure().
> + * @param[out] queue_conf
> + * The pointer to the default event queue configuration data.
> + *
> + * \see rte_event_queue_setup()
> + *
> + */
> +extern void
> +rte_event_queue_default_conf_get(uint8_t dev_id, uint8_t queue_id,
> + struct rte_event_queue_conf *queue_conf);
> +
> +/**
> + * Allocate and set up an event queue for an event device.
> + *
> + * @param dev_id
> + * The identifier of the device.
> + * @param queue_id
> + * The index of the event queue to setup. The value must be in the range
> + * [0, nb_event_queues - 1] previously supplied to
> rte_event_dev_configure().
> + * @param queue_conf
> + * The pointer to the configuration data to be used for the event queue.
> + * NULL value is allowed, in which case default configuration used.
> + *
> + * \see rte_event_queue_default_conf_get()
> + *
> + * @return
> + * - 0: Success, event queue correctly set up.
> + * - <0: event queue configuration failed
> + */
> +extern int
> +rte_event_queue_setup(uint8_t dev_id, uint8_t queue_id,
> + struct rte_event_queue_conf *queue_conf);
> +
> +/**
> + * Get the number of event queues on a specific event device
> + *
> + * @param dev_id
> + * Event device identifier.
> + * @return
> + * - The number of configured event queues
> + */
> +extern uint16_t
> +rte_event_queue_count(uint8_t dev_id);
> +
> +/**
> + * Get the priority of the event queue on a specific event device
> + *
> + * @param dev_id
> + * Event device identifier.
> + * @param queue_id
> + * Event queue identifier.
> + * @return
> + * - If the device has RTE_EVENT_DEV_CAP_QUEUE_QOS capability then the
> + * configured priority of the event queue in
> + * [RTE_EVENT_QUEUE_PRIORITY_HIGHEST,
> RTE_EVENT_QUEUE_PRIORITY_LOWEST] range
> + * else the value one
> + */
> +extern uint8_t
> +rte_event_queue_priority(uint8_t dev_id, uint8_t queue_id);
> +
> +/* Event port specific APIs */
> +
> +/** Event port configuration structure */
> +struct rte_event_port_conf {
> + int32_t new_event_threshold;
> + /**< A backpressure threshold for new event enqueues on this port.
> + * Use for *closed system* event dev where event capacity is limited,
> + * and cannot exceed the capacity of the event dev.
> + * Configuring ports with different thresholds can make higher priority
> + * traffic less likely to be backpressured.
> + * For example, a port used to inject NIC Rx packets into the event dev
> + * can have a lower threshold so as not to overwhelm the device,
> + * while ports used for worker pools can have a higher threshold.
> + */
> + uint8_t dequeue_queue_depth;
> + /**< Configure number of bulk dequeues for this event port.
> + * This value cannot exceed the
> *max_event_port_dequeue_queue_depth*
> + * which previously supplied to rte_event_dev_configure()
> + */
> + uint8_t enqueue_queue_depth;
> + /**< Configure number of bulk enqueues for this event port.
> + * This value cannot exceed the
> *max_event_port_enqueue_queue_depth*
> + * which previously supplied to rte_event_dev_configure()
> + */
> +};
> +
> +/**
> + * Retrieve the default configuration information of an event port designated
> + * by its *port_id* from the event driver for an event device.
> + *
> + * This function intended to be used in conjunction with
> rte_event_port_setup()
> + * where caller needs to set up the port by overriding few default values.
> + *
> + * @param dev_id
> + * The identifier of the device.
> + * @param port_id
> + * The index of the event port to get the configuration information.
> + * The value must be in the range [0, nb_event_ports - 1]
> + * previously supplied to rte_event_dev_configure().
> + * @param[out] port_conf
> + * The pointer to the default event port configuration data
> + *
> + * \see rte_event_port_setup()
> + *
> + */
> +extern void
> +rte_event_port_default_conf_get(uint8_t dev_id, uint8_t port_id,
> + struct rte_event_port_conf *port_conf);
> +
> +/**
> + * Allocate and set up an event port for an event device.
> + *
> + * @param dev_id
> + * The identifier of the device.
> + * @param port_id
> + * The index of the event port to setup. The value must be in the range
> + * [0, nb_event_ports - 1] previously supplied to rte_event_dev_configure().
> + * @param port_conf
> + * The pointer to the configuration data to be used for the queue.
> + * NULL value is allowed, in which case default configuration used.
> + *
> + * \see rte_event_port_default_conf_get()
> + *
> + * @return
> + * - 0: Success, event port correctly set up.
> + * - <0: Port configuration failed
> + * - (-EDQUOT) Quota exceeded(Application tried to link the queue
> configured
> + * with RTE_EVENT_QUEUE_CFG_SINGLE_CONSUMER to more than one
> event ports)
> + */
> +extern int
> +rte_event_port_setup(uint8_t dev_id, uint8_t port_id,
> + struct rte_event_port_conf *port_conf);
> +
> +/**
> + * Get the number of dequeue queue depth configured for event port
> designated
> + * by its *port_id* on a specific event device
> + *
> + * @param dev_id
> + * Event device identifier.
> + * @param port_id
> + * Event port identifier.
> + * @return
> + * - The number of configured dequeue queue depth
> + *
> + * \see rte_event_dequeue_burst()
> + */
> +extern uint8_t
> +rte_event_port_dequeue_depth(uint8_t dev_id, uint8_t port_id);
> +
> +/**
> + * Get the number of enqueue queue depth configured for event port
> designated
> + * by its *port_id* on a specific event device
> + *
> + * @param dev_id
> + * Event device identifier.
> + * @param port_id
> + * Event port identifier.
> + * @return
> + * - The number of configured enqueue queue depth
> + *
> + * \see rte_event_enqueue_burst()
> + */
> +extern uint8_t
> +rte_event_port_enqueue_depth(uint8_t dev_id, uint8_t port_id);
> +
> +/**
> + * Get the number of ports on a specific event device
> + *
> + * @param dev_id
> + * Event device identifier.
> + * @return
> + * - The number of configured ports
> + */
> +extern uint8_t
> +rte_event_port_count(uint8_t dev_id);
> +
> +/**
> + * Start an event device.
> + *
> + * The device start step is the last one and consists of setting the event
> + * queues to start accepting the events and schedules to event ports.
> + *
> + * On success, all basic functions exported by the API (event enqueue,
> + * event dequeue and so on) can be invoked.
> + *
> + * @param dev_id
> + * Event device identifier
> + * @return
> + * - 0: Success, device started.
> + * - <0: Error code of the driver device start function.
> + */
> +extern int
> +rte_event_dev_start(uint8_t dev_id);
> +
> +/**
> + * Stop an event device. The device can be restarted with a call to
> + * rte_event_dev_start()
> + *
> + * @param dev_id
> + * Event device identifier.
> + */
> +extern void
> +rte_event_dev_stop(uint8_t dev_id);
> +
> +/**
> + * Close an event device. The device cannot be restarted!
> + *
> + * @param dev_id
> + * Event device identifier
> + *
> + * @return
> + * - 0 on successfully closing device
> + * - <0 on failure to close device
> + */
> +extern int
> +rte_event_dev_close(uint8_t dev_id);
> +
> +/* Scheduler type definitions */
> +#define RTE_SCHED_TYPE_ORDERED 0
> +/**< Ordered scheduling
> + *
> + * Events from an ordered flow of an event queue can be scheduled to
> multiple
> + * ports for concurrent processing while maintaining the original event order.
> + * This scheme enables the user to achieve high single flow throughput by
> + * avoiding SW synchronization for ordering between ports which bound to
> cores.
> + *
> + * The source flow ordering from an event queue is maintained when events
> are
> + * enqueued to their destination queue within the same ordered flow context.
> + * An event port holds the context until application call rte_event_dequeue()
> + * from the same port, which implicitly releases the context.
> + * User may allow the scheduler to release the context earlier than that
> + * by calling rte_event_release()
> + *
> + * Events from the source queue appear in their original order when dequeued
> + * from a destination queue.
> + * Event ordering is based on the received event(s), but also other
> + * (newly allocated or stored) events are ordered when enqueued within the
> same
> + * ordered context. Events not enqueued (e.g. released or stored) within the
> + * context are considered missing from reordering and are skipped at this
> time
> + * (but can be ordered again within another context).
> + *
> + * \see rte_event_dequeue(), rte_event_release()
> + */
> +
> +#define RTE_SCHED_TYPE_ATOMIC 1
> +/**< Atomic scheduling
> + *
> + * Events from an atomic flow of an event queue can be scheduled only to a
> + * single port at a time. The port is guaranteed to have exclusive (atomic)
> + * access to the associated flow context, which enables the user to avoid SW
> + * synchronization. Atomic flows also help to maintain event ordering
> + * since only one port at a time can process events from a flow of an
> + * event queue.
> + *
> + * The atomic queue synchronization context is dedicated to the port until
> + * application call rte_event_dequeue() from the same port, which implicitly
> + * releases the context. User may allow the scheduler to release the context
> + * earlier than that by calling rte_event_release()
> + *
> + * \see rte_event_dequeue(), rte_event_release()
> + */
> +
> +#define RTE_SCHED_TYPE_PARALLEL 2
> +/**< Parallel scheduling
> + *
> + * The scheduler performs priority scheduling, load balancing, etc. functions
> + * but does not provide additional event synchronization or ordering.
> + * It is free to schedule events from a single parallel flow of an event queue
> + * to multiple events ports for concurrent processing.
> + * The application is responsible for flow context synchronization and
> + * event ordering (SW synchronization).
> + */
> +
> +/* Event types to classify the event source */
> +#define RTE_EVENT_TYPE_ETHDEV 0x0
> +/**< The event generated from ethdev subsystem */
> +#define RTE_EVENT_TYPE_CRYPTODEV 0x1
> +/**< The event generated from crypodev subsystem */
> +#define RTE_EVENT_TYPE_TIMERDEV 0x2
> +/**< The event generated from timerdev subsystem */
> +#define RTE_EVENT_TYPE_CORE 0x3
> +/**< The event generated from core.
> + * Application may use *sub_event_type* to further classify the event
> + */
> +#define RTE_EVENT_TYPE_MAX 0x10
> +/**< Maximum number of event types */
> +
> +/* Event priority */
> +#define RTE_EVENT_PRIORITY_HIGHEST 0
> +/**< Highest event priority */
> +#define RTE_EVENT_PRIORITY_NORMAL 128
> +/**< Normal event priority */
> +#define RTE_EVENT_PRIORITY_LOWEST 255
> +/**< Lowest event priority */
> +
> +/**
> + * The generic *rte_event* structure to hold the event attributes
> + * for dequeue and enqueue operation
> + */
> +struct rte_event {
> + /** WORD0 */
> + RTE_STD_C11
> + union {
> + uint64_t u64;
> + /** Event attributes for dequeue or enqueue operation */
> + struct {
> + uint32_t flow_id:24;
> + /**< Targeted flow identifier for the enqueue and
> + * dequeue operation.
> + * The value must be in the range of
> + * [1 - max_event_queue_flows)] which
> + * previously supplied to rte_event_dev_configure().
> + */
> + uint32_t queue_id:8;
> + /**< Targeted event queue identifier for the enqueue
> or
> + * dequeue operation.
> + * The value must be in the range of
> + * [0, nb_event_queues - 1] which previously supplied
> to
> + * rte_event_dev_configure().
> + */
> + uint8_t sched_type;
> + /**< Scheduler synchronization type
> (RTE_SCHED_TYPE_)
> + * associated with flow id on a given event queue
> + * for the enqueue and dequeue operation.
> + */
> + uint8_t event_type;
> + /**< Event type to classify the event source. */
> + uint8_t sub_event_type;
> + /**< Sub-event types based on the event source.
> + * \see RTE_EVENT_TYPE_CORE
> + */
> + uint8_t priority;
> + /**< Event priority relative to other events in the
> + * event queue. The requested priority should in the
> + * range of [RTE_EVENT_PRIORITY_HIGHEST,
> + * RTE_EVENT_PRIORITY_LOWEST].
> + * The implementation shall normalize the requested
> + * priority to supported priority value.
> + * Valid when the device has
> RTE_EVENT_DEV_CAP_EVENT_QOS
> + * capability.
> + */
> + };
> + };
> + /** WORD1 */
> + RTE_STD_C11
> + union {
> + uintptr_t event;
> + /**< Opaque event pointer */
> + struct rte_mbuf *mbuf;
> + /**< mbuf pointer if dequeued event is associated with mbuf
> */
> + };
> +};
> +
> +/**
> + * Schedule one or more events in the event dev.
> + *
> + * An event dev implementation may define this is a NOOP, for instance if
> + * the event dev performs its scheduling in hardware.
> + *
> + * @param dev_id
> + * The identifier of the device.
> + */
> +extern void
> +rte_event_schedule(uint8_t dev_id);
One idea: Have the function return the number of scheduled packets (or 0 for implementations that do scheduling in hardware). This could be a helpful diagnostic for the software scheduler.
> +
> +/**
> + * Enqueue the event object supplied in the *rte_event* structure on an
> + * event device designated by its *dev_id* through the event port specified by
> + * *port_id*. The event object specifies the event queue on which this
> + * event will be enqueued.
> + *
> + * @param dev_id
> + * Event device identifier.
> + * @param port_id
> + * The identifier of the event port.
> + * @param ev
> + * Pointer to struct rte_event
> + * @param pin_event
> + * Hint to the scheduler that the event can be pinned to the same port for
> + * the next scheduling stage. For implementations that support it, this
> + * allows the same core to process the next stage in the pipeline for a given
> + * event, taking advantage of cache locality. The pinned event will be
> + * received through rte_event_dequeue(). This is a hint and the event is
> + * not guaranteed to be pinned to the port. This hint is valid only when the
> + * event is dequeued with rte_event_dequeue() followed by
> rte_event_enqueue().
> + *
> + * @return
> + * - 0 on success
> + * - <0 on failure. Failure can occur if the event port's output queue is
> + * backpressured, for instance.
> + */
> +extern int
> +rte_event_enqueue(uint8_t dev_id, uint8_t port_id, struct rte_event *ev,
> + bool pin_event);
> +
> +/**
> + * Enqueue a burst of events objects supplied in *rte_event* structure on an
> + * event device designated by its *dev_id* through the event port specified by
> + * *port_id*. Each event object specifies the event queue on which it
> + * will be enqueued.
> + *
> + * The rte_event_enqueue_burst() function is invoked to enqueue
> + * multiple event objects.
> + * It is the burst variant of rte_event_enqueue() function.
> + *
> + * The *num* parameter is the number of event objects to enqueue which are
> + * supplied in the *ev* array of *rte_event* structure.
> + *
> + * The rte_event_enqueue_burst() function returns the number of
> + * events objects it actually enqueued. A return value equal to *num* means
> + * that all event objects have been enqueued.
> + *
> + * @param dev_id
> + * The identifier of the device.
> + * @param port_id
> + * The identifier of the event port.
> + * @param ev
> + * An array of *num* pointers to *rte_event* structure
> + * which contain the event object enqueue operations to be processed.
> + * @param num
> + * The number of event objects to enqueue, typically number of
> + * rte_event_port_enqueue_depth() available for this port.
> + * @param pin_event
> + * Hint to the scheduler that the event can be pinned to the same port for
> + * the next scheduling stage. For implementations that support it, this
> + * allows the same core to process the next stage in the pipeline for a given
> + * event, taking advantage of cache locality. The pinned event will be
> + * received through rte_event_dequeue(). This is a hint and the event is
> + * not guaranteed to be pinned to the port. This hint is valid only when the
> + * event is dequeued with rte_event_dequeue() followed by
> rte_event_enqueue().
> + *
> + * @return
> + * The number of event objects actually enqueued on the event device. The
> + * return value can be less than the value of the *num* parameter when the
> + * event devices queue is full or if invalid parameters are specified in a
> + * *rte_event*. If return value is less than *num*, the remaining events at
> + * the end of ev[] are not consumed, and the caller has to take care of them.
> + *
> + * \see rte_event_enqueue(), rte_event_port_enqueue_depth()
> + */
> +extern int
> +rte_event_enqueue_burst(uint8_t dev_id, uint8_t port_id,
> + struct rte_event ev[], int num, bool pin_event);
> +
> +/**
> + * Converts nanoseconds to *wait* value for rte_event_dequeue()
> + *
> + * If the device is configured with
> RTE_EVENT_DEV_CFG_PER_DEQUEUE_WAIT flag then
> + * application can use this function to convert wait value in nanoseconds to
> + * implementations specific wait value supplied in rte_event_dequeue()
> + *
> + * @param dev_id
> + * The identifier of the device.
> + * @param ns
> + * Wait time in nanosecond
> + *
> + * @return
> + * Value for the *wait* parameter in rte_event_dequeue() function
> + *
> + * \see rte_event_dequeue(), RTE_EVENT_DEV_CFG_PER_DEQUEUE_WAIT
> + * \see rte_event_dev_configure()
> + *
> + */
> +extern uint64_t
> +rte_event_dequeue_wait_time(uint8_t dev_id, uint64_t ns);
> +
> +/**
> + * Dequeue an event from the event port specified by *port_id* on the
> + * event device designated by its *dev_id*.
> + *
> + * rte_event_dequeue() does not dictate the specifics of scheduling algorithm
> as
> + * each eventdev driver may have different criteria to schedule an event.
> + * However, in general, from an application perspective scheduler may use the
> + * following scheme to dispatch an event to the port.
> + *
> + * 1) Selection of event queue based on
> + * a) The list of event queues are linked to the event port.
> + * b) If the device has RTE_EVENT_DEV_CAP_QUEUE_QOS capability then
> event
> + * queue selection from list is based on event queue priority relative to
> + * other event queue supplied as *priority* in rte_event_queue_setup()
> + * c) If the device has RTE_EVENT_DEV_CAP_EVENT_QOS capability then
> event
> + * queue selection from the list is based on event priority supplied as
> + * *priority* in rte_event_enqueue_burst()
> + * 2) Selection of event
> + * a) The number of flows available in selected event queue.
> + * b) Schedule type method associated with the event
> + *
> + * On a successful dequeue, the event port holds flow id and schedule type
> + * context associated with the dispatched event. The context is automatically
> + * released in the next rte_event_dequeue() invocation, or rte_event_release()
> + * can be called to release the context early.
> + *
> + * @param dev_id
> + * The identifier of the device.
> + * @param port_id
> + * The identifier of the event port.
> + * @param[out] ev
> + * Pointer to struct rte_event. On successful event dispatch, implementation
> + * updates the event attributes.
> + * @param wait
> + * 0 - no-wait, returns immediately if there is no event.
> + * >0 - wait for the event, if the device is configured with
> + * RTE_EVENT_DEV_CFG_PER_DEQUEUE_WAIT then this function will wait
> until
> + * the event available or *wait* time.
> + * if the device is not configured with
> RTE_EVENT_DEV_CFG_PER_DEQUEUE_WAIT
> + * then this function will wait until the event available or *dequeue_wait_ns*
> + * ns which was previously supplied to rte_event_dev_configure()
> + *
> + * @return
> + * When true, a valid event has been dispatched by the scheduler.
> + *
> + */
> +extern bool
> +rte_event_dequeue(uint8_t dev_id, uint8_t port_id,
> + struct rte_event *ev, uint64_t wait);
> +
> +/**
> + * Dequeue a burst of events objects from the event port designated by its
> + * *event_port_id*, on an event device designated by its *dev_id*.
> + *
> + * The rte_event_dequeue_burst() function is invoked to dequeue
> + * multiple event objects. It is the burst variant of rte_event_dequeue()
> + * function.
> + *
> + * The *num* parameter is the maximum number of event objects to dequeue
> which
> + * are returned in the *ev* array of *rte_event* structure.
> + *
> + * The rte_event_dequeue_burst() function returns the number of
> + * events objects it actually dequeued. A return value equal to
> + * *num* means that all event objects have been dequeued.
> + *
> + * The number of events dequeued is the number of scheduler contexts held
> by
> + * this port. These contexts are automatically released in the next
> + * rte_event_dequeue() invocation, or rte_event_release() can be called once
> + * per event to release the contexts early.
> + *
> + * @param dev_id
> + * The identifier of the device.
> + * @param port_id
> + * The identifier of the event port.
> + * @param[out] ev
> + * An array of *num* pointers to *rte_event* structure which is populated
> + * with the dequeued event objects.
> + * @param num
> + * The maximum number of event objects to dequeue, typically number of
> + * rte_event_port_dequeue_depth() available for this port.
> + * @param wait
> + * 0 - no-wait, returns immediately if there is no event.
> + * >0 - wait for the event, if the device is configured with
> + * RTE_EVENT_DEV_CFG_PER_DEQUEUE_WAIT then this function will wait
> until the
> + * event available or *wait* time.
> + * if the device is not configured with
> RTE_EVENT_DEV_CFG_PER_DEQUEUE_WAIT
> + * then this function will wait until the event available or *dequeue_wait_ns*
> + * ns which was previously supplied to rte_event_dev_configure()
> + *
> + * @return
> + * The number of event objects actually dequeued from the port. The return
> + * value can be less than the value of the *num* parameter when the
> + * event port's queue is not full.
> + *
> + * \see rte_event_dequeue(), rte_event_port_dequeue_depth()
> + */
> +extern int
> +rte_event_dequeue_burst(uint8_t dev_id, uint8_t port_id,
> + struct rte_event *ev, int num, uint64_t wait);
> +
> +/**
> + * Release the current flow context associated with a schedule type which
> + * dequeued from a given event queue though the event port designated by
> + * its *port_id*
> + *
> + * If current flow's scheduler type method is *RTE_SCHED_TYPE_ATOMIC*
> + * then this function hints the scheduler that the user has completed critical
> + * section processing in the current atomic context.
> + * The scheduler is now allowed to schedule events from the same flow from
> + * an event queue to another port. However, the context may be still held
> + * until the next rte_event_dequeue() or rte_event_dequeue_burst() call, this
> + * call allows but does not force the scheduler to release the context early.
> + *
> + * Early atomic context release may increase parallelism and thus system
> + * performance, but the user needs to design carefully the split into critical
> + * vs non-critical sections.
> + *
> + * If current flow's scheduler type method is *RTE_SCHED_TYPE_ORDERED*
> + * then this function hints the scheduler that the user has done all that need
> + * to maintain event order in the current ordered context.
> + * The scheduler is allowed to release the ordered context of this port and
> + * avoid reordering any following enqueues.
> + *
> + * Early ordered context release may increase parallelism and thus system
> + * performance.
> + *
> + * If current flow's scheduler type method is *RTE_SCHED_TYPE_PARALLEL*
> + * or no scheduling context is held then this function may be an NOOP,
> + * depending on the implementation.
> + *
> + * If multiple events are dequeued with rte_event_dequeue_burst(),
> + * rte_event_release() will release each flow context associated with a
> + * schedule type of an event though *index*, it denotes the order in
> + * which it was dequeued with rte_event_dequeue_burst()
> + *
> + * @param dev_id
> + * The identifier of the device.
> + * @param port_id
> + * The identifier of the event port.
> + * @param index
> + * The index of the event that dequeued with rte_event_dequeue_burst()
> + * which needs to release. The value zero used if the event dequeued with
> + * rte_event_dequeue()
> + *
> + * \see rte_event_dequeue(), rte_event_dequeue_burst()
> + */
> +extern void
> +rte_event_release(uint8_t dev_id, uint8_t port_id, uint8_t index);
> +
> +#define RTE_EVENT_QUEUE_SERVICE_PRIORITY_HIGHEST 0
> +/**< Highest event queue servicing priority */
> +#define RTE_EVENT_QUEUE_SERVICE_PRIORITY_NORMAL 128
> +/**< Normal event queue servicing priority */
> +#define RTE_EVENT_QUEUE_SERVICE_PRIORITY_LOWEST 255
> +/**< Lowest event queue servicing priority */
> +
> +/** Structure to hold the queue to port link establishment attributes */
> +struct rte_event_queue_link {
> + uint8_t queue_id;
> + /**< Event queue identifier to select the source queue to link */
> + uint8_t priority;
> + /**< The priority of the event queue for this event port.
> + * The priority defines the event port's servicing priority for
> + * event queue, which may be ignored by an implementation.
> + * The requested priority should in the range of
> + * [RTE_EVENT_QUEUE_SERVICE_PRIORITY_HIGHEST,
> + * RTE_EVENT_QUEUE_SERVICE_PRIORITY_LOWEST].
> + * The implementation shall normalize the requested priority to
> + * implementation supported priority value.
> + */
> +};
> +
> +/**
> + * Link multiple source event queues supplied in *rte_event_queue_link*
> + * structure as *queue_id* to the destination event port designated by its
> + * *port_id* on the event device designated by its *dev_id*.
> + *
> + * The link establishment shall enable the event port *port_id* from
> + * receiving events from the specified event queue *queue_id*
> + *
> + * An event queue may link to one or more event ports.
> + * The number of links can be established from an event queue to event port is
> + * implementation defined.
> + *
> + * Event queue(s) to event port link establishment can be changed at runtime
> + * without re-configuring the device to support scaling and to reduce the
> + * latency of critical work by establishing the link with more event ports
> + * at runtime.
> + *
> + * @param dev_id
> + * The identifier of the device.
> + *
> + * @param port_id
> + * Event port identifier to select the destination port to link.
> + *
> + * @param link
> + * An array of *num* pointers to *rte_event_queue_link* structure
> + * which contain the event queue to event port link establishment attributes.
> + * NULL value is allowed, in which case this function links all the configured
> + * event queues *nb_event_queues* which previously supplied to
> + * rte_event_dev_configure() to the event port *port_id* with normal
> servicing
> + * priority(RTE_EVENT_QUEUE_SERVICE_PRIORITY_NORMAL).
> + *
> + * @param num
> + * The number of links to establish
> + *
> + * @return
> + * The number of links actually established on the event device. The return
> + * value can be less than the value of the *num* parameter when the
> + * implementation has the limitation on specific queue to port link
> + * establishment or if invalid parameters are specified
> + * in a *rte_event_queue_link*.
> + * If the return value is less than *num*, the remaining links at the end of
> + * link[] are not established, and the caller has to take care of them.
> + * If return value is less than *num* then implementation shall update the
> + * rte_errno accordingly, Possible rte_errno values are
> + * (-EDQUOT) Quota exceeded(Application tried to link the queue configured
> with
> + * RTE_EVENT_QUEUE_CFG_SINGLE_CONSUMER to more than one event
> ports)
> + * (-EINVAL) Invalid parameter
> + *
> + */
> +extern int
> +rte_event_port_link(uint8_t dev_id, uint8_t port_id,
> + struct rte_event_queue_link link[], int num);
> +
> +/**
> + * Unlink multiple source event queues supplied in *queues* from the
> destination
> + * event port designated by its *port_id* on the event device designated
> + * by its *dev_id*.
> + *
> + * The unlink establishment shall disable the event port *port_id* from
> + * receiving events from the specified event queue *queue_id*
> + *
> + * Event queue(s) to event port unlink establishment can be changed at
> runtime
> + * without re-configuring the device.
> + *
> + * @param dev_id
> + * The identifier of the device.
> + *
> + * @param port_id
> + * Event port identifier to select the destination port to unlink.
> + *
> + * @param queues
> + * An array of *num* event queues to be unlinked from the event port.
> + * NULL value is allowed, in which case this function unlinks all the
> + * event queue(s) from the event port *port_id*.
> + *
> + * @param num
> + * The number of unlinks to establish
> + *
> + * @return
> + * The number of unlinks actually established on the event device. The return
> + * value can be less than the value of the *num* parameter when the
> + * implementation has the limitation on specific queue to port unlink
> + * establishment or if invalid parameters are specified.
> + * If the return value is less than *num*, the remaining queues at the end of
> + * queues[] are not established, and the caller has to take care of them.
> + * If return value is less than *num* then implementation shall update the
> + * rte_errno accordingly, Possible rte_errno values are
> + * (-EINVAL) Invalid parameter
> + *
> + */
> +extern int
> +rte_event_port_unlink(uint8_t dev_id, uint8_t port_id,
> + uint8_t queues[], int num);
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* _RTE_EVENTDEV_H_ */
> --
> 2.5.5
More information about the dev
mailing list