All of lore.kernel.org
 help / color / mirror / Atom feed
From: Michael Roth <mdroth@linux.vnet.ibm.com>
To: Stefan Hajnoczi <stefanha@redhat.com>, qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH v2 3/4] sockets: add AF_VSOCK support
Date: Mon, 31 Oct 2016 19:58:14 -0500	[thread overview]
Message-ID: <20161101005814.24053.89188@loki> (raw)
In-Reply-To: <20161025235119.17113.17155@loki>

Quoting Michael Roth (2016-10-25 18:51:19)
> Quoting Stefan Hajnoczi (2016-10-14 04:00:55)
> > Add the AF_VSOCK address family so that qemu-ga will be able to use
> > virtio-vsock.
> > 
> > The AF_VSOCK address family uses <cid, port> address tuples.  The cid is
> > the unique identifier comparable to an IP address.  AF_VSOCK does not
> > use name resolution so it's easy to convert between struct sockaddr_vm
> > and strings.
> > 
> > This patch defines a VsockSocketAddress instead of trying to piggy-back
> > on InetSocketAddress.  This is cleaner in the long run since it avoids
> > lots of IPv4 vs IPv6 vs vsock special casing.
> > 
> > Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> > ---
> > v2:
> >  * s/seasy/easy/ typo fix in commit description [Eric]
> >  * Use %n to check for trailing characters in addresses [Eric]
> > ---
> >  qapi-schema.json    |  23 +++++-
> >  util/qemu-sockets.c | 227 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 249 insertions(+), 1 deletion(-)
> > 
> > diff --git a/qapi-schema.json b/qapi-schema.json
> > index 9e47b47..12aea99 100644
> > --- a/qapi-schema.json
> > +++ b/qapi-schema.json
> > @@ -988,12 +988,14 @@
> >  #
> >  # @unix: unix socket
> >  #
> > +# @vsock: vsock family (since 2.8)
> > +#
> >  # @unknown: otherwise
> >  #
> >  # Since: 2.1
> >  ##
> >  { 'enum': 'NetworkAddressFamily',
> > -  'data': [ 'ipv4', 'ipv6', 'unix', 'unknown' ] }
> > +  'data': [ 'ipv4', 'ipv6', 'unix', 'vsock', 'unknown' ] }
> > 
> >  ##
> >  # @VncBasicInfo
> > @@ -3018,6 +3020,24 @@
> >      'path': 'str' } }
> > 
> >  ##
> > +# @VsockSocketAddress
> > +#
> > +# Captures a socket address in the vsock namespace.
> > +#
> > +# @cid: unique host identifier
> > +# @port: port
> > +#
> > +# Note that string types are used to allow for possible future hostname or
> > +# service resolution support.
> > +#
> > +# Since 2.8
> > +##
> > +{ 'struct': 'VsockSocketAddress',
> > +  'data': {
> > +    'cid': 'str',
> > +    'port': 'str' } }
> > +
> > +##
> >  # @SocketAddress
> >  #
> >  # Captures the address of a socket, which could also be a named file descriptor
> > @@ -3028,6 +3048,7 @@
> >    'data': {
> >      'inet': 'InetSocketAddress',
> >      'unix': 'UnixSocketAddress',
> > +    'vsock': 'VsockSocketAddress',
> >      'fd': 'String' } }
> > 
> >  ##
> > diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
> > index 6db48b3..6ef3cc5 100644
> > --- a/util/qemu-sockets.c
> > +++ b/util/qemu-sockets.c
> > @@ -17,6 +17,10 @@
> >   */
> >  #include "qemu/osdep.h"
> > 
> > +#ifdef AF_VSOCK
> > +#include <linux/vm_sockets.h>
> > +#endif /* AF_VSOCK */
> 
> I have this series applied locally but I hit some build issues on Ubuntu
> 14.04 due to linux/vm_sockets.h not being provided by Ubuntu 14.04's
> linux-libc-dev package. It is however included with linux-libc-dev in
> 16.04. linux-headers package includes it in both cases, but installs
> to /usr/src/linux-headers*, which are not part of the default include
> path.
> 
> Do you think we need a configure check and CONFIG_AF_VSOCK flag instead?

I've applied this series with the above-mentioned configure check
squashed into this patch. Here's the diff:

