lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20121016003305.27018.37887.stgit@promb-2n-dhcp175.eng.vmware.com>
Date:	Mon, 15 Oct 2012 17:33:13 -0700
From:	George Zhang <georgezhang@...are.com>
To:	netdev@...r.kernel.org, linux-kernel@...r.kernel.org,
	georgezhang@...are.com, virtualization@...ts.linux-foundation.org
Cc:	pv-drivers@...are.com, vm-crosstalk@...are.com,
	davem@...emloft.net, gregkh@...uxfoundation.org
Subject: [PATCH 6/6] VSOCK: header and config files.

VSOCK header files, Makefiles and Kconfig systems for Linux VSocket module.


Signed-off-by: George Zhang <georgezhang@...are.com>
---
 net/Kconfig                         |    1 
 net/Makefile                        |    1 
 net/vmw_vsock/Kconfig               |   14 +
 net/vmw_vsock/Makefile              |    8 
 net/vmw_vsock/notify_qstate.c       |  670 +++++++++++++++++++++++++++++++++++
 net/vmw_vsock/vmci_sockets.h        |  517 +++++++++++++++++++++++++++
 net/vmw_vsock/vmci_sockets_packet.h |  107 ++++++
 net/vmw_vsock/vsock_common.h        |  130 +++++++
 net/vmw_vsock/vsock_packet.h        |  131 +++++++
 net/vmw_vsock/vsock_version.h       |   29 ++
 10 files changed, 1608 insertions(+), 0 deletions(-)
 create mode 100644 net/vmw_vsock/Kconfig
 create mode 100644 net/vmw_vsock/Makefile
 create mode 100644 net/vmw_vsock/notify_qstate.c
 create mode 100644 net/vmw_vsock/vmci_sockets.h
 create mode 100644 net/vmw_vsock/vmci_sockets_packet.h
 create mode 100644 net/vmw_vsock/vsock_common.h
 create mode 100644 net/vmw_vsock/vsock_packet.h
 create mode 100644 net/vmw_vsock/vsock_version.h

diff --git a/net/Kconfig b/net/Kconfig
index 245831b..75b8d5e 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -216,6 +216,7 @@ source "net/dcb/Kconfig"
 source "net/dns_resolver/Kconfig"
 source "net/batman-adv/Kconfig"
 source "net/openvswitch/Kconfig"
+source "net/vmw_vsock/Kconfig"
 
 config RPS
 	boolean
diff --git a/net/Makefile b/net/Makefile
index 4f4ee08..cae59f4 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -70,3 +70,4 @@ obj-$(CONFIG_CEPH_LIB)		+= ceph/
 obj-$(CONFIG_BATMAN_ADV)	+= batman-adv/
 obj-$(CONFIG_NFC)		+= nfc/
 obj-$(CONFIG_OPENVSWITCH)	+= openvswitch/
