From 2c3e794febc235de5a927e9569c7da86820f256c Mon Sep 17 00:00:00 2001 From: Moshe Levi Date: Sun, 31 May 2015 17:16:48 +0300 Subject: [PATCH] Adding support for InfiniBand SR-IOV vif type Implements: blueprint vif-driver-ib-passthrough Change-Id: I1294fb1c160e8307c4b5dd555bc6415bf7f77f8a --- nova/network/model.py | 1 + nova/tests/unit/virt/libvirt/test_vif.py | 28 +++++++++++++++-- nova/virt/libvirt/designer.py | 8 +++++ nova/virt/libvirt/vif.py | 39 ++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 2 deletions(-) diff --git a/nova/network/model.py b/nova/network/model.py index 99ab96db987e..f6ecbacba171 100644 --- a/nova/network/model.py +++ b/nova/network/model.py @@ -38,6 +38,7 @@ VIF_TYPE_802_QBG = '802.1qbg' VIF_TYPE_802_QBH = '802.1qbh' VIF_TYPE_HW_VEB = 'hw_veb' VIF_TYPE_MLNX_DIRECT = 'mlnx_direct' +VIF_TYPE_IB_HOSTDEV = 'ib_hostdev' VIF_TYPE_MIDONET = 'midonet' VIF_TYPE_VHOSTUSER = 'vhostuser' VIF_TYPE_VROUTER = 'vrouter' diff --git a/nova/tests/unit/virt/libvirt/test_vif.py b/nova/tests/unit/virt/libvirt/test_vif.py index f74d8d30a5dc..c1a77fc5a46d 100644 --- a/nova/tests/unit/virt/libvirt/test_vif.py +++ b/nova/tests/unit/virt/libvirt/test_vif.py @@ -255,6 +255,18 @@ class LibvirtVifTestCase(test.NoDBTestCase): type=network_model.VIF_TYPE_MLNX_DIRECT, devname='tap-xxx-yyy-zzz') + vif_ib_hostdev = network_model.VIF(id='vif-xxx-yyy-zzz', + address='ca:fe:de:ad:be:ef', + network=network_8021, + type=network_model.VIF_TYPE_IB_HOSTDEV, + vnic_type=network_model.VNIC_TYPE_DIRECT, + ovs_interfaceid=None, + details={ + network_model.VIF_DETAILS_VLAN: '100'}, + profile={'pci_vendor_info': '1137:0043', + 'pci_slot': '0000:0a:00.1', + 'physical_network': 'phynet1'}) + vif_mlnx_net = network_model.VIF(id='vif-xxx-yyy-zzz', address='ca:fe:de:ad:be:ef', network=network_mlnx, @@ -395,9 +407,13 @@ class LibvirtVifTestCase(test.NoDBTestCase): def _assertTypeAndPciEquals(self, node, type, vif): self.assertEqual(node.get("type"), type) + self._assertPciEqual(node, vif, type="pci") + + def _assertPciEqual(self, node, vif, type=None): address = node.find("source").find("address") - addr_type = address.get("type") - self.assertEqual("pci", addr_type) + if type: + addr_type = address.get("type") + self.assertEqual(type, addr_type) pci_slot = "%(domain)s:%(bus)s:%(slot)s.%(func)s" % { 'domain': address.get("domain")[2:], 'bus': address.get("bus")[2:], @@ -1019,6 +1035,14 @@ class LibvirtVifTestCase(test.NoDBTestCase): self._assertMacEquals(node, self.vif_mlnx) self._assertModel(xml, network_model.VIF_MODEL_VIRTIO) + def test_ib_hostdev_driver(self): + d = vif.LibvirtGenericVIFDriver() + xml = self._get_instance_xml(d, self.vif_ib_hostdev) + doc = etree.fromstring(xml) + node = doc.findall('./devices/hostdev')[0] + self.assertEqual(1, len(node)) + self._assertPciEqual(node, self.vif_ib_hostdev) + def test_midonet_ethernet_vif_driver(self): d = vif.LibvirtGenericVIFDriver() self.flags(firewall_driver="nova.virt.firewall.NoopFirewallDriver") diff --git a/nova/virt/libvirt/designer.py b/nova/virt/libvirt/designer.py index b03c5df48d68..17749ad9f101 100644 --- a/nova/virt/libvirt/designer.py +++ b/nova/virt/libvirt/designer.py @@ -133,6 +133,14 @@ def set_vif_host_backend_hw_veb(conf, net_type, devname, vlan, conf.target_dev = tapname +def set_vif_host_backend_ib_hostdev_config(conf, pci_slot): + """Populate a LibvirtConfigGuestInterface instance + with hostdev Interface. + """ + conf.domain, conf.bus, conf.slot, conf.function = ( + pci_utils.get_pci_address_fields(pci_slot)) + + def set_vif_host_backend_direct_config(conf, devname, mode="passthrough"): """Populate a LibvirtConfigGuestInterface instance with direct Interface. diff --git a/nova/virt/libvirt/vif.py b/nova/virt/libvirt/vif.py index 01b139927463..3667d0613ed9 100644 --- a/nova/virt/libvirt/vif.py +++ b/nova/virt/libvirt/vif.py @@ -385,6 +385,13 @@ class LibvirtGenericVIFDriver(object): designer.set_vif_host_backend_vhostuser_config(conf, mode, sock_path) return conf + def get_config_ib_hostdev(self, instance, vif, image_meta, + inst_type, virt_type): + conf = vconfig.LibvirtConfigGuestHostdevPCI() + pci_slot = vif['profile']['pci_slot'] + designer.set_vif_host_backend_ib_hostdev_config(conf, pci_slot) + return conf + def get_config_vrouter(self, instance, vif, image_meta, inst_type, virt_type): conf = self.get_base_config(instance, vif, image_meta, @@ -527,6 +534,25 @@ class LibvirtGenericVIFDriver(object): except processutils.ProcessExecutionError: LOG.exception(_LE("Failed while plugging vif"), instance=instance) + def plug_ib_hostdev(self, instance, vif): + fabric = vif.get_physical_network() + if not fabric: + raise exception.NetworkMissingPhysicalNetwork( + network_uuid=vif['network']['id'] + ) + pci_slot = vif['profile']['pci_slot'] + device_id = instance['uuid'] + vnic_mac = vif['address'] + try: + utils.execute('ebrctl', 'add-port', vnic_mac, device_id, + fabric, network_model.VIF_TYPE_IB_HOSTDEV, + pci_slot, run_as_root=True) + except processutils.ProcessExecutionError: + LOG.exception( + _LE("Failed while plugging ib hostdev vif"), + instance=instance + ) + def plug_802qbg(self, instance, vif): pass @@ -750,6 +776,19 @@ class LibvirtGenericVIFDriver(object): LOG.exception(_LE("Failed while unplugging vif"), instance=instance) + def unplug_ib_hostdev(self, instance, vif): + fabric = vif.get_physical_network() + if not fabric: + raise exception.NetworkMissingPhysicalNetwork( + network_uuid=vif['network']['id'] + ) + vnic_mac = vif['address'] + try: + utils.execute('ebrctl', 'del-port', fabric, vnic_mac, + run_as_root=True) + except Exception: + LOG.exception(_LE("Failed while unplugging ib hostdev vif")) + def unplug_802qbg(self, instance, vif): pass