get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2510,
    "url": "https://patches.dpdk.org/api/patches/2510/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1422242440-28948-11-git-send-email-huawei.xie@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": "<1422242440-28948-11-git-send-email-huawei.xie@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1422242440-28948-11-git-send-email-huawei.xie@intel.com",
    "date": "2015-01-26T03:20:36",
    "name": "[dpdk-dev,RFC,v2,10/14] vhost user support",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "4554586baf006ed3f03e86d3ef584ebf691775ad",
    "submitter": {
        "id": 16,
        "url": "https://patches.dpdk.org/api/people/16/?format=api",
        "name": "Huawei Xie",
        "email": "huawei.xie@intel.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1422242440-28948-11-git-send-email-huawei.xie@intel.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/2510/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/2510/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 766985AB1;\n\tMon, 26 Jan 2015 04:21:44 +0100 (CET)",
            "from mga14.intel.com (mga14.intel.com [192.55.52.115])\n\tby dpdk.org (Postfix) with ESMTP id 269185AB7\n\tfor <dev@dpdk.org>; Mon, 26 Jan 2015 04:21:36 +0100 (CET)",
            "from orsmga003.jf.intel.com ([10.7.209.27])\n\tby fmsmga103.fm.intel.com with ESMTP; 25 Jan 2015 19:15:35 -0800",
            "from shvmail01.sh.intel.com ([10.239.29.42])\n\tby orsmga003.jf.intel.com with ESMTP; 25 Jan 2015 19:14:35 -0800",
            "from shecgisg003.sh.intel.com (shecgisg003.sh.intel.com\n\t[10.239.29.90])\n\tby shvmail01.sh.intel.com with ESMTP id t0Q3LW0d015171;\n\tMon, 26 Jan 2015 11:21:32 +0800",
            "from shecgisg003.sh.intel.com (localhost [127.0.0.1])\n\tby shecgisg003.sh.intel.com (8.13.6/8.13.6/SuSE Linux 0.8) with ESMTP\n\tid t0Q3LUcu029053; Mon, 26 Jan 2015 11:21:32 +0800",
            "(from hxie5@localhost)\n\tby shecgisg003.sh.intel.com (8.13.6/8.13.6/Submit) id t0Q3LUk2029049; \n\tMon, 26 Jan 2015 11:21:30 +0800"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.09,466,1418112000\"; d=\"scan'208\";a=\"517465175\"",
        "From": "Huawei Xie <huawei.xie@intel.com>",
        "To": "dev@dpdk.org",
        "Date": "Mon, 26 Jan 2015 11:20:36 +0800",
        "Message-Id": "<1422242440-28948-11-git-send-email-huawei.xie@intel.com>",
        "X-Mailer": "git-send-email 1.7.4.1",
        "In-Reply-To": "<1422242440-28948-1-git-send-email-huawei.xie@intel.com>",
        "References": "<1422242440-28948-1-git-send-email-huawei.xie@intel.com>",
        "Subject": "[dpdk-dev] [RFC PATCH v2 10/14] vhost user support",
        "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": "Signed-off-by: Huawei Xie <huawei.xie@intel.com>\n---\n lib/librte_vhost/Makefile                     |   5 +-\n lib/librte_vhost/vhost-net.h                  |   4 +\n lib/librte_vhost/vhost_cuse/virtio-net-cdev.c |  12 +-\n lib/librte_vhost/vhost_user/fd_man.c          |   4 +-\n lib/librte_vhost/vhost_user/vhost-net-user.c  | 428 ++++++++++++++++++++++++++\n lib/librte_vhost/vhost_user/vhost-net-user.h  | 108 +++++++\n lib/librte_vhost/vhost_user/virtio-net-user.c | 205 ++++++++++++\n lib/librte_vhost/vhost_user/virtio-net-user.h |  48 +++\n lib/librte_vhost/virtio-net.c                 |  26 +-\n lib/librte_vhost/virtio-net.h                 |  43 +++\n 10 files changed, 865 insertions(+), 18 deletions(-)\n create mode 100644 lib/librte_vhost/vhost_user/vhost-net-user.c\n create mode 100644 lib/librte_vhost/vhost_user/vhost-net-user.h\n create mode 100644 lib/librte_vhost/vhost_user/virtio-net-user.c\n create mode 100644 lib/librte_vhost/vhost_user/virtio-net-user.h\n create mode 100644 lib/librte_vhost/virtio-net.h",
    "diff": "diff --git a/lib/librte_vhost/Makefile b/lib/librte_vhost/Makefile\nindex e0d0ef6..b2f14a0 100644\n--- a/lib/librte_vhost/Makefile\n+++ b/lib/librte_vhost/Makefile\n@@ -34,10 +34,11 @@ include $(RTE_SDK)/mk/rte.vars.mk\n # library name\n LIB = librte_vhost.a\n \n-CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -I vhost_cuse -O3 -D_FILE_OFFSET_BITS=64 -lfuse\n+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -I vhost_cuse -I vhost_user -O3 -D_FILE_OFFSET_BITS=64 -lfuse\n LDFLAGS += -lfuse\n # all source are stored in SRCS-y\n-SRCS-$(CONFIG_RTE_LIBRTE_VHOST) := vhost_cuse/vhost-net-cdev.c vhost_cuse/virtio-net-cdev.c virtio-net.c vhost_rxtx.c\n+#SRCS-$(CONFIG_RTE_LIBRTE_VHOST) := vhost_cuse/vhost-net-cdev.c vhost_cuse/virtio-net-cdev.c virtio-net.c vhost_rxtx.c\n+SRCS-$(CONFIG_RTE_LIBRTE_VHOST) := vhost_user/vhost-net-user.c vhost_user/virtio-net-user.c vhost_user/fd_man.c virtio-net.c vhost_rxtx.c\n \n # install includes\n SYMLINK-$(CONFIG_RTE_LIBRTE_VHOST)-include += rte_virtio_net.h\ndiff --git a/lib/librte_vhost/vhost-net.h b/lib/librte_vhost/vhost-net.h\nindex 11737cc..3f18f25 100644\n--- a/lib/librte_vhost/vhost-net.h\n+++ b/lib/librte_vhost/vhost-net.h\n@@ -41,8 +41,12 @@\n \n #include <rte_log.h>\n \n+#include \"rte_virtio_net.h\"\n+\n #define VHOST_MEMORY_MAX_NREGIONS 8\n \n+extern struct vhost_net_device_ops const *ops;\n+\n /* Macros for printing using RTE_LOG */\n #define RTE_LOGTYPE_VHOST_CONFIG RTE_LOGTYPE_USER1\n #define RTE_LOGTYPE_VHOST_DATA   RTE_LOGTYPE_USER1\ndiff --git a/lib/librte_vhost/vhost_cuse/virtio-net-cdev.c b/lib/librte_vhost/vhost_cuse/virtio-net-cdev.c\nindex edcbc10..1d2c403 100644\n--- a/lib/librte_vhost/vhost_cuse/virtio-net-cdev.c\n+++ b/lib/librte_vhost/vhost_cuse/virtio-net-cdev.c\n@@ -50,8 +50,7 @@\n #include \"rte_virtio_net.h\"\n #include \"vhost-net.h\"\n #include \"virtio-net-cdev.h\"\n-\n-extern struct vhost_net_device_ops const *ops;\n+#include \"virtio-net.h\"\n \n /* Line size for reading maps file. */\n static const uint32_t BUFSIZE = PATH_MAX;\n@@ -268,6 +267,7 @@ cuse_set_mem_table(struct vhost_device_ctx ctx,\n \tstruct vhost_memory_region *mem_regions = (void *)(uintptr_t)\n \t\t((uint64_t)(uintptr_t)mem_regions_addr + size);\n \tuint64_t base_address = 0, mapped_address, mapped_size;\n+\tstruct virtio_net *dev;\n \n \tfor (idx = 0; idx < nregions; idx++) {\n \t\tregions[idx].guest_phys_address =\n@@ -335,6 +335,14 @@ cuse_set_mem_table(struct vhost_device_ctx ctx,\n \t\t\tregions[idx].guest_phys_address;\n \t}\n \n+\tdev = get_device(ctx);\n+\tif (dev && dev->mem && dev->mem->mapped_address) {\n+\t\tmunmap((void *)(uintptr_t)dev->mem->mapped_address,\n+\t\t\t(size_t)dev->mem->mapped_size);\n+\t\tfree(dev->mem);\n+\t\tdev->mem = NULL;\n+\t}\n+\n \tops->set_mem_table(ctx, &regions[0], valid_regions);\n \treturn 0;\n }\ndiff --git a/lib/librte_vhost/vhost_user/fd_man.c b/lib/librte_vhost/vhost_user/fd_man.c\nindex 09187e0..0d2beb9 100644\n--- a/lib/librte_vhost/vhost_user/fd_man.c\n+++ b/lib/librte_vhost/vhost_user/fd_man.c\n@@ -72,7 +72,7 @@ fdset_find_free_slot(struct fdset *pfdset)\n \n static void\n fdset_add_fd(struct fdset  *pfdset, int idx, int fd,\n-\tfd_cb rcb, fd_cb wcb, uint64_t dat)\n+\tfd_cb rcb, fd_cb wcb, void *dat)\n {\n \tstruct fdentry *pfdentry;\n \n@@ -138,7 +138,7 @@ fdset_init(struct fdset *pfdset)\n  * Register the fd in the fdset with read/write handler and context.\n  */\n int\n-fdset_add(struct fdset *pfdset, int fd, fd_cb rcb, fd_cb wcb, uint64_t dat)\n+fdset_add(struct fdset *pfdset, int fd, fd_cb rcb, fd_cb wcb, void *dat)\n {\n \tint i;\n \ndiff --git a/lib/librte_vhost/vhost_user/vhost-net-user.c b/lib/librte_vhost/vhost_user/vhost-net-user.c\nnew file mode 100644\nindex 0000000..c84fd3b\n--- /dev/null\n+++ b/lib/librte_vhost/vhost_user/vhost-net-user.c\n@@ -0,0 +1,428 @@\n+/*-\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+\n+#include <stdint.h>\n+#include <stdio.h>\n+#include <limits.h>\n+#include <stdlib.h>\n+#include <unistd.h>\n+#include <string.h>\n+#include <sys/types.h>\n+#include <sys/socket.h>\n+#include <sys/un.h>\n+#include <errno.h>\n+\n+#include <rte_log.h>\n+#include <rte_virtio_net.h>\n+\n+#include \"fd_man.h\"\n+#include \"vhost-net-user.h\"\n+#include \"vhost-net.h\"\n+#include \"virtio-net-user.h\"\n+\n+static void vserver_new_vq_conn(int fd, void *data);\n+static void vserver_message_handler(int fd, void *dat);\n+struct vhost_net_device_ops const *ops;\n+\n+static struct vhost_server *g_vhost_server;\n+\n+static const char *vhost_message_str[VHOST_USER_MAX] = {\n+\t[VHOST_USER_NONE] = \"VHOST_USER_NONE\",\n+\t[VHOST_USER_GET_FEATURES] = \"VHOST_USER_GET_FEATURES\",\n+\t[VHOST_USER_SET_FEATURES] = \"VHOST_USER_SET_FEATURES\",\n+\t[VHOST_USER_SET_OWNER] = \"VHOST_USER_SET_OWNER\",\n+\t[VHOST_USER_RESET_OWNER] = \"VHOST_USER_RESET_OWNER\",\n+\t[VHOST_USER_SET_MEM_TABLE] = \"VHOST_USER_SET_MEM_TABLE\",\n+\t[VHOST_USER_SET_LOG_BASE] = \"VHOST_USER_SET_LOG_BASE\",\n+\t[VHOST_USER_SET_LOG_FD] = \"VHOST_USER_SET_LOG_FD\",\n+\t[VHOST_USER_SET_VRING_NUM] = \"VHOST_USER_SET_VRING_NUM\",\n+\t[VHOST_USER_SET_VRING_ADDR] = \"VHOST_USER_SET_VRING_ADDR\",\n+\t[VHOST_USER_SET_VRING_BASE] = \"VHOST_USER_SET_VRING_BASE\",\n+\t[VHOST_USER_GET_VRING_BASE] = \"VHOST_USER_GET_VRING_BASE\",\n+\t[VHOST_USER_SET_VRING_KICK] = \"VHOST_USER_SET_VRING_KICK\",\n+\t[VHOST_USER_SET_VRING_CALL] = \"VHOST_USER_SET_VRING_CALL\",\n+\t[VHOST_USER_SET_VRING_ERR]  = \"VHOST_USER_SET_VRING_ERR\"\n+};\n+\n+/**\n+ * Create a unix domain socket, bind to path and listen for connection.\n+ * @return\n+ *  socket fd or -1 on failure\n+ */\n+static int\n+uds_socket(const char *path)\n+{\n+\tstruct sockaddr_un un;\n+\tint sockfd;\n+\tint ret;\n+\n+\tif (path == NULL)\n+\t\treturn -1;\n+\n+\tsockfd = socket(AF_UNIX, SOCK_STREAM, 0);\n+\tif (sockfd < 0)\n+\t\treturn -1;\n+\tRTE_LOG(INFO, VHOST_CONFIG, \"socket created, fd:%d\\n\", sockfd);\n+\n+\tmemset(&un, 0, sizeof(un));\n+\tun.sun_family = AF_UNIX;\n+\tsnprintf(un.sun_path, sizeof(un.sun_path), \"%s\", path);\n+\tret = bind(sockfd, (struct sockaddr *)&un, sizeof(un));\n+\tif (ret == -1)\n+\t\tgoto err;\n+\tRTE_LOG(INFO, VHOST_CONFIG, \"bind to %s\\n\", path);\n+\n+\tret = listen(sockfd, 1);\n+\tif (ret == -1)\n+\t\tgoto err;\n+\n+\treturn sockfd;\n+\n+err:\n+\tclose(sockfd);\n+\treturn -1;\n+}\n+\n+/* return bytes# of read on success or negative val on failure. */\n+static int\n+read_fd_message(int sockfd, char *buf, int buflen, int *fds, int fd_num)\n+{\n+\tstruct iovec iov;\n+\tstruct msghdr msgh = { 0 };\n+\tsize_t fdsize = fd_num * sizeof(int);\n+\tchar control[CMSG_SPACE(fdsize)];\n+\tstruct cmsghdr *cmsg;\n+\tint ret;\n+\n+\tiov.iov_base = buf;\n+\tiov.iov_len  = buflen;\n+\n+\tmsgh.msg_iov = &iov;\n+\tmsgh.msg_iovlen = 1;\n+\tmsgh.msg_control = control;\n+\tmsgh.msg_controllen = sizeof(control);\n+\n+\tret = recvmsg(sockfd, &msgh, 0);\n+\tif (ret <= 0) {\n+\t\tRTE_LOG(ERR, VHOST_CONFIG, \"recvmsg failed\\n\");\n+\t\treturn ret;\n+\t}\n+\n+\tif (msgh.msg_flags & (MSG_TRUNC | MSG_CTRUNC)) {\n+\t\tRTE_LOG(ERR, VHOST_CONFIG, \"truncted msg\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tfor (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL;\n+\t\tcmsg = CMSG_NXTHDR(&msgh, cmsg)) {\n+\t\tif ((cmsg->cmsg_level == SOL_SOCKET) &&\n+\t\t\t(cmsg->cmsg_type == SCM_RIGHTS)) {\n+\t\t\tmemcpy(fds, CMSG_DATA(cmsg), fdsize);\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\treturn ret;\n+}\n+\n+/* return bytes# of read on success or negative val on failure. */\n+static int\n+read_vhost_message(int sockfd, struct VhostUserMsg *msg)\n+{\n+\tint ret;\n+\n+\tret = read_fd_message(sockfd, (char *)msg, VHOST_USER_HDR_SIZE,\n+\t\tmsg->fds, VHOST_MEMORY_MAX_NREGIONS);\n+\tif (ret <= 0)\n+\t\treturn ret;\n+\n+\tif (msg && msg->size) {\n+\t\tif (msg->size > sizeof(msg->payload)) {\n+\t\t\tRTE_LOG(ERR, VHOST_CONFIG,\n+\t\t\t\t\"invalid msg size: %d\\n\", msg->size);\n+\t\t\treturn -1;\n+\t\t}\n+\t\tret = read(sockfd, &msg->payload, msg->size);\n+\t\tif (ret <= 0)\n+\t\t\treturn ret;\n+\t\tif (ret != (int)msg->size) {\n+\t\t\tRTE_LOG(ERR, VHOST_CONFIG,\n+\t\t\t\t\"read control message failed\\n\");\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static int\n+send_fd_message(int sockfd, char *buf, int buflen, int *fds, int fd_num)\n+{\n+\n+\tstruct iovec iov;\n+\tstruct msghdr msgh = { 0 };\n+\tsize_t fdsize = fd_num * sizeof(int);\n+\tchar control[CMSG_SPACE(fdsize)];\n+\tstruct cmsghdr *cmsg;\n+\tint ret;\n+\n+\tiov.iov_base = buf;\n+\tiov.iov_len = buflen;\n+\n+\tmsgh.msg_iov = &iov;\n+\tmsgh.msg_iovlen = 1;\n+\n+\tif (fds && fd_num > 0) {\n+\t\tmsgh.msg_control = control;\n+\t\tmsgh.msg_controllen = sizeof(control);\n+\t\tcmsg = CMSG_FIRSTHDR(&msgh);\n+\t\tcmsg->cmsg_len = CMSG_LEN(fdsize);\n+\t\tcmsg->cmsg_level = SOL_SOCKET;\n+\t\tcmsg->cmsg_type = SCM_RIGHTS;\n+\t\tmemcpy(CMSG_DATA(cmsg), fds, fdsize);\n+\t} else {\n+\t\tmsgh.msg_control = NULL;\n+\t\tmsgh.msg_controllen = 0;\n+\t}\n+\n+\tdo {\n+\t\tret = sendmsg(sockfd, &msgh, 0);\n+\t} while (ret < 0 && errno == EINTR);\n+\n+\tif (ret < 0) {\n+\t\tRTE_LOG(ERR, VHOST_CONFIG,  \"sendmsg error\\n\");\n+\t\treturn ret;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static int\n+send_vhost_message(int sockfd, struct VhostUserMsg *msg)\n+{\n+\tint ret;\n+\n+\tif (!msg)\n+\t\treturn 0;\n+\n+\tmsg->flags &= ~VHOST_USER_VERSION_MASK;\n+\tmsg->flags |= VHOST_USER_VERSION;\n+\tmsg->flags |= VHOST_USER_REPLY_MASK;\n+\n+\tret = send_fd_message(sockfd, (char *)msg,\n+\t\tVHOST_USER_HDR_SIZE + msg->size, NULL, 0);\n+\n+\treturn ret;\n+}\n+\n+/* call back when there is new virtio connection.  */\n+static void\n+vserver_new_vq_conn(int fd, void *dat)\n+{\n+\tstruct vhost_server *vserver = (struct vhost_server *)dat;\n+\tint conn_fd;\n+\tint fh;\n+\tstruct vhost_device_ctx vdev_ctx = { 0 };\n+\n+\tconn_fd = accept(fd, NULL, NULL);\n+\tRTE_LOG(INFO, VHOST_CONFIG,\n+\t\t\"new virtio connection is %d\\n\", conn_fd);\n+\tif (conn_fd < 0)\n+\t\treturn;\n+\n+\tfh = ops->new_device(vdev_ctx);\n+\tif (fh == -1) {\n+\t\tclose(conn_fd);\n+\t\treturn;\n+\t}\n+\tRTE_LOG(INFO, VHOST_CONFIG, \"new device, handle is %d\\n\", fh);\n+\n+\tfdset_add(&vserver->fdset,\n+\t\tconn_fd, vserver_message_handler, NULL, (void *)fh);\n+}\n+\n+/* callback when there is message on the connfd */\n+static void\n+vserver_message_handler(int connfd, void *dat)\n+{\n+\tstruct vhost_device_ctx ctx;\n+\tuint32_t fh = (uint32_t)dat;\n+\tstruct VhostUserMsg msg;\n+\tuint64_t features;\n+\tint ret;\n+\n+\tctx.fh = fh;\n+\tret = read_vhost_message(connfd, &msg);\n+\tif (ret < 0) {\n+\t\tRTE_LOG(ERR, VHOST_CONFIG,\n+\t\t\t\"vhost read message failed\\n\");\n+\n+\t\tclose(connfd);\n+\t\tfdset_del(&g_vhost_server->fdset, connfd);\n+\t\tops->destroy_device(ctx);\n+\n+\t\treturn;\n+\t} else if (ret == 0) {\n+\t\tRTE_LOG(INFO, VHOST_CONFIG,\n+\t\t\t\"vhost peer closed\\n\");\n+\n+\t\tclose(connfd);\n+\t\tfdset_del(&g_vhost_server->fdset, connfd);\n+\t\tops->destroy_device(ctx);\n+\n+\t\treturn;\n+\t}\n+\tif (msg.request > VHOST_USER_MAX) {\n+\t\tRTE_LOG(ERR, VHOST_CONFIG,\n+\t\t\t\"vhost read incorrect message\\n\");\n+\n+\t\tclose(connfd);\n+\t\tfdset_del(&g_vhost_server->fdset, connfd);\n+\n+\t\treturn;\n+\t}\n+\n+\tRTE_LOG(INFO, VHOST_CONFIG, \"read message %s\\n\",\n+\t\tvhost_message_str[msg.request]);\n+\tswitch (msg.request) {\n+\tcase VHOST_USER_GET_FEATURES:\n+\t\tret = ops->get_features(ctx, &features);\n+\t\tmsg.payload.u64 = features;\n+\t\tmsg.size = sizeof(msg.payload.u64);\n+\t\tsend_vhost_message(connfd, &msg);\n+\t\tbreak;\n+\tcase VHOST_USER_SET_FEATURES:\n+\t\tfeatures = msg.payload.u64;\n+\t\tops->set_features(ctx, &features);\n+\t\tbreak;\n+\n+\tcase VHOST_USER_SET_OWNER:\n+\t\tops->set_owner(ctx);\n+\t\tbreak;\n+\tcase VHOST_USER_RESET_OWNER:\n+\t\tops->reset_owner(ctx);\n+\t\tbreak;\n+\n+\tcase VHOST_USER_SET_MEM_TABLE:\n+\t\tuser_set_mem_table(ctx, &msg);\n+\t\tbreak;\n+\n+\tcase VHOST_USER_SET_LOG_BASE:\n+\t\tRTE_LOG(INFO, VHOST_CONFIG, \"not implemented.\\n\");\n+\tcase VHOST_USER_SET_LOG_FD:\n+\t\tclose(msg.fds[0]);\n+\t\tRTE_LOG(INFO, VHOST_CONFIG, \"not implemented.\\n\");\n+\t\tbreak;\n+\n+\tcase VHOST_USER_SET_VRING_NUM:\n+\t\tops->set_vring_num(ctx, &msg.payload.state);\n+\t\tbreak;\n+\tcase VHOST_USER_SET_VRING_ADDR:\n+\t\tops->set_vring_addr(ctx, &msg.payload.addr);\n+\t\tbreak;\n+\tcase VHOST_USER_SET_VRING_BASE:\n+\t\tops->set_vring_base(ctx, &msg.payload.state);\n+\t\tbreak;\n+\n+\tcase VHOST_USER_GET_VRING_BASE:\n+\t\tret = user_get_vring_base(ctx, &msg.payload.state);\n+\t\tmsg.size = sizeof(msg.payload.state);\n+\t\tsend_vhost_message(connfd, &msg);\n+\t\tbreak;\n+\n+\tcase VHOST_USER_SET_VRING_KICK:\n+\t\tuser_set_vring_kick(ctx, &msg);\n+\t\tbreak;\n+\tcase VHOST_USER_SET_VRING_CALL:\n+\t\tuser_set_vring_call(ctx, &msg);\n+\t\tbreak;\n+\n+\tcase VHOST_USER_SET_VRING_ERR:\n+\t\tif (!(msg.payload.u64 & VHOST_USER_VRING_NOFD_MASK))\n+\t\t\tclose(msg.fds[0]);\n+\t\tRTE_LOG(INFO, VHOST_CONFIG, \"not implemented\\n\");\n+\t\tbreak;\n+\n+\tdefault:\n+\t\tbreak;\n+\n+\t}\n+}\n+\n+\n+/**\n+ * Creates and initialise the vhost server.\n+ */\n+int\n+rte_vhost_driver_register(const char *path)\n+{\n+\n+\tstruct vhost_server *vserver;\n+\n+\tif (g_vhost_server != NULL)\n+\t\treturn -1;\n+\n+\tvserver = calloc(sizeof(struct vhost_server), 1);\n+\tif (vserver == NULL)\n+\t\treturn -1;\n+\n+\tfdset_init(&vserver->fdset);\n+\n+\tunlink(path);\n+\n+\tvserver->listenfd = uds_socket(path);\n+\tif (vserver->listenfd < 0) {\n+\t\tfree(vserver);\n+\t\treturn -1;\n+\t}\n+\tvserver->path = path;\n+\n+\tfdset_add(&vserver->fdset, vserver->listenfd,\n+\t\tvserver_new_vq_conn, NULL,\n+\t\tvserver);\n+\n+\tops = get_virtio_net_callbacks();\n+\n+\tg_vhost_server = vserver;\n+\n+\treturn 0;\n+}\n+\n+\n+int\n+rte_vhost_driver_session_start(void)\n+{\n+\tfdset_event_dispatch(&g_vhost_server->fdset);\n+\treturn 0;\n+}\n+\ndiff --git a/lib/librte_vhost/vhost_user/vhost-net-user.h b/lib/librte_vhost/vhost_user/vhost-net-user.h\nnew file mode 100644\nindex 0000000..7e6cda4\n--- /dev/null\n+++ b/lib/librte_vhost/vhost_user/vhost-net-user.h\n@@ -0,0 +1,108 @@\n+/*-\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+\n+#ifndef _VHOST_NET_USER_H\n+#define _VHOST_NET_USER_H\n+\n+#include <stdint.h>\n+#include <linux/vhost.h>\n+\n+#include \"fd_man.h\"\n+\n+struct vhost_server {\n+\tconst char *path; /**< The path the uds is bind to. */\n+\tint listenfd;     /**< The listener sockfd. */\n+\tstruct fdset fdset; /**< The fd list this vhost server manages. */\n+};\n+\n+/* refer to hw/virtio/vhost-user.c */\n+\n+#define VHOST_MEMORY_MAX_NREGIONS    8\n+\n+typedef enum VhostUserRequest {\n+\tVHOST_USER_NONE = 0,\n+\tVHOST_USER_GET_FEATURES = 1,\n+\tVHOST_USER_SET_FEATURES = 2,\n+\tVHOST_USER_SET_OWNER = 3,\n+\tVHOST_USER_RESET_OWNER = 4,\n+\tVHOST_USER_SET_MEM_TABLE = 5,\n+\tVHOST_USER_SET_LOG_BASE = 6,\n+\tVHOST_USER_SET_LOG_FD = 7,\n+\tVHOST_USER_SET_VRING_NUM = 8,\n+\tVHOST_USER_SET_VRING_ADDR = 9,\n+\tVHOST_USER_SET_VRING_BASE = 10,\n+\tVHOST_USER_GET_VRING_BASE = 11,\n+\tVHOST_USER_SET_VRING_KICK = 12,\n+\tVHOST_USER_SET_VRING_CALL = 13,\n+\tVHOST_USER_SET_VRING_ERR = 14,\n+\tVHOST_USER_MAX\n+} VhostUserRequest;\n+\n+typedef struct VhostUserMemoryRegion {\n+\tuint64_t guest_phys_addr;\n+\tuint64_t memory_size;\n+\tuint64_t userspace_addr;\n+\tuint64_t mmap_offset;\n+} VhostUserMemoryRegion;\n+\n+typedef struct VhostUserMemory {\n+\tuint32_t nregions;\n+\tuint32_t padding;\n+\tVhostUserMemoryRegion regions[VHOST_MEMORY_MAX_NREGIONS];\n+} VhostUserMemory;\n+\n+typedef struct VhostUserMsg {\n+\tVhostUserRequest request;\n+\n+#define VHOST_USER_VERSION_MASK     (0x3)\n+#define VHOST_USER_REPLY_MASK       (0x1 << 2)\n+\tuint32_t flags;\n+\tuint32_t size; /* the following payload size */\n+\tunion {\n+#define VHOST_USER_VRING_IDX_MASK   (0xff)\n+#define VHOST_USER_VRING_NOFD_MASK  (0x1<<8)\n+\t\tuint64_t u64;\n+\t\tstruct vhost_vring_state state;\n+\t\tstruct vhost_vring_addr addr;\n+\t\tVhostUserMemory memory;\n+\t} payload;\n+\tint fds[VHOST_MEMORY_MAX_NREGIONS];\n+} __attribute((packed)) VhostUserMsg;\n+\n+#define VHOST_USER_HDR_SIZE (intptr_t)(&((VhostUserMsg *)0)->payload.u64)\n+\n+/* The version of the protocol we support */\n+#define VHOST_USER_VERSION    (0x1)\n+\n+/*****************************************************************************/\n+#endif\ndiff --git a/lib/librte_vhost/vhost_user/virtio-net-user.c b/lib/librte_vhost/vhost_user/virtio-net-user.c\nnew file mode 100644\nindex 0000000..6601fcd\n--- /dev/null\n+++ b/lib/librte_vhost/vhost_user/virtio-net-user.c\n@@ -0,0 +1,205 @@\n+/*-\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+\n+#include <stdint.h>\n+#include <stdio.h>\n+#include <stdlib.h>\n+#include <unistd.h>\n+#include <sys/mman.h>\n+\n+#include <rte_log.h>\n+\n+#include \"virtio-net.h\"\n+#include \"virtio-net-user.h\"\n+#include \"vhost-net-user.h\"\n+#include \"vhost-net.h\"\n+\n+int\n+user_set_mem_table(struct vhost_device_ctx ctx, struct VhostUserMsg *pmsg)\n+{\n+\tunsigned int idx;\n+\tstruct VhostUserMemory memory = pmsg->payload.memory;\n+\tstruct virtio_memory_regions regions[VHOST_MEMORY_MAX_NREGIONS];\n+\tuint64_t mapped_address, base_address = 0;\n+\n+\tfor (idx = 0; idx < memory.nregions; idx++) {\n+\t\tif (memory.regions[idx].guest_phys_addr == 0)\n+\t\t\tbase_address = memory.regions[idx].userspace_addr;\n+\t}\n+\tif (base_address == 0) {\n+\t\tRTE_LOG(ERR, VHOST_CONFIG,\n+\t\t\t\"couldn't find the mem region whose GPA is 0.\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tfor (idx = 0; idx < memory.nregions; idx++) {\n+\t\tregions[idx].guest_phys_address =\n+\t\t\tmemory.regions[idx].guest_phys_addr;\n+\t\tregions[idx].guest_phys_address_end =\n+\t\t\tmemory.regions[idx].guest_phys_addr +\n+\t\t\tmemory.regions[idx].memory_size;\n+\t\tregions[idx].memory_size = memory.regions[idx].memory_size;\n+\t\tregions[idx].userspace_address =\n+\t\t\tmemory.regions[idx].userspace_addr;\n+\n+\t\t/* This is ugly */\n+\t\tmapped_address = (uint64_t)(uintptr_t)mmap(NULL,\n+\t\t\tregions[idx].memory_size +\n+\t\t\t\tmemory.regions[idx].mmap_offset,\n+\t\t\tPROT_READ | PROT_WRITE, MAP_SHARED,\n+\t\t\tpmsg->fds[idx],\n+\t\t\t0);\n+\t\tRTE_LOG(INFO, VHOST_CONFIG,\n+\t\t\t\"mapped region %d to %p\\n\",\n+\t\t\tidx, (void *)mapped_address);\n+\n+\t\tif (mapped_address == (uint64_t)(uintptr_t)MAP_FAILED) {\n+\t\t\tRTE_LOG(ERR, VHOST_CONFIG,\n+\t\t\t\t\"mmap qemu guest failed.\\n\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tmapped_address +=  memory.regions[idx].mmap_offset;\n+\n+\t\tregions[idx].address_offset = mapped_address -\n+\t\t\tregions[idx].guest_phys_address;\n+\t\tLOG_DEBUG(VHOST_CONFIG,\n+\t\t\t\"REGION: %u GPA: %p QEMU VA: %p SIZE (%\"PRIu64\")\\n\",\n+\t\t\tidx,\n+\t\t\t(void *)(uintptr_t)regions[idx].guest_phys_address,\n+\t\t\t(void *)(uintptr_t)regions[idx].userspace_address,\n+\t\t\t regions[idx].memory_size);\n+\t}\n+\tops->set_mem_table(ctx, regions, memory.nregions);\n+\treturn 0;\n+}\n+\n+\n+static int\n+virtio_is_ready(struct virtio_net *dev)\n+{\n+\tstruct vhost_virtqueue *rvq, *tvq;\n+\n+\t/* mq support in future.*/\n+\trvq = dev->virtqueue[VIRTIO_RXQ];\n+\ttvq = dev->virtqueue[VIRTIO_TXQ];\n+\tif (rvq && tvq && rvq->desc && tvq->desc &&\n+\t\t(rvq->kickfd != (eventfd_t)-1) &&\n+\t\t(rvq->callfd != (eventfd_t)-1) &&\n+\t\t(tvq->kickfd != (eventfd_t)-1) &&\n+\t\t(tvq->callfd != (eventfd_t)-1)) {\n+\t\tRTE_LOG(INFO, VHOST_CONFIG,\n+\t\t\t\"virtio is now ready for processing.\\n\");\n+\t\treturn 1;\n+\t}\n+\tRTE_LOG(INFO, VHOST_CONFIG,\n+\t\t\"virtio isn't ready for processing.\\n\");\n+\treturn 0;\n+}\n+\n+void\n+user_set_vring_call(struct vhost_device_ctx ctx, struct VhostUserMsg *pmsg)\n+{\n+\tstruct vhost_vring_file file;\n+\n+\tfile.index = pmsg->payload.u64 & VHOST_USER_VRING_IDX_MASK;\n+\tif (pmsg->payload.u64 & VHOST_USER_VRING_NOFD_MASK)\n+\t\tfile.fd = -1;\n+\telse\n+\t\tfile.fd = pmsg->fds[0];\n+\tRTE_LOG(INFO, VHOST_CONFIG,\n+\t\t\"vring call idx:%d file:%d\\n\", file.index, file.fd);\n+\tops->set_vring_call(ctx, &file);\n+}\n+\n+\n+/*\n+ *  In vhost-user, when we receive kick message, will test whether virtio\n+ *  device is ready for packet processing.\n+ */\n+void\n+user_set_vring_kick(struct vhost_device_ctx ctx, struct VhostUserMsg *pmsg)\n+{\n+\tstruct vhost_vring_file file;\n+\tstruct virtio_net *dev = get_device(ctx);\n+\n+\tfile.index = pmsg->payload.u64 & VHOST_USER_VRING_IDX_MASK;\n+\tif (pmsg->payload.u64 & VHOST_USER_VRING_NOFD_MASK)\n+\t\tfile.fd = -1;\n+\telse\n+\t\tfile.fd = pmsg->fds[0];\n+\tRTE_LOG(INFO, VHOST_CONFIG,\n+\t\t\"vring kick idx:%d file:%d\\n\", file.index, file.fd);\n+\tops->set_vring_kick(ctx, &file);\n+\n+\tif (virtio_is_ready(dev) &&\n+\t\t!(dev->flags & VIRTIO_DEV_RUNNING))\n+\t\t\tnotify_ops->new_device(dev);\n+\n+}\n+\n+/*\n+ * when virtio is stopped, qemu will send us the GET_VRING_BASE message.\n+ */\n+int\n+user_get_vring_base(struct vhost_device_ctx ctx,\n+\tstruct vhost_vring_state *state)\n+{\n+\tstruct virtio_net *dev = get_device(ctx);\n+\n+\t/* We have to stop the queue (virtio) if it is running. */\n+\tif (dev->flags & VIRTIO_DEV_RUNNING)\n+\t\tnotify_ops->destroy_device(dev);\n+\n+\t/* Here we are safe to get the last used index */\n+\tops->get_vring_base(ctx, state->index, state);\n+\n+\tRTE_LOG(INFO, VHOST_CONFIG,\n+\t\t\"vring base idx:%d file:%d\\n\", state->index, state->num);\n+\t/*\n+\t * Based on current qemu vhost-user implementation, this message is\n+\t * sent and only sent in vhost_vring_stop.\n+\t * TODO: cleanup the vring, it isn't usable since here.\n+\t */\n+\tif (((int)dev->virtqueue[VIRTIO_RXQ]->callfd) >= 0) {\n+\t\tclose(dev->virtqueue[VIRTIO_RXQ]->callfd);\n+\t\tdev->virtqueue[VIRTIO_RXQ]->callfd = (eventfd_t)-1;\n+\t}\n+\tif (((int)dev->virtqueue[VIRTIO_TXQ]->callfd) >= 0) {\n+\t\tclose(dev->virtqueue[VIRTIO_TXQ]->callfd);\n+\t\tdev->virtqueue[VIRTIO_TXQ]->callfd = (eventfd_t)-1;\n+\t}\n+\n+\treturn 0;\n+\n+}\ndiff --git a/lib/librte_vhost/vhost_user/virtio-net-user.h b/lib/librte_vhost/vhost_user/virtio-net-user.h\nnew file mode 100644\nindex 0000000..0f6a75a\n--- /dev/null\n+++ b/lib/librte_vhost/vhost_user/virtio-net-user.h\n@@ -0,0 +1,48 @@\n+/*-\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+\n+#ifndef _VIRTIO_NET_USER_H\n+#define _VIRTIO_NET_USER_H\n+\n+#include \"vhost-net.h\"\n+#include \"vhost-net-user.h\"\n+\n+int user_set_mem_table(struct vhost_device_ctx, struct VhostUserMsg *);\n+\n+void user_set_vring_call(struct vhost_device_ctx, struct VhostUserMsg *);\n+\n+void user_set_vring_kick(struct vhost_device_ctx, struct VhostUserMsg *);\n+\n+int user_get_vring_base(struct vhost_device_ctx, struct vhost_vring_state *);\n+\n+#endif\ndiff --git a/lib/librte_vhost/virtio-net.c b/lib/librte_vhost/virtio-net.c\nindex 57a5801..c458ed9 100644\n--- a/lib/librte_vhost/virtio-net.c\n+++ b/lib/librte_vhost/virtio-net.c\n@@ -50,6 +50,7 @@\n #include <rte_virtio_net.h>\n \n #include \"vhost-net.h\"\n+#include \"virtio-net.h\"\n \n /*\n  * Device linked list structure for configuration.\n@@ -60,7 +61,7 @@ struct virtio_net_config_ll {\n };\n \n /* device ops to add/remove device to/from data core. */\n-static struct virtio_net_device_ops const *notify_ops;\n+struct virtio_net_device_ops const *notify_ops;\n /* root address of the linked list of managed virtio devices */\n static struct virtio_net_config_ll *ll_root;\n \n@@ -88,8 +89,9 @@ qva_to_vva(struct virtio_net *dev, uint64_t qemu_va)\n \t\tif ((qemu_va >= region->userspace_address) &&\n \t\t\t(qemu_va <= region->userspace_address +\n \t\t\tregion->memory_size)) {\n-\t\t\tvhost_va = dev->mem->mapped_address + qemu_va -\n-\t\t\t\t\tdev->mem->base_address;\n+\t\t\tvhost_va = qemu_va + region->guest_phys_address +\n+\t\t\t\tregion->address_offset -\n+\t\t\t\tregion->userspace_address;\n \t\t\tbreak;\n \t\t}\n \t}\n@@ -119,7 +121,7 @@ get_config_ll_entry(struct vhost_device_ctx ctx)\n  * Searches the configuration core linked list and\n  * retrieves the device if it exists.\n  */\n-static struct virtio_net *\n+struct virtio_net *\n get_device(struct vhost_device_ctx ctx)\n {\n \tstruct virtio_net_config_ll *ll_dev;\n@@ -256,6 +258,11 @@ init_device(struct virtio_net *dev)\n \tmemset(dev->virtqueue[VIRTIO_RXQ], 0, sizeof(struct vhost_virtqueue));\n \tmemset(dev->virtqueue[VIRTIO_TXQ], 0, sizeof(struct vhost_virtqueue));\n \n+\tdev->virtqueue[VIRTIO_RXQ]->kickfd = (eventfd_t)-1;\n+\tdev->virtqueue[VIRTIO_RXQ]->callfd = (eventfd_t)-1;\n+\tdev->virtqueue[VIRTIO_TXQ]->kickfd = (eventfd_t)-1;\n+\tdev->virtqueue[VIRTIO_TXQ]->callfd = (eventfd_t)-1;\n+\n \t/* Backends are set to -1 indicating an inactive device. */\n \tdev->virtqueue[VIRTIO_RXQ]->backend = VIRTIO_DEV_STOPPED;\n \tdev->virtqueue[VIRTIO_TXQ]->backend = VIRTIO_DEV_STOPPED;\n@@ -455,12 +462,6 @@ set_mem_table(struct vhost_device_ctx ctx,\n \tif (dev == NULL)\n \t\treturn -1;\n \n-\tif (dev->mem) {\n-\t\tmunmap((void *)(uintptr_t)dev->mem->mapped_address,\n-\t\t\t(size_t)dev->mem->mapped_size);\n-\t\tfree(dev->mem);\n-\t}\n-\n \t/* Malloc the memory structure depending on the number of regions. */\n \tmem = calloc(1, sizeof(struct virtio_memory) +\n \t\t(sizeof(struct virtio_memory_regions) * nregions));\n@@ -624,7 +625,7 @@ set_vring_call(struct vhost_device_ctx ctx, struct vhost_vring_file *file)\n \t/* file->index refers to the queue index. The txq is 1, rxq is 0. */\n \tvq = dev->virtqueue[file->index];\n \n-\tif (vq->kickfd)\n+\tif ((int)vq->kickfd >= 0)\n \t\tclose((int)vq->kickfd);\n \n \tvq->kickfd = file->fd;\n@@ -650,8 +651,9 @@ set_vring_kick(struct vhost_device_ctx ctx, struct vhost_vring_file *file)\n \t/* file->index refers to the queue index. The txq is 1, rxq is 0. */\n \tvq = dev->virtqueue[file->index];\n \n-\tif (vq->callfd)\n+\tif ((int)vq->callfd >= 0)\n \t\tclose((int)vq->callfd);\n+\n \tvq->callfd = file->fd;\n \n \treturn 0;\ndiff --git a/lib/librte_vhost/virtio-net.h b/lib/librte_vhost/virtio-net.h\nnew file mode 100644\nindex 0000000..75fb57e\n--- /dev/null\n+++ b/lib/librte_vhost/virtio-net.h\n@@ -0,0 +1,43 @@\n+/*-\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+\n+#ifndef _VIRTIO_NET_H\n+#define _VIRTIO_NET_H\n+\n+#include \"vhost-net.h\"\n+#include \"rte_virtio_net.h\"\n+\n+struct virtio_net_device_ops const *notify_ops;\n+struct virtio_net *get_device(struct vhost_device_ctx ctx);\n+\n+#endif\n",
    "prefixes": [
        "dpdk-dev",
        "RFC",
        "v2",
        "10/14"
    ]
}