+obj-$(CONFIG_VMWARE_VSOCK)	+= vmw_vsock/
diff --git a/net/vmw_vsock/Kconfig b/net/vmw_vsock/Kconfig
new file mode 100644
index 0000000..95e2568
--- /dev/null
+++ b/net/vmw_vsock/Kconfig
@@ -0,0 +1,14 @@
+#
+# Vsock protocol
+#
+
+config VMWARE_VSOCK
+	tristate "Virtual Socket protocol"
+	depends on VMWARE_VMCI
+	help
+	  Virtual Socket Protocol is a socket protocol similar to TCP/IP
+	  allowing comunication between Virtual Machines and VMware
+	  hypervisor.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called vsock. If unsure, say N.
diff --git a/net/vmw_vsock/Makefile b/net/vmw_vsock/Makefile
new file mode 100644
index 0000000..8cb1e1c
--- /dev/null
+++ b/net/vmw_vsock/Makefile
@@ -0,0 +1,8 @@
+obj-$(CONFIG_VMWARE_VSOCK) += vmw_vsock.o
+ccflags-y += -I$(src)/shared
+vmw_vsock-y += af_vsock.o
+vmw_vsock-y += notify.o
+vmw_vsock-y += notify_qstate.o
+vmw_vsock-y += stats.o
+vmw_vsock-y += util.o
+vmw_vsock-y += vsock_addr.o
diff --git a/net/vmw_vsock/notify_qstate.c b/net/vmw_vsock/notify_qstate.c
new file mode 100644
index 0000000..fafb76c
--- /dev/null
+++ b/net/vmw_vsock/notify_qstate.c
@@ -0,0 +1,670 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2009-2012 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+/*
+ * notifyQState.c --
+ *
+ * Linux control notifications based on Queuepair state for the VMCI Stream
+ * Sockets protocol.
+ */
+
+#include <linux/types.h>
+
+#include <linux/socket.h>
+
+#include <linux/stddef.h>	/* for NULL */
+#include <net/sock.h>
+
+#include "notify.h"
+#include "af_vsock.h"
+
+#define PKT_FIELD(vsk, field_name)		\
+	(vsk)->notify.pkt_q_state.field_name
+
+/*
+ *
+ * vsock_vmci_notify_waiting_write --
+ *
+ * Determines if the conditions have been met to notify a waiting writer.
+ *
+ * Results: true if a notification should be sent, false otherwise.
+ *
+ * Side effects: None.
+ */
+
+static bool vsock_vmci_notify_waiting_write(vsock_vmci_sock *vsk)
+{
+	bool retval;
+	u64 notify_limit;
+
+	if (!PKT_FIELD(vsk, peer_waiting_write))
+		return false;
+
+	/*
+	 * When the sender blocks, we take that as a sign that the sender is
+	 * faster than the receiver. To reduce the transmit rate of the sender,
+	 * we delay the sending of the read notification by decreasing the
+	 * write_notify_window. The notification is delayed until the number of
+	 * bytes used in the queue drops below the write_notify_window.
+	 */
+
+	if (!PKT_FIELD(vsk, peer_waiting_write_detected)) {
+		PKT_FIELD(vsk, peer_waiting_write_detected) = true;
+		if (PKT_FIELD(vsk, write_notify_window) < PAGE_SIZE) {
+			PKT_FIELD(vsk, write_notify_window) =
+			    PKT_FIELD(vsk, write_notify_min_window);
+		} else {
+			PKT_FIELD(vsk, write_notify_window) -= PAGE_SIZE;
+			if (PKT_FIELD(vsk, write_notify_window) <
+			    PKT_FIELD(vsk, write_notify_min_window))
+				PKT_FIELD(vsk, write_notify_window) =
+				    PKT_FIELD(vsk, write_notify_min_window);
+
+		}
+	}
+	notify_limit = vsk->consume_size - PKT_FIELD(vsk, write_notify_window);
+
+	/*
+	 * The notify_limit is used to delay notifications in the case where
+	 * flow control is enabled. Below the test is expressed in terms of
+	 * free space in the queue: if free_space > ConsumeSize -
+	 * write_notify_window then notify An alternate way of expressing this
+	 * is to rewrite the expression to use the data ready in the receive
+	 * queue: if write_notify_window > bufferReady then notify as
+	 * free_space == ConsumeSize - bufferReady.
+	 */
+
+	retval = vmci_qpair_consume_free_space(vsk->qpair) > notify_limit;
+
+	if (retval) {
+		/*
+		 * Once we notify the peer, we reset the detected flag so the
+		 * next wait will again cause a decrease in the window size.
+		 */
+
+		PKT_FIELD(vsk, peer_waiting_write_detected) = false;
+	}
+	return retval;
+}
+
+/*
+ *
+ * vsock_vmci_handle_read --
+ *
+ * Handles an incoming read message.
+ *
+ * Results: None.
+ *
+ * Side effects: None.
+ */
+
+static void
+vsock_vmci_handle_read(struct sock *sk,
+		       vsock_packet *pkt,
+		       bool bottom_half,
+		       struct sockaddr_vm *dst, struct sockaddr_vm *src)
+{
+
+	sk->sk_write_space(sk);
+}
+
+/*
+ *
+ * vsock_vmci_handle_wrote --
+ *
+ * Handles an incoming wrote message.
+ *
+ * Results: None.
+ *
+ * Side effects: None.
+ */
+
+static void
+vsock_vmci_handle_wrote(struct sock *sk,
+			vsock_packet *pkt,
+			bool bottom_half,
+			struct sockaddr_vm *dst, struct sockaddr_vm *src)
+{
+	sk->sk_data_ready(sk, 0);
+}
+
+/*
+ *
+ * vsock_vmci_block_update_write_window --
+ *
+ * Updates the write window when we are blocking for data.
+ *
+ * Results: None.
+ *
+ * Side effects: None.
+ */
+
+static void vsock_vmci_block_update_write_window(struct sock *sk)
+{
+	vsock_vmci_sock *vsk;
+
+	vsk = vsock_sk(sk);
+
+	if (PKT_FIELD(vsk, write_notify_window) < vsk->consume_size)
+		PKT_FIELD(vsk, write_notify_window) =
+		    min(PKT_FIELD(vsk, write_notify_window) + PAGE_SIZE,
+			vsk->consume_size);
+
+}
+
+/*
+ *
+ * vsock_vmci_send_read_notification --
+ *
+ * Sends a read notification to this socket's peer.
+ *
+ * Results: >= 0 if the datagram is sent successfully, negative error value
+ * otherwise.
+ *
+ * Side effects: None.
+ */
+
+static int vsock_vmci_send_read_notification(struct sock *sk)
+{
+	vsock_vmci_sock *vsk;
+	bool sent_read;
+	unsigned int retries;
+	int err;
+
+	ASSERT(sk);
+
+	vsk = vsock_sk(sk);
+	sent_read = false;
+	retries = 0;
+	err = 0;
+
+	if (vsock_vmci_notify_waiting_write(vsk)) {
+		/*
+		 * Notify the peer that we have read, retrying the send on
+		 * failure up to our maximum value.  XXX For now we just log
+		 * the failure, but later we should schedule a work item to
+		 * handle the resend until it succeeds.  That would require
+		 * keeping track of work items in the vsk and cleaning them up
+		 * upon socket close.
+		 */
+		while (!(vsk->peer_shutdown & RCV_SHUTDOWN) &&
+		       !sent_read && retries < VSOCK_MAX_DGRAM_RESENDS) {
+			err = VSOCK_SEND_READ(sk);
+			if (err >= 0)
+				sent_read = true;
+
+			retries++;
+		}
+
+		if (retries >= VSOCK_MAX_DGRAM_RESENDS && !sent_read)
+			printk
+			    ("%p unable to send read notification to peer.\n",
+			     sk);
+		else
+			PKT_FIELD(vsk, peer_waiting_write) = false;
+
+	}
+	return err;
+}
+
+/*
+ *
+ * vsock_vmci_notify_pkt_socket_init --
+ *
+ * Function that is called after a socket is created and before any notify ops
+ * are used.
+ *
+ * Results: None.
+ *
+ * Side effects: None.
+ */
+
+static void vsock_vmci_notify_pkt_socket_init(struct sock *sk)
+{
+	vsock_vmci_sock *vsk;
+	vsk = vsock_sk(sk);
+
+	PKT_FIELD(vsk, write_notify_window) = PAGE_SIZE;
+	PKT_FIELD(vsk, write_notify_min_window) = PAGE_SIZE;
+	PKT_FIELD(vsk, peer_waiting_write) = false;
+	PKT_FIELD(vsk, peer_waiting_write_detected) = false;
+}
+
+/*
+ *
+ * vsock_vmci_notify_pkt_socket_destruct --
+ *
+ * Function that is called when the socket is being released.
+ *
+ * Results: None.
+ *
+ * Side effects: None.
+ */
+
+static void vsock_vmci_notify_pkt_socket_destruct(struct sock *sk)
+{
+	vsock_vmci_sock *vsk;
+	vsk = vsock_sk(sk);
+
+	PKT_FIELD(vsk, write_notify_window) = PAGE_SIZE;
+	PKT_FIELD(vsk, write_notify_min_window) = PAGE_SIZE;
+	PKT_FIELD(vsk, peer_waiting_write) = false;
+	PKT_FIELD(vsk, peer_waiting_write_detected) = false;
+}
+
+/*
+ *
+ * vsock_vmci_notify_pkt_poll_in --
+ *
+ * Called by the poll function to figure out if there is data to read and to
+ * setup future notifications if needed. Only called on sockets that aren't
+ * shutdown for recv.
+ *
+ * Results: 0 on success. Negative error on failure.
+ *
+ * Side effects: None.
+ */
+
+static int
+vsock_vmci_notify_pkt_poll_in(struct sock *sk,
+			      size_t target, bool *data_ready_now)
+{
+	vsock_vmci_sock *vsk;
+
+	ASSERT(sk);
+	ASSERT(data_ready_now);
+
+	vsk = vsock_sk(sk);
+
+	if (vsock_vmci_stream_has_data(vsk)) {
+		*data_ready_now = true;
+	} else {
+		/*
+		 * We can't read right now because there is nothing in the
+		 * queue. Ask for notifications when there is something to
+		 * read.
+		 */
+		if (sk->sk_state == SS_CONNECTED)
+			vsock_vmci_block_update_write_window(sk);
+
+		*data_ready_now = false;
+	}
+
+	return 0;
+}
+
+/*
+ *
+ * vsock_vmci_notify_pkt_poll_out
+ *
+ * Called by the poll function to figure out if there is space to write and to
+ * setup future notifications if needed. Only called on a connected socket that
+ * isn't shutdown for send.
+ *
+ * Results: 0 on success. Negative error on failure.
+ *
+ * Side effects: None.
+ */
+
+static int
+vsock_vmci_notify_pkt_poll_out(struct sock *sk,
+			       size_t target, bool *space_avail_now)
+{
+	s64 produce_q_free_space;
+	vsock_vmci_sock *vsk;
+
+	ASSERT(sk);
+	ASSERT(space_avail_now);
+
+	vsk = vsock_sk(sk);
+
+	produce_q_free_space = vsock_vmci_stream_has_space(vsk);
+	if (produce_q_free_space > 0) {
+		*space_avail_now = true;
+		return 0;
+	} else if (produce_q_free_space == 0) {
+		/*
+		 * This is a connected socket but we can't currently send data.
+		 * Nothing else to do.
+		 */
+		*space_avail_now = false;
+	}
+
+	return 0;
+}
+
+/*
+ *
+ * vsock_vmci_notify_pkt_recv_init --
+ *
+ * Called at the start of a stream recv call with the socket lock held.
+ *
+ * Results: 0 on success. Negative error on failure.
+ *
+ * Side effects: None.
+ */
+
+static int
+vsock_vmci_notify_pkt_recv_init(struct sock *sk,
+				size_t target,
+				vsock_vmci_recv_notify_data *data)
+{
+	vsock_vmci_sock *vsk;
+
+	ASSERT(sk);
+	ASSERT(data);
+
+	vsk = vsock_sk(sk);
+
+	data->consume_head = 0;
+	data->produce_tail = 0;
+	data->notify_on_block = false;
+
+	if (PKT_FIELD(vsk, write_notify_min_window) < target + 1) {
+		ASSERT(target < vsk->consume_size);
+		PKT_FIELD(vsk, write_notify_min_window) = target + 1;
+		if (PKT_FIELD(vsk, write_notify_window) <
+		    PKT_FIELD(vsk, write_notify_min_window)) {
+			/*
+			 * If the current window is smaller than the new
+			 * minimal window size, we need to reevaluate whether
+			 * we need to notify the sender. If the number of ready
+			 * bytes are smaller than the new window, we need to
+			 * send a notification to the sender before we block.
+			 */
+
+			PKT_FIELD(vsk, write_notify_window) =
+			    PKT_FIELD(vsk, write_notify_min_window);
+			data->notify_on_block = true;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ *
+ * vsock_vmci_notify_pkt_recv_pre_block --
+ *
+ * Called right before a socket is about to block with the socket lock held.
+ * The socket lock may have been released between the entry function and the
+ * preblock call.
+ *
+ * Note: This function may be called multiple times before the post block
+ * function is called.
+ *
+ * Results: 0 on success. Negative error on failure.
+ *
+ * Side effects: None.
+ */
+
+static int
+vsock_vmci_notify_pkt_recv_pre_block(struct sock *sk,
+				     size_t target,
+				     vsock_vmci_recv_notify_data *data)
+{
+	int err;
+
+	ASSERT(sk);
+	ASSERT(data);
+
+	err = 0;
+
+	vsock_vmci_block_update_write_window(sk);
+
+	if (data->notify_on_block) {
+		err = vsock_vmci_send_read_notification(sk);
+		if (err < 0)
+			return err;
+
+		data->notify_on_block = false;
+	}
+
+	return err;
+}
+
+/*
+ *
+ * vsock_vmci_notify_pkt_recv_post_dequeue --
+ *
+ * Called right after we dequeue / peek data from a socket.
+ *
+ * Results: 0 on success. Negative error on failure.
+ *
+ * Side effects: None.
+ */
+
+static int
+vsock_vmci_notify_pkt_recv_post_dequeue(struct sock *sk,
+					size_t target,
+					ssize_t copied,
+					bool data_read,
+					vsock_vmci_recv_notify_data *data)
+{
+	vsock_vmci_sock *vsk;
+	int err;
+	bool was_full = false;
+	u64 free_space;
+
+	ASSERT(sk);
+	ASSERT(data);
+
+	vsk = vsock_sk(sk);
+	err = 0;
+
+	if (data_read) {
+		smp_mb();
+
+		free_space = vmci_qpair_consume_free_space(vsk->qpair);
+		was_full = free_space == copied;
+
+		if (was_full)
+			PKT_FIELD(vsk, peer_waiting_write) = true;
+
+		err = vsock_vmci_send_read_notification(sk);
+		if (err < 0)
+			return err;
+
+		/* See the comment in vsock_vmci_notify_pkt_send_post_enqueue */
+		sk->sk_data_ready(sk, 0);
+	}
+
+	return err;
+}
+
+/*
+ *
+ * vsock_vmci_notify_pkt_send_init --
+ *
+ * Called at the start of a stream send call with the socket lock held.
+ *
+ * Results: 0 on success. A negative error code on failure.
+ *
+ * Side effects:
+ */
+
+static int
+vsock_vmci_notify_pkt_send_init(struct sock *sk,
+				vsock_vmci_send_notify_data *data)
+{
+	ASSERT(sk);
+	ASSERT(data);
+
+	data->consume_head = 0;
+	data->produce_tail = 0;
+
+	return 0;
+}
+
+/*
+ *
+ * vsock_vmci_notifySendPostEnqueue --
+ *
+ * Called right after we enqueue data to a socket.
+ *
+ * Results: 0 on success. Negative error on failure.
+ *
+ * Side effects: None.
+ */
+
+static int
+vsock_vmci_notify_pkt_send_post_enqueue(struct sock *sk,
+					ssize_t written,
+					vsock_vmci_send_notify_data *data)
+{
+	int err = 0;
+	vsock_vmci_sock *vsk;
+	bool sent_wrote = false;
+	bool was_empty;
+
+	int retries = 0;
+
+	ASSERT(sk);
+	ASSERT(data);
+
+	vsk = vsock_sk(sk);
+
+	smp_mb();
+
+	was_empty = (vmci_qpair_produce_buf_ready(vsk->qpair) == written);
+	if (was_empty) {
+		while (!(vsk->peer_shutdown & RCV_SHUTDOWN) &&
+		       !sent_wrote && retries < VSOCK_MAX_DGRAM_RESENDS) {
+			err = VSOCK_SEND_WROTE(sk);
+			if (err >= 0)
+				sent_wrote = true;
+
+			retries++;
+		}
+	}
+
+	if (retries >= VSOCK_MAX_DGRAM_RESENDS && !sent_wrote) {
+		printk
+		    ("%p unable to send wrote notification to peer.\n",
+		     sk);
+		return err;
+	}
+
+	return err;
+}
+
+/*
+ *
+ * vsock_vmci_notify_pkt_handle_pkt
+ *
+ * Called when a notify packet is recieved for a socket in the connected state.
+ * Note this might be called from a bottom half.
+ *
+ * Results: None.
+ *
+ * Side effects: None.
+ */
+
+static void
+vsock_vmci_notify_pkt_handle_pkt(struct sock *sk,
+				 vsock_packet *pkt,
+				 bool bottom_half,
+				 struct sockaddr_vm *dst,
+				 struct sockaddr_vm *src, bool *pkt_processed)
+{
+	bool processed = false;
+
+	ASSERT(sk);
+	ASSERT(pkt);
+
+	switch (pkt->type) {
+	case VSOCK_PACKET_TYPE_WROTE:
+		vsock_vmci_handle_wrote(sk, pkt, bottom_half, dst, src);
+		processed = true;
+		break;
+	case VSOCK_PACKET_TYPE_READ:
+		vsock_vmci_handle_read(sk, pkt, bottom_half, dst, src);
+		processed = true;
+		break;
+	}
+
+	if (pkt_processed)
+		*pkt_processed = processed;
+
+}
+
+/*
+ *
+ * vsock_vmci_notify_pkt_process_request
+ *
+ * Called near the end of process request.
+ *
+ * Results: None.
+ *
+ * Side effects: None.
+ */
+
+static void vsock_vmci_notify_pkt_process_request(struct sock *sk)
+{
+	vsock_vmci_sock *vsk;
+
+	ASSERT(sk);
+
+	vsk = vsock_sk(sk);
+
+	PKT_FIELD(vsk, write_notify_window) = vsk->consume_size;
+	if (vsk->consume_size < PKT_FIELD(vsk, write_notify_min_window))
+		PKT_FIELD(vsk, write_notify_min_window) = vsk->consume_size;
+
+}
+
+/*
+ *
+ * vsock_vmci_notify_pkt_process_negotiate
+ *
+ * Called near the end of process negotiate.
+ *
+ * Results: None.
+ *
+ * Side effects: None.
+ */
+
+static void vsock_vmci_notify_pkt_process_negotiate(struct sock *sk)
+{
+	vsock_vmci_sock *vsk;
+
+	ASSERT(sk);
+
+	vsk = vsock_sk(sk);
+
+	PKT_FIELD(vsk, write_notify_window) = vsk->consume_size;
+	if (vsk->consume_size < PKT_FIELD(vsk, write_notify_min_window))
+		PKT_FIELD(vsk, write_notify_min_window) = vsk->consume_size;
+
+}
+
+/* Socket always on control packet based operations. */
+vsock_vmci_notify_ops vsock_vmci_notify_pkt_q_state_ops = {
+	vsock_vmci_notify_pkt_socket_init,
+	vsock_vmci_notify_pkt_socket_destruct,
+	vsock_vmci_notify_pkt_poll_in,
+	vsock_vmci_notify_pkt_poll_out,
+	vsock_vmci_notify_pkt_handle_pkt,
+	vsock_vmci_notify_pkt_recv_init,
+	vsock_vmci_notify_pkt_recv_pre_block,
+	NULL,			/* recv_pre_dequeue */
+	vsock_vmci_notify_pkt_recv_post_dequeue,
+	vsock_vmci_notify_pkt_send_init,
+	NULL,			/* send_pre_block */
+	NULL,			/* send_pre_enqueue */
+	vsock_vmci_notify_pkt_send_post_enqueue,
+	vsock_vmci_notify_pkt_process_request,
+	vsock_vmci_notify_pkt_process_negotiate,
+};
diff --git a/net/vmw_vsock/vmci_sockets.h b/net/vmw_vsock/vmci_sockets.h
new file mode 100644
index 0000000..6e6fd98
--- /dev/null
+++ b/net/vmw_vsock/vmci_sockets.h
@@ -0,0 +1,517 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2007-2012 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+/*
+ * vmci_sockets.h --
+ *
+ * VMCI sockets public constants and types.
+ */
+
+#ifndef _VMCI_SOCKETS_H_
+#define _VMCI_SOCKETS_H_
+
+#if !defined(__KERNEL__)
+#include <sys/socket.h>
+#endif
+
+/*
+ * \brief Option name for STREAM socket buffer size.
+ *
+ * Use as the option name in \c setsockopt(3) or \c getsockopt(3) to set or get
+ * an \c unsigned \c long \c long that specifies the size of the buffer
+ * underlying a vSockets STREAM socket.
+ *
+ * \note Value is clamped to the MIN and MAX.
+ *
+ * \see vmci_sock_get_af_value_fd() \see SO_VMCI_BUFFER_MIN_SIZE \see
+ * SO_VMCI_BUFFER_MAX_SIZE
+ *
+ * An example is given below.
+ *
+ * \code int vmciFd; int af = vmci_sock_get_af_value_fd(&vmciFd); unsigned long
+ * long val = 0x1000; int fd = socket(af, SOCK_STREAM, 0); setsockopt(fd, af,
+ * SO_VMCI_BUFFER_SIZE, &val, sizeof val); ... close(fd);
+ * vmci_sock_release_af_value_fd(vmciFd); \endcode
+ */
+
+#define SO_VMCI_BUFFER_SIZE                 0
+
+/*
+ * \brief Option name for STREAM socket minimum buffer size.
+ *
+ * Use as the option name in \c setsockopt(3) or \c getsockopt(3) to set or get
+ * an \c unsigned \c long \c long that specifies the minimum size allowed for
+ * the buffer underlying a vSockets STREAM socket.
+ *
+ * \see vmci_sock_get_af_value_fd() \see SO_VMCI_BUFFER_SIZE \see
+ * SO_VMCI_BUFFER_MAX_SIZE
+ *
+ * An example is given below.
+ *
+ * \code int vmciFd; int af = vmci_sock_get_af_value_fd(&vmciFd); unsigned long
+ * long val = 0x500; int fd = socket(af, SOCK_STREAM, 0); setsockopt(fd, af,
+ * SO_VMCI_BUFFER_MIN_SIZE, &val, sizeof val); ... close(fd);
+ * vmci_sock_release_af_value_fd(vmciFd); \endcode
+ */
+
+#define SO_VMCI_BUFFER_MIN_SIZE             1
+
+/*
+ * \brief Option name for STREAM socket maximum buffer size.
+ *
+ * Use as the option name in \c setsockopt(3) or \c getsockopt(3) to set or get
+ * an unsigned long long that specifies the maximum size allowed for the buffer
+ * underlying a vSockets STREAM socket.
+ *
+ * \see vmci_sock_get_af_value_fd() \see SO_VMCI_BUFFER_SIZE \see
+ * SO_VMCI_BUFFER_MIN_SIZE
+ *
+ * An example is given below.
+ *
+ * \code int vmciFd; int af = vmci_sock_get_af_value_fd(&vmciFd); unsigned long
+ * long val = 0x4000; int fd = socket(af, SOCK_STREAM, 0); setsockopt(fd, af,
+ * SO_VMCI_BUFFER_MAX_SIZE, &val, sizeof val); ... close(fd);
+ * vmci_sock_release_af_value_fd(vmciFd); \endcode
+ */
+
+#define SO_VMCI_BUFFER_MAX_SIZE             2
+
+/*
+ * \brief Option name for socket peer's host-specific VM ID.
+ *
+ * Use as the option name in \c getsockopt(3) to get a host-specific identifier
+ * for the peer endpoint's VM.  The identifier is a signed integer.
+ *
+ * \note Only available for ESX (VMKernel/userworld) endpoints.
+ *
+ * An example is given below.
+ *
+ * \code int vmciFd; int af = vmci_sock_get_af_value_fd(&vmciFd); int id;
+ * socklen_t len = sizeof id; int fd = socket(af, SOCK_DGRAM, 0); getsockopt(fd,
+ * af, SO_VMCI_PEER_HOST_VM_ID, &id, &len); ... close(fd);
+ * vmci_sock_release_af_value_fd(vmciFd); \endcode
+ */
+
+#define SO_VMCI_PEER_HOST_VM_ID             3
+
+/*
+ * \brief Option name for socket's service label.
+ *
+ * Use as the option name in \c setsockopt(3) or \c getsockopt(3) to set or get
+ * the service label for a socket.  The service label is a C-style
+ * NUL-terminated string.
+ *
+ * \note Only available for ESX (VMkernel/userworld) endpoints.
+ */
+
+#define SO_VMCI_SERVICE_LABEL               4
+
+/*
+ * \brief Option name for determining if a socket is trusted.
+ *
+ * Use as the option name in \c getsockopt(3) to determine if a socket is
+ * trusted.  The value is a signed integer.
+ *
+ * An example is given below.
+ *
+ * \code int vmciFd; int af = vmci_sock_get_af_value_fd(&vmciFd); int trusted;
+ * socklen_t len = sizeof trusted; int fd = socket(af, SOCK_DGRAM, 0);
+ * getsockopt(fd, af, SO_VMCI_TRUSTED, &trusted, &len); ... close(fd);
+ * vmci_sock_release_af_value_fd(vmciFd); \endcode
+ */
+
+#define SO_VMCI_TRUSTED                     5
+
+/*
+ * \brief Option name for STREAM socket connection timeout.
+ *
+ * Use as the option name in \c setsockopt(3) or \c getsockopt(3) to set or get
+ * the connection timeout for a STREAM socket.  The value is platform
+ * dependent.  On ESX, Linux and Mac OS, it is a \c struct \c timeval. On
+ * Windows, it is a \c DWORD.
+ *
+ * An example is given below.
+ *
+ * \code int vmciFd; int af = vmci_sock_get_af_value_fd(&vmciFd); struct
+ * timeval t = { 5, 100000 }; int fd = socket(af, SOCK_STREAM, 0);
+ * setsockopt(fd, af, SO_VMCI_CONNECT_TIMEOUT, &t, sizeof t); ... close(fd);
+ * vmci_sock_release_af_value_fd(vmciFd); \endcode
+ */
+
+#define SO_VMCI_CONNECT_TIMEOUT             6
+
+/*
+ * \brief Option name for using non-blocking send/receive.
+ *
+ * Use as the option name for \c setsockopt(3) or \c getsockopt(3) to set or
+ * get the non-blocking transmit/receive flag for a STREAM socket.  This flag
+ * determines whether \c send() and \c recv() can be called in non-blocking
+ * contexts for the given socket.  The value is a signed integer.
+ *
+ * This option is only relevant to kernel endpoints, where descheduling the
+ * thread of execution is not allowed, for example, while holding a spinlock.
+ * It is not to be confused with conventional non-blocking socket operations.
+ *
+ * \note Only available for VMKernel endpoints.
+ *
+ * An example is given below.
+ *
+ * \code int vmciFd; int af = vmci_sock_get_af_value_fd(&vmciFd); int nonblock;
+ * socklen_t len = sizeof nonblock; int fd = socket(af, SOCK_STREAM, 0);
+ * getsockopt(fd, af, SO_VMCI_NONBLOCK_TXRX, &nonblock, &len); ... close(fd);
+ * vmci_sock_release_af_value_fd(vmciFd); \endcode
+ */
+
+#define SO_VMCI_NONBLOCK_TXRX               7
+
+/*
+ * \brief The vSocket equivalent of INADDR_ANY.
+ *
+ * This works for the \c svm_cid field of sockaddr_vm and indicates the context
+ * ID of the current endpoint.
+ *
+ * \see sockaddr_vm
+ *
+ * An example is given below.
+ *
+ * \code int vmciFd; int af = vmci_sock_get_af_value_fd(&vmciFd); struct
+ * sockaddr_vm addr; int fd = socket(af, SOCK_DGRAM, 0); addr.svm_family = af;
+ * addr.svm_cid = VMADDR_CID_ANY; addr.svm_port = 2000; bind(fd, &addr, sizeof
+ * addr); ... close(fd); vmci_sock_release_af_value_fd(vmciFd); \endcode
+ */
+
+#define VMADDR_CID_ANY  ((unsigned int)-1)
+
+/*
+ * \brief Bind to any available port.
+ *
+ * Works for the \c svm_port field of sockaddr_vm.
+ *
+ * \see sockaddr_vm
+ *
+ * An example is given below.
+ *
+ * \code int vmciFd; int af = vmci_sock_get_af_value_fd(&vmciFd); struct
+ * sockaddr_vm addr; int fd = socket(af, SOCK_DGRAM, 0); addr.svm_family = af;
+ * addr.svm_cid = VMADDR_CID_ANY; addr.svm_port = VMADDR_PORT_ANY; bind(fd,
+ * &addr, sizeof addr); ... close(fd); vmci_sock_release_af_value_fd(vmciFd);
+ * \endcode
+ */
+
+#define VMADDR_PORT_ANY ((unsigned int)-1)
+
+/*
+ * \brief Invalid vSockets version.
+ *
+ * \see VMCISock_Version()
+ */
+
+#define VMCI_SOCKETS_INVALID_VERSION ((unsigned int)-1)
+
+/*
+ * \brief The epoch (first) component of the vSockets version.
+ *
+ * A single byte representing the epoch component of the vSockets version.
+ *
+ * \see VMCISock_Version()
+ *
+ * An example is given below.
+ *
+ * \code unsigned int ver = VMCISock_Version(); unsigned char epoch =
+ * VMCI_SOCKETS_VERSION_EPOCH(ver); \endcode
+ */
+
+#define VMCI_SOCKETS_VERSION_EPOCH(_v) (((_v) & 0xFF000000) >> 24)
+
+/*
+ * \brief The major (second) component of the vSockets version.
+ *
+ * A single byte representing the major component of the vSockets version.
+ * Typically changes for every major release of a product.
+ *
+ * \see VMCISock_Version()
+ *
+ * An example is given below.
+ *
+ * \code unsigned int ver = VMCISock_Version(); unsigned char major =
+ * VMCI_SOCKETS_VERSION_MAJOR(ver); \endcode
+ */
+
+#define VMCI_SOCKETS_VERSION_MAJOR(_v) (((_v) & 0x00FF0000) >> 16)
+
+/*
+ * \brief The minor (third) component of the vSockets version.
+ *
+ * Two bytes representing the minor component of the vSockets version.
+ *
+ * \see VMCISock_Version()
+ *
+ * An example is given below.
+ *
+ * \code unsigned int ver = VMCISock_Version(); unsigned short minor =
+ * VMCI_SOCKETS_VERSION_MINOR(ver); \endcode
+ */
+
+#define VMCI_SOCKETS_VERSION_MINOR(_v) (((_v) & 0x0000FFFF))
+
+/** \cond PRIVATE */
+
+/** \endcond */
+
+/*
+ * \brief Address structure for vSockets.
+ *
+ * The address family should be set to whatever vmci_sock_get_af_value_fd()
+ * returns.  The structure members should all align on their natural boundaries
+ * without resorting to compiler packing directives.  The total size of this
+ * structure should be exactly the same as that of \c struct \c sockaddr.
+ *
+ * \see vmci_sock_get_af_value_fd()
+ */
+
+struct sockaddr_vm {
+
+   /** \brief Address family. \see vmci_sock_get_af_value_fd() */
+	sa_family_t svm_family;
+
+   /** \cond PRIVATE */
+	unsigned short svm_reserved1;
+   /** \endcond */
+
+   /** \brief Port.  \see VMADDR_PORT_ANY */
+	unsigned int svm_port;
+
+   /** \brief Context ID.  \see VMADDR_CID_ANY */
+	unsigned int svm_cid;
+
+   /** \cond PRIVATE */
+	unsigned char svm_zero[sizeof(struct sockaddr) -
+			       sizeof(sa_family_t) -
+			       sizeof(unsigned short) -
+			       sizeof(unsigned int) - sizeof(unsigned int)];
+   /** \endcond */
+};
+
+#if defined(linux) && defined(__KERNEL__)
+int vmci_sock_get_local_c_id(void);
+#else
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include <stdio.h>
+
+/** \cond PRIVATE */
+#define VMCI_SOCKETS_DEFAULT_DEVICE      "/dev/vsock"
+#define VMCI_SOCKETS_CLASSIC_ESX_DEVICE  "/vmfs/devices/char/vsock/vsock"
+#define VMCI_SOCKETS_VERSION       1972
+#define VMCI_SOCKETS_GET_AF_VALUE  1976
+#define VMCI_SOCKETS_GET_LOCAL_CID 1977
+/** \endcond */
+
+   /*
+    * VMCISock_Version
+    *
+    * \brief Retrieve the vSockets version.
+    *
+    * Returns the current version of vSockets.  The version is a 32-bit
+    * unsigned integer that consist of three components: the epoch, the major
+    * version, and the minor version.  Use the \c VMCI_SOCKETS_VERSION macros
+    * to extract the components.
+    *
+    * \see VMCI_SOCKETS_VERSION_EPOCH() \see VMCI_SOCKETS_VERSION_MAJOR() \see
+    * VMCI_SOCKETS_VERSION_MINOR()
+    *
+    * \retval VMCI_SOCKETS_INVALID_VERSION Not available. \retval other The
+    * current version.
+    *
+    * An example is given below.
+    *
+    * \code unsigned int ver = VMCISock_Version(); if (ver !=
+    * VMCI_SOCKETS_INVALID_VERSION) { printf("vSockets version=%d.%d.%d\n",
+    * VMCI_SOCKETS_VERSION_EPOCH(ver), VMCI_SOCKETS_VERSION_MAJOR(ver),
+    * VMCI_SOCKETS_VERSION_MINOR(ver)); } \endcode
+    */
+
+static inline unsigned int VMCISock_Version(void)
+{
+	int fd;
+	unsigned int version;
+
+	fd = open(VMCI_SOCKETS_DEFAULT_DEVICE, O_RDWR);
+	if (fd < 0) {
+		fd = open(VMCI_SOCKETS_CLASSIC_ESX_DEVICE, O_RDWR);
+		if (fd < 0)
+			return VMCI_SOCKETS_INVALID_VERSION;
+
+	}
+
+	if (ioctl(fd, VMCI_SOCKETS_VERSION, &version) < 0)
+		version = VMCI_SOCKETS_INVALID_VERSION;
+
+	close(fd);
+	return version;
+}
+
+   /*
+    * vmci_sock_get_af_value_fd
+    *
+    * \brief Retrieve the address family value for vSockets.
+    *
+    * Returns the value to be used for the VMCI Sockets address family. This
+    * value should be used as the domain argument to \c socket(2) (when you
+    * might otherwise use \c AF_INET).  For VMCI Socket-specific options, this
+    * value should also be used for the level argument to \c setsockopt(2)
+    * (when you might otherwise use \c SOL_TCP).
+    *
+    * \see vmci_sock_release_af_value_fd() \see sockaddr_vm
+    *
+    * \param[out] out_fd File descriptor to the VMCI device.  The address
+    * family value is valid until this descriptor is closed.  This parameter is
+    * only valid if the return value is not -1. Call
+    * vmci_sock_release_af_value_fd() to close this descriptor.
+    *
+    * \retval -1 Not available. \retval other The address family value.
+    *
+    * An example is given below.
+    *
+    * \code int vmciFd; int af = vmci_sock_get_af_value_fd(&vmciFd); if (af !=
+    * -1) { int fd = socket(af, SOCK_STREAM, 0); ... close(fd); close(vmciFd); }
+    * \endcode
+    */
+
+static inline int vmci_sock_get_af_value_fd(int *out_fd)
+{
+	int fd;
+	int family;
+
+	fd = open(VMCI_SOCKETS_DEFAULT_DEVICE, O_RDWR);
+	if (fd < 0) {
+		fd = open(VMCI_SOCKETS_CLASSIC_ESX_DEVICE, O_RDWR);
+		if (fd < 0)
+			return -1;
+
+	}
+
+	if (ioctl(fd, VMCI_SOCKETS_GET_AF_VALUE, &family) < 0)
+		family = -1;
+
+	if (family < 0)
+		close(fd);
+	else if (out_fd)
+		*out_fd = fd;
+
+	return family;
+}
+
+   /** \cond PRIVATE */
+   /*
+    * vmci_sock_get_af_value
+    *
+    * \brief Retrieve the address family value for vSockets.
+    *
+    * Returns the value to be used for the VMCI Sockets address family. This
+    * value should be used as the domain argument to \c socket(2) (when you
+    * might otherwise use \c AF_INET).  For VMCI Socket-specific options, this
+    * value should also be used for the level argument to \c setsockopt(2)
+    * (when you might otherwise use \c SOL_TCP).
+    *
+    * \note This function leaves its descriptor to the vsock device open so
+    * that the socket implementation knows that the socket family is still in
+    * use.  This is done because the address family is registered with the
+    * kernel on-demand and a notification is needed to unregister the address
+    * family.  Use of this function is thus discouraged; please use
+    * vmci_sock_get_af_value_fd() instead.
+    *
+    * \see vmci_sock_get_af_value_fd() \see sockaddr_vm
+    *
+    * \retval -1 Not available. \retval other The address family value.
+    *
+    * An example is given below.
+    *
+    * \code int af = vmci_sock_get_af_value(); if (af != -1) { int fd =
+    * socket(af, SOCK_STREAM, 0); ... close(fd); } \endcode
+    */
+
+static inline int vmci_sock_get_af_value(void)
+{
+	return vmci_sock_get_af_value_fd(NULL);
+}
+
+   /** \endcond PRIVATE */
+
+   /*
+    * vmci_sock_release_af_value_fd
+    *
+    * \brief Release the file descriptor obtained when retrieving the address
+    * family value.
+    *
+    * Use this to release the file descriptor obtained by calling
+    * vmci_sock_get_af_value_fd().
+    *
+    * \see vmci_sock_get_af_value_fd()
+    *
+    * \param[in] fd File descriptor to the VMCI device.
+    */
+
+static inline void vmci_sock_release_af_value_fd(int fd)
+{
+	if (fd >= 0)
+		close(fd);
+
+}
+
+   /*
+    * vmci_sock_get_local_c_id
+    *
+    * \brief Retrieve the current context ID.
+    *
+    * \see VMADDR_CID_ANY
+    *
+    * \retval VMADDR_CID_ANY Not available. \retval other The current context
+    * ID.
+    *
+    * An example is given below.
+    *
+    * \code int vmciFd; int af = vmci_sock_get_af_value_fd(&vmciFd); struct
+    * sockaddr_vm addr; addr.svm_family = af; addr.svm_cid =
+    * vmci_sock_get_local_c_id(); vmci_sock_release_af_value_fd(vmciFd);
+    * \endcode
+    */
+
+static inline unsigned int vmci_sock_get_local_c_id(void)
+{
+	int fd;
+	unsigned int context_id;
+
+	fd = open(VMCI_SOCKETS_DEFAULT_DEVICE, O_RDWR);
+	if (fd < 0) {
+		fd = open(VMCI_SOCKETS_CLASSIC_ESX_DEVICE, O_RDWR);
+		if (fd < 0)
+			return VMADDR_CID_ANY;
+
+	}
+
+	if (ioctl(fd, VMCI_SOCKETS_GET_LOCAL_CID, &context_id) < 0)
+		context_id = VMADDR_CID_ANY;
+
+	close(fd);
+	return context_id;
+}
+#endif
+
+#endif
diff --git a/net/vmw_vsock/vmci_sockets_packet.h b/net/vmw_vsock/vmci_sockets_packet.h
new file mode 100644
index 0000000..ec4e15f
--- /dev/null
+++ b/net/vmw_vsock/vmci_sockets_packet.h
@@ -0,0 +1,107 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2012 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+/*
+ * vmci_sockets_packet.h --
+ *
+ * Definition of VMCI Sockets packet format, constants, and types.
+ */
+
+#ifndef _VMCI_SOCKETS_PACKET_H_
+#define _VMCI_SOCKETS_PACKET_H_
+
+#include <linux/vmw_vmci_defs.h>
+#include <linux/vmw_vmci_api.h>
+
+/*
+ * STREAM control packets.
+ */
+
+/* If the packet format changes in a release then this should change too. */
+#define VSOCK_PACKET_VERSION 1
+
+/* The resource ID on which control packets are sent. */
+#define VSOCK_PACKET_RID 1
+
+/*
+ * Assert that the given packet is valid. We check that the two original
+ * reserved fields equal zero because the version of the common code that
+ * shipped with ESX 4.0 and WS 6.5 did so and will return a RST packet if they
+ * aren't set that way. For newer packet types added after that release we
+ * don't do this.
+ */
+#define VSOCK_PACKET_ASSERT(_p)			     \
+	do {					     \
+		ASSERT((_p));			     \
+		ASSERT((_p)->type < VSOCK_PACKET_TYPE_MAX);	\
+		if ((_p)->type < VSOCK_PACKET_TYPE_REQUEST2) {	\
+			ASSERT(0 == (_p)->proto);		\
+			ASSERT(0 == (_p)->_reserved2);		\
+		}						\
+	} while (0)
+
+typedef enum vsock_packet_type {
+	VSOCK_PACKET_TYPE_INVALID = 0,
+	VSOCK_PACKET_TYPE_REQUEST,
+	VSOCK_PACKET_TYPE_NEGOTIATE,
+	VSOCK_PACKET_TYPE_OFFER,
+	VSOCK_PACKET_TYPE_ATTACH,
+	VSOCK_PACKET_TYPE_WROTE,
+	VSOCK_PACKET_TYPE_READ,
+	VSOCK_PACKET_TYPE_RST,
+	VSOCK_PACKET_TYPE_SHUTDOWN,
+	VSOCK_PACKET_TYPE_WAITING_WRITE,
+	VSOCK_PACKET_TYPE_WAITING_READ,
+	VSOCK_PACKET_TYPE_REQUEST2,
+	VSOCK_PACKET_TYPE_NEGOTIATE2,
+	VSOCK_PACKET_TYPE_MAX
+} vsock_packet_type;
+
+typedef u16 vsock_proto_version;
+#define VSOCK_PROTO_INVALID        0
+#define VSOCK_PROTO_PKT_ON_NOTIFY (1 << 0)
+
+#define VSOCK_PROTO_ALL_SUPPORTED (VSOCK_PROTO_PKT_ON_NOTIFY)
+
+typedef struct vsock_waiting_info {
+	u64 generation;
+	u64 offset;
+} vsock_waiting_info;
+
+/*
+ * Control packet type for STREAM sockets.  DGRAMs have no control packets nor
+ * special packet header for data packets, they are just raw VMCI DGRAM
+ * messages.  For STREAMs, control packets are sent over the control channel
+ * while data is written and read directly from queue pairs with no packet
+ * format.
+ */
+typedef struct vsock_packet {
+	struct vmci_datagram dg;
+	u8 version;
+	u8 type;
+	vsock_proto_version proto;
+
+	u32 src_port;
+	u32 dst_port;
+	u32 _reserved2;
+	union {
+		u64 size;
+		u64 mode;
+		struct vmci_handle handle;
+		vsock_waiting_info wait;
+	} u;
+} vsock_packet;
+
+#endif
diff --git a/net/vmw_vsock/vsock_common.h b/net/vmw_vsock/vsock_common.h
new file mode 100644
index 0000000..fd7f2cd
--- /dev/null
+++ b/net/vmw_vsock/vsock_common.h
@@ -0,0 +1,130 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2007-2012 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+/*
+ * vsockCommon.h --
+ *
+ * VSockets common constants, types and functions.
+ */
+
+#ifndef _VSOCK_COMMON_H_
+#define _VSOCK_COMMON_H_
+
+/*
+ * vmci_sock_get_af_value_int is defined separately from vmci_sock_get_af_value
+ * because it is used in several different contexts. In particular it is called
+ * from vsock_addr.c which gets compiled into both our kernel modules as well
+ * as the user level vsock library. In the linux kernel we need different
+ * behavior than external kernel modules using VMCI Sockets api inside the
+ * kernel.  FIXME
+ */
+
+#if defined __KERNEL__
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+#else
+/* In userland, just use the normal exported userlevel api. */
+#define vmci_sock_get_af_value_int() vmci_sock_get_af_value()
+#endif
+
+#include <linux/vmw_vmci_defs.h>
+#include <linux/vmw_vmci_api.h>
+
+#include "vmci_sockets.h"
+#include "vsock_addr.h"
+
+#define ASSERT(cond) BUG_ON(!(cond))
+#define ASSERT_ON_COMPILE(cond) BUILD_BUG_ON(!(cond))
+
+#ifdef __x86_64__
+#define FMT64 "ll"
+#else
+#define FMT64 "L"
+#endif
+
+#ifndef PAGE_SHIFT
+#if defined __i386__
+#define PAGE_SHIFT 12
+#elif defined __arm__
+#define PAGE_SHIFT 12
+#else
+#error
+#endif
+#endif
+
+#ifndef PAGE_SIZE
+#define PAGE_SIZE (1<<PAGE_SHIFT)
+#endif
+
+#define MAX_UINT32 ((u32)0xffffffff)
+
+#ifndef ESYSNOTREADY
+#define ESYSNOTREADY EOPNOTSUPP
+#endif
+
+#define sockerr() 	errno
+#define sockerr2err(_e)	(((_e) > 0) ? -(_e) : (_e))
+#define SS_LISTEN 	255
+
+extern vmci_id vmci_get_context_id(void);
+
+/*
+ * Helper function to determine if the given handle points to the local context.
+ * Returns TRUE if the given handle is for the local context, FALSE otherwise.
+ */
+
+static inline bool vsock_vmci_is_local(struct vmci_handle handle)
+{
+	return vmci_get_context_id() == VMCI_HANDLE_TO_CONTEXT_ID(handle);
+}
+
+/*
+ * Helper function to convert from a VMCI error code to a VSock error code.
+ */
+
+static inline s32 vsock_vmci_error_to_vsock_error(s32 vmci_error)
+{
+	int err;
+
+	switch (vmci_error) {
+	case VMCI_ERROR_NO_MEM:
+		err = ENOMEM;
+		break;
+	case VMCI_ERROR_DUPLICATE_ENTRY:
+	case VMCI_ERROR_ALREADY_EXISTS:
+		err = EADDRINUSE;
+		break;
+	case VMCI_ERROR_NO_ACCESS:
+		err = EPERM;
+		break;
+	case VMCI_ERROR_NO_RESOURCES:
+		err = ENOBUFS;
+		break;
+	case VMCI_ERROR_INVALID_RESOURCE:
+		err = EHOSTUNREACH;
+		break;
+	case VMCI_ERROR_MODULE_NOT_LOADED:
+		err = ESYSNOTREADY;
+		break;
+	case VMCI_ERROR_INVALID_ARGS:
+	default:
+		err = EINVAL;
+	}
+
+	return sockerr2err(err);
+}
+
+#endif
diff --git a/net/vmw_vsock/vsock_packet.h b/net/vmw_vsock/vsock_packet.h
new file mode 100644
index 0000000..76bcac0
--- /dev/null
+++ b/net/vmw_vsock/vsock_packet.h
@@ -0,0 +1,131 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2007-2012 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+/*
+ * vsockPacket.h --
+ *
+ * Packet constants, types and functions.
+ */
+
+#ifndef _VSOCK_PACKET_H_
+#define _VSOCK_PACKET_H_
+
+#include "vmci_sockets_packet.h"
+
+/*
+ *
+ * vsock_packet_init --
+ *
+ * Initialize the given packet.  The packet version is set and the fields are
+ * filled out.  Reserved fields are cleared.
+ *
+ * Results: None.
+ *
+ * Side effects: None.
+ */
+
+static inline void
+vsock_packet_init(vsock_packet *pkt,
+		  struct sockaddr_vm *src,
+		  struct sockaddr_vm *dst,
+		  u8 type,
+		  u64 size,
+		  u64 mode,
+		  vsock_waiting_info *wait,
+		  vsock_proto_version proto, struct vmci_handle handle)
+{
+	BUG_ON(!pkt);
+	BUG_ON(vsock_addr_validate(src) != 0);
+	BUG_ON(vsock_addr_validate(dst) != 0);
+
+	/*
+	 * We register the stream control handler as an any cid handle so we
+	 * must always send from a source address of VMADDR_CID_ANY
+	 */
+	pkt->dg.src = VMCI_MAKE_HANDLE(VMADDR_CID_ANY, VSOCK_PACKET_RID);
+	pkt->dg.dst = VMCI_MAKE_HANDLE(dst->svm_cid, VSOCK_PACKET_RID);
+	pkt->dg.payload_size = sizeof *pkt - sizeof pkt->dg;
+	pkt->version = VSOCK_PACKET_VERSION;
+	pkt->type = type;
+	pkt->src_port = src->svm_port;
+	pkt->dst_port = dst->svm_port;
+	memset(&pkt->proto, 0, sizeof pkt->proto);
+	memset(&pkt->_reserved2, 0, sizeof pkt->_reserved2);
+
+	switch (pkt->type) {
+	case VSOCK_PACKET_TYPE_INVALID:
+		pkt->u.size = 0;
+		break;
+
+	case VSOCK_PACKET_TYPE_REQUEST:
+	case VSOCK_PACKET_TYPE_NEGOTIATE:
+		pkt->u.size = size;
+		break;
+
+	case VSOCK_PACKET_TYPE_OFFER:
+	case VSOCK_PACKET_TYPE_ATTACH:
+		pkt->u.handle = handle;
+		break;
+
+	case VSOCK_PACKET_TYPE_WROTE:
+	case VSOCK_PACKET_TYPE_READ:
+	case VSOCK_PACKET_TYPE_RST:
+		pkt->u.size = 0;
+		break;
+
+	case VSOCK_PACKET_TYPE_SHUTDOWN:
+		pkt->u.mode = mode;
+		break;
+
+	case VSOCK_PACKET_TYPE_WAITING_READ:
+	case VSOCK_PACKET_TYPE_WAITING_WRITE:
+		ASSERT(wait);
+		memcpy(&pkt->u.wait, wait, sizeof pkt->u.wait);
+		break;
+
+	case VSOCK_PACKET_TYPE_REQUEST2:
+	case VSOCK_PACKET_TYPE_NEGOTIATE2:
+		pkt->u.size = size;
+		pkt->proto = proto;
+		break;
+	}
+
+	VSOCK_PACKET_ASSERT(pkt);
+}
+
+/*
+ *
+ * vsock_packet_get_addresses --
+ *
+ * Get the local and remote addresses from the given packet.
+ *
+ * Results: None.
+ *
+ * Side effects: None.
+ */
+
+static inline void
+vsock_packet_get_addresses(vsock_packet *pkt,
+			   struct sockaddr_vm *local,
+			   struct sockaddr_vm *remote)
+{
+	VSOCK_PACKET_ASSERT(pkt);
+	vsock_addr_init(local, VMCI_HANDLE_TO_CONTEXT_ID(pkt->dg.dst),
+			pkt->dst_port);
+	vsock_addr_init(remote, VMCI_HANDLE_TO_CONTEXT_ID(pkt->dg.src),
+			pkt->src_port);
+}
+
+#endif
diff --git a/net/vmw_vsock/vsock_version.h b/net/vmw_vsock/vsock_version.h
new file mode 100644
index 0000000..9a6a63b
--- /dev/null
+++ b/net/vmw_vsock/vsock_version.h
@@ -0,0 +1,29 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2011-2012 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+/*
+ * vsock_version.h --
+ *
+ * Version definitions for the Linux vsock driver.
+ */
+
+#ifndef _VSOCK_VERSION_H_
+#define _VSOCK_VERSION_H_
+
+#define VSOCK_DRIVER_VERSION          1.0.0.0-k
+#define VSOCK_DRIVER_VERSION_COMMAS   1,0,0,0
+#define VSOCK_DRIVER_VERSION_STRING   "1.0.0.0-k"
+
+#endif /* _VSOCK_VERSION_H_ */

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