diff --git a/nova/tests/unit/virt/libvirt/test_vif.py b/nova/tests/unit/virt/libvirt/test_vif.py index 260148188ce3..1955dfb33143 100644 --- a/nova/tests/unit/virt/libvirt/test_vif.py +++ b/nova/tests/unit/virt/libvirt/test_vif.py @@ -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']) diff --git a/nova/virt/libvirt/vif.py b/nova/virt/libvirt/vif.py index 4b846b6c2bb9..08039ce9fad0 100644 --- a/nova/virt/libvirt/vif.py +++ b/nova/virt/libvirt/vif.py @@ -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)