summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2020-12-14 19:33:51 -0800
committerJakub Kicinski <kuba@kernel.org>2020-12-14 19:33:51 -0800
commit28f53159e1219265b4f41728782087b9f922a9c0 (patch)
tree6d3e957b647ce7f82ddb4674477176f41887c66b
parentae0b04b238e283cafd906cdc3489cf5dc9a825cf (diff)
parent7f816984f439dfe24da25032254cb10512900346 (diff)
Merge branch 'vsock-add-flags-field-in-the-vsock-address'
Andra Paraschiv says: ==================== vsock: Add flags field in the vsock address vsock enables communication between virtual machines and the host they are running on. Nested VMs can be setup to use vsock channels, as the multi transport support has been available in the mainline since the v5.5 Linux kernel has been released. Implicitly, if no host->guest vsock transport is loaded, all the vsock packets are forwarded to the host. This behavior can be used to setup communication channels between sibling VMs that are running on the same host. One example can be the vsock channels that can be established within AWS Nitro Enclaves (see Documentation/virt/ne_overview.rst). To be able to explicitly mark a connection as being used for a certain use case, add a flags field in the vsock address data structure. The value of the flags field is taken into consideration when the vsock transport is assigned. This way can distinguish between different use cases, such as nested VMs / local communication and sibling VMs. The flags field can be set in the user space application connect logic. On the listen path, the field can be set in the kernel space logic. ==================== Link: https://lore.kernel.org/r/20201214161122.37717-1-andraprs@amazon.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r--include/uapi/linux/vm_sockets.h26
-rw-r--r--net/vmw_vsock/af_vsock.c21
-rw-r--r--net/vmw_vsock/vsock_addr.c4
3 files changed, 47 insertions, 4 deletions
diff --git a/include/uapi/linux/vm_sockets.h b/include/uapi/linux/vm_sockets.h
index fd0ed7221645..46918a1852d7 100644
--- a/include/uapi/linux/vm_sockets.h
+++ b/include/uapi/linux/vm_sockets.h
@@ -18,6 +18,7 @@
#define _UAPI_VM_SOCKETS_H
#include <linux/socket.h>
+#include <linux/types.h>
/* Option name for STREAM socket buffer size. Use as the option name in
* setsockopt(3) or getsockopt(3) to set or get an unsigned long long that
@@ -114,6 +115,26 @@
#define VMADDR_CID_HOST 2
+/* The current default use case for the vsock channel is the following:
+ * local vsock communication between guest and host and nested VMs setup.
+ * In addition to this, implicitly, the vsock packets are forwarded to the host
+ * if no host->guest vsock transport is set.
+ *
+ * Set this flag value in the sockaddr_vm corresponding field if the vsock
+ * packets need to be always forwarded to the host. Using this behavior,
+ * vsock communication between sibling VMs can be setup.
+ *
+ * This way can explicitly distinguish between vsock channels created for
+ * different use cases, such as nested VMs (or local communication between
+ * guest and host) and sibling VMs.
+ *
+ * The flag can be set in the connect logic in the user space application flow.
+ * In the listen logic (from kernel space) the flag is set on the remote peer
+ * address. This happens for an incoming connection when it is routed from the
+ * host and comes from the guest (local CID and remote CID > VMADDR_CID_HOST).
+ */
+#define VMADDR_FLAG_TO_HOST 0x01
+
/* Invalid vSockets version. */
#define VM_SOCKETS_INVALID_VERSION -1U
@@ -148,10 +169,13 @@ struct sockaddr_vm {
unsigned short svm_reserved1;
unsigned int svm_port;
unsigned int svm_cid;
+ __u8 svm_flags;
unsigned char svm_zero[sizeof(struct sockaddr) -
sizeof(sa_family_t) -
sizeof(unsigned short) -
- sizeof(unsigned int) - sizeof(unsigned int)];
+ sizeof(unsigned int) -
+ sizeof(unsigned int) -
+ sizeof(__u8)];
};
#define IOCTL_VM_SOCKETS_GET_LOCAL_CID _IO(7, 0xb9)
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index d2834047c6db..b12d3a322242 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -421,7 +421,8 @@ static void vsock_deassign_transport(struct vsock_sock *vsk)
* The vsk->remote_addr is used to decide which transport to use:
* - remote CID == VMADDR_CID_LOCAL or g2h->local_cid or VMADDR_CID_HOST if
* g2h is not loaded, will use local transport;
- * - remote CID <= VMADDR_CID_HOST will use guest->host transport;
+ * - remote CID <= VMADDR_CID_HOST or h2g is not loaded or remote flags field
+ * includes VMADDR_FLAG_TO_HOST flag value, will use guest->host transport;
* - remote CID > VMADDR_CID_HOST will use host->guest transport;
*/
int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk)
@@ -429,8 +430,23 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk)
const struct vsock_transport *new_transport;
struct sock *sk = sk_vsock(vsk);
unsigned int remote_cid = vsk->remote_addr.svm_cid;
+ __u8 remote_flags;
int ret;
+ /* If the packet is coming with the source and destination CIDs higher
+ * than VMADDR_CID_HOST, then a vsock channel where all the packets are
+ * forwarded to the host should be established. Then the host will
+ * need to forward the packets to the guest.
+ *
+ * The flag is set on the (listen) receive path (psk is not NULL). On
+ * the connect path the flag can be set by the user space application.
+ */
+ if (psk && vsk->local_addr.svm_cid > VMADDR_CID_HOST &&
+ vsk->remote_addr.svm_cid > VMADDR_CID_HOST)
+ vsk->remote_addr.svm_flags |= VMADDR_FLAG_TO_HOST;
+
+ remote_flags = vsk->remote_addr.svm_flags;
+
switch (sk->sk_type) {
case SOCK_DGRAM:
new_transport = transport_dgram;
@@ -438,7 +454,8 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk)
case SOCK_STREAM:
if (vsock_use_local_transport(remote_cid))
new_transport = transport_local;
- else if (remote_cid <= VMADDR_CID_HOST || !transport_h2g)
+ else if (remote_cid <= VMADDR_CID_HOST || !transport_h2g ||
+ (remote_flags & VMADDR_FLAG_TO_HOST))
new_transport = transport_g2h;
else
new_transport = transport_h2g;
diff --git a/net/vmw_vsock/vsock_addr.c b/net/vmw_vsock/vsock_addr.c
index 909de26cb0e7..223b9660a759 100644
--- a/net/vmw_vsock/vsock_addr.c
+++ b/net/vmw_vsock/vsock_addr.c
@@ -22,13 +22,15 @@ EXPORT_SYMBOL_GPL(vsock_addr_init);
int vsock_addr_validate(const struct sockaddr_vm *addr)
{
+ __u8 svm_valid_flags = VMADDR_FLAG_TO_HOST;
+
if (!addr)
return -EFAULT;
if (addr->svm_family != AF_VSOCK)
return -EAFNOSUPPORT;
- if (addr->svm_zero[0] != 0)
+ if (addr->svm_flags & ~svm_valid_flags)
return -EINVAL;
return 0;