[dpdk-dev] [PATCH v4 3/4] eventdev: Add eventdev ethernet Rx adapter

santosh santosh.shukla at caviumnetworks.com
Fri Sep 22 08:08:26 CEST 2017


On Friday 22 September 2017 02:47 AM, Nikhil Rao wrote:
> Add common APIs for configuring packet transfer from ethernet Rx
> queues to event devices across HW & SW packet transfer mechanisms.
> A detailed description of the adapter is contained in the header's
> comments.
>
> The adapter implementation uses eventdev PMDs to configure the packet
> transfer if HW support is available and if not, it uses an EAL service
> function that reads packets from ethernet Rx queues and injects these
> as events into the event device.
>
> Signed-off-by: Nikhil Rao <nikhil.rao at intel.com>
> Signed-off-by: Gage Eads <gage.eads at intel.com>
> Signed-off-by: Abhinandan Gujjar <abhinandan.gujjar at intel.com>
> ---
>  lib/librte_eventdev/rte_event_eth_rx_adapter.h |  384 ++++++++
>  lib/librte_eventdev/rte_event_eth_rx_adapter.c | 1238 ++++++++++++++++++++++++
>  lib/Makefile                                   |    2 +-
>  lib/librte_eventdev/Makefile                   |    2 +
>  lib/librte_eventdev/rte_eventdev_version.map   |   11 +-
>  5 files changed, 1635 insertions(+), 2 deletions(-)
>  create mode 100644 lib/librte_eventdev/rte_event_eth_rx_adapter.h
>  create mode 100644 lib/librte_eventdev/rte_event_eth_rx_adapter.c
>
> diff --git a/lib/librte_eventdev/rte_event_eth_rx_adapter.h b/lib/librte_eventdev/rte_event_eth_rx_adapter.h
> new file mode 100644
> index 000000000..c3849ec31
> --- /dev/null
> +++ b/lib/librte_eventdev/rte_event_eth_rx_adapter.h
> @@ -0,0 +1,384 @@
> +/*
> + *   Copyright(c) 2017 Intel Corporation. All rights reserved.
> + *   All rights reserved.
> + *
> + *   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 Intel Corporation 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_EVENT_ETH_RX_ADAPTER_
> +#define _RTE_EVENT_ETH_RX_ADAPTER_
> +
> +/**
> + * @file
> + *
> + * RTE Event Ethernet Rx Adapter
> + *
> + * An eventdev-based packet processing application enqueues/dequeues mbufs
> + * to/from the event device. The application uses the adapter APIs to configure
> + * the packet flow between the ethernet devices and event devices. Depending on
> + * on the capabilties of the eventdev PMD, the adapter may use a EAL service
> + * core function for packet transfer or use internal PMD functions to configure
> + * the packet transfer between the ethernet device and the event device.
> + *
> + * The ethernet Rx event adapter's functions are:
> + *  - rte_event_eth_rx_adapter_create_ext()
> + *  - rte_event_eth_rx_adapter_create()/free()
> + *  - rte_event_eth_rx_adapter_queue_add()/del()
> + *  - rte_event_eth_rx_adapter_start()/stop()
> + *  - rte_event_eth_rx_adapter_stats_get()/reset()
> + *
> + * The applicaton creates an event to ethernet adapter using
> + * rte_event_eth_rx_adapter_create_ext() or rte_event_eth_rx_adapter_create()
> + * functions.
> + * The adapter needs to know which ethernet rx queues to poll for mbufs as well
> + * as event device parameters such as the event queue identifier, event
> + * priority and scheduling type that the adapter should use when constructing
> + * events. The rte_event_eth_rx_adapter_queue_add() function is provided for
> + * this purpose.
> + * The servicing weight parameter in the rte_event_eth_rx_adapter_queue_conf
> + * is applicable when the Rx adapter uses a service core function and is
> + * intended to provide application control of the polling frequency of ethernet
> + * device receive queues, for example, the application may want to poll higher
> + * priority queues with a higher frequency but at the same time not starve
> + * lower priority queues completely. If this parameter is zero and the receive
> + * interrupt is enabled when configuring the device, the receive queue is
> + * interrupt driven; else, the queue is assigned a servicing weight of one.
> + *
> + * If the adapter uses a rte_service function, then the application is also
> + * required to assign a core to the service function and control the service
> + * core using the rte_service APIs. The rte_event_eth_rx_adapter_service_id_get
> + * function can be used to retrieve the service function ID of the adapter in
> + * this case.
> + *
> + * Note: Interrupt driven receive queues are currentely unimplemented.
> + */
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +#include <stdint.h>
> +#include <rte_service.h>
> +
> +#include "rte_eventdev.h"
> +
> +#define RTE_MAX_EVENT_ETH_RX_ADAPTER_INSTANCE 32
> +
> +/* struct rte_event_eth_rx_adapter_queue_conf flags definitions */
> +#define RTE_EVENT_ETH_RX_ADAPTER_QUEUE_FLOW_ID_VALID	0x1
> +/**< This flag indicates the flow identifier is valid
> + * @see rte_event_eth_rx_adapter_queue_conf
> + */
> +
> +struct rte_event_eth_rx_adapter_conf {
> +	uint8_t event_port_id;
> +	/**< Event port identifier, the adapter enqueues mbuf events to this
> +	 * port
> +	 */
> +	uint32_t max_nb_rx;
> +	/**< The adapter can return early if it has processed at least
> +	 * max_nb_rx mbufs. This isn't treated as a requirement; batching may
> +	 * cause the adapter to process more than max_nb_rx mbufs
> +	 */
> +};
> +
> +/**
> + * Function type used for adapter configuration callback. The callback is
> + * used to fill in members of the struct rte_event_eth_rx_adapter_conf, this
> + * callback is invoked when creating a SW service for packet transfer from
> + * ethdev queues to the event device. The SW service is created within the
> + * rte_event_eth_rx_adapter_queue_add() function if packet required.
> + *
> + * @param id
> + *  Adapter identifier.
> + *
> + * @param dev_id
> + *  Event device identifier.
> + *
> + * @conf
> + *  Structure that needs to be populated by this callback.
> + *
> + * @arg
> + *  Argument to the callback. This is the same as the conf_arg passed to the
> + *  rte_event_eth_rx_adapter_create_ext()
> + */
> +typedef int (*rx_adapter_conf_cb) (uint8_t id, uint8_t dev_id,
> +			struct rte_event_eth_rx_adapter_conf *conf,
> +			void *arg);
> +
> +/** Rx queue configuration structure */
> +struct rte_event_eth_rx_adapter_queue_conf {
> +	uint32_t rx_queue_flags;
> +	 /**< Flags for handling received packets
> +	  * @see RTE_EVENT_ETH_RX_ADAPTER_QUEUE_FLOW_ID_VALID
> +	  */
> +	uint16_t servicing_weight;
> +	/**< Relative polling frequency of ethernet receive queue, if this
> +	 * is set to zero, the Rx queue is interrupt driven (unless rx queue
> +	 * interrupts are not enabled for the ethernet device)
> +	 */
> +	struct rte_event ev;
> +	/**<
> +	 *  The values from the following event fields will be used when
> +	 *  enqueuing mbuf events:
> +	 *   - event_queue_id: Targeted event queue ID for received packets.
> +	 *   - event_priority: Event priority of packets from this Rx queue in
> +	 *                     the event queue relative to other events.
> +	 *   - sched_type: Scheduling type for packets from this Rx queue.
> +	 *   - flow_id: If the RTE_ETH_RX_EVENT_ADAPTER_QUEUE_FLOW_ID_VALID bit
> +	 *		is set in rx_queue_flags, this flow_id is used for all
> +	 *		packets received from this queue. Otherwise the flow ID
> +	 *		is set to the RSS hash of the src and dst IPv4/6
> +	 *		address.
> +	 *
> +	 * The event adapter sets ev.event_type to RTE_EVENT_TYPE_ETHDEV in the
> +	 * enqueued event
> +	 */
> +};
> +
> +struct rte_event_eth_rx_adapter_stats {
> +	uint64_t rx_poll_count;
> +	/**< Receive queue poll count */
> +	uint64_t rx_packets;
> +	/**< Received packet count */
> +	uint64_t rx_enq_count;
> +	/**< Eventdev enqueue count */
> +	uint64_t rx_enq_retry;
> +	/**< Eventdev enqueue retry count */
> +	uint64_t rx_enq_start_ts;
> +	/**< Rx enqueue start timestamp */
> +	uint64_t rx_enq_block_cycles;
> +	/**< Cycles for which the service is blocked by the event device,
> +	 * i.e, the service fails to enqueue to the event device.
> +	 */
> +	uint64_t rx_enq_end_ts;
> +	/**< Latest timestamp at which the service is unblocked
> +	 * by the event device. The start, end timestamps and
> +	 * block cycles can be used to compute the percentage of
> +	 * cycles the service is blocked by the event device.
> +	 */
> +};
> +
> +/**
> + * Create a new ethernet Rx event adapter with the specified identifier.
> + *
> + * @param id
> + *  The identifier of the ethernet Rx event adapter.
> + *
> + * @dev_id
> + *  The identifier of the device to configure.
> + *
> + * @eth_port_id
> + *  The identifier of the ethernet device.
> + *
> + * @param conf_cb
> + *  Callback function that fills in members of a
> + *  struct rte_event_eth_rx_adapter_conf struct passed into
> + *  it.
> + *
> + * @param conf_arg
> + *  Argument that is passed to the conf_cb function.
> + *
> + * @return
> + *   - 0: Success
> + *   - <0: Error code on failure
> + */
> +int rte_event_eth_rx_adapter_create_ext(uint8_t id, uint8_t dev_id,
> +					rx_adapter_conf_cb conf_cb,
> +					void *conf_arg);
> +
> +/**
> + * Create a new ethernet Rx event adapter with the specified identifier.
> + * This function uses an internal configuration function that creates an event
> + * port. This default function reconfigures the event device with an
> + * additional event port and setups up the event port using the port_config
> + * parameter passed into this function. In case the application needs more
> + * control in configuration of the service, it should use the
> + * rte_event_eth_rx_adapter_create_ext() version.
> + *
> + * @param id
> + *  The identifier of the ethernet Rx event adapter.
> + *
> + * @dev_id
> + *  The identifier of the device to configure.
> + *
> + * @eth_port_id
> + *  The identifier of the ethernet device.
> + *
> + * @param conf_cb
> + *  Callback function that fills in members of a
> + *  struct rte_event_eth_rx_adapter_conf struct passed into
> + *  it.
> + *
> + * @param conf_arg
> + *  Argument of type *rte_event_port_conf* that is passed to the conf_cb
> + *  function.
> + *
> + * @return
> + *   - 0: Success
> + *   - <0: Error code on failure
> + */
> +int rte_event_eth_rx_adapter_create(uint8_t id, uint8_t dev_id,
> +				struct rte_event_port_conf *port_config);
> +
> +/**
> + * Free an event adapter
> + *
> + * @param id
> + *  Adapter identifier.
> + *
> + * @return
> + *   - 0: Success
> + *   - <0: Error code on failure, If the adapter still has Rx queues
> + *      added to it, the function returns -EBUSY.
> + */
> +int rte_event_eth_rx_adapter_free(uint8_t id);
> +
> +/**
> + * Add receive queue to an event adapter. After a queue has been
> + * added to the event adapter, the result of the application calling
> + * rte_eth_rx_burst(eth_dev_id, rx_queue_id, ..) is undefined.
> + *
> + * @param id
> + *  Adapter identifier.
> + *
> + * @param eth_dev_id
> + *  Port identifier of Ethernet device.
> + *
> + * @param rx_queue_id
> + *  Ethernet device receive queue index.
> + *  If rx_queue_id is -1, then all Rx queues configured for
> + *  the device are added. If the ethdev Rx queues can only be
> + *  connected to a single event queue then rx_queue_id is
> + *  required to be -1.
> + *
> + * @param conf
> + *  Additonal configuration structure of type *rte_event_eth_rx_adapte_conf*
> + *
> + * @see
> + * @return
> + *  - 0: Success, Receive queue added correctly.
> + *  - <0: Error code on failure.
> + */
> +int rte_event_eth_rx_adapter_queue_add(uint8_t id,
> +			uint8_t eth_dev_id,
> +			int32_t rx_queue_id,
> +			const struct rte_event_eth_rx_adapter_queue_conf *conf);
> +
> +/**
> + * Delete receive queue from an event adapter.
> + *
> + * @param id
> + *  Adapter identifier.
> + *
> + * @param eth_dev_id
> + *  Port identifier of Ethernet device.
> + *
> + * @param rx_queue_id
> + *  Ethernet device receive queue index.
> + *  If rx_queue_id is -1, then all Rx queues configured for
> + *  the device are deleted. If the ethdev Rx queues can only be
> + *  connected to a single event queue then rx_queue_id is
> + *  required to be -1.
> + *
> + * @return
> + *  - 0: Success, Receive queue deleted correctly.
> + *  - <0: Error code on failure.
> + */
> +int rte_event_eth_rx_adapter_queue_del(uint8_t id, uint8_t eth_dev_id,
> +				       int32_t rx_queue_id);
> +
> +/**
> + * Start  ethernet Rx event adapter
> + *
> + * @param id
> + *  Adapter identifier.
> + *
> + * @return
> + *  - 0: Success, Adapter started correctly.
> + *  - <0: Error code on failure.
> + */
> +int rte_event_eth_rx_adapter_start(uint8_t id);
> +
> +/**
> + * Stop  ethernet Rx event adapter
> + *
> + * @param id
> + *  Adapter identifier.
> + *
> + * @return
> + *  - 0: Success, Adapter started correctly.
> + *  - <0: Error code on failure.
> + */
> +int rte_event_eth_rx_adapter_stop(uint8_t id);
> +
> +/**
> + * Retrieve statistics for an adapter
> + *
> + * @param id
> + *  Adapter identifier.
> + *
> + * @param stats
> + *  A pointer to structure used to retrieve statistics for an adapter.
> + *
> + * @return
> + *  - 0: Success, retrieved successfully.
> + *  - <0: Error code on failure.
> + */
> +int rte_event_eth_rx_adapter_stats_get(uint8_t id,
> +				struct rte_event_eth_rx_adapter_stats *stats);
> +
> +/**
> + * Reset statistics for an adapter
> + *
> + * @param id
> + *  Adapter identifier.
> + *
> + * @return
> + *  - 0: Success, statistics reset successfully.
> + *  - <0: Error code on failure.
> + */
> +int rte_event_eth_rx_adapter_stats_reset(uint8_t id);
> +
> +/**
> + * Retrieve the service ID of an adapter. If the adapter doesn't use
> + * a rte_service function, this function returns -ESRCH
> + *
> + * @param id
> + *  Adapter identifier.
> + *
> + * @return
> + *  - 0: Success, statistics reset successfully.
> + *  - <0: Error code on failure, if the adapter doesn't use a rte_service
> + * function, this function returns -ESRCH.
> + */
> +int rte_event_eth_rx_adapter_service_id_get(uint8_t id, uint32_t *service_id);
> +

