diff options
| author | Daniil Baturin <daniil@vyos.io> | 2025-10-28 15:23:37 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-10-28 15:23:37 +0000 |
| commit | ecc4c85b799047f51e4a32ae5b0590017a6ce374 (patch) | |
| tree | 9c210ed6efa3f9ae6b503d099963b96b8b75db34 /src | |
| parent | 761968da584199e74a23d6381b3f6b400906083f (diff) | |
| parent | 4c08b0694c65f1bb434538980a44a94e5ae15d24 (diff) | |
| download | vyos-1x-ecc4c85b799047f51e4a32ae5b0590017a6ce374.tar.gz vyos-1x-ecc4c85b799047f51e4a32ae5b0590017a6ce374.zip | |
Merge pull request #4796 from natali-rs1985/T7938
T7938: VPP: Rewrite sFlow implementation
Diffstat (limited to 'src')
| -rwxr-xr-x | src/conf_mode/system_sflow.py | 44 | ||||
| -rw-r--r-- | src/conf_mode/vpp_sflow.py | 64 | ||||
| -rw-r--r-- | src/migration-scripts/vpp/2-to-3 | 30 |
3 files changed, 94 insertions, 44 deletions
diff --git a/src/conf_mode/system_sflow.py b/src/conf_mode/system_sflow.py index c5fe5641f..d54801ecf 100755 --- a/src/conf_mode/system_sflow.py +++ b/src/conf_mode/system_sflow.py @@ -19,12 +19,14 @@ import os from sys import exit from vyos.config import Config +from vyos.configdep import set_dependents, call_dependents from vyos.configverify import verify_vrf from vyos.template import render from vyos.utils.process import call from vyos.utils.network import is_addr_assigned from vyos import ConfigError from vyos import airbag + airbag.enable() hsflowd_conf_path = '/run/sflow/hsflowd.conf' @@ -38,17 +40,37 @@ def get_config(config=None): else: conf = Config() base = ['system', 'sflow'] + + vpp_sflow = conf.exists(['vpp', 'sflow']) + if not conf.exists(base): - return None + return { + 'remove': True, + 'vpp_sflow': vpp_sflow, + } - sflow = conf.get_config_dict(base, key_mangling=('-', '_'), - get_first_key=True, - with_recursive_defaults=True) + sflow = conf.get_config_dict( + base, key_mangling=('-', '_'), get_first_key=True, with_recursive_defaults=True + ) + + sflow.update({'vpp_sflow': vpp_sflow}) + + if vpp_sflow: + set_dependents('vpp_sflow', conf) return sflow + def verify(sflow): - if not sflow: + # Check if "vpp" flag could be deleted from configuration + if sflow.get('vpp_sflow'): + if 'vpp' not in sflow or 'remove' in sflow: + raise ConfigError( + 'sFlow is still configured in VPP. ' + 'Please remove sFlow configuration from VPP before proceeding.' + ) + + if 'remove' in sflow: return None # Check if configured sflow agent-address exist in the system @@ -62,8 +84,7 @@ def verify(sflow): # Check if at least one interface is configured # Skip this check if VPP is enabled if 'interface' not in sflow and 'vpp' not in sflow: - raise ConfigError( - 'sFlow requires at least one interface to be configured!') + raise ConfigError('sFlow requires at least one interface to be configured!') # Check if at least one server is configured if 'server' not in sflow: @@ -72,8 +93,9 @@ def verify(sflow): verify_vrf(sflow) return None + def generate(sflow): - if not sflow: + if 'remove' in sflow: return None render(hsflowd_conf_path, 'sflow/hsflowd.conf.j2', sflow) @@ -81,8 +103,9 @@ def generate(sflow): # Reload systemd manager configuration call('systemctl daemon-reload') + def apply(sflow): - if not sflow: + if 'remove' in sflow: # Stop flow-accounting daemon and remove configuration file call(f'systemctl stop {systemd_service}') if os.path.exists(hsflowd_conf_path): @@ -92,6 +115,9 @@ def apply(sflow): # Start/reload flow-accounting daemon call(f'systemctl restart {systemd_service}') + call_dependents() + + if __name__ == '__main__': try: config = get_config() diff --git a/src/conf_mode/vpp_sflow.py b/src/conf_mode/vpp_sflow.py index 7da4c24d6..df9d0365f 100644 --- a/src/conf_mode/vpp_sflow.py +++ b/src/conf_mode/vpp_sflow.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 +# # Copyright VyOS maintainers and contributors <maintainers@vyos.io> # # This program is free software; you can redistribute it and/or modify @@ -16,7 +18,7 @@ from vyos import ConfigError from vyos.config import Config from vyos.vpp.utils import cli_ifaces_list -from vyos.vpp import VPPControl +from vyos.vpp.sflow import SFlow def get_config(config=None) -> dict: @@ -52,21 +54,22 @@ def get_config(config=None) -> dict: key_mangling=('-', '_'), get_first_key=True, no_tag_node_value_mangle=True, + with_recursive_defaults=True, ) if system_sflow: config['system_sflow'] = system_sflow - if not config: + if effective_config: + config.update({'effective': effective_config}) + + if not conf.exists(base): config['remove'] = True return config # Add list of VPP interfaces to the config config.update({'vpp_ifaces': cli_ifaces_list(conf)}) - if effective_config: - config.update({'effective': effective_config}) - return config @@ -76,7 +79,7 @@ def verify(config): # Check if interface section exists if 'interface' not in config: - return None + raise ConfigError('Interfaces must be configured for sFlow') # Verify that all interfaces specified exist in VPP for interface in config['interface']: @@ -85,19 +88,10 @@ def verify(config): f'{interface} must be a VPP interface for sFlow monitoring' ) - # Verify sample rate is a positive integer - if 'sample_rate' in config: - try: - sample_rate = int(config['sample_rate']) - if sample_rate <= 0: - raise ConfigError('sFlow sample rate must be a positive integer') - except ValueError: - raise ConfigError('sFlow sample rate must be a valid integer') - # Verify that system sflow has enable-vpp defined if 'system_sflow' not in config or 'vpp' not in config.get('system_sflow', {}): raise ConfigError( - 'sFlow enable-vpp must be defined under system sflow configuration' + '"sflow vpp" must be defined under system sflow configuration' ) @@ -107,31 +101,31 @@ def generate(config): def apply(config): - # Initialize VPP control API - vpp = VPPControl(attempts=20, interval=500) + s = SFlow() + + # Disable sFlow on deleted interface + for interface in config.get('effective', {}).get('interface', []): + if interface not in config.get('interface', []): + s.disable_sflow(interface) if 'remove' in config: - # Disable sFlow on all interfaces - for interface in config.get('effective', {}).get('interface', []): - vpp.cli_cmd(f'sflow enable-disable {interface} disable') return None - # Configure sample rate if specified - if 'sample_rate' in config: - vpp.cli_cmd(f'sflow sampling-rate {config["sample_rate"]}') + # Configure sample rate + if 'sampling_rate' in config.get('system_sflow', {}): + s.set_sampling_rate(int(config['system_sflow']['sampling_rate'])) + + # Configure polling interval + if 'polling' in config.get('system_sflow', {}): + s.set_polling_interval(int(config['system_sflow']['polling'])) + + # Configure header bytes + if 'header_bytes' in config: + s.set_header_bytes(int(config['header_bytes'])) # Configure interfaces - if 'interface' in config: - # Enable sFlow on specified interfaces - for interface in config['interface']: - vpp.cli_cmd(f'sflow enable-disable {interface}') - - # Disable sFlow on interfaces that were removed from config - effective_interfaces = config.get('effective', {}).get('interface', []) - if effective_interfaces: - for interface in effective_interfaces: - if interface not in config['interface']: - vpp.cli_cmd(f'sflow enable-disable {interface} disable') + for interface in config.get('interface', []): + s.enable_sflow(interface) if __name__ == '__main__': diff --git a/src/migration-scripts/vpp/2-to-3 b/src/migration-scripts/vpp/2-to-3 new file mode 100644 index 000000000..655862546 --- /dev/null +++ b/src/migration-scripts/vpp/2-to-3 @@ -0,0 +1,30 @@ +# Copyright VyOS maintainers and contributors <maintainers@vyos.io> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library. If not, see <http://www.gnu.org/licenses/>. + +# Remove "vpp sflow sample-rate" since it should be automatically inherited +# from "system sflow" to prevent conflicts + +from vyos.configtree import ConfigTree + +base = ['vpp', 'sflow'] + +def migrate(config: ConfigTree) -> None: + if not config.exists(base): + # Nothing to do + return + + if config.exists(base + ['sample-rate']): + # Delete sample-rate option from sFlow configuration + config.delete(base + ['sample-rate']) |
