2 Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in
13 the documentation and/or other materials provided with the
15 * Neither the name of Intel Corporation nor the names of its
16 contributors may be used to endorse or promote products derived
17 from this software without specific prior written permission.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 I40E/IXGBE/IGB Virtual Function Driver
32 ======================================
34 Supported Intel® Ethernet Controllers (see the *DPDK Release Notes* for details)
35 support the following modes of operation in a virtualized environment:
37 * **SR-IOV mode**: Involves direct assignment of part of the port resources to different guest operating systems
38 using the PCI-SIG Single Root I/O Virtualization (SR IOV) standard,
39 also known as "native mode" or "pass-through" mode.
40 In this chapter, this mode is referred to as IOV mode.
42 * **VMDq mode**: Involves central management of the networking resources by an IO Virtual Machine (IOVM) or
43 a Virtual Machine Monitor (VMM), also known as software switch acceleration mode.
44 In this chapter, this mode is referred to as the Next Generation VMDq mode.
46 SR-IOV Mode Utilization in a DPDK Environment
47 ---------------------------------------------
49 The DPDK uses the SR-IOV feature for hardware-based I/O sharing in IOV mode.
50 Therefore, it is possible to partition SR-IOV capability on Ethernet controller NIC resources logically and
51 expose them to a virtual machine as a separate PCI function called a "Virtual Function".
54 Therefore, a NIC is logically distributed among multiple virtual machines (as shown in Figure 10),
55 while still having global data in common to share with the Physical Function and other Virtual Functions.
56 The DPDK fm10kvf, i40evf, igbvf or ixgbevf as a Poll Mode Driver (PMD) serves for the Intel® 82576 Gigabit Ethernet Controller,
57 Intel® Ethernet Controller I350 family, Intel® 82599 10 Gigabit Ethernet Controller NIC,
58 Intel® Fortville 10/40 Gigabit Ethernet Controller NIC's virtual PCI function,or PCIE host-interface of the Intel Ethernet Switch
60 Meanwhile the DPDK Poll Mode Driver (PMD) also supports "Physical Function" of such NIC's on the host.
62 The DPDK PF/VF Poll Mode Driver (PMD) supports the Layer 2 switch on Intel® 82576 Gigabit Ethernet Controller,
63 Intel® Ethernet Controller I350 family, Intel® 82599 10 Gigabit Ethernet Controller,
64 and Intel® Fortville 10/40 Gigabit Ethernet Controller NICs so that guest can choose it for inter virtual machine traffic in SR-IOV mode.
66 For more detail on SR-IOV, please refer to the following documents:
68 * `SR-IOV provides hardware based I/O sharing <http://www.intel.com/network/connectivity/solutions/vmdc.htm>`_
70 * `PCI-SIG-Single Root I/O Virtualization Support on IA
71 <http://www.intel.com/content/www/us/en/pci-express/pci-sig-single-root-io-virtualization-support-in-virtualization-technology-for-connectivity-paper.html>`_
73 * `Scalable I/O Virtualized Servers <http://www.intel.com/content/www/us/en/virtualization/server-virtualization/scalable-i-o-virtualized-servers-paper.html>`_
77 **Figure 1. Virtualization for a Single Port NIC in SR-IOV Mode**
79 .. image:: img/single_port_nic.*
81 Physical and Virtual Function Infrastructure
82 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
84 The following describes the Physical Function and Virtual Functions infrastructure for the supported Ethernet Controller NICs.
86 Virtual Functions operate under the respective Physical Function on the same NIC Port and therefore have no access
87 to the global NIC resources that are shared between other functions for the same NIC port.
89 A Virtual Function has basic access to the queue resources and control structures of the queues assigned to it.
90 For global resource access, a Virtual Function has to send a request to the Physical Function for that port,
91 and the Physical Function operates on the global resources on behalf of the Virtual Function.
92 For this out-of-band communication, an SR-IOV enabled NIC provides a memory buffer for each Virtual Function,
93 which is called a "Mailbox".
95 The PCIE host-interface of Intel Ethernet Switch FM10000 Series VF infrastructure
96 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
98 In a virtualized environment, the programmer can enable a maximum of *64 Virtual Functions (VF)*
99 globally per PCIE host-interface of the Intel Ethernet Switch FM10000 Series device.
100 Each VF can have a maximum of 16 queue pairs.
101 The Physical Function in host could be only configured by the Linux* fm10k driver
102 (in the case of the Linux Kernel-based Virtual Machine [KVM]), DPDK PMD PF driver doesn't support it yet.
106 * Using Linux* fm10k driver:
108 .. code-block:: console
110 rmmod fm10k (To remove the fm10k module)
111 insmod fm0k.ko max_vfs=2,2 (To enable two Virtual Functions per port)
113 Virtual Function enumeration is performed in the following sequence by the Linux* pci driver for a dual-port NIC.
114 When you enable the four Virtual Functions with the above command, the four enabled functions have a Function#
115 represented by (Bus#, Device#, Function#) in sequence starting from 0 to 3.
118 * Virtual Functions 0 and 2 belong to Physical Function 0
120 * Virtual Functions 1 and 3 belong to Physical Function 1
124 The above is an important consideration to take into account when targeting specific packets to a selected port.
126 Intel® Fortville 10/40 Gigabit Ethernet Controller VF Infrastructure
127 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
129 In a virtualized environment, the programmer can enable a maximum of *128 Virtual Functions (VF)*
130 globally per Intel® Fortville 10/40 Gigabit Ethernet Controller NIC device.
131 Each VF can have a maximum of 16 queue pairs.
132 The Physical Function in host could be either configured by the Linux* i40e driver
133 (in the case of the Linux Kernel-based Virtual Machine [KVM]) or by DPDK PMD PF driver.
134 When using both DPDK PMD PF/VF drivers, the whole NIC will be taken over by DPDK based application.
138 * Using Linux* i40e driver:
140 .. code-block:: console
142 rmmod i40e (To remove the i40e module)
143 insmod i40e.ko max_vfs=2,2 (To enable two Virtual Functions per port)
145 * Using the DPDK PMD PF i40e driver:
147 Kernel Params: iommu=pt, intel_iommu=on
149 .. code-block:: console
153 ./dpdk_nic_bind.py -b igb_uio bb:ss.f
154 echo 2 > /sys/bus/pci/devices/0000\:bb\:ss.f/max_vfs (To enable two VFs on a specific PCI device)
156 Launch the DPDK testpmd/example or your own host daemon application using the DPDK PMD library.
158 Virtual Function enumeration is performed in the following sequence by the Linux* pci driver for a dual-port NIC.
159 When you enable the four Virtual Functions with the above command, the four enabled functions have a Function#
160 represented by (Bus#, Device#, Function#) in sequence starting from 0 to 3.
163 * Virtual Functions 0 and 2 belong to Physical Function 0
165 * Virtual Functions 1 and 3 belong to Physical Function 1
169 The above is an important consideration to take into account when targeting specific packets to a selected port.
171 Intel® 82599 10 Gigabit Ethernet Controller VF Infrastructure
172 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
174 The programmer can enable a maximum of *63 Virtual Functions* and there must be *one Physical Function* per Intel® 82599
175 10 Gigabit Ethernet Controller NIC port.
176 The reason for this is that the device allows for a maximum of 128 queues per port and a virtual/physical function has to
177 have at least one queue pair (RX/TX).
178 The current implementation of the DPDK ixgbevf driver supports a single queue pair (RX/TX) per Virtual Function.
179 The Physical Function in host could be either configured by the Linux* ixgbe driver
180 (in the case of the Linux Kernel-based Virtual Machine [KVM]) or by DPDK PMD PF driver.
181 When using both DPDK PMD PF/VF drivers, the whole NIC will be taken over by DPDK based application.
185 * Using Linux* ixgbe driver:
187 .. code-block:: console
189 rmmod ixgbe (To remove the ixgbe module)
190 insmod ixgbe max_vfs=2,2 (To enable two Virtual Functions per port)
192 * Using the DPDK PMD PF ixgbe driver:
194 Kernel Params: iommu=pt, intel_iommu=on
196 .. code-block:: console
200 ./dpdk_nic_bind.py -b igb_uio bb:ss.f
201 echo 2 > /sys/bus/pci/devices/0000\:bb\:ss.f/max_vfs (To enable two VFs on a specific PCI device)
203 Launch the DPDK testpmd/example or your own host daemon application using the DPDK PMD library.
205 Virtual Function enumeration is performed in the following sequence by the Linux* pci driver for a dual-port NIC.
206 When you enable the four Virtual Functions with the above command, the four enabled functions have a Function#
207 represented by (Bus#, Device#, Function#) in sequence starting from 0 to 3.
210 * Virtual Functions 0 and 2 belong to Physical Function 0
212 * Virtual Functions 1 and 3 belong to Physical Function 1
216 The above is an important consideration to take into account when targeting specific packets to a selected port.
218 Intel® 82576 Gigabit Ethernet Controller and Intel® Ethernet Controller I350 Family VF Infrastructure
219 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
221 In a virtualized environment, an Intel® 82576 Gigabit Ethernet Controller serves up to eight virtual machines (VMs).
222 The controller has 16 TX and 16 RX queues.
223 They are generally referred to (or thought of) as queue pairs (one TX and one RX queue).
224 This gives the controller 16 queue pairs.
226 A pool is a group of queue pairs for assignment to the same VF, used for transmit and receive operations.
227 The controller has eight pools, with each pool containing two queue pairs, that is, two TX and two RX queues assigned to each VF.
229 In a virtualized environment, an Intel® Ethernet Controller I350 family device serves up to eight virtual machines (VMs) per port.
230 The eight queues can be accessed by eight different VMs if configured correctly (the i350 has 4x1GbE ports each with 8T X and 8 RX queues),
231 that means, one Transmit and one Receive queue assigned to each VF.
235 * Using Linux* igb driver:
237 .. code-block:: console
239 rmmod igb (To remove the igb module)
240 insmod igb max_vfs=2,2 (To enable two Virtual Functions per port)
242 * Using Intel® DPDK PMD PF igb driver:
244 Kernel Params: iommu=pt, intel_iommu=on modprobe uio
246 .. code-block:: console
249 ./dpdk_nic_bind.py -b igb_uio bb:ss.f
250 echo 2 > /sys/bus/pci/devices/0000\:bb\:ss.f/max_vfs (To enable two VFs on a specific pci device)
252 Launch DPDK testpmd/example or your own host daemon application using the DPDK PMD library.
254 Virtual Function enumeration is performed in the following sequence by the Linux* pci driver for a four-port NIC.
255 When you enable the four Virtual Functions with the above command, the four enabled functions have a Function#
256 represented by (Bus#, Device#, Function#) in sequence, starting from 0 to 7.
259 * Virtual Functions 0 and 4 belong to Physical Function 0
261 * Virtual Functions 1 and 5 belong to Physical Function 1
263 * Virtual Functions 2 and 6 belong to Physical Function 2
265 * Virtual Functions 3 and 7 belong to Physical Function 3
269 The above is an important consideration to take into account when targeting specific packets to a selected port.
271 Validated Hypervisors
272 ~~~~~~~~~~~~~~~~~~~~~
274 The validated hypervisor is:
276 * KVM (Kernel Virtual Machine) with Qemu, version 0.14.0
278 However, the hypervisor is bypassed to configure the Virtual Function devices using the Mailbox interface,
279 the solution is hypervisor-agnostic.
280 Xen* and VMware* (when SR- IOV is supported) will also be able to support the DPDK with Virtual Function driver support.
282 Expected Guest Operating System in Virtual Machine
283 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
285 The expected guest operating systems in a virtualized environment are:
287 * Fedora* 14 (64-bit)
289 * Ubuntu* 10.04 (64-bit)
291 For supported kernel versions, refer to the *DPDK Release Notes*.
293 Setting Up a KVM Virtual Machine Monitor
294 ----------------------------------------
296 The following describes a target environment:
298 * Host Operating System: Fedora 14
300 * Hypervisor: KVM (Kernel Virtual Machine) with Qemu version 0.14.0
302 * Guest Operating System: Fedora 14
304 * Linux Kernel Version: Refer to the *DPDK Getting Started Guide*
306 * Target Applications: l2fwd, l3fwd-vf
308 The setup procedure is as follows:
310 #. Before booting the Host OS, open **BIOS setup** and enable **Intel® VT features**.
312 #. While booting the Host OS kernel, pass the intel_iommu=on kernel command line argument using GRUB.
313 When using DPDK PF driver on host, pass the iommu=pt kernel command line argument in GRUB.
315 #. Download qemu-kvm-0.14.0 from
316 `http://sourceforge.net/projects/kvm/files/qemu-kvm/ <http://sourceforge.net/projects/kvm/files/qemu-kvm/>`_
317 and install it in the Host OS using the following steps:
319 When using a recent kernel (2.6.25+) with kvm modules included:
321 .. code-block:: console
323 tar xzf qemu-kvm-release.tar.gz
325 ./configure --prefix=/usr/local/kvm
328 sudo /sbin/modprobe kvm-intel
330 When using an older kernel, or a kernel from a distribution without the kvm modules,
331 you must download (from the same link), compile and install the modules yourself:
333 .. code-block:: console
335 tar xjf kvm-kmod-release.tar.bz2
340 sudo /sbin/modprobe kvm-intel
342 qemu-kvm installs in the /usr/local/bin directory.
344 For more details about KVM configuration and usage, please refer to:
346 `http://www.linux-kvm.org/page/HOWTO1 <http://www.linux-kvm.org/page/HOWTO1>`_.
348 #. Create a Virtual Machine and install Fedora 14 on the Virtual Machine.
349 This is referred to as the Guest Operating System (Guest OS).
351 #. Download and install the latest ixgbe driver from:
353 `http://downloadcenter.intel.com/Detail_Desc.aspx?agr=Y&DwnldID=14687 <http://downloadcenter.intel.com/Detail_Desc.aspx?agr=Y&DwnldID=14687>`_
357 When using Linux kernel ixgbe driver, unload the Linux ixgbe driver and reload it with the max_vfs=2,2 argument:
359 .. code-block:: console
362 modprobe ixgbe max_vfs=2,2
364 When using DPDK PMD PF driver, insert DPDK kernel module igb_uio and set the number of VF by sysfs max_vfs:
366 .. code-block:: console
370 ./dpdk_nic_bind.py -b igb_uio 02:00.0 02:00.1 0e:00.0 0e:00.1
371 echo 2 > /sys/bus/pci/devices/0000\:02\:00.0/max_vfs
372 echo 2 > /sys/bus/pci/devices/0000\:02\:00.1/max_vfs
373 echo 2 > /sys/bus/pci/devices/0000\:0e\:00.0/max_vfs
374 echo 2 > /sys/bus/pci/devices/0000\:0e\:00.1/max_vfs
378 You need to explicitly specify number of vfs for each port, for example,
379 in the command above, it creates two vfs for the first two ixgbe ports.
381 Let say we have a machine with four physical ixgbe ports:
392 The command above creates two vfs for device 0000:02:00.0:
394 .. code-block:: console
396 ls -alrt /sys/bus/pci/devices/0000\:02\:00.0/virt*
397 lrwxrwxrwx. 1 root root 0 Apr 13 05:40 /sys/bus/pci/devices/0000:02:00.0/virtfn1 -> ../0000:02:10.2
398 lrwxrwxrwx. 1 root root 0 Apr 13 05:40 /sys/bus/pci/devices/0000:02:00.0/virtfn0 -> ../0000:02:10.0
400 It also creates two vfs for device 0000:02:00.1:
402 .. code-block:: console
404 ls -alrt /sys/bus/pci/devices/0000\:02\:00.1/virt*
405 lrwxrwxrwx. 1 root root 0 Apr 13 05:51 /sys/bus/pci/devices/0000:02:00.1/virtfn1 -> ../0000:02:10.3
406 lrwxrwxrwx. 1 root root 0 Apr 13 05:51 /sys/bus/pci/devices/0000:02:00.1/virtfn0 -> ../0000:02:10.1
408 #. List the PCI devices connected and notice that the Host OS shows two Physical Functions (traditional ports)
409 and four Virtual Functions (two for each port).
410 This is the result of the previous step.
412 #. Insert the pci_stub module to hold the PCI devices that are freed from the default driver using the following command
413 (see http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM Section 4 for more information):
415 .. code-block:: console
417 sudo /sbin/modprobe pci-stub
419 Unbind the default driver from the PCI devices representing the Virtual Functions.
420 A script to perform this action is as follows:
422 .. code-block:: console
424 echo "8086 10ed" > /sys/bus/pci/drivers/pci-stub/new_id
425 echo 0000:08:10.0 > /sys/bus/pci/devices/0000:08:10.0/driver/unbind
426 echo 0000:08:10.0 > /sys/bus/pci/drivers/pci-stub/bind
428 where, 0000:08:10.0 belongs to the Virtual Function visible in the Host OS.
430 #. Now, start the Virtual Machine by running the following command:
432 .. code-block:: console
434 /usr/local/kvm/bin/qemu-system-x86_64 -m 4096 -smp 4 -boot c -hda lucid.qcow2 -device pci-assign,host=08:10.0
438 — -m = memory to assign
440 — -smp = number of smp cores
442 — -boot = boot option
444 — -hda = virtual disk image
446 — -device = device to attach
450 — The pci-assign,host=08:10.0 alue indicates that you want to attach a PCI device
451 to a Virtual Machine and the respective (Bus:Device.Function)
452 numbers should be passed for the Virtual Function to be attached.
454 — qemu-kvm-0.14.0 allows a maximum of four PCI devices assigned to a VM,
455 but this is qemu-kvm version dependent since qemu-kvm-0.14.1 allows a maximum of five PCI devices.
457 — qemu-system-x86_64 also has a -cpu command line option that is used to select the cpu_model
458 to emulate in a Virtual Machine. Therefore, it can be used as:
460 .. code-block:: console
462 /usr/local/kvm/bin/qemu-system-x86_64 -cpu ?
464 (to list all available cpu_models)
466 /usr/local/kvm/bin/qemu-system-x86_64 -m 4096 -cpu host -smp 4 -boot c -hda lucid.qcow2 -device pci-assign,host=08:10.0
468 (to use the same cpu_model equivalent to the host cpu)
470 For more information, please refer to: `http://wiki.qemu.org/Features/CPUModels <http://wiki.qemu.org/Features/CPUModels>`_.
472 #. Install and run DPDK host app to take over the Physical Function. Eg.
474 .. code-block:: console
476 make install T=x86_64-native-linuxapp-gcc
477 ./x86_64-native-linuxapp-gcc/app/testpmd -c f -n 4 -- -i
479 #. Finally, access the Guest OS using vncviewer with the localhost:5900 port and check the lspci command output in the Guest OS.
480 The virtual functions will be listed as available for use.
482 #. Configure and install the DPDK with an x86_64-native-linuxapp-gcc configuration on the Guest OS as normal,
483 that is, there is no change to the normal installation procedure.
485 .. code-block:: console
487 make config T=x86_64-native-linuxapp-gcc O=x86_64-native-linuxapp-gcc
488 cd x86_64-native-linuxapp-gcc
493 If you are unable to compile the DPDK and you are getting "error: CPU you selected does not support x86-64 instruction set",
494 power off the Guest OS and start the virtual machine with the correct -cpu option in the qemu- system-x86_64 command as shown in step 9.
495 You must select the best x86_64 cpu_model to emulate or you can select host option if available.
499 Run the DPDK l2fwd sample application in the Guest OS with Hugepages enabled.
500 For the expected benchmark performance, you must pin the cores from the Guest OS to the Host OS (taskset can be used to do this) and
501 you must also look at the PCI Bus layout on the board to ensure you are not running the traffic over the QPI Inteface.
505 * The Virtual Machine Manager (the Fedora package name is virt-manager) is a utility for virtual machine management
506 that can also be used to create, start, stop and delete virtual machines.
507 If this option is used, step 2 and 6 in the instructions provided will be different.
509 * virsh, a command line utility for virtual machine management,
510 can also be used to bind and unbind devices to a virtual machine in Ubuntu.
511 If this option is used, step 6 in the instructions provided will be different.
513 * The Virtual Machine Monitor (see Figure 11) is equivalent to a Host OS with KVM installed as described in the instructions.
517 **Figure 2. Performance Benchmark Setup**
519 .. image:: img/perf_benchmark.*
521 DPDK SR-IOV PMD PF/VF Driver Usage Model
522 ----------------------------------------
524 Fast Host-based Packet Processing
525 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
527 Software Defined Network (SDN) trends are demanding fast host-based packet handling.
528 In a virtualization environment,
529 the DPDK VF PMD driver performs the same throughput result as a non-VT native environment.
531 With such host instance fast packet processing, lots of services such as filtering, QoS,
532 DPI can be offloaded on the host fast path.
534 Figure 12 shows the scenario where some VMs directly communicate externally via a VFs,
535 while others connect to a virtual switch and share the same uplink bandwidth.
539 **Figure 3. Fast Host-based Packet Processing**
541 .. image:: img/fast_pkt_proc.*
543 SR-IOV (PF/VF) Approach for Inter-VM Communication
544 --------------------------------------------------
546 Inter-VM data communication is one of the traffic bottle necks in virtualization platforms.
547 SR-IOV device assignment helps a VM to attach the real device, taking advantage of the bridge in the NIC.
548 So VF-to-VF traffic within the same physical port (VM0<->VM1) have hardware acceleration.
549 However, when VF crosses physical ports (VM0<->VM2), there is no such hardware bridge.
550 In this case, the DPDK PMD PF driver provides host forwarding between such VMs.
552 Figure 13 shows an example.
553 In this case an update of the MAC address lookup tables in both the NIC and host DPDK application is required.
555 In the NIC, writing the destination of a MAC address belongs to another cross device VM to the PF specific pool.
556 So when a packet comes in, its destination MAC address will match and forward to the host DPDK PMD application.
558 In the host DPDK application, the behavior is similar to L2 forwarding,
559 that is, the packet is forwarded to the correct PF pool.
560 The SR-IOV NIC switch forwards the packet to a specific VM according to the MAC destination address
561 which belongs to the destination VF on the VM.
565 **Figure 4. Inter-VM Communication**
567 .. image:: img/inter_vm_comms.*