In general api comment: Fix missing param definition like *service_id* above
and pl. remove other unnecessary params description from api above.

> +#ifdef __cplusplus
> +}
> +#endif
> +#endif	/* _RTE_EVENT_ETH_RX_ADAPTER_ */
> diff --git a/lib/librte_eventdev/rte_event_eth_rx_adapter.c b/lib/librte_eventdev/rte_event_eth_rx_adapter.c
> new file mode 100644
> index 000000000..d5b655dae
> --- /dev/null
> +++ b/lib/librte_eventdev/rte_event_eth_rx_adapter.c
> @@ -0,0 +1,1238 @@
> +#include <rte_cycles.h>
> +#include <rte_common.h>
> +#include <rte_dev.h>
> +#include <rte_errno.h>
> +#include <rte_ethdev.h>
> +#include <rte_log.h>
> +#include <rte_malloc.h>
> +#include <rte_service_component.h>
> +#include <rte_thash.h>
> +
> +#include "rte_eventdev.h"
> +#include "rte_eventdev_pmd.h"
> +#include "rte_event_eth_rx_adapter.h"
> +
> +#define BATCH_SIZE		32
> +#define BLOCK_CNT_THRESHOLD	10
> +#define ETH_EVENT_BUFFER_SIZE	(4*BATCH_SIZE)
> +
> +#define ETH_RX_ADAPTER_SERVICE_NAME_LEN	32
> +#define ETH_RX_ADAPTER_MEM_NAME_LEN	32
> +
> +/*
> + * There is an instance of this struct per polled Rx queue added to the
> + * adapter
> + */
> +struct eth_rx_poll_entry {
> +	/* eth port to poll */
> +	uint8_t eth_dev_id;
> +	/* eth rx queue to poll */
> +	uint16_t eth_rx_qid;
> +};
> +
> +/* Instance per adapter */
> +struct rte_eth_event_enqueue_buffer {
> +	/* Count of events in this buffer */
> +	uint16_t count;
> +	/* Array of events in this buffer */
> +	struct rte_event events[ETH_EVENT_BUFFER_SIZE];
> +};
> +
> +struct rte_event_eth_rx_adapter {
> +	/* event device identifier */
> +	uint8_t eventdev_id;
> +	/* per ethernet device structure */
> +	struct eth_device_info *eth_devices;
> +	/* malloc name */
> +	char mem_name[ETH_RX_ADAPTER_MEM_NAME_LEN];
> +	/* socket identifier cached from eventdev */
> +	int socket_id;
> +
> +	/* elements below are used by SW service */
> +
> +	/* event port identifier */
> +	uint8_t event_port_id;
> +	/* per adapter EAL service */
> +	uint32_t service_id;
> +	/* lock to serialize config updates with service function */
> +	rte_spinlock_t rx_lock;
> +	/* max mbufs processed in any service function invocation */
> +	uint32_t max_nb_rx;
> +	/* Receive queues that need to be polled */
> +	struct eth_rx_poll_entry *eth_rx_poll;
> +	/* size of the eth_rx_poll array */
> +	uint16_t num_rx_polled;
> +	/* Weighted round robin schedule */
> +	uint32_t *wrr_sched;
> +	/* wrr_sched[] size */
> +	uint32_t wrr_len;
> +	/* Next entry in wrr[] to begin polling */
> +	uint32_t wrr_pos;
> +	/* Event burst buffer */
> +	struct rte_eth_event_enqueue_buffer event_enqueue_buffer;
> +	/* per adapter stats */
> +	struct rte_event_eth_rx_adapter_stats stats;
> +	/* Block count, counts upto BLOCK_CNT_THRESHOLD */
> +	uint16_t enq_block_count;
> +	/* Block start ts */
> +	uint64_t rx_enq_block_start_ts;
> +	/* Configuration callback for rte_service configuration */
> +	rx_adapter_conf_cb conf_cb;
> +	/* Configuration callback argument */
> +	void *conf_arg;
> +	/* Service initialization state */
> +	uint8_t service_inited;
> +	/* Total count of Rx queues in adapter */
> +	uint32_t nb_queues;
> +} __rte_cache_aligned;
> +
> +/* Per eth device */
> +struct eth_device_info {
> +	struct rte_eth_dev *dev;
> +	struct eth_rx_queue_info *rx_queue;
> +	/* Set if ethdev->eventdev packet transfer uses a
> +	 * hardware mechanism
> +	 */
> +	uint8_t internal_event_port;
> +	/* set if the adapter is processing rx queues for
> +	 * this eth device and packet processing has been
> +	 * started, allows for the code to know if the PMD
> +	 * rx_adapter_stop callback needs to be invoked
> +	 */
> +	uint8_t dev_rx_started;
> +	/* if nb_dev_queues > 0, the start callback will
> +	 * be invoked if not already invoked
> +	 */
> +	uint16_t nb_dev_queues;
> +};
> +
> +/* Per Rx queue */
> +struct eth_rx_queue_info {
> +	int queue_enabled;	/* true if added */
> +	uint16_t wt;		/* polling weight */
> +	uint8_t event_queue_id;	/* Event queue to enqueue packets to */
> +	uint8_t sched_type;	/* sched type for events */
> +	uint8_t priority;	/* event priority */
> +	uint32_t flow_id;	/* app provided flow identifier */
> +	uint32_t flow_id_mask;	/* Set to ~0 if app provides flow id else 0 */
> +};
> +
> +static struct rte_event_eth_rx_adapter **rte_event_eth_rx_adapter;
> +static struct rte_event_port_conf
> +		create_port_conf[RTE_MAX_EVENT_ETH_RX_ADAPTER_INSTANCE];
> +
> +static uint8_t default_rss_key[] = {
> +	0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
> +	0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
> +	0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
> +	0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
> +	0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa,
> +};
> +static uint8_t *rss_key_be;
> +
> +static inline int
> +valid_id(uint8_t id)
> +{
> +	return id < RTE_MAX_EVENT_ETH_RX_ADAPTER_INSTANCE;
> +}
> +
> +#define RTE_EVENT_ETH_RX_ADAPTER_ID_VALID_OR_ERR_RET(id, retval) do { \
> +	if (!valid_id(id)) { \
> +		RTE_EDEV_LOG_ERR("Invalid eth Rx adapter id = %d\n", id); \
> +		return retval; \
> +	} \
> +} while (0)
> +

