1 # Copyright 2015 Intel Corporation.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
15 """Automation of QEMU hypervisor with direct access to host NICs via
23 from conf import settings as S
24 from vnfs.qemu.qemu import IVnfQemu
25 from tools import tasks
26 from tools.module_manager import ModuleManager
28 _MODULE_MANAGER = ModuleManager()
29 _RTE_PCI_TOOL = os.path.join(S.getValue('RTE_SDK'), 'tools', 'dpdk_nic_bind.py')
31 class QemuPciPassthrough(IVnfQemu):
33 Control an instance of QEMU with direct access to the host network devices
37 Initialization function.
39 super(QemuPciPassthrough, self).__init__()
40 self._logger = logging.getLogger(__name__)
41 self._nics = S.getValue('NICS')
43 # in case of SRIOV and PCI passthrough we must ensure, that MAC addresses are swapped
44 if S.getValue('SRIOV_ENABLED') and not self._testpmd_fwd_mode.startswith('mac'):
45 self._logger.info("SRIOV detected, forwarding mode of testpmd was changed from '%s' to '%s'",
46 self._testpmd_fwd_mode, 'mac_retry')
47 self._testpmd_fwd_mode = 'mac_retry'
49 for nic in self._nics:
50 self._cmd += ['-device', 'vfio-pci,host=' + nic['pci']]
54 Start QEMU instance, bind host NICs to vfio-pci driver
57 _MODULE_MANAGER.insert_modules(['vfio-pci'])
59 # bind every interface to vfio-pci driver
61 nics_list = list(tmp_nic['pci'] for tmp_nic in self._nics)
62 tasks.run_task(['sudo', _RTE_PCI_TOOL, '--bind=vfio-pci'] + nics_list,
63 self._logger, 'Binding NICs %s...' % nics_list, True)
65 except subprocess.CalledProcessError:
66 self._logger.error('Unable to bind NICs %s', self._nics)
68 super(QemuPciPassthrough, self).start()
72 Stop QEMU instance, bind host NICs to the original driver
74 super(QemuPciPassthrough, self).stop()
76 # bind original driver to every interface
77 for nic in self._nics:
80 tasks.run_task(['sudo', _RTE_PCI_TOOL, '--bind=' + nic['driver'], nic['pci']],
81 self._logger, 'Binding NIC %s...' % nic['pci'], True)
83 except subprocess.CalledProcessError:
84 self._logger.error('Unable to bind NIC %s to driver %s', nic['pci'], nic['driver'])
86 # unload vfio-pci driver
87 _MODULE_MANAGER.remove_modules()