@@ -1276,6 +1276,13 @@ F: doc/guides/rawdevs/ntb.rst
F: examples/ntb/
F: doc/guides/sample_app_ug/ntb.rst
+Emudev Drivers
+--------------
+
+Intel iavf
+M: Chenbo Xia <chenbo.xia@intel.com>
+M: Xiuchun Lu <xiuchun.lu@intel.com>
+F: drivers/emulation/iavf/
Packet processing
-----------------
new file mode 100644
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Intel Corporation
+ */
+
+#include "iavf_emu_internal.h"
+
+static int
+iavf_emu_dev_close(struct rte_emudev *dev)
+{
+ struct iavf_emudev *iavf;
+
+ /* For now, we don't support device close when data
+ * path driver is attached
+ */
+ if (dev->backend_priv) {
+ EMU_IAVF_LOG(ERR, "Close failed because of "
+ "data path attached\n");
+ return -EPERM;
+ }
+
+ iavf = (struct iavf_emudev *)dev->priv_data;
+ iavf_emu_uninit_device(iavf);
+ dev->priv_data = NULL;
+
+ return 0;
+}
+
+struct rte_emudev_ops emu_iavf_ops = {
+ .dev_close = iavf_emu_dev_close,
+};
new file mode 100644
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Intel Corporation
+ */
+
+#ifndef _IAVF_EMU_ITNL_H
+#define _IAVF_EMU_ITNL_H
+
+#include <stdint.h>
+
+#include <rte_log.h>
+
+#include "rte_iavf_emu.h"
+
+extern struct rte_emudev_ops emu_iavf_ops;
+
+extern int emu_iavf_logtype;
+#define EMU_IAVF_LOG(level, ...) \
+ rte_log(RTE_LOG_ ## level, emu_iavf_logtype, "EMU_IAVF: " __VA_ARGS__)
+
+struct iavf_emu_intr_info {
+ int enable;
+ int fd;
+};
+
+struct iavf_emu_intr {
+ uint32_t intr_num;
+ struct iavf_emu_intr_info info[RTE_IAVF_EMU_MAX_INTR];
+};
+
+struct iavf_emu_lanQ {
+ uint16_t db_size;
+ void *doorbell;
+};
+
+struct iavf_emudev {
+ struct rte_emudev *edev;
+ /* Maximum LANQ queue pair that this emulated iavf has */
+ uint16_t max_lanqp;
+ /* Maximum LANQ queue pair number that back-end driver can use */
+ uint16_t max_be_lanqp;
+ unsigned int numa_node;
+ char *sock_addr;
+ struct rte_iavf_emu_mem *mem;
+ struct iavf_emu_intr *intr;
+ struct iavf_emu_lanQ *lanq;
+};
+
+void iavf_emu_uninit_device(struct iavf_emudev *dev);
+#endif
new file mode 100644
@@ -0,0 +1,209 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Intel Corporation
+ */
+
+#include <rte_kvargs.h>
+#include <rte_emudev.h>
+#include <rte_emudev_vdev.h>
+
+#include "iavf_emu_internal.h"
+
+#define EMU_IAVF_SOCK_ARG "sock"
+#define EMU_IAVF_QUEUES_ARG "queues"
+
+static const char * const emu_iavf_valid_arg[] = {
+ EMU_IAVF_SOCK_ARG,
+ EMU_IAVF_QUEUES_ARG,
+ NULL
+};
+
+static inline int
+save_sockaddr(const char *key __rte_unused, const char *value,
+ void *extra_args)
+{
+ const char **sock_addr = extra_args;
+
+ if (value == NULL)
+ return -1;
+
+ *sock_addr = value;
+
+ return 0;
+}
+
+static inline int
+save_int(const char *key __rte_unused, const char *value, void *extra_args)
+{
+ uint16_t *n = extra_args;
+
+ if (value == NULL || extra_args == NULL)
+ return -EINVAL;
+
+ *n = (uint16_t)strtoul(value, NULL, 0);
+ if (*n == USHRT_MAX && errno == ERANGE)
+ return -1;
+
+ return 0;
+}
+
+static int
+iavf_emu_init_device(struct iavf_emudev *dev,
+ char *sock_addr, uint16_t queues, unsigned int numa_node)
+{
+ dev->sock_addr = rte_malloc_socket("sock_addr",
+ strlen(sock_addr) + 1, 0, numa_node);
+ if (!dev->sock_addr) {
+ EMU_IAVF_LOG(ERR, "Failed to alloc sock addr\n");
+ goto exit;
+ }
+ strcpy(dev->sock_addr, sock_addr);
+
+ dev->mem = rte_zmalloc_socket("iavf_emu_mem",
+ sizeof(struct rte_iavf_emu_mem),
+ 0, numa_node);
+ if (!dev->mem) {
+ EMU_IAVF_LOG(ERR, "Unable to alloc iavf_emu_mem.\n");
+ goto err_mem;
+ }
+
+ dev->intr = rte_zmalloc_socket("iavf_emu_intr",
+ sizeof(struct iavf_emu_intr),
+ 0, numa_node);
+ if (!dev->intr) {
+ EMU_IAVF_LOG(ERR, "Unable to alloc iavf_emu_intr.\n");
+ goto err_intr;
+ }
+
+ dev->lanq = rte_zmalloc_socket("iavf_emu_lanQ",
+ sizeof(struct iavf_emu_lanQ) * queues * 2,
+ 0, numa_node);
+ if (!dev->lanq) {
+ EMU_IAVF_LOG(ERR, "Unable to alloc iavf_emu_lanQ.\n");
+ goto err_lanq;
+ }
+
+ dev->numa_node = numa_node;
+
+ return 0;
+
+err_lanq:
+ rte_free(dev->lanq);
+err_intr:
+ rte_free(dev->intr);
+err_mem:
+ rte_free(dev->sock_addr);
+exit:
+ return -1;
+}
+
+void
+iavf_emu_uninit_device(struct iavf_emudev *dev)
+{
+ rte_free(dev->sock_addr);
+ rte_free(dev->mem);
+ rte_free(dev->intr);
+ rte_free(dev->lanq);
+}
+
+static int
+rte_emu_iavf_probe(struct rte_vdev_device *dev)
+{
+ struct rte_kvargs *kvlist = NULL;
+ struct rte_emudev *edev;
+ struct iavf_emudev *iavf;
+ char *sock_addr;
+ uint16_t queues;
+ int ret = 0;
+
+ kvlist = rte_kvargs_parse(rte_vdev_device_args(dev),
+ emu_iavf_valid_arg);
+ if (kvlist == NULL)
+ return -1;
+
+ if (rte_kvargs_count(kvlist, EMU_IAVF_SOCK_ARG) == 1) {
+ ret = rte_kvargs_process(kvlist, EMU_IAVF_SOCK_ARG,
+ &save_sockaddr, &sock_addr);
+ if (ret < 0)
+ goto err;
+ } else {
+ ret = -1;
+ goto err;
+ }
+
+ if (rte_kvargs_count(kvlist, EMU_IAVF_QUEUES_ARG) == 1) {
+ ret = rte_kvargs_process(kvlist, EMU_IAVF_QUEUES_ARG,
+ &save_int, &queues);
+ if (ret < 0 || queues > RTE_MAX_QUEUES_PER_PORT ||
+ queues > RTE_IAVF_EMU_MAX_QP_NUM)
+ goto err;
+
+ } else
+ queues = 1;
+
+ if (dev->device.numa_node == SOCKET_ID_ANY)
+ dev->device.numa_node = rte_socket_id();
+
+ edev = rte_emu_vdev_allocate(dev, sizeof(*iavf));
+ if (!edev) {
+ EMU_IAVF_LOG(ERR, "Failed to allocate emu_vdev\n");
+ ret = -1;
+ goto err;
+ }
+ edev->dev_ops = &emu_iavf_ops;
+ edev->dev_info.region_num = RTE_IAVF_EMU_MAPPABLE_REG_NUM;
+ edev->dev_info.max_qp_num = queues + RTE_IAVF_EMU_ADMINQ_NUM / 2;
+
+ strcpy(edev->dev_info.dev_type, RTE_IAVF_EMUDEV_TYPE);
+
+ iavf = (struct iavf_emudev *)edev->priv_data;
+ ret = iavf_emu_init_device(iavf, sock_addr, queues,
+ dev->device.numa_node);
+ if (ret) {
+ EMU_IAVF_LOG(ERR, "Failed to init new iavf device\n");
+ ret = -1;
+ goto err_ndev;
+ }
+
+ iavf->edev = edev;
+ /* If not configured, we assume back-end driver
+ * can use all queues of emulated iavf
+ */
+ iavf->max_be_lanqp = queues;
+ iavf->max_lanqp = queues;
+ edev->priv_data = (void *)iavf;
+
+ edev->started = 1;
+ rte_kvargs_free(kvlist);
+ return 0;
+
+err_ndev:
+ rte_emudev_release(edev);
+err:
+ rte_kvargs_free(kvlist);
+ return ret;
+}
+
+static int
+rte_emu_iavf_remove(struct rte_vdev_device *dev)
+{
+ struct rte_emudev *emu_dev;
+
+ /* Find the emudev entry */
+ emu_dev = rte_emudev_allocated(rte_vdev_device_name(dev));
+ if (!emu_dev)
+ return 0;
+
+ return rte_emudev_close(emu_dev->dev_id);
+}
+
+static struct rte_vdev_driver emu_iavf_drv = {
+ .probe = rte_emu_iavf_probe,
+ .remove = rte_emu_iavf_remove,
+};
+
+RTE_PMD_REGISTER_VDEV(emu_iavf, emu_iavf_drv);
+RTE_PMD_REGISTER_PARAM_STRING(emu_iavf,
+ "sock=<path> "
+ "queues=<int> ");
+
+RTE_LOG_REGISTER(emu_iavf_logtype, emu.iavf, INFO);
new file mode 100644
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2020 Intel Corporation
+
+sources = files('iavf_emu.c', 'iavf_emudev.c')
+
+deps += ['bus_vdev', 'emudev']
+
+headers = files('rte_iavf_emu.h')
new file mode 100644
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Intel Corporation
+ */
+
+#ifndef _IAVF_EMU_H
+#define _IAVF_EMU_H
+
+#include <stdint.h>
+
+#include <rte_emudev.h>
+
+#define RTE_IAVF_EMUDEV_TYPE "iavf"
+#define RTE_IAVF_EMU_MAX_MEM_REGIONS 256
+#define RTE_IAVF_EMU_MAX_QP_NUM 256
+#define RTE_IAVF_EMU_MAX_INTR 32
+
+enum {
+ RTE_IAVF_EMU_ADMINQ_TXQ = 0,
+ RTE_IAVF_EMU_ADMINQ_RXQ = 1,
+ RTE_IAVF_EMU_ADMINQ_NUM = 2,
+};
+
+enum {
+ RTE_IAVF_EMU_MAPPABLE_REG_BAR0 = 0,
+ RTE_IAVF_EMU_MAPPABLE_REG_BAR3 = 1,
+ RTE_IAVF_EMU_MAPPABLE_REG_NUM = 2,
+};
+
+struct rte_iavf_emu_mem_reg {
+ uint64_t guest_phys_addr;
+ uint64_t host_user_addr;
+ uint64_t size;
+ void *mmap_addr;
+ uint64_t mmap_size;
+ int fd;
+};
+
+struct rte_iavf_emu_mem {
+ uint32_t region_num;
+ struct rte_iavf_emu_mem_reg regions[RTE_IAVF_EMU_MAX_MEM_REGIONS];
+};
+
+#endif
new file mode 100644
@@ -0,0 +1,3 @@
+DPDK_21 {
+ local: *;
+};
new file mode 100644
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2020 Intel Corporation
+
+drivers = ['iavf']
+std_deps = ['emudev']
+config_flag_fmt = 'RTE_LIBRTE_PMD_@0@_EMUDEV'
@@ -8,6 +8,7 @@ subdirs = [
'common/mlx5', # depends on bus.
'common/qat', # depends on bus.
'mempool', # depends on common and bus.
+ 'emu', # depends on common and bus.
'net', # depends on common, bus, mempool
'raw', # depends on common, bus and net.
'crypto', # depends on common, bus and mempool (net in future).