diff --git a/nova/tests/unit/virt/libvirt/test_vif.py b/nova/tests/unit/virt/libvirt/test_vif.py index 24fe95a98efb..8d3f5e9d7d3b 100644 --- a/nova/tests/unit/virt/libvirt/test_vif.py +++ b/nova/tests/unit/virt/libvirt/test_vif.py @@ -1206,7 +1206,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 0d4a6efe6742..67514c931bb6 100644 --- a/nova/virt/libvirt/designer.py +++ b/nova/virt/libvirt/designer.py @@ -107,14 +107,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 094a2a1dad2c..e3952634d880 100644 --- a/nova/virt/libvirt/vif.py +++ b/nova/virt/libvirt/vif.py @@ -46,6 +46,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): @@ -327,6 +329,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 @@ -636,6 +643,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'], @@ -859,6 +868,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