Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <georgezhang@vmware.com>
Acked-by: Andy king <acking@vmware.com>
Acked-by: Dmitry Torokhov <dtor@vmware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

George Zhang and committed by
Greg Kroah-Hartman
e76ffea3 bc63dedb

+256
+226
drivers/misc/vmw_vmci/vmci_route.c
··· 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 + }
+30
drivers/misc/vmw_vmci/vmci_route.h
··· 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_ */