diff --git a/configure b/configure
index d3dafcb..60f1060 100755
--- a/configure
+++ b/configure
@@ -4605,6 +4605,33 @@ if compile_prog "" "" ; then
     have_rtnetlink=yes
 fi
 
+##########################################
+# check for usable AF_VSOCK environment
+have_af_vsock=no
+cat > $TMPC << EOF
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#if !defined(AF_VSOCK)
+# error missing AF_VSOCK flag
+#endif
+#include <linux/vm_sockets.h>
+int main(void) {
+    int sock, ret;
+    struct sockaddr_vm svm;
+    socklen_t len = sizeof(svm);
+    sock = socket(AF_VSOCK, SOCK_STREAM, 0);
+    ret = getpeername(sock, (struct sockaddr *)&svm, &len);
+    if ((ret == -1) && (errno == ENOTCONN)) {
+        return 0;
+    }
+    return -1;
+}
+EOF
+if compile_prog "" "" ; then
+    have_af_vsock=yes
+fi
+
 #################################################
 # Sparc implicitly links with --relax, which is
 # incompatible with -r, so --no-relax should be
@@ -5580,6 +5607,10 @@ if test "$replication" = "yes" ; then
   echo "CONFIG_REPLICATION=y" >> $config_host_mak
 fi
 
+if test "$have_af_vsock" = "yes" ; then
+  echo "CONFIG_AF_VSOCK=y" >> $config_host_mak
+fi
+
 # Hold two types of flag:
 #   CONFIG_THREAD_SETNAME_BYTHREAD  - we've got a way of setting the name on
 #                                     a thread we have a handle to
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index 559f452..e616f48 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -17,9 +17,9 @@
  */
 #include "qemu/osdep.h"
 
-#ifdef AF_VSOCK
+#ifdef CONFIG_AF_VSOCK
 #include <linux/vm_sockets.h>
-#endif /* AF_VSOCK */
+#endif /* CONFIG_AF_VSOCK */
 
 #include "monitor/monitor.h"
 #include "qapi/error.h"
@@ -79,9 +79,9 @@ NetworkAddressFamily inet_netfamily(int family)
     case PF_INET6: return NETWORK_ADDRESS_FAMILY_IPV6;
     case PF_INET:  return NETWORK_ADDRESS_FAMILY_IPV4;
     case PF_UNIX:  return NETWORK_ADDRESS_FAMILY_UNIX;
-#ifdef AF_VSOCK
+#ifdef CONFIG_AF_VSOCK
     case PF_VSOCK: return NETWORK_ADDRESS_FAMILY_VSOCK;
-#endif /* AF_VSOCK */
+#endif /* CONFIG_AF_VSOCK */
     }
     return NETWORK_ADDRESS_FAMILY_UNKNOWN;
 }
@@ -657,7 +657,7 @@ int inet_connect(const char *str, Error **errp)
     return sock;
 }
 
-#ifdef AF_VSOCK
+#ifdef CONFIG_AF_VSOCK
 static bool vsock_parse_vaddr_to_sockaddr(const VsockSocketAddress *vaddr,
                                           struct sockaddr_vm *svm,
                                           Error **errp)
@@ -830,7 +830,7 @@ static VsockSocketAddress *vsock_parse(const char *str, Error **errp)
     vsock_unsupported(errp);
     return NULL;
 }
-#endif /* AF_VSOCK */
+#endif /* CONFIG_AF_VSOCK */
 
 #ifndef _WIN32
 
@@ -1218,7 +1218,7 @@ socket_sockaddr_to_address_unix(struct sockaddr_storage *sa,
 }
 #endif /* WIN32 */
 
