diff --git a/vif_plug_ovs/linux_net.py b/vif_plug_ovs/linux_net.py index 999e486b..4039b741 100644 --- a/vif_plug_ovs/linux_net.py +++ b/vif_plug_ovs/linux_net.py @@ -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 diff --git a/vif_plug_ovs/tests/unit/test_linux_net.py b/vif_plug_ovs/tests/unit/test_linux_net.py index 0ac142e4..0cf1002e 100644 --- a/vif_plug_ovs/tests/unit/test_linux_net.py +++ b/vif_plug_ovs/tests/unit/test_linux_net.py @@ -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(),