[V3] framework/*: Modified create_eal_parameters API to support flexibility

Message ID 20220126074748.2828-1-junx.dong@intel.com (mailing list archive)
State Superseded
Headers
Series [V3] framework/*: Modified create_eal_parameters API to support flexibility |

Checks

Context Check Description
ci/Intel-dts-suite-test success Testing OK

Commit Message

Jun Dong Jan. 26, 2022, 7:47 a.m. UTC
  From: DongJunX <junx.dong@intel.com>

- Refactoring API for easy maintenance.
- Format the output format of the continuous cores list.
- Append user defined eal parameters.

Signed-off-by: Jun Dong <junx.dong@intel.com>
---
 framework/dut.py        | 339 ++++++++++++++++++++++++----------------
 framework/pmd_output.py |   6 +-
 2 files changed, 208 insertions(+), 137 deletions(-)
  

Patch

diff --git a/framework/dut.py b/framework/dut.py
index dc3fc874..90c43b19 100644
--- a/framework/dut.py
+++ b/framework/dut.py
@@ -117,137 +117,209 @@  class Dut(Crb):
 
     def create_eal_parameters(self, fixed_prefix=False, socket=-1, **config):
         """
-        generate eal parameters character string
-        :param config:
-        :return: eal_str eg:'-c 0xf -a 0000:88:00.0 -a 0000:88:00.1 --file-prefix=dpdk_1112_20190809143420',
-        if dpdk version < 20.11-rc4, eal_str eg: '-c 0xf -w 0000:88:00.0 --file-prefix=dpdk_1112_20190809143420',
-        """
-        default_cores = '1S/2C/1T'
-        blank = ' '
-        os_type = self.get_os_type()
-        if config:
-            # deal with cores
-            if 'cores' in config:
-                if type(config['cores']) == list:
-                    core_list = config['cores']
-                elif isinstance(config['cores'], str):
-                    if config['cores'] == '' or config['cores'].lower() == 'default':
-                        core_list = self.get_core_list(default_cores)
-                    else:
-                        core_list = self.get_core_list(config['cores'], socket=socket)
-            else:
-                core_list = self.get_core_list(default_cores)
-
-            # deal with ports
-            w_pci_list = []
-            if 'ports' in config and len(config['ports']) != 0:
-                allow_option = '-a' if self.dpdk_version > '20.11.0-rc3' or self.dpdk_version == '20.11.0' else '-w'
-                for port in config['ports']:
-                    if type(port) == int:
-                        if 'port_options' in config and port in list(config['port_options'].keys()):
-                            port_option = config['port_options'][port]
-                            w_pci_list.append('%s %s,%s' % (allow_option, self.ports_info[port]['pci'], port_option))
+        generate eal parameters character string;
+        :param fixed_prefix: use fixed file-prefix or not, when it is true,
+                             the file-prefix will not be added a timestamp
+        :param socket: the physical CPU socket index, -1 means no care cpu socket;
+        :param config: kwargs user defined eal parameters, eg:
+                sub param cores: set the core info, eg:
+                        cores=[0,1,2,3],
+                        cores='default',
+                        cores='1S/4C/1T',
+                        cores='all';
+                sub param ports: set PCI allow list, eg:
+                        ports=['0000:1a:00.0', '0000:1a:00.1'],
+                        ports=[0, 1];
+                sub param port_options: set options of port, eg:
+                        port_options={'0000:1a:00.0': "proto_xtr=vlan"},
+                        port_options={0: "cap=dcf"};
+                sub param prefix: set file prefix string, eg:
+                        prefix='vf';
+                sub param no_pci: switch of disable PCI bus eg:
+                        no_pci=True;
+                sub param b_ports: skip probing a PCI device to prevent EAL from using it, eg:
+                        b_ports=['0000:1a:00.0'],
+                        b_ports=[0];
+                sub param vdevs: virtual device list, eg:
+                        vdevs=['net_ring0', 'net_ring1'];
+                sub param other_eal_param: user defined DPDK eal parameters, eg:
+                        other_eal_param='--single-file-segments';
+        :return: eal param string, eg:
+                '-c 0xf -a 0000:88:00.0 --file-prefix=dpdk_1112_20190809143420';
+        if DPDK version < 20.11-rc4, eal_str eg:
+                '-c 0xf -w 0000:88:00.0 --file-prefix=dpdk_1112_20190809143420';
+        """
+
+        class _EalParameter(object):
+            def __init__(self, _dut, _fixed_prefix, _socket, _config=None):
+                self.BLANK = ' '
+                self.config = _config if _config is not None else dict()
+                self.os_type = _dut.get_os_type()
+                self.fixed_prefix = _fixed_prefix
+                self.socket = _socket
+                self.dut = _dut
+
+            def _make_cores_param(self):
+                is_use_default_cores = 'cores' not in self.config \
+                                       or self.config['cores'] == '' \
+                                       or isinstance(self.config['cores'], str) \
+                                       and self.config['cores'].lower() == 'default'
+                if is_use_default_cores:
+                    default_cores = '1S/2C/1T'
+                    core_list = self.dut.get_core_list(default_cores)
+                else:
+                    core_list = self._get_cores_from_config()
+
+                def _get_consecutive_cores_range(_cores: list):
+                    _formated_core_list = []
+                    _tmp_cores_list = list(sorted(map(int, _cores)))
+                    _segment = _tmp_cores_list[:1]
+                    for _core_num in _tmp_cores_list[1:]:
+                        if _core_num - _segment[-1] == 1:
+                            _segment.append(_core_num)
                         else:
-                            w_pci_list.append('%s %s' % (allow_option, self.ports_info[port]['pci']))
-                    else:
-                        if 'port_options' in config and port in list(config['port_options'].keys()):
-                            port_option = config['port_options'][port]
-                            w_pci_list.append('%s %s,%s' % (allow_option, port, port_option))
+                            _formated_core_list.append(
+                                f'{_segment[0]}-{_segment[-1]}' if len(_segment) > 1 else f'{_segment[0]}')
+                            _index = _tmp_cores_list.index(_core_num)
+                            _formated_core_list.extend(_get_consecutive_cores_range(_tmp_cores_list[_index:]))
+                            _segment.clear()
+                            break
+                    if len(_segment) > 0:
+                        _formated_core_list.append(
+                            f'{_segment[0]}-{_segment[-1]}' if len(_segment) > 1 else f'{_segment[0]}')
+                    return _formated_core_list
+
+                return f'-l {", ".join(_get_consecutive_cores_range(core_list))}'
+
+            def _make_memory_channels(self):
+                param_template = '-n {}'
+                return param_template.format(self.dut.get_memory_channels())
+
+            def _make_ports_param(self):
+                if 'ports' in self.config and len(self.config['ports']) != 0:
+                    return self._get_ports_and_wraped_port_with_port_options()
+                else:
+                    return self._make_default_ports_param()
+
+            def _make_default_ports_param(self):
+                pci_list = []
+                allow_option = self._make_allow_option()
+                if len(self.dut.ports_info) != 0:
+                    for port_info in self.dut.ports_info:
+                        pci_list.append('%s %s' % (allow_option, port_info['pci']))
+                self.dut.logger.info(pci_list)
+                return ' '.join(pci_list)
+
+            def _make_b_ports_param(self):
+                b_pci_list = []
+                if 'b_ports' in self.config and len(self.config['b_ports']) != 0:
+                    for port in self.config['b_ports']:
+                        if type(port) == int:
+                            b_pci_list.append('-b %s' % self.dut.ports_info[port]['pci'])
                         else:
-                            w_pci_list.append('%s %s' % (allow_option, port))
-            w_pci_str = ' '.join(w_pci_list)
-
-            # deal with block ports
-            b_pci_list = []
-            if 'b_ports' in config and len(config['b_ports']) != 0:
-                for port in config['b_ports']:
-                    if type(port) == int:
-                        b_pci_list.append('-b %s' % self.ports_info[port]['pci'])
-                    else:
-                        b_pci_list = ['-b %s' % pci for pci in config['b_ports']]
-            b_ports_str = ' '.join(b_pci_list)
+                            b_pci_list = ['-b %s' % pci for pci in self.config['b_ports']]
+                return ' '.join(b_pci_list)
 
-            # deal with no-pci
-            if 'no_pci' in config:
-                if config['no_pci'] == True:
-                    no_pci = '--no-pci'
+            def _make_no_pci_param(self):
+                if 'no_pci' in self.config and self.config['no_pci'] is True:
+                    return '--no-pci'
                 else:
-                    no_pci = ''
-            else:
-                no_pci = ''
+                    return ''
 
-            # deal with file prefix
-            if 'prefix' in config and config['prefix'] != '':
-                if fixed_prefix == True:
-                    file_prefix = config['prefix']
+            def _make_prefix_param(self):
+                is_prefix_param_available = 'prefix' in self.config and self.config['prefix'] != ''
+                if is_prefix_param_available:
+                    if self.fixed_prefix is True:
+                        fixed_file_prefix = self.config['prefix']
+                    else:
+                        fixed_file_prefix = self.config['prefix'] + '_' + self.dut.prefix_subfix
                 else:
-                    file_prefix = config['prefix'] + '_' + self.prefix_subfix
-            else:
-                file_prefix = 'dpdk' + '_' + self.prefix_subfix
-            if file_prefix not in self.prefix_list:
-                self.prefix_list.append(file_prefix)
+                    fixed_file_prefix = 'dpdk' + '_' + self.dut.prefix_subfix
+                fixed_file_prefix = self._do_os_handle_with_prefix_param(fixed_file_prefix)
+                fixed_file_prefix = '--file-prefix=' + fixed_file_prefix
+                return fixed_file_prefix
+
+            def _make_vdevs_param(self):
+                if 'vdevs' in self.config and len(self.config['vdevs']) != 0:
+                    _vdevs = ['--vdev ' + vdev for vdev in self.config['vdevs']]
+                    return ' '.join(_vdevs)
+                else:
+                    return ''
+
+            def _make_share_library_path_param(self):
+                use_shared_lib = settings.load_global_setting(settings.HOST_SHARED_LIB_SETTING)
+                shared_lib_path = settings.load_global_setting(settings.HOST_SHARED_LIB_PATH)
+                if use_shared_lib == 'true' and shared_lib_path and 'Virt' not in str(self.dut):
+                    return ' -d {} '.format(shared_lib_path)
+                return ''
+
+            def _make_default_force_max_simd_bitwidth_param(self):
+                rx_mode = settings.load_global_setting(settings.DPDK_RXMODE_SETTING)
+                build_type = settings.load_global_setting(settings.HOST_BUILD_TYPE_SETTING)
+                param_template = ' --force-max-simd-bitwidth=%s '
+                bitwith_dict = {'novector': '64', 'sse': '128', 'avx2': '256', 'avx512': '512', 'nolimit': '0'}
+                if build_type == 'meson' and rx_mode in bitwith_dict and \
+                        'force-max-simd-bitwidth' not in self.config.get('other_eal_param', ''):
+                    return param_template % bitwith_dict.get(rx_mode)
+                else:
+                    return ''
+
+            def _get_cores_from_config(self):
+                if type(self.config['cores']) == list:
+                    return self.config['cores']
+                elif isinstance(self.config['cores'], str):
+                    return self.dut.get_core_list(self.config['cores'], socket=self.socket)
+
+            def _get_ports_and_wraped_port_with_port_options(self):
+                w_pci_list = []
+                for port in self.config['ports']:
+                    w_pci_list.append(self._add_port_options_to(port))
+                return ' '.join(w_pci_list)
+
+            def _add_port_options_to(self, port):
+                allow_option = self._make_allow_option()
+                port_mac_addr = self.dut.ports_info[port]['pci'] if type(port) == int else port
+                port_param = '%s %s' % (allow_option, port_mac_addr)
+                port_option = self._get_port_options_from_config(port)
+                if port_option:
+                    port_param = f'{port_param},{port_option}'
+                return port_param
+
+            def _get_port_options_from_config(self, port):
+                if 'port_options' in self.config and port in list(self.config['port_options'].keys()):
+                    return self.config['port_options'][port]
+                else:
+                    return ''
 
-            # deal with vdev
-            if 'vdevs' in config and len(config['vdevs']) != 0:
-                vdev = '--vdev ' + ' --vdev '.join(config['vdevs'])
-            else:
-                vdev = ''
-
-            if os_type == 'freebsd':
-                eal_str = '-l ' + ','.join(map(str, core_list)) \
-                          + blank + '-n %d' % self.get_memory_channels() \
-                          + blank + w_pci_str \
-                          + blank + b_ports_str \
-                          + blank + no_pci \
-                          + blank + vdev
-                self.prefix_list = []
-            else:
-                eal_str = '-l ' + ','.join(map(str, core_list)) \
-                          + blank + '-n %d' % self.get_memory_channels() \
-                          + blank + w_pci_str \
-                          + blank + b_ports_str \
-                          + blank + '--file-prefix=' + file_prefix \
-                          + blank + no_pci \
-                          + blank + vdev
-        else:
-            allow_option = '-a' if self.dpdk_version > '20.11.0-rc3' or self.dpdk_version == '20.11.0' else '-w'
-            # get pci from ports_info
-            pci_list = []
-            if len(self.ports_info) != 0:
-                for port_info in self.ports_info:
-                    pci_list.append('%s %s' % (allow_option, port_info['pci']))
-            self.logger.info(pci_list)
-            pci_str = ' '.join(pci_list)
-            # default cores '1S/2C/1T'
-            core_list = self.get_core_list(default_cores)
-            file_prefix = 'dpdk' + '_' + self.prefix_subfix
-            self.prefix_list.append(file_prefix)
-            if os_type == 'freebsd':
-                eal_str = '-l ' + ','.join(map(str, core_list)) \
-                          + blank + '-n %d' % self.get_memory_channels() \
-                          + blank + pci_str
-                self.prefix_list = []
-            else:
-                eal_str = '-l ' + ','.join(map(str, core_list)) \
-                          + blank + '-n %d' % self.get_memory_channels() \
-                          + blank + pci_str \
-                          + blank + '--file-prefix=' + file_prefix
-        use_shared_lib = settings.load_global_setting(settings.HOST_SHARED_LIB_SETTING)
-        shared_lib_path = settings.load_global_setting(settings.HOST_SHARED_LIB_PATH)
-        if use_shared_lib == 'true' and shared_lib_path and 'Virt' not in str(self):
-            eal_str = eal_str + ' -d {} '.format(shared_lib_path)
-        rx_mode = settings.load_global_setting(settings.DPDK_RXMODE_SETTING)
-        build_type = settings.load_global_setting(settings.HOST_BUILD_TYPE_SETTING)
-        if build_type == 'meson' and ('other_eal_param' not in config or
-                                      'force-max-simd-bitwidth' not in config['other_eal_param']):
-            if rx_mode == 'novector':
-                eal_str = eal_str + ' --force-max-simd-bitwidth=64 '
-            elif rx_mode == 'sse':
-                eal_str = eal_str + ' --force-max-simd-bitwidth=128 '
-            elif rx_mode == 'avx2':
-                eal_str = eal_str + ' --force-max-simd-bitwidth=256 '
-            elif rx_mode == 'avx512':
-                eal_str = eal_str + ' --force-max-simd-bitwidth=512 '
+            def _make_allow_option(self):
+                is_new_dpdk_version = self.dut.dpdk_version > '20.11.0-rc3' or self.dut.dpdk_version == '20.11.0'
+                return '-a' if is_new_dpdk_version else '-w'
+
+            def _do_os_handle_with_prefix_param(self, file_prefix):
+                if self.dut.get_os_type() == 'freebsd':
+                    self.dut.prefix_list = []
+                    file_prefix = ''
+                else:
+                    self.dut.prefix_list.append(file_prefix)
+                return file_prefix
+
+            def make_eal_param(self):
+                _eal_str = self.BLANK.join([self._make_cores_param(),
+                                            self._make_memory_channels(),
+                                            self._make_ports_param(),
+                                            self._make_b_ports_param(),
+                                            self._make_prefix_param(),
+                                            self._make_no_pci_param(),
+                                            self._make_vdevs_param(),
+                                            self._make_share_library_path_param(),
+                                            self._make_default_force_max_simd_bitwidth_param(),
+                                            # append user defined eal parameters
+                                            self.config.get('other_eal_param', '')
+                                            ])
+                return _eal_str
+
+        eal_parameter_creator = _EalParameter(self, fixed_prefix, socket, config)
+        eal_str = eal_parameter_creator.make_eal_param()
 
         return eal_str
 
@@ -556,7 +628,6 @@  class Dut(Crb):
             total_numa_nodes = len(numa_nodes)
             self.logger.info(numa_nodes)
 
-
         force_socket = False
 
         if int(hugepages_size) < (1024 * 1024):
@@ -578,7 +649,7 @@  class Dut(Crb):
                     arch_huge_pages = hugepages if hugepages > 0 else 2048
 
             if total_huge_pages != arch_huge_pages:
-                if total_numa_nodes == -1 :
+                if total_numa_nodes == -1:
                     self.set_huge_pages(arch_huge_pages)
                 else:
                     # before all hugepage average distribution  by all socket,
@@ -749,7 +820,7 @@  class Dut(Crb):
             for portid in range(len(self.ports_info)):
                 if self.ports_info[portid]['source'] == 'cfg':
                     if (socket is None or
-                        self.ports_info[portid]['numa'] == -1 or
+                            self.ports_info[portid]['numa'] == -1 or
                             socket == self.ports_info[portid]['numa']):
                         ports.append(portid)
             return ports
@@ -760,7 +831,7 @@  class Dut(Crb):
                 if port_info['type'] == NICS[nic_type]:
                     # match numa or none numa awareness
                     if (socket is None or
-                        port_info['numa'] == -1 or
+                            port_info['numa'] == -1 or
                             socket == port_info['numa']):
                         # port has link,
                         if self.tester.get_local_port(portid) != -1:
@@ -913,7 +984,7 @@  class Dut(Crb):
                 ipv6 = "Not connected"
 
             out = self.send_expect("ip -family inet address show dev %s | awk '/inet/ { print $2 }'"
-                    % intf, "# ")
+                                   % intf, "# ")
             ipv4 = out.split('/')[0]
 
             port_info['ipv6'] = ipv6
@@ -992,7 +1063,7 @@  class Dut(Crb):
             port_info['port'] = port
 
             self.logger.info("DUT cached: [%s %s] %s" % (port_info['pci'],
-                                port_info['type'], port_info['intf']))
+                                                         port_info['type'], port_info['intf']))
 
     def scan_ports_uncached(self):
         """
@@ -1056,7 +1127,7 @@  class Dut(Crb):
         self.ports_info = []
 
         skipped = RED('Skipped: Unknown/not selected')
-        
+
         for (pci_bus, pci_id) in self.pci_devices_info:
 
             if not settings.accepted_nic(pci_id):
@@ -1068,7 +1139,7 @@  class Dut(Crb):
             bus_id = addr_array[1]
             devfun_id = addr_array[2]
             port = GetNicObj(self, domain_id, bus_id, devfun_id)
-            port.pci_id= pci_id
+            port.pci_id = pci_id
             port.name = settings.get_nic_name(pci_id)
             port.default_driver = settings.get_nic_driver(pci_id)
             intf = port.get_interface_name()
@@ -1095,7 +1166,7 @@  class Dut(Crb):
 
             # store the port info to port mapping
             self.ports_info.append({'port': port, 'pci': pci_str, 'type': pci_id, 'intf':
-                                    intf, 'mac': macaddr, 'ipv6': ipv6, 'numa': -1})
+                intf, 'mac': macaddr, 'ipv6': ipv6, 'numa': -1})
 
     def setup_virtenv(self, virttype):
         """
@@ -1145,7 +1216,7 @@  class Dut(Crb):
         vflist = []
         port_driver = port.get_nic_driver()
         if 'sriov_vfs_pci' in self.ports_info[port_id] and \
-           self.ports_info[port_id]['sriov_vfs_pci']:
+                self.ports_info[port_id]['sriov_vfs_pci']:
             vflist = self.ports_info[port_id]['sriov_vfs_pci']
         else:
             if not port.get_sriov_vfs_pci():
diff --git a/framework/pmd_output.py b/framework/pmd_output.py
index 113e85f6..da2b0de3 100644
--- a/framework/pmd_output.py
+++ b/framework/pmd_output.py
@@ -139,17 +139,17 @@  class PmdOutput():
         config['cores'] = cores
         if ' -w ' not in eal_param and ' -a ' not in eal_param and ' -b ' not in eal_param \
             and 'ports' not in config and 'b_ports' not in config and ' --no-pci ' not in eal_param \
-            and ( 'no_pci' not in config or ('no_pci' in config and config['no_pci'] != True)):
+            and ('no_pci' not in config or ('no_pci' in config and config['no_pci'] != True)):
             config['ports'] = [self.dut.ports_info[i]['pci'] for i in range(len(self.dut.ports_info))]
         part_eal_param = self.dut.create_eal_parameters(fixed_prefix=fixed_prefix, socket=socket, **config)
-        all_eal_param = part_eal_param + ' ' + eal_param
+        all_eal_param = part_eal_param
 
         app_name = self.dut.apps_name['test-pmd']
         command = app_name + " %s -- -i %s" % (all_eal_param, param)
         command = command.replace('  ', ' ')
         if self.session != self.dut:
             self.session.send_expect("cd %s" % self.dut.base_dir, "# ")
-        timeout = config.get('timeout',120)
+        timeout = config.get('timeout', 120)
         out = self.session.send_expect(command, expected, timeout)
         self.command = command
         # wait 10s to ensure links getting up before test start.