Merge ~fnordahl/ubuntu/+source/python-os-vif:bug/1892132-ussuri into ~ubuntu-openstack-dev/ubuntu/+source/python-os-vif:stable/ussuri
- Git
- lp:~fnordahl/ubuntu/+source/python-os-vif
- bug/1892132-ussuri
- Merge into stable/ussuri
Proposed by
Frode Nordahl
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | 0119aebdc0949b9f3a74f78f1c275d1f51ee59c7 | ||||
Proposed branch: | ~fnordahl/ubuntu/+source/python-os-vif:bug/1892132-ussuri | ||||
Merge into: | ~ubuntu-openstack-dev/ubuntu/+source/python-os-vif:stable/ussuri | ||||
Diff against target: |
696 lines (+670/-0) 4 files modified
debian/changelog (+9/-0) debian/patches/Fix-os-vif-fails-to-get-the-correct-UpLink-Representor.patch (+168/-0) debian/patches/Refactor-code-of-linux_net-to-more-cleaner-and-increase-performace.patch (+491/-0) debian/patches/series (+2/-0) |
||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Corey Bryant | Pending | ||
Chris MacNaughton | Pending | ||
Ubuntu OpenStack uploaders | Pending | ||
Review via email: mp+405805@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/debian/changelog b/debian/changelog |
2 | index e2673a2..b62c1c2 100644 |
3 | --- a/debian/changelog |
4 | +++ b/debian/changelog |
5 | @@ -1,3 +1,12 @@ |
6 | +python-os-vif (2.0.0-0ubuntu1.2) UNRELEASED; urgency=medium |
7 | + |
8 | + * Add support for switchdev NICs that link representor ports to parent PCI |
9 | + device. (LP: #1892132) |
10 | + - d/p/Refactor-code-of-linux_net-to-more-cleaner-and-increase-performace.patch |
11 | + - d/p/Fix-os-vif-fails-to-get-the-correct-UpLink-Representor.patch |
12 | + |
13 | + -- Frode Nordahl <frode.nordahl@canonical.com> Fri, 16 Jul 2021 09:43:06 +0000 |
14 | + |
15 | python-os-vif (2.0.0-0ubuntu1.1) UNRELEASED; urgency=medium |
16 | |
17 | [ Corey Bryant ] |
18 | diff --git a/debian/patches/Fix-os-vif-fails-to-get-the-correct-UpLink-Representor.patch b/debian/patches/Fix-os-vif-fails-to-get-the-correct-UpLink-Representor.patch |
19 | new file mode 100644 |
20 | index 0000000..bb82b13 |
21 | --- /dev/null |
22 | +++ b/debian/patches/Fix-os-vif-fails-to-get-the-correct-UpLink-Representor.patch |
23 | @@ -0,0 +1,168 @@ |
24 | +From ssh://review.opendev.org:29418/openstack/os-vif |
25 | + * branch refs/changes/67/765967/5 -> FETCH_HEAD |
26 | +From 1226d46cc8bde9531821c68465a05292528142f0 Mon Sep 17 00:00:00 2001 |
27 | +From: Mamduh Alassi <mamduhala@mellanox.com> |
28 | +Date: Wed, 12 Aug 2020 16:24:47 +0300 |
29 | +Subject: [PATCH] Fix - os-vif fails to get the correct UpLink Representor |
30 | + |
31 | +Till kernel 5.7 PF and VF representors are exposed as virtual device. |
32 | +They are not linked to its parent PCI device like how uplink |
33 | +representor is linked. |
34 | + |
35 | +Starting from kernel 5.8 due to new change [1] the PF and VF representors are |
36 | +linked to their parent PCI device, and so "get_ifname_by_pci_address" fails |
37 | +to get the correct UpLink Representor. |
38 | + |
39 | +This patch modifys the behviour of "get_ifname_by_pci_address" to |
40 | +check the physical port name of the netdev in |
41 | +vf_pci_addr_path/physfn/net to match the formart for the uplink "p\d+". |
42 | + |
43 | +[1] https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git/commit/?id=123f0f53dd64b67e34142485fe866a8a581f12f1 |
44 | + |
45 | +Closes-Bug: #1892132 |
46 | +Change-Id: I49f6ae3f0e6bfbf555c8284bfd70371ce90da0c7 |
47 | +(cherry picked from commit a28aafa796378b8a36ccb51d2c0010a44f622d14) |
48 | +--- |
49 | + .../notes/bug-1892132-812e6d5ce0588ebb.yaml | 10 +++++ |
50 | + vif_plug_ovs/linux_net.py | 28 +++++++++--- |
51 | + vif_plug_ovs/tests/unit/test_linux_net.py | 44 +++++++++++++++++-- |
52 | + 3 files changed, 74 insertions(+), 8 deletions(-) |
53 | + create mode 100644 releasenotes/notes/bug-1892132-812e6d5ce0588ebb.yaml |
54 | + |
55 | +diff --git a/releasenotes/notes/bug-1892132-812e6d5ce0588ebb.yaml b/releasenotes/notes/bug-1892132-812e6d5ce0588ebb.yaml |
56 | +new file mode 100644 |
57 | +index 0000000..f7604dd |
58 | +--- /dev/null |
59 | ++++ b/releasenotes/notes/bug-1892132-812e6d5ce0588ebb.yaml |
60 | +@@ -0,0 +1,10 @@ |
61 | ++--- |
62 | ++fixes: |
63 | ++ - | |
64 | ++ Linux kernel 5.8 changed the sysfs interface that is used to |
65 | ++ discover the interfaces used for OVS offloads for certain NIC |
66 | ++ models. This results in network plugging failure, as described |
67 | ++ in `bug #1892132`_. This release fixes the plugging issue by |
68 | ++ properly handling the new sysfs structure. |
69 | ++ |
70 | ++ .. _bug #1892132: https://bugs.launchpad.net/os-vif/+bug/1892132 |
71 | +diff --git a/vif_plug_ovs/linux_net.py b/vif_plug_ovs/linux_net.py |
72 | +index 3e77585..f7b120c 100644 |
73 | +--- a/vif_plug_ovs/linux_net.py |
74 | ++++ b/vif_plug_ovs/linux_net.py |
75 | +@@ -45,6 +45,8 @@ VF_RE = re.compile(r"vf(\d+)", re.IGNORECASE) |
76 | + PF_RE = re.compile(r"pf(\d+)", re.IGNORECASE) |
77 | + # bus_info (bdf) contains <bus>:<dev>.<func> |
78 | + PF_FUNC_RE = re.compile(r"\.(\d+)", 0) |
79 | ++# phys_port_name contains p## |
80 | ++UPLINK_PORT_RE = re.compile(r"p(\d+)", re.IGNORECASE) |
81 | + |
82 | + _SRIOV_TOTALVFS = "sriov_totalvfs" |
83 | + NIC_NAME_LEN = 14 |
84 | +@@ -327,12 +329,28 @@ def get_ifname_by_pci_address(pci_addr, pf_interface=False, switchdev=False): |
85 | + itself based on the argument of pf_interface. |
86 | + """ |
87 | + dev_path = _get_sysfs_netdev_path(pci_addr, pf_interface) |
88 | +- # make the if statement later more readable |
89 | +- ignore_switchdev = not switchdev |
90 | + try: |
91 | +- for netdev in os.listdir(dev_path): |
92 | +- if ignore_switchdev or _is_switchdev(netdev): |
93 | +- return netdev |
94 | ++ devices = os.listdir(dev_path) |
95 | ++ |
96 | ++ # Return the first netdev in case of switchdev=False |
97 | ++ if not switchdev: |
98 | ++ return devices[0] |
99 | ++ elif pf_interface: |
100 | ++ fallback_netdev = None |
101 | ++ for netdev in devices: |
102 | ++ # Return the uplink representor in case of switchdev=True |
103 | ++ if _is_switchdev(netdev): |
104 | ++ fallback_netdev = netdev if fallback_netdev is None \ |
105 | ++ else fallback_netdev |
106 | ++ phys_port_name = _get_phys_port_name(netdev) |
107 | ++ if phys_port_name is not None and \ |
108 | ++ UPLINK_PORT_RE.search(phys_port_name): |
109 | ++ return netdev |
110 | ++ |
111 | ++ # Fallback to first switchdev netdev in case of switchdev=True |
112 | ++ if fallback_netdev is not None: |
113 | ++ return fallback_netdev |
114 | ++ |
115 | + except Exception: |
116 | + raise exception.PciDeviceNotFoundById(id=pci_addr) |
117 | + raise exception.PciDeviceNotFoundById(id=pci_addr) |
118 | +diff --git a/vif_plug_ovs/tests/unit/test_linux_net.py b/vif_plug_ovs/tests/unit/test_linux_net.py |
119 | +index a5404ea..e19ce94 100644 |
120 | +--- a/vif_plug_ovs/tests/unit/test_linux_net.py |
121 | ++++ b/vif_plug_ovs/tests/unit/test_linux_net.py |
122 | +@@ -260,26 +260,64 @@ class LinuxNetTest(testtools.TestCase): |
123 | + |
124 | + @mock.patch.object(os, 'listdir') |
125 | + @mock.patch.object(linux_net, '_get_phys_switch_id') |
126 | ++ @mock.patch.object(linux_net, "_get_phys_port_name") |
127 | + def test_physical_function_interface_name( |
128 | +- self, mock__get_phys_switch_id, mock_listdir): |
129 | ++ self, mock__get_phys_port_name, mock__get_phys_switch_id, |
130 | ++ mock_listdir): |
131 | + mock_listdir.return_value = ['foo', 'bar'] |
132 | + mock__get_phys_switch_id.side_effect = ( |
133 | + ['', 'valid_switch']) |
134 | ++ mock__get_phys_port_name.side_effect = (["p1"]) |
135 | + ifname = linux_net.get_ifname_by_pci_address( |
136 | + '0000:00:00.1', pf_interface=True, switchdev=False) |
137 | + self.assertEqual(ifname, 'foo') |
138 | + |
139 | + @mock.patch.object(os, 'listdir') |
140 | +- @mock.patch.object(linux_net, '_get_phys_switch_id') |
141 | ++ @mock.patch.object(linux_net, "_get_phys_switch_id") |
142 | ++ @mock.patch.object(linux_net, "_get_phys_port_name") |
143 | + def test_physical_function_interface_name_with_switchdev( |
144 | +- self, mock__get_phys_switch_id, mock_listdir): |
145 | ++ self, mock__get_phys_port_name, mock__get_phys_switch_id, |
146 | ++ mock_listdir): |
147 | + mock_listdir.return_value = ['foo', 'bar'] |
148 | + mock__get_phys_switch_id.side_effect = ( |
149 | + ['', 'valid_switch']) |
150 | ++ mock__get_phys_port_name.side_effect = (["p1s0"]) |
151 | + ifname = linux_net.get_ifname_by_pci_address( |
152 | + '0000:00:00.1', pf_interface=True, switchdev=True) |
153 | + self.assertEqual(ifname, 'bar') |
154 | + |
155 | ++ @mock.patch.object(os, 'listdir') |
156 | ++ @mock.patch.object(linux_net, "_get_phys_switch_id") |
157 | ++ @mock.patch.object(linux_net, "_get_phys_port_name") |
158 | ++ def test_physical_function_interface_name_with_representors( |
159 | ++ self, mock__get_phys_port_name, mock__get_phys_switch_id, |
160 | ++ mock_listdir): |
161 | ++ # Get the PF that matches the phys_port_name regex |
162 | ++ mock_listdir.return_value = ['enp2s0f0_0', 'enp2s0f0_1', 'enp2s0f0'] |
163 | ++ mock__get_phys_switch_id.side_effect = ( |
164 | ++ ['valid_switch', 'valid_switch', 'valid_switch']) |
165 | ++ mock__get_phys_port_name.side_effect = (["pf0vf0", "pf0vf1", "p0"]) |
166 | ++ ifname = linux_net.get_ifname_by_pci_address( |
167 | ++ '0000:00:00.1', pf_interface=True, switchdev=True) |
168 | ++ self.assertEqual(ifname, 'enp2s0f0') |
169 | ++ |
170 | ++ @mock.patch.object(os, 'listdir') |
171 | ++ @mock.patch.object(linux_net, "_get_phys_switch_id") |
172 | ++ @mock.patch.object(linux_net, "_get_phys_port_name") |
173 | ++ def test_physical_function_interface_name_with_fallback_To_first_netdev( |
174 | ++ self, mock__get_phys_port_name, mock__get_phys_switch_id, |
175 | ++ mock_listdir): |
176 | ++ # Try with switchdev mode to get PF but fail because there is no match |
177 | ++ # for the phys_port_name then fallback to first interface found |
178 | ++ mock_listdir.return_value = ['enp2s0f0_0', 'enp2s0f0_1', 'enp2s0f0'] |
179 | ++ mock__get_phys_switch_id.side_effect = (['valid_switch', |
180 | ++ 'valid_switch', |
181 | ++ 'valid_switch']) |
182 | ++ mock__get_phys_port_name.side_effect = (["pf0vf0", "pf0vf1", "pf0vf2"]) |
183 | ++ ifname = linux_net.get_ifname_by_pci_address( |
184 | ++ '0000:00:00.1', pf_interface=True, switchdev=True) |
185 | ++ self.assertEqual(ifname, 'enp2s0f0_0') |
186 | ++ |
187 | + @mock.patch.object(os, 'listdir') |
188 | + def test_get_ifname_by_pci_address_exception(self, mock_listdir): |
189 | + mock_listdir.side_effect = OSError('No such file or directory') |
190 | +-- |
191 | +2.31.1 |
192 | diff --git a/debian/patches/Refactor-code-of-linux_net-to-more-cleaner-and-increase-performace.patch b/debian/patches/Refactor-code-of-linux_net-to-more-cleaner-and-increase-performace.patch |
193 | new file mode 100644 |
194 | index 0000000..e895a24 |
195 | --- /dev/null |
196 | +++ b/debian/patches/Refactor-code-of-linux_net-to-more-cleaner-and-increase-performace.patch |
197 | @@ -0,0 +1,491 @@ |
198 | +From ssh://review.opendev.org:29418/openstack/os-vif |
199 | + * branch refs/changes/19/765419/6 -> FETCH_HEAD |
200 | +From 3e1d898b752c327165aeca1fec0919d858a87ec4 Mon Sep 17 00:00:00 2001 |
201 | +From: Mamduh <mamduhala@nvidia.com> |
202 | +Date: Tue, 18 Aug 2020 12:40:10 +0300 |
203 | +Subject: [PATCH] Refactor code of linux_net to more cleaner and increase |
204 | + performace |
205 | + |
206 | +The patch adds new functions '_get_phys_port_name' for reading physical |
207 | +port name of the SR-IOV port and '_get_phys_switch_id' for reading |
208 | +physical port switch ID of the SR-IOV port, in addition to refactoring |
209 | +'get_representor_port' to use the new functions and decrease calls for |
210 | +"_get_pf_func" and netdevs associated with the PF will now be processed |
211 | +in the loop, however it will not be matching 'phys_port_name' which |
212 | +ensures the correct behaviour. |
213 | + |
214 | +In addition to updating the unit test for linux_net and remove not |
215 | +needed mocks |
216 | + |
217 | +Conflicts: |
218 | + vif_plug_ovs/linux_net.py |
219 | + vif_plug_ovs/tests/unit/test_linux_net.py |
220 | + |
221 | +Related-Bug: #1892132 |
222 | +Change-Id: I3fdbea4f48cb79ebfd03a4da21e2232ccafb7a76 |
223 | +(cherry picked from commit 167bb030f1143f37ce189673d831bd572f64d4ad) |
224 | +--- |
225 | + vif_plug_ovs/linux_net.py | 77 ++++--- |
226 | + vif_plug_ovs/tests/unit/test_linux_net.py | 250 ++++++++-------------- |
227 | + 2 files changed, 139 insertions(+), 188 deletions(-) |
228 | + |
229 | +diff --git a/vif_plug_ovs/linux_net.py b/vif_plug_ovs/linux_net.py |
230 | +index 20baab3..3e77585 100644 |
231 | +--- a/vif_plug_ovs/linux_net.py |
232 | ++++ b/vif_plug_ovs/linux_net.py |
233 | +@@ -239,46 +239,35 @@ def get_representor_port(pf_ifname, vf_num): |
234 | + VF number in the phys_port_name. That interface is the representor for |
235 | + the requested VF. |
236 | + """ |
237 | +- pf_path = "/sys/class/net/%s" % pf_ifname |
238 | +- pf_sw_id_file = os.path.join(pf_path, "phys_switch_id") |
239 | + |
240 | + pf_sw_id = None |
241 | + try: |
242 | +- with open(pf_sw_id_file, 'r') as fd: |
243 | +- pf_sw_id = fd.readline().rstrip() |
244 | ++ pf_sw_id = _get_phys_switch_id(pf_ifname) |
245 | + except (OSError, IOError): |
246 | + raise exception.RepresentorNotFound(ifname=pf_ifname, vf_num=vf_num) |
247 | + |
248 | +- pf_subsystem_file = os.path.join(pf_path, "subsystem") |
249 | ++ pf_subsystem_file = "/sys/class/net/%s/subsystem" % pf_ifname |
250 | + try: |
251 | + devices = os.listdir(pf_subsystem_file) |
252 | + except (OSError, IOError): |
253 | + raise exception.RepresentorNotFound(ifname=pf_ifname, vf_num=vf_num) |
254 | + |
255 | +- for device in devices: |
256 | +- address_str, pf = get_function_by_ifname(device) |
257 | +- if pf: |
258 | +- continue |
259 | ++ ifname_pf_func = _get_pf_func(pf_ifname) |
260 | ++ if ifname_pf_func is None: |
261 | ++ raise exception.RepresentorNotFound(ifname=pf_ifname, vf_num=vf_num) |
262 | + |
263 | +- device_path = "/sys/class/net/%s" % device |
264 | +- device_sw_id_file = os.path.join(device_path, "phys_switch_id") |
265 | ++ for device in devices: |
266 | + try: |
267 | +- with open(device_sw_id_file, 'r') as fd: |
268 | +- device_sw_id = fd.readline().rstrip() |
269 | ++ device_sw_id = _get_phys_switch_id(device) |
270 | ++ if not device_sw_id or device_sw_id != pf_sw_id: |
271 | ++ continue |
272 | + except (OSError, IOError): |
273 | + continue |
274 | + |
275 | +- if device_sw_id != pf_sw_id: |
276 | +- continue |
277 | +- device_port_name_file = ( |
278 | +- os.path.join(device_path, 'phys_port_name')) |
279 | +- |
280 | +- if not os.path.isfile(device_port_name_file): |
281 | +- continue |
282 | +- |
283 | + try: |
284 | +- with open(device_port_name_file, 'r') as fd: |
285 | +- phys_port_name = fd.readline().rstrip() |
286 | ++ phys_port_name = _get_phys_port_name(device) |
287 | ++ if phys_port_name is None: |
288 | ++ continue |
289 | + except (OSError, IOError): |
290 | + continue |
291 | + |
292 | +@@ -287,12 +276,8 @@ def get_representor_port(pf_ifname, vf_num): |
293 | + # the PCI func number of pf_ifname. |
294 | + rep_parent_pf_func = _parse_pf_number(phys_port_name) |
295 | + if rep_parent_pf_func is not None: |
296 | +- ifname_pf_func = _get_pf_func(pf_ifname) |
297 | +- if ifname_pf_func is None: |
298 | +- continue |
299 | +- if int(rep_parent_pf_func) != int(ifname_pf_func): |
300 | +- continue |
301 | +- |
302 | ++ if int(rep_parent_pf_func) != int(ifname_pf_func): |
303 | ++ continue |
304 | + representor_num = _parse_vf_number(phys_port_name) |
305 | + # Note: representor_num can be 0, referring to VF0 |
306 | + if representor_num is None: |
307 | +@@ -321,9 +306,7 @@ def _get_sysfs_netdev_path(pci_addr, pf_interface): |
308 | + def _is_switchdev(netdev): |
309 | + """Returns True if a netdev has a readable phys_switch_id""" |
310 | + try: |
311 | +- sw_id_file = "/sys/class/net/%s/phys_switch_id" % netdev |
312 | +- with open(sw_id_file, 'r') as fd: |
313 | +- phys_switch_id = fd.readline().rstrip() |
314 | ++ phys_switch_id = _get_phys_switch_id(netdev) |
315 | + if phys_switch_id != "" and phys_switch_id is not None: |
316 | + return True |
317 | + except (OSError, IOError): |
318 | +@@ -389,3 +372,33 @@ def get_pf_pci_from_vf(vf_pci): |
319 | + """ |
320 | + physfn_path = os.readlink("/sys/bus/pci/devices/%s/physfn" % vf_pci) |
321 | + return os.path.basename(physfn_path) |
322 | ++ |
323 | ++ |
324 | ++def _get_phys_port_name(ifname): |
325 | ++ """Get the interface name and return its phys_port_name |
326 | ++ |
327 | ++ :param ifname: The interface name |
328 | ++ :return: The phys_port_name of the given ifname |
329 | ++ """ |
330 | ++ phys_port_name_path = "/sys/class/net/%s/phys_port_name" % ifname |
331 | ++ |
332 | ++ if not os.path.isfile(phys_port_name_path): |
333 | ++ return None |
334 | ++ |
335 | ++ with open(phys_port_name_path, 'r') as fd: |
336 | ++ return fd.readline().strip() |
337 | ++ |
338 | ++ |
339 | ++def _get_phys_switch_id(ifname): |
340 | ++ """Get the interface name and return its phys_switch_id |
341 | ++ |
342 | ++ :param ifname: The interface name |
343 | ++ :return: The phys_switch_id of the given ifname |
344 | ++ """ |
345 | ++ phys_port_name_path = "/sys/class/net/%s/phys_switch_id" % ifname |
346 | ++ |
347 | ++ if not os.path.isfile(phys_port_name_path): |
348 | ++ return None |
349 | ++ |
350 | ++ with open(phys_port_name_path, 'r') as fd: |
351 | ++ return fd.readline().strip() |
352 | +diff --git a/vif_plug_ovs/tests/unit/test_linux_net.py b/vif_plug_ovs/tests/unit/test_linux_net.py |
353 | +index 4eaa1f7..a5404ea 100644 |
354 | +--- a/vif_plug_ovs/tests/unit/test_linux_net.py |
355 | ++++ b/vif_plug_ovs/tests/unit/test_linux_net.py |
356 | +@@ -132,47 +132,22 @@ class LinuxNetTest(testtools.TestCase): |
357 | + linux_net.add_bridge_port("br0", "vnet1") |
358 | + mock_set.assert_called_once_with("vnet1", master="br0") |
359 | + |
360 | +- @mock.patch('six.moves.builtins.open') |
361 | +- @mock.patch.object(os.path, 'isfile') |
362 | +- def test_is_switchdev_ioerror(self, mock_isfile, mock_open): |
363 | +- mock_isfile.side_effect = [True] |
364 | +- mock_open.return_value.__enter__ = lambda s: s |
365 | +- readline_mock = mock_open.return_value.readline |
366 | +- readline_mock.side_effect = ( |
367 | +- [IOError()]) |
368 | ++ @mock.patch.object(linux_net, '_get_phys_switch_id') |
369 | ++ def test_is_switchdev_ioerror(self, mock__get_phys_switch_id): |
370 | ++ mock__get_phys_switch_id.side_effect = ([IOError()]) |
371 | + test_switchdev = linux_net._is_switchdev('pf_ifname') |
372 | + self.assertEqual(test_switchdev, False) |
373 | + |
374 | +- @mock.patch('six.moves.builtins.open') |
375 | +- @mock.patch.object(os.path, 'isfile') |
376 | +- def test_is_switchdev_empty(self, mock_isfile, mock_open): |
377 | +- mock_isfile.side_effect = [True] |
378 | +- mock_open.return_value.__enter__ = lambda s: s |
379 | +- readline_mock = mock_open.return_value.readline |
380 | +- readline_mock.side_effect = ( |
381 | +- ['']) |
382 | +- open_calls = ( |
383 | +- [mock.call('/sys/class/net/pf_ifname/phys_switch_id', 'r'), |
384 | +- mock.call().readline(), |
385 | +- mock.call().__exit__(None, None, None)]) |
386 | ++ @mock.patch.object(linux_net, '_get_phys_switch_id') |
387 | ++ def test_is_switchdev_empty(self, mock__get_phys_switch_id): |
388 | ++ mock__get_phys_switch_id.return_value = '' |
389 | + test_switchdev = linux_net._is_switchdev('pf_ifname') |
390 | +- mock_open.assert_has_calls(open_calls) |
391 | + self.assertEqual(test_switchdev, False) |
392 | + |
393 | +- @mock.patch('six.moves.builtins.open') |
394 | +- @mock.patch.object(os.path, 'isfile') |
395 | +- def test_is_switchdev_positive(self, mock_isfile, mock_open): |
396 | +- mock_isfile.side_effect = [True] |
397 | +- mock_open.return_value.__enter__ = lambda s: s |
398 | +- readline_mock = mock_open.return_value.readline |
399 | +- readline_mock.side_effect = ( |
400 | +- ['pf_sw_id']) |
401 | +- open_calls = ( |
402 | +- [mock.call('/sys/class/net/pf_ifname/phys_switch_id', 'r'), |
403 | +- mock.call().readline(), |
404 | +- mock.call().__exit__(None, None, None)]) |
405 | ++ @mock.patch.object(linux_net, '_get_phys_switch_id') |
406 | ++ def test_is_switchdev_positive(self, mock__get_phys_switch_id): |
407 | ++ mock__get_phys_switch_id.return_value = 'pf_sw_id' |
408 | + test_switchdev = linux_net._is_switchdev('pf_ifname') |
409 | +- mock_open.assert_has_calls(open_calls) |
410 | + self.assertEqual(test_switchdev, True) |
411 | + |
412 | + def test_parse_vf_number(self): |
413 | +@@ -191,184 +166,115 @@ class LinuxNetTest(testtools.TestCase): |
414 | + self.assertEqual(linux_net._parse_pf_number("pf31"), "31") |
415 | + self.assertIsNone(linux_net._parse_pf_number("g4rbl3d")) |
416 | + |
417 | +- @mock.patch('six.moves.builtins.open') |
418 | +- @mock.patch.object(os.path, 'isfile') |
419 | + @mock.patch.object(os, 'listdir') |
420 | +- @mock.patch.object(linux_net, "get_function_by_ifname") |
421 | +- def test_get_representor_port(self, mock_get_function_by_ifname, |
422 | +- mock_listdir, mock_isfile, mock_open): |
423 | ++ @mock.patch.object(linux_net, "_get_pf_func") |
424 | ++ @mock.patch.object(linux_net, "_get_phys_port_name") |
425 | ++ @mock.patch.object(linux_net, '_get_phys_switch_id') |
426 | ++ def test_get_representor_port(self, mock__get_phys_switch_id, |
427 | ++ mock__get_phys_port_name, |
428 | ++ mock__get_pf_func, |
429 | ++ mock_listdir): |
430 | + mock_listdir.return_value = [ |
431 | + 'pf_ifname', 'rep_vf_1', 'rep_vf_2' |
432 | + ] |
433 | +- mock_isfile.side_effect = [True, True] |
434 | +- mock_open.return_value.__enter__ = lambda s: s |
435 | +- readline_mock = mock_open.return_value.readline |
436 | +- readline_mock.side_effect = ( |
437 | +- ['pf_sw_id', 'pf_sw_id', '1', 'pf_sw_id', 'pf0vf2']) |
438 | +- # PCI IDs mocked: |
439 | +- # PF0: 0000:0a:00.0 |
440 | +- # PF0VF1: 0000:0a:02.1 PF0VF2: 0000:0a:02.2 |
441 | +- mock_get_function_by_ifname.side_effect = ( |
442 | +- [("0000:0a:00.0", True), |
443 | +- ("0000:0a:02.1", False), |
444 | +- ("0000:0a:02.2", False), ("0000:0a:00.0", True)]) |
445 | +- open_calls = ( |
446 | +- [mock.call('/sys/class/net/pf_ifname/phys_switch_id', 'r'), |
447 | +- mock.call().readline(), |
448 | +- mock.call().__exit__(None, None, None), |
449 | +- mock.call('/sys/class/net/rep_vf_1/phys_switch_id', 'r'), |
450 | +- mock.call().readline(), |
451 | +- mock.call().__exit__(None, None, None), |
452 | +- mock.call('/sys/class/net/rep_vf_1/phys_port_name', 'r'), |
453 | +- mock.call().readline(), |
454 | +- mock.call().__exit__(None, None, None), |
455 | +- mock.call('/sys/class/net/rep_vf_2/phys_switch_id', 'r'), |
456 | +- mock.call().readline(), |
457 | +- mock.call().__exit__(None, None, None), |
458 | +- mock.call('/sys/class/net/rep_vf_2/phys_port_name', 'r'), |
459 | +- mock.call().readline(), |
460 | +- mock.call().__exit__(None, None, None)]) |
461 | ++ mock__get_phys_switch_id.return_value = 'pf_sw_id' |
462 | ++ mock__get_pf_func.return_value = "0" |
463 | ++ mock__get_phys_port_name.side_effect = (['1', "pf0vf1", "pf0vf2"]) |
464 | + ifname = linux_net.get_representor_port('pf_ifname', '2') |
465 | +- mock_open.assert_has_calls(open_calls) |
466 | + self.assertEqual('rep_vf_2', ifname) |
467 | + |
468 | +- @mock.patch('six.moves.builtins.open') |
469 | +- @mock.patch.object(os.path, 'isfile') |
470 | + @mock.patch.object(os, 'listdir') |
471 | +- @mock.patch.object(linux_net, "get_function_by_ifname") |
472 | ++ @mock.patch.object(linux_net, "_get_pf_func") |
473 | ++ @mock.patch.object(linux_net, "_get_phys_port_name") |
474 | ++ @mock.patch.object(linux_net, "_get_phys_switch_id") |
475 | + def test_get_representor_port_2_pfs( |
476 | +- self, mock_get_function_by_ifname, mock_listdir, mock_isfile, |
477 | +- mock_open): |
478 | ++ self, mock__get_phys_switch_id, mock__get_phys_port_name, |
479 | ++ mock__get_pf_func, mock_listdir): |
480 | + mock_listdir.return_value = [ |
481 | + 'pf_ifname1', 'pf_ifname2', 'rep_pf1_vf_1', 'rep_pf1_vf_2', |
482 | + 'rep_pf2_vf_1', 'rep_pf2_vf_2', |
483 | + ] |
484 | +- mock_isfile.side_effect = [True, True, True, True] |
485 | +- mock_open.return_value.__enter__ = lambda s: s |
486 | +- readline_mock = mock_open.return_value.readline |
487 | +- readline_mock.side_effect = ( |
488 | +- ['pf_sw_id', |
489 | +- 'pf_sw_id', 'VF1@PF1', 'pf_sw_id', 'vf2@pf1', |
490 | +- 'pf_sw_id', 'pf2vf1', 'pf_sw_id', 'pf2vf2']) |
491 | +- # PCI IDs mocked: |
492 | +- # PF1: 0000:0a:00.1 PF2: 0000:0a:00.2 |
493 | +- # PF1VF1: 0000:0a:02.1 PF1VF2: 0000:0a:02.2 |
494 | +- # PF2VF1: 0000:0a:04.1 PF2VF2: 0000:0a:04.2 |
495 | +- mock_get_function_by_ifname.side_effect = ( |
496 | +- [("0000:0a:00.1", True), ("0000:0a:00.2", True), |
497 | +- ("0000:0a:02.1", False), ("0000:0a:00.2", True), |
498 | +- ("0000:0a:02.2", False), ("0000:0a:00.2", True), |
499 | +- ("0000:0a:04.1", False), ("0000:0a:00.2", True), |
500 | +- ("0000:0a:04.2", False), ("0000:0a:00.2", True)]) |
501 | ++ mock__get_phys_switch_id.return_value = 'pf_sw_id' |
502 | ++ mock__get_pf_func.return_value = "2" |
503 | ++ mock__get_phys_port_name.side_effect = ( |
504 | ++ ["p1", "p2", "VF1@PF1", "pf2vf1", "vf2@pf1", "pf2vf2"]) |
505 | + ifname = linux_net.get_representor_port('pf_ifname2', '2') |
506 | + self.assertEqual('rep_pf2_vf_2', ifname) |
507 | + |
508 | +- @mock.patch('six.moves.builtins.open') |
509 | +- @mock.patch.object(os.path, 'isfile') |
510 | + @mock.patch.object(os, 'listdir') |
511 | +- @mock.patch.object(linux_net, "get_function_by_ifname") |
512 | ++ @mock.patch.object(linux_net, "_get_pf_func") |
513 | ++ @mock.patch.object(linux_net, "_get_phys_switch_id") |
514 | ++ @mock.patch.object(linux_net, "_get_phys_port_name") |
515 | + def test_get_representor_port_not_found( |
516 | +- self, mock_get_function_by_ifname, mock_listdir, mock_isfile, |
517 | +- mock_open): |
518 | ++ self, mock__get_phys_port_name, mock__get_phys_switch_id, |
519 | ++ mock__get_pf_func, mock_listdir): |
520 | + mock_listdir.return_value = [ |
521 | + 'pf_ifname', 'rep_vf_1', 'rep_vf_2' |
522 | + ] |
523 | +- mock_isfile.side_effect = [True, True] |
524 | +- mock_open.return_value.__enter__ = lambda s: s |
525 | +- readline_mock = mock_open.return_value.readline |
526 | +- readline_mock.side_effect = ( |
527 | +- ['pf_sw_id', 'pf_sw_id', '1', 'pf_sw_id', '2']) |
528 | +- # PCI IDs mocked: |
529 | +- # PF0: 0000:0a:00.0 |
530 | +- # PF0VF1: 0000:0a:02.1 PF0VF2: 0000:0a:02.2 |
531 | +- mock_get_function_by_ifname.side_effect = ( |
532 | +- [("0000:0a:00.0", True), |
533 | +- ("0000:0a:02.1", False), |
534 | +- ("0000:0a:02.2", False)]) |
535 | ++ mock__get_phys_switch_id.return_value = 'pf_sw_id' |
536 | ++ mock__get_pf_func.return_value = "0" |
537 | ++ mock__get_phys_port_name.side_effect = ( |
538 | ++ ["p0", "1", "2"]) |
539 | + self.assertRaises( |
540 | + exception.RepresentorNotFound, |
541 | + linux_net.get_representor_port, |
542 | + 'pf_ifname', '3'), |
543 | + |
544 | +- @mock.patch('six.moves.builtins.open') |
545 | +- @mock.patch.object(os.path, 'isfile') |
546 | + @mock.patch.object(os, 'listdir') |
547 | +- @mock.patch.object(linux_net, "get_function_by_ifname") |
548 | ++ @mock.patch.object(linux_net, "_get_pf_func") |
549 | ++ @mock.patch.object(linux_net, "_get_phys_port_name") |
550 | ++ @mock.patch.object(linux_net, "_get_phys_switch_id") |
551 | + def test_get_representor_port_exception_io_error( |
552 | +- self, mock_get_function_by_ifname, mock_listdir, mock_isfile, |
553 | +- mock_open): |
554 | ++ self, mock__get_phys_switch_id, mock__get_phys_port_name, |
555 | ++ mock__get_pf_func, mock_listdir): |
556 | + mock_listdir.return_value = [ |
557 | + 'pf_ifname', 'rep_vf_1', 'rep_vf_2' |
558 | + ] |
559 | +- mock_isfile.side_effect = [True, True] |
560 | +- mock_open.return_value.__enter__ = lambda s: s |
561 | +- readline_mock = mock_open.return_value.readline |
562 | +- readline_mock.side_effect = ( |
563 | ++ mock__get_phys_switch_id.side_effect = ( |
564 | + ['pf_sw_id', 'pf_sw_id', IOError(), 'pf_sw_id', '2']) |
565 | +- # PCI IDs mocked: |
566 | +- # PF0: 0000:0a:00.0 |
567 | +- # PF0VF1: 0000:0a:02.1 PF0VF2: 0000:0a:02.2 |
568 | +- mock_get_function_by_ifname.side_effect = ( |
569 | +- [("0000:0a:00.0", True), |
570 | +- ("0000:0a:02.1", False), |
571 | +- ("0000:0a:02.2", False), ("0000:0a:00.0", True)]) |
572 | ++ mock__get_pf_func.return_value = "0" |
573 | ++ mock__get_phys_port_name.side_effect = ( |
574 | ++ ["p0", "pf0vf0", "pf0vf1"]) |
575 | + self.assertRaises( |
576 | + exception.RepresentorNotFound, |
577 | + linux_net.get_representor_port, |
578 | + 'pf_ifname', '3') |
579 | + |
580 | +- @mock.patch('six.moves.builtins.open') |
581 | +- @mock.patch.object(os.path, 'isfile') |
582 | + @mock.patch.object(os, 'listdir') |
583 | +- @mock.patch.object(linux_net, "get_function_by_ifname") |
584 | ++ @mock.patch.object(linux_net, "_get_pf_func") |
585 | ++ @mock.patch.object(linux_net, "_get_phys_port_name") |
586 | ++ @mock.patch.object(linux_net, "_get_phys_switch_id") |
587 | + def test_get_representor_port_exception_value_error( |
588 | +- self, mock_get_function_by_ifname, mock_listdir, mock_isfile, |
589 | +- mock_open): |
590 | ++ self, mock__get_phys_switch_id, mock__get_phys_port_name, |
591 | ++ mock__get_pf_func, mock_listdir): |
592 | + mock_listdir.return_value = [ |
593 | + 'pf_ifname', 'rep_vf_1', 'rep_vf_2' |
594 | + ] |
595 | +- mock_isfile.side_effect = [True, True] |
596 | +- mock_open.return_value.__enter__ = lambda s: s |
597 | +- readline_mock = mock_open.return_value.readline |
598 | +- readline_mock.side_effect = ( |
599 | +- ['pf_sw_id', 'pf_sw_id', '1', 'pf_sw_id', 'a']) |
600 | +- # PCI IDs mocked: |
601 | +- # PF0: 0000:0a:00.0 |
602 | +- # PF0VF1: 0000:0a:02.1 PF0VF2: 0000:0a:02.2 |
603 | +- mock_get_function_by_ifname.side_effect = ( |
604 | +- [("0000:0a:00.0", True), |
605 | +- ("0000:0a:02.1", False), |
606 | +- ("0000:0a:02.2", False)]) |
607 | ++ mock__get_phys_switch_id.return_value = 'pf_sw_id' |
608 | ++ mock__get_phys_port_name.side_effect = (['p0', '1', 'a']) |
609 | ++ mock__get_pf_func.return_value = "0" |
610 | + self.assertRaises( |
611 | + exception.RepresentorNotFound, |
612 | + linux_net.get_representor_port, |
613 | + 'pf_ifname', '3') |
614 | + |
615 | +- @mock.patch('six.moves.builtins.open') |
616 | +- @mock.patch.object(os.path, 'isfile') |
617 | + @mock.patch.object(os, 'listdir') |
618 | +- def test_physical_function_inferface_name( |
619 | +- self, mock_listdir, mock_isfile, mock_open): |
620 | ++ @mock.patch.object(linux_net, '_get_phys_switch_id') |
621 | ++ def test_physical_function_interface_name( |
622 | ++ self, mock__get_phys_switch_id, mock_listdir): |
623 | + mock_listdir.return_value = ['foo', 'bar'] |
624 | +- mock_isfile.side_effect = [True, True] |
625 | +- mock_open.return_value.__enter__ = lambda s: s |
626 | +- readline_mock = mock_open.return_value.readline |
627 | +- readline_mock.side_effect = ( |
628 | ++ mock__get_phys_switch_id.side_effect = ( |
629 | + ['', 'valid_switch']) |
630 | + ifname = linux_net.get_ifname_by_pci_address( |
631 | + '0000:00:00.1', pf_interface=True, switchdev=False) |
632 | + self.assertEqual(ifname, 'foo') |
633 | + |
634 | +- @mock.patch('six.moves.builtins.open') |
635 | +- @mock.patch.object(os.path, 'isfile') |
636 | + @mock.patch.object(os, 'listdir') |
637 | +- def test_physical_function_inferface_name_with_switchdev( |
638 | +- self, mock_listdir, mock_isfile, mock_open): |
639 | ++ @mock.patch.object(linux_net, '_get_phys_switch_id') |
640 | ++ def test_physical_function_interface_name_with_switchdev( |
641 | ++ self, mock__get_phys_switch_id, mock_listdir): |
642 | + mock_listdir.return_value = ['foo', 'bar'] |
643 | +- mock_isfile.side_effect = [True, True] |
644 | +- mock_open.return_value.__enter__ = lambda s: s |
645 | +- readline_mock = mock_open.return_value.readline |
646 | +- readline_mock.side_effect = ( |
647 | ++ mock__get_phys_switch_id.side_effect = ( |
648 | + ['', 'valid_switch']) |
649 | + ifname = linux_net.get_ifname_by_pci_address( |
650 | + '0000:00:00.1', pf_interface=True, switchdev=True) |
651 | +@@ -419,3 +325,35 @@ class LinuxNetTest(testtools.TestCase): |
652 | + linux_net.get_vf_num_by_pci_address, |
653 | + '0000:00:00.1' |
654 | + ) |
655 | ++ |
656 | ++ @mock.patch('builtins.open') |
657 | ++ @mock.patch.object(os.path, 'isfile') |
658 | ++ def test__get_phys_port_name(self, mock_isfile, mock_open): |
659 | ++ mock_open.return_value.__enter__ = lambda s: s |
660 | ++ readline_mock = mock_open.return_value.readline |
661 | ++ readline_mock.return_value = 'pf0vf0' |
662 | ++ mock_isfile.return_value = True |
663 | ++ phys_port_name = linux_net._get_phys_port_name("vf_ifname") |
664 | ++ self.assertEqual(phys_port_name, 'pf0vf0') |
665 | ++ |
666 | ++ @mock.patch.object(os.path, 'isfile') |
667 | ++ def test__get_phys_port_name_not_found(self, mock_isfile): |
668 | ++ mock_isfile.return_value = False |
669 | ++ phys_port_name = linux_net._get_phys_port_name("vf_ifname") |
670 | ++ self.assertIsNone(phys_port_name) |
671 | ++ |
672 | ++ @mock.patch('builtins.open') |
673 | ++ @mock.patch.object(os.path, 'isfile') |
674 | ++ def test__get_phys_switch_id(self, mock_isfile, mock_open): |
675 | ++ mock_open.return_value.__enter__ = lambda s: s |
676 | ++ readline_mock = mock_open.return_value.readline |
677 | ++ readline_mock.return_value = '66e40000039b0398' |
678 | ++ mock_isfile.return_value = True |
679 | ++ phys_port_name = linux_net._get_phys_switch_id("ifname") |
680 | ++ self.assertEqual(phys_port_name, '66e40000039b0398') |
681 | ++ |
682 | ++ @mock.patch.object(os.path, 'isfile') |
683 | ++ def test__get_phys_switch_id_not_found(self, mock_isfile): |
684 | ++ mock_isfile.return_value = False |
685 | ++ phys_port_name = linux_net._get_phys_switch_id("ifname") |
686 | ++ self.assertIsNone(phys_port_name) |
687 | +-- |
688 | +2.31.1 |
689 | diff --git a/debian/patches/series b/debian/patches/series |
690 | new file mode 100644 |
691 | index 0000000..2467eb6 |
692 | --- /dev/null |
693 | +++ b/debian/patches/series |
694 | @@ -0,0 +1,2 @@ |
695 | +Refactor-code-of-linux_net-to-more-cleaner-and-increase-performace.patch |
696 | +Fix-os-vif-fails-to-get-the-correct-UpLink-Representor.patch |