get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/85489/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 85489,
    "url": "https://patches.dpdk.org/api/patches/85489/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20201219062806.56477-2-chenbo.xia@intel.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20201219062806.56477-2-chenbo.xia@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20201219062806.56477-2-chenbo.xia@intel.com",
    "date": "2020-12-19T06:27:59",
    "name": "[v2,1/8] lib: introduce emudev library",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "e24dac855b86862036dca43df8c6b12286792827",
    "submitter": {
        "id": 1276,
        "url": "https://patches.dpdk.org/api/people/1276/?format=api",
        "name": "Chenbo Xia",
        "email": "chenbo.xia@intel.com"
    },
    "delegate": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20201219062806.56477-2-chenbo.xia@intel.com/mbox/",
    "series": [
        {
            "id": 14383,
            "url": "https://patches.dpdk.org/api/series/14383/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=14383",
            "date": "2020-12-19T06:27:58",
            "name": "Introduce emudev library and iavf emudev driver",
            "version": 2,
            "mbox": "https://patches.dpdk.org/series/14383/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/85489/comments/",
    "check": "warning",
    "checks": "https://patches.dpdk.org/api/patches/85489/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id D30BEA04B5;\n\tSat, 19 Dec 2020 07:43:35 +0100 (CET)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 36EA5CB05;\n\tSat, 19 Dec 2020 07:43:18 +0100 (CET)",
            "from mga18.intel.com (mga18.intel.com [134.134.136.126])\n by dpdk.org (Postfix) with ESMTP id 3B77CCACA\n for <dev@dpdk.org>; Sat, 19 Dec 2020 07:43:15 +0100 (CET)",
            "from fmsmga001.fm.intel.com ([10.253.24.23])\n by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 18 Dec 2020 22:43:14 -0800",
            "from npg-dpdk-virtio-xiachenbo-nw.sh.intel.com ([10.67.119.123])\n by fmsmga001.fm.intel.com with ESMTP; 18 Dec 2020 22:43:12 -0800"
        ],
        "IronPort-SDR": [
            "\n Tii5bxe0/qrnHtFVPWriqZgsgIawdj2P2d/SVOXvcMDS+lcbA8R+2DPa7RM6FpnGU3UMhK2ujJ\n dyUoK9nvJJ6Q==",
            "\n 3lAetFPIbCmAhxXLHmbjerLWKOMI8FTPZJsfHKL+F/wmBmUzR8FrP/BdLvEWuHFSEJBJCj1CzK\n M+x9AyT/t1wg=="
        ],
        "X-IronPort-AV": [
            "E=McAfee;i=\"6000,8403,9839\"; a=\"163285186\"",
            "E=Sophos;i=\"5.78,432,1599548400\"; d=\"scan'208\";a=\"163285186\"",
            "E=Sophos;i=\"5.78,432,1599548400\"; d=\"scan'208\";a=\"454449594\""
        ],
        "X-ExtLoop1": "1",
        "From": "Chenbo Xia <chenbo.xia@intel.com>",
        "To": "dev@dpdk.org,\n\tthomas@monjalon.net,\n\tdavid.marchand@redhat.com",
        "Cc": "stephen@networkplumber.org, cunming.liang@intel.com, xiuchun.lu@intel.com,\n miao.li@intel.com, jingjing.wu@intel.com",
        "Date": "Sat, 19 Dec 2020 14:27:59 +0800",
        "Message-Id": "<20201219062806.56477-2-chenbo.xia@intel.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<20201219062806.56477-1-chenbo.xia@intel.com>",
        "References": "<20201218074736.93999-1-chenbo.xia@intel.com>\n <20201219062806.56477-1-chenbo.xia@intel.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=UTF-8",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[dpdk-dev] [PATCH v2 1/8] lib: introduce emudev library",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "This patch introduces the emudev library. Emudev library is used\nto abstract an emulated device, whose type could be general\n(e.g., network, crypto and etc.). Several device-level APIs are\nimplemented to use or manipulate the device. It can be attached\nto another data path driver (e.g., ethdev driver) to plug in its\nhigh performance data path.\n\nSigned-off-by: Chenbo Xia <chenbo.xia@intel.com>\nSigned-off-by: Xiuchun Lu <xiuchun.lu@intel.com>\nSigned-off-by: Miao Li <miao.li@intel.com>\n---\n MAINTAINERS                         |   5 +\n lib/librte_emudev/meson.build       |   5 +\n lib/librte_emudev/rte_emudev.c      | 486 ++++++++++++++++++++++++++++\n lib/librte_emudev/rte_emudev.h      | 410 +++++++++++++++++++++++\n lib/librte_emudev/rte_emudev_vdev.h |  53 +++\n lib/librte_emudev/version.map       |  27 ++\n lib/meson.build                     |   2 +-\n 7 files changed, 987 insertions(+), 1 deletion(-)\n create mode 100644 lib/librte_emudev/meson.build\n create mode 100644 lib/librte_emudev/rte_emudev.c\n create mode 100644 lib/librte_emudev/rte_emudev.h\n create mode 100644 lib/librte_emudev/rte_emudev_vdev.h\n create mode 100644 lib/librte_emudev/version.map",
    "diff": "diff --git a/MAINTAINERS b/MAINTAINERS\nindex 5fb4880758..1b395e181d 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -1545,6 +1545,11 @@ M: Chenbo Xia <chenbo.xia@intel.com>\n M: Xiuchun Lu <xiuchun.lu@intel.com>\n F: lib/librte_vfio_user/\n \n+Emudev - EXPERIMENTAL\n+M: Chenbo Xia <chenbo.xia@intel.com>\n+M: Xiuchun Lu <xiuchun.lu@intel.com>\n+F: lib/librte_emudev/\n+\n Test Applications\n -----------------\n \ndiff --git a/lib/librte_emudev/meson.build b/lib/librte_emudev/meson.build\nnew file mode 100644\nindex 0000000000..4e16cecbaf\n--- /dev/null\n+++ b/lib/librte_emudev/meson.build\n@@ -0,0 +1,5 @@\n+# SPDX-License-Identifier: BSD-3-Clause\n+# Copyright(c) 2020 Intel Corporation\n+\n+sources = files('rte_emudev.c')\n+headers = files('rte_emudev.h', 'rte_emudev_vdev.h')\ndiff --git a/lib/librte_emudev/rte_emudev.c b/lib/librte_emudev/rte_emudev.c\nnew file mode 100644\nindex 0000000000..2bbf3970d8\n--- /dev/null\n+++ b/lib/librte_emudev/rte_emudev.c\n@@ -0,0 +1,486 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020 Intel Corporation\n+ */\n+\n+#include <string.h>\n+\n+#include <rte_malloc.h>\n+#include <rte_memcpy.h>\n+\n+#include \"rte_emudev.h\"\n+\n+#define RTE_MAX_EMU_DEV 1024\n+struct rte_emudev rte_emu_devices[RTE_MAX_EMU_DEV];\n+\n+static struct rte_emudev_global emu_dev_globals = {\n+\t.nb_devs = 0\n+};\n+\n+static inline uint16_t rte_emu_alloc_dev_id(void)\n+{\n+\tunsigned int i;\n+\n+\tfor (i = 0; i < RTE_MAX_EMU_DEV; i++) {\n+\t\tif (rte_emu_devices[i].name[0] == '\\0')\n+\t\t\treturn i;\n+\t}\n+\treturn RTE_MAX_EMU_DEV;\n+}\n+\n+uint8_t\n+rte_emudev_count(void)\n+{\n+\treturn emu_dev_globals.nb_devs;\n+}\n+\n+int\n+rte_emudev_get_dev_id(const char *name)\n+{\n+\tuint16_t i;\n+\n+\tif (!name) {\n+\t\tRTE_EMUDEV_LOG(ERR, \"Failed to get device ID: \"\n+\t\t\t\"NULL device name\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tfor (i = 0; i < emu_dev_globals.nb_devs; i++)\n+\t\tif (!strncmp(rte_emu_devices[i].name, name,\n+\t\t\tRTE_EMU_NAME_MAX_LEN))\n+\t\t\treturn i;\n+\n+\treturn -ENODEV;\n+}\n+\n+struct rte_emudev *\n+rte_emudev_allocate(const char *name)\n+{\n+\tuint16_t dev_id;\n+\tstruct rte_emudev *emu_dev = NULL;\n+\tsize_t name_len;\n+\n+\tif (!name) {\n+\t\tRTE_EMUDEV_LOG(ERR, \"Failed to allocate emudev: \"\n+\t\t\t\"NULL device name\\n\");\n+\t\treturn NULL;\n+\t}\n+\n+\tname_len = strnlen(name, RTE_EMU_NAME_MAX_LEN);\n+\tif (!name_len) {\n+\t\tRTE_EMUDEV_LOG(ERR, \"Emulated device name has zero length\\n\");\n+\t\treturn NULL;\n+\t}\n+\n+\tif (name_len >= RTE_EMU_NAME_MAX_LEN) {\n+\t\tRTE_EMUDEV_LOG(ERR, \"Emulated device name too long\\n\");\n+\t\treturn NULL;\n+\t}\n+\n+\tif (rte_emudev_allocated(name) != NULL) {\n+\t\tRTE_EMUDEV_LOG(ERR,\n+\t\t\t\"Emulated device with name %s already exists\\n\",\n+\t\t\tname);\n+\t\treturn NULL;\n+\t}\n+\n+\tdev_id = rte_emu_alloc_dev_id();\n+\tif (dev_id == RTE_MAX_EMU_DEV) {\n+\t\tRTE_EMUDEV_LOG(ERR, \"Reached max number of Emulated device\\n\");\n+\t\treturn NULL;\n+\t}\n+\n+\temu_dev = &rte_emu_devices[dev_id];\n+\tstrncpy(emu_dev->name, name, sizeof(emu_dev->name));\n+\temu_dev->dev_id = dev_id;\n+\temu_dev_globals.nb_devs++;\n+\n+\treturn emu_dev;\n+}\n+\n+int\n+rte_emudev_release(struct rte_emudev *dev)\n+{\n+\tif (!dev)\n+\t\treturn -EINVAL;\n+\n+\tif (dev->priv_data) {\n+\t\trte_free(dev->priv_data);\n+\t\tdev->priv_data = NULL;\n+\t}\n+\n+\tmemset(dev, 0, sizeof(*dev));\n+\temu_dev_globals.nb_devs--;\n+\treturn 0;\n+}\n+\n+struct rte_emudev *\n+rte_emudev_allocated(const char *name)\n+{\n+\tunsigned int i;\n+\n+\tif (!name) {\n+\t\tRTE_EMUDEV_LOG(ERR, \"Failed to find emudev: \"\n+\t\t\t\"NULL device name\\n\");\n+\t\treturn NULL;\n+\t}\n+\n+\tfor (i = 0; i < RTE_MAX_EMU_DEV; i++) {\n+\t\tif (rte_emu_devices[i].dev_ops != NULL &&\n+\t\t    strcmp(rte_emu_devices[i].device->name, name) == 0)\n+\t\t\treturn &rte_emu_devices[i];\n+\t}\n+\treturn NULL;\n+}\n+\n+int rte_emudev_is_valid_id(uint16_t dev_id)\n+{\n+\tif (dev_id >= RTE_MAX_EMU_DEV ||\n+\t\trte_emu_devices[dev_id].name[0] == '\\0')\n+\t\treturn 0;\n+\telse\n+\t\treturn 1;\n+}\n+\n+int\n+rte_emudev_selftest(uint16_t dev_id)\n+{\n+\tRTE_EMU_CHECK_VALID_DEVID_ERR(dev_id);\n+\n+\tstruct rte_emudev *dev = &rte_emu_devices[dev_id];\n+\n+\tRTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_selftest, -ENOTSUP);\n+\n+\treturn (*dev->dev_ops->dev_selftest)(dev_id);\n+}\n+\n+\n+int rte_emudev_start(uint16_t dev_id)\n+{\n+\tstruct rte_emudev *dev;\n+\tint ret;\n+\n+\tRTE_EMU_CHECK_VALID_DEVID_ERR(dev_id);\n+\n+\tdev = &rte_emu_devices[dev_id];\n+\n+\tif (dev->started) {\n+\t\tRTE_EMUDEV_LOG(ERR, \"Device %u already started\\n\", dev_id);\n+\t\treturn 0;\n+\t}\n+\n+\tRTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_start, -ENOTSUP);\n+\n+\tret = (*dev->dev_ops->dev_start)(dev);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tdev->started = 1;\n+\treturn 0;\n+}\n+\n+void rte_emudev_stop(uint16_t dev_id)\n+{\n+\tstruct rte_emudev *dev;\n+\n+\tRTE_EMU_CHECK_VALID_DEVID(dev_id);\n+\n+\tdev = &rte_emu_devices[dev_id];\n+\n+\tif (!dev->started) {\n+\t\tRTE_EMUDEV_LOG(ERR, \"Device %u already stopped\\n\", dev_id);\n+\t\treturn;\n+\t}\n+\n+\tRTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_stop);\n+\n+\t(*dev->dev_ops->dev_stop)(dev);\n+\n+\tdev->started = 0;\n+}\n+\n+int rte_emudev_configure(uint16_t dev_id, struct rte_emudev_info *dev_conf)\n+{\n+\tstruct rte_emudev *dev;\n+\n+\tRTE_EMU_CHECK_VALID_DEVID_ERR(dev_id);\n+\n+\tdev = &rte_emu_devices[dev_id];\n+\n+\tif (!dev_conf)\n+\t\treturn -EINVAL;\n+\n+\tif (dev->started) {\n+\t\tRTE_EMUDEV_LOG(ERR, \"Device %u must be stopped \"\n+\t\t\t\"before configure\\n\", dev_id);\n+\t\treturn -EBUSY;\n+\t}\n+\n+\tRTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_configure, -ENOTSUP);\n+\n+\tif (strcmp(dev_conf->dev_type, dev->dev_info.dev_type)) {\n+\t\tRTE_EMUDEV_LOG(ERR, \"Wrong device type to configure\"\n+\t\t\t\" for device %u\\n\", dev_id);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\treturn (*dev->dev_ops->dev_configure)(dev, dev_conf);\n+}\n+\n+int rte_emudev_close(uint16_t dev_id)\n+{\n+\tstruct rte_emudev *dev;\n+\n+\tRTE_EMU_CHECK_VALID_DEVID_ERR(dev_id);\n+\n+\tdev = &rte_emu_devices[dev_id];\n+\n+\tif (dev->started) {\n+\t\tRTE_EMUDEV_LOG(ERR, \"Device %u must be stopped \"\n+\t\t\t\"before close\\n\", dev_id);\n+\t\treturn -EBUSY;\n+\t}\n+\n+\tRTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_close, -ENOTSUP);\n+\n+\t(*dev->dev_ops->dev_close)(dev);\n+\n+\trte_emudev_release(dev);\n+\treturn 0;\n+}\n+\n+int rte_emudev_subscribe_event(uint16_t dev_id,\n+\t\tconst rte_emudev_event_chnl_t ev_chnl)\n+{\n+\tstruct rte_emudev *dev;\n+\n+\tRTE_EMU_CHECK_VALID_DEVID_ERR(dev_id);\n+\n+\tif (!ev_chnl) {\n+\t\tRTE_EMUDEV_LOG(ERR, \"Failed to subscribe because of NULL\"\n+\t\t\t\" event channel for device %u\\n\", dev_id);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tdev = &rte_emu_devices[dev_id];\n+\n+\tRTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->subscribe_event, -ENOTSUP);\n+\n+\treturn (*dev->dev_ops->subscribe_event)(dev, ev_chnl);\n+}\n+\n+int rte_emudev_unsubscribe_event(uint16_t dev_id,\n+\t\tconst rte_emudev_event_chnl_t ev_chnl)\n+{\n+\tstruct rte_emudev *dev;\n+\n+\tRTE_EMU_CHECK_VALID_DEVID_ERR(dev_id);\n+\n+\tif (!ev_chnl) {\n+\t\tRTE_EMUDEV_LOG(ERR, \"Failed to unsubscribe because of NULL\"\n+\t\t\t\" event channel for device %u\\n\", dev_id);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tdev = &rte_emu_devices[dev_id];\n+\n+\tRTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->unsubscribe_event, -ENOTSUP);\n+\n+\treturn (*dev->dev_ops->unsubscribe_event)(dev, ev_chnl);\n+}\n+\n+int rte_emudev_get_dev_info(uint16_t dev_id, struct rte_emudev_info *info)\n+{\n+\tstruct rte_emudev *dev;\n+\tstruct rte_emudev_info *dev_info;\n+\n+\tRTE_EMU_CHECK_VALID_DEVID_ERR(dev_id);\n+\n+\tif (!info) {\n+\t\tRTE_EMUDEV_LOG(ERR, \"NULL device info for device %u\\n\",\n+\t\t\tdev_id);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tdev = &rte_emu_devices[dev_id];\n+\tdev_info = &dev->dev_info;\n+\n+\tstrcpy(info->dev_type, dev_info->dev_type);\n+\tinfo->max_qp_num = dev_info->max_qp_num;\n+\tinfo->region_num = dev_info->region_num;\n+\n+\tRTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_info_get, -ENOTSUP);\n+\n+\treturn (*dev->dev_ops->dev_info_get)(dev, info->dev_priv);\n+}\n+\n+int rte_emudev_get_mem_table(uint16_t dev_id, rte_emudev_mem_table_t *tb)\n+{\n+\tstruct rte_emudev *dev;\n+\n+\tRTE_EMU_CHECK_VALID_DEVID_ERR(dev_id);\n+\n+\tif (!tb) {\n+\t\tRTE_EMUDEV_LOG(ERR, \"NULL memory table for device %u\\n\",\n+\t\t\tdev_id);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tdev = &rte_emu_devices[dev_id];\n+\n+\tRTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_mem_table, -ENOTSUP);\n+\n+\treturn (*dev->dev_ops->get_mem_table)(dev, tb);\n+}\n+\n+int rte_emudev_get_queue_info(uint16_t dev_id, uint32_t queue,\n+\tstruct rte_emudev_q_info *info)\n+{\n+\tstruct rte_emudev *dev;\n+\n+\tRTE_EMU_CHECK_VALID_DEVID_ERR(dev_id);\n+\n+\tif (!info) {\n+\t\tRTE_EMUDEV_LOG(ERR, \"NULL queue info for queue %d\"\n+\t\t\t\" of device %u\\n\", queue, dev_id);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tdev = &rte_emu_devices[dev_id];\n+\n+\tif (queue >= dev->dev_info.max_qp_num * 2) {\n+\t\tRTE_EMUDEV_LOG(ERR, \"Queue index of device %u exceeds max\\n\",\n+\t\t\tdev_id);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tRTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_queue_info, -ENOTSUP);\n+\n+\tmemset(info, 0, sizeof(*info));\n+\n+\treturn (*dev->dev_ops->get_queue_info)(dev, queue, info);\n+}\n+\n+int rte_emudev_get_irq_info(uint16_t dev_id, uint32_t vector,\n+\tstruct rte_emudev_irq_info *info)\n+{\n+\tstruct rte_emudev *dev;\n+\n+\tRTE_EMU_CHECK_VALID_DEVID_ERR(dev_id);\n+\n+\tif (!info) {\n+\t\tRTE_EMUDEV_LOG(ERR, \"NULL irq info for vector %u\"\n+\t\t\t\" of device %u\\n\", vector, dev_id);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tdev = &rte_emu_devices[dev_id];\n+\n+\tRTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_irq_info, -ENOTSUP);\n+\n+\tmemset(info, 0, sizeof(*info));\n+\n+\treturn (*dev->dev_ops->get_irq_info)(dev, vector, info);\n+}\n+\n+int rte_emudev_get_db_info(uint16_t dev_id, uint32_t doorbell,\n+\tstruct rte_emudev_db_info *info)\n+{\n+\tstruct rte_emudev *dev;\n+\n+\tRTE_EMU_CHECK_VALID_DEVID_ERR(dev_id);\n+\n+\tif (!info) {\n+\t\tRTE_EMUDEV_LOG(ERR, \"NULL doorbell info of device %u\"\n+\t\t\t\" for id %u\\n\", dev_id, doorbell);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tdev = &rte_emu_devices[dev_id];\n+\n+\tRTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_db_info, -ENOTSUP);\n+\n+\tmemset(info, 0, sizeof(*info));\n+\n+\treturn (*dev->dev_ops->get_db_info)(dev, doorbell, info);\n+}\n+\n+int rte_emudev_set_attr(uint16_t dev_id, const char *attr_name,\n+\trte_emudev_attr_t attr)\n+{\n+\tstruct rte_emudev *dev;\n+\n+\tRTE_EMU_CHECK_VALID_DEVID_ERR(dev_id);\n+\n+\tif (!attr_name) {\n+\t\tRTE_EMUDEV_LOG(ERR, \"NULL attribute name of device %u \"\n+\t\t\t\"for set\\n\", dev_id);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (!attr) {\n+\t\tRTE_EMUDEV_LOG(ERR, \"NULL attribute of device %u \"\n+\t\t\t\"for set_attr\\n\", dev_id);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tdev = &rte_emu_devices[dev_id];\n+\n+\tRTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_attr, -ENOTSUP);\n+\n+\treturn (*dev->dev_ops->set_attr)(dev, attr_name, attr);\n+}\n+\n+int rte_emudev_get_attr(uint16_t dev_id, const char *attr_name,\n+\trte_emudev_attr_t attr)\n+{\n+\tstruct rte_emudev *dev;\n+\n+\tRTE_EMU_CHECK_VALID_DEVID_ERR(dev_id);\n+\n+\tif (!attr_name) {\n+\t\tRTE_EMUDEV_LOG(ERR, \"NULL attribute name of device %u \"\n+\t\t\t\"for get\\n\", dev_id);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (!attr) {\n+\t\tRTE_EMUDEV_LOG(ERR, \"NULL attribute of device %u \"\n+\t\t\t\"for get_attr\\n\", dev_id);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tdev = &rte_emu_devices[dev_id];\n+\n+\tRTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_attr, -ENOTSUP);\n+\n+\treturn (*dev->dev_ops->get_attr)(dev, attr_name, attr);\n+}\n+\n+int rte_emudev_region_map(uint16_t dev_id, uint32_t index,\n+\tuint64_t *region_size, uint64_t *base_addr)\n+{\n+\tstruct rte_emudev *dev;\n+\n+\tRTE_EMU_CHECK_VALID_DEVID_ERR(dev_id);\n+\n+\tif (!region_size || !base_addr)\n+\t\treturn -EINVAL;\n+\n+\tdev = &rte_emu_devices[dev_id];\n+\n+\tif (index >= dev->dev_info.region_num) {\n+\t\tRTE_EMUDEV_LOG(ERR, \"Wrong region index for device %u\\n\",\n+\t\t\tdev_id);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tRTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->region_map, -ENOTSUP);\n+\n+\tmemset(region_size, 0, sizeof(*region_size));\n+\tmemset(base_addr, 0, sizeof(*base_addr));\n+\n+\treturn (*dev->dev_ops->region_map)(dev, index, region_size,\n+\t\tbase_addr);\n+}\n+\n+RTE_LOG_REGISTER(rte_emudev_logtype, lib.emudev, INFO);\ndiff --git a/lib/librte_emudev/rte_emudev.h b/lib/librte_emudev/rte_emudev.h\nnew file mode 100644\nindex 0000000000..df31c631b7\n--- /dev/null\n+++ b/lib/librte_emudev/rte_emudev.h\n@@ -0,0 +1,410 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020 Intel Corporation\n+ */\n+\n+#ifndef _RTE_EMUDEV_H_\n+#define _RTE_EMUDEV_H_\n+\n+#include <rte_config.h>\n+#include <rte_dev.h>\n+#include <rte_compat.h>\n+\n+#define RTE_EMU_NAME_MAX_LEN RTE_DEV_NAME_MAX_LEN\n+\n+extern int rte_emudev_logtype;\n+\n+#define RTE_EMUDEV_LOG(level, ...) \\\n+\trte_log(RTE_LOG_ ## level, rte_emudev_logtype, \"\" __VA_ARGS__)\n+\n+/* Macros to check for valid dev id */\n+#define RTE_EMU_CHECK_VALID_DEVID_ERR(dev_id) do { \\\n+\tif (!rte_emudev_is_valid_id(dev_id)) { \\\n+\t\tRTE_EMUDEV_LOG(ERR, \"Invalid dev_id=%u\\n\", dev_id); \\\n+\t\treturn -ENODEV; \\\n+\t} \\\n+} while (0)\n+\n+#define RTE_EMU_CHECK_VALID_DEVID(dev_id) do { \\\n+\tif (!rte_emudev_is_valid_id(dev_id)) { \\\n+\t\tRTE_EMUDEV_LOG(ERR, \"Invalid dev_id=%u\\n\", dev_id); \\\n+\t\treturn; \\\n+\t} \\\n+} while (0)\n+\n+typedef void *rte_emudev_obj_t;\n+typedef void *rte_emudev_attr_t;\n+typedef void *rte_emudev_mem_table_t;\n+typedef void *rte_emudev_event_chnl_t;\n+\n+struct rte_emudev;\n+\n+/** \n+ * Global structure used for maintaining state\n+ * of allocated emu devices\n+ */\n+struct rte_emudev_global {\n+\tuint8_t nb_devs;\t/**< Number of devices found */\n+};\n+\n+struct rte_emudev_info {\n+\tchar dev_type[RTE_EMU_NAME_MAX_LEN];\n+\tuint32_t region_num;\n+\tuint32_t max_qp_num;\n+\trte_emudev_obj_t dev_priv;\n+};\n+\n+struct rte_emudev_q_info {\n+\tuint64_t base;\n+\tuint64_t size;\n+\tint doorbell_id;\n+\tint irq_vector;\n+};\n+\n+struct rte_emudev_irq_info {\n+\tuint32_t vector;\n+\tbool enable;\n+\tint eventfd;\n+};\n+\n+struct rte_emudev_db_info {\n+\tuint32_t id;\n+\tuint32_t flag;\n+#define RTE_EMUDEV_DB_FD\t(0x1 << 0)\n+#define RTE_EMUDEV_DB_MEM\t(0x1 << 1)\n+\tunion {\n+\t\tint eventfd;\n+\t\tstruct {\n+\t\t\tuint64_t base;\n+\t\t\tuint64_t size;\n+\t\t} mem;\n+\t} data;\n+};\n+\n+struct rte_emudev_ops {\n+\tint (*dev_start)(struct rte_emudev *dev);\n+\tvoid (*dev_stop)(struct rte_emudev *dev);\n+\tint (*dev_configure)(struct rte_emudev *dev,\n+\t\tstruct rte_emudev_info *conf);\n+\tint (*dev_close)(struct rte_emudev *dev);\n+\tint (*dev_info_get)(struct rte_emudev *dev, rte_emudev_obj_t info);\n+\tint (*subscribe_event)(struct rte_emudev *dev,\n+\t\trte_emudev_event_chnl_t ev_chnl);\n+\tint (*unsubscribe_event)(struct rte_emudev *dev,\n+\t\trte_emudev_event_chnl_t ev_chnl);\n+\tint (*get_mem_table)(struct rte_emudev *dev,\n+\t\trte_emudev_mem_table_t *tb);\n+\tint (*get_queue_info)(struct rte_emudev *dev, uint32_t queue,\n+\t\tstruct rte_emudev_q_info *info);\n+\tint (*get_irq_info)(struct rte_emudev *dev, uint32_t vector,\n+\t\tstruct rte_emudev_irq_info *info);\n+\tint (*get_db_info)(struct rte_emudev *dev, uint32_t doorbell,\n+\t\tstruct rte_emudev_db_info *info);\n+\tint (*get_attr)(struct rte_emudev *dev, const char *attr_name,\n+\t\trte_emudev_attr_t attr);\n+\tint (*set_attr)(struct rte_emudev *dev, const char *attr_name,\n+\t\trte_emudev_attr_t attr);\n+\tint (*region_map)(struct rte_emudev *dev, uint32_t index,\n+\t\tuint64_t *region_size, uint64_t *base_addr);\n+\tint (*dev_selftest)(uint16_t dev_id);\n+};\n+\n+struct rte_emudev {\n+\tchar name[RTE_EMU_NAME_MAX_LEN];\n+\tuint16_t dev_id;\n+\tint numa_node;\n+\tint started;\n+\tstruct rte_device *device;\n+\tstruct rte_emudev_info dev_info;\n+\tconst struct rte_emudev_ops *dev_ops;\n+\tvoid *priv_data;\n+\tvoid *backend_priv;\n+} __rte_cache_aligned;\n+\n+/**\n+ * Note that 'rte_emudev_allocate', 'rte_emudev_release' and\n+ * 'rte_emudev_allocated' should be called by emulated device\n+ * provider.\n+ */\n+\n+/**\n+ * Allocate a new emudev for an emulation device and returns the pointer\n+ * to the emudev.\n+ *\n+ * @param name\n+ *   Name of the emudev\n+ * @return\n+ *   Pointer to rte_emudev on success, NULL on failure\n+ */\n+__rte_experimental\n+struct rte_emudev *rte_emudev_allocate(const char *name);\n+\n+/**\n+ * Release the emudev.\n+ *\n+ * @param dev\n+ *   The emulated device\n+ * @return\n+ *   - 0: Success, device release\n+ *   - <0: Failure on release\n+ */\n+__rte_experimental\n+int rte_emudev_release(struct rte_emudev *dev);\n+\n+/**\n+ * Find an emudev using name.\n+ *\n+ * @param name\n+ *   Name of the emudev\n+ * @return\n+ *   Pointer to rte_emudev on success, NULL on failure\n+ */\n+__rte_experimental\n+struct rte_emudev *rte_emudev_allocated(const char *name);\n+\n+/**\n+ * Start an emulation device.\n+ *\n+ * @param dev_id\n+ *   Device ID of emudev\n+ * @return\n+ *   - 0: Success, device start\n+ *   - <0: Failure on start\n+ */\n+__rte_experimental\n+int rte_emudev_start(uint16_t dev_id);\n+\n+/**\n+ * Stop an emulation device.\n+ *\n+ * @param dev_id\n+ *   Device ID of emudev\n+ */\n+__rte_experimental\n+void rte_emudev_stop(uint16_t dev_id);\n+\n+/**\n+ * Configure an emulation device.\n+ *\n+ * @param dev_id\n+ *   Device ID of emudev\n+ * @param dev_conf\n+ *   Device configure info\n+ * @return\n+ *   - 0: Success, device configured\n+ *   - <0: Failure on configure\n+ */\n+__rte_experimental\n+int rte_emudev_configure(uint16_t dev_id, struct rte_emudev_info *dev_conf);\n+\n+/**\n+ * Close an emulation device.\n+ *\n+ * @param dev_id\n+ *   Device ID of emudev\n+ * @return\n+ *   - 0: Success, device close\n+ *   - <0: Failure on close\n+ */\n+__rte_experimental\n+int rte_emudev_close(uint16_t dev_id);\n+\n+/* Note that below APIs should only be called by back-end (data path) driver */\n+\n+/**\n+ * Back-end driver subscribes events of the emulated device.\n+ *\n+ * @param dev_id\n+ *   Device ID of emudev\n+ * @param ev_chnl\n+ *   Event channel that events should be passed to\n+ * @return\n+ *   - 0: Success, event subscribed\n+ *   - <0: Failure on subscribe\n+ */\n+__rte_experimental\n+int rte_emudev_subscribe_event(uint16_t dev_id,\n+\t\tconst rte_emudev_event_chnl_t ev_chnl);\n+\n+/**\n+ * Back-end driver unsubscribes events of the emulated device.\n+ *\n+ * @param dev_id\n+ *   Device ID of emudev\n+ * @param set\n+ *   Event channel that events should be passed to\n+ * @return\n+ *   - 0: Success, event unsubscribed\n+ *   - <0: Failure on unsubscribe\n+ */\n+__rte_experimental\n+int rte_emudev_unsubscribe_event(uint16_t dev_id,\n+\t\tconst rte_emudev_event_chnl_t ev_chnl);\n+\n+/**\n+ * Get the total number of emulated devices that have been\n+ * successfully initialised.\n+ *\n+ * @return\n+ *   The total number of usable emudev.\n+ */\n+__rte_experimental\n+uint8_t rte_emudev_count(void);\n+\n+/**\n+ * Get the device identifier for the named emulated device.\n+ *\n+ * @param name\n+ *   Emulated device name to select the device identifier.\n+ *\n+ * @return\n+ *   - 0: Success, emulated device identifier returned\n+ *   - <0: Failure on unsubscribe\n+ */\n+__rte_experimental\n+int rte_emudev_get_dev_id(const char *name);\n+\n+/**\n+ * Back-end driver gets the device info of the emulated device.\n+ *\n+ * @param dev_id\n+ *   Device ID of emudev\n+ * @return\n+ *   - 0: Success, emulated device info updated\n+ *   - <0: Failure on get device information\n+ */\n+__rte_experimental\n+int rte_emudev_get_dev_info(uint16_t dev_id, struct rte_emudev_info *info);\n+\n+/**\n+ * Get the memory table content and operations of the emulated device.\n+ *\n+ * @param dev_id\n+ *   Device ID of emudev\n+ * @return\n+ *   - 0: Success, memory table of emulated device updated\n+ *   - <0: Failure on get memory table\n+ */\n+__rte_experimental\n+int rte_emudev_get_mem_table(uint16_t dev_id, rte_emudev_mem_table_t *tb);\n+\n+/**\n+ * Get queue info of the emudev.\n+ *\n+ * @param dev_id\n+ *   Device ID of emudev\n+ * @param queue\n+ *   Queue ID of emudev\n+ * @return\n+ *   - 0: Success, queue information of emulated device updated\n+ *   - <0: Failure on get queue information\n+ */\n+__rte_experimental\n+int rte_emudev_get_queue_info(uint16_t dev_id, uint32_t queue,\n+\tstruct rte_emudev_q_info *info);\n+\n+/**\n+ * Get irq info of the emudev.\n+ *\n+ * @param dev_id\n+ *   Device ID of emudev\n+ * @param vector\n+ *   Interrupt vector\n+ * @return\n+ *   - 0: Success, irq information of emulated device updated\n+ *   - <0: Failure on get irq information\n+ */\n+__rte_experimental\n+int rte_emudev_get_irq_info(uint16_t dev_id, uint32_t vector,\n+\tstruct rte_emudev_irq_info *info);\n+\n+/**\n+ * Get doorbell info of the emudev.\n+ *\n+ * @param dev_id\n+ *   Device ID of emudev\n+ * @param doorbell\n+ *   Doorbell ID\n+ * @return\n+ *   - 0: Success, doorbell information of emulated device updated\n+ *   - <0: Failure on get doorbell information\n+ */\n+__rte_experimental\n+int rte_emudev_get_db_info(uint16_t dev_id, uint32_t doorbell,\n+\tstruct rte_emudev_db_info *info);\n+\n+/**\n+ * Set attribute of the emudev.\n+ *\n+ * @param dev_id\n+ *   Device ID of emudev\n+ * @param attr_name\n+ *   Opaque object representing an attribute in implementation.\n+ * @param attr\n+ *   Pointer to attribute\n+ * @return\n+ *   - 0: Success, attribute set\n+ *   - <0: Failure on attribute set\n+ */\n+__rte_experimental\n+int rte_emudev_set_attr(uint16_t dev_id, const char *attr_name,\n+\trte_emudev_attr_t attr);\n+\n+/**\n+ * Get attribute of the emudev.\n+ *\n+ * @param dev_id\n+ *   Device ID of emudev\n+ * @param attr_name\n+ *   Opaque object representing an attribute in implementation.\n+ * @return\n+ *   - 0: Success, attribute of emulated device updated\n+ *   - <0: Failure on attribute get\n+ */\n+__rte_experimental\n+int rte_emudev_get_attr(uint16_t dev_id, const char *attr_name,\n+\trte_emudev_attr_t attr);\n+\n+/**\n+ * Back-end driver maps a region to the emulated device.\n+ * Region name identifies the meaning of the region and the emulated\n+ * device and the back-end driver should have the same definition of\n+ * region name and its meaning.\n+ *\n+ * @param dev_id\n+ *   Device ID of emudev\n+ * @param index\n+ *   Region index\n+ * @param attr\n+ *   Pointer to attribute\n+ * @return\n+ *   - 0: Success, region mapped\n+ *   - <0: Failure on region map\n+ */\n+__rte_experimental\n+int rte_emudev_region_map(uint16_t dev_id, uint32_t index,\n+\tuint64_t *region_size, uint64_t *base_addr);\n+\n+/**\n+ * Trigger the emudev self test.\n+ *\n+ * @param dev_id\n+ *   The identifier of the device\n+ * @return\n+ *   - 0: Selftest successful\n+ *   - <0: Failure on selftest\n+ */\n+__rte_experimental\n+int rte_emudev_selftest(uint16_t dev_id);\n+\n+/**\n+ * Check if an emudev device ID is valid.\n+ *\n+ * @param dev_id\n+ *   The identifier of the device\n+ * @return\n+ *   0 on failure, 1 on success\n+ */\n+__rte_experimental\n+int rte_emudev_is_valid_id(uint16_t dev_id);\n+\n+#endif /* _RTE_EMUDEV_H_ */\ndiff --git a/lib/librte_emudev/rte_emudev_vdev.h b/lib/librte_emudev/rte_emudev_vdev.h\nnew file mode 100644\nindex 0000000000..85f534b4bd\n--- /dev/null\n+++ b/lib/librte_emudev/rte_emudev_vdev.h\n@@ -0,0 +1,53 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020 Intel Corporation\n+ */\n+\n+#ifndef _RTE_EMUDEV_VDEV_H_\n+#define _RTE_EMUDEV_VDEV_H_\n+\n+#include <rte_bus_vdev.h>\n+#include <rte_malloc.h>\n+\n+#include \"rte_emudev.h\"\n+\n+/**\n+ * @internal\n+ * Allocates a new emudev instance for an emulated device and\n+ * returns the pointer to that instance for the driver to use.\n+ *\n+ * @param dev\n+ *\tPointer to virtual device\n+ *\n+ * @param private_data_size\n+ *\tSize of private data structure\n+ *\n+ * @return\n+ *\tA pointer to a rte_emudev or NULL if allocation failed.\n+ */\n+static inline struct rte_emudev *\n+rte_emu_vdev_allocate(struct rte_vdev_device *dev, size_t private_data_size)\n+{\n+\tstruct rte_emudev *emu_dev;\n+\tconst char *name = rte_vdev_device_name(dev);\n+\n+\temu_dev = rte_emudev_allocate(name);\n+\tif (!emu_dev)\n+\t\treturn NULL;\n+\n+\tif (private_data_size) {\n+\t\temu_dev->priv_data = rte_zmalloc_socket(name,\n+\t\t\tprivate_data_size, RTE_CACHE_LINE_SIZE,\n+\t\t\tdev->device.numa_node);\n+\t\tif (!emu_dev->priv_data) {\n+\t\t\trte_emudev_release(emu_dev);\n+\t\t\treturn NULL;\n+\t\t}\n+\t}\n+\n+\temu_dev->device = &dev->device;\n+\temu_dev->numa_node = dev->device.numa_node;\n+\n+\treturn emu_dev;\n+}\n+\n+#endif /* _RTE_EMUDEV_VDEV_H_ */\ndiff --git a/lib/librte_emudev/version.map b/lib/librte_emudev/version.map\nnew file mode 100644\nindex 0000000000..f800b4c21c\n--- /dev/null\n+++ b/lib/librte_emudev/version.map\n@@ -0,0 +1,27 @@\n+EXPERIMENTAL {\n+\tglobal:\n+\n+\trte_emudev_allocate;\n+\trte_emudev_release;\n+\trte_emudev_allocated;\n+\trte_emudev_start;\n+\trte_emudev_stop;\n+\trte_emudev_configure;\n+\trte_emudev_close;\n+\trte_emudev_subscribe_event;\n+\trte_emudev_unsubscribe_event;\n+\trte_emudev_count;\n+\trte_emudev_get_dev_id;\n+\trte_emudev_get_dev_info;\n+\trte_emudev_get_mem_table;\n+\trte_emudev_get_queue_info;\n+\trte_emudev_get_irq_info;\n+\trte_emudev_get_db_info;\n+\trte_emudev_set_attr;\n+\trte_emudev_get_attr;\n+\trte_emudev_region_map;\n+\trte_emudev_selftest;\n+\trte_emudev_is_valid_id;\n+\n+\tlocal: *;\n+};\ndiff --git a/lib/meson.build b/lib/meson.build\nindex b7fbfcc95b..6dd07fb73e 100644\n--- a/lib/meson.build\n+++ b/lib/meson.build\n@@ -28,7 +28,7 @@ libraries = [\n \t'rib', 'reorder', 'sched', 'security', 'stack', 'vhost',\n \t# ipsec lib depends on net, crypto and security\n \t'ipsec',\n-\t'vfio_user',\n+\t'vfio_user', 'emudev',\n \t#fib lib depends on rib\n \t'fib',\n \t# add pkt framework libs which use other libs from above\n",
    "prefixes": [
        "v2",
        "1/8"
    ]
}