Libvirt: do not set MAC when unplugging macvtap VF

- This change updates unplug_hw_veb to reset the
  VF MAC when unplugging macvtap SR-IOV vifs.
  Doing this will prevent a network partition to
  be formed as the VM's MAC is no longer retained on
  the VF after the vif has been unplugged, allowing
  traffic with the VFs former MAC to be transmitted
  on the PF in case it is reused in another host.

- This change corrects an outdated comment to reflect
  that network drivers allow setting a VF's MAC to zero
  via ip tool.
  It should be noted that setting the VF's netdev MAC to zero
  is not allowed and thus ip tool return code in this scenario
  is ignored in linux_utils.set_vf_interface_vlan().
  We also leave a TODO to futher clean up this code later in Stein.

Change-Id: I4f78f3cc412d7ec59456aea915a1ebfc8b27681f
Closes-Bug: #1808252
This commit is contained in:
Sean Mooney 2018-12-13 00:56:44 +00:00 committed by Adrian Chiris
parent ee57c92e8b
commit 9e77c3d3bb
2 changed files with 16 additions and 14 deletions

View File

@ -975,6 +975,8 @@ class LibvirtVifTestCase(test.NoDBTestCase):
mock_get_ifname.side_effect = ['eth1', 'eth13']
exit_code = [0, 2, 254]
port_state = 'up' if vlan > 0 else 'down'
mac = ('00:00:00:00:00:00' if op.__name__ == 'unplug'
else self.vif_hw_veb_macvtap['address'])
calls = {
'get_ifname':
[mock.call(self.vif_hw_veb_macvtap['profile']['pci_slot'],
@ -982,15 +984,10 @@ class LibvirtVifTestCase(test.NoDBTestCase):
mock.call(self.vif_hw_veb_macvtap['profile']['pci_slot'])],
'get_vf_num':
[mock.call(self.vif_hw_veb_macvtap['profile']['pci_slot'])],
'execute': [mock.call('ip', 'link', 'set', 'eth1',
'vf', 1, 'mac',
self.vif_hw_veb_macvtap['address'],
'vlan', vlan,
run_as_root=True,
'execute': [mock.call('ip', 'link', 'set', 'eth1', 'vf', 1,
'mac', mac, 'vlan', vlan, run_as_root=True,
check_exit_code=exit_code)],
'set_macaddr': [mock.call('eth13',
self.vif_hw_veb_macvtap['address'],
port_state=port_state)]
'set_macaddr': [mock.call('eth13', mac, port_state=port_state)]
}
op(self.instance, self.vif_hw_veb_macvtap)
mock_get_ifname.assert_has_calls(calls['get_ifname'])

View File

@ -765,14 +765,19 @@ 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
# TODO(sean-k-mooney): remove in Train after backporting 0 mac
# change as this should no longer be needed with libvirt >= 3.2.0.
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
# the same VF will not be affected by the existing MAC.
# NOTE(sean-k-mooney): Retaining the vm mac on the vf
# after unplugging the vif prevents the PF from transmitting
# a packet with that destination address. This would create a
# a network partition in the event a vm is migrated or the neuton
# port is reused for another vm before the VF is reused.
# The ip utility accepts the MAC 00:00:00:00:00:00 which can
# be used to reset the VF mac when no longer in use by a vm.
# As such we hardcode the 00:00:00:00:00:00 mac.
linux_net_utils.set_vf_interface_vlan(vif['profile']['pci_slot'],
mac_addr=vif['address'])
mac_addr='00:00:00:00:00:00')
elif vif['vnic_type'] == network_model.VNIC_TYPE_DIRECT:
if "trusted" in vif['profile']:
linux_net.set_vf_trusted(vif['profile']['pci_slot'], False)