summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDaniil Baturin <daniil@vyos.io>2025-10-28 15:23:37 +0000
committerGitHub <noreply@github.com>2025-10-28 15:23:37 +0000
commitecc4c85b799047f51e4a32ae5b0590017a6ce374 (patch)
tree9c210ed6efa3f9ae6b503d099963b96b8b75db34 /src
parent761968da584199e74a23d6381b3f6b400906083f (diff)
parent4c08b0694c65f1bb434538980a44a94e5ae15d24 (diff)
downloadvyos-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-xsrc/conf_mode/system_sflow.py44
-rw-r--r--src/conf_mode/vpp_sflow.py64
-rw-r--r--src/migration-scripts/vpp/2-to-330
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'])