#include <rte_memcpy.h>
#include <rte_memzone.h>
#include <rte_launch.h>
-#include <rte_tailq.h>
#include <rte_eal.h>
#include <rte_per_lcore.h>
#include <rte_lcore.h>
#include <rte_mbuf.h>
#include <rte_errno.h>
#include <rte_spinlock.h>
+#include <rte_string_fns.h>
#include "rte_ether.h"
#include "rte_ethdev.h"
/* spinlock for eth device callbacks */
static rte_spinlock_t rte_eth_dev_cb_lock = RTE_SPINLOCK_INITIALIZER;
+/* store statistics names and its offset in stats structure */
+struct rte_eth_xstats_name_off {
+ char name[RTE_ETH_XSTATS_NAME_SIZE];
+ unsigned offset;
+};
+
+static struct rte_eth_xstats_name_off rte_stats_strings[] = {
+ {"rx_packets", offsetof(struct rte_eth_stats, ipackets)},
+ {"tx_packets", offsetof(struct rte_eth_stats, opackets)},
+ {"rx_bytes", offsetof(struct rte_eth_stats, ibytes)},
+ {"tx_bytes", offsetof(struct rte_eth_stats, obytes)},
+ {"tx_errors", offsetof(struct rte_eth_stats, oerrors)},
+ {"rx_missed_errors", offsetof(struct rte_eth_stats, imissed)},
+ {"rx_crc_errors", offsetof(struct rte_eth_stats, ibadcrc)},
+ {"rx_bad_length_errors", offsetof(struct rte_eth_stats, ibadlen)},
+ {"rx_errors", offsetof(struct rte_eth_stats, ierrors)},
+ {"alloc_rx_buff_failed", offsetof(struct rte_eth_stats, rx_nombuf)},
+ {"fdir_match", offsetof(struct rte_eth_stats, fdirmatch)},
+ {"fdir_miss", offsetof(struct rte_eth_stats, fdirmiss)},
+ {"tx_flow_control_xon", offsetof(struct rte_eth_stats, tx_pause_xon)},
+ {"rx_flow_control_xon", offsetof(struct rte_eth_stats, rx_pause_xon)},
+ {"tx_flow_control_xoff", offsetof(struct rte_eth_stats, tx_pause_xoff)},
+ {"rx_flow_control_xoff", offsetof(struct rte_eth_stats, rx_pause_xoff)},
+};
+#define RTE_NB_STATS (sizeof(rte_stats_strings) / sizeof(rte_stats_strings[0]))
+
+static struct rte_eth_xstats_name_off rte_rxq_stats_strings[] = {
+ {"rx_packets", offsetof(struct rte_eth_stats, q_ipackets)},
+ {"rx_bytes", offsetof(struct rte_eth_stats, q_ibytes)},
+};
+#define RTE_NB_RXQ_STATS (sizeof(rte_rxq_stats_strings) / \
+ sizeof(rte_rxq_stats_strings[0]))
+
+static struct rte_eth_xstats_name_off rte_txq_stats_strings[] = {
+ {"tx_packets", offsetof(struct rte_eth_stats, q_opackets)},
+ {"tx_bytes", offsetof(struct rte_eth_stats, q_obytes)},
+ {"tx_errors", offsetof(struct rte_eth_stats, q_errors)},
+};
+#define RTE_NB_TXQ_STATS (sizeof(rte_txq_stats_strings) / \
+ sizeof(rte_txq_stats_strings[0]))
+
+
/**
* The user application callback description.
*
STAT_QMAP_RX
};
+enum {
+ DEV_DETACHED = 0,
+ DEV_ATTACHED
+};
+
static inline void
rte_eth_dev_data_alloc(void)
{
}
struct rte_eth_dev *
-rte_eth_dev_allocate(void)
+rte_eth_dev_allocated(const char *name)
+{
+ unsigned i;
+
+ for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
+ if ((rte_eth_devices[i].attached == DEV_ATTACHED) &&
+ strcmp(rte_eth_devices[i].data->name, name) == 0)
+ return &rte_eth_devices[i];
+ }
+ return NULL;
+}
+
+static uint8_t
+rte_eth_dev_find_free_port(void)
+{
+ unsigned i;
+
+ for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
+ if (rte_eth_devices[i].attached == DEV_DETACHED)
+ return i;
+ }
+ return RTE_MAX_ETHPORTS;
+}
+
+struct rte_eth_dev *
+rte_eth_dev_allocate(const char *name, enum rte_eth_dev_type type)
{
+ uint8_t port_id;
struct rte_eth_dev *eth_dev;
- if (nb_ports == RTE_MAX_ETHPORTS) {
- PMD_DEBUG_TRACE("Reached maximum number of ethernet ports\n");
+ port_id = rte_eth_dev_find_free_port();
+ if (port_id == RTE_MAX_ETHPORTS) {
+ PMD_DEBUG_TRACE("Reached maximum number of Ethernet ports\n");
return NULL;
}
if (rte_eth_dev_data == NULL)
rte_eth_dev_data_alloc();
- eth_dev = &rte_eth_devices[nb_ports];
- eth_dev->data = &rte_eth_dev_data[nb_ports];
- eth_dev->data->port_id = nb_ports++;
+ if (rte_eth_dev_allocated(name) != NULL) {
+ PMD_DEBUG_TRACE("Ethernet Device with name %s already allocated!\n", name);
+ return NULL;
+ }
+
+ eth_dev = &rte_eth_devices[port_id];
+ eth_dev->data = &rte_eth_dev_data[port_id];
+ snprintf(eth_dev->data->name, sizeof(eth_dev->data->name), "%s", name);
+ eth_dev->data->port_id = port_id;
+ eth_dev->attached = DEV_ATTACHED;
+ eth_dev->dev_type = type;
+ nb_ports++;
return eth_dev;
}
+static inline int
+rte_eth_dev_create_unique_device_name(char *name, size_t size,
+ struct rte_pci_device *pci_dev)
+{
+ int ret;
+
+ if ((name == NULL) || (pci_dev == NULL))
+ return -EINVAL;
+
+ ret = snprintf(name, size, "%d:%d.%d",
+ pci_dev->addr.bus, pci_dev->addr.devid,
+ pci_dev->addr.function);
+ if (ret < 0)
+ return ret;
+ return 0;
+}
+
+int
+rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
+{
+ if (eth_dev == NULL)
+ return -EINVAL;
+
+ eth_dev->attached = 0;
+ nb_ports--;
+ return 0;
+}
+
static int
rte_eth_dev_init(struct rte_pci_driver *pci_drv,
struct rte_pci_device *pci_dev)
{
struct eth_driver *eth_drv;
struct rte_eth_dev *eth_dev;
+ char ethdev_name[RTE_ETH_NAME_MAX_LEN];
+
int diag;
eth_drv = (struct eth_driver *)pci_drv;
- eth_dev = rte_eth_dev_allocate();
+ /* Create unique Ethernet device name using PCI address */
+ rte_eth_dev_create_unique_device_name(ethdev_name,
+ sizeof(ethdev_name), pci_dev);
+
+ eth_dev = rte_eth_dev_allocate(ethdev_name, RTE_ETH_DEV_PCI);
if (eth_dev == NULL)
return -ENOMEM;
if (rte_eal_process_type() == RTE_PROC_PRIMARY){
eth_dev->data->dev_private = rte_zmalloc("ethdev private structure",
eth_drv->dev_private_size,
- CACHE_LINE_SIZE);
+ RTE_CACHE_LINE_SIZE);
if (eth_dev->data->dev_private == NULL)
rte_panic("Cannot allocate memzone for private port data\n");
}
eth_dev->data->rx_mbuf_alloc_failed = 0;
/* init user callbacks */
- TAILQ_INIT(&(eth_dev->callbacks));
+ TAILQ_INIT(&(eth_dev->link_intr_cbs));
/*
* Set the default MTU.
eth_dev->data->mtu = ETHER_MTU;
/* Invoke PMD device initialization function */
- diag = (*eth_drv->eth_dev_init)(eth_drv, eth_dev);
+ diag = (*eth_drv->eth_dev_init)(eth_dev);
if (diag == 0)
return (0);
(unsigned) pci_dev->id.device_id);
if (rte_eal_process_type() == RTE_PROC_PRIMARY)
rte_free(eth_dev->data->dev_private);
+ eth_dev->attached = DEV_DETACHED;
nb_ports--;
return diag;
}
+static int
+rte_eth_dev_uninit(struct rte_pci_device *pci_dev)
+{
+ const struct eth_driver *eth_drv;
+ struct rte_eth_dev *eth_dev;
+ char ethdev_name[RTE_ETH_NAME_MAX_LEN];
+ int ret;
+
+ if (pci_dev == NULL)
+ return -EINVAL;
+
+ /* Create unique Ethernet device name using PCI address */
+ rte_eth_dev_create_unique_device_name(ethdev_name,
+ sizeof(ethdev_name), pci_dev);
+
+ eth_dev = rte_eth_dev_allocated(ethdev_name);
+ if (eth_dev == NULL)
+ return -ENODEV;
+
+ eth_drv = (const struct eth_driver *)pci_dev->driver;
+
+ /* Invoke PMD device uninit function */
+ if (*eth_drv->eth_dev_uninit) {
+ ret = (*eth_drv->eth_dev_uninit)(eth_dev);
+ if (ret)
+ return ret;
+ }
+
+ /* free ether device */
+ rte_eth_dev_release_port(eth_dev);
+
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+ rte_free(eth_dev->data->dev_private);
+
+ eth_dev->pci_dev = NULL;
+ eth_dev->driver = NULL;
+ eth_dev->data = NULL;
+
+ return 0;
+}
+
/**
* Register an Ethernet [Poll Mode] driver.
*
rte_eth_driver_register(struct eth_driver *eth_drv)
{
eth_drv->pci_drv.devinit = rte_eth_dev_init;
+ eth_drv->pci_drv.devuninit = rte_eth_dev_uninit;
rte_eal_pci_register(ð_drv->pci_drv);
}
+static int
+rte_eth_dev_is_valid_port(uint8_t port_id)
+{
+ if (port_id >= RTE_MAX_ETHPORTS ||
+ rte_eth_devices[port_id].attached != DEV_ATTACHED)
+ return 0;
+ else
+ return 1;
+}
+
int
rte_eth_dev_socket_id(uint8_t port_id)
{
- if (port_id >= nb_ports)
+ if (!rte_eth_dev_is_valid_port(port_id))
return -1;
return rte_eth_devices[port_id].pci_dev->numa_node;
}
return (nb_ports);
}
+/* So far, DPDK hotplug function only supports linux */
+#ifdef RTE_LIBRTE_EAL_HOTPLUG
+
+static enum rte_eth_dev_type
+rte_eth_dev_get_device_type(uint8_t port_id)
+{
+ if (!rte_eth_dev_is_valid_port(port_id))
+ return RTE_ETH_DEV_UNKNOWN;
+ return rte_eth_devices[port_id].dev_type;
+}
+
+static int
+rte_eth_dev_save(struct rte_eth_dev *devs, size_t size)
+{
+ if ((devs == NULL) ||
+ (size != sizeof(struct rte_eth_dev) * RTE_MAX_ETHPORTS))
+ return -EINVAL;
+
+ /* save current rte_eth_devices */
+ memcpy(devs, rte_eth_devices, size);
+ return 0;
+}
+
+static int
+rte_eth_dev_get_changed_port(struct rte_eth_dev *devs, uint8_t *port_id)
+{
+ if ((devs == NULL) || (port_id == NULL))
+ return -EINVAL;
+
+ /* check which port was attached or detached */
+ for (*port_id = 0; *port_id < RTE_MAX_ETHPORTS; (*port_id)++, devs++) {
+ if (rte_eth_devices[*port_id].attached ^ devs->attached)
+ return 0;
+ }
+ return -ENODEV;
+}
+
+static int
+rte_eth_dev_get_addr_by_port(uint8_t port_id, struct rte_pci_addr *addr)
+{
+ if (!rte_eth_dev_is_valid_port(port_id)) {
+ PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+ return -EINVAL;
+ }
+
+ if (addr == NULL) {
+ PMD_DEBUG_TRACE("Null pointer is specified\n");
+ return -EINVAL;
+ }
+
+ *addr = rte_eth_devices[port_id].pci_dev->addr;
+ return 0;
+}
+
+static int
+rte_eth_dev_get_name_by_port(uint8_t port_id, char *name)
+{
+ char *tmp;
+
+ if (!rte_eth_dev_is_valid_port(port_id)) {
+ PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+ return -EINVAL;
+ }
+
+ if (name == NULL) {
+ PMD_DEBUG_TRACE("Null pointer is specified\n");
+ return -EINVAL;
+ }
+
+ /* shouldn't check 'rte_eth_devices[i].data',
+ * because it might be overwritten by VDEV PMD */
+ tmp = rte_eth_dev_data[port_id].name;
+ strcpy(name, tmp);
+ return 0;
+}
+
+static int
+rte_eth_dev_is_detachable(uint8_t port_id)
+{
+ uint32_t drv_flags;
+
+ if (port_id >= RTE_MAX_ETHPORTS) {
+ PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+ return -EINVAL;
+ }
+
+ if (rte_eth_devices[port_id].dev_type == RTE_ETH_DEV_PCI) {
+ switch (rte_eth_devices[port_id].pci_dev->kdrv) {
+ case RTE_KDRV_IGB_UIO:
+ case RTE_KDRV_UIO_GENERIC:
+ break;
+ case RTE_KDRV_VFIO:
+ default:
+ return -ENOTSUP;
+ }
+ }
+
+ drv_flags = rte_eth_devices[port_id].driver->pci_drv.drv_flags;
+ return !(drv_flags & RTE_PCI_DRV_DETACHABLE);
+}
+
+/* attach the new physical device, then store port_id of the device */
+static int
+rte_eth_dev_attach_pdev(struct rte_pci_addr *addr, uint8_t *port_id)
+{
+ uint8_t new_port_id;
+ struct rte_eth_dev devs[RTE_MAX_ETHPORTS];
+
+ if ((addr == NULL) || (port_id == NULL))
+ goto err;
+
+ /* save current port status */
+ if (rte_eth_dev_save(devs, sizeof(devs)))
+ goto err;
+ /* re-construct pci_device_list */
+ if (rte_eal_pci_scan())
+ goto err;
+ /* invoke probe func of the driver can handle the new device.
+ * TODO:
+ * rte_eal_pci_probe_one() should return port_id.
+ * And rte_eth_dev_save() and rte_eth_dev_get_changed_port()
+ * should be removed. */
+ if (rte_eal_pci_probe_one(addr))
+ goto err;
+ /* get port_id enabled by above procedures */
+ if (rte_eth_dev_get_changed_port(devs, &new_port_id))
+ goto err;
+
+ *port_id = new_port_id;
+ return 0;
+err:
+ RTE_LOG(ERR, EAL, "Driver, cannot attach the device\n");
+ return -1;
+}
+
+/* detach the new physical device, then store pci_addr of the device */
+static int
+rte_eth_dev_detach_pdev(uint8_t port_id, struct rte_pci_addr *addr)
+{
+ struct rte_pci_addr freed_addr;
+ struct rte_pci_addr vp;
+
+ if (addr == NULL)
+ goto err;
+
+ /* check whether the driver supports detach feature, or not */
+ if (rte_eth_dev_is_detachable(port_id))
+ goto err;
+
+ /* get pci address by port id */
+ if (rte_eth_dev_get_addr_by_port(port_id, &freed_addr))
+ goto err;
+
+ /* Zerod pci addr means the port comes from virtual device */
+ vp.domain = vp.bus = vp.devid = vp.function = 0;
+ if (rte_eal_compare_pci_addr(&vp, &freed_addr) == 0)
+ goto err;
+
+ /* invoke close func of the driver,
+ * also remove the device from pci_device_list */
+ if (rte_eal_pci_close_one(&freed_addr))
+ goto err;
+
+ *addr = freed_addr;
+ return 0;
+err:
+ RTE_LOG(ERR, EAL, "Driver, cannot detach the device\n");
+ return -1;
+}
+
+/* attach the new virtual device, then store port_id of the device */
+static int
+rte_eth_dev_attach_vdev(const char *vdevargs, uint8_t *port_id)
+{
+ char *name = NULL, *args = NULL;
+ uint8_t new_port_id;
+ struct rte_eth_dev devs[RTE_MAX_ETHPORTS];
+ int ret = -1;
+
+ if ((vdevargs == NULL) || (port_id == NULL))
+ goto end;
+
+ /* parse vdevargs, then retrieve device name and args */
+ if (rte_eal_parse_devargs_str(vdevargs, &name, &args))
+ goto end;
+
+ /* save current port status */
+ if (rte_eth_dev_save(devs, sizeof(devs)))
+ goto end;
+ /* walk around dev_driver_list to find the driver of the device,
+ * then invoke probe function o the driver.
+ * TODO:
+ * rte_eal_vdev_init() should return port_id,
+ * And rte_eth_dev_save() and rte_eth_dev_get_changed_port()
+ * should be removed. */
+ if (rte_eal_vdev_init(name, args))
+ goto end;
+ /* get port_id enabled by above procedures */
+ if (rte_eth_dev_get_changed_port(devs, &new_port_id))
+ goto end;
+ ret = 0;
+ *port_id = new_port_id;
+end:
+ if (name)
+ free(name);
+ if (args)
+ free(args);
+
+ if (ret < 0)
+ RTE_LOG(ERR, EAL, "Driver, cannot attach the device\n");
+ return ret;
+}
+
+/* detach the new virtual device, then store the name of the device */
+static int
+rte_eth_dev_detach_vdev(uint8_t port_id, char *vdevname)
+{
+ char name[RTE_ETH_NAME_MAX_LEN];
+
+ if (vdevname == NULL)
+ goto err;
+
+ /* check whether the driver supports detach feature, or not */
+ if (rte_eth_dev_is_detachable(port_id))
+ goto err;
+
+ /* get device name by port id */
+ if (rte_eth_dev_get_name_by_port(port_id, name))
+ goto err;
+ /* walk around dev_driver_list to find the driver of the device,
+ * then invoke close function o the driver */
+ if (rte_eal_vdev_uninit(name))
+ goto err;
+
+ strncpy(vdevname, name, sizeof(name));
+ return 0;
+err:
+ RTE_LOG(ERR, EAL, "Driver, cannot detach the device\n");
+ return -1;
+}
+
+/* attach the new device, then store port_id of the device */
+int
+rte_eth_dev_attach(const char *devargs, uint8_t *port_id)
+{
+ struct rte_pci_addr addr;
+
+ if ((devargs == NULL) || (port_id == NULL))
+ return -EINVAL;
+
+ if (eal_parse_pci_DomBDF(devargs, &addr) == 0)
+ return rte_eth_dev_attach_pdev(&addr, port_id);
+ else
+ return rte_eth_dev_attach_vdev(devargs, port_id);
+}
+
+/* detach the device, then store the name of the device */
+int
+rte_eth_dev_detach(uint8_t port_id, char *name)
+{
+ struct rte_pci_addr addr;
+ int ret;
+
+ if (name == NULL)
+ return -EINVAL;
+
+ if (rte_eth_dev_get_device_type(port_id) == RTE_ETH_DEV_PCI) {
+ ret = rte_eth_dev_get_addr_by_port(port_id, &addr);
+ if (ret < 0)
+ return ret;
+
+ ret = rte_eth_dev_detach_pdev(port_id, &addr);
+ if (ret == 0)
+ snprintf(name, RTE_ETH_NAME_MAX_LEN,
+ "%04x:%02x:%02x.%d",
+ addr.domain, addr.bus,
+ addr.devid, addr.function);
+
+ return ret;
+ } else
+ return rte_eth_dev_detach_vdev(port_id, name);
+}
+#else /* RTE_LIBRTE_EAL_HOTPLUG */
+int
+rte_eth_dev_attach(const char *devargs __rte_unused,
+ uint8_t *port_id __rte_unused)
+{
+ RTE_LOG(ERR, EAL, "Hotplug support isn't enabled\n");
+ return -1;
+}
+
+/* detach the device, then store the name of the device */
+int
+rte_eth_dev_detach(uint8_t port_id __rte_unused,
+ char *name __rte_unused)
+{
+ RTE_LOG(ERR, EAL, "Hotplug support isn't enabled\n");
+ return -1;
+}
+#endif /* RTE_LIBRTE_EAL_HOTPLUG */
+
static int
rte_eth_dev_rx_queue_config(struct rte_eth_dev *dev, uint16_t nb_queues)
{
if (dev->data->rx_queues == NULL) { /* first time configuration */
dev->data->rx_queues = rte_zmalloc("ethdev->rx_queues",
sizeof(dev->data->rx_queues[0]) * nb_queues,
- CACHE_LINE_SIZE);
+ RTE_CACHE_LINE_SIZE);
if (dev->data->rx_queues == NULL) {
dev->data->nb_rx_queues = 0;
return -(ENOMEM);
for (i = nb_queues; i < old_nb_queues; i++)
(*dev->dev_ops->rx_queue_release)(rxq[i]);
rxq = rte_realloc(rxq, sizeof(rxq[0]) * nb_queues,
- CACHE_LINE_SIZE);
+ RTE_CACHE_LINE_SIZE);
if (rxq == NULL)
return -(ENOMEM);
-
- if (nb_queues > old_nb_queues)
+ if (nb_queues > old_nb_queues) {
+ uint16_t new_qs = nb_queues - old_nb_queues;
memset(rxq + old_nb_queues, 0,
- sizeof(rxq[0]) * (nb_queues - old_nb_queues));
+ sizeof(rxq[0]) * new_qs);
+ }
dev->data->rx_queues = rxq;
* in a multi-process setup*/
PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY);
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return -EINVAL;
}
* in a multi-process setup*/
PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY);
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return -EINVAL;
}
* in a multi-process setup*/
PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY);
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return -EINVAL;
}
* in a multi-process setup*/
PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY);
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return -EINVAL;
}
if (dev->data->tx_queues == NULL) { /* first time configuration */
dev->data->tx_queues = rte_zmalloc("ethdev->tx_queues",
sizeof(dev->data->tx_queues[0]) * nb_queues,
- CACHE_LINE_SIZE);
+ RTE_CACHE_LINE_SIZE);
if (dev->data->tx_queues == NULL) {
dev->data->nb_tx_queues = 0;
return -(ENOMEM);
for (i = nb_queues; i < old_nb_queues; i++)
(*dev->dev_ops->tx_queue_release)(txq[i]);
txq = rte_realloc(txq, sizeof(txq[0]) * nb_queues,
- CACHE_LINE_SIZE);
+ RTE_CACHE_LINE_SIZE);
if (txq == NULL)
- return -(ENOMEM);
-
- if (nb_queues > old_nb_queues)
+ return -ENOMEM;
+ if (nb_queues > old_nb_queues) {
+ uint16_t new_qs = nb_queues - old_nb_queues;
memset(txq + old_nb_queues, 0,
- sizeof(txq[0]) * (nb_queues - old_nb_queues));
+ sizeof(txq[0]) * new_qs);
+ }
dev->data->tx_queues = txq;
return (0);
}
+static int
+rte_eth_dev_check_vf_rss_rxq_num(uint8_t port_id, uint16_t nb_rx_q)
+{
+ struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+ switch (nb_rx_q) {
+ case 1:
+ case 2:
+ RTE_ETH_DEV_SRIOV(dev).active =
+ ETH_64_POOLS;
+ break;
+ case 4:
+ RTE_ETH_DEV_SRIOV(dev).active =
+ ETH_32_POOLS;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool = nb_rx_q;
+ RTE_ETH_DEV_SRIOV(dev).def_pool_q_idx =
+ dev->pci_dev->max_vfs * nb_rx_q;
+
+ return 0;
+}
+
static int
rte_eth_dev_check_mq_mode(uint8_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
const struct rte_eth_conf *dev_conf)
if (RTE_ETH_DEV_SRIOV(dev).active != 0) {
/* check multi-queue mode */
- if ((dev_conf->rxmode.mq_mode == ETH_MQ_RX_RSS) ||
- (dev_conf->rxmode.mq_mode == ETH_MQ_RX_DCB) ||
+ if ((dev_conf->rxmode.mq_mode == ETH_MQ_RX_DCB) ||
(dev_conf->rxmode.mq_mode == ETH_MQ_RX_DCB_RSS) ||
(dev_conf->txmode.mq_mode == ETH_MQ_TX_DCB)) {
/* SRIOV only works in VMDq enable mode */
}
switch (dev_conf->rxmode.mq_mode) {
- case ETH_MQ_RX_VMDQ_RSS:
case ETH_MQ_RX_VMDQ_DCB:
case ETH_MQ_RX_VMDQ_DCB_RSS:
/* DCB/RSS VMDQ in SRIOV mode, not implement yet */
"unsupported VMDQ mq_mode rx %u\n",
port_id, dev_conf->rxmode.mq_mode);
return (-EINVAL);
+ case ETH_MQ_RX_RSS:
+ PMD_DEBUG_TRACE("ethdev port_id=%" PRIu8
+ " SRIOV active, "
+ "Rx mq mode is changed from:"
+ "mq_mode %u into VMDQ mq_mode %u\n",
+ port_id,
+ dev_conf->rxmode.mq_mode,
+ dev->data->dev_conf.rxmode.mq_mode);
+ case ETH_MQ_RX_VMDQ_RSS:
+ dev->data->dev_conf.rxmode.mq_mode = ETH_MQ_RX_VMDQ_RSS;
+ if (nb_rx_q <= RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool)
+ if (rte_eth_dev_check_vf_rss_rxq_num(port_id, nb_rx_q) != 0) {
+ PMD_DEBUG_TRACE("ethdev port_id=%d"
+ " SRIOV active, invalid queue"
+ " number for VMDQ RSS, allowed"
+ " value are 1, 2 or 4\n",
+ port_id);
+ return -EINVAL;
+ }
+ break;
default: /* ETH_MQ_RX_VMDQ_ONLY or ETH_MQ_RX_NONE */
/* if nothing mq mode configure, use default scheme */
dev->data->dev_conf.rxmode.mq_mode = ETH_MQ_RX_VMDQ_ONLY;
default: /* ETH_MQ_TX_VMDQ_ONLY or ETH_MQ_TX_NONE */
/* if nothing mq mode configure, use default scheme */
dev->data->dev_conf.txmode.mq_mode = ETH_MQ_TX_VMDQ_ONLY;
- if (RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool > 1)
- RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool = 1;
break;
}
* in a multi-process setup*/
PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY);
- if (port_id >= nb_ports || port_id >= RTE_MAX_ETHPORTS) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-EINVAL);
}
+
+ if (nb_rx_q > RTE_MAX_QUEUES_PER_PORT) {
+ PMD_DEBUG_TRACE(
+ "Number of RX queues requested (%u) is greater than max supported(%d)\n",
+ nb_rx_q, RTE_MAX_QUEUES_PER_PORT);
+ return (-EINVAL);
+ }
+
+ if (nb_tx_q > RTE_MAX_QUEUES_PER_PORT) {
+ PMD_DEBUG_TRACE(
+ "Number of TX queues requested (%u) is greater than max supported(%d)\n",
+ nb_tx_q, RTE_MAX_QUEUES_PER_PORT);
+ return (-EINVAL);
+ }
+
dev = &rte_eth_devices[port_id];
FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_infos_get, -ENOTSUP);
/* Copy the dev_conf parameter into the dev structure */
memcpy(&dev->data->dev_conf, dev_conf, sizeof(dev->data->dev_conf));
+ /*
+ * If link state interrupt is enabled, check that the
+ * device supports it.
+ */
+ if (dev_conf->intr_conf.lsc == 1) {
+ const struct rte_pci_driver *pci_drv = &dev->driver->pci_drv;
+
+ if (!(pci_drv->drv_flags & RTE_PCI_DRV_INTR_LSC)) {
+ PMD_DEBUG_TRACE("driver %s does not support lsc\n",
+ pci_drv->name);
+ return (-EINVAL);
+ }
+ }
+
/*
* If jumbo frames are enabled, check that the maximum RX packet
* length is supported by the configured device.
continue;
/* add address to the hardware */
- if (*dev->dev_ops->mac_addr_add)
+ if (*dev->dev_ops->mac_addr_add &&
+ (dev->data->mac_pool_sel[i] & (1ULL << pool)))
(*dev->dev_ops->mac_addr_add)(dev, &addr, i, pool);
else {
PMD_DEBUG_TRACE("port %d: MAC address array not supported\n",
* in a multi-process setup*/
PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY);
- if (port_id >= nb_ports) {
- PMD_DEBUG_TRACE("Invalid port_id=%" PRIu8 "\n", port_id);
+ if (!rte_eth_dev_is_valid_port(port_id)) {
+ PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-EINVAL);
}
+
dev = &rte_eth_devices[port_id];
FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_start, -ENOTSUP);
rte_eth_dev_config_restore(port_id);
+ if (dev->data->dev_conf.intr_conf.lsc != 0) {
+ FUNC_PTR_OR_ERR_RET(*dev->dev_ops->link_update, -ENOTSUP);
+ (*dev->dev_ops->link_update)(dev, 0);
+ }
return 0;
}
* in a multi-process setup*/
PROC_PRIMARY_OR_RET();
- if (port_id >= nb_ports) {
- PMD_DEBUG_TRACE("Invalid port_id=%" PRIu8 "\n", port_id);
+ if (!rte_eth_dev_is_valid_port(port_id)) {
+ PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return;
}
+
dev = &rte_eth_devices[port_id];
FUNC_PTR_OR_RET(*dev->dev_ops->dev_stop);
* in a multi-process setup*/
PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY);
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return -EINVAL;
}
+
dev = &rte_eth_devices[port_id];
FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_set_link_up, -ENOTSUP);
* in a multi-process setup*/
PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY);
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return -EINVAL;
}
+
dev = &rte_eth_devices[port_id];
FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_set_link_down, -ENOTSUP);
* in a multi-process setup*/
PROC_PRIMARY_OR_RET();
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return;
}
* in a multi-process setup*/
PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY);
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-EINVAL);
}
+
dev = &rte_eth_devices[port_id];
if (rx_queue_id >= dev->data->nb_rx_queues) {
PMD_DEBUG_TRACE("Invalid RX queue_id=%d\n", rx_queue_id);
* This value must be provided in the private data of the memory pool.
* First check that the memory pool has a valid private data.
*/
- (*dev->dev_ops->dev_infos_get)(dev, &dev_info);
+ rte_eth_dev_info_get(port_id, &dev_info);
if (mp->private_data_size < sizeof(struct rte_pktmbuf_pool_private)) {
PMD_DEBUG_TRACE("%s private_data_size %d < %d\n",
mp->name, (int) mp->private_data_size,
return (-EINVAL);
}
+ if (rx_conf == NULL)
+ rx_conf = &dev_info.default_rxconf;
+
ret = (*dev->dev_ops->rx_queue_setup)(dev, rx_queue_id, nb_rx_desc,
socket_id, rx_conf, mp);
if (!ret) {
const struct rte_eth_txconf *tx_conf)
{
struct rte_eth_dev *dev;
+ struct rte_eth_dev_info dev_info;
/* This function is only safe when called from the primary process
* in a multi-process setup*/
PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY);
- if (port_id >= RTE_MAX_ETHPORTS || port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-EINVAL);
}
+
dev = &rte_eth_devices[port_id];
if (tx_queue_id >= dev->data->nb_tx_queues) {
PMD_DEBUG_TRACE("Invalid TX queue_id=%d\n", tx_queue_id);
return -EBUSY;
}
+ FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_infos_get, -ENOTSUP);
FUNC_PTR_OR_ERR_RET(*dev->dev_ops->tx_queue_setup, -ENOTSUP);
+
+ rte_eth_dev_info_get(port_id, &dev_info);
+
+ if (tx_conf == NULL)
+ tx_conf = &dev_info.default_txconf;
+
return (*dev->dev_ops->tx_queue_setup)(dev, tx_queue_id, nb_tx_desc,
socket_id, tx_conf);
}
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return;
}
+
dev = &rte_eth_devices[port_id];
FUNC_PTR_OR_RET(*dev->dev_ops->promiscuous_enable);
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return;
}
+
dev = &rte_eth_devices[port_id];
FUNC_PTR_OR_RET(*dev->dev_ops->promiscuous_disable);
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return -1;
}
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return;
}
+
dev = &rte_eth_devices[port_id];
FUNC_PTR_OR_RET(*dev->dev_ops->allmulticast_enable);
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return;
}
+
dev = &rte_eth_devices[port_id];
FUNC_PTR_OR_RET(*dev->dev_ops->allmulticast_disable);
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return -1;
}
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return;
}
+
dev = &rte_eth_devices[port_id];
- FUNC_PTR_OR_RET(*dev->dev_ops->link_update);
if (dev->data->dev_conf.intr_conf.lsc != 0)
rte_eth_dev_atomic_read_link_status(dev, eth_link);
else {
+ FUNC_PTR_OR_RET(*dev->dev_ops->link_update);
(*dev->dev_ops->link_update)(dev, 1);
*eth_link = dev->data->dev_link;
}
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return;
}
+
dev = &rte_eth_devices[port_id];
- FUNC_PTR_OR_RET(*dev->dev_ops->link_update);
if (dev->data->dev_conf.intr_conf.lsc != 0)
rte_eth_dev_atomic_read_link_status(dev, eth_link);
else {
+ FUNC_PTR_OR_RET(*dev->dev_ops->link_update);
(*dev->dev_ops->link_update)(dev, 0);
*eth_link = dev->data->dev_link;
}
}
-void
+int
rte_eth_stats_get(uint8_t port_id, struct rte_eth_stats *stats)
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
- return;
+ return (-ENODEV);
}
+
dev = &rte_eth_devices[port_id];
memset(stats, 0, sizeof(*stats));
- FUNC_PTR_OR_RET(*dev->dev_ops->stats_get);
+ FUNC_PTR_OR_ERR_RET(*dev->dev_ops->stats_get, -ENOTSUP);
(*dev->dev_ops->stats_get)(dev, stats);
stats->rx_nombuf = dev->data->rx_mbuf_alloc_failed;
+ return 0;
}
void
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return;
}
+
dev = &rte_eth_devices[port_id];
FUNC_PTR_OR_RET(*dev->dev_ops->stats_reset);
(*dev->dev_ops->stats_reset)(dev);
}
+/* retrieve ethdev extended statistics */
+int
+rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
+ unsigned n)
+{
+ struct rte_eth_stats eth_stats;
+ struct rte_eth_dev *dev;
+ unsigned count, i, q;
+ uint64_t val;
+ char *stats_ptr;
+
+ if (!rte_eth_dev_is_valid_port(port_id)) {
+ PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+ return -1;
+ }
+
+ dev = &rte_eth_devices[port_id];
+
+ /* implemented by the driver */
+ if (dev->dev_ops->xstats_get != NULL)
+ return (*dev->dev_ops->xstats_get)(dev, xstats, n);
+
+ /* else, return generic statistics */
+ count = RTE_NB_STATS;
+ count += dev->data->nb_rx_queues * RTE_NB_RXQ_STATS;
+ count += dev->data->nb_tx_queues * RTE_NB_TXQ_STATS;
+ if (n < count)
+ return count;
+
+ /* now fill the xstats structure */
+
+ count = 0;
+ memset(ð_stats, 0, sizeof(eth_stats));
+ rte_eth_stats_get(port_id, ð_stats);
+
+ /* global stats */
+ for (i = 0; i < RTE_NB_STATS; i++) {
+ stats_ptr = (char *)ð_stats + rte_stats_strings[i].offset;
+ val = *(uint64_t *)stats_ptr;
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "%s", rte_stats_strings[i].name);
+ xstats[count++].value = val;
+ }
+
+ /* per-rxq stats */
+ for (q = 0; q < dev->data->nb_rx_queues; q++) {
+ for (i = 0; i < RTE_NB_RXQ_STATS; i++) {
+ stats_ptr = (char *)ð_stats;
+ stats_ptr += rte_rxq_stats_strings[i].offset;
+ stats_ptr += q * sizeof(uint64_t);
+ val = *(uint64_t *)stats_ptr;
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "rx_queue_%u_%s", q,
+ rte_rxq_stats_strings[i].name);
+ xstats[count++].value = val;
+ }
+ }
+
+ /* per-txq stats */
+ for (q = 0; q < dev->data->nb_tx_queues; q++) {
+ for (i = 0; i < RTE_NB_TXQ_STATS; i++) {
+ stats_ptr = (char *)ð_stats;
+ stats_ptr += rte_txq_stats_strings[i].offset;
+ stats_ptr += q * sizeof(uint64_t);
+ val = *(uint64_t *)stats_ptr;
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "tx_queue_%u_%s", q,
+ rte_txq_stats_strings[i].name);
+ xstats[count++].value = val;
+ }
+ }
+
+ return count;
+}
+
+/* reset ethdev extended statistics */
+void
+rte_eth_xstats_reset(uint8_t port_id)
+{
+ struct rte_eth_dev *dev;
+
+ if (!rte_eth_dev_is_valid_port(port_id)) {
+ PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+ return;
+ }
+
+ dev = &rte_eth_devices[port_id];
+
+ /* implemented by the driver */
+ if (dev->dev_ops->xstats_reset != NULL) {
+ (*dev->dev_ops->xstats_reset)(dev);
+ return;
+ }
+
+ /* fallback to default */
+ rte_eth_stats_reset(port_id);
+}
static int
set_queue_stats_mapping(uint8_t port_id, uint16_t queue_id, uint8_t stat_idx,
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return -ENODEV;
}
+
dev = &rte_eth_devices[port_id];
FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_stats_mapping_set, -ENOTSUP);
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return;
}
+
dev = &rte_eth_devices[port_id];
- /* Default device offload capabilities to zero */
- dev_info->rx_offload_capa = 0;
- dev_info->tx_offload_capa = 0;
- dev_info->if_index = 0;
+ memset(dev_info, 0, sizeof(struct rte_eth_dev_info));
+
FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
(*dev->dev_ops->dev_infos_get)(dev, dev_info);
dev_info->pci_dev = dev->pci_dev;
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return;
}
+
dev = &rte_eth_devices[port_id];
ether_addr_copy(&dev->data->mac_addrs[0], mac_addr);
}
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
int ret;
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
+
dev = &rte_eth_devices[port_id];
if (! (dev->data->dev_conf.rxmode.hw_vlan_filter)) {
PMD_DEBUG_TRACE("port %d: vlan-filtering disabled\n", port_id);
return (-EINVAL);
}
FUNC_PTR_OR_ERR_RET(*dev->dev_ops->vlan_filter_set, -ENOTSUP);
- (*dev->dev_ops->vlan_filter_set)(dev, vlan_id, on);
- return (0);
+
+ return (*dev->dev_ops->vlan_filter_set)(dev, vlan_id, on);
}
int
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
int mask = 0;
int cur, org = 0;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
struct rte_eth_dev *dev;
int ret = 0;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
+
dev = &rte_eth_devices[port_id];
FUNC_PTR_OR_ERR_RET(*dev->dev_ops->vlan_pvid_set, -ENOTSUP);
(*dev->dev_ops->vlan_pvid_set)(dev, pvid, on);
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
return (-ENOTSUP);
}
+static inline int
+rte_eth_check_reta_mask(struct rte_eth_rss_reta_entry64 *reta_conf,
+ uint16_t reta_size)
+{
+ uint16_t i, num;
+
+ if (!reta_conf)
+ return -EINVAL;
+
+ if (reta_size != RTE_ALIGN(reta_size, RTE_RETA_GROUP_SIZE)) {
+ PMD_DEBUG_TRACE("Invalid reta size, should be %u aligned\n",
+ RTE_RETA_GROUP_SIZE);
+ return -EINVAL;
+ }
+
+ num = reta_size / RTE_RETA_GROUP_SIZE;
+ for (i = 0; i < num; i++) {
+ if (reta_conf[i].mask)
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static inline int
+rte_eth_check_reta_entry(struct rte_eth_rss_reta_entry64 *reta_conf,
+ uint16_t reta_size,
+ uint8_t max_rxq)
+{
+ uint16_t i, idx, shift;
+
+ if (!reta_conf)
+ return -EINVAL;
+
+ if (max_rxq == 0) {
+ PMD_DEBUG_TRACE("No receive queue is available\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < reta_size; i++) {
+ idx = i / RTE_RETA_GROUP_SIZE;
+ shift = i % RTE_RETA_GROUP_SIZE;
+ if ((reta_conf[idx].mask & (1ULL << shift)) &&
+ (reta_conf[idx].reta[shift] >= max_rxq)) {
+ PMD_DEBUG_TRACE("reta_conf[%u]->reta[%u]: %u exceeds "
+ "the maximum rxq index: %u\n", idx, shift,
+ reta_conf[idx].reta[shift], max_rxq);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
int
-rte_eth_dev_rss_reta_update(uint8_t port_id, struct rte_eth_rss_reta *reta_conf)
+rte_eth_dev_rss_reta_update(uint8_t port_id,
+ struct rte_eth_rss_reta_entry64 *reta_conf,
+ uint16_t reta_size)
{
struct rte_eth_dev *dev;
- uint16_t max_rxq;
- uint8_t i,j;
+ int ret;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
- return (-ENODEV);
+ return -ENODEV;
}
- /* Invalid mask bit(s) setting */
- if ((reta_conf->mask_lo == 0) && (reta_conf->mask_hi == 0)) {
- PMD_DEBUG_TRACE("Invalid update mask bits for port=%d\n",port_id);
- return (-EINVAL);
- }
+ /* Check mask bits */
+ ret = rte_eth_check_reta_mask(reta_conf, reta_size);
+ if (ret < 0)
+ return ret;
dev = &rte_eth_devices[port_id];
- max_rxq = (dev->data->nb_rx_queues <= ETH_RSS_RETA_MAX_QUEUE) ?
- dev->data->nb_rx_queues : ETH_RSS_RETA_MAX_QUEUE;
- if (reta_conf->mask_lo != 0) {
- for (i = 0; i < ETH_RSS_RETA_NUM_ENTRIES/2; i++) {
- if ((reta_conf->mask_lo & (1ULL << i)) &&
- (reta_conf->reta[i] >= max_rxq)) {
- PMD_DEBUG_TRACE("RETA hash index output"
- "configration for port=%d,invalid"
- "queue=%d\n",port_id,reta_conf->reta[i]);
-
- return (-EINVAL);
- }
- }
- }
- if (reta_conf->mask_hi != 0) {
- for (i = 0; i< ETH_RSS_RETA_NUM_ENTRIES/2; i++) {
- j = (uint8_t)(i + ETH_RSS_RETA_NUM_ENTRIES/2);
-
- /* Check if the max entry >= 128 */
- if ((reta_conf->mask_hi & (1ULL << i)) &&
- (reta_conf->reta[j] >= max_rxq)) {
- PMD_DEBUG_TRACE("RETA hash index output"
- "configration for port=%d,invalid"
- "queue=%d\n",port_id,reta_conf->reta[j]);
-
- return (-EINVAL);
- }
- }
- }
+ /* Check entry value */
+ ret = rte_eth_check_reta_entry(reta_conf, reta_size,
+ dev->data->nb_rx_queues);
+ if (ret < 0)
+ return ret;
FUNC_PTR_OR_ERR_RET(*dev->dev_ops->reta_update, -ENOTSUP);
- return (*dev->dev_ops->reta_update)(dev, reta_conf);
+ return (*dev->dev_ops->reta_update)(dev, reta_conf, reta_size);
}
int
-rte_eth_dev_rss_reta_query(uint8_t port_id, struct rte_eth_rss_reta *reta_conf)
+rte_eth_dev_rss_reta_query(uint8_t port_id,
+ struct rte_eth_rss_reta_entry64 *reta_conf,
+ uint16_t reta_size)
{
struct rte_eth_dev *dev;
+ int ret;
if (port_id >= nb_ports) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
- return (-ENODEV);
+ return -ENODEV;
}
- if((reta_conf->mask_lo == 0) && (reta_conf->mask_hi == 0)) {
- PMD_DEBUG_TRACE("Invalid update mask bits for the port=%d\n",port_id);
- return (-EINVAL);
- }
+ /* Check mask bits */
+ ret = rte_eth_check_reta_mask(reta_conf, reta_size);
+ if (ret < 0)
+ return ret;
dev = &rte_eth_devices[port_id];
FUNC_PTR_OR_ERR_RET(*dev->dev_ops->reta_query, -ENOTSUP);
- return (*dev->dev_ops->reta_query)(dev, reta_conf);
+ return (*dev->dev_ops->reta_query)(dev, reta_conf, reta_size);
}
int
struct rte_eth_dev *dev;
uint16_t rss_hash_protos;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
+
rss_hash_protos = rss_conf->rss_hf;
if ((rss_hash_protos != 0) &&
((rss_hash_protos & ETH_RSS_PROTO_MASK) == 0)) {
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
+
dev = &rte_eth_devices[port_id];
FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rss_hash_conf_get, -ENOTSUP);
return (*dev->dev_ops->rss_hash_conf_get)(dev, rss_conf);
}
+int
+rte_eth_dev_udp_tunnel_add(uint8_t port_id,
+ struct rte_eth_udp_tunnel *udp_tunnel)
+{
+ struct rte_eth_dev *dev;
+
+ if (!rte_eth_dev_is_valid_port(port_id)) {
+ PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+ return -ENODEV;
+ }
+
+ if (udp_tunnel == NULL) {
+ PMD_DEBUG_TRACE("Invalid udp_tunnel parameter\n");
+ return -EINVAL;
+ }
+
+ if (udp_tunnel->prot_type >= RTE_TUNNEL_TYPE_MAX) {
+ PMD_DEBUG_TRACE("Invalid tunnel type\n");
+ return -EINVAL;
+ }
+
+ dev = &rte_eth_devices[port_id];
+ FUNC_PTR_OR_ERR_RET(*dev->dev_ops->udp_tunnel_add, -ENOTSUP);
+ return (*dev->dev_ops->udp_tunnel_add)(dev, udp_tunnel);
+}
+
+int
+rte_eth_dev_udp_tunnel_delete(uint8_t port_id,
+ struct rte_eth_udp_tunnel *udp_tunnel)
+{
+ struct rte_eth_dev *dev;
+
+ if (!rte_eth_dev_is_valid_port(port_id)) {
+ PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+ return -ENODEV;
+ }
+
+ dev = &rte_eth_devices[port_id];
+
+ if (udp_tunnel == NULL) {
+ PMD_DEBUG_TRACE("Invalid udp_tunnel parametr\n");
+ return -EINVAL;
+ }
+
+ if (udp_tunnel->prot_type >= RTE_TUNNEL_TYPE_MAX) {
+ PMD_DEBUG_TRACE("Invalid tunnel type\n");
+ return -EINVAL;
+ }
+
+ FUNC_PTR_OR_ERR_RET(*dev->dev_ops->udp_tunnel_del, -ENOTSUP);
+ return (*dev->dev_ops->udp_tunnel_del)(dev, udp_tunnel);
+}
+
int
rte_eth_led_on(uint8_t port_id)
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
int index;
uint64_t pool_mask;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
+
dev = &rte_eth_devices[port_id];
FUNC_PTR_OR_ERR_RET(*dev->dev_ops->mac_addr_add, -ENOTSUP);
struct rte_eth_dev *dev;
int index;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
+
dev = &rte_eth_devices[port_id];
FUNC_PTR_OR_ERR_RET(*dev->dev_ops->mac_addr_remove, -ENOTSUP);
/* Update address in NIC data structure */
ether_addr_copy(&null_mac_addr, &dev->data->mac_addrs[index]);
+ /* reset pool bitmap */
+ dev->data->mac_pool_sel[index] = 0;
+
return 0;
}
struct rte_eth_dev *dev;
struct rte_eth_dev_info dev_info;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("set VF RX mode:Invalid port_id=%d\n",
port_id);
return (-ENODEV);
int ret;
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("unicast hash setting:Invalid port_id=%d\n",
port_id);
return (-ENODEV);
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("unicast hash setting:Invalid port_id=%d\n",
port_id);
return (-ENODEV);
struct rte_eth_dev *dev;
struct rte_eth_dev_info dev_info;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
struct rte_eth_dev *dev;
struct rte_eth_dev_info dev_info;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("set pool tx:Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("VF VLAN filter:invalid port id=%d\n",
port_id);
return (-ENODEV);
struct rte_eth_dev_info dev_info;
struct rte_eth_link link;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("set queue rate limit:invalid port id=%d\n",
port_id);
return -ENODEV;
if (tx_rate > link.link_speed) {
PMD_DEBUG_TRACE("set queue rate limit:invalid tx_rate=%d, "
"bigger than link speed= %d\n",
- tx_rate, link_speed);
+ tx_rate, link.link_speed);
return -EINVAL;
}
if (q_msk == 0)
return 0;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("set VF rate limit:invalid port id=%d\n",
port_id);
return -ENODEV;
if (tx_rate > link.link_speed) {
PMD_DEBUG_TRACE("set VF rate limit:invalid tx_rate=%d, "
"bigger than link speed= %d\n",
- tx_rate, link_speed);
+ tx_rate, link.link_speed);
return -EINVAL;
}
{
struct rte_eth_dev *dev = &rte_eth_devices[port_id];
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
{
struct rte_eth_dev *dev = &rte_eth_devices[port_id];
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return 0;
}
+
dev = &rte_eth_devices[port_id];
- FUNC_PTR_OR_ERR_RET(*dev->rx_pkt_burst, -ENOTSUP);
+ FUNC_PTR_OR_ERR_RET(*dev->rx_pkt_burst, 0);
if (queue_id >= dev->data->nb_rx_queues) {
PMD_DEBUG_TRACE("Invalid RX queue_id=%d\n", queue_id);
return 0;
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return 0;
}
+
dev = &rte_eth_devices[port_id];
- FUNC_PTR_OR_ERR_RET(*dev->tx_pkt_burst, -ENOTSUP);
+ FUNC_PTR_OR_ERR_RET(*dev->tx_pkt_burst, 0);
if (queue_id >= dev->data->nb_tx_queues) {
PMD_DEBUG_TRACE("Invalid TX queue_id=%d\n", queue_id);
return 0;
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return 0;
}
+
dev = &rte_eth_devices[port_id];
- FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_queue_count, -ENOTSUP);
+ FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_queue_count, 0);
return (*dev->dev_ops->rx_queue_count)(dev, queue_id);
}
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
+
dev = &rte_eth_devices[port_id];
FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_descriptor_done, -ENOTSUP);
return (*dev->dev_ops->rx_descriptor_done)( \
if (!cb_fn)
return (-EINVAL);
- if (port_id >= nb_ports) {
+
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-EINVAL);
}
dev = &rte_eth_devices[port_id];
rte_spinlock_lock(&rte_eth_dev_cb_lock);
- TAILQ_FOREACH(user_cb, &(dev->callbacks), next) {
+ TAILQ_FOREACH(user_cb, &(dev->link_intr_cbs), next) {
if (user_cb->cb_fn == cb_fn &&
user_cb->cb_arg == cb_arg &&
user_cb->event == event) {
user_cb->cb_fn = cb_fn;
user_cb->cb_arg = cb_arg;
user_cb->event = event;
- TAILQ_INSERT_TAIL(&(dev->callbacks), user_cb, next);
+ TAILQ_INSERT_TAIL(&(dev->link_intr_cbs), user_cb, next);
}
rte_spinlock_unlock(&rte_eth_dev_cb_lock);
if (!cb_fn)
return (-EINVAL);
- if (port_id >= nb_ports) {
+
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-EINVAL);
}
rte_spinlock_lock(&rte_eth_dev_cb_lock);
ret = 0;
- for (cb = TAILQ_FIRST(&dev->callbacks); cb != NULL; cb = next) {
+ for (cb = TAILQ_FIRST(&dev->link_intr_cbs); cb != NULL; cb = next) {
next = TAILQ_NEXT(cb, next);
* then remove it.
*/
if (cb->active == 0) {
- TAILQ_REMOVE(&(dev->callbacks), cb, next);
+ TAILQ_REMOVE(&(dev->link_intr_cbs), cb, next);
rte_free(cb);
} else {
ret = -EAGAIN;
struct rte_eth_dev_callback dev_cb;
rte_spinlock_lock(&rte_eth_dev_cb_lock);
- TAILQ_FOREACH(cb_lst, &(dev->callbacks), next) {
+ TAILQ_FOREACH(cb_lst, &(dev->link_intr_cbs), next) {
if (cb_lst->cb_fn == NULL || cb_lst->event != event)
continue;
dev_cb = *cb_lst;
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return (-ENODEV);
}
#endif
int
-rte_eth_dev_add_syn_filter(uint8_t port_id,
- struct rte_syn_filter *filter, uint16_t rx_queue)
-{
- struct rte_eth_dev *dev;
-
- if (port_id >= nb_ports) {
- PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
- return -ENODEV;
- }
-
- dev = &rte_eth_devices[port_id];
- FUNC_PTR_OR_ERR_RET(*dev->dev_ops->add_syn_filter, -ENOTSUP);
- return (*dev->dev_ops->add_syn_filter)(dev, filter, rx_queue);
-}
-
-int
-rte_eth_dev_remove_syn_filter(uint8_t port_id)
-{
- struct rte_eth_dev *dev;
-
- if (port_id >= nb_ports) {
- PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
- return -ENODEV;
- }
-
- dev = &rte_eth_devices[port_id];
- FUNC_PTR_OR_ERR_RET(*dev->dev_ops->remove_syn_filter, -ENOTSUP);
- return (*dev->dev_ops->remove_syn_filter)(dev);
-}
-
-int
-rte_eth_dev_get_syn_filter(uint8_t port_id,
- struct rte_syn_filter *filter, uint16_t *rx_queue)
+rte_eth_dev_filter_supported(uint8_t port_id, enum rte_filter_type filter_type)
{
struct rte_eth_dev *dev;
- if (filter == NULL || rx_queue == NULL)
- return -EINVAL;
-
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return -ENODEV;
}
dev = &rte_eth_devices[port_id];
- FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_syn_filter, -ENOTSUP);
- return (*dev->dev_ops->get_syn_filter)(dev, filter, rx_queue);
-}
-
-int
-rte_eth_dev_add_ethertype_filter(uint8_t port_id, uint16_t index,
- struct rte_ethertype_filter *filter, uint16_t rx_queue)
-{
- struct rte_eth_dev *dev;
-
- if (port_id >= nb_ports) {
- PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
- return -ENODEV;
- }
- if (filter->ethertype == ETHER_TYPE_IPv4 ||
- filter->ethertype == ETHER_TYPE_IPv6){
- PMD_DEBUG_TRACE("IP and IPv6 are not supported"
- " in ethertype filter\n");
- return -EINVAL;
- }
- dev = &rte_eth_devices[port_id];
- FUNC_PTR_OR_ERR_RET(*dev->dev_ops->add_ethertype_filter, -ENOTSUP);
- return (*dev->dev_ops->add_ethertype_filter)(dev, index,
- filter, rx_queue);
+ FUNC_PTR_OR_ERR_RET(*dev->dev_ops->filter_ctrl, -ENOTSUP);
+ return (*dev->dev_ops->filter_ctrl)(dev, filter_type,
+ RTE_ETH_FILTER_NOP, NULL);
}
int
-rte_eth_dev_remove_ethertype_filter(uint8_t port_id, uint16_t index)
+rte_eth_dev_filter_ctrl(uint8_t port_id, enum rte_filter_type filter_type,
+ enum rte_filter_op filter_op, void *arg)
{
struct rte_eth_dev *dev;
- if (port_id >= nb_ports) {
+ if (!rte_eth_dev_is_valid_port(port_id)) {
PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
return -ENODEV;
}
dev = &rte_eth_devices[port_id];
- FUNC_PTR_OR_ERR_RET(*dev->dev_ops->remove_ethertype_filter, -ENOTSUP);
- return (*dev->dev_ops->remove_ethertype_filter)(dev, index);
+ FUNC_PTR_OR_ERR_RET(*dev->dev_ops->filter_ctrl, -ENOTSUP);
+ return (*dev->dev_ops->filter_ctrl)(dev, filter_type, filter_op, arg);
}
-int
-rte_eth_dev_get_ethertype_filter(uint8_t port_id, uint16_t index,
- struct rte_ethertype_filter *filter, uint16_t *rx_queue)
+void *
+rte_eth_add_rx_callback(uint8_t port_id, uint16_t queue_id,
+ rte_rx_callback_fn fn, void *user_param)
{
- struct rte_eth_dev *dev;
-
- if (filter == NULL || rx_queue == NULL)
- return -EINVAL;
-
- if (port_id >= nb_ports) {
- PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
- return -ENODEV;
+#ifndef RTE_ETHDEV_RXTX_CALLBACKS
+ rte_errno = ENOTSUP;
+ return NULL;
+#endif
+ /* check input parameters */
+ if (!rte_eth_dev_is_valid_port(port_id) || fn == NULL ||
+ queue_id >= rte_eth_devices[port_id].data->nb_rx_queues) {
+ rte_errno = EINVAL;
+ return NULL;
}
- dev = &rte_eth_devices[port_id];
- FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_ethertype_filter, -ENOTSUP);
- return (*dev->dev_ops->get_ethertype_filter)(dev, index,
- filter, rx_queue);
-}
-
-int
-rte_eth_dev_add_2tuple_filter(uint8_t port_id, uint16_t index,
- struct rte_2tuple_filter *filter, uint16_t rx_queue)
-{
- struct rte_eth_dev *dev;
+ struct rte_eth_rxtx_callback *cb = rte_zmalloc(NULL, sizeof(*cb), 0);
- if (port_id >= nb_ports) {
- PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
- return -ENODEV;
- }
- if (filter->protocol != IPPROTO_TCP &&
- filter->tcp_flags != 0){
- PMD_DEBUG_TRACE("tcp flags is 0x%x, but the protocol value"
- " is not TCP\n",
- filter->tcp_flags);
- return -EINVAL;
+ if (cb == NULL) {
+ rte_errno = ENOMEM;
+ return NULL;
}
- dev = &rte_eth_devices[port_id];
- FUNC_PTR_OR_ERR_RET(*dev->dev_ops->add_2tuple_filter, -ENOTSUP);
- return (*dev->dev_ops->add_2tuple_filter)(dev, index, filter, rx_queue);
+ cb->fn.rx = fn;
+ cb->param = user_param;
+ cb->next = rte_eth_devices[port_id].post_rx_burst_cbs[queue_id];
+ rte_eth_devices[port_id].post_rx_burst_cbs[queue_id] = cb;
+ return cb;
}
-int
-rte_eth_dev_remove_2tuple_filter(uint8_t port_id, uint16_t index)
+void *
+rte_eth_add_tx_callback(uint8_t port_id, uint16_t queue_id,
+ rte_tx_callback_fn fn, void *user_param)
{
- struct rte_eth_dev *dev;
-
- if (port_id >= nb_ports) {
- PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
- return -ENODEV;
+#ifndef RTE_ETHDEV_RXTX_CALLBACKS
+ rte_errno = ENOTSUP;
+ return NULL;
+#endif
+ /* check input parameters */
+ if (!rte_eth_dev_is_valid_port(port_id) || fn == NULL ||
+ queue_id >= rte_eth_devices[port_id].data->nb_tx_queues) {
+ rte_errno = EINVAL;
+ return NULL;
}
- dev = &rte_eth_devices[port_id];
- FUNC_PTR_OR_ERR_RET(*dev->dev_ops->remove_2tuple_filter, -ENOTSUP);
- return (*dev->dev_ops->remove_2tuple_filter)(dev, index);
-}
-
-int
-rte_eth_dev_get_2tuple_filter(uint8_t port_id, uint16_t index,
- struct rte_2tuple_filter *filter, uint16_t *rx_queue)
-{
- struct rte_eth_dev *dev;
-
- if (filter == NULL || rx_queue == NULL)
- return -EINVAL;
+ struct rte_eth_rxtx_callback *cb = rte_zmalloc(NULL, sizeof(*cb), 0);
- if (port_id >= nb_ports) {
- PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
- return -ENODEV;
+ if (cb == NULL) {
+ rte_errno = ENOMEM;
+ return NULL;
}
- dev = &rte_eth_devices[port_id];
- FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_2tuple_filter, -ENOTSUP);
- return (*dev->dev_ops->get_2tuple_filter)(dev, index, filter, rx_queue);
+ cb->fn.tx = fn;
+ cb->param = user_param;
+ cb->next = rte_eth_devices[port_id].pre_tx_burst_cbs[queue_id];
+ rte_eth_devices[port_id].pre_tx_burst_cbs[queue_id] = cb;
+ return cb;
}
int
-rte_eth_dev_add_5tuple_filter(uint8_t port_id, uint16_t index,
- struct rte_5tuple_filter *filter, uint16_t rx_queue)
+rte_eth_remove_rx_callback(uint8_t port_id, uint16_t queue_id,
+ struct rte_eth_rxtx_callback *user_cb)
{
- struct rte_eth_dev *dev;
-
- if (port_id >= nb_ports) {
- PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
- return -ENODEV;
- }
-
- if (filter->protocol != IPPROTO_TCP &&
- filter->tcp_flags != 0){
- PMD_DEBUG_TRACE("tcp flags is 0x%x, but the protocol value"
- " is not TCP\n",
- filter->tcp_flags);
- return -EINVAL;
+#ifndef RTE_ETHDEV_RXTX_CALLBACKS
+ return (-ENOTSUP);
+#endif
+ /* Check input parameters. */
+ if (!rte_eth_dev_is_valid_port(port_id) || user_cb == NULL ||
+ queue_id >= rte_eth_devices[port_id].data->nb_rx_queues) {
+ return (-EINVAL);
}
- dev = &rte_eth_devices[port_id];
- FUNC_PTR_OR_ERR_RET(*dev->dev_ops->add_5tuple_filter, -ENOTSUP);
- return (*dev->dev_ops->add_5tuple_filter)(dev, index, filter, rx_queue);
-}
-
-int
-rte_eth_dev_remove_5tuple_filter(uint8_t port_id, uint16_t index)
-{
- struct rte_eth_dev *dev;
+ struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+ struct rte_eth_rxtx_callback *cb = dev->post_rx_burst_cbs[queue_id];
+ struct rte_eth_rxtx_callback *prev_cb;
- if (port_id >= nb_ports) {
- PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
- return -ENODEV;
+ /* Reset head pointer and remove user cb if first in the list. */
+ if (cb == user_cb) {
+ dev->post_rx_burst_cbs[queue_id] = user_cb->next;
+ return 0;
}
- dev = &rte_eth_devices[port_id];
- FUNC_PTR_OR_ERR_RET(*dev->dev_ops->remove_5tuple_filter, -ENOTSUP);
- return (*dev->dev_ops->remove_5tuple_filter)(dev, index);
-}
-
-int
-rte_eth_dev_get_5tuple_filter(uint8_t port_id, uint16_t index,
- struct rte_5tuple_filter *filter, uint16_t *rx_queue)
-{
- struct rte_eth_dev *dev;
+ /* Remove the user cb from the callback list. */
+ do {
+ prev_cb = cb;
+ cb = cb->next;
- if (filter == NULL || rx_queue == NULL)
- return -EINVAL;
+ if (cb == user_cb) {
+ prev_cb->next = user_cb->next;
+ return 0;
+ }
- if (port_id >= nb_ports) {
- PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
- return -ENODEV;
- }
+ } while (cb != NULL);
- dev = &rte_eth_devices[port_id];
- FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_5tuple_filter, -ENOTSUP);
- return (*dev->dev_ops->get_5tuple_filter)(dev, index, filter,
- rx_queue);
+ /* Callback wasn't found. */
+ return (-EINVAL);
}
int
-rte_eth_dev_add_flex_filter(uint8_t port_id, uint16_t index,
- struct rte_flex_filter *filter, uint16_t rx_queue)
+rte_eth_remove_tx_callback(uint8_t port_id, uint16_t queue_id,
+ struct rte_eth_rxtx_callback *user_cb)
{
- struct rte_eth_dev *dev;
-
- if (port_id >= nb_ports) {
- PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
- return -ENODEV;
+#ifndef RTE_ETHDEV_RXTX_CALLBACKS
+ return (-ENOTSUP);
+#endif
+ /* Check input parameters. */
+ if (!rte_eth_dev_is_valid_port(port_id) || user_cb == NULL ||
+ queue_id >= rte_eth_devices[port_id].data->nb_tx_queues) {
+ return (-EINVAL);
}
- dev = &rte_eth_devices[port_id];
- FUNC_PTR_OR_ERR_RET(*dev->dev_ops->add_flex_filter, -ENOTSUP);
- return (*dev->dev_ops->add_flex_filter)(dev, index, filter, rx_queue);
-}
-
-int
-rte_eth_dev_remove_flex_filter(uint8_t port_id, uint16_t index)
-{
- struct rte_eth_dev *dev;
+ struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+ struct rte_eth_rxtx_callback *cb = dev->pre_tx_burst_cbs[queue_id];
+ struct rte_eth_rxtx_callback *prev_cb;
- if (port_id >= nb_ports) {
- PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
- return -ENODEV;
+ /* Reset head pointer and remove user cb if first in the list. */
+ if (cb == user_cb) {
+ dev->pre_tx_burst_cbs[queue_id] = user_cb->next;
+ return 0;
}
- dev = &rte_eth_devices[port_id];
- FUNC_PTR_OR_ERR_RET(*dev->dev_ops->remove_flex_filter, -ENOTSUP);
- return (*dev->dev_ops->remove_flex_filter)(dev, index);
-}
-
-int
-rte_eth_dev_get_flex_filter(uint8_t port_id, uint16_t index,
- struct rte_flex_filter *filter, uint16_t *rx_queue)
-{
- struct rte_eth_dev *dev;
+ /* Remove the user cb from the callback list. */
+ do {
+ prev_cb = cb;
+ cb = cb->next;
- if (filter == NULL || rx_queue == NULL)
- return -EINVAL;
+ if (cb == user_cb) {
+ prev_cb->next = user_cb->next;
+ return 0;
+ }
- if (port_id >= nb_ports) {
- PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
- return -ENODEV;
- }
+ } while (cb != NULL);
- dev = &rte_eth_devices[port_id];
- FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_flex_filter, -ENOTSUP);
- return (*dev->dev_ops->get_flex_filter)(dev, index, filter,
- rx_queue);
+ /* Callback wasn't found. */
+ return (-EINVAL);
}