Merge "Fix - os-vif fails to get the correct UpLink Representor"
This commit is contained in:
commit
cb21c4ed8d
10
releasenotes/notes/bug-1892132-812e6d5ce0588ebb.yaml
Normal file
10
releasenotes/notes/bug-1892132-812e6d5ce0588ebb.yaml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
Linux kernel 5.8 changed the sysfs interface that is used to
|
||||||
|
discover the interfaces used for OVS offloads for certain NIC
|
||||||
|
models. This results in network plugging failure, as described
|
||||||
|
in `bug #1892132`_. This release fixes the plugging issue by
|
||||||
|
properly handling the new sysfs structure.
|
||||||
|
|
||||||
|
.. _bug #1892132: https://bugs.launchpad.net/os-vif/+bug/1892132
|
@ -45,6 +45,8 @@ VF_RE = re.compile(r"vf(\d+)", re.IGNORECASE)
|
|||||||
PF_RE = re.compile(r"pf(\d+)", re.IGNORECASE)
|
PF_RE = re.compile(r"pf(\d+)", re.IGNORECASE)
|
||||||
# bus_info (bdf) contains <bus>:<dev>.<func>
|
# bus_info (bdf) contains <bus>:<dev>.<func>
|
||||||
PF_FUNC_RE = re.compile(r"\.(\d+)", 0)
|
PF_FUNC_RE = re.compile(r"\.(\d+)", 0)
|
||||||
|
# phys_port_name contains p##
|
||||||
|
UPLINK_PORT_RE = re.compile(r"p(\d+)", re.IGNORECASE)
|
||||||
|
|
||||||
_SRIOV_TOTALVFS = "sriov_totalvfs"
|
_SRIOV_TOTALVFS = "sriov_totalvfs"
|
||||||
NIC_NAME_LEN = 14
|
NIC_NAME_LEN = 14
|
||||||
@ -328,12 +330,28 @@ def get_ifname_by_pci_address(pci_addr, pf_interface=False, switchdev=False):
|
|||||||
itself based on the argument of pf_interface.
|
itself based on the argument of pf_interface.
|
||||||
"""
|
"""
|
||||||
dev_path = _get_sysfs_netdev_path(pci_addr, pf_interface)
|
dev_path = _get_sysfs_netdev_path(pci_addr, pf_interface)
|
||||||
# make the if statement later more readable
|
|
||||||
ignore_switchdev = not switchdev
|
|
||||||
try:
|
try:
|
||||||
for netdev in os.listdir(dev_path):
|
devices = os.listdir(dev_path)
|
||||||
if ignore_switchdev or _is_switchdev(netdev):
|
|
||||||
return netdev
|
# Return the first netdev in case of switchdev=False
|
||||||
|
if not switchdev:
|
||||||
|
return devices[0]
|
||||||
|
elif pf_interface:
|
||||||
|
fallback_netdev = None
|
||||||
|
for netdev in devices:
|
||||||
|
# Return the uplink representor in case of switchdev=True
|
||||||
|
if _is_switchdev(netdev):
|
||||||
|
fallback_netdev = netdev if fallback_netdev is None \
|
||||||
|
else fallback_netdev
|
||||||
|
phys_port_name = _get_phys_port_name(netdev)
|
||||||
|
if phys_port_name is not None and \
|
||||||
|
UPLINK_PORT_RE.search(phys_port_name):
|
||||||
|
return netdev
|
||||||
|
|
||||||
|
# Fallback to first switchdev netdev in case of switchdev=True
|
||||||
|
if fallback_netdev is not None:
|
||||||
|
return fallback_netdev
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
raise exception.PciDeviceNotFoundById(id=pci_addr)
|
raise exception.PciDeviceNotFoundById(id=pci_addr)
|
||||||
raise exception.PciDeviceNotFoundById(id=pci_addr)
|
raise exception.PciDeviceNotFoundById(id=pci_addr)
|
||||||
|
@ -261,26 +261,64 @@ class LinuxNetTest(testtools.TestCase):
|
|||||||
|
|
||||||
@mock.patch.object(os, 'listdir')
|
@mock.patch.object(os, 'listdir')
|
||||||
@mock.patch.object(linux_net, '_get_phys_switch_id')
|
@mock.patch.object(linux_net, '_get_phys_switch_id')
|
||||||
|
@mock.patch.object(linux_net, "_get_phys_port_name")
|
||||||
def test_physical_function_interface_name(
|
def test_physical_function_interface_name(
|
||||||
self, mock__get_phys_switch_id, mock_listdir):
|
self, mock__get_phys_port_name, mock__get_phys_switch_id,
|
||||||
|
mock_listdir):
|
||||||
mock_listdir.return_value = ['foo', 'bar']
|
mock_listdir.return_value = ['foo', 'bar']
|
||||||
mock__get_phys_switch_id.side_effect = (
|
mock__get_phys_switch_id.side_effect = (
|
||||||
['', 'valid_switch'])
|
['', 'valid_switch'])
|
||||||
|
mock__get_phys_port_name.side_effect = (["p1"])
|
||||||
ifname = linux_net.get_ifname_by_pci_address(
|
ifname = linux_net.get_ifname_by_pci_address(
|
||||||
'0000:00:00.1', pf_interface=True, switchdev=False)
|
'0000:00:00.1', pf_interface=True, switchdev=False)
|
||||||
self.assertEqual(ifname, 'foo')
|
self.assertEqual(ifname, 'foo')
|
||||||
|
|
||||||
@mock.patch.object(os, 'listdir')
|
@mock.patch.object(os, 'listdir')
|
||||||
@mock.patch.object(linux_net, '_get_phys_switch_id')
|
@mock.patch.object(linux_net, "_get_phys_switch_id")
|
||||||
|
@mock.patch.object(linux_net, "_get_phys_port_name")
|
||||||
def test_physical_function_interface_name_with_switchdev(
|
def test_physical_function_interface_name_with_switchdev(
|
||||||
self, mock__get_phys_switch_id, mock_listdir):
|
self, mock__get_phys_port_name, mock__get_phys_switch_id,
|
||||||
|
mock_listdir):
|
||||||
mock_listdir.return_value = ['foo', 'bar']
|
mock_listdir.return_value = ['foo', 'bar']
|
||||||
mock__get_phys_switch_id.side_effect = (
|
mock__get_phys_switch_id.side_effect = (
|
||||||
['', 'valid_switch'])
|
['', 'valid_switch'])
|
||||||
|
mock__get_phys_port_name.side_effect = (["p1s0"])
|
||||||
ifname = linux_net.get_ifname_by_pci_address(
|
ifname = linux_net.get_ifname_by_pci_address(
|
||||||
'0000:00:00.1', pf_interface=True, switchdev=True)
|
'0000:00:00.1', pf_interface=True, switchdev=True)
|
||||||
self.assertEqual(ifname, 'bar')
|
self.assertEqual(ifname, 'bar')
|
||||||
|
|
||||||
|
@mock.patch.object(os, 'listdir')
|
||||||
|
@mock.patch.object(linux_net, "_get_phys_switch_id")
|
||||||
|
@mock.patch.object(linux_net, "_get_phys_port_name")
|
||||||
|
def test_physical_function_interface_name_with_representors(
|
||||||
|
self, mock__get_phys_port_name, mock__get_phys_switch_id,
|
||||||
|
mock_listdir):
|
||||||
|
# Get the PF that matches the phys_port_name regex
|
||||||
|
mock_listdir.return_value = ['enp2s0f0_0', 'enp2s0f0_1', 'enp2s0f0']
|
||||||
|
mock__get_phys_switch_id.side_effect = (
|
||||||
|
['valid_switch', 'valid_switch', 'valid_switch'])
|
||||||
|
mock__get_phys_port_name.side_effect = (["pf0vf0", "pf0vf1", "p0"])
|
||||||
|
ifname = linux_net.get_ifname_by_pci_address(
|
||||||
|
'0000:00:00.1', pf_interface=True, switchdev=True)
|
||||||
|
self.assertEqual(ifname, 'enp2s0f0')
|
||||||
|
|
||||||
|
@mock.patch.object(os, 'listdir')
|
||||||
|
@mock.patch.object(linux_net, "_get_phys_switch_id")
|
||||||
|
@mock.patch.object(linux_net, "_get_phys_port_name")
|
||||||
|
def test_physical_function_interface_name_with_fallback_To_first_netdev(
|
||||||
|
self, mock__get_phys_port_name, mock__get_phys_switch_id,
|
||||||
|
mock_listdir):
|
||||||
|
# Try with switchdev mode to get PF but fail because there is no match
|
||||||
|
# for the phys_port_name then fallback to first interface found
|
||||||
|
mock_listdir.return_value = ['enp2s0f0_0', 'enp2s0f0_1', 'enp2s0f0']
|
||||||
|
mock__get_phys_switch_id.side_effect = (['valid_switch',
|
||||||
|
'valid_switch',
|
||||||
|
'valid_switch'])
|
||||||
|
mock__get_phys_port_name.side_effect = (["pf0vf0", "pf0vf1", "pf0vf2"])
|
||||||
|
ifname = linux_net.get_ifname_by_pci_address(
|
||||||
|
'0000:00:00.1', pf_interface=True, switchdev=True)
|
||||||
|
self.assertEqual(ifname, 'enp2s0f0_0')
|
||||||
|
|
||||||
@mock.patch.object(os, 'listdir')
|
@mock.patch.object(os, 'listdir')
|
||||||
def test_get_ifname_by_pci_address_exception(self, mock_listdir):
|
def test_get_ifname_by_pci_address_exception(self, mock_listdir):
|
||||||
mock_listdir.side_effect = OSError('No such file or directory')
|
mock_listdir.side_effect = OSError('No such file or directory')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user