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+)")
|
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):
|
def _ovs_vsctl(args, timeout=None):
|
||||||
full_args = ['ovs-vsctl']
|
full_args = ['ovs-vsctl']
|
||||||
@ -225,6 +232,35 @@ def _ovs_supports_mtu_requests(timeout=None):
|
|||||||
return True
|
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):
|
def get_representor_port(pf_ifname, vf_num):
|
||||||
"""Get the representor netdevice which is corresponding to the VF.
|
"""Get the representor netdevice which is corresponding to the VF.
|
||||||
|
|
||||||
@ -271,10 +307,16 @@ def get_representor_port(pf_ifname, vf_num):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
with open(device_port_name_file, 'r') as fd:
|
with open(device_port_name_file, 'r') as fd:
|
||||||
representor_num = fd.readline().rstrip()
|
phys_port_name = fd.readline().rstrip()
|
||||||
except (OSError, IOError):
|
except (OSError, IOError):
|
||||||
continue
|
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:
|
try:
|
||||||
if int(representor_num) == int(vf_num):
|
if int(representor_num) == int(vf_num):
|
||||||
return device
|
return device
|
||||||
|
@ -358,6 +358,22 @@ class LinuxNetTest(testtools.TestCase):
|
|||||||
mock_open.assert_has_calls(open_calls)
|
mock_open.assert_has_calls(open_calls)
|
||||||
self.assertEqual(test_switchdev, True)
|
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('six.moves.builtins.open')
|
||||||
@mock.patch.object(os.path, 'isfile')
|
@mock.patch.object(os.path, 'isfile')
|
||||||
@mock.patch.object(os, 'listdir')
|
@mock.patch.object(os, 'listdir')
|
||||||
@ -369,7 +385,7 @@ class LinuxNetTest(testtools.TestCase):
|
|||||||
mock_open.return_value.__enter__ = lambda s: s
|
mock_open.return_value.__enter__ = lambda s: s
|
||||||
readline_mock = mock_open.return_value.readline
|
readline_mock = mock_open.return_value.readline
|
||||||
readline_mock.side_effect = (
|
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 = (
|
open_calls = (
|
||||||
[mock.call('/sys/class/net/pf_ifname/phys_switch_id', 'r'),
|
[mock.call('/sys/class/net/pf_ifname/phys_switch_id', 'r'),
|
||||||
mock.call().readline(),
|
mock.call().readline(),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user