Worth, moving this macro to rte_eventdev_pmd.h
Or How about reusing existing one ie.. RTE_EVENTDEV_VALID_DEVID_OR_ERR_RET?

> +static inline int
> +sw_rx_adapter_queue_count(struct rte_event_eth_rx_adapter *rx_adapter)
> +{
> +	return rx_adapter->num_rx_polled;
> +}
> +
> +/* Greatest common divisor */
> +static uint16_t gcd_u16(uint16_t a, uint16_t b)
> +{
> +	uint16_t r = a % b;
> +
> +	return r ? gcd_u16(b, r) : b;
> +}
> +
> +/* Returns the next queue in the polling sequence
> + *
> + * http://kb.linuxvirtualserver.org/wiki/Weighted_Round-Robin_Scheduling
> + */
> +static int
> +wrr_next(struct rte_event_eth_rx_adapter *rx_adapter,
> +	 unsigned int n, int *cw,
> +	 struct eth_rx_poll_entry *eth_rx_poll, uint16_t max_wt,
> +	 uint16_t gcd, int prev)
> +{
> +	int i = prev;
> +	uint16_t w;
> +
> +	while (1) {
> +		uint16_t q;
> +		uint8_t d;
> +
> +		i = (i + 1) % n;
> +		if (i == 0) {
> +			*cw = *cw - gcd;
> +			if (*cw <= 0)
> +				*cw = max_wt;
> +		}
> +
> +		q = eth_rx_poll[i].eth_rx_qid;
> +		d = eth_rx_poll[i].eth_dev_id;
> +		w = rx_adapter->eth_devices[d].rx_queue[q].wt;
> +
> +		if ((int)w >= *cw)
> +			return i;
> +	}
> +}
> +
> +/* Precalculate WRR polling sequence for all queues in rx_adapter */
> +static int
> +eth_poll_wrr_calc(struct rte_event_eth_rx_adapter *rx_adapter)
> +{
> +	uint8_t d;
> +	uint16_t q;
> +	unsigned int i;
> +
> +	/* Initialize variables for calculaton of wrr schedule */
> +	uint16_t max_wrr_pos = 0;
> +	unsigned int poll_q = 0;
> +	uint16_t max_wt = 0;
> +	uint16_t gcd = 0;
> +
> +	struct eth_rx_poll_entry *rx_poll = NULL;
> +	uint32_t *rx_wrr = NULL;
> +
> +	if (rx_adapter->num_rx_polled) {
> +		size_t len = RTE_ALIGN(rx_adapter->num_rx_polled *
> +				sizeof(*rx_adapter->eth_rx_poll),
> +				RTE_CACHE_LINE_SIZE);
> +		rx_poll = rte_zmalloc_socket(rx_adapter->mem_name,
> +					     len,
> +					     RTE_CACHE_LINE_SIZE,
> +					     rx_adapter->socket_id);
> +		if (!rx_poll)
> +			return -ENOMEM;
> +
> +		/* Generate array of all queues to poll, the size of this
> +		 * array is poll_q
> +		 */
> +		for (d = 0; d < rte_eth_dev_count(); d++) {
> +			uint16_t nb_rx_queues;
> +			struct eth_device_info *dev_info =
> +					&rx_adapter->eth_devices[d];
> +			nb_rx_queues = dev_info->dev->data->nb_rx_queues;
> +			if (!dev_info->rx_queue)
> +				continue;
> +			for (q = 0; q < nb_rx_queues; q++) {
> +				struct eth_rx_queue_info *queue_info =
> +					&dev_info->rx_queue[q];
> +				if (!queue_info->queue_enabled)
> +					continue;
> +
> +				uint16_t wt = queue_info->wt;
> +				rx_poll[poll_q].eth_dev_id = d;
> +				rx_poll[poll_q].eth_rx_qid = q;
> +				max_wrr_pos += wt;
> +				max_wt = RTE_MAX(max_wt, wt);
> +				gcd = (gcd) ? gcd_u16(gcd, wt) : wt;
> +				poll_q++;
> +			}
> +		}
> +
> +		len = RTE_ALIGN(max_wrr_pos * sizeof(*rx_wrr),
> +				RTE_CACHE_LINE_SIZE);
> +		rx_wrr = rte_zmalloc_socket(rx_adapter->mem_name,
> +					    len,
> +					    RTE_CACHE_LINE_SIZE,
> +					    rx_adapter->socket_id);
> +		if (!rx_wrr) {
> +			rte_free(rx_poll);
> +			return -ENOMEM;
> +		}
> +
> +		/* Generate polling sequence based on weights */
> +		int prev = -1;
> +		int cw = -1;
> +		for (i = 0; i < max_wrr_pos; i++) {
> +			rx_wrr[i] = wrr_next(rx_adapter, poll_q, &cw,
> +					     rx_poll, max_wt, gcd, prev);
> +			prev = rx_wrr[i];
> +		}
> +	}
> +
> +	rte_free(rx_adapter->eth_rx_poll);
> +	rte_free(rx_adapter->wrr_sched);
> +
> +	rx_adapter->eth_rx_poll = rx_poll;
> +	rx_adapter->wrr_sched = rx_wrr;
> +	rx_adapter->wrr_len = max_wrr_pos;
> +
> +	return 0;
> +}
> +
> +static inline void
> +mtoip(struct rte_mbuf *m, struct ipv4_hdr **ipv4_hdr,
> +	struct ipv6_hdr **ipv6_hdr)
> +{

mtoip(), imo is more of global api, likely other modules may use in future..
perhaps move to rte_io.h Or more correct place.. thought?

Thanks.



More information about the dev mailing list