Merge ~fnordahl/ubuntu/+source/python-os-vif:bug/1892132-victoria into ~ubuntu-openstack-dev/ubuntu/+source/python-os-vif:stable/victoria
- Git
- lp:~fnordahl/ubuntu/+source/python-os-vif
- bug/1892132-victoria
- Merge into stable/victoria
Proposed by
Frode Nordahl
Status: | Merged | ||||
---|---|---|---|---|---|
Merge reported by: | Corey Bryant | ||||
Merged at revision: | 98b7c9312ffcbcec06d6880669be746f0e04633d | ||||
Proposed branch: | ~fnordahl/ubuntu/+source/python-os-vif:bug/1892132-victoria | ||||
Merge into: | ~ubuntu-openstack-dev/ubuntu/+source/python-os-vif:stable/victoria | ||||
Diff against target: |
687 lines (+661/-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 (+482/-0) debian/patches/series (+2/-0) |
||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Corey Bryant | Approve | ||
Review via email: mp+408212@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Corey Bryant (corey.bryant) : | # |
review:
Approve
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 7ff1394..7f75459 100644 |
3 | --- a/debian/changelog |
4 | +++ b/debian/changelog |
5 | @@ -1,3 +1,12 @@ |
6 | +python-os-vif (2.2.0-0ubuntu2.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.2.0-0ubuntu2.1) UNRELEASED; urgency=medium |
16 | |
17 | * d/gbp.conf: Create stable/victoria branch. |
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..31c4fdb |
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/55/759255/1 -> FETCH_HEAD |
26 | +From a28aafa796378b8a36ccb51d2c0010a44f622d14 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 b37de19c58c877f5174d76d0a4ba5ab519f464e8) |
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 448b08c..7c5e1a2 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 | +@@ -328,12 +330,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 63ee393..029087a 100644 |
120 | +--- a/vif_plug_ovs/tests/unit/test_linux_net.py |
121 | ++++ b/vif_plug_ovs/tests/unit/test_linux_net.py |
122 | +@@ -261,26 +261,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..46cc4d8 |
195 | --- /dev/null |
196 | +++ b/debian/patches/Refactor-code-of-linux_net-to-more-cleaner-and-increase-performace.patch |
197 | @@ -0,0 +1,482 @@ |
198 | +From https://review.opendev.org/openstack/os-vif |
199 | + * branch refs/changes/06/756406/1 -> FETCH_HEAD |
200 | +From 167bb030f1143f37ce189673d831bd572f64d4ad 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 | +Related-Bug: #1892132 |
218 | +Change-Id: I3fdbea4f48cb79ebfd03a4da21e2232ccafb7a76 |
219 | +(cherry picked from commit 76f7565b99e637d74878955a0033f35e9eb0e13f) |
220 | +--- |
221 | + vif_plug_ovs/linux_net.py | 72 ++++--- |
222 | + vif_plug_ovs/tests/unit/test_linux_net.py | 250 ++++++++-------------- |
223 | + 2 files changed, 137 insertions(+), 185 deletions(-) |
224 | + |
225 | +diff --git a/vif_plug_ovs/linux_net.py b/vif_plug_ovs/linux_net.py |
226 | +index 0d677a6..448b08c 100644 |
227 | +--- a/vif_plug_ovs/linux_net.py |
228 | ++++ b/vif_plug_ovs/linux_net.py |
229 | +@@ -239,46 +239,35 @@ def get_representor_port(pf_ifname, vf_num): |
230 | + VF number in the phys_port_name. That interface is the representor for |
231 | + the requested VF. |
232 | + """ |
233 | +- pf_path = "/sys/class/net/%s" % pf_ifname |
234 | +- pf_sw_id_file = os.path.join(pf_path, "phys_switch_id") |
235 | + |
236 | + pf_sw_id = None |
237 | + try: |
238 | +- with open(pf_sw_id_file, 'r') as fd: |
239 | +- pf_sw_id = fd.readline().rstrip() |
240 | ++ pf_sw_id = _get_phys_switch_id(pf_ifname) |
241 | + except (OSError, IOError): |
242 | + raise exception.RepresentorNotFound(ifname=pf_ifname, vf_num=vf_num) |
243 | + |
244 | +- pf_subsystem_file = os.path.join(pf_path, "subsystem") |
245 | ++ pf_subsystem_file = "/sys/class/net/%s/subsystem" % pf_ifname |
246 | + try: |
247 | + devices = os.listdir(pf_subsystem_file) |
248 | + except (OSError, IOError): |
249 | + raise exception.RepresentorNotFound(ifname=pf_ifname, vf_num=vf_num) |
250 | + |
251 | +- for device in devices: |
252 | +- address_str, pf = get_function_by_ifname(device) |
253 | +- if pf: |
254 | +- continue |
255 | ++ ifname_pf_func = _get_pf_func(pf_ifname) |
256 | ++ if ifname_pf_func is None: |
257 | ++ raise exception.RepresentorNotFound(ifname=pf_ifname, vf_num=vf_num) |
258 | + |
259 | +- device_path = "/sys/class/net/%s" % device |
260 | +- device_sw_id_file = os.path.join(device_path, "phys_switch_id") |
261 | ++ for device in devices: |
262 | + try: |
263 | +- with open(device_sw_id_file, 'r') as fd: |
264 | +- device_sw_id = fd.readline().rstrip() |
265 | ++ device_sw_id = _get_phys_switch_id(device) |
266 | ++ if not device_sw_id or device_sw_id != pf_sw_id: |
267 | ++ continue |
268 | + except (OSError, IOError): |
269 | + continue |
270 | + |
271 | +- if device_sw_id != pf_sw_id: |
272 | +- continue |
273 | +- device_port_name_file = ( |
274 | +- os.path.join(device_path, 'phys_port_name')) |
275 | +- |
276 | +- if not os.path.isfile(device_port_name_file): |
277 | +- continue |
278 | +- |
279 | + try: |
280 | +- with open(device_port_name_file, 'r') as fd: |
281 | +- phys_port_name = fd.readline().rstrip() |
282 | ++ phys_port_name = _get_phys_port_name(device) |
283 | ++ if phys_port_name is None: |
284 | ++ continue |
285 | + except (OSError, IOError): |
286 | + continue |
287 | + |
288 | +@@ -287,9 +276,6 @@ def get_representor_port(pf_ifname, vf_num): |
289 | + # the PCI func number of pf_ifname. |
290 | + rep_parent_pf_func = _parse_pf_number(phys_port_name) |
291 | + if rep_parent_pf_func is not None: |
292 | +- ifname_pf_func = _get_pf_func(pf_ifname) |
293 | +- if ifname_pf_func is None: |
294 | +- continue |
295 | + if int(rep_parent_pf_func) != int(ifname_pf_func): |
296 | + continue |
297 | + |
298 | +@@ -321,9 +307,7 @@ def _get_sysfs_netdev_path(pci_addr, pf_interface): |
299 | + def _is_switchdev(netdev): |
300 | + """Returns True if a netdev has a readable phys_switch_id""" |
301 | + try: |
302 | +- sw_id_file = "/sys/class/net/%s/phys_switch_id" % netdev |
303 | +- with open(sw_id_file, 'r') as fd: |
304 | +- phys_switch_id = fd.readline().rstrip() |
305 | ++ phys_switch_id = _get_phys_switch_id(netdev) |
306 | + if phys_switch_id != "" and phys_switch_id is not None: |
307 | + return True |
308 | + except (OSError, IOError): |
309 | +@@ -389,3 +373,33 @@ def get_pf_pci_from_vf(vf_pci): |
310 | + """ |
311 | + physfn_path = os.readlink("/sys/bus/pci/devices/%s/physfn" % vf_pci) |
312 | + return os.path.basename(physfn_path) |
313 | ++ |
314 | ++ |
315 | ++def _get_phys_port_name(ifname): |
316 | ++ """Get the interface name and return its phys_port_name |
317 | ++ |
318 | ++ :param ifname: The interface name |
319 | ++ :return: The phys_port_name of the given ifname |
320 | ++ """ |
321 | ++ phys_port_name_path = "/sys/class/net/%s/phys_port_name" % ifname |
322 | ++ |
323 | ++ if not os.path.isfile(phys_port_name_path): |
324 | ++ return None |
325 | ++ |
326 | ++ with open(phys_port_name_path, 'r') as fd: |
327 | ++ return fd.readline().strip() |
328 | ++ |
329 | ++ |
330 | ++def _get_phys_switch_id(ifname): |
331 | ++ """Get the interface name and return its phys_switch_id |
332 | ++ |
333 | ++ :param ifname: The interface name |
334 | ++ :return: The phys_switch_id of the given ifname |
335 | ++ """ |
336 | ++ phys_port_name_path = "/sys/class/net/%s/phys_switch_id" % ifname |
337 | ++ |
338 | ++ if not os.path.isfile(phys_port_name_path): |
339 | ++ return None |
340 | ++ |
341 | ++ with open(phys_port_name_path, 'r') as fd: |
342 | ++ return fd.readline().strip() |
343 | +diff --git a/vif_plug_ovs/tests/unit/test_linux_net.py b/vif_plug_ovs/tests/unit/test_linux_net.py |
344 | +index 659b1a2..63ee393 100644 |
345 | +--- a/vif_plug_ovs/tests/unit/test_linux_net.py |
346 | ++++ b/vif_plug_ovs/tests/unit/test_linux_net.py |
347 | +@@ -133,47 +133,22 @@ class LinuxNetTest(testtools.TestCase): |
348 | + linux_net.add_bridge_port("br0", "vnet1") |
349 | + mock_set.assert_called_once_with("vnet1", master="br0") |
350 | + |
351 | +- @mock.patch('builtins.open') |
352 | +- @mock.patch.object(os.path, 'isfile') |
353 | +- def test_is_switchdev_ioerror(self, mock_isfile, mock_open): |
354 | +- mock_isfile.side_effect = [True] |
355 | +- mock_open.return_value.__enter__ = lambda s: s |
356 | +- readline_mock = mock_open.return_value.readline |
357 | +- readline_mock.side_effect = ( |
358 | +- [IOError()]) |
359 | ++ @mock.patch.object(linux_net, '_get_phys_switch_id') |
360 | ++ def test_is_switchdev_ioerror(self, mock__get_phys_switch_id): |
361 | ++ mock__get_phys_switch_id.side_effect = ([IOError()]) |
362 | + test_switchdev = linux_net._is_switchdev('pf_ifname') |
363 | + self.assertEqual(test_switchdev, False) |
364 | + |
365 | +- @mock.patch('builtins.open') |
366 | +- @mock.patch.object(os.path, 'isfile') |
367 | +- def test_is_switchdev_empty(self, mock_isfile, mock_open): |
368 | +- mock_isfile.side_effect = [True] |
369 | +- mock_open.return_value.__enter__ = lambda s: s |
370 | +- readline_mock = mock_open.return_value.readline |
371 | +- readline_mock.side_effect = ( |
372 | +- ['']) |
373 | +- open_calls = ( |
374 | +- [mock.call('/sys/class/net/pf_ifname/phys_switch_id', 'r'), |
375 | +- mock.call().readline(), |
376 | +- mock.call().__exit__(None, None, None)]) |
377 | ++ @mock.patch.object(linux_net, '_get_phys_switch_id') |
378 | ++ def test_is_switchdev_empty(self, mock__get_phys_switch_id): |
379 | ++ mock__get_phys_switch_id.return_value = '' |
380 | + test_switchdev = linux_net._is_switchdev('pf_ifname') |
381 | +- mock_open.assert_has_calls(open_calls) |
382 | + self.assertEqual(test_switchdev, False) |
383 | + |
384 | +- @mock.patch('builtins.open') |
385 | +- @mock.patch.object(os.path, 'isfile') |
386 | +- def test_is_switchdev_positive(self, mock_isfile, mock_open): |
387 | +- mock_isfile.side_effect = [True] |
388 | +- mock_open.return_value.__enter__ = lambda s: s |
389 | +- readline_mock = mock_open.return_value.readline |
390 | +- readline_mock.side_effect = ( |
391 | +- ['pf_sw_id']) |
392 | +- open_calls = ( |
393 | +- [mock.call('/sys/class/net/pf_ifname/phys_switch_id', 'r'), |
394 | +- mock.call().readline(), |
395 | +- mock.call().__exit__(None, None, None)]) |
396 | ++ @mock.patch.object(linux_net, '_get_phys_switch_id') |
397 | ++ def test_is_switchdev_positive(self, mock__get_phys_switch_id): |
398 | ++ mock__get_phys_switch_id.return_value = 'pf_sw_id' |
399 | + test_switchdev = linux_net._is_switchdev('pf_ifname') |
400 | +- mock_open.assert_has_calls(open_calls) |
401 | + self.assertEqual(test_switchdev, True) |
402 | + |
403 | + def test_parse_vf_number(self): |
404 | +@@ -192,184 +167,115 @@ class LinuxNetTest(testtools.TestCase): |
405 | + self.assertEqual(linux_net._parse_pf_number("pf31"), "31") |
406 | + self.assertIsNone(linux_net._parse_pf_number("g4rbl3d")) |
407 | + |
408 | +- @mock.patch('builtins.open') |
409 | +- @mock.patch.object(os.path, 'isfile') |
410 | + @mock.patch.object(os, 'listdir') |
411 | +- @mock.patch.object(linux_net, "get_function_by_ifname") |
412 | +- def test_get_representor_port(self, mock_get_function_by_ifname, |
413 | +- mock_listdir, mock_isfile, mock_open): |
414 | ++ @mock.patch.object(linux_net, "_get_pf_func") |
415 | ++ @mock.patch.object(linux_net, "_get_phys_port_name") |
416 | ++ @mock.patch.object(linux_net, '_get_phys_switch_id') |
417 | ++ def test_get_representor_port(self, mock__get_phys_switch_id, |
418 | ++ mock__get_phys_port_name, |
419 | ++ mock__get_pf_func, |
420 | ++ mock_listdir): |
421 | + mock_listdir.return_value = [ |
422 | + 'pf_ifname', 'rep_vf_1', 'rep_vf_2' |
423 | + ] |
424 | +- mock_isfile.side_effect = [True, True] |
425 | +- mock_open.return_value.__enter__ = lambda s: s |
426 | +- readline_mock = mock_open.return_value.readline |
427 | +- readline_mock.side_effect = ( |
428 | +- ['pf_sw_id', 'pf_sw_id', '1', 'pf_sw_id', 'pf0vf2']) |
429 | +- # PCI IDs mocked: |
430 | +- # PF0: 0000:0a:00.0 |
431 | +- # PF0VF1: 0000:0a:02.1 PF0VF2: 0000:0a:02.2 |
432 | +- mock_get_function_by_ifname.side_effect = ( |
433 | +- [("0000:0a:00.0", True), |
434 | +- ("0000:0a:02.1", False), |
435 | +- ("0000:0a:02.2", False), ("0000:0a:00.0", True)]) |
436 | +- open_calls = ( |
437 | +- [mock.call('/sys/class/net/pf_ifname/phys_switch_id', 'r'), |
438 | +- mock.call().readline(), |
439 | +- mock.call().__exit__(None, None, None), |
440 | +- mock.call('/sys/class/net/rep_vf_1/phys_switch_id', 'r'), |
441 | +- mock.call().readline(), |
442 | +- mock.call().__exit__(None, None, None), |
443 | +- mock.call('/sys/class/net/rep_vf_1/phys_port_name', 'r'), |
444 | +- mock.call().readline(), |
445 | +- mock.call().__exit__(None, None, None), |
446 | +- mock.call('/sys/class/net/rep_vf_2/phys_switch_id', 'r'), |
447 | +- mock.call().readline(), |
448 | +- mock.call().__exit__(None, None, None), |
449 | +- mock.call('/sys/class/net/rep_vf_2/phys_port_name', 'r'), |
450 | +- mock.call().readline(), |
451 | +- mock.call().__exit__(None, None, None)]) |
452 | ++ mock__get_phys_switch_id.return_value = 'pf_sw_id' |
453 | ++ mock__get_pf_func.return_value = "0" |
454 | ++ mock__get_phys_port_name.side_effect = (['1', "pf0vf1", "pf0vf2"]) |
455 | + ifname = linux_net.get_representor_port('pf_ifname', '2') |
456 | +- mock_open.assert_has_calls(open_calls) |
457 | + self.assertEqual('rep_vf_2', ifname) |
458 | + |
459 | +- @mock.patch('builtins.open') |
460 | +- @mock.patch.object(os.path, 'isfile') |
461 | + @mock.patch.object(os, 'listdir') |
462 | +- @mock.patch.object(linux_net, "get_function_by_ifname") |
463 | ++ @mock.patch.object(linux_net, "_get_pf_func") |
464 | ++ @mock.patch.object(linux_net, "_get_phys_port_name") |
465 | ++ @mock.patch.object(linux_net, "_get_phys_switch_id") |
466 | + def test_get_representor_port_2_pfs( |
467 | +- self, mock_get_function_by_ifname, mock_listdir, mock_isfile, |
468 | +- mock_open): |
469 | ++ self, mock__get_phys_switch_id, mock__get_phys_port_name, |
470 | ++ mock__get_pf_func, mock_listdir): |
471 | + mock_listdir.return_value = [ |
472 | + 'pf_ifname1', 'pf_ifname2', 'rep_pf1_vf_1', 'rep_pf1_vf_2', |
473 | + 'rep_pf2_vf_1', 'rep_pf2_vf_2', |
474 | + ] |
475 | +- mock_isfile.side_effect = [True, True, True, True] |
476 | +- mock_open.return_value.__enter__ = lambda s: s |
477 | +- readline_mock = mock_open.return_value.readline |
478 | +- readline_mock.side_effect = ( |
479 | +- ['pf_sw_id', |
480 | +- 'pf_sw_id', 'VF1@PF1', 'pf_sw_id', 'vf2@pf1', |
481 | +- 'pf_sw_id', 'pf2vf1', 'pf_sw_id', 'pf2vf2']) |
482 | +- # PCI IDs mocked: |
483 | +- # PF1: 0000:0a:00.1 PF2: 0000:0a:00.2 |
484 | +- # PF1VF1: 0000:0a:02.1 PF1VF2: 0000:0a:02.2 |
485 | +- # PF2VF1: 0000:0a:04.1 PF2VF2: 0000:0a:04.2 |
486 | +- mock_get_function_by_ifname.side_effect = ( |
487 | +- [("0000:0a:00.1", True), ("0000:0a:00.2", True), |
488 | +- ("0000:0a:02.1", False), ("0000:0a:00.2", True), |
489 | +- ("0000:0a:02.2", False), ("0000:0a:00.2", True), |
490 | +- ("0000:0a:04.1", False), ("0000:0a:00.2", True), |
491 | +- ("0000:0a:04.2", False), ("0000:0a:00.2", True)]) |
492 | ++ mock__get_phys_switch_id.return_value = 'pf_sw_id' |
493 | ++ mock__get_pf_func.return_value = "2" |
494 | ++ mock__get_phys_port_name.side_effect = ( |
495 | ++ ["p1", "p2", "VF1@PF1", "pf2vf1", "vf2@pf1", "pf2vf2"]) |
496 | + ifname = linux_net.get_representor_port('pf_ifname2', '2') |
497 | + self.assertEqual('rep_pf2_vf_2', ifname) |
498 | + |
499 | +- @mock.patch('builtins.open') |
500 | +- @mock.patch.object(os.path, 'isfile') |
501 | + @mock.patch.object(os, 'listdir') |
502 | +- @mock.patch.object(linux_net, "get_function_by_ifname") |
503 | ++ @mock.patch.object(linux_net, "_get_pf_func") |
504 | ++ @mock.patch.object(linux_net, "_get_phys_switch_id") |
505 | ++ @mock.patch.object(linux_net, "_get_phys_port_name") |
506 | + def test_get_representor_port_not_found( |
507 | +- self, mock_get_function_by_ifname, mock_listdir, mock_isfile, |
508 | +- mock_open): |
509 | ++ self, mock__get_phys_port_name, mock__get_phys_switch_id, |
510 | ++ mock__get_pf_func, mock_listdir): |
511 | + mock_listdir.return_value = [ |
512 | + 'pf_ifname', 'rep_vf_1', 'rep_vf_2' |
513 | + ] |
514 | +- mock_isfile.side_effect = [True, True] |
515 | +- mock_open.return_value.__enter__ = lambda s: s |
516 | +- readline_mock = mock_open.return_value.readline |
517 | +- readline_mock.side_effect = ( |
518 | +- ['pf_sw_id', 'pf_sw_id', '1', 'pf_sw_id', '2']) |
519 | +- # PCI IDs mocked: |
520 | +- # PF0: 0000:0a:00.0 |
521 | +- # PF0VF1: 0000:0a:02.1 PF0VF2: 0000:0a:02.2 |
522 | +- mock_get_function_by_ifname.side_effect = ( |
523 | +- [("0000:0a:00.0", True), |
524 | +- ("0000:0a:02.1", False), |
525 | +- ("0000:0a:02.2", False)]) |
526 | ++ mock__get_phys_switch_id.return_value = 'pf_sw_id' |
527 | ++ mock__get_pf_func.return_value = "0" |
528 | ++ mock__get_phys_port_name.side_effect = ( |
529 | ++ ["p0", "1", "2"]) |
530 | + self.assertRaises( |
531 | + exception.RepresentorNotFound, |
532 | + linux_net.get_representor_port, |
533 | + 'pf_ifname', '3'), |
534 | + |
535 | +- @mock.patch('builtins.open') |
536 | +- @mock.patch.object(os.path, 'isfile') |
537 | + @mock.patch.object(os, 'listdir') |
538 | +- @mock.patch.object(linux_net, "get_function_by_ifname") |
539 | ++ @mock.patch.object(linux_net, "_get_pf_func") |
540 | ++ @mock.patch.object(linux_net, "_get_phys_port_name") |
541 | ++ @mock.patch.object(linux_net, "_get_phys_switch_id") |
542 | + def test_get_representor_port_exception_io_error( |
543 | +- self, mock_get_function_by_ifname, mock_listdir, mock_isfile, |
544 | +- mock_open): |
545 | ++ self, mock__get_phys_switch_id, mock__get_phys_port_name, |
546 | ++ mock__get_pf_func, mock_listdir): |
547 | + mock_listdir.return_value = [ |
548 | + 'pf_ifname', 'rep_vf_1', 'rep_vf_2' |
549 | + ] |
550 | +- mock_isfile.side_effect = [True, True] |
551 | +- mock_open.return_value.__enter__ = lambda s: s |
552 | +- readline_mock = mock_open.return_value.readline |
553 | +- readline_mock.side_effect = ( |
554 | ++ mock__get_phys_switch_id.side_effect = ( |
555 | + ['pf_sw_id', 'pf_sw_id', IOError(), 'pf_sw_id', '2']) |
556 | +- # PCI IDs mocked: |
557 | +- # PF0: 0000:0a:00.0 |
558 | +- # PF0VF1: 0000:0a:02.1 PF0VF2: 0000:0a:02.2 |
559 | +- mock_get_function_by_ifname.side_effect = ( |
560 | +- [("0000:0a:00.0", True), |
561 | +- ("0000:0a:02.1", False), |
562 | +- ("0000:0a:02.2", False), ("0000:0a:00.0", True)]) |
563 | ++ mock__get_pf_func.return_value = "0" |
564 | ++ mock__get_phys_port_name.side_effect = ( |
565 | ++ ["p0", "pf0vf0", "pf0vf1"]) |
566 | + self.assertRaises( |
567 | + exception.RepresentorNotFound, |
568 | + linux_net.get_representor_port, |
569 | + 'pf_ifname', '3') |
570 | + |
571 | +- @mock.patch('builtins.open') |
572 | +- @mock.patch.object(os.path, 'isfile') |
573 | + @mock.patch.object(os, 'listdir') |
574 | +- @mock.patch.object(linux_net, "get_function_by_ifname") |
575 | ++ @mock.patch.object(linux_net, "_get_pf_func") |
576 | ++ @mock.patch.object(linux_net, "_get_phys_port_name") |
577 | ++ @mock.patch.object(linux_net, "_get_phys_switch_id") |
578 | + def test_get_representor_port_exception_value_error( |
579 | +- self, mock_get_function_by_ifname, mock_listdir, mock_isfile, |
580 | +- mock_open): |
581 | ++ self, mock__get_phys_switch_id, mock__get_phys_port_name, |
582 | ++ mock__get_pf_func, mock_listdir): |
583 | + mock_listdir.return_value = [ |
584 | + 'pf_ifname', 'rep_vf_1', 'rep_vf_2' |
585 | + ] |
586 | +- mock_isfile.side_effect = [True, True] |
587 | +- mock_open.return_value.__enter__ = lambda s: s |
588 | +- readline_mock = mock_open.return_value.readline |
589 | +- readline_mock.side_effect = ( |
590 | +- ['pf_sw_id', 'pf_sw_id', '1', 'pf_sw_id', 'a']) |
591 | +- # PCI IDs mocked: |
592 | +- # PF0: 0000:0a:00.0 |
593 | +- # PF0VF1: 0000:0a:02.1 PF0VF2: 0000:0a:02.2 |
594 | +- mock_get_function_by_ifname.side_effect = ( |
595 | +- [("0000:0a:00.0", True), |
596 | +- ("0000:0a:02.1", False), |
597 | +- ("0000:0a:02.2", False)]) |
598 | ++ mock__get_phys_switch_id.return_value = 'pf_sw_id' |
599 | ++ mock__get_phys_port_name.side_effect = (['p0', '1', 'a']) |
600 | ++ mock__get_pf_func.return_value = "0" |
601 | + self.assertRaises( |
602 | + exception.RepresentorNotFound, |
603 | + linux_net.get_representor_port, |
604 | + 'pf_ifname', '3') |
605 | + |
606 | +- @mock.patch('builtins.open') |
607 | +- @mock.patch.object(os.path, 'isfile') |
608 | + @mock.patch.object(os, 'listdir') |
609 | +- def test_physical_function_inferface_name( |
610 | +- self, mock_listdir, mock_isfile, mock_open): |
611 | ++ @mock.patch.object(linux_net, '_get_phys_switch_id') |
612 | ++ def test_physical_function_interface_name( |
613 | ++ self, mock__get_phys_switch_id, mock_listdir): |
614 | + mock_listdir.return_value = ['foo', 'bar'] |
615 | +- mock_isfile.side_effect = [True, True] |
616 | +- mock_open.return_value.__enter__ = lambda s: s |
617 | +- readline_mock = mock_open.return_value.readline |
618 | +- readline_mock.side_effect = ( |
619 | ++ mock__get_phys_switch_id.side_effect = ( |
620 | + ['', 'valid_switch']) |
621 | + ifname = linux_net.get_ifname_by_pci_address( |
622 | + '0000:00:00.1', pf_interface=True, switchdev=False) |
623 | + self.assertEqual(ifname, 'foo') |
624 | + |
625 | +- @mock.patch('builtins.open') |
626 | +- @mock.patch.object(os.path, 'isfile') |
627 | + @mock.patch.object(os, 'listdir') |
628 | +- def test_physical_function_inferface_name_with_switchdev( |
629 | +- self, mock_listdir, mock_isfile, mock_open): |
630 | ++ @mock.patch.object(linux_net, '_get_phys_switch_id') |
631 | ++ def test_physical_function_interface_name_with_switchdev( |
632 | ++ self, mock__get_phys_switch_id, mock_listdir): |
633 | + mock_listdir.return_value = ['foo', 'bar'] |
634 | +- mock_isfile.side_effect = [True, True] |
635 | +- mock_open.return_value.__enter__ = lambda s: s |
636 | +- readline_mock = mock_open.return_value.readline |
637 | +- readline_mock.side_effect = ( |
638 | ++ mock__get_phys_switch_id.side_effect = ( |
639 | + ['', 'valid_switch']) |
640 | + ifname = linux_net.get_ifname_by_pci_address( |
641 | + '0000:00:00.1', pf_interface=True, switchdev=True) |
642 | +@@ -420,3 +326,35 @@ class LinuxNetTest(testtools.TestCase): |
643 | + linux_net.get_vf_num_by_pci_address, |
644 | + '0000:00:00.1' |
645 | + ) |
646 | ++ |
647 | ++ @mock.patch('builtins.open') |
648 | ++ @mock.patch.object(os.path, 'isfile') |
649 | ++ def test__get_phys_port_name(self, mock_isfile, mock_open): |
650 | ++ mock_open.return_value.__enter__ = lambda s: s |
651 | ++ readline_mock = mock_open.return_value.readline |
652 | ++ readline_mock.return_value = 'pf0vf0' |
653 | ++ mock_isfile.return_value = True |
654 | ++ phys_port_name = linux_net._get_phys_port_name("vf_ifname") |
655 | ++ self.assertEqual(phys_port_name, 'pf0vf0') |
656 | ++ |
657 | ++ @mock.patch.object(os.path, 'isfile') |
658 | ++ def test__get_phys_port_name_not_found(self, mock_isfile): |
659 | ++ mock_isfile.return_value = False |
660 | ++ phys_port_name = linux_net._get_phys_port_name("vf_ifname") |
661 | ++ self.assertIsNone(phys_port_name) |
662 | ++ |
663 | ++ @mock.patch('builtins.open') |
664 | ++ @mock.patch.object(os.path, 'isfile') |
665 | ++ def test__get_phys_switch_id(self, mock_isfile, mock_open): |
666 | ++ mock_open.return_value.__enter__ = lambda s: s |
667 | ++ readline_mock = mock_open.return_value.readline |
668 | ++ readline_mock.return_value = '66e40000039b0398' |
669 | ++ mock_isfile.return_value = True |
670 | ++ phys_port_name = linux_net._get_phys_switch_id("ifname") |
671 | ++ self.assertEqual(phys_port_name, '66e40000039b0398') |
672 | ++ |
673 | ++ @mock.patch.object(os.path, 'isfile') |
674 | ++ def test__get_phys_switch_id_not_found(self, mock_isfile): |
675 | ++ mock_isfile.return_value = False |
676 | ++ phys_port_name = linux_net._get_phys_switch_id("ifname") |
677 | ++ self.assertIsNone(phys_port_name) |
678 | +-- |
679 | +2.31.1 |
680 | diff --git a/debian/patches/series b/debian/patches/series |
681 | new file mode 100644 |
682 | index 0000000..2467eb6 |
683 | --- /dev/null |
684 | +++ b/debian/patches/series |
685 | @@ -0,0 +1,2 @@ |
686 | +Refactor-code-of-linux_net-to-more-cleaner-and-increase-performace.patch |
687 | +Fix-os-vif-fails-to-get-the-correct-UpLink-Representor.patch |