Merge "Reduce IP link show calls for SR-IOV scan loop"
This commit is contained in:
commit
499f3c6d56
@ -63,7 +63,7 @@ class PciOsWrapper(object):
|
|||||||
return vf_list
|
return vf_list
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def is_assigned_vf(cls, dev_name, vf_index):
|
def is_assigned_vf(cls, dev_name, vf_index, ip_link_show_output):
|
||||||
"""Check if VF is assigned.
|
"""Check if VF is assigned.
|
||||||
|
|
||||||
Checks if a given vf index of a given device name is assigned
|
Checks if a given vf index of a given device name is assigned
|
||||||
@ -73,6 +73,7 @@ class PciOsWrapper(object):
|
|||||||
Macvtap VF: macvtap@<vf interface> interface exists in ip link show
|
Macvtap VF: macvtap@<vf interface> interface exists in ip link show
|
||||||
@param dev_name: pf network device name
|
@param dev_name: pf network device name
|
||||||
@param vf_index: vf index
|
@param vf_index: vf index
|
||||||
|
@param ip_link_show_output: 'ip link show' output
|
||||||
"""
|
"""
|
||||||
path = cls.PCI_PATH % (dev_name, vf_index)
|
path = cls.PCI_PATH % (dev_name, vf_index)
|
||||||
|
|
||||||
@ -86,7 +87,8 @@ class PciOsWrapper(object):
|
|||||||
# for macvtap interface. Therefore we workaround it
|
# for macvtap interface. Therefore we workaround it
|
||||||
# by parsing ip link show and checking if macvtap interface exists
|
# by parsing ip link show and checking if macvtap interface exists
|
||||||
for ifname in ifname_list:
|
for ifname in ifname_list:
|
||||||
if pci_lib.PciDeviceIPWrapper.is_macvtap_assigned(ifname):
|
if pci_lib.PciDeviceIPWrapper.is_macvtap_assigned(
|
||||||
|
ifname, ip_link_show_output):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -138,8 +140,9 @@ class EmbSwitch(object):
|
|||||||
"""
|
"""
|
||||||
vf_to_pci_slot_mapping = {}
|
vf_to_pci_slot_mapping = {}
|
||||||
assigned_devices_info = []
|
assigned_devices_info = []
|
||||||
|
ls = self.pci_dev_wrapper.link_show()
|
||||||
for pci_slot, vf_index in self.pci_slot_map.items():
|
for pci_slot, vf_index in self.pci_slot_map.items():
|
||||||
if not PciOsWrapper.is_assigned_vf(self.dev_name, vf_index):
|
if not PciOsWrapper.is_assigned_vf(self.dev_name, vf_index, ls):
|
||||||
continue
|
continue
|
||||||
vf_to_pci_slot_mapping[vf_index] = pci_slot
|
vf_to_pci_slot_mapping[vf_index] = pci_slot
|
||||||
if vf_to_pci_slot_mapping:
|
if vf_to_pci_slot_mapping:
|
||||||
@ -230,7 +233,8 @@ class EmbSwitch(object):
|
|||||||
vf_index = self.pci_slot_map.get(pci_slot)
|
vf_index = self.pci_slot_map.get(pci_slot)
|
||||||
mac = None
|
mac = None
|
||||||
if vf_index is not None:
|
if vf_index is not None:
|
||||||
if PciOsWrapper.is_assigned_vf(self.dev_name, vf_index):
|
ls = pci_lib.PciDeviceIPWrapper.link_show()
|
||||||
|
if PciOsWrapper.is_assigned_vf(self.dev_name, vf_index, ls):
|
||||||
macs = self.pci_dev_wrapper.get_assigned_macs([vf_index])
|
macs = self.pci_dev_wrapper.get_assigned_macs([vf_index])
|
||||||
mac = macs.get(vf_index)
|
mac = macs.get(vf_index)
|
||||||
return mac
|
return mac
|
||||||
|
@ -186,22 +186,26 @@ class PciDeviceIPWrapper(ip_lib.IPWrapper):
|
|||||||
return vf_details
|
return vf_details
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def is_macvtap_assigned(cls, ifname):
|
def link_show(cls):
|
||||||
|
try:
|
||||||
|
out = cls._execute([], "link", ("show", ), run_as_root=True)
|
||||||
|
except Exception as e:
|
||||||
|
LOG.error(_LE("Failed executing ip command: %s"), e)
|
||||||
|
raise exc.IpCommandError(reason=e)
|
||||||
|
return out
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def is_macvtap_assigned(cls, ifname, ip_link_show_output):
|
||||||
"""Check if vf has macvtap interface assigned
|
"""Check if vf has macvtap interface assigned
|
||||||
|
|
||||||
Parses the output of ip link show command and checks
|
Parses the output of ip link show command and checks
|
||||||
if macvtap[0-9]+@<vf interface> regex matches the
|
if macvtap[0-9]+@<vf interface> regex matches the
|
||||||
output.
|
output.
|
||||||
@param ifname: vf interface name
|
@param ifname: vf interface name
|
||||||
|
@param ip_link_show_output: 'ip link show' result to parse
|
||||||
@return: True on match otherwise False
|
@return: True on match otherwise False
|
||||||
"""
|
"""
|
||||||
try:
|
for line in ip_link_show_output.splitlines():
|
||||||
out = cls._execute([], "link", ("show", ), run_as_root=True)
|
|
||||||
except Exception as e:
|
|
||||||
LOG.error(_LE("Failed executing ip command: %s"), e)
|
|
||||||
raise exc.IpCommandError(reason=e)
|
|
||||||
|
|
||||||
for line in out.splitlines():
|
|
||||||
pattern_match = cls.MACVTAP_REG_EX.match(line)
|
pattern_match = cls.MACVTAP_REG_EX.match(line)
|
||||||
if pattern_match:
|
if pattern_match:
|
||||||
if ifname == pattern_match.group('vf_interface'):
|
if ifname == pattern_match.group('vf_interface'):
|
||||||
|
@ -99,7 +99,10 @@ class TestESwitchManagerApi(base.BaseTestCase):
|
|||||||
def test_get_assigned_devices_info(self):
|
def test_get_assigned_devices_info(self):
|
||||||
with mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
|
with mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
|
||||||
"eswitch_manager.EmbSwitch.get_assigned_devices_info",
|
"eswitch_manager.EmbSwitch.get_assigned_devices_info",
|
||||||
return_value=[(self.ASSIGNED_MAC, self.PCI_SLOT)]):
|
return_value=[(self.ASSIGNED_MAC, self.PCI_SLOT)]),\
|
||||||
|
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
|
||||||
|
"pci_lib.PciDeviceIPWrapper.link_show",
|
||||||
|
return_value=''):
|
||||||
result = self.eswitch_mgr.get_assigned_devices_info()
|
result = self.eswitch_mgr.get_assigned_devices_info()
|
||||||
self.assertIn(self.ASSIGNED_MAC, list(result)[0])
|
self.assertIn(self.ASSIGNED_MAC, list(result)[0])
|
||||||
self.assertIn(self.PCI_SLOT, list(result)[0])
|
self.assertIn(self.PCI_SLOT, list(result)[0])
|
||||||
@ -267,7 +270,10 @@ class TestESwitchManagerApi(base.BaseTestCase):
|
|||||||
as set_rate_mock, \
|
as set_rate_mock, \
|
||||||
mock.patch('neutron.plugins.ml2.drivers.mech_sriov.agent.'
|
mock.patch('neutron.plugins.ml2.drivers.mech_sriov.agent.'
|
||||||
'pci_lib.PciDeviceIPWrapper.get_assigned_macs',
|
'pci_lib.PciDeviceIPWrapper.get_assigned_macs',
|
||||||
return_value=mac_address):
|
return_value=mac_address), \
|
||||||
|
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
|
||||||
|
"pci_lib.PciDeviceIPWrapper.link_show",
|
||||||
|
return_value=''):
|
||||||
self.eswitch_mgr._clear_rate(pci_slot, rate_type)
|
self.eswitch_mgr._clear_rate(pci_slot, rate_type)
|
||||||
if passed:
|
if passed:
|
||||||
set_rate_mock.assert_called_once_with(pci_slot, rate_type, 0)
|
set_rate_mock.assert_called_once_with(pci_slot, rate_type, 0)
|
||||||
@ -335,7 +341,10 @@ class TestEmbSwitch(base.BaseTestCase):
|
|||||||
return_value={0: self.ASSIGNED_MAC}),\
|
return_value={0: self.ASSIGNED_MAC}),\
|
||||||
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
|
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
|
||||||
"eswitch_manager.PciOsWrapper.is_assigned_vf",
|
"eswitch_manager.PciOsWrapper.is_assigned_vf",
|
||||||
return_value=True):
|
return_value=True), \
|
||||||
|
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
|
||||||
|
"pci_lib.PciDeviceIPWrapper.link_show",
|
||||||
|
return_value=''):
|
||||||
result = emb_switch.get_assigned_devices_info()
|
result = emb_switch.get_assigned_devices_info()
|
||||||
self.assertIn(self.ASSIGNED_MAC, list(result)[0])
|
self.assertIn(self.ASSIGNED_MAC, list(result)[0])
|
||||||
self.assertIn(self.PCI_SLOT, list(result)[0])
|
self.assertIn(self.PCI_SLOT, list(result)[0])
|
||||||
@ -350,7 +359,10 @@ class TestEmbSwitch(base.BaseTestCase):
|
|||||||
return_value=self.VF_TO_MAC_MAPPING),\
|
return_value=self.VF_TO_MAC_MAPPING),\
|
||||||
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
|
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
|
||||||
"eswitch_manager.PciOsWrapper.is_assigned_vf",
|
"eswitch_manager.PciOsWrapper.is_assigned_vf",
|
||||||
return_value=True):
|
return_value=True),\
|
||||||
|
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
|
||||||
|
"pci_lib.PciDeviceIPWrapper.link_show",
|
||||||
|
return_value=''):
|
||||||
devices_info = emb_switch.get_assigned_devices_info()
|
devices_info = emb_switch.get_assigned_devices_info()
|
||||||
for device_info in devices_info:
|
for device_info in devices_info:
|
||||||
mac = device_info[0]
|
mac = device_info[0]
|
||||||
@ -361,7 +373,10 @@ class TestEmbSwitch(base.BaseTestCase):
|
|||||||
def test_get_assigned_devices_empty(self):
|
def test_get_assigned_devices_empty(self):
|
||||||
with mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
|
with mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
|
||||||
"eswitch_manager.PciOsWrapper.is_assigned_vf",
|
"eswitch_manager.PciOsWrapper.is_assigned_vf",
|
||||||
return_value=False):
|
return_value=False), \
|
||||||
|
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
|
||||||
|
"pci_lib.PciDeviceIPWrapper.link_show",
|
||||||
|
return_value=''):
|
||||||
result = self.emb_switch.get_assigned_devices_info()
|
result = self.emb_switch.get_assigned_devices_info()
|
||||||
self.assertFalse(result)
|
self.assertFalse(result)
|
||||||
|
|
||||||
@ -478,7 +493,10 @@ class TestEmbSwitch(base.BaseTestCase):
|
|||||||
return_value={0: self.ASSIGNED_MAC}),\
|
return_value={0: self.ASSIGNED_MAC}),\
|
||||||
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
|
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
|
||||||
"eswitch_manager.PciOsWrapper.is_assigned_vf",
|
"eswitch_manager.PciOsWrapper.is_assigned_vf",
|
||||||
return_value=True):
|
return_value=True),\
|
||||||
|
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
|
||||||
|
"pci_lib.PciDeviceIPWrapper.link_show",
|
||||||
|
return_value=''):
|
||||||
result = self.emb_switch.get_pci_device(self.PCI_SLOT)
|
result = self.emb_switch.get_pci_device(self.PCI_SLOT)
|
||||||
self.assertEqual(self.ASSIGNED_MAC, result)
|
self.assertEqual(self.ASSIGNED_MAC, result)
|
||||||
|
|
||||||
@ -556,21 +574,21 @@ class TestPciOsWrapper(base.BaseTestCase):
|
|||||||
@mock.patch("os.listdir", side_effect=OSError())
|
@mock.patch("os.listdir", side_effect=OSError())
|
||||||
def test_is_assigned_vf_true(self, *args):
|
def test_is_assigned_vf_true(self, *args):
|
||||||
self.assertTrue(esm.PciOsWrapper.is_assigned_vf(
|
self.assertTrue(esm.PciOsWrapper.is_assigned_vf(
|
||||||
self.DEV_NAME, self.VF_INDEX))
|
self.DEV_NAME, self.VF_INDEX, ''))
|
||||||
|
|
||||||
@mock.patch("os.listdir", return_value=[DEV_NAME, "eth1"])
|
@mock.patch("os.listdir", return_value=[DEV_NAME, "eth1"])
|
||||||
@mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent.pci_lib."
|
@mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent.pci_lib."
|
||||||
"PciDeviceIPWrapper.is_macvtap_assigned", return_value=False)
|
"PciDeviceIPWrapper.is_macvtap_assigned", return_value=False)
|
||||||
def test_is_assigned_vf_false(self, *args):
|
def test_is_assigned_vf_false(self, *args):
|
||||||
self.assertFalse(esm.PciOsWrapper.is_assigned_vf(
|
self.assertFalse(esm.PciOsWrapper.is_assigned_vf(
|
||||||
self.DEV_NAME, self.VF_INDEX))
|
self.DEV_NAME, self.VF_INDEX, ''))
|
||||||
|
|
||||||
@mock.patch("os.listdir", return_value=["eth0", "eth1"])
|
@mock.patch("os.listdir", return_value=["eth0", "eth1"])
|
||||||
@mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent.pci_lib."
|
@mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent.pci_lib."
|
||||||
"PciDeviceIPWrapper.is_macvtap_assigned", return_value=True)
|
"PciDeviceIPWrapper.is_macvtap_assigned", return_value=True)
|
||||||
def test_is_assigned_vf_macvtap(
|
def test_is_assigned_vf_macvtap(
|
||||||
self, mock_is_macvtap_assigned, *args):
|
self, mock_is_macvtap_assigned, *args):
|
||||||
esm.PciOsWrapper.is_assigned_vf(self.DEV_NAME, self.VF_INDEX)
|
esm.PciOsWrapper.is_assigned_vf(self.DEV_NAME, self.VF_INDEX, '')
|
||||||
mock_is_macvtap_assigned.called_with(self.VF_INDEX, "eth0")
|
mock_is_macvtap_assigned.called_with(self.VF_INDEX, "eth0")
|
||||||
|
|
||||||
@mock.patch("os.listdir", side_effect=OSError())
|
@mock.patch("os.listdir", side_effect=OSError())
|
||||||
@ -578,5 +596,5 @@ class TestPciOsWrapper(base.BaseTestCase):
|
|||||||
"PciDeviceIPWrapper.is_macvtap_assigned")
|
"PciDeviceIPWrapper.is_macvtap_assigned")
|
||||||
def test_is_assigned_vf_macvtap_failure(
|
def test_is_assigned_vf_macvtap_failure(
|
||||||
self, mock_is_macvtap_assigned, *args):
|
self, mock_is_macvtap_assigned, *args):
|
||||||
esm.PciOsWrapper.is_assigned_vf(self.DEV_NAME, self.VF_INDEX)
|
esm.PciOsWrapper.is_assigned_vf(self.DEV_NAME, self.VF_INDEX, '')
|
||||||
self.assertFalse(mock_is_macvtap_assigned.called)
|
self.assertFalse(mock_is_macvtap_assigned.called)
|
||||||
|
@ -176,30 +176,20 @@ class TestPciLib(base.BaseTestCase):
|
|||||||
state=True)
|
state=True)
|
||||||
|
|
||||||
def test_is_macvtap_assigned(self):
|
def test_is_macvtap_assigned(self):
|
||||||
with mock.patch.object(pci_lib.PciDeviceIPWrapper,
|
self.assertTrue(pci_lib.PciDeviceIPWrapper.is_macvtap_assigned(
|
||||||
"_execute") as mock_exec:
|
'enp129s0f1', self.IP_LINK_SHOW_WITH_MACVTAP))
|
||||||
mock_exec.return_value = self.IP_LINK_SHOW_WITH_MACVTAP
|
|
||||||
self.assertTrue(
|
|
||||||
pci_lib.PciDeviceIPWrapper.is_macvtap_assigned('enp129s0f1'))
|
|
||||||
|
|
||||||
def test_is_macvtap_assigned_interface_with_underscore(self):
|
def test_is_macvtap_assigned_interface_with_underscore(self):
|
||||||
with mock.patch.object(pci_lib.PciDeviceIPWrapper,
|
self.assertTrue(pci_lib.PciDeviceIPWrapper.is_macvtap_assigned(
|
||||||
"_execute") as mock_exec:
|
'p1p2_1', self.IP_LINK_SHOW_WITH_MACVTAP2))
|
||||||
mock_exec.return_value = self.IP_LINK_SHOW_WITH_MACVTAP2
|
|
||||||
self.assertTrue(
|
|
||||||
pci_lib.PciDeviceIPWrapper.is_macvtap_assigned('p1p2_1'))
|
|
||||||
|
|
||||||
def test_is_macvtap_assigned_not_assigned(self):
|
def test_is_macvtap_assigned_not_assigned(self):
|
||||||
with mock.patch.object(pci_lib.PciDeviceIPWrapper,
|
self.assertFalse(pci_lib.PciDeviceIPWrapper.is_macvtap_assigned(
|
||||||
"_execute") as mock_exec:
|
'enp129s0f2', self.IP_LINK_SHOW_WITH_MACVTAP))
|
||||||
mock_exec.return_value = self.IP_LINK_SHOW_WITH_MACVTAP
|
|
||||||
self.assertFalse(
|
|
||||||
pci_lib.PciDeviceIPWrapper.is_macvtap_assigned('enp129s0f2'))
|
|
||||||
|
|
||||||
def test_is_macvtap_assigned_failed(self):
|
def test_link_show_command_failed(self):
|
||||||
with mock.patch.object(pci_lib.PciDeviceIPWrapper,
|
with mock.patch.object(pci_lib.PciDeviceIPWrapper,
|
||||||
"_execute") as mock_exec:
|
"_execute") as mock_exec:
|
||||||
mock_exec.side_effect = Exception()
|
mock_exec.side_effect = Exception()
|
||||||
self.assertRaises(exc.IpCommandError,
|
self.assertRaises(exc.IpCommandError,
|
||||||
pci_lib.PciDeviceIPWrapper.is_macvtap_assigned,
|
pci_lib.PciDeviceIPWrapper.link_show)
|
||||||
'enp129s0f3')
|
|
||||||
|
Loading…
Reference in New Issue
Block a user