get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 45342,
    "url": "http://patches.dpdk.org/api/patches/45342/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20180926090638.4705-3-xiaolong.ye@intel.com/",
    "project": {
        "id": 1,
        "url": "http://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": "<20180926090638.4705-3-xiaolong.ye@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20180926090638.4705-3-xiaolong.ye@intel.com",
    "date": "2018-09-26T09:06:38",
    "name": "[v6,2/2] examples/vdpa: introduce a new sample for vDPA",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "7064016ae77990533324c4b8fd65fbead97fd965",
    "submitter": {
        "id": 1120,
        "url": "http://patches.dpdk.org/api/people/1120/?format=api",
        "name": "Xiaolong Ye",
        "email": "xiaolong.ye@intel.com"
    },
    "delegate": {
        "id": 2642,
        "url": "http://patches.dpdk.org/api/users/2642/?format=api",
        "username": "mcoquelin",
        "first_name": "Maxime",
        "last_name": "Coquelin",
        "email": "maxime.coquelin@redhat.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20180926090638.4705-3-xiaolong.ye@intel.com/mbox/",
    "series": [
        {
            "id": 1504,
            "url": "http://patches.dpdk.org/api/series/1504/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=1504",
            "date": "2018-09-26T09:06:37",
            "name": "introduce vdpa sample",
            "version": 6,
            "mbox": "http://patches.dpdk.org/series/1504/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/45342/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/45342/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 6E4E25F35;\n\tWed, 26 Sep 2018 04:25:07 +0200 (CEST)",
            "from mga01.intel.com (mga01.intel.com [192.55.52.88])\n\tby dpdk.org (Postfix) with ESMTP id 14C7D5B2C\n\tfor <dev@dpdk.org>; Wed, 26 Sep 2018 04:25:04 +0200 (CEST)",
            "from fmsmga005.fm.intel.com ([10.253.24.32])\n\tby fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t25 Sep 2018 19:25:04 -0700",
            "from yexl-server.sh.intel.com ([10.67.110.207])\n\tby fmsmga005.fm.intel.com with ESMTP; 25 Sep 2018 19:18:40 -0700"
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.54,304,1534834800\"; d=\"scan'208\";a=\"265745530\"",
        "From": "Xiaolong Ye <xiaolong.ye@intel.com>",
        "To": "dev@dpdk.org, Maxime Coquelin <maxime.coquelin@redhat.com>,\n\tTiwei Bie <tiwei.bie@intel.com>, Zhihong Wang <zhihong.wang@intel.com>",
        "Cc": "xiao.w.wang@intel.com, Rami Rosen <roszenrami@gmail.com>,\n\tWang Haiyue <haiyue.wang@intel.com>, Xiaolong Ye <xiaolong.ye@intel.com>",
        "Date": "Wed, 26 Sep 2018 17:06:38 +0800",
        "Message-Id": "<20180926090638.4705-3-xiaolong.ye@intel.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<20180926090638.4705-1-xiaolong.ye@intel.com>",
        "References": "<20180925120716.102144-1-xiaolong.ye@intel.com>\n\t<20180926090638.4705-1-xiaolong.ye@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v6 2/2] examples/vdpa: introduce a new sample for\n\tvDPA",
        "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\t<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\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "The vdpa sample application creates vhost-user sockets by using the\nvDPA backend. vDPA stands for vhost Data Path Acceleration which utilizes\nvirtio ring compatible devices to serve virtio driver directly to enable\ndatapath acceleration. As vDPA driver can help to set up vhost datapath,\nthis application doesn't need to launch dedicated worker threads for vhost\nenqueue/dequeue operations.\n\nSigned-off-by: Xiao Wang <xiao.w.wang@intel.com>\nSigned-off-by: Xiaolong Ye <xiaolong.ye@intel.com>\n---\n MAINTAINERS                            |   2 +\n doc/guides/rel_notes/release_18_11.rst |   8 +\n doc/guides/sample_app_ug/index.rst     |   1 +\n doc/guides/sample_app_ug/vdpa.rst      | 120 +++++++\n examples/Makefile                      |   2 +-\n examples/vdpa/Makefile                 |  32 ++\n examples/vdpa/main.c                   | 466 +++++++++++++++++++++++++\n examples/vdpa/meson.build              |  16 +\n 8 files changed, 646 insertions(+), 1 deletion(-)\n create mode 100644 doc/guides/sample_app_ug/vdpa.rst\n create mode 100644 examples/vdpa/Makefile\n create mode 100644 examples/vdpa/main.c\n create mode 100644 examples/vdpa/meson.build",
    "diff": "diff --git a/MAINTAINERS b/MAINTAINERS\nindex 5967c1dd3..5656f18e8 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -683,6 +683,8 @@ F: doc/guides/sample_app_ug/vhost.rst\n F: examples/vhost_scsi/\n F: doc/guides/sample_app_ug/vhost_scsi.rst\n F: examples/vhost_crypto/\n+F: examples/vdpa/\n+F: doc/guides/sample_app_ug/vdpa.rst\n \n Vhost PMD\n M: Maxime Coquelin <maxime.coquelin@redhat.com>\ndiff --git a/doc/guides/rel_notes/release_18_11.rst b/doc/guides/rel_notes/release_18_11.rst\nindex bc9b74ec4..dd53a9ecf 100644\n--- a/doc/guides/rel_notes/release_18_11.rst\n+++ b/doc/guides/rel_notes/release_18_11.rst\n@@ -67,6 +67,14 @@ New Features\n   SR-IOV option in Hyper-V and Azure. This is an alternative to the previous\n   vdev_netvsc, tap, and failsafe drivers combination.\n \n+* **Add a new sample for vDPA**\n+\n+  The vdpa sample application creates vhost-user sockets by using the\n+  vDPA backend. vDPA stands for vhost Data Path Acceleration which utilizes\n+  virtio ring compatible devices to serve virtio driver directly to enable\n+  datapath acceleration. As vDPA driver can help to set up vhost datapath,\n+  this application doesn't need to launch dedicated worker threads for vhost\n+  enqueue/dequeue operations.\n \n API Changes\n -----------\ndiff --git a/doc/guides/sample_app_ug/index.rst b/doc/guides/sample_app_ug/index.rst\nindex 5bedf4f6f..74b12af85 100644\n--- a/doc/guides/sample_app_ug/index.rst\n+++ b/doc/guides/sample_app_ug/index.rst\n@@ -45,6 +45,7 @@ Sample Applications User Guides\n     vhost\n     vhost_scsi\n     vhost_crypto\n+    vdpa\n     netmap_compatibility\n     ip_pipeline\n     test_pipeline\ndiff --git a/doc/guides/sample_app_ug/vdpa.rst b/doc/guides/sample_app_ug/vdpa.rst\nnew file mode 100644\nindex 000000000..745f196ca\n--- /dev/null\n+++ b/doc/guides/sample_app_ug/vdpa.rst\n@@ -0,0 +1,120 @@\n+..  SPDX-License-Identifier: BSD-3-Clause\n+    Copyright(c) 2018 Intel Corporation.\n+\n+Vdpa Sample Application\n+=======================\n+\n+The vdpa sample application creates vhost-user sockets by using the\n+vDPA backend. vDPA stands for vhost Data Path Acceleration which utilizes\n+virtio ring compatible devices to serve virtio driver directly to enable\n+datapath acceleration. As vDPA driver can help to set up vhost datapath,\n+this application doesn't need to launch dedicated worker threads for vhost\n+enqueue/dequeue operations.\n+\n+Testing steps\n+-------------\n+\n+This section shows the steps of how to start VMs with vDPA vhost-user\n+backend and verify network connection & live migration.\n+\n+Build\n+~~~~~\n+\n+To compile the sample application see :doc:`compiling`.\n+\n+The application is located in the ``vdpa`` sub-directory.\n+\n+Start the vdpa example\n+~~~~~~~~~~~~~~~~~~~~~~\n+\n+.. code-block:: console\n+\n+        ./vdpa [EAL options]  -- [--client] [--interactive|-i] or [--iface SOCKET_PATH]\n+\n+where\n+\n+* --client means running vdpa app in client mode, in the client mode, QEMU needs\n+  to run as the server mode and take charge of socket file creation.\n+* --iface specifies the path prefix of the UNIX domain socket file, e.g.\n+  /tmp/vhost-user-, then the socket files will be named as /tmp/vhost-user-<n>\n+  (n starts from 0).\n+* --interactive means run the vdpa sample in interactive mode, currently 4\n+  internal cmds are supported:\n+\n+  1. help: show help message\n+  2. list: list all available vdpa devices\n+  3. create: create a new vdpa port with socket file and vdpa device address\n+  4. quit: unregister vhost driver and exit the application\n+\n+Take IFCVF driver for example:\n+\n+.. code-block:: console\n+\n+        ./vdpa -c 0x2 -n 4 --socket-mem 1024,1024 \\\n+                -w 0000:06:00.3,vdpa=1 -w 0000:06:00.4,vdpa=1 \\\n+                -- --interactive\n+\n+.. note::\n+    Here 0000:06:00.3 and 0000:06:00.4 refer to virtio ring compatible devices,\n+    and we need to bind vfio-pci to them before running vdpa sample.\n+\n+    * modprobe vfio-pci\n+    * ./usertools/dpdk-devbind.py -b vfio-pci 06:00.3 06:00.4\n+\n+Then we can create 2 vdpa ports in interactive cmdline.\n+\n+.. code-block:: console\n+\n+        vdpa> list\n+        device id       device address  queue num       supported features\n+        0               0000:06:00.3    1               0x14c238020\n+        1               0000:06:00.4    1               0x14c238020\n+        2               0000:06:00.5    1               0x14c238020\n+\n+        vdpa> create /tmp/vdpa-socket0 0000:06:00.3\n+        vdpa> create /tmp/vdpa-socket1 0000:06:00.4\n+\n+.. _vdpa_app_run_vm:\n+\n+Start the VMs\n+~~~~~~~~~~~~~\n+\n+.. code-block:: console\n+\n+       qemu-system-x86_64 -cpu host -enable-kvm \\\n+       <snip>\n+       -mem-prealloc \\\n+       -chardev socket,id=char0,path=<socket_file created in above steps> \\\n+       -netdev type=vhost-user,id=vdpa,chardev=char0 \\\n+       -device virtio-net-pci,netdev=vdpa,mac=00:aa:bb:cc:dd:ee,page-per-vq=on \\\n+\n+After the VMs launches, we can login the VMs and configure the ip, verify the\n+network connection via ping or netperf.\n+\n+.. note::\n+    Suggest to use QEMU 3.0.0 which extends vhost-user for vDPA.\n+\n+Live Migration\n+~~~~~~~~~~~~~~\n+vDPA supports cross-backend live migration, user can migrate SW vhost backend\n+VM to vDPA backend VM and vice versa. Here are the detailed steps. Assume A is\n+the source host with SW vhost VM and B is the destination host with vDPA.\n+\n+1. Start vdpa sample and launch a VM with exact same parameters as the VM on A,\n+   in migration-listen mode:\n+\n+.. code-block:: console\n+\n+        B: <qemu-command-line> -incoming tcp:0:4444 (or other PORT))\n+\n+2. Start the migration (on source host):\n+\n+.. code-block:: console\n+\n+        A: (qemu) migrate -d tcp:<B ip>:4444 (or other PORT)\n+\n+3. Check the status (on source host):\n+\n+.. code-block:: console\n+\n+        A: (qemu) info migrate\ndiff --git a/examples/Makefile b/examples/Makefile\nindex 481720cb6..356fcb1cd 100644\n--- a/examples/Makefile\n+++ b/examples/Makefile\n@@ -65,7 +65,7 @@ ifeq ($(CONFIG_RTE_LIBRTE_HASH),y)\n DIRS-$(CONFIG_RTE_LIBRTE_VHOST) += tep_termination\n endif\n DIRS-$(CONFIG_RTE_LIBRTE_TIMER) += timer\n-DIRS-$(CONFIG_RTE_LIBRTE_VHOST) += vhost vhost_scsi\n+DIRS-$(CONFIG_RTE_LIBRTE_VHOST) += vhost vhost_scsi vdpa\n ifeq ($(CONFIG_RTE_LIBRTE_CRYPTODEV),y)\n DIRS-$(CONFIG_RTE_LIBRTE_VHOST) += vhost_crypto\n endif\ndiff --git a/examples/vdpa/Makefile b/examples/vdpa/Makefile\nnew file mode 100644\nindex 000000000..42672a2bc\n--- /dev/null\n+++ b/examples/vdpa/Makefile\n@@ -0,0 +1,32 @@\n+# SPDX-License-Identifier: BSD-3-Clause\n+# Copyright(c) 2018 Intel Corporation\n+\n+ifeq ($(RTE_SDK),)\n+$(error \"Please define RTE_SDK environment variable\")\n+endif\n+\n+# Default target, can be overridden by command line or environment\n+RTE_TARGET ?= x86_64-native-linuxapp-gcc\n+\n+include $(RTE_SDK)/mk/rte.vars.mk\n+\n+ifneq ($(CONFIG_RTE_EXEC_ENV),\"linuxapp\")\n+$(info This application can only operate in a linuxapp environment, \\\n+please change the definition of the RTE_TARGET environment variable)\n+all:\n+else\n+\n+# binary name\n+APP = vdpa\n+\n+# all source are stored in SRCS-y\n+SRCS-y := main.c\n+\n+CFLAGS += -O2 -D_FILE_OFFSET_BITS=64\n+CFLAGS += $(WERROR_FLAGS)\n+CFLAGS += -D_GNU_SOURCE\n+CFLAGS += -DALLOW_EXPERIMENTAL_API\n+\n+include $(RTE_SDK)/mk/rte.extapp.mk\n+\n+endif\ndiff --git a/examples/vdpa/main.c b/examples/vdpa/main.c\nnew file mode 100644\nindex 000000000..898286e30\n--- /dev/null\n+++ b/examples/vdpa/main.c\n@@ -0,0 +1,466 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2018 Intel Corporation\n+ */\n+\n+#include <getopt.h>\n+#include <signal.h>\n+#include <stdint.h>\n+#include <string.h>\n+#include <unistd.h>\n+\n+#include <rte_ethdev.h>\n+#include <rte_malloc.h>\n+#include <rte_vhost.h>\n+#include <rte_vdpa.h>\n+#include <rte_pci.h>\n+\n+#include <cmdline_parse.h>\n+#include <cmdline_socket.h>\n+#include <cmdline_parse_string.h>\n+#include <cmdline.h>\n+\n+#define MAX_PATH_LEN 128\n+#define MAX_VDPA_SAMPLE_PORTS 1024\n+#define RTE_LOGTYPE_VDPA RTE_LOGTYPE_USER1\n+\n+struct vdpa_port {\n+\tchar ifname[MAX_PATH_LEN];\n+\tint did;\n+\tint vid;\n+\tuint64_t flags;\n+};\n+\n+struct vdpa_port vports[MAX_VDPA_SAMPLE_PORTS];\n+\n+static char iface[MAX_PATH_LEN];\n+static int dev_total;\n+static int devcnt;\n+static int interactive;\n+static int client_mode;\n+\n+/* display usage */\n+static void\n+vdpa_usage(const char *prgname)\n+{\n+\tprintf(\"Usage: %s [EAL options] -- \"\n+\t\t\t\t \"\t--interactive|-i: run in interactive mode.\\n\"\n+\t\t\t\t \"\t--iface <path>: specify the path prefix of the socket files, e.g. /tmp/vhost-user-.\\n\"\n+\t\t\t\t \"\t--client: register a vhost-user socket as client mode.\\n\",\n+\t\t\t\t prgname);\n+}\n+\n+static int\n+parse_args(int argc, char **argv)\n+{\n+\tstatic const char *short_option = \"i\";\n+\tstatic struct option long_option[] = {\n+\t\t{\"iface\", required_argument, NULL, 0},\n+\t\t{\"interactive\", no_argument, &interactive, 1},\n+\t\t{\"client\", no_argument, &client_mode, 1},\n+\t\t{NULL, 0, 0, 0},\n+\t};\n+\tint opt, idx;\n+\tchar *prgname = argv[0];\n+\n+\twhile ((opt = getopt_long(argc, argv, short_option, long_option, &idx))\n+\t\t\t!= EOF) {\n+\t\tswitch (opt) {\n+\t\tcase 'i':\n+\t\t\tprintf(\"Interactive-mode selected\\n\");\n+\t\t\tinteractive = 1;\n+\t\t\tbreak;\n+\t\t/* long options */\n+\t\tcase 0:\n+\t\t\tif (strncmp(long_option[idx].name, \"iface\",\n+\t\t\t\t\t\tMAX_PATH_LEN) == 0) {\n+\t\t\t\tstrncpy(iface, optarg, MAX_PATH_LEN);\n+\t\t\t\tprintf(\"iface %s\\n\", iface);\n+\t\t\t}\n+\t\t\tif (!strcmp(long_option[idx].name, \"interactive\")) {\n+\t\t\t\tprintf(\"Interactive-mode selected\\n\");\n+\t\t\t\tinteractive = 1;\n+\t\t\t}\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\tvdpa_usage(prgname);\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\tif (iface[0] == '\\0' && interactive == 0) {\n+\t\tvdpa_usage(prgname);\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+data_init(void)\n+{\n+\tdev_total = rte_vdpa_get_device_num();\n+\tif (dev_total <= 0) {\n+\t\tprintf(\"No available vdpa device found\\n\");\n+\t\treturn -1;\n+\t}\n+\tdevcnt = 0;\n+\tinteractive = 0;\n+\tmemset(iface, 0, sizeof(iface));\n+\tmemset(vports, 0, sizeof(vports));\n+\treturn 0;\n+}\n+\n+static int\n+new_device(int vid)\n+{\n+\tchar ifname[MAX_PATH_LEN];\n+\tint i;\n+\n+\trte_vhost_get_ifname(vid, ifname, sizeof(ifname));\n+\tfor (i = 0; i < MAX_VDPA_SAMPLE_PORTS; i++) {\n+\t\tif (strncmp(ifname, vports[i].ifname, MAX_PATH_LEN) == 0) {\n+\t\t\tprintf(\"\\nnew port %s, did: %d\\n\",\n+\t\t\t\t\tifname, vports[i].did);\n+\t\t\tvports[i].vid = vid;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\tif (i >= MAX_VDPA_SAMPLE_PORTS)\n+\t\treturn -1;\n+\n+\treturn 0;\n+}\n+\n+static void\n+destroy_device(int vid)\n+{\n+\tchar ifname[MAX_PATH_LEN];\n+\tint i;\n+\n+\trte_vhost_get_ifname(vid, ifname, sizeof(ifname));\n+\tfor (i = 0; i < MAX_VDPA_SAMPLE_PORTS; i++) {\n+\t\tif (strcmp(ifname, vports[i].ifname) == 0) {\n+\t\t\tprintf(\"\\ndestroy port %s, did: %d\\n\",\n+\t\t\t\t\tifname, vports[i].did);\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+}\n+\n+static const struct vhost_device_ops vdpa_sample_devops = {\n+\t.new_device = new_device,\n+\t.destroy_device = destroy_device,\n+};\n+\n+static int\n+start_vdpa(struct vdpa_port *vport)\n+{\n+\tint ret;\n+\tchar *socket_path = vport->ifname;\n+\tint did = vport->did;\n+\n+\tif (client_mode)\n+\t\tvport->flags |= RTE_VHOST_USER_CLIENT;\n+\n+\tif (access(socket_path, F_OK) != -1 && !client_mode) {\n+\t\tRTE_LOG(ERR, VDPA,\n+\t\t\t\"%s exists, please remove it or specify another file and try again.\\n\",\n+\t\t\tsocket_path);\n+\t\treturn -1;\n+\t}\n+\tret = rte_vhost_driver_register(socket_path, vport->flags);\n+\tif (ret != 0)\n+\t\trte_exit(EXIT_FAILURE,\n+\t\t\t\"register driver failed: %s\\n\",\n+\t\t\tsocket_path);\n+\n+\tret = rte_vhost_driver_callback_register(socket_path,\n+\t\t\t&vdpa_sample_devops);\n+\tif (ret != 0)\n+\t\trte_exit(EXIT_FAILURE,\n+\t\t\t\"register driver ops failed: %s\\n\",\n+\t\t\tsocket_path);\n+\n+\tret = rte_vhost_driver_attach_vdpa_device(socket_path, did);\n+\tif (ret != 0)\n+\t\trte_exit(EXIT_FAILURE,\n+\t\t\t\"attach vdpa device failed: %s\\n\",\n+\t\t\tsocket_path);\n+\n+\tif (rte_vhost_driver_start(socket_path) < 0)\n+\t\trte_exit(EXIT_FAILURE,\n+\t\t\t\"start vhost driver failed: %s\\n\",\n+\t\t\tsocket_path);\n+\treturn 0;\n+}\n+\n+static void\n+close_vdpa(struct vdpa_port *vport)\n+{\n+\tint ret;\n+\tchar *socket_path = vport->ifname;\n+\n+\tret = rte_vhost_driver_detach_vdpa_device(socket_path);\n+\tif (ret != 0)\n+\t\tRTE_LOG(ERR, VDPA,\n+\t\t\t\t\"detach vdpa device failed: %s\\n\",\n+\t\t\t\tsocket_path);\n+\n+\tret = rte_vhost_driver_unregister(socket_path);\n+\tif (ret != 0)\n+\t\tRTE_LOG(ERR, VDPA,\n+\t\t\t\t\"Fail to unregister vhost driver for %s.\\n\",\n+\t\t\t\tsocket_path);\n+}\n+\n+static void\n+vdpa_sample_quit(void)\n+{\n+\tint i;\n+\tfor (i = 0; i < RTE_MIN(MAX_VDPA_SAMPLE_PORTS, dev_total); i++) {\n+\t\tif (vports[i].ifname[0] != '\\0')\n+\t\t\tclose_vdpa(&vports[i]);\n+\t}\n+}\n+\n+static void\n+signal_handler(int signum)\n+{\n+\tif (signum == SIGINT || signum == SIGTERM) {\n+\t\tprintf(\"\\nSignal %d received, preparing to exit...\\n\", signum);\n+\t\tvdpa_sample_quit();\n+\t\texit(0);\n+\t}\n+}\n+\n+/* interactive cmds */\n+\n+/* *** Help command with introduction. *** */\n+struct cmd_help_result {\n+\tcmdline_fixed_string_t help;\n+};\n+\n+static void cmd_help_parsed(__attribute__((unused)) void *parsed_result,\n+\t\tstruct cmdline *cl,\n+\t\t__attribute__((unused)) void *data)\n+{\n+\tcmdline_printf(\n+\t\tcl,\n+\t\t\"\\n\"\n+\t\t\"The following commands are currently available:\\n\\n\"\n+\t\t\"Control:\\n\"\n+\t\t\"    help                                      : Show interactive instructions.\\n\"\n+\t\t\"    list                                      : list all available vdpa devices.\\n\"\n+\t\t\"    create <socket file> <vdev addr>          : create a new vdpa port.\\n\"\n+\t\t\"    quit                                      : exit vdpa sample app.\\n\"\n+\t);\n+}\n+\n+cmdline_parse_token_string_t cmd_help_help =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_help_result, help, \"help\");\n+\n+cmdline_parse_inst_t cmd_help = {\n+\t.f = cmd_help_parsed,\n+\t.data = NULL,\n+\t.help_str = \"show help\",\n+\t.tokens = {\n+\t\t(void *)&cmd_help_help,\n+\t\tNULL,\n+\t},\n+};\n+\n+/* *** List all available vdpa devices *** */\n+struct cmd_list_result {\n+\tcmdline_fixed_string_t action;\n+};\n+\n+static void cmd_list_vdpa_devices_parsed(\n+\t\t__attribute__((unused)) void *parsed_result,\n+\t\tstruct cmdline *cl,\n+\t\t__attribute__((unused)) void *data)\n+{\n+\tint did;\n+\tuint32_t queue_num;\n+\tuint64_t features;\n+\tstruct rte_vdpa_device *vdev;\n+\tstruct rte_pci_addr addr;\n+\n+\tcmdline_printf(cl, \"device id\\tdevice address\\tqueue num\\tsupported features\\n\");\n+\tfor (did = 0; did < dev_total; did++) {\n+\t\tvdev = rte_vdpa_get_device(did);\n+\t\tif (!vdev)\n+\t\t\tcontinue;\n+\t\tif (vdev->ops->get_queue_num(did, &queue_num) < 0) {\n+\t\t\tRTE_LOG(ERR, VDPA,\n+\t\t\t\t\"failed to get vdpa queue number \"\n+\t\t\t\t\"for device id %d.\\n\", did);\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (vdev->ops->get_features(did, &features) < 0) {\n+\t\t\tRTE_LOG(ERR, VDPA,\n+\t\t\t\t\"failed to get vdpa features \"\n+\t\t\t\t\"for device id %d.\\n\", did);\n+\t\t\tcontinue;\n+\t\t}\n+\t\taddr = vdev->addr.pci_addr;\n+\t\tcmdline_printf(cl,\n+\t\t\t\"%d\\t\\t\" PCI_PRI_FMT \"\\t%\" PRIu32 \"\\t\\t0x%\" PRIx64 \"\\n\",\n+\t\t\tdid, addr.domain, addr.bus, addr.devid,\n+\t\t\taddr.function, queue_num, features);\n+\t}\n+}\n+\n+cmdline_parse_token_string_t cmd_action_list =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_list_result, action, \"list\");\n+\n+cmdline_parse_inst_t cmd_list_vdpa_devices = {\n+\t.f = cmd_list_vdpa_devices_parsed,\n+\t.data = NULL,\n+\t.help_str = \"list all available vdpa devices\",\n+\t.tokens = {\n+\t\t(void *)&cmd_action_list,\n+\t\tNULL,\n+\t},\n+};\n+\n+/* *** Create new vdpa port *** */\n+struct cmd_create_result {\n+\tcmdline_fixed_string_t action;\n+\tcmdline_fixed_string_t socket_path;\n+\tcmdline_fixed_string_t bdf;\n+};\n+\n+static void cmd_create_vdpa_port_parsed(void *parsed_result,\n+\t\tstruct cmdline *cl,\n+\t\t__attribute__((unused)) void *data)\n+{\n+\tint did;\n+\tstruct cmd_create_result *res = parsed_result;\n+\tstruct rte_vdpa_dev_addr addr;\n+\n+\tstrncpy(vports[devcnt].ifname, res->socket_path, MAX_PATH_LEN);\n+\tif (rte_pci_addr_parse(res->bdf, &addr.pci_addr) != 0) {\n+\t\tcmdline_printf(cl, \"Unable to parse the given bdf.\\n\");\n+\t\treturn;\n+\t}\n+\taddr.type = PCI_ADDR;\n+\tdid = rte_vdpa_find_device_id(&addr);\n+\tif (did < 0) {\n+\t\tcmdline_printf(cl, \"Unable to find vdpa devide id.\\n\");\n+\t\treturn;\n+\t}\n+\n+\tvports[devcnt].did = did;\n+\n+\tif (start_vdpa(&vports[devcnt]) == 0)\n+\t\tdevcnt++;\n+}\n+\n+cmdline_parse_token_string_t cmd_action_create =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_create_result, action, \"create\");\n+cmdline_parse_token_string_t cmd_socket_path =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_create_result, socket_path, NULL);\n+cmdline_parse_token_string_t cmd_bdf =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_create_result, bdf, NULL);\n+\n+cmdline_parse_inst_t cmd_create_vdpa_port = {\n+\t.f = cmd_create_vdpa_port_parsed,\n+\t.data = NULL,\n+\t.help_str = \"create a new vdpa port\",\n+\t.tokens = {\n+\t\t(void *)&cmd_action_create,\n+\t\t(void *)&cmd_socket_path,\n+\t\t(void *)&cmd_bdf,\n+\t\tNULL,\n+\t},\n+};\n+\n+/* *** QUIT *** */\n+struct cmd_quit_result {\n+\tcmdline_fixed_string_t quit;\n+};\n+\n+static void cmd_quit_parsed(__attribute__((unused)) void *parsed_result,\n+\t\tstruct cmdline *cl,\n+\t\t__attribute__((unused)) void *data)\n+{\n+\tvdpa_sample_quit();\n+\tcmdline_quit(cl);\n+}\n+\n+cmdline_parse_token_string_t cmd_quit_quit =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, \"quit\");\n+\n+cmdline_parse_inst_t cmd_quit = {\n+\t.f = cmd_quit_parsed,\n+\t.data = NULL,\n+\t.help_str = \"quit: exit application\",\n+\t.tokens = {\n+\t\t(void *)&cmd_quit_quit,\n+\t\tNULL,\n+\t},\n+};\n+cmdline_parse_ctx_t main_ctx[] = {\n+\t(cmdline_parse_inst_t *)&cmd_help,\n+\t(cmdline_parse_inst_t *)&cmd_list_vdpa_devices,\n+\t(cmdline_parse_inst_t *)&cmd_create_vdpa_port,\n+\t(cmdline_parse_inst_t *)&cmd_quit,\n+\tNULL,\n+};\n+\n+int\n+main(int argc, char *argv[])\n+{\n+\tchar ch;\n+\tint i;\n+\tint ret;\n+\tstruct cmdline *cl;\n+\n+\tret = rte_eal_init(argc, argv);\n+\tif (ret < 0)\n+\t\trte_exit(EXIT_FAILURE, \"eal init failed\\n\");\n+\targc -= ret;\n+\targv += ret;\n+\n+\tdata_init();\n+\n+\tsignal(SIGINT, signal_handler);\n+\tsignal(SIGTERM, signal_handler);\n+\n+\tret = parse_args(argc, argv);\n+\tif (ret < 0)\n+\t\trte_exit(EXIT_FAILURE, \"invalid argument\\n\");\n+\n+\tif (interactive == 1) {\n+\t\tcl = cmdline_stdin_new(main_ctx, \"vdpa> \");\n+\t\tif (cl == NULL)\n+\t\t\trte_panic(\"Cannot create cmdline instance\\n\");\n+\t\tcmdline_interact(cl);\n+\t\tcmdline_stdin_exit(cl);\n+\t} else {\n+\t\tfor (i = 0; i < RTE_MIN(MAX_VDPA_SAMPLE_PORTS, dev_total);\n+\t\t\t\ti++) {\n+\t\t\tvports[i].did = i;\n+\t\t\tsnprintf(vports[i].ifname, MAX_PATH_LEN, \"%s%d\",\n+\t\t\t\t\tiface, i);\n+\n+\t\t\tstart_vdpa(&vports[i]);\n+\t\t}\n+\n+\t\tprintf(\"enter \\'q\\' to quit\\n\");\n+\t\twhile (scanf(\"%c\", &ch)) {\n+\t\t\tif (ch == 'q')\n+\t\t\t\tbreak;\n+\t\t\twhile (ch != '\\n') {\n+\t\t\t\tif (scanf(\"%c\", &ch))\n+\t\t\t\t\tprintf(\"%c\", ch);\n+\t\t\t}\n+\t\t\tprintf(\"enter \\'q\\' to quit\\n\");\n+\t\t}\n+\t\tvdpa_sample_quit();\n+\t}\n+\n+\treturn 0;\n+}\ndiff --git a/examples/vdpa/meson.build b/examples/vdpa/meson.build\nnew file mode 100644\nindex 000000000..2e38a069f\n--- /dev/null\n+++ b/examples/vdpa/meson.build\n@@ -0,0 +1,16 @@\n+# SPDX-License-Identifier: BSD-3-Clause\n+# Copyright(c) 2018 Intel Corporation\n+\n+# meson file, for building this example as part of a main DPDK build.\n+#\n+# To build this example as a standalone application with an already-installed\n+# DPDK instance, use 'make'\n+\n+if host_machine.system() != 'linux'\n+\tbuild = false\n+endif\n+deps += 'vhost'\n+allow_experimental_apis = true\n+sources = files(\n+\t'main.c'\n+)\n\\ No newline at end of file\n",
    "prefixes": [
        "v6",
        "2/2"
    ]
}