Merge "Improve OVS Representor Lookup"
This commit is contained in:
commit
063b2e3d8f
@ -294,18 +294,41 @@ def _get_sysfs_netdev_path(pci_addr, pf_interface):
|
||||
return "/sys/bus/pci/devices/%s/net" % (pci_addr)
|
||||
|
||||
|
||||
def get_ifname_by_pci_address(pci_addr, pf_interface=False):
|
||||
def _is_switchdev(netdev):
|
||||
"""Returns True if a netdev has a readable phys_switch_id"""
|
||||
try:
|
||||
sw_id_file = "/sys/class/net/%s/phys_switch_id" % netdev
|
||||
with open(sw_id_file, 'r') as fd:
|
||||
phys_switch_id = fd.readline().rstrip()
|
||||
if phys_switch_id != "" and phys_switch_id is not None:
|
||||
return True
|
||||
except (OSError, IOError):
|
||||
return False
|
||||
return False
|
||||
|
||||
|
||||
def get_ifname_by_pci_address(pci_addr, pf_interface=False, switchdev=False):
|
||||
"""Get the interface name based on a VF's pci address
|
||||
|
||||
:param pci_addr: the PCI address of the VF
|
||||
:param pf_interface: if True, look for the netdev of the parent PF
|
||||
:param switchdev: if True, ensure that phys_switch_id is valid
|
||||
|
||||
:returns: netdev interface name
|
||||
|
||||
The returned interface name is either the parent PF or that of the VF
|
||||
itself based on the argument of pf_interface.
|
||||
"""
|
||||
dev_path = _get_sysfs_netdev_path(pci_addr, pf_interface)
|
||||
# make the if statement later more readable
|
||||
ignore_switchdev = not switchdev
|
||||
try:
|
||||
dev_info = os.listdir(dev_path)
|
||||
return dev_info.pop()
|
||||
for netdev in os.listdir(dev_path):
|
||||
if ignore_switchdev or _is_switchdev(netdev):
|
||||
return netdev
|
||||
except Exception:
|
||||
raise exception.PciDeviceNotFoundById(id=pci_addr)
|
||||
raise exception.PciDeviceNotFoundById(id=pci_addr)
|
||||
|
||||
|
||||
def get_vf_num_by_pci_address(pci_addr):
|
||||
|
@ -160,7 +160,7 @@ class OvsPlugin(plugin.PluginBase):
|
||||
vif.network.bridge, constants.OVS_DATAPATH_SYSTEM)
|
||||
pci_slot = vif.dev_address
|
||||
pf_ifname = linux_net.get_ifname_by_pci_address(
|
||||
pci_slot, pf_interface=True)
|
||||
pci_slot, pf_interface=True, switchdev=True)
|
||||
vf_num = linux_net.get_vf_num_by_pci_address(pci_slot)
|
||||
representor = linux_net.get_representor_port(pf_ifname, vf_num)
|
||||
linux_net.set_interface_state(representor, 'up')
|
||||
@ -221,7 +221,7 @@ class OvsPlugin(plugin.PluginBase):
|
||||
"""Remove port from OVS."""
|
||||
pci_slot = vif.dev_address
|
||||
pf_ifname = linux_net.get_ifname_by_pci_address(pci_slot,
|
||||
pf_interface=True)
|
||||
pf_interface=True, switchdev=True)
|
||||
vf_num = linux_net.get_vf_num_by_pci_address(pci_slot)
|
||||
representor = linux_net.get_representor_port(pf_ifname, vf_num)
|
||||
# The representor interface can't be deleted because it bind the
|
||||
|
@ -315,6 +315,49 @@ class LinuxNetTest(testtools.TestCase):
|
||||
mock_vsctl.assert_called_with(args, timeout=timeout)
|
||||
self.assertTrue(result)
|
||||
|
||||
@mock.patch('six.moves.builtins.open')
|
||||
@mock.patch.object(os.path, 'isfile')
|
||||
def test_is_switchdev_ioerror(self, mock_isfile, mock_open):
|
||||
mock_isfile.side_effect = [True]
|
||||
mock_open.return_value.__enter__ = lambda s: s
|
||||
readline_mock = mock_open.return_value.readline
|
||||
readline_mock.side_effect = (
|
||||
[IOError()])
|
||||
test_switchdev = linux_net._is_switchdev('pf_ifname')
|
||||
self.assertEqual(test_switchdev, False)
|
||||
|
||||
@mock.patch('six.moves.builtins.open')
|
||||
@mock.patch.object(os.path, 'isfile')
|
||||
def test_is_switchdev_empty(self, mock_isfile, mock_open):
|
||||
mock_isfile.side_effect = [True]
|
||||
mock_open.return_value.__enter__ = lambda s: s
|
||||
readline_mock = mock_open.return_value.readline
|
||||
readline_mock.side_effect = (
|
||||
[''])
|
||||
open_calls = (
|
||||
[mock.call('/sys/class/net/pf_ifname/phys_switch_id', 'r'),
|
||||
mock.call().readline(),
|
||||
mock.call().__exit__(None, None, None)])
|
||||
test_switchdev = linux_net._is_switchdev('pf_ifname')
|
||||
mock_open.assert_has_calls(open_calls)
|
||||
self.assertEqual(test_switchdev, False)
|
||||
|
||||
@mock.patch('six.moves.builtins.open')
|
||||
@mock.patch.object(os.path, 'isfile')
|
||||
def test_is_switchdev_positive(self, mock_isfile, mock_open):
|
||||
mock_isfile.side_effect = [True]
|
||||
mock_open.return_value.__enter__ = lambda s: s
|
||||
readline_mock = mock_open.return_value.readline
|
||||
readline_mock.side_effect = (
|
||||
['pf_sw_id'])
|
||||
open_calls = (
|
||||
[mock.call('/sys/class/net/pf_ifname/phys_switch_id', 'r'),
|
||||
mock.call().readline(),
|
||||
mock.call().__exit__(None, None, None)])
|
||||
test_switchdev = linux_net._is_switchdev('pf_ifname')
|
||||
mock_open.assert_has_calls(open_calls)
|
||||
self.assertEqual(test_switchdev, True)
|
||||
|
||||
@mock.patch('six.moves.builtins.open')
|
||||
@mock.patch.object(os.path, 'isfile')
|
||||
@mock.patch.object(os, 'listdir')
|
||||
@ -418,18 +461,34 @@ class LinuxNetTest(testtools.TestCase):
|
||||
linux_net.get_representor_port,
|
||||
'pf_ifname', '3')
|
||||
|
||||
@mock.patch('six.moves.builtins.open')
|
||||
@mock.patch.object(os.path, 'isfile')
|
||||
@mock.patch.object(os, 'listdir')
|
||||
def test_physical_function_inferface_name(self, mock_listdir):
|
||||
def test_physical_function_inferface_name(
|
||||
self, mock_listdir, mock_isfile, mock_open):
|
||||
mock_listdir.return_value = ['foo', 'bar']
|
||||
mock_isfile.side_effect = [True, True]
|
||||
mock_open.return_value.__enter__ = lambda s: s
|
||||
readline_mock = mock_open.return_value.readline
|
||||
readline_mock.side_effect = (
|
||||
['', 'valid_switch'])
|
||||
ifname = linux_net.get_ifname_by_pci_address(
|
||||
'0000:00:00.1', pf_interface=True)
|
||||
self.assertEqual(ifname, 'bar')
|
||||
'0000:00:00.1', pf_interface=True, switchdev=False)
|
||||
self.assertEqual(ifname, 'foo')
|
||||
|
||||
@mock.patch('six.moves.builtins.open')
|
||||
@mock.patch.object(os.path, 'isfile')
|
||||
@mock.patch.object(os, 'listdir')
|
||||
def test_virtual_function_inferface_name(self, mock_listdir):
|
||||
def test_physical_function_inferface_name_with_switchdev(
|
||||
self, mock_listdir, mock_isfile, mock_open):
|
||||
mock_listdir.return_value = ['foo', 'bar']
|
||||
mock_isfile.side_effect = [True, True]
|
||||
mock_open.return_value.__enter__ = lambda s: s
|
||||
readline_mock = mock_open.return_value.readline
|
||||
readline_mock.side_effect = (
|
||||
['', 'valid_switch'])
|
||||
ifname = linux_net.get_ifname_by_pci_address(
|
||||
'0000:00:00.1', pf_interface=False)
|
||||
'0000:00:00.1', pf_interface=True, switchdev=True)
|
||||
self.assertEqual(ifname, 'bar')
|
||||
|
||||
@mock.patch.object(os, 'listdir')
|
||||
|
@ -345,7 +345,8 @@ class PluginTest(testtools.TestCase):
|
||||
'ensure_ovs_bridge': [mock.call('br0',
|
||||
constants.OVS_DATAPATH_SYSTEM)],
|
||||
'get_ifname_by_pci_address': [mock.call('0002:24:12.3',
|
||||
pf_interface=True)],
|
||||
pf_interface=True,
|
||||
switchdev=True)],
|
||||
'get_vf_num_by_pci_address': [mock.call('0002:24:12.3')],
|
||||
'get_representor_port': [mock.call('eth0', '2')],
|
||||
'set_interface_state': [mock.call('eth0_2', 'up')],
|
||||
@ -379,7 +380,8 @@ class PluginTest(testtools.TestCase):
|
||||
calls = {
|
||||
|
||||
'get_ifname_by_pci_address': [mock.call('0002:24:12.3',
|
||||
pf_interface=True)],
|
||||
pf_interface=True,
|
||||
switchdev=True)],
|
||||
'get_vf_num_by_pci_address': [mock.call('0002:24:12.3')],
|
||||
'get_representor_port': [mock.call('eth0', '2')],
|
||||
'set_interface_state': [mock.call('eth0_2', 'down')],
|
||||
|
Loading…
x
Reference in New Issue
Block a user