summaryrefslogtreecommitdiff
path: root/src/conf_mode
diff options
context:
space:
mode:
Diffstat (limited to 'src/conf_mode')
-rwxr-xr-xsrc/conf_mode/protocols_mpls.py411
1 files changed, 95 insertions, 316 deletions
diff --git a/src/conf_mode/protocols_mpls.py b/src/conf_mode/protocols_mpls.py
index 84948baf4..6d3b98c47 100755
--- a/src/conf_mode/protocols_mpls.py
+++ b/src/conf_mode/protocols_mpls.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2019-2020 VyOS maintainers and contributors
+# Copyright (C) 2017-2020 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
@@ -16,351 +16,130 @@
import os
+from sys import exit
+
from vyos.config import Config
+from vyos.configdict import node_changed
from vyos import ConfigError
from vyos.util import call
from vyos.template import render
-
+from vyos.template import render_to_string
+from vyos import frr
from vyos import airbag
airbag.enable()
config_file = r'/tmp/ldpd.frr'
-def sysctl(name, value):
- call('sysctl -wq {}={}'.format(name, value))
-
def get_config(config=None):
if config:
conf = config
else:
conf = Config()
- mpls_conf = {
- 'router_id' : None,
- 'mpls_ldp' : False,
- 'old_parameters' : {
- 'no_ttl_propagation' : False,
- 'maximum_ttl' : None
- },
- 'parameters' : {
- 'no_ttl_propagation' : False,
- 'maximum_ttl' : None
- },
- 'old_ldp' : {
- 'interfaces' : [],
- 'neighbors' : {},
- 'd_transp_ipv4' : None,
- 'd_transp_ipv6' : None,
- 'hello_ipv4_holdtime' : None,
- 'hello_ipv4_interval' : None,
- 'hello_ipv6_holdtime' : None,
- 'hello_ipv6_interval' : None,
- 'ses_ipv4_hold' : None,
- 'ses_ipv6_hold' : None,
- 'export_ipv4_exp' : False,
- 'export_ipv6_exp' : False,
- 'cisco_interop_tlv' : False,
- 'transport_prefer_ipv4' : False,
- 'target_ipv4_addresses' : [],
- 'target_ipv6_addresses' : [],
- 'target_ipv4_enable' : False,
- 'target_ipv6_enable' : False,
- 'target_ipv4_hello_int' : None,
- 'target_ipv6_hello_int' : None,
- 'target_ipv4_hello_hold' : None,
- 'target_ipv6_hello_hold' : None
- },
- 'ldp' : {
- 'interfaces' : [],
- 'neighbors' : {},
- 'd_transp_ipv4' : None,
- 'd_transp_ipv6' : None,
- 'hello_ipv4_holdtime' : None,
- 'hello_ipv4_interval' : None,
- 'hello_ipv6_holdtime' : None,
- 'hello_ipv6_interval' : None,
- 'ses_ipv4_hold' : None,
- 'ses_ipv6_hold' : None,
- 'export_ipv4_exp' : False,
- 'export_ipv6_exp' : False,
- 'cisco_interop_tlv' : False,
- 'transport_prefer_ipv4' : False,
- 'target_ipv4_addresses' : [],
- 'target_ipv6_addresses' : [],
- 'target_ipv4_enable' : False,
- 'target_ipv6_enable' : False,
- 'target_ipv4_hello_int' : None,
- 'target_ipv6_hello_int' : None,
- 'target_ipv4_hello_hold' : None,
- 'target_ipv6_hello_hold' : None
- }
- }
- if not (conf.exists('protocols mpls') or conf.exists_effective('protocols mpls')):
- return None
-
- # If LDP is defined then enable LDP portion of code
- if conf.exists('protocols mpls ldp'):
- mpls_conf['mpls_ldp'] = True
-
- # Set to MPLS hierarchy configuration level
- conf.set_level('protocols mpls')
-
- # Get no_ttl_propagation
- if conf.exists_effective('parameters no-propagate-ttl'):
- mpls_conf['old_parameters']['no_ttl_propagation'] = True
-
- if conf.exists('parameters no-propagate-ttl'):
- mpls_conf['parameters']['no_ttl_propagation'] = True
-
- # Get maximum_ttl
- if conf.exists_effective('parameters maximum-ttl'):
- mpls_conf['old_parameters']['maximum_ttl'] = conf.return_effective_value('parameters maximum-ttl')
-
- if conf.exists('parameters maximum-ttl'):
- mpls_conf['parameters']['maximum_ttl'] = conf.return_value('parameters maximum-ttl')
-
- # Set to LDP hierarchy configuration level
- conf.set_level('protocols mpls ldp')
-
- # Get router-id
- if conf.exists_effective('router-id'):
- mpls_conf['old_router_id'] = conf.return_effective_value('router-id')
-
- if conf.exists('router-id'):
- mpls_conf['router_id'] = conf.return_value('router-id')
-
- # Get hello-ipv4-holdtime
- if conf.exists_effective('discovery hello-ipv4-holdtime'):
- mpls_conf['old_ldp']['hello_ipv4_holdtime'] = conf.return_effective_value('discovery hello-ipv4-holdtime')
-
- if conf.exists('discovery hello-ipv4-holdtime'):
- mpls_conf['ldp']['hello_ipv4_holdtime'] = conf.return_value('discovery hello-ipv4-holdtime')
-
- # Get hello-ipv4-interval
- if conf.exists_effective('discovery hello-ipv4-interval'):
- mpls_conf['old_ldp']['hello_ipv4_interval'] = conf.return_effective_value('discovery hello-ipv4-interval')
-
- if conf.exists('discovery hello-ipv4-interval'):
- mpls_conf['ldp']['hello_ipv4_interval'] = conf.return_value('discovery hello-ipv4-interval')
-
- # Get hello-ipv6-holdtime
- if conf.exists_effective('discovery hello-ipv6-holdtime'):
- mpls_conf['old_ldp']['hello_ipv6_holdtime'] = conf.return_effective_value('discovery hello-ipv6-holdtime')
-
- if conf.exists('discovery hello-ipv6-holdtime'):
- mpls_conf['ldp']['hello_ipv6_holdtime'] = conf.return_value('discovery hello-ipv6-holdtime')
-
- # Get hello-ipv6-interval
- if conf.exists_effective('discovery hello-ipv6-interval'):
- mpls_conf['old_ldp']['hello_ipv6_interval'] = conf.return_effective_value('discovery hello-ipv6-interval')
-
- if conf.exists('discovery hello-ipv6-interval'):
- mpls_conf['ldp']['hello_ipv6_interval'] = conf.return_value('discovery hello-ipv6-interval')
-
- # Get session-ipv4-holdtime
- if conf.exists_effective('discovery session-ipv4-holdtime'):
- mpls_conf['old_ldp']['ses_ipv4_hold'] = conf.return_effective_value('discovery session-ipv4-holdtime')
-
- if conf.exists('discovery session-ipv4-holdtime'):
- mpls_conf['ldp']['ses_ipv4_hold'] = conf.return_value('discovery session-ipv4-holdtime')
-
- # Get session-ipv6-holdtime
- if conf.exists_effective('discovery session-ipv6-holdtime'):
- mpls_conf['old_ldp']['ses_ipv6_hold'] = conf.return_effective_value('discovery session-ipv6-holdtime')
-
- if conf.exists('discovery session-ipv6-holdtime'):
- mpls_conf['ldp']['ses_ipv6_hold'] = conf.return_value('discovery session-ipv6-holdtime')
-
- # Get discovery transport-ipv4-address
- if conf.exists_effective('discovery transport-ipv4-address'):
- mpls_conf['old_ldp']['d_transp_ipv4'] = conf.return_effective_value('discovery transport-ipv4-address')
-
- if conf.exists('discovery transport-ipv4-address'):
- mpls_conf['ldp']['d_transp_ipv4'] = conf.return_value('discovery transport-ipv4-address')
-
- # Get discovery transport-ipv6-address
- if conf.exists_effective('discovery transport-ipv6-address'):
- mpls_conf['old_ldp']['d_transp_ipv6'] = conf.return_effective_value('discovery transport-ipv6-address')
-
- if conf.exists('discovery transport-ipv6-address'):
- mpls_conf['ldp']['d_transp_ipv6'] = conf.return_value('discovery transport-ipv6-address')
-
- # Get export ipv4 explicit-null
- if conf.exists_effective('export ipv4 explicit-null'):
- mpls_conf['old_ldp']['export_ipv4_exp'] = True
-
- if conf.exists('export ipv4 explicit-null'):
- mpls_conf['ldp']['export_ipv4_exp'] = True
-
- # Get export ipv6 explicit-null
- if conf.exists_effective('export ipv6 explicit-null'):
- mpls_conf['old_ldp']['export_ipv6_exp'] = True
-
- if conf.exists('export ipv6 explicit-null'):
- mpls_conf['ldp']['export_ipv6_exp'] = True
-
- # Get target_ipv4_addresses
- if conf.exists_effective('targeted-neighbor ipv4 address'):
- mpls_conf['old_ldp']['target_ipv4_addresses'] = conf.return_effective_values('targeted-neighbor ipv4 address')
-
- if conf.exists('targeted-neighbor ipv4 address'):
- mpls_conf['ldp']['target_ipv4_addresses'] = conf.return_values('targeted-neighbor ipv4 address')
-
- # Get target_ipv4_enable
- if conf.exists_effective('targeted-neighbor ipv4 enable'):
- mpls_conf['old_ldp']['target_ipv4_enable'] = True
-
- if conf.exists('targeted-neighbor ipv4 enable'):
- mpls_conf['ldp']['target_ipv4_enable'] = True
-
- # Get target_ipv4_hello_int
- if conf.exists_effective('targeted-neighbor ipv4 hello-interval'):
- mpls_conf['old_ldp']['target_ipv4_hello_int'] = conf.return_effective_value('targeted-neighbor ipv4 hello-interval')
-
- if conf.exists('targeted-neighbor ipv4 hello-interval'):
- mpls_conf['ldp']['target_ipv4_hello_int'] = conf.return_value('targeted-neighbor ipv4 hello-interval')
-
- # Get target_ipv4_hello_hold
- if conf.exists_effective('targeted-neighbor ipv4 hello-holdtime'):
- mpls_conf['old_ldp']['target_ipv4_hello_hold'] = conf.return_effective_value('targeted-neighbor ipv4 hello-holdtime')
-
- if conf.exists('targeted-neighbor ipv4 hello-holdtime'):
- mpls_conf['ldp']['target_ipv4_hello_hold'] = conf.return_value('targeted-neighbor ipv4 hello-holdtime')
-
- # Get target_ipv6_addresses
- if conf.exists_effective('targeted-neighbor ipv6 address'):
- mpls_conf['old_ldp']['target_ipv6_addresses'] = conf.return_effective_values('targeted-neighbor ipv6 address')
-
- if conf.exists('targeted-neighbor ipv6 address'):
- mpls_conf['ldp']['target_ipv6_addresses'] = conf.return_values('targeted-neighbor ipv6 address')
-
- # Get target_ipv6_enable
- if conf.exists_effective('targeted-neighbor ipv6 enable'):
- mpls_conf['old_ldp']['target_ipv6_enable'] = True
-
- if conf.exists('targeted-neighbor ipv6 enable'):
- mpls_conf['ldp']['target_ipv6_enable'] = True
-
- # Get target_ipv6_hello_int
- if conf.exists_effective('targeted-neighbor ipv6 hello-interval'):
- mpls_conf['old_ldp']['target_ipv6_hello_int'] = conf.return_effective_value('targeted-neighbor ipv6 hello-interval')
-
- if conf.exists('targeted-neighbor ipv6 hello-interval'):
- mpls_conf['ldp']['target_ipv6_hello_int'] = conf.return_value('targeted-neighbor ipv6 hello-interval')
-
- # Get target_ipv6_hello_hold
- if conf.exists_effective('targeted-neighbor ipv6 hello-holdtime'):
- mpls_conf['old_ldp']['target_ipv6_hello_hold'] = conf.return_effective_value('targeted-neighbor ipv6 hello-holdtime')
-
- if conf.exists('targeted-neighbor ipv6 hello-holdtime'):
- mpls_conf['ldp']['target_ipv6_hello_hold'] = conf.return_value('targeted-neighbor ipv6 hello-holdtime')
-
- # Get parameters cisco-interop-tlv
- if conf.exists_effective('parameters cisco-interop-tlv'):
- mpls_conf['old_ldp']['cisco_interop_tlv'] = True
-
- if conf.exists('parameters cisco-interop-tlv'):
- mpls_conf['ldp']['cisco_interop_tlv'] = True
-
- # Get parameters transport-prefer-ipv4
- if conf.exists_effective('parameters transport-prefer-ipv4'):
- mpls_conf['old_ldp']['transport_prefer_ipv4'] = True
-
- if conf.exists('parameters transport-prefer-ipv4'):
- mpls_conf['ldp']['transport_prefer_ipv4'] = True
-
- # Get interfaces
- if conf.exists_effective('interface'):
- mpls_conf['old_ldp']['interfaces'] = conf.return_effective_values('interface')
-
- if conf.exists('interface'):
- mpls_conf['ldp']['interfaces'] = conf.return_values('interface')
-
- # Get neighbors
- for neighbor in conf.list_effective_nodes('neighbor'):
- mpls_conf['old_ldp']['neighbors'].update({
- neighbor : {
- 'password' : conf.return_effective_value('neighbor {0} password'.format(neighbor), default=''),
- 'ttl_security' : conf.return_effective_value('neighbor {0} ttl-security'.format(neighbor), default=''),
- 'session_holdtime' : conf.return_effective_value('neighbor {0} session-holdtime'.format(neighbor), default='')
- }
- })
-
- for neighbor in conf.list_nodes('neighbor'):
- mpls_conf['ldp']['neighbors'].update({
- neighbor : {
- 'password' : conf.return_value('neighbor {0} password'.format(neighbor), default=''),
- 'ttl_security' : conf.return_value('neighbor {0} ttl-security'.format(neighbor), default=''),
- 'session_holdtime' : conf.return_value('neighbor {0} session-holdtime'.format(neighbor), default='')
- }
- })
-
- return mpls_conf
-
-def operate_mpls_on_intfc(interfaces, action):
- rp_filter = 0
- if action == 1:
- rp_filter = 2
- for iface in interfaces:
- sysctl('net.mpls.conf.{0}.input'.format(iface), action)
- # Operate rp filter
- sysctl('net.ipv4.conf.{0}.rp_filter'.format(iface), rp_filter)
+ base = ['protocols', 'mpls']
+ mpls = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True)
+ return mpls
def verify(mpls):
- if mpls is None:
+ # If no config, then just bail out early.
+ if not mpls:
return None
- if mpls['mpls_ldp']:
- # Require router-id
- if not mpls['router_id']:
- raise ConfigError(f"MPLS ldp router-id is mandatory!")
-
- # Require discovery transport-address
- if not mpls['ldp']['d_transp_ipv4'] and not mpls['ldp']['d_transp_ipv6']:
- raise ConfigError(f"MPLS ldp discovery transport address is mandatory!")
+ # Checks to see if LDP is properly configured
+ if 'ldp' in mpls:
+ # If router ID not defined
+ if 'router_id' in mpls['ldp']:
+ pass
+ else:
+ raise ConfigError('Router ID missing. An LDP router id is mandatory!')
+ # If interface not set
+ if 'interface' in mpls['ldp']:
+ pass
+ else:
+ raise ConfigError('LDP interfaces are missing. An LDP interface is mandatory!')
+ # If transport addresses are not set
+ if 'discovery' in mpls['ldp']:
+ if 'transport_ipv4_address' in mpls['ldp']['discovery']:
+ pass
+ elif 'transport_ipv6_address' in mpls['ldp']['discovery']:
+ pass
+ else:
+ raise ConfigError('LDP transport address is missing. Add an LDP transport address!')
+ else:
+ raise ConfigError('LDP transport address is missing. Add an LDP transport address!')
- # Require interface
- if not mpls['ldp']['interfaces']:
- raise ConfigError(f"MPLS ldp interface is mandatory!")
+ return None
def generate(mpls):
- if mpls is None:
+ # If there's no MPLS config generated, create dictionary key with no value.
+ if not mpls:
+ mpls['new_frr_config'] = ''
return None
- render(config_file, 'frr/ldpd.frr.tmpl', mpls)
+ mpls['new_frr_config'] = render_to_string('frr/ldpd.frr.tmpl', mpls, trim_blocks=True)
return None
def apply(mpls):
- if mpls is None:
- return None
-
- # Set number of entries in the platform label table
- if mpls['mpls_ldp']:
- sysctl('net.mpls.platform_labels', '1048575')
+ # Define dictionary that will load FRR config
+ frr_cfg = {}
+ # Save original configuration prior to starting any commit actions
+ frr_cfg['original_config'] = frr.get_configuration(daemon='ldpd')
+ frr_cfg['modified_config'] = frr.replace_section(frr_cfg['original_config'], mpls['new_frr_config'], from_re='mpls.*')
+
+ # If FRR config is blank, rerun the blank commit three times due to frr-reload
+ # behavior/bug not properly clearing out on one commit.
+ if mpls['new_frr_config'] == '':
+ for x in range(3):
+ frr.reload_configuration(frr_cfg['modified_config'], daemon='ldpd')
+ elif not 'ldp' in mpls:
+ for x in range(3):
+ frr.reload_configuration(frr_cfg['modified_config'], daemon='ldpd')
else:
- sysctl('net.mpls.platform_labels', '0')
+ # FRR mark configuration will test for syntax errors and throws an
+ # exception if any syntax errors is detected
+ frr.mark_configuration(frr_cfg['modified_config'])
+
+ # Commit resulting configuration to FRR, this will throw CommitError
+ # on failure
+ frr.reload_configuration(frr_cfg['modified_config'], daemon='ldpd')
- # Choose whether to copy IP TTL to MPLS header TTL
- if mpls['parameters']['no_ttl_propagation']:
- sysctl('net.mpls.ip_ttl_propagate', '0')
+ # Set number of entries in the platform label tables
+ if 'interface' in mpls:
+ os.system('sysctl -wq net.mpls.platform_labels=1048575')
else:
- sysctl('net.mpls.ip_ttl_propagate', '1')
-
- # Choose whether to limit maximum MPLS header TTL
- if mpls['parameters']['maximum_ttl']:
- sysctl('net.mpls.default_ttl', '%s' %(mpls['parameters']['maximum_ttl']))
+ os.system('sysctl -wq net.mpls.platform_labels=0')
+
+ # Check for changes in global MPLS options
+ if 'parameters' in mpls:
+ # Choose whether to copy IP TTL to MPLS header TTL
+ if 'no_propagate_ttl' in mpls['parameters']:
+ os.system('sysctl -wq net.mpls.ip_ttl_propagate=0')
+ # Choose whether to limit maximum MPLS header TTL
+ if 'maximum_ttl' in mpls['parameters']:
+ os.system('sysctl -wq net.mpls.default_ttl=%s' %(mpls['parameters'].get('maximum_ttl')))
else:
- sysctl('net.mpls.default_ttl', '255')
-
- # Allow mpls on interfaces
- operate_mpls_on_intfc(mpls['ldp']['interfaces'], 1)
-
- # Disable mpls on deleted interfaces
- diactive_ifaces = set(mpls['old_ldp']['interfaces']).difference(mpls['ldp']['interfaces'])
- operate_mpls_on_intfc(diactive_ifaces, 0)
-
- if os.path.exists(config_file):
- call(f'vtysh -d ldpd -f {config_file}')
- os.remove(config_file)
+ # Set default global MPLS options if not defined.
+ os.system('sysctl -wq net.mpls.ip_ttl_propagate=1')
+ os.system('sysctl -wq net.mpls.default_ttl=255')
+
+ # Enable and disable MPLS processing on interfaces per configuration
+ if 'interface' in mpls:
+ system_interfaces = []
+ system_interfaces.append(((os.popen('sysctl net.mpls.conf').read()).split('\n')))
+ del system_interfaces[0][-1]
+ for configured_interface in mpls['interface']:
+ for system_interface in system_interfaces[0]:
+ if configured_interface in system_interface:
+ os.system('sysctl -wq net.mpls.conf.%s.input=1' %(configured_interface))
+ elif system_interface.endswith(' = 1'):
+ system_interface = system_interface.replace(' = 1', '=0')
+ os.system('sysctl -wq %s' %(system_interface))
+ else:
+ # If MPLS interfaces are not configured, set MPLS processing disabled
+ system_interfaces = []
+ system_interfaces.append(((os.popen('sysctl net.mpls.conf').read()).replace(" = 1", "=0")).split('\n'))
+ del system_interfaces[0][-1]
+ for interface in (system_interfaces[0]):
+ os.system('sysctl -wq %s' %(interface))
return None