From 43b616d904088b830bdb42ed9c016ce5f239bc73 Mon Sep 17 00:00:00 2001
From: Alexey Makhalov <amakhalov@vmware.com>
Date: Tue, 9 May 2017 12:37:20 -0700
Subject: [PATCH] net 9p vsock support

---
 net/9p/trans_fd.c | 45 +++++++++++++++++++++++++++++++++++++--------
 1 file changed, 37 insertions(+), 8 deletions(-)

diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
index 7bc2208b6cc4..4acfd8a7f52c 100644
--- a/net/9p/trans_fd.c
+++ b/net/9p/trans_fd.c
@@ -37,6 +37,8 @@
 #include <linux/un.h>
 #include <linux/uaccess.h>
 #include <linux/inet.h>
+#include <linux/vmw_vmci_defs.h>
+#include <uapi/linux/vm_sockets.h>
 #include <linux/idr.h>
 #include <linux/file.h>
 #include <linux/parser.h>
@@ -64,6 +66,7 @@ struct p9_fd_opts {
 	int wfd;
 	u16 port;
 	int privport;
+	int vsock;
 };
 
 /*
@@ -73,7 +76,7 @@ struct p9_fd_opts {
 
 enum {
 	/* Options that take integer arguments */
-	Opt_port, Opt_rfdno, Opt_wfdno, Opt_err,
+	Opt_port, Opt_rfdno, Opt_wfdno, Opt_err, Opt_vsock,
 	/* Options that take no arguments */
 	Opt_privport,
 };
@@ -83,6 +86,7 @@ static const match_table_t tokens = {
 	{Opt_rfdno, "rfdno=%u"},
 	{Opt_wfdno, "wfdno=%u"},
 	{Opt_privport, "privport"},
+	{Opt_vsock, "vsock=%d"},
 	{Opt_err, NULL},
 };
 
@@ -739,6 +743,7 @@ static int parse_opts(char *params, struct p9_fd_opts *opts)
 	opts->rfd = ~0;
 	opts->wfd = ~0;
 	opts->privport = 0;
+	opts->vsock = 0;
 
 	if (!params)
 		return 0;
@@ -778,6 +783,9 @@ static int parse_opts(char *params, struct p9_fd_opts *opts)
 		case Opt_privport:
 			opts->privport = 1;
 			break;
+		case Opt_vsock:
+			opts->vsock = option;
+			break;
 		default:
 			continue;
 		}
@@ -942,11 +950,27 @@ p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args)
 
 	csocket = NULL;
 
-	sin_server.sin_family = AF_INET;
-	sin_server.sin_addr.s_addr = in_aton(addr);
-	sin_server.sin_port = htons(opts.port);
-	err = __sock_create(current->nsproxy->net_ns, PF_INET,
-			    SOCK_STREAM, IPPROTO_TCP, &csocket, 1);
+	if (opts.vsock == 0) {
+		sin_server.sin_family = AF_INET;
+		sin_server.sin_addr.s_addr = in_aton(addr);
+		sin_server.sin_port = htons(opts.port);
+		err = __sock_create(current->nsproxy->net_ns, PF_INET,
+		                    SOCK_STREAM, IPPROTO_TCP, &csocket, 1);
+	} else {
+		/*
+		 * for vsock, addr is not used, but opts.vsock is the vsock address,
+		 * where 2 means host (hypervisor), and other numbers mean the vmci id
+		 * in the VMX file of this running VM
+		 */
+		struct sockaddr_vm *vsock_server = (struct sockaddr_vm*)&sin_server;
+
+		memset(vsock_server, 0, sizeof(struct sockaddr_vm));
+		vsock_server->svm_family = AF_VSOCK;
+		vsock_server->svm_port = opts.port;
+		vsock_server->svm_cid = opts.vsock;
+		err = __sock_create(current->nsproxy->net_ns, PF_VSOCK,
+		                    SOCK_STREAM, 0, &csocket, 1);
+	}
 	if (err) {
 		pr_err("%s (%d): problem creating socket\n",
 		       __func__, task_pid_nr(current));
@@ -967,8 +991,13 @@ p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args)
 				    (struct sockaddr *)&sin_server,
 				    sizeof(struct sockaddr_in), 0);
 	if (err < 0) {
-		pr_err("%s (%d): problem connecting socket to %s\n",
-		       __func__, task_pid_nr(current), addr);
+		if (opts.vsock) {
+			pr_err("%s (%d): problem connecting vmware vsock addr %d\n",
+			       __func__, task_pid_nr(current), opts.vsock);
+		} else {
+			pr_err("%s (%d): problem connecting socket to %s\n",
+			       __func__, task_pid_nr(current), addr);
+		}
 		sock_release(csocket);
 		return err;
 	}
-- 
2.11.0