get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 1158,
    "url": "https://patches.dpdk.org/api/patches/1158/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1415273365-3503-2-git-send-email-mukawa@igel.co.jp/",
    "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": "<1415273365-3503-2-git-send-email-mukawa@igel.co.jp>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1415273365-3503-2-git-send-email-mukawa@igel.co.jp",
    "date": "2014-11-06T11:29:25",
    "name": "[dpdk-dev,TEST] lib/librte_pmd_vhost: Add vhost pmd",
    "commit_ref": null,
    "pull_url": null,
    "state": "rfc",
    "archived": true,
    "hash": "38faff684272e006a2022db4e46ea35394afdedd",
    "submitter": {
        "id": 64,
        "url": "https://patches.dpdk.org/api/people/64/?format=api",
        "name": "Tetsuya Mukawa",
        "email": "mukawa@igel.co.jp"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1415273365-3503-2-git-send-email-mukawa@igel.co.jp/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/1158/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/1158/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 [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id 21F777F2D;\n\tThu,  6 Nov 2014 12:20:38 +0100 (CET)",
            "from mail-pa0-f44.google.com (mail-pa0-f44.google.com\n\t[209.85.220.44]) by dpdk.org (Postfix) with ESMTP id DF8717E80\n\tfor <dev@dpdk.org>; Thu,  6 Nov 2014 12:20:31 +0100 (CET)",
            "by mail-pa0-f44.google.com with SMTP id bj1so1089339pad.17\n\tfor <dev@dpdk.org>; Thu, 06 Nov 2014 03:29:58 -0800 (PST)",
            "from localhost.localdomain (napt.igel.co.jp. [219.106.231.132])\n\tby mx.google.com with ESMTPSA id\n\tl9sm5722468pbq.26.2014.11.06.03.29.56 for <multiple recipients>\n\t(version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128);\n\tThu, 06 Nov 2014 03:29:57 -0800 (PST)"
        ],
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20130820;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references;\n\tbh=/5g/HGPnFMEJy+2BKhN/4MRGaj+U9ryczVIMyLTZH/8=;\n\tb=WrKvyLObKfshHGrAkxWUg9qv074sReggj++gG9TCbY1NSMSZFkTIKJmgiH1Sf3NVMK\n\t5ZwvMVDEcbPlJLp2A/vu9jzxyUpW4a3MhlAvhTNWpMRHGfp0mMEDio/GRyko8dXl63nf\n\tZjtYDbv1bPAldhyIjwZJROUi6epGQbvTDVmTUn4+AiuTEmsIpwIBeRvvq6jE8RZgxm1k\n\t2e3wGw0u5s1yjZPKtNolT5u82wNUbh1hZHZhn+FiN+pSAsoUzqJJoP0gxn8f3aNoL8JE\n\txQJX+IXpAfxDJzJBGTIho89fsmXU+NfYpJWx1+/y1kCgzWKHieb8LhUiqlwGlF1QZmsb\n\tYvzw==",
        "X-Gm-Message-State": "ALoCoQnIoFQ3KfhcRUj63z25pihWvxMq0W/GnPMYxjyKkMs/F0rwx7mwfpoQFdA/WsFOIDhm6yin",
        "X-Received": "by 10.66.65.106 with SMTP id w10mr1517629pas.145.1415273398542; \n\tThu, 06 Nov 2014 03:29:58 -0800 (PST)",
        "From": "Tetsuya Mukawa <mukawa@igel.co.jp>",
        "To": "dev@dpdk.org",
        "Date": "Thu,  6 Nov 2014 20:29:25 +0900",
        "Message-Id": "<1415273365-3503-2-git-send-email-mukawa@igel.co.jp>",
        "X-Mailer": "git-send-email 1.9.1",
        "In-Reply-To": "<1415273365-3503-1-git-send-email-mukawa@igel.co.jp>",
        "References": "<1415273365-3503-1-git-send-email-mukawa@igel.co.jp>",
        "Cc": "nakajima.yoshihiro@lab.ntt.co.jp, masutani.hitoshi@lab.ntt.co.jp",
        "Subject": "[dpdk-dev] [TEST] lib/librte_pmd_vhost: Add vhost pmd",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "List-Unsubscribe": "<http://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": "<http://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": "The vhost pmd is a poll mode driver using librte_vhost library. It is\nalmost similar to a relation between librte_ring and ring pmd.\n\nHere is a command example of QEMU(above 2.1) to communicate with the vhost pmd.\nqemu-system-x86_64 -M pc-1.0 -cpu host -m 4096 \\\n\t-object memory-backend-file,id=mem,size=4096M,mem-path=/mnt/huge,share=on\n\t-numa node,memdev=mem \\\n\t-chardev socket,id=chr0,path=/tmp/virtq0,server \\\n\t-netdev vhost-user,id=net0,chardev=chr0 \\\n\t-device virtio-net-pci,netdev=net0\n\nAlso testpmd example is here.\ntestpmd -c f -n 1 -m 1024 --vdev 'eth_vhost0,iface=/tmp/virtq0' -- -i\n\nYou can invoke QEMU and testpmd with any order. But if you invoke QEMU\nafter testpmd, please set '-m' option for qemu not to use all hugepage\nmemory.\n\nSigned-off-by: Tetsuya Mukawa <mukawa@igel.co.jp>\n---\n config/common_linuxapp               |   5 +\n lib/Makefile                         |   1 +\n lib/librte_pmd_vhost/Makefile        |  57 ++++\n lib/librte_pmd_vhost/rte_eth_vhost.c | 487 +++++++++++++++++++++++++++++++++++\n lib/librte_pmd_vhost/rte_eth_vhost.h |  55 ++++\n mk/rte.app.mk                        |   4 +\n 6 files changed, 609 insertions(+)\n create mode 100644 lib/librte_pmd_vhost/Makefile\n create mode 100644 lib/librte_pmd_vhost/rte_eth_vhost.c\n create mode 100644 lib/librte_pmd_vhost/rte_eth_vhost.h",
    "diff": "diff --git a/config/common_linuxapp b/config/common_linuxapp\nindex 8be79c3..71a54fc 100644\n--- a/config/common_linuxapp\n+++ b/config/common_linuxapp\n@@ -243,6 +243,11 @@ CONFIG_RTE_PMD_RING_MAX_TX_RINGS=16\n CONFIG_RTE_LIBRTE_PMD_PCAP=n\n \n #\n+# Compile burst-oriented VHOST PMD driver\n+#\n+CONFIG_RTE_LIBRTE_PMD_VHOST=n\n+\n+#\n # Compile link bonding PMD library\n #\n CONFIG_RTE_LIBRTE_PMD_BOND=y\ndiff --git a/lib/Makefile b/lib/Makefile\nindex e3237ff..4f314a7 100644\n--- a/lib/Makefile\n+++ b/lib/Makefile\n@@ -47,6 +47,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += librte_pmd_i40e\n DIRS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += librte_pmd_bond\n DIRS-$(CONFIG_RTE_LIBRTE_PMD_RING) += librte_pmd_ring\n DIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += librte_pmd_pcap\n+DIRS-$(CONFIG_RTE_LIBRTE_PMD_VHOST) += librte_pmd_vhost\n DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += librte_pmd_virtio\n DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += librte_pmd_vmxnet3\n DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += librte_pmd_xenvirt\ndiff --git a/lib/librte_pmd_vhost/Makefile b/lib/librte_pmd_vhost/Makefile\nnew file mode 100644\nindex 0000000..6c85d55\n--- /dev/null\n+++ b/lib/librte_pmd_vhost/Makefile\n@@ -0,0 +1,57 @@\n+#   BSD LICENSE\n+#\n+#   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\n+#   All rights reserved.\n+#\n+#   Redistribution and use in source and binary forms, with or without\n+#   modification, are permitted provided that the following conditions\n+#   are met:\n+#\n+#     * Redistributions of source code must retain the above copyright\n+#       notice, this list of conditions and the following disclaimer.\n+#     * Redistributions in binary form must reproduce the above copyright\n+#       notice, this list of conditions and the following disclaimer in\n+#       the documentation and/or other materials provided with the\n+#       distribution.\n+#     * Neither the name of Intel Corporation nor the names of its\n+#       contributors may be used to endorse or promote products derived\n+#       from this software without specific prior written permission.\n+#\n+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+#   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+\n+include $(RTE_SDK)/mk/rte.vars.mk\n+\n+#\n+# library name\n+#\n+LIB = librte_pmd_vhost.a\n+\n+CFLAGS += -O3\n+CFLAGS += $(WERROR_FLAGS)\n+\n+#\n+# all source are stored in SRCS-y\n+#\n+SRCS-$(CONFIG_RTE_LIBRTE_PMD_VHOST) += rte_eth_vhost.c\n+\n+#\n+# Export include files\n+#\n+SYMLINK-y-include += rte_eth_vhost.h\n+\n+# this lib depends upon:\n+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_VHOST) += lib/librte_eal lib/librte_vhost\n+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_VHOST) += lib/librte_mbuf lib/librte_ether\n+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_VHOST) += lib/librte_kvargs\n+\n+include $(RTE_SDK)/mk/rte.lib.mk\ndiff --git a/lib/librte_pmd_vhost/rte_eth_vhost.c b/lib/librte_pmd_vhost/rte_eth_vhost.c\nnew file mode 100644\nindex 0000000..9e5f622\n--- /dev/null\n+++ b/lib/librte_pmd_vhost/rte_eth_vhost.c\n@@ -0,0 +1,487 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.\n+ *\n+ *   All rights reserved.\n+ *\n+ *   Redistribution and use in source and binary forms, with or without\n+ *   modification, are permitted provided that the following conditions\n+ *   are met:\n+ *\n+ *     * Redistributions of source code must retain the above copyright\n+ *       notice, this list of conditions and the following disclaimer.\n+ *     * Redistributions in binary form must reproduce the above copyright\n+ *       notice, this list of conditions and the following disclaimer in\n+ *       the documentation and/or other materials provided with the\n+ *       distribution.\n+ *     * Neither the name of Intel Corporation nor the names of its\n+ *       contributors may be used to endorse or promote products derived\n+ *       from this software without specific prior written permission.\n+ *\n+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+ *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+#include <unistd.h>\n+\n+#include <rte_virtio_net.h>\n+#include <rte_mbuf.h>\n+#include <rte_ethdev.h>\n+#include <rte_malloc.h>\n+#include <rte_memcpy.h>\n+#include <rte_dev.h>\n+#include <rte_kvargs.h>\n+\n+#include \"rte_eth_vhost.h\"\n+\n+#define VHOST_PORT_START_TIMEOUT\t10\n+\n+struct vhost_queue {\n+\tstruct virtio_net *device;\n+\tstruct rte_mempool *mb_pool;\n+\trte_atomic64_t rx_pkts;\n+\trte_atomic64_t tx_pkts;\n+\trte_atomic64_t err_pkts;\n+};\n+\n+struct pmd_internals {\n+\tstruct vhost_driver *driver;\n+\tunsigned nb_rx_queues;\n+\tunsigned nb_tx_queues;\n+\n+\tstruct vhost_queue rx_vhost_queues[RTE_PMD_RING_MAX_RX_RINGS];\n+\tstruct vhost_queue tx_vhost_queues[RTE_PMD_RING_MAX_TX_RINGS];\n+};\n+\n+static struct ether_addr eth_addr = {\n+\t.addr_bytes ={\n+\t\t0x56 /* V */,\n+\t\t0x48 /* H */,\n+\t\t0x4F /* O */,\n+\t\t0x53 /* S */,\n+\t\t0x54 /* T */,\n+\t\t0x00\n+\t}\n+};\n+static const char *drivername = \"VHOST PMD\";\n+static struct rte_eth_link pmd_link = {\n+\t\t.link_speed = 10000,\n+\t\t.link_duplex = ETH_LINK_FULL_DUPLEX,\n+\t\t.link_status = 0\n+};\n+\n+#define ETH_VHOST_IFACE_ARG    \"iface\"\n+\n+static const char *valid_arguments[] = {\n+\tETH_VHOST_IFACE_ARG,\n+\tNULL\n+};\n+\n+static uint16_t\n+eth_vhost_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)\n+{\n+\tstruct vhost_queue *r = q;\n+\tuint16_t nb_rx;\n+\n+\t/* connection not established yet */\n+\tif (r->device == NULL)\n+\t\treturn 0;\n+\n+\tnb_rx = (uint16_t)rte_vhost_dequeue_burst(r->device,\n+\t\t\tVIRTIO_TXQ, r->mb_pool, bufs, nb_bufs);\n+\n+\trte_atomic64_add(&(r->rx_pkts), nb_rx);\n+\n+\treturn nb_rx;\n+}\n+\n+static uint16_t\n+eth_vhost_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)\n+{\n+\tstruct vhost_queue *r = q;\n+\tuint16_t i, nb_tx;\n+\n+\t/* connection not established yet */\n+\tif (r->device == NULL)\n+\t\treturn 0;\n+\n+\tnb_tx = (uint16_t)rte_vhost_enqueue_burst(r->device,\n+\t\t\tVIRTIO_RXQ, bufs, nb_bufs);\n+\n+\trte_atomic64_add(&(r->tx_pkts), nb_tx);\n+\trte_atomic64_add(&(r->err_pkts), nb_bufs - nb_tx);\n+\n+\tfor (i = 0; likely(i < nb_tx); i++)\n+\t\trte_pktmbuf_free(bufs[i]);\n+\n+\treturn nb_tx;\n+}\n+\n+static int\n+eth_dev_configure(struct rte_eth_dev *dev __rte_unused) { return 0; }\n+\n+static int\n+eth_dev_start(struct rte_eth_dev *dev)\n+{\n+\tstruct pmd_internals *internal = dev->data->dev_private;\n+\n+\tif (rte_vhost_driver_session_start(internal->driver) < 0)\n+\t\treturn -1;\n+\n+\treturn 0;\n+}\n+\n+static void\n+eth_dev_stop(struct rte_eth_dev *dev)\n+{\n+\tstruct pmd_internals *internal = dev->data->dev_private;\n+\n+\t/* stop event thread and wait until connection is closed */\n+\trte_vhost_driver_session_stop(internal->driver);\n+\n+\treturn;\n+}\n+\n+static int\n+eth_rx_queue_setup(struct rte_eth_dev *dev,uint16_t rx_queue_id,\n+\t\t\t\t    uint16_t nb_rx_desc __rte_unused,\n+\t\t\t\t    unsigned int socket_id __rte_unused,\n+\t\t\t\t    const struct rte_eth_rxconf *rx_conf __rte_unused,\n+\t\t\t\t    struct rte_mempool *mb_pool)\n+{\n+\tstruct pmd_internals *internals = dev->data->dev_private;\n+\tinternals->rx_vhost_queues[rx_queue_id].mb_pool = mb_pool;\n+\tdev->data->rx_queues[rx_queue_id] = &internals->rx_vhost_queues[rx_queue_id];\n+\treturn 0;\n+}\n+\n+static int\n+eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,\n+\t\t\t\t    uint16_t nb_tx_desc __rte_unused,\n+\t\t\t\t    unsigned int socket_id __rte_unused,\n+\t\t\t\t    const struct rte_eth_txconf *tx_conf __rte_unused)\n+{\n+\tstruct pmd_internals *internals = dev->data->dev_private;\n+\tdev->data->tx_queues[tx_queue_id] = &internals->tx_vhost_queues[tx_queue_id];\n+\treturn 0;\n+}\n+\n+\n+static void\n+eth_dev_info(struct rte_eth_dev *dev,\n+\t\tstruct rte_eth_dev_info *dev_info)\n+{\n+\tstruct pmd_internals *internals = dev->data->dev_private;\n+\tdev_info->driver_name = drivername;\n+\tdev_info->max_mac_addrs = 1;\n+\tdev_info->max_rx_pktlen = (uint32_t)-1;\n+\tdev_info->max_rx_queues = (uint16_t)internals->nb_rx_queues;\n+\tdev_info->max_tx_queues = (uint16_t)internals->nb_tx_queues;\n+\tdev_info->min_rx_bufsize = 0;\n+\tdev_info->pci_dev = NULL;\n+}\n+\n+static void\n+eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *igb_stats)\n+{\n+\tunsigned i;\n+\tunsigned long rx_total = 0, tx_total = 0, tx_err_total = 0;\n+\tconst struct pmd_internals *internal = dev->data->dev_private;\n+\n+\tmemset(igb_stats, 0, sizeof(*igb_stats));\n+\tfor (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&\n+\t\t\ti < internal->nb_rx_queues; i++) {\n+\t\tigb_stats->q_ipackets[i] = internal->rx_vhost_queues[i].rx_pkts.cnt;\n+\t\trx_total += igb_stats->q_ipackets[i];\n+\t}\n+\n+\tfor (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&\n+\t\t\ti < internal->nb_tx_queues; i++) {\n+\t\tigb_stats->q_opackets[i] = internal->tx_vhost_queues[i].tx_pkts.cnt;\n+\t\tigb_stats->q_errors[i] = internal->tx_vhost_queues[i].err_pkts.cnt;\n+\t\ttx_total += igb_stats->q_opackets[i];\n+\t\ttx_err_total += igb_stats->q_errors[i];\n+\t}\n+\n+\tigb_stats->ipackets = rx_total;\n+\tigb_stats->opackets = tx_total;\n+\tigb_stats->oerrors = tx_err_total;\n+}\n+\n+static void\n+eth_stats_reset(struct rte_eth_dev *dev)\n+{\n+\tunsigned i;\n+\tstruct pmd_internals *internal = dev->data->dev_private;\n+\tfor (i = 0; i < internal->nb_rx_queues; i++)\n+\t\tinternal->rx_vhost_queues[i].rx_pkts.cnt = 0;\n+\tfor (i = 0; i < internal->nb_tx_queues; i++) {\n+\t\tinternal->tx_vhost_queues[i].tx_pkts.cnt = 0;\n+\t\tinternal->tx_vhost_queues[i].err_pkts.cnt = 0;\n+\t}\n+}\n+\n+static void\n+eth_queue_release(void *q __rte_unused) { ; }\n+static int\n+eth_link_update(struct rte_eth_dev *dev __rte_unused,\n+\t\tint wait_to_complete __rte_unused)\n+{\n+#if 0\n+\tstruct pmd_internals *internal = dev->data->dev_private;\n+\tunsigned i;\n+\n+\tfor (i = 0; i < internal->nb_rx_queues; i++)\n+\t\tif (internal->rx_vhost_queues[i].device == NULL)\n+\t\t\tgoto not_yet;\n+\n+\tfor (i = 0; i < internal->nb_tx_queues; i++)\n+\t\tif (internal->tx_vhost_queues[i].device == NULL)\n+\t\t\tgoto not_yet;\n+\n+\t//dev->data->dev_link.link_status = 1;\n+\treturn 0;\n+\n+not_yet:\n+\t//dev->data->dev_link.link_status = 0;\n+#endif\n+\treturn 0;\n+}\n+\n+static struct eth_dev_ops ops = {\n+\t\t.dev_start = eth_dev_start,\n+\t\t.dev_stop = eth_dev_stop,\n+\t\t.dev_configure = eth_dev_configure,\n+\t\t.dev_infos_get = eth_dev_info,\n+\t\t.rx_queue_setup = eth_rx_queue_setup,\n+\t\t.tx_queue_setup = eth_tx_queue_setup,\n+\t\t.rx_queue_release = eth_queue_release,\n+\t\t.tx_queue_release = eth_queue_release,\n+\t\t.link_update = eth_link_update,\n+\t\t.stats_get = eth_stats_get,\n+\t\t.stats_reset = eth_stats_reset,\n+};\n+\n+static int\n+new_device(struct virtio_net *dev)\n+{\n+\tstruct rte_eth_dev *eth_dev = dev->priv;\n+\tstruct pmd_internals *internal;\n+\tunsigned i;\n+\n+\tif ((eth_dev == NULL) || (eth_dev->data->dev_private == NULL)) {\n+\t\tRTE_LOG(INFO, PMD, \"failuer to establish a new connection\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tinternal = eth_dev->data->dev_private;\n+\n+\tRTE_LOG(INFO, PMD, \"New connection '%s' established\\n\",\n+\t\t\tinternal->driver->dev_name);\n+\n+\tfor (i = 0; i < internal->nb_rx_queues; i++)\n+\t\tinternal->rx_vhost_queues[i].device = dev;\n+\tfor (i = 0; i < internal->nb_tx_queues; i++)\n+\t\tinternal->tx_vhost_queues[i].device = dev;\n+\n+\tdev->flags |= VIRTIO_DEV_RUNNING;\n+\n+\teth_dev->data->dev_link.link_status = 1;\n+\n+\treturn 0;\n+}\n+\n+static void\n+destroy_device(volatile struct virtio_net *dev)\n+{\n+\tstruct rte_eth_dev *eth_dev = dev->priv;\n+\tstruct pmd_internals *internal;\n+\tunsigned i;\n+\n+\tif ((dev == NULL) || (eth_dev->data->dev_private == NULL)) {\n+\t\tRTE_LOG(INFO, PMD, \"failuer to close a connection\\n\");\n+\t\treturn;\n+\t}\n+\n+\tinternal = eth_dev->data->dev_private;\n+\n+\tRTE_LOG(INFO, PMD, \"Connection '%s' closed\\n\",\n+\t\t\tinternal->driver->dev_name);\n+\n+\tfor (i = 0; i < internal->nb_rx_queues; i++)\n+\t\tinternal->rx_vhost_queues[i].device = NULL;\n+\tfor (i = 0; i < internal->nb_tx_queues; i++)\n+\t\tinternal->rx_vhost_queues[i].device = NULL;\n+\n+\tdev->flags &= ~VIRTIO_DEV_RUNNING;\n+\n+\teth_dev->data->dev_link.link_status = 0;\n+\n+\treturn;\n+}\n+\n+static int\n+rte_eth_from_vhosts(const char *name, const unsigned numa_node)\n+{\n+\tstruct rte_eth_dev_data *data = NULL;\n+\tstruct rte_pci_device *pci_dev = NULL;\n+\tstruct pmd_internals *internals = NULL;\n+\tstruct rte_eth_dev *eth_dev = NULL;\n+\tstruct vhost_driver *drv = NULL;\n+\tstatic struct virtio_net_device_ops *vhost_ops = NULL;;\n+\n+\tuint16_t nb_rx_queues = 1;\n+\tuint16_t nb_tx_queues = 1;\n+\n+\t/* now do all data allocation - for eth_dev structure, dummy pci driver\n+\t * and internal (private) data\n+\t */\n+\tdata = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node);\n+\tif (data == NULL)\n+\t\tgoto error;\n+\n+\tpci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, numa_node);\n+\tif (pci_dev == NULL)\n+\t\tgoto error;\n+\n+\tinternals = rte_zmalloc_socket(name, sizeof(*internals), 0, numa_node);\n+\tif (internals == NULL)\n+\t\tgoto error;\n+\n+\tvhost_ops = rte_zmalloc_socket(name, sizeof(*vhost_ops), 0, numa_node);\n+\tif (vhost_ops == NULL)\n+\t\tgoto error;\n+\n+\tdrv = rte_vhost_driver_register(name, VHOST_DRV_USER);\n+\tif (internals == NULL)\n+\t\tgoto error;\n+\n+\t/* reserve an ethdev entry */\n+\teth_dev = rte_eth_dev_allocate(name);\n+\tif (eth_dev == NULL)\n+\t\tgoto error;\n+\n+\t/* set vhost arguments */\n+\tvhost_ops->new_device = new_device;\n+\tvhost_ops->destroy_device = destroy_device;\n+\tif (rte_vhost_driver_callback_register(drv, vhost_ops, eth_dev) < 0)\n+\t\tgoto error;\n+\n+\t/* now put it all together\n+\t * - store numa_node info in pci_driver\n+\t * - point eth_dev_data to internals and pci_driver\n+\t * - and point eth_dev structure to new eth_dev_data structure\n+\t */\n+\t/* NOTE: we'll replace the data element, of originally allocated eth_dev\n+\t * so the vhosts are local per-process */\n+\n+\tinternals->driver = drv;\n+\tinternals->nb_rx_queues = nb_rx_queues;\n+\tinternals->nb_tx_queues = nb_tx_queues;\n+\n+\tpci_dev->numa_node = numa_node;\n+\n+\tdata->dev_private = internals;\n+\tdata->port_id = eth_dev->data->port_id;\n+\tdata->nb_rx_queues = (uint16_t)nb_rx_queues;\n+\tdata->nb_tx_queues = (uint16_t)nb_tx_queues;\n+\tdata->dev_link = pmd_link;\n+\tdata->mac_addrs = &eth_addr;\n+\n+\teth_dev->data = data;\n+\teth_dev->dev_ops = &ops;\n+\teth_dev->pci_dev = pci_dev;\n+\n+\t/* finally assign rx and tx ops */\n+\teth_dev->rx_pkt_burst = eth_vhost_rx;\n+\teth_dev->tx_pkt_burst = eth_vhost_tx;\n+\n+\treturn 0;\n+\n+error:\n+\tif (data)\n+\t\trte_free(data);\n+\tif (pci_dev)\n+\t\trte_free(pci_dev);\n+\tif (internals)\n+\t\trte_free(internals);\n+\tif (vhost_ops)\n+\t\trte_free(internals);\n+\t//if (drv)\n+\t//\trte_vhost_driver_unregister(drv);\n+\treturn -1;\n+}\n+\n+static int\n+eth_dev_vhost_create(const char *name, const unsigned numa_node)\n+{\n+\n+\tif (rte_eth_from_vhosts(name, numa_node))\n+\t\treturn -1;\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * Opens an interface for reading and writing\n+ */\n+static inline int\n+open_iface(const char *key __rte_unused, const char *value, void *extra_args)\n+{\n+\tconst char **iface_name = extra_args;\n+\n+\tif(value == NULL)\n+\t\treturn -1;\n+\n+\t*iface_name = value;\n+\n+\treturn 0;\n+}\n+\n+int\n+rte_pmd_vhost_devinit(const char *name, const char *params)\n+{\n+\tconst char *iface_name;\n+\tstruct rte_kvargs *kvlist;\n+\tint ret;\n+\n+\tRTE_LOG(INFO, PMD, \"Initializing pmd_vhost for %s\\n\", name);\n+\n+\tkvlist = rte_kvargs_parse(params, valid_arguments);\n+\tif (kvlist == NULL)\n+\t\treturn -1;\n+\n+\t/*\n+\t * If iface argument is passed we open the NICs and use them for\n+\t * reading / writing\n+\t */\n+\tif (rte_kvargs_count(kvlist, ETH_VHOST_IFACE_ARG) == 1) {\n+\n+\t\tret = rte_kvargs_process(kvlist, ETH_VHOST_IFACE_ARG,\n+\t\t\t\t&open_iface, &iface_name);\n+\t\tif (ret < 0)\n+\t\t\treturn -1;\n+\t}\n+\n+\teth_dev_vhost_create(iface_name, rte_socket_id());\n+\n+\treturn 0;\n+}\n+\n+static struct rte_driver pmd_vhost_drv = {\n+\t.name = \"eth_vhost\",\n+\t.type = PMD_VDEV,\n+\t.init = rte_pmd_vhost_devinit,\n+};\n+\n+PMD_REGISTER_DRIVER(pmd_vhost_drv);\ndiff --git a/lib/librte_pmd_vhost/rte_eth_vhost.h b/lib/librte_pmd_vhost/rte_eth_vhost.h\nnew file mode 100644\nindex 0000000..6b039f2\n--- /dev/null\n+++ b/lib/librte_pmd_vhost/rte_eth_vhost.h\n@@ -0,0 +1,55 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.\n+ *   All rights reserved.\n+ *\n+ *   Redistribution and use in source and binary forms, with or without\n+ *   modification, are permitted provided that the following conditions\n+ *   are met:\n+ *\n+ *     * Redistributions of source code must retain the above copyright\n+ *       notice, this list of conditions and the following disclaimer.\n+ *     * Redistributions in binary form must reproduce the above copyright\n+ *       notice, this list of conditions and the following disclaimer in\n+ *       the documentation and/or other materials provided with the\n+ *       distribution.\n+ *     * Neither the name of Intel Corporation nor the names of its\n+ *       contributors may be used to endorse or promote products derived\n+ *       from this software without specific prior written permission.\n+ *\n+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+ *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+#ifndef _RTE_ETH_VHOST_H_\n+#define _RTE_ETH_VHOST_H_\n+\n+#ifdef __cplusplus\n+extern \"C\" {\n+#endif\n+\n+#include <rte_virtio_net.h>\n+\n+int rte_eth_register_vhost(const char *name);\n+\n+/**\n+ * For use by test apps only. Called as part of EAL init to set up any dummy NICs\n+ * configured on command line.\n+ */\n+int rte_pmd_vhost_devinit(const char *name, const char *params);\n+\n+#ifdef __cplusplus\n+}\n+#endif\n+\n+#endif\ndiff --git a/mk/rte.app.mk b/mk/rte.app.mk\nindex 285b65c..a2227dc 100644\n--- a/mk/rte.app.mk\n+++ b/mk/rte.app.mk\n@@ -215,6 +215,10 @@ ifeq ($(CONFIG_RTE_LIBRTE_PMD_PCAP),y)\n LDLIBS += -lrte_pmd_pcap -lpcap\n endif\n \n+ifeq ($(CONFIG_RTE_LIBRTE_PMD_VHOST),y)\n+LDLIBS += -lrte_pmd_vhost\n+endif\n+\n endif # plugins\n \n LDLIBS += $(EXECENV_LDLIBS)\n",
    "prefixes": [
        "dpdk-dev",
        "TEST"
    ]
}