Skip to content

Commit e76ffea

Browse files
georgezhang11gregkh
authored andcommitted
VMCI: routing implementation.
VMCI routing code is responsible for routing between various hosts/guests as well as routing in nested scenarios. Signed-off-by: George Zhang <[email protected]> Acked-by: Andy king <[email protected]> Acked-by: Dmitry Torokhov <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent bc63ded commit e76ffea

File tree

2 files changed

+256
-0
lines changed

2 files changed

+256
-0
lines changed

drivers/misc/vmw_vmci/vmci_route.c

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
/*
2+
* VMware VMCI Driver
3+
*
4+
* Copyright (C) 2012 VMware, Inc. All rights reserved.
5+
*
6+
* This program is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License as published by the
8+
* Free Software Foundation version 2 and no later version.
9+
*
10+
* This program is distributed in the hope that it will be useful, but
11+
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12+
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
* for more details.
14+
*/
15+
16+
#include <linux/vmw_vmci_defs.h>
17+
#include <linux/vmw_vmci_api.h>
18+
19+
#include "vmci_context.h"
20+
#include "vmci_driver.h"
21+
#include "vmci_route.h"
22+
23+
/*
24+
* Make a routing decision for the given source and destination handles.
25+
* This will try to determine the route using the handles and the available
26+
* devices. Will set the source context if it is invalid.
27+
*/
28+
int vmci_route(struct vmci_handle *src,
29+
const struct vmci_handle *dst,
30+
bool from_guest,
31+
enum vmci_route *route)
32+
{
33+
bool has_host_device = vmci_host_code_active();
34+
bool has_guest_device = vmci_guest_code_active();
35+
36+
*route = VMCI_ROUTE_NONE;
37+
38+
/*
39+
* "from_guest" is only ever set to true by
40+
* IOCTL_VMCI_DATAGRAM_SEND (or by the vmkernel equivalent),
41+
* which comes from the VMX, so we know it is coming from a
42+
* guest.
43+
*
44+
* To avoid inconsistencies, test these once. We will test
45+
* them again when we do the actual send to ensure that we do
46+
* not touch a non-existent device.
47+
*/
48+
49+
/* Must have a valid destination context. */
50+
if (VMCI_INVALID_ID == dst->context)
51+
return VMCI_ERROR_INVALID_ARGS;
52+
53+
/* Anywhere to hypervisor. */
54+
if (VMCI_HYPERVISOR_CONTEXT_ID == dst->context) {
55+
56+
/*
57+
* If this message already came from a guest then we
58+
* cannot send it to the hypervisor. It must come
59+
* from a local client.
60+
*/
61+
if (from_guest)
62+
return VMCI_ERROR_DST_UNREACHABLE;
63+
64+
/*
65+
* We must be acting as a guest in order to send to
66+
* the hypervisor.
67+
*/
68+
if (!has_guest_device)
69+
return VMCI_ERROR_DEVICE_NOT_FOUND;
70+
71+
/* And we cannot send if the source is the host context. */
72+
if (VMCI_HOST_CONTEXT_ID == src->context)
73+
return VMCI_ERROR_INVALID_ARGS;
74+
75+
/*
76+
* If the client passed the ANON source handle then
77+
* respect it (both context and resource are invalid).
78+
* However, if they passed only an invalid context,
79+
* then they probably mean ANY, in which case we
80+
* should set the real context here before passing it
81+
* down.
82+
*/
83+
if (VMCI_INVALID_ID == src->context &&
84+
VMCI_INVALID_ID != src->resource)
85+
src->context = vmci_get_context_id();
86+
87+
/* Send from local client down to the hypervisor. */
88+
*route = VMCI_ROUTE_AS_GUEST;
89+
return VMCI_SUCCESS;
90+
}
91+
92+
/* Anywhere to local client on host. */
93+
if (VMCI_HOST_CONTEXT_ID == dst->context) {
94+
/*
95+
* If it is not from a guest but we are acting as a
96+
* guest, then we need to send it down to the host.
97+
* Note that if we are also acting as a host then this
98+
* will prevent us from sending from local client to
99+
* local client, but we accept that restriction as a
100+
* way to remove any ambiguity from the host context.
101+
*/
102+
if (src->context == VMCI_HYPERVISOR_CONTEXT_ID) {
103+
/*
104+
* If the hypervisor is the source, this is
105+
* host local communication. The hypervisor
106+
* may send vmci event datagrams to the host
107+
* itself, but it will never send datagrams to
108+
* an "outer host" through the guest device.
109+
*/
110+
111+
if (has_host_device) {
112+
*route = VMCI_ROUTE_AS_HOST;
113+
return VMCI_SUCCESS;
114+
} else {
115+
return VMCI_ERROR_DEVICE_NOT_FOUND;
116+
}
117+
}
118+
119+
if (!from_guest && has_guest_device) {
120+
/* If no source context then use the current. */
121+
if (VMCI_INVALID_ID == src->context)
122+
src->context = vmci_get_context_id();
123+
124+
/* Send it from local client down to the host. */
125+
*route = VMCI_ROUTE_AS_GUEST;
126+
return VMCI_SUCCESS;
127+
}
128+
129+
/*
130+
* Otherwise we already received it from a guest and
131+
* it is destined for a local client on this host, or
132+
* it is from another local client on this host. We
133+
* must be acting as a host to service it.
134+
*/
135+
if (!has_host_device)
136+
return VMCI_ERROR_DEVICE_NOT_FOUND;
137+
138+
if (VMCI_INVALID_ID == src->context) {
139+
/*
140+
* If it came from a guest then it must have a
141+
* valid context. Otherwise we can use the
142+
* host context.
143+
*/
144+
if (from_guest)
145+
return VMCI_ERROR_INVALID_ARGS;
146+
147+
src->context = VMCI_HOST_CONTEXT_ID;
148+
}
149+
150+
/* Route to local client. */
151+
*route = VMCI_ROUTE_AS_HOST;
152+
return VMCI_SUCCESS;
153+
}
154+
155+
/*
156+
* If we are acting as a host then this might be destined for
157+
* a guest.
158+
*/
159+
if (has_host_device) {
160+
/* It will have a context if it is meant for a guest. */
161+
if (vmci_ctx_exists(dst->context)) {
162+
if (VMCI_INVALID_ID == src->context) {
163+
/*
164+
* If it came from a guest then it
165+
* must have a valid context.
166+
* Otherwise we can use the host
167+
* context.
168+
*/
169+
170+
if (from_guest)
171+
return VMCI_ERROR_INVALID_ARGS;
172+
173+
src->context = VMCI_HOST_CONTEXT_ID;
174+
} else if (VMCI_CONTEXT_IS_VM(src->context) &&
175+
src->context != dst->context) {
176+
/*
177+
* VM to VM communication is not
178+
* allowed. Since we catch all
179+
* communication destined for the host
180+
* above, this must be destined for a
181+
* VM since there is a valid context.
182+
*/
183+
184+
return VMCI_ERROR_DST_UNREACHABLE;
185+
}
186+
187+
/* Pass it up to the guest. */
188+
*route = VMCI_ROUTE_AS_HOST;
189+
return VMCI_SUCCESS;
190+
} else if (!has_guest_device) {
191+
/*
192+
* The host is attempting to reach a CID
193+
* without an active context, and we can't
194+
* send it down, since we have no guest
195+
* device.
196+
*/
197+
198+
return VMCI_ERROR_DST_UNREACHABLE;
199+
}
200+
}
201+
202+
/*
203+
* We must be a guest trying to send to another guest, which means
204+
* we need to send it down to the host. We do not filter out VM to
205+
* VM communication here, since we want to be able to use the guest
206+
* driver on older versions that do support VM to VM communication.
207+
*/
208+
if (!has_guest_device) {
209+
/*
210+
* Ending up here means we have neither guest nor host
211+
* device.
212+
*/
213+
return VMCI_ERROR_DEVICE_NOT_FOUND;
214+
}
215+
216+
/* If no source context then use the current context. */
217+
if (VMCI_INVALID_ID == src->context)
218+
src->context = vmci_get_context_id();
219+
220+
/*
221+
* Send it from local client down to the host, which will
222+
* route it to the other guest for us.
223+
*/
224+
*route = VMCI_ROUTE_AS_GUEST;
225+
return VMCI_SUCCESS;
226+
}

drivers/misc/vmw_vmci/vmci_route.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* VMware VMCI Driver
3+
*
4+
* Copyright (C) 2012 VMware, Inc. All rights reserved.
5+
*
6+
* This program is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License as published by the
8+
* Free Software Foundation version 2 and no later version.
9+
*
10+
* This program is distributed in the hope that it will be useful, but
11+
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12+
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
* for more details.
14+
*/
15+
16+
#ifndef _VMCI_ROUTE_H_
17+
#define _VMCI_ROUTE_H_
18+
19+
#include <linux/vmw_vmci_defs.h>
20+
21+
enum vmci_route {
22+
VMCI_ROUTE_NONE,
23+
VMCI_ROUTE_AS_HOST,
24+
VMCI_ROUTE_AS_GUEST,
25+
};
26+
27+
int vmci_route(struct vmci_handle *src, const struct vmci_handle *dst,
28+
bool from_guest, enum vmci_route *route);
29+
30+
#endif /* _VMCI_ROUTE_H_ */

0 commit comments

Comments
 (0)