1 # Copyright (c) 2016-2017 Intel Corporation
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
20 from yardstick.common import exceptions
21 from yardstick.network_services.helpers.dpdkbindnic_helper import DpdkInterface
22 from yardstick.network_services.helpers.dpdkbindnic_helper import DpdkNode
23 from yardstick.network_services.helpers.dpdkbindnic_helper import DpdkBindHelper
24 from yardstick.network_services.helpers.dpdkbindnic_helper import DpdkBindHelperException
25 from yardstick.network_services.helpers.dpdkbindnic_helper import NETWORK_KERNEL
26 from yardstick.network_services.helpers.dpdkbindnic_helper import NETWORK_DPDK
27 from yardstick.network_services.helpers.dpdkbindnic_helper import CRYPTO_KERNEL
28 from yardstick.network_services.helpers.dpdkbindnic_helper import CRYPTO_DPDK
29 from yardstick.network_services.helpers.dpdkbindnic_helper import NETWORK_OTHER
30 from yardstick.network_services.helpers.dpdkbindnic_helper import CRYPTO_OTHER
36 class TestDpdkInterface(unittest.TestCase):
40 'address': '0a:de:ad:be:ef:f5',
44 'interface_name': 'enp11s0',
46 'pci_bus_id': '0000:0b:00.0',
47 'subsystem_device': '0x1533',
48 'subsystem_vendor': '0x15d9',
52 'address': '0a:de:ad:be:ef:f4',
56 'interface_name': 'lan',
58 'pci_bus_id': '0000:00:19.0',
59 'subsystem_device': '0x153a',
60 'subsystem_vendor': '0x15d9',
67 'address': 'fa:de:ad:be:ef:5b',
69 'driver': 'virtio_net',
71 'interface_name': 'eth1',
73 'pci_bus_id': '0000:00:04.0',
78 def test_parse_netdev_info(self):
80 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/ifindex:2
81 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/address:0a:de:ad:be:ef:f5
82 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/operstate:down
83 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/vendor:0x8086
84 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/device:0x1533
85 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/subsystem_vendor:0x15d9
86 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/subsystem_device:0x1533
87 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/driver:igb
88 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/pci_bus_id:0000:0b:00.0
89 /sys/devices/pci0000:00/0000:00:19.0/net/lan/ifindex:3
90 /sys/devices/pci0000:00/0000:00:19.0/net/lan/address:0a:de:ad:be:ef:f4
91 /sys/devices/pci0000:00/0000:00:19.0/net/lan/operstate:up
92 /sys/devices/pci0000:00/0000:00:19.0/net/lan/device/vendor:0x8086
93 /sys/devices/pci0000:00/0000:00:19.0/net/lan/device/device:0x153a
94 /sys/devices/pci0000:00/0000:00:19.0/net/lan/device/subsystem_vendor:0x15d9
95 /sys/devices/pci0000:00/0000:00:19.0/net/lan/device/subsystem_device:0x153a
96 /sys/devices/pci0000:00/0000:00:19.0/net/lan/driver:e1000e
97 /sys/devices/pci0000:00/0000:00:19.0/net/lan/pci_bus_id:0000:00:19.0
99 res = DpdkBindHelper.parse_netdev_info(output)
100 self.assertDictEqual(res, self.SAMPLE_NETDEVS)
102 def test_parse_netdev_info_virtio(self):
104 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/ifindex:3
105 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/address:fa:de:ad:be:ef:5b
106 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/operstate:down
107 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/device/vendor:0x1af4
108 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/device/device:0x0001
109 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/driver:virtio_net
111 res = DpdkBindHelper.parse_netdev_info(output)
112 self.assertDictEqual(res, self.SAMPLE_VM_NETDEVS)
114 def test_probe_missing_values(self):
115 mock_dpdk_node = mock.Mock()
116 mock_dpdk_node.netdevs = self.SAMPLE_NETDEVS.copy()
118 interface = {'local_mac': '0a:de:ad:be:ef:f5'}
119 dpdk_intf = DpdkInterface(mock_dpdk_node, interface)
121 dpdk_intf.probe_missing_values()
122 self.assertEqual(interface['vpci'], '0000:0b:00.0')
124 interface['local_mac'] = '0a:de:ad:be:ef:f4'
125 dpdk_intf.probe_missing_values()
126 self.assertEqual(interface['vpci'], '0000:00:19.0')
128 def test_probe_missing_values_no_update(self):
129 mock_dpdk_node = mock.Mock()
130 mock_dpdk_node.netdevs = self.SAMPLE_NETDEVS.copy()
131 del mock_dpdk_node.netdevs['enp11s0']['driver']
132 del mock_dpdk_node.netdevs['lan']['driver']
134 interface = {'local_mac': '0a:de:ad:be:ef:f5'}
135 dpdk_intf = DpdkInterface(mock_dpdk_node, interface)
137 dpdk_intf.probe_missing_values()
138 self.assertNotIn('vpci', interface)
139 self.assertNotIn('driver', interface)
141 def test_probe_missing_values_negative(self):
142 mock_dpdk_node = mock.Mock()
143 mock_dpdk_node.netdevs.values.side_effect = (
144 exceptions.IncorrectNodeSetup(error_msg=''))
146 interface = {'local_mac': '0a:de:ad:be:ef:f5'}
147 dpdk_intf = DpdkInterface(mock_dpdk_node, interface)
149 with self.assertRaises(exceptions.IncorrectConfig):
150 dpdk_intf.probe_missing_values()
153 class TestDpdkNode(unittest.TestCase):
157 'virtual-interface': {
162 'virtual-interface': {
167 'virtual-interface': {
173 def test_probe_dpdk_drivers(self):
174 mock_ssh_helper = mock.Mock()
175 mock_ssh_helper.execute.return_value = 0, '', ''
179 'virtual-interface': {
184 'virtual-interface': {
189 'virtual-interface': {
195 dpdk_node = DpdkNode(NAME, interfaces, mock_ssh_helper)
196 dpdk_helper = dpdk_node.dpdk_helper
198 dpdk_helper.probe_real_kernel_drivers = mock.Mock()
199 dpdk_helper.real_kernel_interface_driver_map = {
207 dpdk_node._probe_dpdk_drivers()
208 self.assertNotIn('driver', interfaces[0]['virtual-interface'])
209 self.assertEqual(interfaces[1]['virtual-interface']['driver'], 'driver2')
210 self.assertEqual(interfaces[2]['virtual-interface']['driver'], 'driver1')
212 def test_check(self):
214 if not mock_force_rebind.called:
215 raise exceptions.IncorrectConfig(error_msg='')
217 interfaces[0]['virtual-interface'].update({
218 'vpci': '0000:01:02.1',
219 'local_ip': '10.20.30.40',
220 'netmask': '255.255.0.0',
224 mock_ssh_helper = mock.Mock()
225 mock_ssh_helper.execute.return_value = 0, '', ''
229 'virtual-interface': {
234 dpdk_node = DpdkNode(NAME, interfaces, mock_ssh_helper)
235 dpdk_node._probe_missing_values = mock_probe_missing = mock.Mock(side_effect=update)
236 dpdk_node._force_rebind = mock_force_rebind = mock.Mock()
238 self.assertIsNone(dpdk_node.check())
239 self.assertEqual(mock_probe_missing.call_count, 2)
241 @mock.patch('yardstick.network_services.helpers.dpdkbindnic_helper.DpdkInterface')
242 def test_check_negative(self, mock_intf_type):
243 mock_ssh_helper = mock.Mock()
244 mock_ssh_helper.execute.return_value = 0, '', ''
246 mock_intf_type().check.side_effect = exceptions.SSHError
248 dpdk_node = DpdkNode(NAME, self.INTERFACES, mock_ssh_helper)
250 with self.assertRaises(exceptions.IncorrectSetup):
253 def test_probe_netdevs(self):
254 mock_ssh_helper = mock.Mock()
255 mock_ssh_helper.execute.return_value = 0, '', ''
257 expected = {'key1': 500, 'key2': 'hello world'}
258 update = {'key1': 1000, 'key3': []}
260 dpdk_node = DpdkNode(NAME, self.INTERFACES, mock_ssh_helper)
261 dpdk_helper = dpdk_node.dpdk_helper
262 dpdk_helper.find_net_devices = mock.Mock(side_effect=[expected, update])
264 self.assertDictEqual(dpdk_node.netdevs, {})
265 dpdk_node._probe_netdevs()
266 self.assertDictEqual(dpdk_node.netdevs, expected)
268 expected = {'key1': 1000, 'key2': 'hello world', 'key3': []}
269 dpdk_node._probe_netdevs()
270 self.assertDictEqual(dpdk_node.netdevs, expected)
272 def test_probe_netdevs_setup_negative(self):
273 mock_ssh_helper = mock.Mock()
274 mock_ssh_helper.execute.return_value = 0, '', ''
276 dpdk_node = DpdkNode(NAME, self.INTERFACES, mock_ssh_helper)
277 dpdk_helper = dpdk_node.dpdk_helper
278 dpdk_helper.find_net_devices = mock.Mock(side_effect=DpdkBindHelperException)
280 with self.assertRaises(DpdkBindHelperException):
281 dpdk_node._probe_netdevs()
283 def test_force_rebind(self):
284 mock_ssh_helper = mock.Mock()
285 mock_ssh_helper.execute.return_value = 0, '', ''
287 dpdk_node = DpdkNode(NAME, self.INTERFACES, mock_ssh_helper)
288 dpdk_helper = dpdk_node.dpdk_helper
289 dpdk_helper.force_dpdk_rebind = mock_helper_func = mock.Mock()
291 dpdk_node._force_rebind()
292 self.assertEqual(mock_helper_func.call_count, 1)
295 class TestDpdkBindHelper(unittest.TestCase):
296 bin_path = "/opt/nsb_bin"
299 Network devices using DPDK-compatible driver
300 ============================================
301 0000:00:04.0 'Virtio network device' drv=igb_uio unused=
302 0000:00:05.0 'Virtio network device' drv=igb_uio unused=
304 Network devices using kernel driver
305 ===================================
306 0000:00:03.0 'Virtio network device' if=ens3 drv=virtio-pci unused=igb_uio *Active*
308 Other network devices
309 =====================
312 Crypto devices using DPDK-compatible driver
313 ===========================================
316 Crypto devices using kernel driver
317 ==================================
328 'dev_type': 'Virtio network device',
332 'vpci': '0000:00:04.0',
335 'dev_type': 'Virtio network device',
339 'vpci': '0000:00:05.0',
344 'dev_type': 'Virtio network device',
345 'driver': 'virtio-pci',
348 'vpci': '0000:00:03.0',
366 ONE_INPUT_LINE = ("0000:00:03.0 'Virtio network device' if=ens3 "
367 "drv=virtio-pci unused=igb_uio *Active*")
369 ONE_INPUT_LINE_PARSED = [{
370 'vpci': '0000:00:03.0',
371 'dev_type': 'Virtio network device',
373 'driver': 'virtio-pci',
378 def test___init__(self):
380 conn.provision_tool = mock.Mock(return_value='path_to_tool')
381 conn.join_bin_path.return_value = os.path.join(self.bin_path, DpdkBindHelper.DPDK_DEVBIND)
383 dpdk_bind_helper = DpdkBindHelper(conn)
385 self.assertEqual(conn, dpdk_bind_helper.ssh_helper)
386 self.assertEqual(self.CLEAN_STATUS, dpdk_bind_helper.dpdk_status)
387 self.assertIsNone(dpdk_bind_helper.status_nic_row_re)
388 self.assertEqual(dpdk_bind_helper.dpdk_devbind,
389 os.path.join(self.bin_path, dpdk_bind_helper.DPDK_DEVBIND))
390 self.assertIsNone(dpdk_bind_helper._status_cmd_attr)
392 def test__dpdk_execute(self):
394 conn.execute = mock.Mock(return_value=(0, 'output', 'error'))
395 conn.provision_tool = mock.Mock(return_value='tool_path')
396 dpdk_bind_helper = DpdkBindHelper(conn)
397 self.assertEqual((0, 'output', 'error'), dpdk_bind_helper._dpdk_execute('command'))
399 def test__dpdk_execute_failure(self):
401 conn.execute = mock.Mock(return_value=(1, 'output', 'error'))
402 conn.provision_tool = mock.Mock(return_value='tool_path')
403 dpdk_bind_helper = DpdkBindHelper(conn)
404 with self.assertRaises(DpdkBindHelperException):
405 dpdk_bind_helper._dpdk_execute('command')
407 def test__addline(self):
410 dpdk_bind_helper = DpdkBindHelper(conn)
412 dpdk_bind_helper._add_line(NETWORK_KERNEL, self.ONE_INPUT_LINE)
414 self.assertIsNotNone(dpdk_bind_helper.dpdk_status)
415 self.assertEqual(self.ONE_INPUT_LINE_PARSED, dpdk_bind_helper.dpdk_status[NETWORK_KERNEL])
417 def test__switch_active_dict_by_header(self):
418 line = "Crypto devices using DPDK-compatible driver"
420 self.assertEqual(CRYPTO_DPDK, DpdkBindHelper._switch_active_dict(line, olddict))
422 def test__switch_active_dict_by_header_empty(self):
425 self.assertEqual(olddict, DpdkBindHelper._switch_active_dict(line, olddict))
427 def test_parse_dpdk_status_output(self):
430 dpdk_bind_helper = DpdkBindHelper(conn)
432 dpdk_bind_helper._parse_dpdk_status_output(self.EXAMPLE_OUTPUT)
435 self.assertEqual(self.PARSED_EXAMPLE, dpdk_bind_helper.dpdk_status)
437 def test_kernel_bound_pci_addresses(self):
438 mock_ssh_helper = mock.Mock()
439 mock_ssh_helper.execute.return_value = 0, '', ''
441 expected = ['a', 'b', 3]
443 dpdk_helper = DpdkBindHelper(mock_ssh_helper)
444 dpdk_helper.dpdk_status = {
445 NETWORK_DPDK: [{'vpci': 4}, {'vpci': 5}, {'vpci': 'g'}],
446 NETWORK_KERNEL: [{'vpci': 'a'}, {'vpci': 'b'}, {'vpci': 3}],
450 result = dpdk_helper.kernel_bound_pci_addresses
451 self.assertEqual(result, expected)
453 def test_find_net_devices_negative(self):
454 mock_ssh_helper = mock.Mock()
455 mock_ssh_helper.execute.return_value = 1, 'error', 'debug'
457 dpdk_helper = DpdkBindHelper(mock_ssh_helper)
459 self.assertDictEqual(dpdk_helper.find_net_devices(), {})
461 def test_read_status(self):
463 conn.execute = mock.Mock(return_value=(0, self.EXAMPLE_OUTPUT, ''))
464 conn.provision_tool = mock.Mock(return_value='path_to_tool')
466 dpdk_bind_helper = DpdkBindHelper(conn)
468 self.assertEqual(self.PARSED_EXAMPLE, dpdk_bind_helper.read_status())
470 def test__get_bound_pci_addresses(self):
473 dpdk_bind_helper = DpdkBindHelper(conn)
475 dpdk_bind_helper._parse_dpdk_status_output(self.EXAMPLE_OUTPUT)
477 self.assertEqual(['0000:00:04.0', '0000:00:05.0'],
478 dpdk_bind_helper._get_bound_pci_addresses(NETWORK_DPDK))
479 self.assertEqual(['0000:00:03.0'],
480 dpdk_bind_helper._get_bound_pci_addresses(NETWORK_KERNEL))
482 def test_interface_driver_map(self):
485 dpdk_bind_helper = DpdkBindHelper(conn)
487 dpdk_bind_helper._parse_dpdk_status_output(self.EXAMPLE_OUTPUT)
489 self.assertEqual({'0000:00:04.0': 'igb_uio',
490 '0000:00:03.0': 'virtio-pci',
491 '0000:00:05.0': 'igb_uio',
493 dpdk_bind_helper.interface_driver_map)
497 conn.execute = mock.Mock(return_value=(0, '', ''))
498 conn.join_bin_path.return_value = os.path.join(self.bin_path, DpdkBindHelper.DPDK_DEVBIND)
500 dpdk_bind_helper = DpdkBindHelper(conn)
501 dpdk_bind_helper.read_status = mock.Mock()
503 dpdk_bind_helper.bind(['0000:00:03.0', '0000:00:04.0'], 'my_driver')
505 conn.execute.assert_called_with('sudo /opt/nsb_bin/dpdk-devbind.py --force '
506 '-b my_driver 0000:00:03.0 0000:00:04.0')
507 dpdk_bind_helper.read_status.assert_called_once()
509 def test_bind_single_pci(self):
511 conn.execute = mock.Mock(return_value=(0, '', ''))
512 conn.join_bin_path.return_value = os.path.join(self.bin_path, DpdkBindHelper.DPDK_DEVBIND)
514 dpdk_bind_helper = DpdkBindHelper(conn)
515 dpdk_bind_helper.read_status = mock.Mock()
517 dpdk_bind_helper.bind('0000:00:03.0', 'my_driver')
519 conn.execute.assert_called_with('sudo /opt/nsb_bin/dpdk-devbind.py --force '
520 '-b my_driver 0000:00:03.0')
521 dpdk_bind_helper.read_status.assert_called_once()
523 def test_rebind_drivers(self):
526 dpdk_bind_helper = DpdkBindHelper(conn)
528 dpdk_bind_helper.bind = mock.Mock()
529 dpdk_bind_helper.used_drivers = {
530 'd1': ['0000:05:00.0'],
531 'd3': ['0000:05:01.0', '0000:05:02.0'],
534 dpdk_bind_helper.rebind_drivers()
536 dpdk_bind_helper.bind.assert_any_call(['0000:05:00.0'], 'd1', True)
537 dpdk_bind_helper.bind.assert_any_call(['0000:05:01.0', '0000:05:02.0'], 'd3', True)
539 def test_save_used_drivers(self):
541 dpdk_bind_helper = DpdkBindHelper(conn)
542 dpdk_bind_helper.dpdk_status = self.PARSED_EXAMPLE
544 dpdk_bind_helper.save_used_drivers()
547 'igb_uio': ['0000:00:04.0', '0000:00:05.0'],
548 'virtio-pci': ['0000:00:03.0'],
551 self.assertDictEqual(expected, dpdk_bind_helper.used_drivers)
553 def test_force_dpdk_rebind(self):
554 mock_ssh_helper = mock.Mock()
555 mock_ssh_helper.execute.return_value = 0, '', ''
557 dpdk_helper = DpdkBindHelper(mock_ssh_helper, 'driver2')
558 dpdk_helper.dpdk_status = {
574 dpdk_helper.real_kernel_interface_driver_map = {
575 'pci1': 'real_driver1',
576 'pci2': 'real_driver2',
577 'pci3': 'real_driver1',
578 'pci4': 'real_driver4',
579 'pci6': 'real_driver6',
581 dpdk_helper.load_dpdk_driver = mock.Mock()
582 dpdk_helper.read_status = mock.Mock()
583 dpdk_helper.save_real_kernel_interface_driver_map = mock.Mock()
584 dpdk_helper.save_used_drivers = mock.Mock()
585 dpdk_helper.bind = mock_bind = mock.Mock()
587 dpdk_helper.force_dpdk_rebind()
588 self.assertEqual(mock_bind.call_count, 2)
590 def test_save_real_kernel_drivers(self):
591 mock_ssh_helper = mock.Mock()
592 mock_ssh_helper.execute.return_value = 0, '', ''
594 dpdk_helper = DpdkBindHelper(mock_ssh_helper)
595 dpdk_helper.real_kernel_drivers = {
598 dpdk_helper.real_kernel_interface_driver_map = {
605 # save_used_drivers must be called before save_real_kernel_drivers can be
606 with self.assertRaises(AttributeError):
607 dpdk_helper.save_real_kernel_drivers()
609 dpdk_helper.save_used_drivers()
611 expected_used_drivers = {
612 'AAA': ['abc', 'abs'],
616 dpdk_helper.save_real_kernel_drivers()
617 self.assertDictEqual(dpdk_helper.used_drivers, expected_used_drivers)
618 self.assertDictEqual(dpdk_helper.real_kernel_drivers, {})
620 def test_get_real_kernel_driver(self):
621 mock_ssh_helper = mock.Mock()
622 mock_ssh_helper.execute.side_effect = [
623 (0, 'non-matching text', ''),
624 (0, 'pre Kernel modules: real_driver1', ''),
625 (0, 'before Ethernet middle Virtio network device after', ''),
628 dpdk_helper = DpdkBindHelper(mock_ssh_helper)
630 self.assertIsNone(dpdk_helper.get_real_kernel_driver('abc'))
631 self.assertEqual(dpdk_helper.get_real_kernel_driver('abc'), 'real_driver1')
632 self.assertEqual(dpdk_helper.get_real_kernel_driver('abc'), DpdkBindHelper.VIRTIO_DRIVER)