From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53443) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Vu0nI-0001Oa-TT for qemu-devel@nongnu.org; Fri, 20 Dec 2013 09:11:18 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Vu0nC-0003Z3-Si for qemu-devel@nongnu.org; Fri, 20 Dec 2013 09:11:12 -0500 Received: from mail-wg0-f41.google.com ([74.125.82.41]:50742) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Vu0nC-0003Yp-KH for qemu-devel@nongnu.org; Fri, 20 Dec 2013 09:11:06 -0500 Received: by mail-wg0-f41.google.com with SMTP id y10so6961543wgg.0 for ; Fri, 20 Dec 2013 06:11:06 -0800 (PST) From: "Mian M. Hamayun" Date: Fri, 20 Dec 2013 15:10:37 +0100 Message-Id: <1387548640-7120-5-git-send-email-m.hamayun@virtualopensystems.com> In-Reply-To: <1387548640-7120-1-git-send-email-m.hamayun@virtualopensystems.com> References: <1387548640-7120-1-git-send-email-m.hamayun@virtualopensystems.com> Subject: [Qemu-devel] [PATCH v4 4/7] Add domain socket communication for vhost-user backend List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org, snabb-devel@googlegroups.com Cc: lukego@gmail.com, Antonios Motakis , tech@virtualopensystems.com, n.nikolaev@virtualopensystems.com, "Michael S. Tsirkin" From: Antonios Motakis Add structures for passing vhost-user messages over a unix domain socket. This is the equivalent to 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 = { -- 1.8.3.2