get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 34924,
    "url": "http://patches.dpdk.org/api/patches/34924/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20180204145542.38345-4-xiao.w.wang@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": "<20180204145542.38345-4-xiao.w.wang@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20180204145542.38345-4-xiao.w.wang@intel.com",
    "date": "2018-02-04T14:55:42",
    "name": "[dpdk-dev,3/3] examples/vdpa: add a new sample for vdpa",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "24b436b3c7ec6273d8195bd1313b01ef7e25803c",
    "submitter": {
        "id": 281,
        "url": "http://patches.dpdk.org/api/people/281/?format=api",
        "name": "Xiao Wang",
        "email": "xiao.w.wang@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/20180204145542.38345-4-xiao.w.wang@intel.com/mbox/",
    "series": [],
    "comments": "http://patches.dpdk.org/api/patches/34924/comments/",
    "check": "fail",
    "checks": "http://patches.dpdk.org/api/patches/34924/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 E49BF1B28D;\n\tSun,  4 Feb 2018 15:56:52 +0100 (CET)",
            "from mga02.intel.com (mga02.intel.com [134.134.136.20])\n\tby dpdk.org (Postfix) with ESMTP id 6BA971B1D3\n\tfor <dev@dpdk.org>; Sun,  4 Feb 2018 15:56:50 +0100 (CET)",
            "from orsmga001.jf.intel.com ([10.7.209.18])\n\tby orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t04 Feb 2018 06:56:50 -0800",
            "from dpdk-xiao-1.sh.intel.com ([10.67.110.153])\n\tby orsmga001.jf.intel.com with ESMTP; 04 Feb 2018 06:56:48 -0800"
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.46,458,1511856000\"; d=\"scan'208\";a=\"28692314\"",
        "From": "Xiao Wang <xiao.w.wang@intel.com>",
        "To": "dev@dpdk.org",
        "Cc": "jianfeng.tan@intel.com, tiwei.bie@intel.com, maxime.coquelin@redhat.com, \n\tyliu@fridaylinux.org, cunming.liang@intel.com, dan.daly@intel.com,\n\tzhihong.wang@intel.com, Xiao Wang <xiao.w.wang@intel.com>",
        "Date": "Sun,  4 Feb 2018 22:55:42 +0800",
        "Message-Id": "<20180204145542.38345-4-xiao.w.wang@intel.com>",
        "X-Mailer": "git-send-email 2.15.1",
        "In-Reply-To": "<20180204145542.38345-1-xiao.w.wang@intel.com>",
        "References": "<20180204145542.38345-1-xiao.w.wang@intel.com>",
        "Subject": "[dpdk-dev] [PATCH 3/3] examples/vdpa: add a new sample for vdpa",
        "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://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "This patch adds a sample which creates vhost-user socket based on\nvdpa driver. vdpa driver can help to set up vhost datapath so this\napp doesn't need to spend a dedicated worker thread on vhost\nenqueue/dequeue operations.\n\nBelow are setup steps for your reference:\n\n1. Make sure your kernnel vhost module and QEMU support vIOMMU.\n   - OS: CentOS 7.4\n   - QEMU: 2.10.1\n   - Guest OS: CentOS 7.2\n   - Nested VM OS: CentOS 7.2\n\n2. enable VT-x feature for vCPU in VM.\n   modprobe kvm_intel nested=1\n\n3. Start a VM with a virtio-net-pci device.\n   ./qemu-2.10.1/x86_64-softmmu/qemu-system-x86_64 -enable-kvm -cpu host \\\n   <snip>\n   -machine q35 \\\n   -device intel-iommu \\\n   -netdev tap,id=mytap,ifname=vdpa,vhostforce=on \\\n   -device virtio-net-pci,netdev=mytap,mac=00:aa:bb:cc:dd:ee,\\\n   disable-modern=off,disable-legacy=on,iommu_platform=on \\\n\n4. Bind VFIO-pci to virtio_net_pci device\n   a) login to VM;\n   b) modprobe vfio-pci\n   c) rmmod vfio_iommu_type1\n   d) modprobe vfio_iommu_type1 allow_unsafe_interrupts=1\n   e) ./usertools/dpdk-devbind.py -b vfio-pci 00:03.0\n\n5. Start vdpa sample\n   ./examples/vdpa/build/vdpa -c 0x2 -n 4 --socket-mem 1024 --no-pci \\\n    --vdev \"net_vdpa_virtio_pci0,bdf=0000:00:03.0\" -- --bdf 0000:00:03.0 \\\n    --iface /tmp/vhost-user- --devcnt 1  --queue 1\n\n6. Start nested VM\n   ./qemu-2.10.1/x86_64-softmmu/qemu-system-x86_64 -cpu host -enable-kvm \\\n   <snip>\n   -mem-prealloc \\\n   -chardev socket,id=char0,path=/tmp/vhost-user-0 \\\n   -netdev type=vhost-user,id=vdpa,chardev=char0,vhostforce \\\n   -device virtio-net-pci,netdev=vdpa,mac=00:aa:bb:cc:dd:ee \\\n\n7. Login the nested VM, and verify the virtio in nested VM can communicate\n   with tap device on the host.\n\nSigned-off-by: Xiao Wang <xiao.w.wang@intel.com>\n---\n examples/vdpa/Makefile |  32 ++++\n examples/vdpa/main.c   | 387 +++++++++++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 419 insertions(+)\n create mode 100644 examples/vdpa/Makefile\n create mode 100644 examples/vdpa/main.c",
    "diff": "diff --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..1c9143469\n--- /dev/null\n+++ b/examples/vdpa/main.c\n@@ -0,0 +1,387 @@\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+\n+#define NUM_MBUFS 8191\n+#define MBUF_CACHE_SIZE 250\n+\n+#define RX_RING_SIZE 128\n+#define TX_RING_SIZE 128\n+\n+#define MAX_PATH_LEN 128\n+#define MAX_VDPA_SAMPLE_PORTS 1024\n+\n+struct vdpa_port {\n+\tchar ifname[MAX_PATH_LEN];\n+\tint eid;\n+\tint did;\n+\tint vid;\n+};\n+\n+struct vdpa_port vports[MAX_VDPA_SAMPLE_PORTS];\n+\n+struct rte_vdpa_eng_attr attr;\n+struct rte_vdpa_eng_addr dev_id;\n+char iface[MAX_PATH_LEN];\n+int queue;\n+int devcnt;\n+\n+/* display usage */\n+static void\n+vdpa_usage(const char *prgname)\n+{\n+\tprintf(\"%s [EAL options]\"\n+\t\t\" -- --bdf B:D:F --iface <path> --devcnt ND  --queue NQ\\n\"\n+\t\t\" --bdf B:D:F, the PCI device used for vdpa\\n\"\n+\t\t\" --iface <path>: The path of the socket file\\n\"\n+\t\t\" --devcnt ND: number of vhost sockets to be created, default 1\\n\"\n+\t\t\" --queue NQ: number of queue pairs to be configured, default 1\\n\",\n+\t\tprgname);\n+}\n+\n+static int\n+get_unsigned(const char *str, int base)\n+{\n+\tunsigned long num;\n+\tchar *end = NULL;\n+\n+\terrno = 0;\n+\tnum = strtoul(str, &end, base);\n+\tif (str[0] == '\\0' || end == NULL || *end != '\\0' || errno != 0)\n+\t\treturn -1;\n+\n+\treturn num;\n+}\n+\n+static int\n+parse_args(int argc, char **argv)\n+{\n+\tstatic const char *short_option = \"\";\n+\tstatic struct option long_option[] = {\n+\t\t{\"bdf\", required_argument, NULL, 0},\n+\t\t{\"queue\", required_argument, NULL, 0},\n+\t\t{\"devcnt\", required_argument, NULL, 0},\n+\t\t{\"iface\", required_argument, NULL, 0},\n+\t\t{NULL, 0, 0, 0},\n+\t};\n+\tchar str[MAX_PATH_LEN];\n+\tint opt, idx;\n+\tint num[4] = {0};\n+\tint i, j;\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 0:\n+\t\t\tif (strncmp(long_option[idx].name, \"bdf\",\n+\t\t\t\t\t\tMAX_PATH_LEN) == 0) {\n+\t\t\t\tstrcpy(str, optarg);\n+\t\t\t\ti = strlen(str) - 1;\n+\t\t\t\tj = 3;\n+\t\t\t\twhile (i > 0 && j >= 0) {\n+\t\t\t\t\twhile ((str[i - 1] != ':'\n+\t\t\t\t\t\t\t&& str[i - 1] != '.')\n+\t\t\t\t\t\t\t&& i > 0)\n+\t\t\t\t\t\ti--;\n+\t\t\t\t\tnum[j--] = get_unsigned(&str[i], 16);\n+\t\t\t\t\ti--;\n+\t\t\t\t\tif (i >= 0)\n+\t\t\t\t\t\tstr[i] = '\\0';\n+\t\t\t\t}\n+\t\t\t\tdev_id.pci_addr.domain = num[0];\n+\t\t\t\tdev_id.pci_addr.bus = num[1];\n+\t\t\t\tdev_id.pci_addr.devid = num[2];\n+\t\t\t\tdev_id.pci_addr.function = num[3];\n+\t\t\t\tprintf(\"bdf %04x:%02x:%02x.%02x\\n\",\n+\t\t\t\t\t\tdev_id.pci_addr.domain,\n+\t\t\t\t\t\tdev_id.pci_addr.bus,\n+\t\t\t\t\t\tdev_id.pci_addr.devid,\n+\t\t\t\t\t\tdev_id.pci_addr.function);\n+\t\t\t} else if (strncmp(long_option[idx].name, \"queue\",\n+\t\t\t\t\t\tMAX_PATH_LEN) == 0) {\n+\t\t\t\tqueue = get_unsigned(optarg, 10);\n+\t\t\t\tprintf(\"queue %d\\n\", queue);\n+\t\t\t} else if (strncmp(long_option[idx].name, \"devcnt\",\n+\t\t\t\t\t\tMAX_PATH_LEN) == 0) {\n+\t\t\t\tdevcnt = get_unsigned(optarg, 10);\n+\t\t\t\tprintf(\"devcnt %d\\n\", devcnt);\n+\t\t\t} else if (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+\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 (queue <= 0 || devcnt <= 0 || *iface == '\\0') {\n+\t\tvdpa_usage(prgname);\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static void\n+data_init(void)\n+{\n+\tdevcnt = 1;\n+\tqueue = 1;\n+\tmemset(&dev_id, 0, sizeof(dev_id));\n+\tmemset(iface, 0, MAX_PATH_LEN * sizeof(iface[0]));\n+\tmemset(vports, 0, MAX_VDPA_SAMPLE_PORTS * sizeof(vports[0]));\n+\n+\treturn;\n+}\n+\n+static void\n+signal_handler(int signum)\n+{\n+\tuint16_t portid, nb_ports;\n+\n+\tif (signum == SIGINT || signum == SIGTERM) {\n+\t\tprintf(\"\\nSignal %d received, preparing to exit...\\n\",\n+\t\t\t\tsignum);\n+\t\tnb_ports = rte_eth_dev_count();\n+\t\tfor (portid = 0; portid < nb_ports; portid++) {\n+\t\t\tprintf(\"Closing port %d...\\n\", portid);\n+\t\t\trte_eth_dev_stop(portid);\n+\t\t\trte_eth_dev_close(portid);\n+\t\t}\n+\t\texit(0);\n+\t}\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 (strcmp(ifname, vports[i].ifname) == 0) {\n+\t\t\tprintf(\"\\nport %s connected, eid: %d, did %d\\n\",\n+\t\t\t\t\tifname, vports[i].eid, 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(\"\\nport %s disconnected, eid: %d, did %d\\n\",\n+\t\t\t\t\tifname, vports[i].eid, vports[i].did);\n+\t\t\tvports[i].vid = vid;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\treturn;\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+\t.vring_state_changed = NULL,\n+\t.features_changed = NULL,\n+\t.new_connection = NULL,\n+\t.destroy_connection = NULL,\n+};\n+\n+static const struct rte_eth_conf port_conf_default = {\n+\t.rxmode = {\n+\t\t.max_rx_pkt_len = ETHER_MAX_LEN,\n+\t\t.ignore_offload_bitfield = 1,\n+\t},\n+};\n+\n+static inline int\n+port_init(uint16_t port, struct rte_mempool *mbuf_pool)\n+{\n+\tuint16_t rx_rings = 1, tx_rings = 1;\n+\tuint16_t nb_rxd = RX_RING_SIZE;\n+\tuint16_t nb_txd = TX_RING_SIZE;\n+\tint retval;\n+\tuint16_t q;\n+\tstruct rte_eth_dev_info dev_info;\n+\tstruct rte_eth_txconf txconf;\n+\tstruct ether_addr addr;\n+\n+\tif (port >= rte_eth_dev_count())\n+\t\treturn -1;\n+\n+\trte_eth_dev_info_get(port, &dev_info);\n+\n+\t/* Configure the Ethernet device. */\n+\tretval = rte_eth_dev_configure(port, rx_rings, tx_rings,\n+\t\t\t&port_conf_default);\n+\tif (retval < 0)\n+\t\treturn retval;\n+\n+\t/* Allocate and set up 1 Rx queue per Ethernet port. */\n+\tfor (q = 0; q < rx_rings; q++) {\n+\t\tretval = rte_eth_rx_queue_setup(port, q, nb_rxd,\n+\t\t\t\trte_eth_dev_socket_id(port), NULL, mbuf_pool);\n+\t\tif (retval < 0)\n+\t\t\treturn retval;\n+\t}\n+\n+\ttxconf = dev_info.default_txconf;\n+\t/* Allocate and set up 1 Tx queue per Ethernet port. */\n+\tfor (q = 0; q < tx_rings; q++) {\n+\t\tretval = rte_eth_tx_queue_setup(port, q, nb_txd,\n+\t\t\t\trte_eth_dev_socket_id(port), &txconf);\n+\t\tif (retval < 0)\n+\t\t\treturn retval;\n+\t}\n+\n+\t/* Start the Ethernet port. */\n+\tretval = rte_eth_dev_start(port);\n+\tif (retval < 0)\n+\t\treturn retval;\n+\n+\t/* Display the port MAC address. */\n+\trte_eth_macaddr_get(port, &addr);\n+\tprintf(\"Port %u MAC: %02\" PRIx8 \" %02\" PRIx8 \" %02\" PRIx8\n+\t\t\t   \" %02\" PRIx8 \" %02\" PRIx8 \" %02\" PRIx8 \"\\n\",\n+\t\t\tport,\n+\t\t\taddr.addr_bytes[0], addr.addr_bytes[1],\n+\t\t\taddr.addr_bytes[2], addr.addr_bytes[3],\n+\t\t\taddr.addr_bytes[4], addr.addr_bytes[5]);\n+\n+\treturn 0;\n+}\n+\n+int\n+main(int argc, char *argv[])\n+{\n+\tchar ifname[MAX_PATH_LEN];\n+\tuint16_t nb_ports, portid;\n+\tstruct rte_mempool *mbuf_pool;\n+\tchar ch;\n+\tint i, eid, did;\n+\tint ret;\n+\tuint64_t flags = 0;\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+\tsignal(SIGINT, signal_handler);\n+\tsignal(SIGTERM, signal_handler);\n+\n+\tnb_ports = rte_eth_dev_count();\n+\tmbuf_pool = rte_pktmbuf_pool_create(\"MBUF_POOL\", NUM_MBUFS * nb_ports,\n+\t\tMBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());\n+\n+\t/* Initialize all ports. */\n+\tfor (portid = 0; portid < nb_ports; portid++)\n+\t\tif (port_init(portid, mbuf_pool) != 0)\n+\t\t\trte_exit(EXIT_FAILURE, \"Cannot init port %d\\n\",\n+\t\t\t\t\tportid);\n+\n+\tdata_init();\n+\n+\tret = parse_args(argc, argv);\n+\tif (ret < 0)\n+\t\trte_exit(EXIT_FAILURE, \"invalid argument\\n\");\n+\n+\teid = rte_vdpa_find_engine_id(&dev_id);\n+\tif (eid < 0)\n+\t\trte_exit(EXIT_FAILURE, \"no vDPA engine found\\n\");\n+\n+\tprintf(\"\\nuse engine %d to create vhost socket\\n\", eid);\n+\trte_vdpa_info_query(eid, &attr);\n+\tif (devcnt > (int)attr.dev_num)\n+\t\trte_exit(EXIT_FAILURE, \"not enough devices in engine\\n\");\n+\n+\tif (queue > (int)attr.queue_num)\n+\t\trte_exit(EXIT_FAILURE, \"not enough queues in engine\\n\");\n+\n+\tfor (i = 0; i <  RTE_MIN(MAX_VDPA_SAMPLE_PORTS, devcnt); i++) {\n+\t\tsnprintf(ifname, sizeof(ifname), \"%s%d\", iface, i);\n+\t\tdid = i;\n+\t\tvports[i].eid = eid;\n+\t\tvports[i].did = did;\n+\t\tstrcpy(vports[i].ifname, ifname);\n+\n+\t\tret = rte_vhost_driver_register(ifname, flags);\n+\t\tif (ret != 0)\n+\t\t\trte_exit(EXIT_FAILURE,\n+\t\t\t\t\t\"register driver failed: %s\\n\",\n+\t\t\t\t\tifname);\n+\n+\t\tret = rte_vhost_driver_callback_register(ifname,\n+\t\t\t\t&vdpa_sample_devops);\n+\t\tif (ret != 0)\n+\t\t\trte_exit(EXIT_FAILURE,\n+\t\t\t\t\t\"register driver ops failed: %s\\n\",\n+\t\t\t\t\tifname);\n+\n+\t\trte_vhost_driver_set_vdpa_eid(ifname, eid);\n+\t\trte_vhost_driver_set_vdpa_did(ifname, did);\n+\t\t/*\n+\t\t * Configure vhost port with vDPA device's maximum capability.\n+\t\t * App has the flexibility to change the features, queue num.\n+\t\t */\n+\t\trte_vhost_driver_set_queue_num(ifname, attr.queue_num);\n+\t\trte_vhost_driver_set_features(ifname, attr.features);\n+\t\trte_vhost_driver_set_protocol_features(ifname,\n+\t\t\t\tattr.protocol_features);\n+\n+\t\tif (rte_vhost_driver_start(ifname) < 0)\n+\t\t\trte_exit(EXIT_FAILURE,\n+\t\t\t\t\t\"start vhost driver failed: %s\\n\",\n+\t\t\t\t\tifname);\n+\t}\n+\n+\tprintf(\"enter \\'q\\' to quit\\n\");\n+\twhile (scanf(\"%c\", &ch)) {\n+\t\tif (ch == 'q')\n+\t\t\tbreak;\n+\t\twhile (ch != '\\n')\n+\t\t\tscanf(\"%c\", &ch);\n+\t\tprintf(\"enter \\'q\\' to quit\\n\");\n+\t}\n+\n+\tfor (portid = 0; portid < nb_ports; portid++) {\n+\t\tprintf(\"Closing port %d...\\n\", portid);\n+\t\trte_eth_dev_stop(portid);\n+\t\trte_eth_dev_close(portid);\n+\t}\n+\n+\treturn 0;\n+}\n",
    "prefixes": [
        "dpdk-dev",
        "3/3"
    ]
}