Page MenuHomeVyOS Platform

FRR: New framework for configuring FRR
Open, Requires assessmentPublic

Description

Configuring FRR is for the time being done in multiple different ways depending on the script used.
Some scripts execute vtysh directly to configure each and every command option, and some use hard to read templates with a script template thats being applied to FRR. this is a mismatch on "set" and "no" statements to add and remove configuration options from FRR.

This makes FRR vulnerable to inconsistency on a failed command/commit as FRR will be in one state but the commit is aborted by and VyOS does not rollback the changes done prior to the issue happening.

To try to fix this i've created a mini-framework for configuring FRR from inside python that uses frr-reload.py (the official FRR configuration reload script) to load a new configuration into FRR. it is by now possible to do this:

  • Collect the config of a daemon in FRR
  • check FRR config syntax
  • replace FRR config block (eg. replace the whole router ospf section
  • apply a new configuration via frr-reload.py

As this is using frr-reload.py we do not need to take into account commands that is going to be removed, as frr-reload.py will mirror our configuration into the running configuration. this makes creating templates in FRR much simpler and we could remove much code from the configuration scripts because of this.

i've created my own branch for doing this work: https://github.com/runborg/vyos-1x/blob/frr-mod/python/vyos/frr.py

Following here is a simple example of configuring frr with this:

>>> new_ospf_config_from_template = """
router ospf
  router-id 1.2.3.4
  area 0 network 0.0.0.0/0
"""
>>> from vyos import frr

# Load configuration from FRR
>>> original_config = frr.get_configuration(daemon='ospfd')

# Modify Configuration
>>> modified_configuration = frr.replace_section(original_config, 
                                                 new_ospf_config_from_template, 
                                                 from_re='router ospf'

# Test configuration, this will exception if an syntax error is detected
>>> frr.mark_configuration(modified_configuration)

# Apply the new configuration
>>> frr.reload_configuration(modified_configuration, daemon='ospfd')

Also see the vyos.frr module for more examples.

as this uses frr-reload.py it depends on the frr-pythontools package to being installed on the system.
and as of FRR version 7.3.0 the frr-reload.py script is not functioning and needs a patch to work as expected:
https://github.com/FRRouting/frr/issues/6062

@@ -155,7 +155,7 @@
         try:
             config_text = subprocess.check_output(
                 bindir + "/vtysh --config_dir " + confdir + " -c 'show run " + daemon + "' | /usr/bin/tail -n +4 | " + bindir + "/vtysh --config_dir " + confdir + " -m -f -",
-                shell=True, stderr=subprocess.STDOUT)
+                shell=True)
         except subprocess.CalledProcessError as e:
             ve = VtyshMarkException(e)
             ve.output = e.output

As for now i've not integrated this into any existing configuration script, but as a start this could be implemented into T2547 as a proof of concept before changing other daemons

There is one limitation on using frr-reload.py, and that is that it wants to save the configuration to frr.conf, so wee need to rewrite the frr.conf on reboot to revert these changes prior to starting FRR. or less we will be out-of-sync with FRR on bootup. (it seems like this behavior changes when writing to the integrated config va a daemon config)

Details

Difficulty level
Unknown (require assessment)
Version
-
Why the issue appeared?
Will be filled on close
Is it a breaking change?
Unspecified (possibly destroys the router)

Event Timeline

runar created this task.Wed, Jun 24, 9:38 AM
runar created this object in space S1 VyOS Public.
runar updated the task description. (Show Details)Wed, Jun 24, 9:43 AM
runar updated the task description. (Show Details)Wed, Jun 24, 9:18 PM
dmbaturin added a subscriber: dmbaturin.

I've reviewed the code and it looks good to me.

pasik added a subscriber: pasik.Sun, Jun 28, 7:07 PM
runar added a comment.Thu, Jul 9, 9:54 PM

After some benchmarking of this code i have i've gotten hold of a quite large test configuration that takes a waste amount of time to load into vyos.

as for now the config is from a production system and is not directly shareable without modification
Loading the configuration into VYOS:

vyos@vm4# time load /config/vyos-config.boot4
Loading configuration from '/config/vyos-config.boot4'
Load complete. Use 'commit' to make changes effective.
real    799m16.914s
user    30m21.682s
sys     167m25.670s
[edit]
vyos@vm4# time commit
real    98m14.035s
user    62m0.585s
sys     24m15.081s
[edit]
vyos@vm4# time show | commands > commands.out
real    6m24.554s
user    3m1.422s
sys     0m58.941s

The longest time here is the loadingtime into VyOS, that time will not be decreased using this library, but the commit time could be substantially lowered as we do not need to run 40k forks of vtysh.

The resulting frr configuration is then saved and reapplied on a new vm using this frr library with a result of:

[edit]
vyos@vm7# cat load_frr.py
from vyos import frr
with open("frr.full","r") as f:
    frr.reload_configuration(f.read())


[edit]
vyos@vm7# cat frr.full | wc -l
40677
[edit]
vyos@vm7# time sudo python3 load_frr.py
real    2m45.161s
user    0m12.901s
sys     0m8.284s