[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