def test_kernel_bound_pci_addresses(self): mock_ssh_helper = mock.Mock() mock_ssh_helper.execute.return_value = 0, '', '' expected = ['a', 'b', 3] dpdk_helper = DpdkBindHelper(mock_ssh_helper) dpdk_helper.dpdk_status = { NETWORK_DPDK: [{ 'vpci': 4 }, { 'vpci': 5 }, { 'vpci': 'g' }], NETWORK_KERNEL: [{ 'vpci': 'a' }, { 'vpci': 'b' }, { 'vpci': 3 }], CRYPTO_DPDK: [], } result = dpdk_helper.kernel_bound_pci_addresses self.assertEqual(result, expected)
def test__dpdk_execute(self): conn = mock.Mock() conn.execute = mock.Mock(return_value=(0, 'output', 'error')) conn.provision_tool = mock.Mock(return_value='tool_path') dpdk_bind_helper = DpdkBindHelper(conn) self.assertEqual((0, 'output', 'error'), dpdk_bind_helper._dpdk_execute('command'))
def test_save_real_kernel_drivers(self): mock_ssh_helper = mock.Mock() mock_ssh_helper.execute.return_value = 0, '', '' dpdk_helper = DpdkBindHelper(mock_ssh_helper) dpdk_helper.real_kernel_drivers = { 'abc': '123', } dpdk_helper.real_kernel_interface_driver_map = { 'abc': 'AAA', 'def': 'DDD', 'abs': 'AAA', 'ghi': 'GGG', } # save_used_drivers must be called before save_real_kernel_drivers can be with self.assertRaises(AttributeError): dpdk_helper.save_real_kernel_drivers() dpdk_helper.save_used_drivers() expected_used_drivers = { 'AAA': ['abc', 'abs'], 'DDD': ['def'], 'GGG': ['ghi'], } dpdk_helper.save_real_kernel_drivers() self.assertDictEqual(dpdk_helper.used_drivers, expected_used_drivers) self.assertDictEqual(dpdk_helper.real_kernel_drivers, {})
def test__dpdk_execute_failure(self): conn = mock.Mock() conn.execute = mock.Mock(return_value=(1, 'output', 'error')) conn.provision_tool = mock.Mock(return_value='tool_path') dpdk_bind_helper = DpdkBindHelper(conn) with self.assertRaises(DpdkBindHelperException): dpdk_bind_helper._dpdk_execute('command')
def __init__(self, vnfd_helper, ssh_helper, scenario_helper): super(DpdkVnfSetupEnvHelper, self).__init__(vnfd_helper, ssh_helper, scenario_helper) self.all_ports = None self.bound_pci = None self.socket = None self.used_drivers = None self.dpdk_bind_helper = DpdkBindHelper(ssh_helper)
def test_find_net_devices_negative(self): mock_ssh_helper = mock.Mock() mock_ssh_helper.execute.return_value = 1, 'error', 'debug' dpdk_helper = DpdkBindHelper(mock_ssh_helper) self.assertDictEqual(dpdk_helper.find_net_devices(), {})
def test_read_status(self): conn = mock.Mock() conn.execute = mock.Mock(return_value=(0, self.EXAMPLE_OUTPUT, '')) conn.provision_tool = mock.Mock(return_value='path_to_tool') dpdk_bind_helper = DpdkBindHelper(conn) self.assertEqual(self.PARSED_EXAMPLE, dpdk_bind_helper.read_status())
def test_parse_dpdk_status_output(self): conn = mock.Mock() dpdk_bind_helper = DpdkBindHelper(conn) dpdk_bind_helper._parse_dpdk_status_output(self.EXAMPLE_OUTPUT) self.maxDiff = None self.assertEqual(self.PARSED_EXAMPLE, dpdk_bind_helper.dpdk_status)
def test__addline(self): conn = mock.Mock() dpdk_bind_helper = DpdkBindHelper(conn) dpdk_bind_helper._add_line(NETWORK_KERNEL, self.ONE_INPUT_LINE) self.assertIsNotNone(dpdk_bind_helper.dpdk_status) self.assertEqual(self.ONE_INPUT_LINE_PARSED, dpdk_bind_helper.dpdk_status[NETWORK_KERNEL])
def test_save_used_drivers(self): conn = mock.Mock() dpdk_bind_helper = DpdkBindHelper(conn) dpdk_bind_helper.dpdk_status = self.PARSED_EXAMPLE dpdk_bind_helper.save_used_drivers() expected = { 'igb_uio': ['0000:00:04.0', '0000:00:05.0'], 'virtio-pci': ['0000:00:03.0'], } self.assertDictEqual(expected, dpdk_bind_helper.used_drivers)
def test_interface_driver_map(self): conn = mock.Mock() dpdk_bind_helper = DpdkBindHelper(conn) dpdk_bind_helper._parse_dpdk_status_output(self.EXAMPLE_OUTPUT) self.assertEqual( { '0000:00:04.0': 'igb_uio', '0000:00:03.0': 'virtio-pci', '0000:00:05.0': 'igb_uio', }, dpdk_bind_helper.interface_driver_map)
def test_bind_single_pci(self): conn = mock.Mock() conn.execute = mock.Mock(return_value=(0, '', '')) conn.join_bin_path.return_value = os.path.join( self.bin_path, DpdkBindHelper.DPDK_DEVBIND) dpdk_bind_helper = DpdkBindHelper(conn) dpdk_bind_helper.read_status = mock.Mock() dpdk_bind_helper.bind('0000:00:03.0', 'my_driver') conn.execute.assert_called_with( 'sudo /opt/nsb_bin/dpdk-devbind.py --force ' '-b my_driver 0000:00:03.0') dpdk_bind_helper.read_status.assert_called_once()
def test_bind_single_pci(self): conn = mock.Mock() conn.execute = mock.Mock(return_value=(0, '', '')) conn.provision_tool = mock.Mock( return_value='/opt/nsb_bin/dpdk-devbind.py') dpdk_bind_helper = DpdkBindHelper(conn) dpdk_bind_helper.read_status = mock.Mock() dpdk_bind_helper.bind('0000:00:03.0', 'my_driver') conn.execute.assert_called_with( 'sudo /opt/nsb_bin/dpdk-devbind.py --force ' '-b my_driver 0000:00:03.0') dpdk_bind_helper.read_status.assert_called_once()
def test_get_real_kernel_driver(self): mock_ssh_helper = mock.Mock() mock_ssh_helper.execute.side_effect = [ (0, 'non-matching text', ''), (0, 'pre Kernel modules: real_driver1', ''), (0, 'before Ethernet middle Virtio network device after', ''), ] dpdk_helper = DpdkBindHelper(mock_ssh_helper) self.assertIsNone(dpdk_helper.get_real_kernel_driver('abc')) self.assertEqual(dpdk_helper.get_real_kernel_driver('abc'), 'real_driver1') self.assertEqual(dpdk_helper.get_real_kernel_driver('abc'), DpdkBindHelper.VIRTIO_DRIVER)
def test_parse_netdev_info_virtio(self): output = """\ /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/ifindex:3 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/address:fa:de:ad:be:ef:5b /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/operstate:down /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/device/vendor:0x1af4 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/device/device:0x0001 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/driver:virtio_net """ res = DpdkBindHelper.parse_netdev_info(output) self.assertDictEqual(res, self.SAMPLE_VM_NETDEVS)
def test___init__(self): conn = mock.Mock() conn.provision_tool = mock.Mock(return_value='path_to_tool') dpdk_bind_helper = DpdkBindHelper(conn) self.assertEquals(conn, dpdk_bind_helper.ssh_helper) self.assertEquals(self.CLEAN_STATUS, dpdk_bind_helper.dpdk_status) self.assertIsNone(dpdk_bind_helper.status_nic_row_re) self.assertIsNone(dpdk_bind_helper._dpdk_nic_bind_attr) self.assertIsNone(dpdk_bind_helper._status_cmd_attr)
def test___init__(self): conn = mock.Mock() conn.provision_tool = mock.Mock(return_value='path_to_tool') conn.join_bin_path.return_value = os.path.join( self.bin_path, DpdkBindHelper.DPDK_DEVBIND) dpdk_bind_helper = DpdkBindHelper(conn) self.assertEqual(conn, dpdk_bind_helper.ssh_helper) self.assertEqual(self.CLEAN_STATUS, dpdk_bind_helper.dpdk_status) self.assertIsNone(dpdk_bind_helper.status_nic_row_re) self.assertEqual( dpdk_bind_helper.dpdk_devbind, os.path.join(self.bin_path, dpdk_bind_helper.DPDK_DEVBIND)) self.assertIsNone(dpdk_bind_helper._status_cmd_attr)
def test_force_dpdk_rebind(self): mock_ssh_helper = mock.Mock() mock_ssh_helper.execute.return_value = 0, '', '' dpdk_helper = DpdkBindHelper(mock_ssh_helper, 'driver2') dpdk_helper.dpdk_status = { NETWORK_DPDK: [ { 'vpci': 'pci1', }, { 'vpci': 'pci3', }, { 'vpci': 'pci6', }, { 'vpci': 'pci3', }, ] } dpdk_helper.real_kernel_interface_driver_map = { 'pci1': 'real_driver1', 'pci2': 'real_driver2', 'pci3': 'real_driver1', 'pci4': 'real_driver4', 'pci6': 'real_driver6', } dpdk_helper.load_dpdk_driver = mock.Mock() dpdk_helper.read_status = mock.Mock() dpdk_helper.save_real_kernel_interface_driver_map = mock.Mock() dpdk_helper.save_used_drivers = mock.Mock() dpdk_helper.bind = mock_bind = mock.Mock() dpdk_helper.force_dpdk_rebind() self.assertEqual(mock_bind.call_count, 2)
def test__get_bound_pci_addresses(self): conn = mock.Mock() dpdk_bind_helper = DpdkBindHelper(conn) dpdk_bind_helper._parse_dpdk_status_output(self.EXAMPLE_OUTPUT) self.assertEqual( ['0000:00:04.0', '0000:00:05.0'], dpdk_bind_helper._get_bound_pci_addresses(NETWORK_DPDK)) self.assertEqual( ['0000:00:03.0'], dpdk_bind_helper._get_bound_pci_addresses(NETWORK_KERNEL))
def test_rebind_drivers(self): conn = mock.Mock() dpdk_bind_helper = DpdkBindHelper(conn) dpdk_bind_helper.bind = mock.Mock() dpdk_bind_helper.used_drivers = { 'd1': ['0000:05:00.0'], 'd3': ['0000:05:01.0', '0000:05:02.0'], } dpdk_bind_helper.rebind_drivers() dpdk_bind_helper.bind.assert_any_call(['0000:05:00.0'], 'd1', True) dpdk_bind_helper.bind.assert_any_call(['0000:05:01.0', '0000:05:02.0'], 'd3', True)
def test_parse_netdev_info(self): output = """\ /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/ifindex:2 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/address:0a:de:ad:be:ef:f5 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/operstate:down /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/vendor:0x8086 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/device:0x1533 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/subsystem_vendor:0x15d9 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/subsystem_device:0x1533 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/driver:igb /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/pci_bus_id:0000:0b:00.0 /sys/devices/pci0000:00/0000:00:19.0/net/lan/ifindex:3 /sys/devices/pci0000:00/0000:00:19.0/net/lan/address:0a:de:ad:be:ef:f4 /sys/devices/pci0000:00/0000:00:19.0/net/lan/operstate:up /sys/devices/pci0000:00/0000:00:19.0/net/lan/device/vendor:0x8086 /sys/devices/pci0000:00/0000:00:19.0/net/lan/device/device:0x153a /sys/devices/pci0000:00/0000:00:19.0/net/lan/device/subsystem_vendor:0x15d9 /sys/devices/pci0000:00/0000:00:19.0/net/lan/device/subsystem_device:0x153a /sys/devices/pci0000:00/0000:00:19.0/net/lan/driver:e1000e /sys/devices/pci0000:00/0000:00:19.0/net/lan/pci_bus_id:0000:00:19.0 """ res = DpdkBindHelper.parse_netdev_info(output) self.assertDictEqual(res, self.SAMPLE_NETDEVS)
class DpdkVnfSetupEnvHelper(SetupEnvHelper): APP_NAME = 'DpdkVnf' FIND_NET_CMD = "find /sys/class/net -lname '*{}*' -printf '%f'" NR_HUGEPAGES_PATH = '/proc/sys/vm/nr_hugepages' @staticmethod def _update_packet_type(ip_pipeline_cfg, traffic_options): match_str = 'pkt_type = ipv4' replace_str = 'pkt_type = {0}'.format(traffic_options['pkt_type']) pipeline_config_str = ip_pipeline_cfg.replace(match_str, replace_str) return pipeline_config_str @classmethod def _update_traffic_type(cls, ip_pipeline_cfg, traffic_options): traffic_type = traffic_options['traffic_type'] if traffic_options['vnf_type'] is not cls.APP_NAME: match_str = 'traffic_type = 4' replace_str = 'traffic_type = {0}'.format(traffic_type) elif traffic_type == 4: match_str = 'pkt_type = ipv4' replace_str = 'pkt_type = ipv4' else: match_str = 'pkt_type = ipv4' replace_str = 'pkt_type = ipv6' pipeline_config_str = ip_pipeline_cfg.replace(match_str, replace_str) return pipeline_config_str def __init__(self, vnfd_helper, ssh_helper, scenario_helper): super(DpdkVnfSetupEnvHelper, self).__init__(vnfd_helper, ssh_helper, scenario_helper) self.all_ports = None self.bound_pci = None self.socket = None self.used_drivers = None self.dpdk_bind_helper = DpdkBindHelper(ssh_helper) def _setup_hugepages(self): meminfo = utils.read_meminfo(self.ssh_helper) hp_size_kb = int(meminfo['Hugepagesize']) hugepages_gb = self.scenario_helper.all_options.get('hugepages_gb', 16) nr_hugepages = int(abs(hugepages_gb * 1024 * 1024 / hp_size_kb)) self.ssh_helper.execute('echo %s | sudo tee %s' % (nr_hugepages, self.NR_HUGEPAGES_PATH)) hp = six.BytesIO() self.ssh_helper.get_file_obj(self.NR_HUGEPAGES_PATH, hp) nr_hugepages_set = int(hp.getvalue().decode('utf-8').splitlines()[0]) LOG.info('Hugepages size (kB): %s, number claimed: %s, number set: %s', hp_size_kb, nr_hugepages, nr_hugepages_set) def build_config(self): vnf_cfg = self.scenario_helper.vnf_cfg task_path = self.scenario_helper.task_path config_file = vnf_cfg.get('file') lb_count = vnf_cfg.get('lb_count', 3) lb_config = vnf_cfg.get('lb_config', 'SW') worker_config = vnf_cfg.get('worker_config', '1C/1T') worker_threads = vnf_cfg.get('worker_threads', 3) traffic_type = self.scenario_helper.all_options.get('traffic_type', 4) traffic_options = { 'traffic_type': traffic_type, 'pkt_type': 'ipv%s' % traffic_type, 'vnf_type': self.VNF_TYPE, } # read actions/rules from file acl_options = None acl_file_name = self.scenario_helper.options.get('rules') if acl_file_name: with utils.open_relative_file(acl_file_name, task_path) as infile: acl_options = yaml_loader.yaml_load(infile) config_tpl_cfg = utils.find_relative_file(self.DEFAULT_CONFIG_TPL_CFG, task_path) config_basename = posixpath.basename(self.CFG_CONFIG) script_basename = posixpath.basename(self.CFG_SCRIPT) multiport = MultiPortConfig(self.scenario_helper.topology, config_tpl_cfg, config_basename, self.vnfd_helper, self.VNF_TYPE, lb_count, worker_threads, worker_config, lb_config, self.socket) multiport.generate_config() if config_file: with utils.open_relative_file(config_file, task_path) as infile: new_config = ['[EAL]'] vpci = [] for port in self.vnfd_helper.port_pairs.all_ports: interface = self.vnfd_helper.find_interface(name=port) vpci.append(interface['virtual-interface']["vpci"]) new_config.extend('w = {0}'.format(item) for item in vpci) new_config = '\n'.join(new_config) + '\n' + infile.read() else: with open(self.CFG_CONFIG) as handle: new_config = handle.read() new_config = self._update_traffic_type(new_config, traffic_options) new_config = self._update_packet_type(new_config, traffic_options) self.ssh_helper.upload_config_file(config_basename, new_config) self.ssh_helper.upload_config_file(script_basename, multiport.generate_script(self.vnfd_helper, self.get_flows_config(acl_options))) LOG.info("Provision and start the %s", self.APP_NAME) self._build_pipeline_kwargs() return self.PIPELINE_COMMAND.format(**self.pipeline_kwargs) def get_flows_config(self, options=None): # pylint: disable=unused-argument """No actions/rules (flows) by default""" return None def _build_pipeline_kwargs(self): tool_path = self.ssh_helper.provision_tool(tool_file=self.APP_NAME) # count the number of actual ports in the list of pairs # remove duplicate ports # this is really a mapping from LINK ID to DPDK PMD ID # e.g. 0x110 maps LINK0 -> PMD_ID_1, LINK1 -> PMD_ID_2 # 0x1010 maps LINK0 -> PMD_ID_1, LINK1 -> PMD_ID_3 ports = self.vnfd_helper.port_pairs.all_ports port_nums = self.vnfd_helper.port_nums(ports) # create mask from all the dpdk port numbers ports_mask_hex = hex(sum(2 ** num for num in port_nums)) vnf_cfg = self.scenario_helper.vnf_cfg lb_config = vnf_cfg.get('lb_config', 'SW') worker_threads = vnf_cfg.get('worker_threads', 3) hwlb = '' if lb_config == 'HW': hwlb = ' --hwlb %s' % worker_threads self.pipeline_kwargs = { 'cfg_file': self.CFG_CONFIG, 'script': self.CFG_SCRIPT, 'port_mask_hex': ports_mask_hex, 'tool_path': tool_path, 'hwlb': hwlb, } def setup_vnf_environment(self): self._setup_dpdk() self.kill_vnf() # bind before _setup_resources so we can use dpdk_port_num self._detect_and_bind_drivers() resource = self._setup_resources() return resource def kill_vnf(self): # pkill is not matching, debug with pgrep self.ssh_helper.execute("sudo pgrep -lax %s" % self.APP_NAME) self.ssh_helper.execute("sudo ps aux | grep -i %s" % self.APP_NAME) # have to use exact match # try using killall to match self.ssh_helper.execute("sudo killall %s" % self.APP_NAME) def _setup_dpdk(self): """Setup DPDK environment needed for VNF to run""" self._setup_hugepages() self.dpdk_bind_helper.load_dpdk_driver() exit_status = self.dpdk_bind_helper.check_dpdk_driver() if exit_status == 0: return def _setup_resources(self): # what is this magic? how do we know which socket is for which port? # what about quad-socket? if any(v[5] == "0" for v in self.bound_pci): self.socket = 0 else: self.socket = 1 # implicit ordering, presumably by DPDK port num, so pre-sort by port_num # this won't work because we don't have DPDK port numbers yet ports = sorted(self.vnfd_helper.interfaces, key=self.vnfd_helper.port_num) port_names = (intf["name"] for intf in ports) plugins = self.collectd_options.get("plugins", {}) interval = self.collectd_options.get("interval") # we must set timeout to be the same as the VNF otherwise KPIs will die before VNF return ResourceProfile(self.vnfd_helper.mgmt_interface, port_names=port_names, plugins=plugins, interval=interval, timeout=self.scenario_helper.timeout) def _check_interface_fields(self): num_nodes = len(self.scenario_helper.nodes) # OpenStack instance creation time is probably proportional to the number # of instances timeout = 120 * num_nodes dpdk_node = DpdkNode(self.scenario_helper.name, self.vnfd_helper.interfaces, self.ssh_helper, timeout) dpdk_node.check() def _detect_and_bind_drivers(self): interfaces = self.vnfd_helper.interfaces self._check_interface_fields() # check for bound after probe self.bound_pci = [v['virtual-interface']["vpci"] for v in interfaces] self.dpdk_bind_helper.read_status() self.dpdk_bind_helper.save_used_drivers() self.dpdk_bind_helper.bind(self.bound_pci, 'igb_uio') sorted_dpdk_pci_addresses = sorted(self.dpdk_bind_helper.dpdk_bound_pci_addresses) for dpdk_port_num, vpci in enumerate(sorted_dpdk_pci_addresses): try: intf = next(v for v in interfaces if vpci == v['virtual-interface']['vpci']) # force to int intf['virtual-interface']['dpdk_port_num'] = int(dpdk_port_num) except: # pylint: disable=bare-except pass time.sleep(2) def get_local_iface_name_by_vpci(self, vpci): find_net_cmd = self.FIND_NET_CMD.format(vpci) exit_status, stdout, _ = self.ssh_helper.execute(find_net_cmd) if exit_status == 0: return stdout return None def tear_down(self): self.dpdk_bind_helper.rebind_drivers()
class DpdkVnfSetupEnvHelper(SetupEnvHelper): APP_NAME = 'DpdkVnf' FIND_NET_CMD = "find /sys/class/net -lname '*{}*' -printf '%f'" @staticmethod def _update_packet_type(ip_pipeline_cfg, traffic_options): match_str = 'pkt_type = ipv4' replace_str = 'pkt_type = {0}'.format(traffic_options['pkt_type']) pipeline_config_str = ip_pipeline_cfg.replace(match_str, replace_str) return pipeline_config_str @classmethod def _update_traffic_type(cls, ip_pipeline_cfg, traffic_options): traffic_type = traffic_options['traffic_type'] if traffic_options['vnf_type'] is not cls.APP_NAME: match_str = 'traffic_type = 4' replace_str = 'traffic_type = {0}'.format(traffic_type) elif traffic_type == 4: match_str = 'pkt_type = ipv4' replace_str = 'pkt_type = ipv4' else: match_str = 'pkt_type = ipv4' replace_str = 'pkt_type = ipv6' pipeline_config_str = ip_pipeline_cfg.replace(match_str, replace_str) return pipeline_config_str def __init__(self, vnfd_helper, ssh_helper, scenario_helper): super(DpdkVnfSetupEnvHelper, self).__init__(vnfd_helper, ssh_helper, scenario_helper) self.all_ports = None self.bound_pci = None self.socket = None self.used_drivers = None self.dpdk_bind_helper = DpdkBindHelper(ssh_helper) def _setup_hugepages(self): cmd = "awk '/Hugepagesize/ { print $2$3 }' < /proc/meminfo" hugepages = self.ssh_helper.execute(cmd)[1].rstrip() memory_path = \ '/sys/kernel/mm/hugepages/hugepages-%s/nr_hugepages' % hugepages self.ssh_helper.execute("awk -F: '{ print $1 }' < %s" % memory_path) if hugepages == "2048kB": pages = 8192 else: pages = 16 self.ssh_helper.execute("echo %s | sudo tee %s" % (pages, memory_path)) def build_config(self): vnf_cfg = self.scenario_helper.vnf_cfg task_path = self.scenario_helper.task_path lb_count = vnf_cfg.get('lb_count', 3) lb_config = vnf_cfg.get('lb_config', 'SW') worker_config = vnf_cfg.get('worker_config', '1C/1T') worker_threads = vnf_cfg.get('worker_threads', 3) traffic_type = self.scenario_helper.all_options.get('traffic_type', 4) traffic_options = { 'traffic_type': traffic_type, 'pkt_type': 'ipv%s' % traffic_type, 'vnf_type': self.VNF_TYPE, } config_tpl_cfg = find_relative_file(self.DEFAULT_CONFIG_TPL_CFG, task_path) config_basename = posixpath.basename(self.CFG_CONFIG) script_basename = posixpath.basename(self.CFG_SCRIPT) multiport = MultiPortConfig(self.scenario_helper.topology, config_tpl_cfg, config_basename, self.vnfd_helper, self.VNF_TYPE, lb_count, worker_threads, worker_config, lb_config, self.socket) multiport.generate_config() with open(self.CFG_CONFIG) as handle: new_config = handle.read() new_config = self._update_traffic_type(new_config, traffic_options) new_config = self._update_packet_type(new_config, traffic_options) self.ssh_helper.upload_config_file(config_basename, new_config) self.ssh_helper.upload_config_file( script_basename, multiport.generate_script(self.vnfd_helper)) LOG.info("Provision and start the %s", self.APP_NAME) self._build_pipeline_kwargs() return self.PIPELINE_COMMAND.format(**self.pipeline_kwargs) def _build_pipeline_kwargs(self): tool_path = self.ssh_helper.provision_tool(tool_file=self.APP_NAME) # count the number of actual ports in the list of pairs # remove duplicate ports # this is really a mapping from LINK ID to DPDK PMD ID # e.g. 0x110 maps LINK0 -> PMD_ID_1, LINK1 -> PMD_ID_2 # 0x1010 maps LINK0 -> PMD_ID_1, LINK1 -> PMD_ID_3 ports = self.vnfd_helper.port_pairs.all_ports port_nums = self.vnfd_helper.port_nums(ports) # create mask from all the dpdk port numbers ports_mask_hex = hex(sum(2**num for num in port_nums)) self.pipeline_kwargs = { 'cfg_file': self.CFG_CONFIG, 'script': self.CFG_SCRIPT, 'port_mask_hex': ports_mask_hex, 'tool_path': tool_path, } def setup_vnf_environment(self): self._setup_dpdk() self.bound_pci = [ v['virtual-interface']["vpci"] for v in self.vnfd_helper.interfaces ] self.kill_vnf() # bind before _setup_resources so we can use dpdk_port_num self._detect_and_bind_drivers() resource = self._setup_resources() return resource def kill_vnf(self): # pkill is not matching, debug with pgrep self.ssh_helper.execute("sudo pgrep -lax %s" % self.APP_NAME) self.ssh_helper.execute("sudo ps aux | grep -i %s" % self.APP_NAME) # have to use exact match # try using killall to match self.ssh_helper.execute("sudo killall %s" % self.APP_NAME) def _setup_dpdk(self): """ setup dpdk environment needed for vnf to run """ self._setup_hugepages() self.ssh_helper.execute("sudo modprobe uio && sudo modprobe igb_uio") exit_status = self.ssh_helper.execute("lsmod | grep -i igb_uio")[0] if exit_status == 0: return dpdk = self.ssh_helper.join_bin_path(DPDK_VERSION) dpdk_setup = self.ssh_helper.provision_tool(tool_file="nsb_setup.sh") exit_status = self.ssh_helper.execute( "which {} >/dev/null 2>&1".format(dpdk))[0] if exit_status != 0: self.ssh_helper.execute("bash %s dpdk >/dev/null 2>&1" % dpdk_setup) def get_collectd_options(self): options = self.scenario_helper.all_options.get("collectd", {}) # override with specific node settings options.update(self.scenario_helper.options.get("collectd", {})) return options def _setup_resources(self): # what is this magic? how do we know which socket is for which port? # what about quad-socket? if any(v[5] == "0" for v in self.bound_pci): self.socket = 0 else: self.socket = 1 # implicit ordering, presumably by DPDK port num, so pre-sort by port_num # this won't work because we don't have DPDK port numbers yet ports = sorted(self.vnfd_helper.interfaces, key=self.vnfd_helper.port_num) port_names = (intf["name"] for intf in ports) collectd_options = self.get_collectd_options() plugins = collectd_options.get("plugins", {}) # we must set timeout to be the same as the VNF otherwise KPIs will die before VNF return ResourceProfile(self.vnfd_helper.mgmt_interface, port_names=port_names, plugins=plugins, interval=collectd_options.get("interval"), timeout=self.scenario_helper.timeout) def _detect_and_bind_drivers(self): interfaces = self.vnfd_helper.interfaces self.dpdk_bind_helper.read_status() self.dpdk_bind_helper.save_used_drivers() self.dpdk_bind_helper.bind(self.bound_pci, 'igb_uio') sorted_dpdk_pci_addresses = sorted( self.dpdk_bind_helper.dpdk_bound_pci_addresses) for dpdk_port_num, vpci in enumerate(sorted_dpdk_pci_addresses): try: intf = next(v for v in interfaces if vpci == v['virtual-interface']['vpci']) # force to int intf['virtual-interface']['dpdk_port_num'] = int(dpdk_port_num) except: pass time.sleep(2) def get_local_iface_name_by_vpci(self, vpci): find_net_cmd = self.FIND_NET_CMD.format(vpci) exit_status, stdout, _ = self.ssh_helper.execute(find_net_cmd) if exit_status == 0: return stdout return None def tear_down(self): self.dpdk_bind_helper.rebind_drivers()
def test__switch_active_dict_by_header(self): line = "Crypto devices using DPDK-compatible driver" olddict = 'olddict' self.assertEqual(CRYPTO_DPDK, DpdkBindHelper._switch_active_dict(line, olddict))
def test__switch_active_dict_by_header_empty(self): line = "<none>" olddict = 'olddict' self.assertEqual(olddict, DpdkBindHelper._switch_active_dict(line, olddict))