diff --git a/nova/tests/unit/virt/libvirt/test_vif.py b/nova/tests/unit/virt/libvirt/test_vif.py index 9ea0cecfb930..be96bb9e6f92 100644 --- a/nova/tests/unit/virt/libvirt/test_vif.py +++ b/nova/tests/unit/virt/libvirt/test_vif.py @@ -1243,7 +1243,26 @@ class LibvirtVifTestCase(test.NoDBTestCase): @mock.patch.object(pci_utils, 'get_ifname_by_pci_address', return_value='eth1') - def test_hw_veb_driver_macvtap(self, mock_get_ifname): + @mock.patch.object(host.Host, "has_min_version", return_value=True) + def test_hw_veb_driver_macvtap(self, ver_mock, mock_get_ifname): + d = vif.LibvirtGenericVIFDriver() + xml = self._get_instance_xml(d, self.vif_hw_veb_macvtap) + node = self._get_node(xml) + self.assertEqual(node.get("type"), "direct") + self._assertTypeEquals(node, "direct", "source", + "dev", "eth1") + self._assertTypeEquals(node, "direct", "source", + "mode", "passthrough") + self._assertMacEquals(node, self.vif_hw_veb_macvtap) + vlan = node.find("vlan").find("tag").get("id") + vlan_want = self.vif_hw_veb["details"]["vlan"] + self.assertEqual(int(vlan), vlan_want) + + @mock.patch.object(pci_utils, 'get_ifname_by_pci_address', + return_value='eth1') + @mock.patch.object(host.Host, "has_min_version", return_value=False) + def test_hw_veb_driver_macvtap_pre_vlan_support(self, ver_mock, + mock_get_ifname): d = vif.LibvirtGenericVIFDriver() xml = self._get_instance_xml(d, self.vif_hw_veb_macvtap) node = self._get_node(xml) diff --git a/nova/virt/libvirt/designer.py b/nova/virt/libvirt/designer.py index df22f02fd616..f7d0b8e692fa 100644 --- a/nova/virt/libvirt/designer.py +++ b/nova/virt/libvirt/designer.py @@ -108,14 +108,14 @@ def set_vif_host_backend_hw_veb(conf, net_type, devname, vlan, """ conf.net_type = net_type + conf.vlan = vlan if net_type == 'direct': conf.source_mode = 'passthrough' conf.source_dev = pci_utils.get_ifname_by_pci_address(devname) conf.driver_name = 'vhost' - else: + else: # net_type == network_model.VNIC_TYPE_DIRECT conf.source_dev = devname conf.model = None - conf.vlan = vlan if tapname: conf.target_dev = tapname diff --git a/nova/virt/libvirt/vif.py b/nova/virt/libvirt/vif.py index 6ab2fa7c57d6..536a938e8bce 100644 --- a/nova/virt/libvirt/vif.py +++ b/nova/virt/libvirt/vif.py @@ -45,6 +45,8 @@ CONF = nova.conf.CONF # vhostuser queues support MIN_LIBVIRT_VHOSTUSER_MQ = (1, 2, 17) +# vlan tag for macvtap passthrough mode on SRIOV VFs +MIN_LIBVIRT_MACVTAP_PASSTHROUGH_VLAN = (1, 3, 5) def is_vif_model_valid_for_virt(virt_type, vif_model): @@ -325,6 +327,11 @@ class LibvirtGenericVIFDriver(object): conf, net_type, profile['pci_slot'], vif_details[network_model.VIF_DETAILS_VLAN]) + # NOTE(vladikr): Not setting vlan tags for macvtap on SR-IOV VFs + # as vlan tag is not supported in Libvirt until version 1.3.5 + if (vif['vnic_type'] == network_model.VNIC_TYPE_MACVTAP and not + host.has_min_version(MIN_LIBVIRT_MACVTAP_PASSTHROUGH_VLAN)): + conf.vlan = None designer.set_vif_bandwidth_config(conf, inst_type) return conf @@ -634,6 +641,8 @@ class LibvirtGenericVIFDriver(object): pass def plug_hw_veb(self, instance, vif): + # TODO(vladikr): This code can be removed once the minimum version of + # Libvirt is incleased above 1.3.5, as vlan will be set by libvirt if vif['vnic_type'] == network_model.VNIC_TYPE_MACVTAP: linux_net.set_vf_interface_vlan( vif['profile']['pci_slot'], @@ -892,6 +901,8 @@ class LibvirtGenericVIFDriver(object): pass def unplug_hw_veb(self, instance, vif): + # TODO(vladikr): This code can be removed once the minimum version of + # Libvirt is incleased above 1.3.5, as vlan will be set by libvirt if vif['vnic_type'] == network_model.VNIC_TYPE_MACVTAP: # The ip utility doesn't accept the MAC 00:00:00:00:00:00. # Therefore, keep the MAC unchanged. Later operations on