diff options
Diffstat (limited to 'python')
| -rw-r--r-- | python/vyos/vpp/config_resource_checks/cpu.py | 76 | ||||
| -rw-r--r-- | python/vyos/vpp/config_resource_checks/memory.py | 11 | ||||
| -rw-r--r-- | python/vyos/vpp/config_verify.py | 116 |
3 files changed, 22 insertions, 181 deletions
diff --git a/python/vyos/vpp/config_resource_checks/cpu.py b/python/vyos/vpp/config_resource_checks/cpu.py deleted file mode 100644 index b319608e4..000000000 --- a/python/vyos/vpp/config_resource_checks/cpu.py +++ /dev/null @@ -1,76 +0,0 @@ -# Used for validating estimated CPU/physical cores use -# -# Copyright (C) VyOS Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -from vyos.utils.cpu import get_available_cpus, get_core_count - -from vyos.vpp.config_resource_checks.resource_defaults import default_resource_map - - -# Get default value for reserved cpu cores -reserved_cpus = default_resource_map.get('reserved_cpu_cores') - - -def available_cores_count(cpu_settings: dict) -> int: - core_count = get_core_count() - - if cpu_settings.get('main_core'): - core_count -= 1 - - skip_cores = int(cpu_settings.get('skip_cores', 0)) - # The default settings assume that - # at least 2 CPU cores should remain reserved for system use - # (only in case of current runtime is not smoke test) - if skip_cores < reserved_cpus: - core_count -= reserved_cpus - else: - core_count -= skip_cores - - return core_count - - -def available_cores_list(skip_cores: int) -> list: - # Available cores are all CPU cores without first N skipped cores that will not be used - # Get all available physical cores - use set to filter out unique values - cpu_cores = set(map(lambda el: el['cpu'], get_available_cpus())) - cpu_cores = list(cpu_cores) - - return cpu_cores[skip_cores:] - - -def worker_cores_list(iface: str, worker_ranges: list) -> list: - all_core_numbers = [] - for worker_range in worker_ranges: - core_numbers = worker_range.split('-') - - if int(core_numbers[0]) > int(core_numbers[-1]): - raise ValueError( - f'Range for "{iface} workers {worker_range}" is not correct' - ) - - all_core_numbers.extend(range(int(core_numbers[0]), int(core_numbers[-1]) + 1)) - - # Check for duplicates - duplicates = set( - [str(x) for n, x in enumerate(all_core_numbers) if x in all_core_numbers[:n]] - ) - if duplicates: - raise ValueError( - f'Some workers in "{iface} workers" are duplicated: #{",".join(list(duplicates))}' - ) - - return all_core_numbers diff --git a/python/vyos/vpp/config_resource_checks/memory.py b/python/vyos/vpp/config_resource_checks/memory.py index 03fe097e9..f1ae6f7bc 100644 --- a/python/vyos/vpp/config_resource_checks/memory.py +++ b/python/vyos/vpp/config_resource_checks/memory.py @@ -174,10 +174,11 @@ def total_memory_required(settings: dict) -> dict: return memory -def buffers_required(settings: dict, workers) -> int: +def buffers_required(settings: dict) -> int: """ Calculate total VPP buffer requirements based on interface settings and workers. """ + workers = int(settings['resource_allocation']['cpu_cores']) buffers_total = 0 for ifname, iface_config in settings.get('interface', {}).items(): # Do not include XDP interfaces in buffer calculations. @@ -185,14 +186,14 @@ def buffers_required(settings: dict, workers) -> int: # so buffer requirements cannot be derived from descriptors here. # Buffers for XDP are handled internally by the kernel/XDP layer, # not by VPP’s buffer allocator. - if iface_config.get('driver') == 'xdp': - continue + # if iface_config.get('driver') == 'xdp': + # continue + dpdk_options = iface_config.get('dpdk_options', {}) rx_queues = int(dpdk_options.get('num_rx_queues', 1)) rx_desc = int(dpdk_options.get('num_rx_desc')) # default TX queues is equal to number of worker threads - # plus 1 main thread - tx_queues = int(dpdk_options.get('num_tx_queues', workers + 1)) + tx_queues = int(dpdk_options.get('num_tx_queues', workers)) tx_desc = int(dpdk_options.get('num_tx_desc')) # buffers for RX/TX queues for interface diff --git a/python/vyos/vpp/config_verify.py b/python/vyos/vpp/config_verify.py index bcc10257f..f8bfb214a 100644 --- a/python/vyos/vpp/config_verify.py +++ b/python/vyos/vpp/config_verify.py @@ -22,7 +22,7 @@ from vyos import ConfigError from vyos.base import Warning from vyos.utils.cpu import get_core_count as total_core_count, get_cpus -from vyos.vpp.config_resource_checks import cpu as cpu_checks, memory as mem_checks +from vyos.vpp.config_resource_checks import memory as mem_checks from vyos.vpp.config_resource_checks.resource_defaults import default_resource_map from vyos.vpp.utils import human_memory_to_bytes, bytes_to_human_memory @@ -183,17 +183,13 @@ def verify_dev_driver(driver_type: str, driver: str) -> bool: return False -def create_cpu_error_message( - cpus_required: int, cpus_available: int = None, skip_cores: int = 0 -) -> str: +def create_cpu_error_message(cpus_required: int, cpus_available: int = None) -> str: cpu_info = get_cpus() logical_cores = sum( [int(s.get('siblings')) if 'siblings' in s else 1 for s in cpu_info] ) reserved_cpus = default_resource_map.get('reserved_cpu_cores') - if skip_cores > reserved_cpus: - reserved_cpus = skip_cores available_str = ( ( @@ -320,100 +316,19 @@ def verify_vpp_memory(config: dict): ) -def verify_vpp_settings_cpu_skip_cores(skip_cores: int): - cpu_cores = total_core_count() - - # The number of skipped cores must not be greater than - # available CPU cores in the system - 1 for main thread - if skip_cores > (cpu_cores - 1): - raise ConfigError( - f'The system does not have enough available CPUs to skip ' - f'(reduce "cpu skip-cores" to {cpu_cores} or less)' - ) - - -def verify_vpp_settings_cpu(settings: dict): - """ - Verify 'cpu main-core' is set if worker-related settings are used. - `set vpp settings cpu workers` and `set vpp settings cpu corelist-workers` - are mutually exclusive! - """ - worker_related = ('corelist_workers', 'workers', 'skip_cores') - - if any(key in settings for key in worker_related) and 'main_core' not in settings: - raise ConfigError('"cpu main-core" is required but not set!') - - if 'corelist_workers' in settings and 'workers' in settings: - raise ConfigError( - '"cpu corelist-workers" and "cpu workers" cannot be used at the same time!' - ) - - -def verify_vpp_cpu_main_core(cpu_settings: dict) -> None: - """Check that the main core is available""" - skip_cores = int(cpu_settings.get('skip_cores', 0)) - available_cores = cpu_checks.available_cores_list(skip_cores) - main_core = int(cpu_settings['main_core']) - - if main_core not in available_cores: - raise ConfigError( - 'Cannot set main core for VPP process: ' - f'CPU#{main_core} is not available.' - ) - - -def verify_vpp_settings_cpu_workers(cpu_settings: dict): +def verify_vpp_cpu_cores(cpu_cores: int): """ Verify that the system has enough available CPU cores to run a given amount of worker processes (1 worker/core) """ - workers = int(cpu_settings.get('workers', 0)) - available_cores = cpu_checks.available_cores_count(cpu_settings) - - if workers > available_cores: - raise ConfigError( - f'Not enough free physical CPU cores for {workers} VPP workers '.ljust(72) - + create_cpu_error_message( - workers, available_cores, cpu_settings.get('skip_cores', 0) - ) - ) - - -def verify_vpp_settings_cpu_corelist_workers(cpu_settings: dict): - """ - Verify that the CPU cores provided to the config are free and can be used by VPP - """ - workers = cpu_settings.get('corelist_workers') - main_core = int(cpu_settings.get('main_core')) - skip_cores = int(cpu_settings.get('skip_cores', 0)) - available_cores = cpu_checks.available_cores_list(skip_cores) - try: - all_core_nums = cpu_checks.worker_cores_list( - iface='cpu corelist', worker_ranges=workers - ) - except ValueError as e: - raise ConfigError(str(e)) - - error_msg = 'Cannot set VPP "cpu corelist-workers": '.ljust(72) - - if main_core in all_core_nums: - raise ConfigError( - f'CPU#{main_core} is set as main core and should not ' - 'be included to the corelist-workers' - ) - - invalid_cores = [str(el) for el in all_core_nums if el not in available_cores] - if invalid_cores: - raise ConfigError(error_msg + f'CPU# {",".join(invalid_cores)} not available.') + total_cores = total_core_count() + reserved_cpus = default_resource_map.get('reserved_cpu_cores') + available_cores = total_cores - reserved_cpus - available_cores_count = cpu_checks.available_cores_count(cpu_settings) - if len(all_core_nums) > available_cores_count: + if cpu_cores > available_cores: raise ConfigError( - error_msg - + 'Not enough free physical CPUs in the system.'.ljust(72) - + create_cpu_error_message( - len(all_core_nums), available_cores_count, skip_cores - ) + f'Not enough free physical CPU cores for {cpu_cores} "cpu-cores" '.ljust(72) + + create_cpu_error_message(cpu_cores, available_cores) ) @@ -441,12 +356,12 @@ def verify_vpp_interfaces_dpdk_num_queues(qtype: str, num_queues: int, workers: if num_queues > workers: raise ConfigError( - f'The number of {qtype} queues cannot be greater than the number of configured VPP workers: ' - f'workers: {workers}, queues: {num_queues}' + f'The number of {qtype} queues cannot be greater than the number of configured VPP "cpu-cores": ' + f'cpu-cores: {workers}, queues: {num_queues}' ) -def verify_routes_count(settings: dict, workers: int): +def verify_routes_count(settings: dict): """ Maximum routes count depending on main heap size, statistics segment size and workers @@ -454,12 +369,13 @@ def verify_routes_count(settings: dict, workers: int): counters = 2 # 2 counters for each route bytes = 16 # each counter consumes 16 bytes statseg_scale = 2 + cpu_cores = int(settings['resource_allocation']['cpu_cores']) statseg_size = settings['statseg']['size'] statseg_size_in_bytes = human_memory_to_bytes(statseg_size) main_heap = settings['memory']['main_heap_size'] main_heap_in_gb = human_memory_to_bytes(main_heap) >> 30 - formula = (workers + 1) * counters * bytes * statseg_scale + formula = cpu_cores * counters * bytes * statseg_scale routes_count_statseg = statseg_size_in_bytes / formula routes_count_statseg = round(routes_count_statseg / 1_000_000, 2) routes_count_mh = main_heap_in_gb * 2 @@ -472,10 +388,10 @@ def verify_routes_count(settings: dict, workers: int): ) -def verify_vpp_buffers(settings: dict, workers: int): +def verify_vpp_buffers(settings: dict): buffers_configured = int(settings['buffers']['buffers_per_numa']) - buffers_required = mem_checks.buffers_required(settings, workers) + buffers_required = mem_checks.buffers_required(settings) if buffers_required > buffers_configured: raise ConfigError( |
