summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Breunig <christian@breunig.cc>2025-10-29 08:46:37 +0100
committerGitHub <noreply@github.com>2025-10-29 08:46:37 +0100
commit0046b24ad9def8b0672606795e70b7927ea79dc4 (patch)
treeb59595d3f8111f97f85e5ecb125c2aa2281305de
parent7e4715447564ec3a8c522ae3e4647a3474b182ed (diff)
parentc23c277d0fe3e08d1fece3e938b32406b7b976d7 (diff)
downloadvyos-1x-0046b24ad9def8b0672606795e70b7927ea79dc4.tar.gz
vyos-1x-0046b24ad9def8b0672606795e70b7927ea79dc4.zip
Merge pull request #4810 from bl0way/T7896-frr-profile
T7896: Add frr profile selection
-rw-r--r--data/templates/frr/daemons.frr.tmpl2
-rw-r--r--interface-definitions/system_frr.xml.in20
-rw-r--r--python/vyos/frrender.py11
-rwxr-xr-xsmoketest/scripts/cli/test_system_frr.py36
-rwxr-xr-xsrc/conf_mode/system_frr.py16
5 files changed, 83 insertions, 2 deletions
diff --git a/data/templates/frr/daemons.frr.tmpl b/data/templates/frr/daemons.frr.tmpl
index afd888122..fa39ae9d0 100644
--- a/data/templates/frr/daemons.frr.tmpl
+++ b/data/templates/frr/daemons.frr.tmpl
@@ -105,7 +105,7 @@ valgrind_enable=no
#watchfrr_options=""
-frr_profile="traditional"
+frr_profile="{{ profile }}"
MAX_FDS={{ descriptors }}
diff --git a/interface-definitions/system_frr.xml.in b/interface-definitions/system_frr.xml.in
index 28242dfe4..9bd190268 100644
--- a/interface-definitions/system_frr.xml.in
+++ b/interface-definitions/system_frr.xml.in
@@ -35,6 +35,26 @@
<valueless/>
</properties>
</leafNode>
+ <leafNode name="profile">
+ <properties>
+ <help>Select configuration profile to adapt different defaults</help>
+ <completionHelp>
+ <list>traditional datacenter</list>
+ </completionHelp>
+ <valueHelp>
+ <format>traditional</format>
+ <description>Adhere mostly to IETF standards or common practices in wide-area internet routing</description>
+ </valueHelp>
+ <valueHelp>
+ <format>datacenter</format>
+ <description>Single administrative domain using aggressive timers</description>
+ </valueHelp>
+ <constraint>
+ <regex>(datacenter|traditional)</regex>
+ </constraint>
+ </properties>
+ <defaultValue>traditional</defaultValue>
+ </leafNode>
<node name="snmp">
<properties>
<help>Enable SNMP integration for next daemons</help>
diff --git a/python/vyos/frrender.py b/python/vyos/frrender.py
index 91fd3667d..54456a598 100644
--- a/python/vyos/frrender.py
+++ b/python/vyos/frrender.py
@@ -233,6 +233,12 @@ def get_frrender_dict(conf: Config, argv=None) -> dict:
ip_dict['afi'] = ip_version
dict.update({ip_version : ip_dict})
+ # Get FRR profile
+ frr_system_cli_path = ['system', 'frr']
+ dict['system_frr'] = conf.get_config_dict(frr_system_cli_path, key_mangling=('-', '_'),
+ get_first_key=True,
+ with_recursive_defaults=True)
+
# Enable SNMP agentx support
# SNMP AgentX support cannot be disabled once enabled
if conf.exists(['service', 'snmp']):
@@ -733,6 +739,11 @@ class FRRender:
# we can not reload an empty file, thus we always embed the marker
output = '!\n'
+ # FRR profile configuration
+ tmp = dict_search('system_frr.profile', config_dict)
+ if tmp:
+ output += f'frr defaults {tmp}\n'
+
# Enable FRR logging
output += 'log facility daemon\n'
output += 'log timestamp precision 3\n'
diff --git a/smoketest/scripts/cli/test_system_frr.py b/smoketest/scripts/cli/test_system_frr.py
index 588f52bf5..9217f2b27 100755
--- a/smoketest/scripts/cli/test_system_frr.py
+++ b/smoketest/scripts/cli/test_system_frr.py
@@ -19,6 +19,7 @@ import unittest
from base_vyostest_shim import VyOSUnitTestSHIM
from vyos.utils.file import read_file
+from vyos.xml_ref import default_value
config_file = '/etc/frr/daemons'
base_path = ['system', 'frr']
@@ -150,7 +151,34 @@ class TestSystemFRR(VyOSUnitTestSHIM.TestCase):
self.assertTrue(bmp_enabled)
self.assertTrue(snmp_enabled)
+ def test_frr_profile_add_remove(self):
+ default_profile = default_value(base_path + ['profile'])
+
+ # test add profile
+ frr_profiles = ['traditional', 'datacenter']
+ for profile in frr_profiles:
+ # set the profile
+ self.cli_set(base_path + ['profile', profile])
+ self.cli_commit()
+ # read the config file and check content
+ self.assertIn(f'frr_profile="{profile}"', read_file(config_file))
+ # read the frr.conf file and check content
+ frrconfig = self.getFRRconfig()
+ self.assertIn(f'frr defaults {profile}', frrconfig)
+
+ # test remove profile
+ self.cli_delete(base_path)
+ self.cli_commit()
+
+ # read the config file and check content
+ self.assertIn(f'frr_profile="{default_profile}"', read_file(config_file))
+
+ # read the frr.conf file and check content
+ frrconfig = self.getFRRconfig()
+ self.assertIn(f'frr defaults {default_profile}', frrconfig)
+
def test_frr_file_descriptors(self):
+ default_descriptors = default_value(base_path + ['descriptors'])
file_descriptors = '4096'
self.cli_set(base_path + ['descriptors', file_descriptors])
@@ -160,5 +188,13 @@ class TestSystemFRR(VyOSUnitTestSHIM.TestCase):
daemons_config = read_file(config_file)
self.assertIn(f'MAX_FDS={file_descriptors}', daemons_config)
+ # test remove of descriptors
+ self.cli_delete(base_path)
+ self.cli_commit()
+
+ # read the config file and check content
+ daemons_config = read_file(config_file)
+ self.assertIn(f'MAX_FDS={default_descriptors}', daemons_config)
+
if __name__ == '__main__':
unittest.main(verbosity=2, failfast=VyOSUnitTestSHIM.TestCase.debug_on())
diff --git a/src/conf_mode/system_frr.py b/src/conf_mode/system_frr.py
index 06af37ad8..5365ac294 100755
--- a/src/conf_mode/system_frr.py
+++ b/src/conf_mode/system_frr.py
@@ -19,12 +19,15 @@ from sys import exit
from vyos import ConfigError
from vyos.base import Warning
from vyos.config import Config
+from vyos.frrender import FRRender
+from vyos.frrender import get_frrender_dict
from vyos.logger import syslog
from vyos.template import render_to_string
from vyos.utils.boot import boot_configuration_complete
from vyos.utils.file import read_file
from vyos.utils.file import write_file
from vyos.utils.process import call
+from vyos.utils.process import is_systemd_service_running
from vyos import airbag
airbag.enable()
@@ -42,7 +45,8 @@ def get_config(config=None):
frr_config = conf.get_config_dict(base, key_mangling=('-', '_'),
get_first_key=True,
with_recursive_defaults=True)
-
+ # get FRR configuration
+ frr_config['frr_dict'] = get_frrender_dict(conf)
return frr_config
def verify(frr_config):
@@ -60,7 +64,17 @@ def generate(frr_config):
write_file(config_file, daemons_config_new)
frr_config['config_file_changed'] = True
+ # profile could be automatically generated by frr in frr.conf
+ # and needs to be updated as it is taking precedence
+ if 'frr_dict' in frr_config and not is_systemd_service_running('vyos-configd.service'):
+ FRRender().generate(frr_config['frr_dict'])
+ return None
+
def apply(frr_config):
+ # applying the profile configuration if necessary
+ if 'frr_dict' in frr_config and not is_systemd_service_running('vyos-configd.service'):
+ FRRender().apply()
+
# display warning to user
if boot_configuration_complete() and frr_config.get('config_file_changed'):
# Since FRR restart is not safe thing, better to give