diff options
author | Hao Chen <chenhaosjtuacm@google.com> | 2020-01-10 13:52:35 -0800 |
---|---|---|
committer | Hao Chen <chenhaosjtuacm@google.com> | 2020-01-10 13:52:35 -0800 |
commit | a0d43cf1a94bc5443ee8ee2499490f6af4da6272 (patch) | |
tree | 110b029d64273a9ffb3cb9af91481516cd49183b /src/core | |
parent | 987bce6ff47fcdb93db330fccb1e3f4471fbd0ec (diff) | |
download | grpc-grpc-a0d43cf1a94bc5443ee8ee2499490f6af4da6272.tar.gz |
Vsock support for GRPC
This is originally from Chrome OS team. Modified to make it
builds on non-Linux platforms
Test: done on Cufflefish VM with ag/9869094
Bug: b/145631107
Change-Id: I41a5f8af68488cc6c9b9629d9c99b54bc085764a
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/ext/filters/client_channel/parse_address.cc | 32 | ||||
-rw-r--r-- | src/core/ext/filters/client_channel/parse_address.h | 5 | ||||
-rw-r--r-- | src/core/lib/iomgr/port.h | 10 | ||||
-rw-r--r-- | src/core/lib/iomgr/resolve_address_posix.cc | 5 | ||||
-rw-r--r-- | src/core/lib/iomgr/sockaddr_posix.h | 7 | ||||
-rw-r--r-- | src/core/lib/iomgr/sockaddr_utils.cc | 29 | ||||
-rw-r--r-- | src/core/lib/iomgr/tcp_client_posix.cc | 2 | ||||
-rw-r--r-- | src/core/lib/iomgr/tcp_server_posix.cc | 2 | ||||
-rw-r--r-- | src/core/lib/iomgr/tcp_server_utils_posix_common.cc | 5 | ||||
-rw-r--r-- | src/core/lib/iomgr/udp_server.cc | 2 | ||||
-rw-r--r-- | src/core/lib/iomgr/unix_sockets_posix.cc | 57 | ||||
-rw-r--r-- | src/core/lib/iomgr/unix_sockets_posix.h | 8 |
12 files changed, 156 insertions, 8 deletions
diff --git a/src/core/ext/filters/client_channel/parse_address.cc b/src/core/ext/filters/client_channel/parse_address.cc index 707beb8876..c737f53d01 100644 --- a/src/core/ext/filters/client_channel/parse_address.cc +++ b/src/core/ext/filters/client_channel/parse_address.cc @@ -26,6 +26,10 @@ #include <string.h> #ifdef GRPC_HAVE_UNIX_SOCKET #include <sys/un.h> +#ifdef GRPC_HAVE_LINUX_VSOCK +#include <sys/socket.h> +#include <linux/vm_sockets.h> +#endif /* GRPC_HAVE_LINUX_VSOCK */ #endif #include <grpc/support/alloc.h> @@ -63,6 +67,32 @@ bool grpc_parse_unix(const grpc_uri* uri, #endif /* GRPC_HAVE_UNIX_SOCKET */ +#if defined(GRPC_HAVE_UNIX_SOCKET) && defined(GRPC_HAVE_LINUX_VSOCK) + +bool grpc_parse_vsock(const grpc_uri* uri, + grpc_resolved_address* resolved_addr) { + memset(resolved_addr, 0, sizeof(*resolved_addr)); + struct sockaddr_vm *vm = + reinterpret_cast<struct sockaddr_vm *>(resolved_addr->addr); + + if (sscanf(uri->path, "%u:%u", &vm->svm_cid, &vm->svm_port) != 2) { + return false; + } + vm->svm_family = AF_VSOCK; + + resolved_addr->len = static_cast<socklen_t>(sizeof(*vm)); + return true; +} + +#else /* defined(GRPC_HAVE_UNIX_SOCKET) && defined(GRPC_HAVE_LINUX_VSOCK) */ + +bool grpc_parse_vsock(const grpc_uri* uri, + grpc_resolved_address* resolved_addr) { + abort(); +} + +#endif /* defined(GRPC_HAVE_UNIX_SOCKET) && defined(GRPC_HAVE_LINUX_VSOCK) */ + bool grpc_parse_ipv4_hostport(const char* hostport, grpc_resolved_address* addr, bool log_errors) { bool success = false; @@ -200,6 +230,8 @@ bool grpc_parse_uri(const grpc_uri* uri, grpc_resolved_address* resolved_addr) { return grpc_parse_ipv4(uri, resolved_addr); } else if (strcmp("ipv6", uri->scheme) == 0) { return grpc_parse_ipv6(uri, resolved_addr); + } else if (strcmp("vsock", uri->scheme) == 0) { + return grpc_parse_vsock(uri, resolved_addr); } gpr_log(GPR_ERROR, "Can't parse scheme '%s'", uri->scheme); return false; diff --git a/src/core/ext/filters/client_channel/parse_address.h b/src/core/ext/filters/client_channel/parse_address.h index c2af0e6c49..2e7356f0ce 100644 --- a/src/core/ext/filters/client_channel/parse_address.h +++ b/src/core/ext/filters/client_channel/parse_address.h @@ -30,6 +30,11 @@ * unix socket path. Returns true upon success. */ bool grpc_parse_unix(const grpc_uri* uri, grpc_resolved_address* resolved_addr); +/** Populate \a resolved_addr from \a uri, whose path is expected to contain a + * vsock specification. Returns true upon success. */ +bool grpc_parse_vsock(const grpc_uri* uri, + grpc_resolved_address* resolved_addr); + /** Populate \a resolved_addr from \a uri, whose path is expected to contain an * IPv4 host:port pair. Returns true upon success. */ bool grpc_parse_ipv4(const grpc_uri* uri, grpc_resolved_address* resolved_addr); diff --git a/src/core/lib/iomgr/port.h b/src/core/lib/iomgr/port.h index 3d459059d7..fde2627e37 100644 --- a/src/core/lib/iomgr/port.h +++ b/src/core/lib/iomgr/port.h @@ -49,6 +49,11 @@ #define GRPC_HAVE_IP_PKTINFO 1 #define GRPC_HAVE_MSG_NOSIGNAL 1 #define GRPC_HAVE_UNIX_SOCKET 1 +#ifdef LINUX_VERSION_CODE +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) +#define GRPC_HAVE_LINUX_VSOCK +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) */ +#endif /* LINUX_VERSION_CODE */ #define GRPC_LINUX_EVENTFD 1 #define GRPC_POSIX_SOCKET 1 #define GRPC_POSIX_SOCKETUTILS 1 @@ -65,6 +70,11 @@ #define GRPC_LINUX_ERRQUEUE 1 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) */ #endif /* LINUX_VERSION_CODE */ +#ifdef LINUX_VERSION_CODE +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) +#define GRPC_HAVE_LINUX_VSOCK +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) */ +#endif /* LINUX_VERSION_CODE */ #define GRPC_LINUX_MULTIPOLL_WITH_EPOLL 1 #define GRPC_POSIX_FORK 1 #define GRPC_POSIX_HOST_NAME_MAX 1 diff --git a/src/core/lib/iomgr/resolve_address_posix.cc b/src/core/lib/iomgr/resolve_address_posix.cc index c285d7eca6..cad143d823 100644 --- a/src/core/lib/iomgr/resolve_address_posix.cc +++ b/src/core/lib/iomgr/resolve_address_posix.cc @@ -59,6 +59,11 @@ static grpc_error* posix_blocking_resolve_address( return grpc_resolve_unix_domain_address(name + 5, addresses); } + if (name[0] == 'v' && name[1] == 's' && name[2] == 'o' && name[3] == 'c' && + name[4] == 'k' && name[5] == ':' && name[6] != 0) { + return grpc_resolve_vsock_address(name + 6, addresses); + } + /* parse name, splitting it into host and port parts */ gpr_split_host_port(name, &host, &port); if (host == nullptr) { diff --git a/src/core/lib/iomgr/sockaddr_posix.h b/src/core/lib/iomgr/sockaddr_posix.h index 3cedd9082d..e32fc9a219 100644 --- a/src/core/lib/iomgr/sockaddr_posix.h +++ b/src/core/lib/iomgr/sockaddr_posix.h @@ -48,8 +48,13 @@ typedef struct in6_addr grpc_in6_addr; #define GRPC_AF_INET AF_INET #define GRPC_AF_INET6 AF_INET6 +#ifdef GRPC_HAVE_LINUX_VSOCK +#include <linux/vm_sockets.h> // Needs to come after sys/socket.h +#define GRPC_AF_VSOCK AF_VSOCK +#endif /* GRPC_HAVE_LINUX_VSOCK */ + #define GRPC_AI_PASSIVE AI_PASSIVE -#endif +#endif /* GRPC_POSIX_SOCKET_SOCKADDR */ #endif /* GRPC_CORE_LIB_IOMGR_SOCKADDR_POSIX_H */ diff --git a/src/core/lib/iomgr/sockaddr_utils.cc b/src/core/lib/iomgr/sockaddr_utils.cc index 1b66dceb13..833b5660fd 100644 --- a/src/core/lib/iomgr/sockaddr_utils.cc +++ b/src/core/lib/iomgr/sockaddr_utils.cc @@ -224,6 +224,8 @@ char* grpc_sockaddr_to_uri(const grpc_resolved_address* resolved_addr) { const char* scheme = grpc_sockaddr_get_uri_scheme(resolved_addr); if (scheme == nullptr || strcmp("unix", scheme) == 0) { return grpc_sockaddr_to_uri_unix_if_possible(resolved_addr); + } else if (strcmp("vsock", scheme) == 0) { + return grpc_sockaddr_to_uri_vsock_if_possible(resolved_addr); } char* path = nullptr; char* uri_str = nullptr; @@ -247,6 +249,10 @@ const char* grpc_sockaddr_get_uri_scheme( return "ipv6"; case GRPC_AF_UNIX: return "unix"; +#ifdef GRPC_AF_VSOCK + case GRPC_AF_VSOCK: + return "vsock"; +#endif /* GRPC_AF_VSOCK */ } return nullptr; } @@ -265,6 +271,15 @@ int grpc_sockaddr_get_port(const grpc_resolved_address* resolved_addr) { return grpc_ntohs(((grpc_sockaddr_in*)addr)->sin_port); case GRPC_AF_INET6: return grpc_ntohs(((grpc_sockaddr_in6*)addr)->sin6_port); +#ifdef GRPC_AF_VSOCK + case GRPC_AF_VSOCK: +#ifdef GRPC_HAVE_LINUX_VSOCK + return static_cast<int>(reinterpret_cast<const struct sockaddr_vm *>(addr)->svm_port); +#else /* GRPC_HAVE_LINUX_VSOCK */ + gpr_log(GPR_ERROR, "Unknown vsock implementation"); + return 0; +#endif /* GRPC_HAVE_LINUX_VSOCK */ +#endif /* GRPC_AF_VSOCK */ default: if (grpc_is_unix_socket(resolved_addr)) { return 1; @@ -277,8 +292,8 @@ int grpc_sockaddr_get_port(const grpc_resolved_address* resolved_addr) { int grpc_sockaddr_set_port(const grpc_resolved_address* resolved_addr, int port) { - const grpc_sockaddr* addr = - reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr); + grpc_sockaddr* addr = + const_cast<grpc_sockaddr*>(reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr)); switch (addr->sa_family) { case GRPC_AF_INET: GPR_ASSERT(port >= 0 && port < 65536); @@ -290,6 +305,16 @@ int grpc_sockaddr_set_port(const grpc_resolved_address* resolved_addr, ((grpc_sockaddr_in6*)addr)->sin6_port = grpc_htons(static_cast<uint16_t>(port)); return 1; +#ifdef GRPC_AF_VSOCK + case GRPC_AF_VSOCK: +#ifdef GRPC_HAVE_LINUX_VSOCK + reinterpret_cast<struct sockaddr_vm *>(addr)->svm_port = static_cast<unsigned int>(port); + return 1; +#else /* GRPC_HAVE_LINUX_VSOCK */ + gpr_log(GPR_ERROR, "Unknown vsock implementation"); + return 0; +#endif /* GRPC_HAVE_LINUX_VSOCK */ +#endif /* GRPC_AF_VSOCK */ default: gpr_log(GPR_ERROR, "Unknown socket family %d in grpc_sockaddr_set_port", addr->sa_family); diff --git a/src/core/lib/iomgr/tcp_client_posix.cc b/src/core/lib/iomgr/tcp_client_posix.cc index 8553ed0db4..207f748f3b 100644 --- a/src/core/lib/iomgr/tcp_client_posix.cc +++ b/src/core/lib/iomgr/tcp_client_posix.cc @@ -73,7 +73,7 @@ static grpc_error* prepare_socket(const grpc_resolved_address* addr, int fd, if (err != GRPC_ERROR_NONE) goto error; err = grpc_set_socket_cloexec(fd, 1); if (err != GRPC_ERROR_NONE) goto error; - if (!grpc_is_unix_socket(addr)) { + if (!grpc_is_unix_socket(addr) && !grpc_is_vsock(addr)) { err = grpc_set_socket_low_latency(fd, 1); if (err != GRPC_ERROR_NONE) goto error; err = grpc_set_socket_tcp_user_timeout(fd, channel_args, diff --git a/src/core/lib/iomgr/tcp_server_posix.cc b/src/core/lib/iomgr/tcp_server_posix.cc index 824db07fbf..34a54b1fab 100644 --- a/src/core/lib/iomgr/tcp_server_posix.cc +++ b/src/core/lib/iomgr/tcp_server_posix.cc @@ -487,7 +487,7 @@ static void tcp_server_start(grpc_tcp_server* s, grpc_pollset** pollsets, sp = s->head; while (sp != nullptr) { if (s->so_reuseport && !grpc_is_unix_socket(&sp->addr) && - pollset_count > 1) { + !grpc_is_vsock(&sp->addr) && pollset_count > 1) { GPR_ASSERT(GRPC_LOG_IF_ERROR( "clone_port", clone_port(sp, (unsigned)(pollset_count - 1)))); for (i = 0; i < pollset_count; i++) { diff --git a/src/core/lib/iomgr/tcp_server_utils_posix_common.cc b/src/core/lib/iomgr/tcp_server_utils_posix_common.cc index 8d8d3f4273..4398baead2 100644 --- a/src/core/lib/iomgr/tcp_server_utils_posix_common.cc +++ b/src/core/lib/iomgr/tcp_server_utils_posix_common.cc @@ -152,7 +152,8 @@ grpc_error* grpc_tcp_server_prepare_socket(grpc_tcp_server* s, int fd, GPR_ASSERT(fd >= 0); - if (so_reuseport && !grpc_is_unix_socket(addr)) { + if (so_reuseport && !grpc_is_unix_socket(addr) && + !grpc_is_vsock(addr)) { err = grpc_set_socket_reuse_port(fd, 1); if (err != GRPC_ERROR_NONE) goto error; } @@ -161,7 +162,7 @@ grpc_error* grpc_tcp_server_prepare_socket(grpc_tcp_server* s, int fd, if (err != GRPC_ERROR_NONE) goto error; err = grpc_set_socket_cloexec(fd, 1); if (err != GRPC_ERROR_NONE) goto error; - if (!grpc_is_unix_socket(addr)) { + if (!grpc_is_unix_socket(addr) && !grpc_is_vsock(addr)) { err = grpc_set_socket_low_latency(fd, 1); if (err != GRPC_ERROR_NONE) goto error; err = grpc_set_socket_reuse_addr(fd, 1); diff --git a/src/core/lib/iomgr/udp_server.cc b/src/core/lib/iomgr/udp_server.cc index 3dd7cab855..49a5b6cf22 100644 --- a/src/core/lib/iomgr/udp_server.cc +++ b/src/core/lib/iomgr/udp_server.cc @@ -404,7 +404,7 @@ static int prepare_socket(grpc_socket_factory* socket_factory, int fd, } } - if (so_reuseport && !grpc_is_unix_socket(addr) && + if (so_reuseport && !grpc_is_unix_socket(addr) && !grpc_is_vsock(addr) && grpc_set_socket_reuse_port(fd, 1) != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "Failed to set SO_REUSEPORT for fd %d", fd); goto error; diff --git a/src/core/lib/iomgr/unix_sockets_posix.cc b/src/core/lib/iomgr/unix_sockets_posix.cc index 22fcaf57fc..0cbe3e9f4e 100644 --- a/src/core/lib/iomgr/unix_sockets_posix.cc +++ b/src/core/lib/iomgr/unix_sockets_posix.cc @@ -23,6 +23,7 @@ #include "src/core/lib/iomgr/sockaddr.h" +#include <stdio.h> #include <string.h> #include <sys/stat.h> #include <sys/types.h> @@ -66,12 +67,49 @@ grpc_error* grpc_resolve_unix_domain_address(const char* name, return GRPC_ERROR_NONE; } +grpc_error* grpc_resolve_vsock_address(const char* name, + grpc_resolved_addresses** addrs) { +#ifdef GRPC_HAVE_LINUX_VSOCK + struct sockaddr_vm *vm; + unsigned int cid; + unsigned int port; + + if (sscanf(name, "%u:%u", &cid, &port) != 2) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to parse cid:port pair"); + } + + *addrs = static_cast<grpc_resolved_addresses*>( + gpr_malloc(sizeof(grpc_resolved_addresses))); + (*addrs)->naddrs = 1; + (*addrs)->addrs = static_cast<grpc_resolved_address*>( + gpr_zalloc(sizeof(grpc_resolved_address))); + vm = (struct sockaddr_vm *)(*addrs)->addrs->addr; + vm->svm_family = AF_VSOCK; + vm->svm_cid = cid; + vm->svm_port = port; + (*addrs)->addrs->len = sizeof(struct sockaddr_vm); + return GRPC_ERROR_NONE; +#else /* GRPC_HAVE_LINUX_VSOCK */ + return GRPC_ERROR_CREATE_FROM_STATIC_STRING("vsock not supported"); +#endif /* GRPC_HAVE_LINUX_VSOCK */ +} + int grpc_is_unix_socket(const grpc_resolved_address* resolved_addr) { const grpc_sockaddr* addr = reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr); return addr->sa_family == AF_UNIX; } +int grpc_is_vsock(const grpc_resolved_address* resolved_addr) { +#ifdef GRPC_HAVE_LINUX_VSOCK + const grpc_sockaddr* addr = + reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr); + return addr->sa_family == AF_VSOCK; +#else /* GRPC_HAVE_LINUX_VSOCK */ + return 0; +#endif /* GRPC_HAVE_LINUX_VSOCK */ +} + void grpc_unlink_if_unix_domain_socket( const grpc_resolved_address* resolved_addr) { const grpc_sockaddr* addr = @@ -101,4 +139,23 @@ char* grpc_sockaddr_to_uri_unix_if_possible( return result; } +char* grpc_sockaddr_to_uri_vsock_if_possible( + const grpc_resolved_address* resolved_addr) { +#ifdef GRPC_HAVE_LINUX_VSOCK + const grpc_sockaddr* addr = + reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr); + + if (addr->sa_family != AF_VSOCK) { + return nullptr; + } + + char *result; + struct sockaddr_vm *vm = (struct sockaddr_vm*)addr; + gpr_asprintf(&result, "vsock:%u:%u", vm->svm_cid, vm->svm_port); + return result; +#else /* GRPC_HAVE_LINUX_VSOCK */ + return nullptr; +#endif /* GRPC_HAVE_LINUX_VSOCK */ +} + #endif diff --git a/src/core/lib/iomgr/unix_sockets_posix.h b/src/core/lib/iomgr/unix_sockets_posix.h index 917d0327a9..ed1f03a328 100644 --- a/src/core/lib/iomgr/unix_sockets_posix.h +++ b/src/core/lib/iomgr/unix_sockets_posix.h @@ -32,12 +32,20 @@ void grpc_create_socketpair_if_unix(int sv[2]); grpc_error* grpc_resolve_unix_domain_address( const char* name, grpc_resolved_addresses** addresses); +grpc_error* grpc_resolve_vsock_address( + const char* name, grpc_resolved_addresses** addrs); + int grpc_is_unix_socket(const grpc_resolved_address* resolved_addr); +int grpc_is_vsock(const grpc_resolved_address* resolved_addr); + void grpc_unlink_if_unix_domain_socket( const grpc_resolved_address* resolved_addr); char* grpc_sockaddr_to_uri_unix_if_possible( const grpc_resolved_address* resolved_addr); +char* grpc_sockaddr_to_uri_vsock_if_possible( + const grpc_resolved_address* resolved_addr); + #endif /* GRPC_CORE_LIB_IOMGR_UNIX_SOCKETS_POSIX_H */ |