diff options
author | Christian Breunig <christian@breunig.cc> | 2023-04-08 22:09:04 +0200 |
---|---|---|
committer | Christian Breunig <christian@breunig.cc> | 2023-04-13 09:01:31 +0200 |
commit | 3f4de1390d6459cdd17dd1b6f22b1a3aec002671 (patch) | |
tree | 5091149b640ff7b064b87f2e1391f931ba5a7677 /src | |
parent | 8993298bc2c9d3e796d658dc71ba6ae6afedc4c3 (diff) | |
download | vyos-1x-3f4de1390d6459cdd17dd1b6f22b1a3aec002671.tar.gz vyos-1x-3f4de1390d6459cdd17dd1b6f22b1a3aec002671.zip |
T5150: initial implementation of new Kernel/Zebra route-map support
It is possible to install a route-map which filters the routes between routing
daemons and the OS kernel (zebra)
As of now this can be done by e.g.
* set protocols ospf route-map foo
* set protocols ospfv3 route-map foo
* set protocols bgp route-map foo
Which in turn will install the following lines into FRR
* ip protocol ospf route-map foo
* ipv6 protocol ospf6 route-map foo
* ip protocol bgp route-map foo
The current state of the VyOS CLI is incomplete as there is no way to:
* Install a filter for BGP IPv6 routes
* Install a filter for static routes
* Install a filter for connected routes
Thus the CLI should be redesigned to close match what FRR does for both the
default and any other VRF
* set system ip protocol ospf route-map foo
* set system ipv6 protocol ospfv3 route-map foo
* set system ip protocol bgp route-map foo
* set system ipv6 protocol bgp route-map foo
The configuration can be migrated accordingly. This commit does not come with
the migrator, it will be comitted later.
Diffstat (limited to 'src')
-rwxr-xr-x | src/conf_mode/protocols_static.py | 7 | ||||
-rwxr-xr-x | src/conf_mode/system-ip.py | 38 | ||||
-rwxr-xr-x | src/conf_mode/system-ipv6.py | 38 |
3 files changed, 70 insertions, 13 deletions
diff --git a/src/conf_mode/protocols_static.py b/src/conf_mode/protocols_static.py index 3e5ebb805..3eabf24bc 100755 --- a/src/conf_mode/protocols_static.py +++ b/src/conf_mode/protocols_static.py @@ -105,17 +105,10 @@ def generate(static): def apply(static): static_daemon = 'staticd' - zebra_daemon = 'zebra' # Save original configuration prior to starting any commit actions frr_cfg = frr.FRRConfig() - # The route-map used for the FIB (zebra) is part of the zebra daemon - frr_cfg.load_configuration(zebra_daemon) - frr_cfg.modify_section(r'^ip protocol static route-map [-a-zA-Z0-9.]+', '') - frr_cfg.commit_configuration(zebra_daemon) - frr_cfg.load_configuration(static_daemon) - if 'vrf' in static: vrf = static['vrf'] frr_cfg.modify_section(f'^vrf {vrf}', stop_pattern='^exit', remove_stop_mark=True) diff --git a/src/conf_mode/system-ip.py b/src/conf_mode/system-ip.py index 0c5063ed3..95865c690 100755 --- a/src/conf_mode/system-ip.py +++ b/src/conf_mode/system-ip.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2019-2022 VyOS maintainers and contributors +# Copyright (C) 2019-2023 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as @@ -18,12 +18,15 @@ from sys import exit from vyos.config import Config from vyos.configdict import dict_merge +from vyos.configverify import verify_route_map +from vyos.template import render_to_string from vyos.util import call from vyos.util import dict_search from vyos.util import sysctl_write from vyos.util import write_file from vyos.xml import defaults from vyos import ConfigError +from vyos import frr from vyos import airbag airbag.enable() @@ -40,13 +43,30 @@ def get_config(config=None): default_values = defaults(base) opt = dict_merge(default_values, opt) + # When working with FRR we need to know the corresponding address-family + opt['afi'] = 'ip' + + # We also need the route-map information from the config + # + # XXX: one MUST always call this without the key_mangling() option! See + # vyos.configverify.verify_common_route_maps() for more information. + tmp = {'policy' : {'route-map' : conf.get_config_dict(['policy', 'route-map'], + get_first_key=True)}} + # Merge policy dict into "regular" config dict + opt = dict_merge(tmp, opt) return opt def verify(opt): - pass + if 'protocol' in opt: + for protocol, protocol_options in opt['protocol'].items(): + if 'route_map' in protocol_options: + verify_route_map(protocol_options['route_map'], opt) + return def generate(opt): - pass + if 'protocol' in opt: + opt['frr_zebra_config'] = render_to_string('frr/zebra.route-map.frr.j2', opt) + return def apply(opt): # Apply ARP threshold values @@ -78,6 +98,18 @@ def apply(opt): value = '1' if (tmp != None) else '0' sysctl_write('net.ipv4.fib_multipath_hash_policy', value) + if 'protocol' in opt: + zebra_daemon = 'zebra' + # Save original configuration prior to starting any commit actions + frr_cfg = frr.FRRConfig() + + # The route-map used for the FIB (zebra) is part of the zebra daemon + frr_cfg.load_configuration(zebra_daemon) + frr_cfg.modify_section(r'ip protocol \w+ route-map [-a-zA-Z0-9.]+', stop_pattern='(\s|!)') + if 'frr_zebra_config' in opt: + frr_cfg.add_before(frr.default_add_before, opt['frr_zebra_config']) + frr_cfg.commit_configuration(zebra_daemon) + if __name__ == '__main__': try: c = get_config() diff --git a/src/conf_mode/system-ipv6.py b/src/conf_mode/system-ipv6.py index 26aacf46b..b6d3a79c3 100755 --- a/src/conf_mode/system-ipv6.py +++ b/src/conf_mode/system-ipv6.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2019-2022 VyOS maintainers and contributors +# Copyright (C) 2019-2023 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as @@ -19,11 +19,14 @@ import os from sys import exit from vyos.config import Config from vyos.configdict import dict_merge +from vyos.configverify import verify_route_map +from vyos.template import render_to_string from vyos.util import dict_search from vyos.util import sysctl_write from vyos.util import write_file from vyos.xml import defaults from vyos import ConfigError +from vyos import frr from vyos import airbag airbag.enable() @@ -41,13 +44,30 @@ def get_config(config=None): default_values = defaults(base) opt = dict_merge(default_values, opt) + # When working with FRR we need to know the corresponding address-family + opt['afi'] = 'ipv6' + + # We also need the route-map information from the config + # + # XXX: one MUST always call this without the key_mangling() option! See + # vyos.configverify.verify_common_route_maps() for more information. + tmp = {'policy' : {'route-map' : conf.get_config_dict(['policy', 'route-map'], + get_first_key=True)}} + # Merge policy dict into "regular" config dict + opt = dict_merge(tmp, opt) return opt def verify(opt): - pass + if 'protocol' in opt: + for protocol, protocol_options in opt['protocol'].items(): + if 'route_map' in protocol_options: + verify_route_map(protocol_options['route_map'], opt) + return def generate(opt): - pass + if 'protocol' in opt: + opt['frr_zebra_config'] = render_to_string('frr/zebra.route-map.frr.j2', opt) + return def apply(opt): # configure multipath @@ -78,6 +98,18 @@ def apply(opt): if name == 'accept_dad': write_file(os.path.join(root, name), value) + if 'protocol' in opt: + zebra_daemon = 'zebra' + # Save original configuration prior to starting any commit actions + frr_cfg = frr.FRRConfig() + + # The route-map used for the FIB (zebra) is part of the zebra daemon + frr_cfg.load_configuration(zebra_daemon) + frr_cfg.modify_section(r'ipv6 protocol \w+ route-map [-a-zA-Z0-9.]+', stop_pattern='(\s|!)') + if 'frr_zebra_config' in opt: + frr_cfg.add_before(frr.default_add_before, opt['frr_zebra_config']) + frr_cfg.commit_configuration(zebra_daemon) + if __name__ == '__main__': try: c = get_config() |