Improve OVS Representor VF Lookup
This patch set addresses some of the concerns outlined in: https://bugs.launchpad.net/os-vif/+bug/1704485 * Determining the VF number from the netdev's phys_port_name: phys_port_name is read and then cast to an int. Currently there is no standard method to associate a representor with the VF number. phys_port_name has emerged as the "default" choice, but merely casting it as a single number has shortcomings: * A switchdev can potentially have VFs, PFs and physical ports as representors. * A switchdev can have multiple PFs. In this case, the recommendation is to use a parse tree that accepts naming conventions like: * 42 * vf42 * PF1VF42 * vf42@PF1 * Test cases have been added for the above scenarios. * An internal function for PF matching has been added for future use. This is important when PF representors are eventually exposed. Change-Id: I051fcc6fd136b389a6200076bd6fc3b73b626d5e Closes-Bug: #1704485 Signed-off-by: Jan Gutter <jan.gutter@netronome.com>
This commit is contained in:
parent
18f3f70234
commit
f4329ffe18
@ -36,6 +36,13 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
VIRTFN_RE = re.compile("virtfn(\d+)")
|
||||
|
||||
# phys_port_name only contains the VF number
|
||||
INT_RE = re.compile("^(\d+)$")
|
||||
# phys_port_name contains VF## or vf##
|
||||
VF_RE = re.compile("vf(\d+)", re.IGNORECASE)
|
||||
# phys_port_name contains PF## or pf##
|
||||
PF_RE = re.compile("pf(\d+)", re.IGNORECASE)
|
||||
|
||||
|
||||
def _ovs_vsctl(args, timeout=None):
|
||||
full_args = ['ovs-vsctl']
|
||||
@ -225,6 +232,35 @@ def _ovs_supports_mtu_requests(timeout=None):
|
||||
return True
|
||||
|
||||
|
||||
def _parse_vf_number(phys_port_name):
|
||||
"""Parses phys_port_name and returns VF number or None.
|
||||
|
||||
To determine the VF number of a representor, parse phys_port_name
|
||||
in the following sequence and return the first valid match. If none
|
||||
match, then the representor is not for a VF.
|
||||
"""
|
||||
match = INT_RE.search(phys_port_name)
|
||||
if match:
|
||||
return match.group(1)
|
||||
match = VF_RE.search(phys_port_name)
|
||||
if match:
|
||||
return match.group(1)
|
||||
return None
|
||||
|
||||
|
||||
def _parse_pf_number(phys_port_name):
|
||||
"""Parses phys_port_name and returns PF number or None.
|
||||
|
||||
To determine the PF number of a representor, parse phys_port_name in
|
||||
the following sequence and return the first valid match. If none
|
||||
match, then the representor is not for a PF.
|
||||
"""
|
||||
match = PF_RE.search(phys_port_name)
|
||||
if match:
|
||||
return match.group(1)
|
||||
return None
|
||||
|
||||
|
||||
def get_representor_port(pf_ifname, vf_num):
|
||||
"""Get the representor netdevice which is corresponding to the VF.
|
||||
|
||||
@ -271,10 +307,16 @@ def get_representor_port(pf_ifname, vf_num):
|
||||
|
||||
try:
|
||||
with open(device_port_name_file, 'r') as fd:
|
||||
representor_num = fd.readline().rstrip()
|
||||
phys_port_name = fd.readline().rstrip()
|
||||
except (OSError, IOError):
|
||||
continue
|
||||
|
||||
representor_num = _parse_vf_number(phys_port_name)
|
||||
# Note: representor_num can be 0, referring to VF0
|
||||
if representor_num is None:
|
||||
continue
|
||||
|
||||
# At this point we're confident we have a representor.
|
||||
try:
|
||||
if int(representor_num) == int(vf_num):
|
||||
return device
|
||||
|
@ -358,6 +358,22 @@ class LinuxNetTest(testtools.TestCase):
|
||||
mock_open.assert_has_calls(open_calls)
|
||||
self.assertEqual(test_switchdev, True)
|
||||
|
||||
def test_parse_vf_number(self):
|
||||
self.assertEqual(linux_net._parse_vf_number("0"), "0")
|
||||
self.assertEqual(linux_net._parse_vf_number("pf13vf42"), "42")
|
||||
self.assertEqual(linux_net._parse_vf_number("VF19@PF13"), "19")
|
||||
self.assertEqual(linux_net._parse_vf_number("p7"), None)
|
||||
self.assertEqual(linux_net._parse_vf_number("pf31"), None)
|
||||
self.assertEqual(linux_net._parse_vf_number("g4rbl3d"), None)
|
||||
|
||||
def test_parse_pf_number(self):
|
||||
self.assertEqual(linux_net._parse_pf_number("0"), None)
|
||||
self.assertEqual(linux_net._parse_pf_number("pf13vf42"), "13")
|
||||
self.assertEqual(linux_net._parse_pf_number("VF19@PF13"), "13")
|
||||
self.assertEqual(linux_net._parse_pf_number("p7"), None)
|
||||
self.assertEqual(linux_net._parse_pf_number("pf31"), "31")
|
||||
self.assertEqual(linux_net._parse_pf_number("g4rbl3d"), None)
|
||||
|
||||
@mock.patch('six.moves.builtins.open')
|
||||
@mock.patch.object(os.path, 'isfile')
|
||||
@mock.patch.object(os, 'listdir')
|
||||
@ -369,7 +385,7 @@ class LinuxNetTest(testtools.TestCase):
|
||||
mock_open.return_value.__enter__ = lambda s: s
|
||||
readline_mock = mock_open.return_value.readline
|
||||
readline_mock.side_effect = (
|
||||
['pf_sw_id', 'pf_sw_id', '1', 'pf_sw_id', '2'])
|
||||
['pf_sw_id', 'pf_sw_id', '1', 'pf_sw_id', 'pf0vf2'])
|
||||
open_calls = (
|
||||
[mock.call('/sys/class/net/pf_ifname/phys_switch_id', 'r'),
|
||||
mock.call().readline(),
|
||||
|
Loading…
Reference in New Issue
Block a user