blob: f7b779b288e05b6026c419cf8f79bc95f45484b4 [file] [log] [blame]
From 716cb35ab711efbd99a65c599b50f044e4912bd0 Mon Sep 17 00:00:00 2001
From: Chirantan Ekbote <chirantan@google.com>
Date: Mon, 10 Jul 2017 13:22:59 -0700
Subject: [PATCH 4/5] grpc-1.3.0: Support vsock
Add support for vsock as a transport for client <-> server communication. Has
not been sent upstream because upstream has not indicated whether they are
interested in adding support for this transport. Also the patch in its current
form is probably not upstream-able because it assumes that vsock is always
available, which is definitely not the case for all the platforms that upstream
supports.
Rebased by: Allen Webb <allenwebb@google.com>
Rebased on: 2018-12-28
diff --git a/src/core/ext/filters/client_channel/parse_address.cc b/src/core/ext/filters/client_channel/parse_address.cc
index 707beb8..9e83452 100644
--- a/src/core/ext/filters/client_channel/parse_address.cc
+++ b/src/core/ext/filters/client_channel/parse_address.cc
@@ -26,6 +26,8 @@
#include <string.h>
#ifdef GRPC_HAVE_UNIX_SOCKET
#include <sys/un.h>
+#include <sys/socket.h>
+#include <linux/vm_sockets.h>
#endif
#include <grpc/support/alloc.h>
@@ -54,6 +56,21 @@ bool grpc_parse_unix(const grpc_uri* uri,
return true;
}
+bool grpc_parse_vsock(const grpc_uri* uri,
+ grpc_resolved_address* resolved_addr) {
+ memset(resolved_addr, 0, sizeof(grpc_resolved_address));
+ 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 /* GRPC_HAVE_UNIX_SOCKET */
bool grpc_parse_unix(const grpc_uri* uri,
@@ -200,6 +217,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 c2af0e6..7daab6a 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 addr and \a len 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/resolve_address_posix.cc b/src/core/lib/iomgr/resolve_address_posix.cc
index c285d7e..cad143d 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 3cedd90..f12f52e 100644
--- a/src/core/lib/iomgr/sockaddr_posix.h
+++ b/src/core/lib/iomgr/sockaddr_posix.h
@@ -50,6 +50,8 @@ typedef struct in6_addr grpc_in6_addr;
#define GRPC_AI_PASSIVE AI_PASSIVE
-#endif
+#endif /* GRPC_POSIX_SOCKET_SOCKADDR */
+
+#include <linux/vm_sockets.h> // Needs to come after sys/socket.h
#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 1b66dce..5b96a3e 100644
--- a/src/core/lib/iomgr/sockaddr_utils.cc
+++ b/src/core/lib/iomgr/sockaddr_utils.cc
@@ -222,7 +222,8 @@ char* grpc_sockaddr_to_uri(const grpc_resolved_address* resolved_addr) {
resolved_addr = &addr_normalized;
}
const char* scheme = grpc_sockaddr_get_uri_scheme(resolved_addr);
- if (scheme == nullptr || strcmp("unix", scheme) == 0) {
+ if (scheme == nullptr || strcmp("unix", scheme) == 0 ||
+ strcmp("vsock", scheme) == 0) {
return grpc_sockaddr_to_uri_unix_if_possible(resolved_addr);
}
char* path = nullptr;
@@ -247,6 +248,8 @@ const char* grpc_sockaddr_get_uri_scheme(
return "ipv6";
case GRPC_AF_UNIX:
return "unix";
+ case AF_VSOCK:
+ return "vsock";
}
return nullptr;
}
@@ -265,6 +268,8 @@ 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);
+ case AF_VSOCK:
+ return (int)((struct sockaddr_vm *)addr)->svm_port;
default:
if (grpc_is_unix_socket(resolved_addr)) {
return 1;
@@ -290,6 +295,9 @@ 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;
+ case AF_VSOCK:
+ ((struct sockaddr_vm *)addr)->svm_port = (unsigned int)port;
+ return 1;
default:
gpr_log(GPR_ERROR, "Unknown socket family %d in grpc_sockaddr_set_port",
addr->sa_family);
diff --git a/src/core/lib/iomgr/unix_sockets_posix.cc b/src/core/lib/iomgr/unix_sockets_posix.cc
index 22fcaf5..e62b9ef 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,10 +67,33 @@ 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) {
+ 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;
+}
+
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;
+ return addr->sa_family == AF_UNIX || addr->sa_family == AF_VSOCK;
}
void grpc_unlink_if_unix_domain_socket(
@@ -92,6 +116,13 @@ char* grpc_sockaddr_to_uri_unix_if_possible(
const grpc_resolved_address* resolved_addr) {
const grpc_sockaddr* addr =
reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr);
+ if (addr->sa_family == AF_VSOCK) {
+ char *result;
+ struct sockaddr_vm *vm = (struct sockaddr_vm*)addr;
+ gpr_asprintf(&result, "vsock:%u:%u", vm->svm_cid, vm->svm_port);
+ return result;
+ }
+
if (addr->sa_family != AF_UNIX) {
return nullptr;
}
diff --git a/src/core/lib/iomgr/unix_sockets_posix.h b/src/core/lib/iomgr/unix_sockets_posix.h
index 917d032..77b85ea 100644
--- a/src/core/lib/iomgr/unix_sockets_posix.h
+++ b/src/core/lib/iomgr/unix_sockets_posix.h
@@ -32,6 +32,9 @@ 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);
void grpc_unlink_if_unix_domain_socket(