-#ifdef AF_VSOCK
+#ifdef CONFIG_AF_VSOCK
 static SocketAddress *
 socket_sockaddr_to_address_vsock(struct sockaddr_storage *sa,
                                  socklen_t salen,
@@ -1236,7 +1236,7 @@ socket_sockaddr_to_address_vsock(struct sockaddr_storage *sa,
 
     return addr;
 }
-#endif /* AF_VSOCK */
+#endif /* CONFIG_AF_VSOCK */
 
 SocketAddress *
 socket_sockaddr_to_address(struct sockaddr_storage *sa,
@@ -1253,7 +1253,7 @@ socket_sockaddr_to_address(struct sockaddr_storage *sa,
         return socket_sockaddr_to_address_unix(sa, salen, errp);
 #endif /* WIN32 */
 
-#ifdef AF_VSOCK
+#ifdef CONFIG_AF_VSOCK
     case AF_VSOCK:
         return socket_sockaddr_to_address_vsock(sa, salen, errp);
 #endif

> 
> > +
> >  #include "monitor/monitor.h"
> >  #include "qapi/error.h"
> >  #include "qemu/sockets.h"
> > @@ -75,6 +79,9 @@ NetworkAddressFamily inet_netfamily(int family)
> >      case PF_INET6: return NETWORK_ADDRESS_FAMILY_IPV6;
> >      case PF_INET:  return NETWORK_ADDRESS_FAMILY_IPV4;
> >      case PF_UNIX:  return NETWORK_ADDRESS_FAMILY_UNIX;
> > +#ifdef AF_VSOCK
> > +    case PF_VSOCK: return NETWORK_ADDRESS_FAMILY_VSOCK;
> > +#endif /* AF_VSOCK */
> >      }
> >      return NETWORK_ADDRESS_FAMILY_UNKNOWN;
> >  }
> > @@ -650,6 +657,181 @@ int inet_connect(const char *str, Error **errp)
> >      return sock;
> >  }
> > 
> > +#ifdef AF_VSOCK
> > +static bool vsock_parse_vaddr_to_sockaddr(const VsockSocketAddress *vaddr,
> > +                                          struct sockaddr_vm *svm,
> > +                                          Error **errp)
> > +{
> > +    unsigned long long val;
> > +
> > +    memset(svm, 0, sizeof(*svm));
> > +    svm->svm_family = AF_VSOCK;
> > +
> > +    if (parse_uint_full(vaddr->cid, &val, 10) < 0 ||
> > +        val > UINT32_MAX) {
> > +        error_setg(errp, "Failed to parse cid '%s'", vaddr->cid);
> > +        return false;
> > +    }
> > +    svm->svm_cid = val;
> > +
> > +    if (parse_uint_full(vaddr->port, &val, 10) < 0 ||
> > +        val > UINT32_MAX) {
> > +        error_setg(errp, "Failed to parse port '%s'", vaddr->port);
> > +        return false;
> > +    }
> > +    svm->svm_port = val;
> > +
> > +    return true;
> > +}
> > +
> > +static int vsock_connect_addr(const struct sockaddr_vm *svm, bool *in_progress,
> > +                              ConnectState *connect_state, Error **errp)
> > +{
> > +    int sock, rc;
> > +
> > +    *in_progress = false;
> > +
> > +    sock = qemu_socket(AF_VSOCK, SOCK_STREAM, 0);
> > +    if (sock < 0) {
> > +        error_setg_errno(errp, errno, "Failed to create socket");
> > +        return -1;
> > +    }
> > +    if (connect_state != NULL) {
> > +        qemu_set_nonblock(sock);
> > +    }
> > +    /* connect to peer */
> > +    do {
> > +        rc = 0;
> > +        if (connect(sock, (const struct sockaddr *)svm, sizeof(*svm)) < 0) {
> > +            rc = -errno;
> > +        }
> > +    } while (rc == -EINTR);
> > +
> > +    if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) {
> > +        connect_state->fd = sock;
> > +        qemu_set_fd_handler(sock, NULL, wait_for_connect, connect_state);
> > +        *in_progress = true;
> > +    } else if (rc < 0) {
> > +        error_setg_errno(errp, errno, "Failed to connect socket");
> > +        closesocket(sock);
> > +        return -1;
> > +    }
> > +    return sock;
> > +}
> > +
> > +static int vsock_connect_saddr(VsockSocketAddress *vaddr, Error **errp,
> > +                               NonBlockingConnectHandler *callback,
> > +                               void *opaque)
> > +{
> > +    struct sockaddr_vm svm;
> > +    int sock = -1;
> > +    bool in_progress;
> > +    ConnectState *connect_state = NULL;
> > +
> > +    if (!vsock_parse_vaddr_to_sockaddr(vaddr, &svm, errp)) {
> > +        return -1;
> > +    }
> > +
> > +    if (callback != NULL) {
> > +        connect_state = g_malloc0(sizeof(*connect_state));
> > +        connect_state->callback = callback;
> > +        connect_state->opaque = opaque;
> > +    }
> > +
> > +    sock = vsock_connect_addr(&svm, &in_progress, connect_state, errp);
> > +    if (sock < 0) {
> > +        /* do nothing */
> > +    } else if (in_progress) {
> > +        /* wait_for_connect() will do the rest */
> > +        return sock;
> > +    } else {
> > +        if (callback) {
> > +            callback(sock, NULL, opaque);
> > +        }
> > +    }
> > +    g_free(connect_state);
> > +    return sock;
> > +}
> > +
> > +static int vsock_listen_saddr(VsockSocketAddress *vaddr,
> > +                              Error **errp)
> > +{
> > +    struct sockaddr_vm svm;
> > +    int slisten;
> > +
> > +    if (!vsock_parse_vaddr_to_sockaddr(vaddr, &svm, errp)) {
> > +        return -1;
> > +    }
> > +
> > +    slisten = qemu_socket(AF_VSOCK, SOCK_STREAM, 0);
> > +    if (slisten < 0) {
> > +        error_setg_errno(errp, errno, "Failed to create socket");
> > +        return -1;
> > +    }
> > +
> > +    if (bind(slisten, (const struct sockaddr *)&svm, sizeof(svm)) != 0) {
> > +        error_setg_errno(errp, errno, "Failed to bind socket");
> > +        closesocket(slisten);
> > +        return -1;
> > +    }
> > +
> > +    if (listen(slisten, 1) != 0) {
> > +        error_setg_errno(errp, errno, "Failed to listen on socket");
> > +        closesocket(slisten);
> > +        return -1;
> > +    }
> > +    return slisten;
> > +}
> > +
> > +static VsockSocketAddress *vsock_parse(const char *str, Error **errp)
> > +{
> > +    VsockSocketAddress *addr = NULL;
> > +    char cid[33];
> > +    char port[33];
> > +    int n;
> > +
> > +    if (sscanf(str, "%32[^:]:%32[^,]%n", cid, port, &n) != 2) {
> > +        error_setg(errp, "error parsing address '%s'", str);
> > +        return NULL;
> > +    }
> > +    if (str[n] != '\0') {
> > +        error_setg(errp, "trailing characters in address '%s'", str);
> > +        return NULL;
> > +    }
> > +
> > +    addr = g_new0(VsockSocketAddress, 1);
> > +    addr->cid = g_strdup(cid);
> > +    addr->port = g_strdup(port);
> > +    return addr;
> > +}
> > +#else
> > +static void vsock_unsupported(Error **errp)
> > +{
> > +    error_setg(errp, "socket family AF_VSOCK unsupported");
> > +}
> > +
> > +static int vsock_connect_saddr(VsockSocketAddress *vaddr, Error **errp,
> > +                               NonBlockingConnectHandler *callback,
> > +                               void *opaque)
> > +{
> > +    vsock_unsupported(errp);
> > +    return -1;
> > +}
> > +
> > +static int vsock_listen_saddr(VsockSocketAddress *vaddr,
> > +                              Error **errp)
> > +{
> > +    vsock_unsupported(errp);
> > +    return -1;
> > +}
> > +
> > +static VsockSocketAddress *vsock_parse(const char *str, Error **errp)
> > +{
> > +    vsock_unsupported(errp);
> > +    return NULL;
> > +}
> > +#endif /* AF_VSOCK */
> > +
> >  #ifndef _WIN32
> > 
> >  static int unix_listen_saddr(UnixSocketAddress *saddr,
> > @@ -864,6 +1046,12 @@ SocketAddress *socket_parse(const char *str, Error **errp)
> >              addr->u.fd.data = g_new(String, 1);
> >              addr->u.fd.data->str = g_strdup(str + 3);
> >          }
> > +    } else if (strstart(str, "vsock:", NULL)) {
> > +        addr->type = SOCKET_ADDRESS_KIND_VSOCK;
> > +        addr->u.vsock.data = vsock_parse(str + strlen("vsock:"), errp);
> > +        if (addr->u.vsock.data == NULL) {
> > +            goto fail;
> > +        }
> >      } else {
> >          addr->type = SOCKET_ADDRESS_KIND_INET;
> >          addr->u.inet.data = inet_parse(str, errp);
> > @@ -900,6 +1088,10 @@ int socket_connect(SocketAddress *addr, Error **errp,
> >          }
> >          break;
> > 
> > +    case SOCKET_ADDRESS_KIND_VSOCK:
> > +        fd = vsock_connect_saddr(addr->u.vsock.data, errp, callback, opaque);
> > +        break;
> > +
> >      default:
> >          abort();
> >      }
> > @@ -923,6 +1115,10 @@ int socket_listen(SocketAddress *addr, Error **errp)
> >          fd = monitor_get_fd(cur_mon, addr->u.fd.data->str, errp);
> >          break;
> > 
> > +    case SOCKET_ADDRESS_KIND_VSOCK:
> > +        fd = vsock_listen_saddr(addr->u.vsock.data, errp);
> > +        break;
> > +
> >      default:
> >          abort();
> >      }
> > @@ -1022,6 +1218,26 @@ socket_sockaddr_to_address_unix(struct sockaddr_storage *sa,
> >  }
> >  #endif /* WIN32 */
> > 
> > +#ifdef AF_VSOCK
> > +static SocketAddress *
> > +socket_sockaddr_to_address_vsock(struct sockaddr_storage *sa,
> > +                                 socklen_t salen,
> > +                                 Error **errp)
> > +{
> > +    SocketAddress *addr;
> > +    VsockSocketAddress *vaddr;
> > +    struct sockaddr_vm *svm = (struct sockaddr_vm *)sa;
> > +
> > +    addr = g_new0(SocketAddress, 1);
> > +    addr->type = SOCKET_ADDRESS_KIND_VSOCK;
> > +    addr->u.vsock.data = vaddr = g_new0(VsockSocketAddress, 1);
> > +    vaddr->cid = g_strdup_printf("%u", svm->svm_cid);
> > +    vaddr->port = g_strdup_printf("%u", svm->svm_port);
> > +
> > +    return addr;
> > +}
> > +#endif /* AF_VSOCK */
> > +
> >  SocketAddress *
> >  socket_sockaddr_to_address(struct sockaddr_storage *sa,
> >                             socklen_t salen,
> > @@ -1037,6 +1253,11 @@ socket_sockaddr_to_address(struct sockaddr_storage *sa,
> >          return socket_sockaddr_to_address_unix(sa, salen, errp);
> >  #endif /* WIN32 */
> > 
> > +#ifdef AF_VSOCK
> > +    case AF_VSOCK:
> > +        return socket_sockaddr_to_address_vsock(sa, salen, errp);
> > +#endif
> > +
> >      default:
> >          error_setg(errp, "socket family %d unsupported",
> >                     sa->ss_family);
> > @@ -1103,6 +1324,12 @@ char *socket_address_to_string(struct SocketAddress *addr, Error **errp)
> >          buf = g_strdup(addr->u.fd.data->str);
> >          break;
> > 
> > +    case SOCKET_ADDRESS_KIND_VSOCK:
> > +        buf = g_strdup_printf("%s:%s",
> > +                              addr->u.vsock.data->cid,
> > +                              addr->u.vsock.data->port);
> > +        break;
> > +
> >      default:
> >          error_setg(errp, "socket family %d unsupported",
> >                     addr->type);
> > -- 
> > 2.7.4
> > 
> 
> 

  reply	other threads:[~2016-11-01  0:58 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-10-14  9:00 [Qemu-devel] [PATCH v2 0/4] qga: add vsock-listen Stefan Hajnoczi
2016-10-14  9:00 ` [Qemu-devel] [PATCH v2 1/4] qga: drop unused sockaddr in accept(2) call Stefan Hajnoczi
2016-10-14  9:00 ` [Qemu-devel] [PATCH v2 2/4] qga: drop unnecessary GA_CHANNEL_UNIX_LISTEN checks Stefan Hajnoczi
2016-10-14  9:00 ` [Qemu-devel] [PATCH v2 3/4] sockets: add AF_VSOCK support Stefan Hajnoczi
2016-10-14 14:40   ` Eric Blake
2016-10-16 13:35     ` Stefan Hajnoczi
2016-10-17 14:25       ` Eric Blake
2016-10-18 10:21         ` Stefan Hajnoczi
2017-11-05 18:59           ` Kashyap Chamarthy
2017-11-06 17:12             ` Stefan Hajnoczi
2016-10-25 23:51   ` Michael Roth
2016-11-01  0:58     ` Michael Roth [this message]
2016-10-14  9:00 ` [Qemu-devel] [PATCH v2 4/4] qga: add vsock-listen method Stefan Hajnoczi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20161101005814.24053.89188@loki \
    --to=mdroth@linux.vnet.ibm.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.