summaryrefslogtreecommitdiff
path: root/src/conf_mode/protocols_segment-routing.py
diff options
context:
space:
mode:
authorChristian Breunig <christian@breunig.cc>2024-12-08 08:34:41 +0100
committerChristian Breunig <christian@breunig.cc>2024-12-16 22:24:36 +0100
commit3c79477adf3cd4f4efb302b58542ddd668b562ac (patch)
tree316d03a81f1c9c37b48b658af7826eaf11413130 /src/conf_mode/protocols_segment-routing.py
parent328f354677a4fd2f60b95473698816e99aaa20a7 (diff)
downloadvyos-1x-3c79477adf3cd4f4efb302b58542ddd668b562ac.tar.gz
vyos-1x-3c79477adf3cd4f4efb302b58542ddd668b562ac.zip
frr: T6747: migrate protocols to unified FRRender class
With FRR 10.0 daemons started to be migrated to integrated FRR mgmtd and a northbound interface. This led to some drawbacks in the current state how changes to FRR are handled. The current implementation will use frr-reload.py and specifies excatly WHICH daemon needs a config update and will only replace this part inside FRR. With FRR10 and mgmtd when a partial configuration is sent to mgmtd, it will remove configuration parts from other daemons like bgpd or ospfd which have not yet been migrated to mgmtd. It's not possible to call frr-reload.py with daemon mgmtd - it will error out. This commit will also change the CLI for static routes: CLI command "set protocols static route 10.0.0.0/8 next-hop 1.2.3.4 bfd multi-hop source 1.1.1.1" will be split into: * set protocols static route 10.0.0.0/8 next-hop 1.2.3.4 bfd source-address 1.1.1.1 * set protocols static route 10.0.0.0/8 next-hop 1.2.3.4 bfd multi-hop To make the XML blocks reusable, and comply with the FRR CLI - this was actually a wrong implementation from the beginning as you can not have multiple BFD source addresses. CLI command "set protocols static route 10.0.0.0/8 next-hop 1.2.3.4 bfd multi-hop source 1.1.1.1 profile bar" is changed to: * set protocols static route 10.0.0.0/8 next-hop 1.2.3.4 bfd profile bar CLI commands "set protocols static multicast interface-route" is moved to: * set protocols static multicast route <x.x.x.x/x> interface To have an identical look and feel with regular static routes.
Diffstat (limited to 'src/conf_mode/protocols_segment-routing.py')
-rwxr-xr-xsrc/conf_mode/protocols_segment-routing.py92
1 files changed, 40 insertions, 52 deletions
diff --git a/src/conf_mode/protocols_segment-routing.py b/src/conf_mode/protocols_segment-routing.py
index 67f8005ef..0fad968e1 100755
--- a/src/conf_mode/protocols_segment-routing.py
+++ b/src/conf_mode/protocols_segment-routing.py
@@ -17,14 +17,17 @@
from sys import exit
from vyos.config import Config
-from vyos.configdict import node_changed
-from vyos.template import render_to_string
+from vyos.configdict import get_frrender_dict
+from vyos.configdict import list_diff
+from vyos.configverify import has_frr_protocol_in_dict
+from vyos.frrender import FRRender
+from vyos.ifconfig import Section
from vyos.utils.dict import dict_search
from vyos.utils.system import sysctl_write
from vyos import ConfigError
-from vyos import frr
from vyos import airbag
airbag.enable()
+frrender = FRRender()
def get_config(config=None):
if config:
@@ -32,25 +35,14 @@ def get_config(config=None):
else:
conf = Config()
- base = ['protocols', 'segment-routing']
- sr = conf.get_config_dict(base, key_mangling=('-', '_'),
- get_first_key=True,
- no_tag_node_value_mangle=True,
- with_recursive_defaults=True)
+ return get_frrender_dict(conf)
- # FRR has VRF support for different routing daemons. As interfaces belong
- # to VRFs - or the global VRF, we need to check for changed interfaces so
- # that they will be properly rendered for the FRR config. Also this eases
- # removal of interfaces from the running configuration.
- interfaces_removed = node_changed(conf, base + ['interface'])
- if interfaces_removed:
- sr['interface_removed'] = list(interfaces_removed)
+def verify(config_dict):
+ if not has_frr_protocol_in_dict(config_dict, 'segment_routing'):
+ return None
- import pprint
- pprint.pprint(sr)
- return sr
+ sr = config_dict['segment_routing']
-def verify(sr):
if 'srv6' in sr:
srv6_enable = False
if 'interface' in sr:
@@ -62,45 +54,41 @@ def verify(sr):
raise ConfigError('SRv6 should be enabled on at least one interface!')
return None
-def generate(sr):
- if not sr:
+def generate(config_dict):
+ frrender.generate(config_dict)
+ return None
+
+def apply(config_dict):
+ if not has_frr_protocol_in_dict(config_dict, 'segment_routing'):
return None
- sr['new_frr_config'] = render_to_string('frr/zebra.segment_routing.frr.j2', sr)
- return None
+ sr = config_dict['segment_routing']
-def apply(sr):
- if 'interface_removed' in sr:
- for interface in sr['interface_removed']:
- # Disable processing of IPv6-SR packets
- sysctl_write(f'net.ipv6.conf.{interface}.seg6_enabled', '0')
+ current_interfaces = Section.interfaces()
+ sr_interfaces = list(sr.get('interface', {}).keys())
- if 'interface' in sr:
- for interface, interface_config in sr['interface'].items():
- # Accept or drop SR-enabled IPv6 packets on this interface
- if 'srv6' in interface_config:
- sysctl_write(f'net.ipv6.conf.{interface}.seg6_enabled', '1')
- # Define HMAC policy for ingress SR-enabled packets on this interface
- # It's a redundant check as HMAC has a default value - but better safe
- # then sorry
- tmp = dict_search('srv6.hmac', interface_config)
- if tmp == 'accept':
- sysctl_write(f'net.ipv6.conf.{interface}.seg6_require_hmac', '0')
- elif tmp == 'drop':
- sysctl_write(f'net.ipv6.conf.{interface}.seg6_require_hmac', '1')
- elif tmp == 'ignore':
- sysctl_write(f'net.ipv6.conf.{interface}.seg6_require_hmac', '-1')
- else:
- sysctl_write(f'net.ipv6.conf.{interface}.seg6_enabled', '0')
+ for interface in list_diff(current_interfaces, sr_interfaces):
+ # Disable processing of IPv6-SR packets
+ sysctl_write(f'net.ipv6.conf.{interface}.seg6_enabled', '0')
- # Save original configuration prior to starting any commit actions
- frr_cfg = frr.FRRConfig()
- frr_cfg.load_configuration(frr.zebra_daemon)
- frr_cfg.modify_section(r'^segment-routing')
- if 'new_frr_config' in sr:
- frr_cfg.add_before(frr.default_add_before, sr['new_frr_config'])
- frr_cfg.commit_configuration(frr.zebra_daemon)
+ for interface, interface_config in sr.get('interface', {}).items():
+ # Accept or drop SR-enabled IPv6 packets on this interface
+ if 'srv6' in interface_config:
+ sysctl_write(f'net.ipv6.conf.{interface}.seg6_enabled', '1')
+ # Define HMAC policy for ingress SR-enabled packets on this interface
+ # It's a redundant check as HMAC has a default value - but better safe
+ # then sorry
+ tmp = dict_search('srv6.hmac', interface_config)
+ if tmp == 'accept':
+ sysctl_write(f'net.ipv6.conf.{interface}.seg6_require_hmac', '0')
+ elif tmp == 'drop':
+ sysctl_write(f'net.ipv6.conf.{interface}.seg6_require_hmac', '1')
+ elif tmp == 'ignore':
+ sysctl_write(f'net.ipv6.conf.{interface}.seg6_require_hmac', '-1')
+ else:
+ sysctl_write(f'net.ipv6.conf.{interface}.seg6_enabled', '0')
+ frrender.apply()
return None
if __name__ == '__main__':