1
/*********************************************************
2
* Copyright (C) 2011 VMware, Inc. All rights reserved.
4
* This program is free software; you can redistribute it and/or modify it
5
* under the terms of the GNU General Public License as published by the
6
* Free Software Foundation version 2 and no later version.
8
* This program is distributed in the hope that it will be useful, but
9
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13
* You should have received a copy of the GNU General Public License along
14
* with this program; if not, write to the Free Software Foundation, Inc.,
15
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
*********************************************************/
22
* Implementation of VMCI routing rules.
25
#include "vmci_kernel_if.h"
26
#include "vm_assert.h"
27
#include "vmci_defs.h"
28
#include "vmci_infrastructure.h"
29
#include "vmciCommonInt.h"
30
#include "vmciContext.h"
31
#include "vmciDriver.h"
32
#include "vmciKernelAPI.h"
33
#include "vmciRoute.h"
35
# include "vmciVmkInt.h"
37
# include "helper_ext.h"
40
#define LGPFX "VMCIRoute: "
44
*------------------------------------------------------------------------------
48
* Make a routing decision for the given source and destination handles.
49
* This will try to determine the route using the handles and the available
56
* Sets the source context if it is invalid.
58
*------------------------------------------------------------------------------
62
VMCI_Route(VMCIHandle *src, // IN/OUT
63
const VMCIHandle *dst, // IN
65
VMCIRoute *route) // OUT
74
*route = VMCI_ROUTE_NONE;
77
* "fromGuest" is only ever set to TRUE by IOCTL_VMCI_DATAGRAM_SEND (or by
78
* the vmkernel equivalent), which comes from the VMX, so we know it is
79
* coming from a guest.
83
* To avoid inconsistencies, test these once. We will test them again
84
* when we do the actual send to ensure that we do not touch a non-existent
88
hasHostDevice = VMCI_HostPersonalityActive();
89
hasGuestDevice = VMCI_GuestPersonalityActive();
91
/* Must have a valid destination context. */
92
if (VMCI_INVALID_ID == dst->context) {
93
return VMCI_ERROR_INVALID_ARGS;
97
* If we are acting as a host and the datagram is from or for a well-known
98
* context (which also means it must have been passed down from a guest),
99
* then we can assume it is intended for a guest on this host.
102
if (fromGuest && hasHostDevice &&
103
(VMCI_WELL_KNOWN_CONTEXT_ID == src->context ||
104
VMCI_WELL_KNOWN_CONTEXT_ID == dst->context)) {
105
*route = VMCI_ROUTE_AS_HOST;
109
/* Anywhere to hypervisor. */
110
if (VMCI_HYPERVISOR_CONTEXT_ID == dst->context) {
112
* If this message already came from a guest then we cannot send it
113
* to the hypervisor. It must come from a local client.
117
return VMCI_ERROR_DST_UNREACHABLE;
120
/* We must be acting as a guest in order to send to the hypervisor. */
121
if (!hasGuestDevice) {
122
return VMCI_ERROR_DEVICE_NOT_FOUND;
125
/* And we cannot send if the source is the host context. */
126
if (VMCI_HOST_CONTEXT_ID == src->context) {
127
return VMCI_ERROR_INVALID_ARGS;
130
/* Send from local client down to the hypervisor. */
131
*route = VMCI_ROUTE_AS_GUEST;
135
/* Anywhere to local client on host. */
136
if (VMCI_HOST_CONTEXT_ID == dst->context) {
138
* If it is not from a guest but we are acting as a guest, then we need
139
* to send it down to the host. Note that if we are also acting as a
140
* host then this will prevent us from sending from local client to
141
* local client, but we accept that restriction as a way to remove
142
* any ambiguity from the host context.
145
if (src->context == VMCI_HYPERVISOR_CONTEXT_ID) {
147
* If the hypervisor is the source, this is host local
148
* communication. The hypervisor may send vmci event
149
* datagrams to the host itself, but it will never send
150
* datagrams to an "outer host" through the guest device.
154
*route = VMCI_ROUTE_AS_HOST;
157
return VMCI_ERROR_DEVICE_NOT_FOUND;
161
if (!fromGuest && hasGuestDevice) {
162
/* If no source context then use the current. */
163
if (VMCI_INVALID_ID == src->context) {
164
src->context = VMCI_GetContextID();
167
/* Send it from local client down to the host. */
168
*route = VMCI_ROUTE_AS_GUEST;
173
* Otherwise we already received it from a guest and it is destined
174
* for a local client on this host, or it is from another local client
175
* on this host. We must be acting as a host to service it.
178
if (!hasHostDevice) {
179
return VMCI_ERROR_DEVICE_NOT_FOUND;
182
if (VMCI_INVALID_ID == src->context) {
184
* If it came from a guest then it must have a valid context.
185
* Otherwise we can use the host context.
189
return VMCI_ERROR_INVALID_ARGS;
191
src->context = VMCI_HOST_CONTEXT_ID;
194
/* Route to local client. */
195
*route = VMCI_ROUTE_AS_HOST;
199
/* If we are acting as a host then this might be destined for a guest. */
201
/* It will have a context if it is meant for a guest. */
202
if (VMCIContext_Exists(dst->context)) {
203
if (VMCI_INVALID_ID == src->context) {
205
* If it came from a guest then it must have a valid context.
206
* Otherwise we can use the host context.
210
return VMCI_ERROR_INVALID_ARGS;
212
src->context = VMCI_HOST_CONTEXT_ID;
215
/* Pass it up to the guest. */
216
*route = VMCI_ROUTE_AS_HOST;
222
* We must be a guest trying to send to another guest, which means we
223
* need to send it down to the host.
226
if (!hasGuestDevice) {
227
return VMCI_ERROR_DEVICE_NOT_FOUND;
230
/* If no source context then use the current context. */
231
if (VMCI_INVALID_ID == src->context) {
232
src->context = VMCI_GetContextID();
236
* Send it from local client down to the host, which will route it to
237
* the other guest for us.
240
*route = VMCI_ROUTE_AS_GUEST;
246
*------------------------------------------------------------------------------
248
* VMCI_RouteString --
250
* Get a string for the given route.
253
* A string representing the route, if the route is valid, otherwise an
259
*------------------------------------------------------------------------------
263
VMCI_RouteString(VMCIRoute route) // IN
265
const char *vmciRouteStrings[] = {
270
if (route >= VMCI_ROUTE_NONE && route <= VMCI_ROUTE_AS_GUEST) {
271
return vmciRouteStrings[route];