get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 3645,
    "url": "https://patches.dpdk.org/api/patches/3645/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1424712993-73818-10-git-send-email-przemyslaw.czesnowicz@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": "<1424712993-73818-10-git-send-email-przemyslaw.czesnowicz@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1424712993-73818-10-git-send-email-przemyslaw.czesnowicz@intel.com",
    "date": "2015-02-23T17:36:31",
    "name": "[dpdk-dev,v3,09/11] lib/librte_vhost: vhost user support",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "a375261a8e40b22fc8dccd604c76ab2ac69472ce",
    "submitter": {
        "id": 145,
        "url": "https://patches.dpdk.org/api/people/145/?format=api",
        "name": "Czesnowicz, Przemyslaw",
        "email": "przemyslaw.czesnowicz@intel.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1424712993-73818-10-git-send-email-przemyslaw.czesnowicz@intel.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/3645/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/3645/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 01CACB3F1;\n\tMon, 23 Feb 2015 18:36:03 +0100 (CET)",
            "from mga14.intel.com (mga14.intel.com [192.55.52.115])\n\tby dpdk.org (Postfix) with ESMTP id E5276ADE7\n\tfor <dev@dpdk.org>; Mon, 23 Feb 2015 18:35:54 +0100 (CET)",
            "from orsmga001.jf.intel.com ([10.7.209.18])\n\tby fmsmga103.fm.intel.com with ESMTP; 23 Feb 2015 09:28:00 -0800",
            "from sie-lab-214-135.ir.intel.com (HELO\n\tsilpixa00385231.ir.intel.com) ([10.237.214.135])\n\tby orsmga001.jf.intel.com with ESMTP; 23 Feb 2015 09:35:53 -0800"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.09,631,1418112000\"; d=\"scan'208\";a=\"655973921\"",
        "From": "Przemyslaw Czesnowicz <przemyslaw.czesnowicz@intel.com>",
        "To": "dev@dpdk.org",
        "Date": "Mon, 23 Feb 2015 17:36:31 +0000",
        "Message-Id": "<1424712993-73818-10-git-send-email-przemyslaw.czesnowicz@intel.com>",
        "X-Mailer": "git-send-email 1.9.3",
        "In-Reply-To": "<1424712993-73818-1-git-send-email-przemyslaw.czesnowicz@intel.com>",
        "References": "<1423717649-11818-1-git-send-email-huawei.xie@intel.com>\n\t<1424712993-73818-1-git-send-email-przemyslaw.czesnowicz@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v3 09/11] lib/librte_vhost: 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": "From: \"Xie, Huawei\" <huawei.xie@intel.com>\n\nIn rte_vhost_driver_register(), vhost unix domain socket listener fd is created\nand added to polled(based on select) fdset.\n\nIn rte_vhost_driver_session_start(), fds in the fdset are checked for\nprocessing. If there is new connection from qemu, connection fd accepted is\nadded to polled fdset. The listener and connection fds in the fdset are\nthen both checked. When there is message on the connection fd, its\ncallback vserver_message_handler is called to process vhost-user messages.\n\nTo support identifying which virtio is from which guest VM, we could call\nrte_vhost_driver_register with different socket path. Virtio devices from\nsame VM will connect to VM specific socket. The socket path information is\nstored in the virtio_net structure.\n\nSigned-off-by: Huawei Xie <huawei.xie@intel.com>\nSigned-off-by: Przemyslaw Czesnowicz <przemyslaw.czesnowicz@intel.com>\n---\n lib/librte_vhost/Makefile                     |   8 +-\n lib/librte_vhost/rte_virtio_net.h             |   2 +\n lib/librte_vhost/vhost-net.h                  |   4 +-\n lib/librte_vhost/vhost_user/vhost-net-user.c  | 457 ++++++++++++++++++++++++++\n lib/librte_vhost/vhost_user/vhost-net-user.h  | 106 ++++++\n lib/librte_vhost/vhost_user/virtio-net-user.c | 314 ++++++++++++++++++\n lib/librte_vhost/vhost_user/virtio-net-user.h |  49 +++\n lib/librte_vhost/virtio-net.c                 |  15 +-\n 8 files changed, 948 insertions(+), 7 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",
    "diff": "diff --git a/lib/librte_vhost/Makefile b/lib/librte_vhost/Makefile\nindex 298e4f8..cac943e 100644\n--- a/lib/librte_vhost/Makefile\n+++ b/lib/librte_vhost/Makefile\n@@ -38,10 +38,14 @@ EXPORT_MAP := rte_vhost_version.map\n \n LIBABIVER := 1\n \n-CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -I vhost_cuse -O3 -D_FILE_OFFSET_BITS=64 -lfuse\n+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 -D_FILE_OFFSET_BITS=64\n+CFLAGS += -I vhost_cuse -lfuse\n+CFLAGS += -I vhost_user\n LDFLAGS += -lfuse\n # all source are stored in SRCS-y\n-SRCS-$(CONFIG_RTE_LIBRTE_VHOST) := virtio-net.c vhost_cuse/vhost-net-cdev.c vhost_cuse/virtio-net-cdev.c vhost_cuse/eventfd_copy.c vhost_rxtx.c\n+SRCS-$(CONFIG_RTE_LIBRTE_VHOST) := virtio-net.c vhost_rxtx.c vhost_cuse/eventfd_copy.c\n+#SRCS-$(CONFIG_RTE_LIBRTE_VHOST) += vhost_cuse/vhost-net-cdev.c vhost_cuse/virtio-net-cdev.c vhost_cuse/eventfd_copy.c\n+SRCS-$(CONFIG_RTE_LIBRTE_VHOST) += vhost_user/vhost-net-user.c vhost_user/virtio-net-user.c vhost_user/fd_man.c\n \n # install includes\n SYMLINK-$(CONFIG_RTE_LIBRTE_VHOST)-include += rte_virtio_net.h\ndiff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h\nindex 0bf07c7..46c2072 100644\n--- a/lib/librte_vhost/rte_virtio_net.h\n+++ b/lib/librte_vhost/rte_virtio_net.h\n@@ -50,6 +50,8 @@\n #include <rte_mempool.h>\n #include <rte_mbuf.h>\n \n+#define VHOST_MEMORY_MAX_NREGIONS 8\n+\n /* Used to indicate that the device is running on a data core */\n #define VIRTIO_DEV_RUNNING 1\n \ndiff --git a/lib/librte_vhost/vhost-net.h b/lib/librte_vhost/vhost-net.h\nindex 86b38a5..a56e405 100644\n--- a/lib/librte_vhost/vhost-net.h\n+++ b/lib/librte_vhost/vhost-net.h\n@@ -41,7 +41,9 @@\n \n #include <rte_log.h>\n \n-#define VHOST_MEMORY_MAX_NREGIONS 8\n+#include \"rte_virtio_net.h\"\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\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..712a82f\n--- /dev/null\n+++ b/lib/librte_vhost/vhost_user/vhost-net-user.c\n@@ -0,0 +1,457 @@\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+#define MAX_VIRTIO_BACKLOG 128\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+struct connfd_ctx {\n+\tstruct vhost_server *vserver;\n+\tuint32_t fh;\n+};\n+\n+#define MAX_VHOST_SERVER 1024\n+static struct {\n+\tstruct vhost_server *server[MAX_VHOST_SERVER];\n+\tstruct fdset fdset;\t/**< The fd list this vhost server manages. */\n+} g_vhost_server;\n+\n+static int vserver_idx;\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, MAX_VIRTIO_BACKLOG);\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;\n+\tsize_t fdsize = fd_num * sizeof(int);\n+\tchar control[CMSG_SPACE(fdsize)];\n+\tstruct cmsghdr *cmsg;\n+\tint ret;\n+\n+\tmemset(&msgh, 0, sizeof(msgh));\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;\n+\tsize_t fdsize = fd_num * sizeof(int);\n+\tchar control[CMSG_SPACE(fdsize)];\n+\tstruct cmsghdr *cmsg;\n+\tint ret;\n+\n+\tmemset(&msgh, 0, sizeof(msgh));\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+\tstruct connfd_ctx *ctx;\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+\tctx = calloc(1, sizeof(*ctx));\n+\tif (ctx == NULL) {\n+\t\tclose(conn_fd);\n+\t\treturn;\n+\t}\n+\n+\tfh = ops->new_device(vdev_ctx);\n+\tif (fh == -1) {\n+\t\tfree(ctx);\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+\tctx->vserver = vserver;\n+\tctx->fh = fh;\n+\tfdset_add(&g_vhost_server.fdset,\n+\t\tconn_fd, vserver_message_handler, NULL, ctx);\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+\tstruct connfd_ctx *cfd_ctx = (struct connfd_ctx *)dat;\n+\tstruct VhostUserMsg msg;\n+\tuint64_t features;\n+\tint ret;\n+\n+\tctx.fh = cfd_ctx->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\tfree(cfd_ctx);\n+\t\tuser_destroy_device(ctx);\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\tfree(cfd_ctx);\n+\t\tuser_destroy_device(ctx);\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+\t\tfree(cfd_ctx);\n+\t\tuser_destroy_device(ctx);\n+\t\tops->destroy_device(ctx);\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+\tstruct vhost_server *vserver;\n+\n+\tif (vserver_idx == 0) {\n+\t\tfdset_init(&g_vhost_server.fdset);\n+\t\tops = get_virtio_net_callbacks();\n+\t}\n+\tif (vserver_idx == MAX_VHOST_SERVER)\n+\t\treturn -1;\n+\n+\tvserver = calloc(sizeof(struct vhost_server), 1);\n+\tif (vserver == NULL)\n+\t\treturn -1;\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(&g_vhost_server.fdset, vserver->listenfd,\n+\t\tvserver_new_vq_conn, NULL,\n+\t\tvserver);\n+\n+\tg_vhost_server.server[vserver_idx++] = 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+}\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..1b6be6c\n--- /dev/null\n+++ b/lib/librte_vhost/vhost_user/vhost-net-user.h\n@@ -0,0 +1,106 @@\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 \"rte_virtio_net.h\"\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+};\n+\n+/* refer to hw/virtio/vhost-user.c */\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 offsetof(VhostUserMsg, 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..97c5177\n--- /dev/null\n+++ b/lib/librte_vhost/vhost_user/virtio-net-user.c\n@@ -0,0 +1,314 @@\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+#include <sys/types.h>\n+#include <sys/stat.h>\n+#include <unistd.h>\n+\n+#include <rte_common.h>\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+struct orig_region_map {\n+\tint fd;\n+\tuint64_t mapped_address;\n+\tuint64_t mapped_size;\n+\tuint64_t blksz;\n+};\n+\n+#define orig_region(ptr, nregions) \\\n+\t((struct orig_region_map *)RTE_PTR_ADD((ptr), \\\n+\t\tsizeof(struct virtio_memory) + \\\n+\t\tsizeof(struct virtio_memory_regions) * (nregions)))\n+\n+static uint64_t\n+get_blk_size(int fd)\n+{\n+\tstruct stat stat;\n+\n+\tfstat(fd, &stat);\n+\treturn (uint64_t)stat.st_blksize;\n+}\n+\n+static void\n+free_mem_region(struct virtio_net *dev)\n+{\n+\tstruct orig_region_map *region;\n+\tunsigned int idx;\n+\tuint64_t alignment;\n+\n+\tif (!dev || !dev->mem)\n+\t\treturn;\n+\n+\tregion = orig_region(dev->mem, dev->mem->nregions);\n+\tfor (idx = 0; idx < dev->mem->nregions; idx++) {\n+\t\tif (region[idx].mapped_address) {\n+\t\t\talignment = region[idx].blksz;\n+\t\t\tmunmap((void *)\n+\t\t\t\tRTE_ALIGN_FLOOR(\n+\t\t\t\t\tregion[idx].mapped_address, alignment),\n+\t\t\t\tRTE_ALIGN_CEIL(\n+\t\t\t\t\tregion[idx].mapped_size, alignment));\n+\t\t\tclose(region[idx].fd);\n+\t\t}\n+\t}\n+}\n+\n+int\n+user_set_mem_table(struct vhost_device_ctx ctx, struct VhostUserMsg *pmsg)\n+{\n+\tstruct VhostUserMemory memory = pmsg->payload.memory;\n+\tstruct virtio_memory_regions *pregion;\n+\tuint64_t mapped_address, mapped_size;\n+\tstruct virtio_net *dev;\n+\tunsigned int idx = 0;\n+\tstruct orig_region_map *pregion_orig;\n+\tuint64_t alignment;\n+\n+\t/* unmap old memory regions one by one*/\n+\tdev = get_device(ctx);\n+\tif (dev == NULL)\n+\t\treturn -1;\n+\n+\tif (dev->mem) {\n+\t\tfree_mem_region(dev);\n+\t\tfree(dev->mem);\n+\t\tdev->mem = NULL;\n+\t}\n+\n+\tdev->mem = calloc(1,\n+\t\tsizeof(struct virtio_memory) +\n+\t\tsizeof(struct virtio_memory_regions) * memory.nregions +\n+\t\tsizeof(struct orig_region_map) * memory.nregions);\n+\tif (dev->mem == NULL) {\n+\t\tRTE_LOG(ERR, VHOST_CONFIG,\n+\t\t\t\"(%\"PRIu64\") Failed to allocate memory for dev->mem\\n\",\n+\t\t\tdev->device_fh);\n+\t\treturn -1;\n+\t}\n+\tdev->mem->nregions = memory.nregions;\n+\n+\tpregion_orig = orig_region(dev->mem, memory.nregions);\n+\tfor (idx = 0; idx < memory.nregions; idx++) {\n+\t\tpregion = &dev->mem->regions[idx];\n+\t\tpregion->guest_phys_address =\n+\t\t\tmemory.regions[idx].guest_phys_addr;\n+\t\tpregion->guest_phys_address_end =\n+\t\t\tmemory.regions[idx].guest_phys_addr +\n+\t\t\tmemory.regions[idx].memory_size;\n+\t\tpregion->memory_size =\n+\t\t\tmemory.regions[idx].memory_size;\n+\t\tpregion->userspace_address =\n+\t\t\tmemory.regions[idx].userspace_addr;\n+\n+\t\t/* This is ugly */\n+\t\tmapped_size = memory.regions[idx].memory_size +\n+\t\t\tmemory.regions[idx].mmap_offset;\n+\t\tmapped_address = (uint64_t)(uintptr_t)mmap(NULL,\n+\t\t\tmapped_size,\n+\t\t\tPROT_READ | PROT_WRITE, MAP_SHARED,\n+\t\t\tpmsg->fds[idx],\n+\t\t\t0);\n+\n+\t\tRTE_LOG(INFO, VHOST_CONFIG,\n+\t\t\t\"mapped region %d fd:%d to %p sz:0x%\"PRIx64\" off:0x%\"PRIx64\"\\n\",\n+\t\t\tidx, pmsg->fds[idx], (void *)mapped_address,\n+\t\t\tmapped_size, memory.regions[idx].mmap_offset);\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\tgoto err_mmap;\n+\t\t}\n+\n+\t\tpregion_orig[idx].mapped_address = mapped_address;\n+\t\tpregion_orig[idx].mapped_size = mapped_size;\n+\t\tpregion_orig[idx].blksz = get_blk_size(pmsg->fds[idx]);\n+\t\tpregion_orig[idx].fd = pmsg->fds[idx];\n+\n+\t\tmapped_address +=  memory.regions[idx].mmap_offset;\n+\n+\t\tpregion->address_offset = mapped_address -\n+\t\t\tpregion->guest_phys_address;\n+\n+\t\tif (memory.regions[idx].guest_phys_addr == 0) {\n+\t\t\tdev->mem->base_address =\n+\t\t\t\tmemory.regions[idx].userspace_addr;\n+\t\t\tdev->mem->mapped_address =\n+\t\t\t\tpregion->address_offset;\n+\t\t}\n+\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)pregion->guest_phys_address,\n+\t\t\t(void *)(uintptr_t)pregion->userspace_address,\n+\t\t\t pregion->memory_size);\n+\t}\n+\n+\treturn 0;\n+\n+err_mmap:\n+\twhile (idx--) {\n+\t\talignment = pregion_orig[idx].blksz;\n+\t\tmunmap((void *)RTE_ALIGN_FLOOR(\n+\t\t\tpregion_orig[idx].mapped_address, alignment),\n+\t\t\tRTE_ALIGN_CEIL(pregion_orig[idx].mapped_size,\n+\t\t\t\t\talignment));\n+\t\tclose(pregion_orig[idx].fd);\n+\t}\n+\tfree(dev->mem);\n+\tdev->mem = NULL;\n+\treturn -1;\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+ * 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+\n+void\n+user_destroy_device(struct vhost_device_ctx ctx)\n+{\n+\tstruct virtio_net *dev = get_device(ctx);\n+\n+\tif (dev && (dev->flags & VIRTIO_DEV_RUNNING))\n+\t\tnotify_ops->destroy_device(dev);\n+\n+\tif (dev && dev->mem) {\n+\t\tfree_mem_region(dev);\n+\t\tfree(dev->mem);\n+\t\tdev->mem = NULL;\n+\t}\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..df24860\n--- /dev/null\n+++ b/lib/librte_vhost/vhost_user/virtio-net-user.h\n@@ -0,0 +1,49 @@\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+void user_destroy_device(struct vhost_device_ctx);\n+#endif\ndiff --git a/lib/librte_vhost/virtio-net.c b/lib/librte_vhost/virtio-net.c\nindex 3e73a35..9dea69c 100644\n--- a/lib/librte_vhost/virtio-net.c\n+++ b/lib/librte_vhost/virtio-net.c\n@@ -92,8 +92,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@@ -260,6 +261,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@@ -576,7 +582,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@@ -602,8 +608,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;\n",
    "prefixes": [
        "dpdk-dev",
        "v3",
        "09/11"
    ]
}