From patchwork Fri Dec 13 11:14:34 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonios Motakis X-Patchwork-Id: 300982 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id ED59A2C00A0 for ; Fri, 13 Dec 2013 22:16:14 +1100 (EST) Received: from localhost ([::1]:41553 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VrQj6-0000U6-AN for incoming@patchwork.ozlabs.org; Fri, 13 Dec 2013 06:16:12 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46936) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VrQiJ-0000MQ-O0 for qemu-devel@nongnu.org; Fri, 13 Dec 2013 06:15:29 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VrQiD-000494-Kq for qemu-devel@nongnu.org; Fri, 13 Dec 2013 06:15:23 -0500 Received: from mail-we0-f174.google.com ([74.125.82.174]:57407) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VrQiD-000489-D4 for qemu-devel@nongnu.org; Fri, 13 Dec 2013 06:15:17 -0500 Received: by mail-we0-f174.google.com with SMTP id q58so1711088wes.19 for ; Fri, 13 Dec 2013 03:15:16 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=tAO9MyOd6a7Ksv5bgXAKdFxmUocFnUYA38geszHtiOk=; b=H4yvMhv0swcTD0B7rB8QbrynJ8nRoy2Nvd00gDFhlhtb7jSrJi6I0hR34si1u8Wjua s7k8uWK7kCk1RgRIrsycsTgOQSFM7jusZtZ8vmQJH7VcQ9bdnUTcmJc8TMb25FbmadQ4 MApxe5UclLSZIjgBWCH/sP38ZpGGvWAIah8szXS26Y3QYP/I8xZcWf+KnkjrMyvzM061 iN0cv1Cdu+TxrbuQ0n1bnEbYkZEjLut/XBeFcg4t8BmsKu2REyJgSTaJUXQL6hab0J3Q MFS8kUEbUTsQiOhh+YcfzaRLezaOHRfJz7MqR2H+oiiR4Ic2sdrC9IKh+rci9mLqiP70 cwdw== X-Gm-Message-State: ALoCoQlY7wFradP9cbQMKr4oQhW0jB6+tRSqLITVVRgkxDfeleRacSVD0w0wGwFVraVVsmlzpS2j X-Received: by 10.180.14.195 with SMTP id r3mr1956015wic.51.1386933316636; Fri, 13 Dec 2013 03:15:16 -0800 (PST) Received: from localhost.localdomain (home.tvelocity.eu. [82.67.68.96]) by mx.google.com with ESMTPSA id n6sm6306661wix.3.2013.12.13.03.15.13 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 13 Dec 2013 03:15:15 -0800 (PST) From: Antonios Motakis To: qemu-devel@nongnu.org, snabb-devel@googlegroups.com Date: Fri, 13 Dec 2013 12:14:34 +0100 Message-Id: <1386933277-20003-5-git-send-email-a.motakis@virtualopensystems.com> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1386933277-20003-1-git-send-email-a.motakis@virtualopensystems.com> References: <1386933277-20003-1-git-send-email-a.motakis@virtualopensystems.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 74.125.82.174 Cc: lukego@gmail.com, Antonios Motakis , tech@virtualopensystems.com, n.nikolaev@virtualopensystems.com, "Michael S. Tsirkin" Subject: [Qemu-devel] [PATCH v3 4/7] Add domain socket communication for vhost-user backend X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Add structures for passing vhost-user messages over a unix domain socket. This is the equivalent of the existing vhost-kernel ioctls. Connect to the named unix domain socket. The system call sendmsg is used for communication. To be able to pass file descriptors between processes - we use SCM_RIGHTS type in the message control header. Signed-off-by: Antonios Motakis Signed-off-by: Nikolay Nikolaev --- hw/virtio/vhost-backend.c | 167 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 161 insertions(+), 6 deletions(-) diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c index 847809f..96d3bf0 100644 --- a/hw/virtio/vhost-backend.c +++ b/hw/virtio/vhost-backend.c @@ -14,30 +14,185 @@ #include #include #include +#include +#include +#include + +#define VHOST_MEMORY_MAX_NREGIONS 8 + +typedef enum VhostUserRequest { + VHOST_USER_NONE = 0, + VHOST_USER_GET_FEATURES = 1, + VHOST_USER_SET_FEATURES = 2, + VHOST_USER_SET_OWNER = 3, + VHOST_USER_RESET_OWNER = 4, + VHOST_USER_SET_MEM_TABLE = 5, + VHOST_USER_SET_LOG_BASE = 6, + VHOST_USER_SET_LOG_FD = 7, + VHOST_USER_SET_VRING_NUM = 8, + VHOST_USER_SET_VRING_ADDR = 9, + VHOST_USER_SET_VRING_BASE = 10, + VHOST_USER_GET_VRING_BASE = 11, + VHOST_USER_SET_VRING_KICK = 12, + VHOST_USER_SET_VRING_CALL = 13, + VHOST_USER_SET_VRING_ERR = 14, + VHOST_USER_NET_SET_BACKEND = 15, + VHOST_USER_MAX +} VhostUserRequest; + +typedef struct VhostUserMemoryRegion { + __u64 guest_phys_addr; + __u64 memory_size; + __u64 userspace_addr; +} VhostUserMemoryRegion; + +typedef struct VhostUserMemory { + __u32 nregions; + VhostUserMemoryRegion regions[VHOST_MEMORY_MAX_NREGIONS]; +} VhostUserMemory; + +typedef struct VhostUserMsg { + VhostUserRequest request; + + int flags; + union { + uint64_t u64; + int fd; + struct vhost_vring_state state; + struct vhost_vring_addr addr; + struct vhost_vring_file file; + + VhostUserMemory memory; + }; +} VhostUserMsg; + +static int vhost_user_recv(int fd, VhostUserMsg *msg) +{ + ssize_t r = read(fd, msg, sizeof(VhostUserMsg)); + + return (r == sizeof(VhostUserMsg)) ? 0 : -1; +} + +static int vhost_user_send_fds(int fd, const VhostUserMsg *msg, int *fds, + size_t fd_num) +{ + int r; + + struct msghdr msgh; + struct iovec iov[1]; + + size_t fd_size = fd_num * sizeof(int); + char control[CMSG_SPACE(fd_size)]; + struct cmsghdr *cmsg; + + memset(&msgh, 0, sizeof(msgh)); + memset(control, 0, sizeof(control)); + + /* set the payload */ + iov[0].iov_base = (void *) msg; + iov[0].iov_len = sizeof(VhostUserMsg); + + msgh.msg_iov = iov; + msgh.msg_iovlen = 1; + + if (fd_num) { + msgh.msg_control = control; + msgh.msg_controllen = sizeof(control); + + cmsg = CMSG_FIRSTHDR(&msgh); + + cmsg->cmsg_len = CMSG_LEN(fd_size); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + memcpy(CMSG_DATA(cmsg), fds, fd_size); + } else { + msgh.msg_control = 0; + msgh.msg_controllen = 0; + } + + do { + r = sendmsg(fd, &msgh, 0); + } while (r < 0 && errno == EINTR); + + if (r < 0) { + fprintf(stderr, "Failed to send msg(%d), reason: %s\n", + msg->request, strerror(errno)); + } else { + r = 0; + } + + return r; +} static int vhost_user_call(struct vhost_dev *dev, unsigned long int request, void *arg) { + int fd = dev->control; + VhostUserMsg msg; + int result = 0, need_reply = 0; + int fds[VHOST_MEMORY_MAX_NREGIONS]; + size_t fd_num = 0; + assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER); - fprintf(stderr, "vhost_user_call not implemented\n"); - return -1; + switch (request) { + default: + fprintf(stderr, "vhost-user trying to send unhandled ioctl\n"); + return -1; + break; + } + + result = vhost_user_send_fds(fd, &msg, fds, fd_num); + + if (!result && need_reply) { + result = vhost_user_recv(fd, &msg); + if (!result) { + switch (request) { + default: + break; + } + } + } + + return result; } static int vhost_user_init(struct vhost_dev *dev, const char *devpath) { + int fd = -1; + struct sockaddr_un un; + size_t len; + assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER); - fprintf(stderr, "vhost_user_init not implemented\n"); - return -1; + /* Create the socket */ + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd == -1) { + perror("socket"); + return -1; + } + + un.sun_family = AF_UNIX; + strcpy(un.sun_path, devpath); + + len = sizeof(un.sun_family) + strlen(devpath); + + /* Connect */ + if (connect(fd, (struct sockaddr *) &un, len) == -1) { + perror("connect"); + return -1; + } + + dev->control = fd; + + return fd; } static int vhost_user_cleanup(struct vhost_dev *dev) { assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER); - fprintf(stderr, "vhost_user_cleanup not implemented\n"); - return -1; + return close(dev->control); } static const VhostOps user_ops = {