libvirt: set vlan tag for macvtap on SR-IOV VFs

Starting from version 1.3.5, Libvirt allows to set a vlan tag for macvtap
passthrough mode on SR-IOV VFs. Libvirt also removes any vlan tags that
has been set externally, by the ip link command.

In order to support the older libvirt versions, this code will make
the behaviour backward compatible by checking the libvirt version.
This can be completely removed once the minimum libvirt version will increase.

NOTE(mriedem): There is a slight modification in the test in Newton
because 6a6457b5a6 is not in Newton.

Change-Id: Ia14e78e0eda81b8d29d5aa6e07e68777665d0710
Closes-Bug: #1657035
(cherry picked from commit bf3ba76a91)
(cherry picked from commit ce513278f1)
This commit is contained in:
Vladik Romanovsky 2017-01-17 04:56:47 -05:00 committed by Matt Riedemann
parent d0ee248bab
commit adec640bfa
3 changed files with 33 additions and 3 deletions

View File

@ -1145,7 +1145,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), int(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)

View File

@ -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

View File

@ -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):
@ -318,6 +320,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
@ -619,6 +626,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'],
@ -908,6 +917,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