summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorViacheslav Hletenko <v.gletenko@vyos.io>2020-06-22 23:04:57 +0300
committerGitHub <noreply@github.com>2020-06-22 22:04:57 +0200
commita8ae4f46a5d0e059f2ca1181c7730b81179160f8 (patch)
treecf94ee90a6bd70fc4bcb65a01bc7d485ab4238cc
parent7945c491fb7ed2ba7462dd2e12051ad8ce9b7e56 (diff)
downloadvyos-1x-a8ae4f46a5d0e059f2ca1181c7730b81179160f8.tar.gz
vyos-1x-a8ae4f46a5d0e059f2ca1181c7730b81179160f8.zip
rip: T2547: rewriten implementation in Python and XML
-rw-r--r--Makefile1
-rw-r--r--data/templates/frr/rip.frr.tmpl143
-rw-r--r--interface-definitions/protocols-rip.xml.in2
-rwxr-xr-xsrc/conf_mode/protocols_rip.py317
4 files changed, 461 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index 593a8a5f7..d74df8538 100644
--- a/Makefile
+++ b/Makefile
@@ -73,7 +73,6 @@ interface_definitions: $(BUILD_DIR) $(obj)
rm -f $(TMPL_DIR)/interfaces/wirelessmodem/node.tag/ipv6/node.def
rm -f $(TMPL_DIR)/protocols/node.def
rm -rf $(TMPL_DIR)/protocols/nbgp
- rm -rf $(TMPL_DIR)/protocols/nrip
rm -rf $(TMPL_DIR)/protocols/isis
rm -f $(TMPL_DIR)/protocols/static/node.def
rm -f $(TMPL_DIR)/system/node.def
diff --git a/data/templates/frr/rip.frr.tmpl b/data/templates/frr/rip.frr.tmpl
new file mode 100644
index 000000000..60bc686bd
--- /dev/null
+++ b/data/templates/frr/rip.frr.tmpl
@@ -0,0 +1,143 @@
+!
+{% if rip_conf -%}
+router rip
+{% if old_default_distance -%}
+no distance {{old_default_distance}}
+{% endif -%}
+{% if default_distance -%}
+distance {{default_distance}}
+{% endif -%}
+{% if old_default_originate -%}
+no default-information originate
+{% endif -%}
+{% if default_originate -%}
+default-information originate
+{% endif -%}
+{% if old_rip.default_metric -%}
+no default-metric {{old_rip.default_metric}}
+{% endif -%}
+{% if rip.default_metric -%}
+default-metric {{rip.default_metric}}
+{% endif -%}
+{% for protocol in old_rip.redist -%}
+{% if old_rip.redist[protocol]['metric'] and old_rip.redist[protocol]['route_map'] -%}
+no redistribute {{protocol}} metric {{rip.redist[protocol]['metric']}} route-map {{rip.redist[protocol]['route_map']}}
+{% elif old_rip.redist[protocol]['metric'] -%}
+no redistribute {{protocol}} metric {{old_rip.redist[protocol]['metric']}}
+{% elif old_rip.redist[protocol]['route_map'] -%}
+no redistribute {{protocol}} route-map {{old_rip.redist[protocol]['route_map']}}
+{% else -%}
+no redistribute {{protocol}}
+{% endif -%}
+{% endfor -%}
+{% for protocol in rip.redist -%}
+{% if rip.redist[protocol]['metric'] and rip.redist[protocol]['route_map'] -%}
+redistribute {{protocol}} metric {{rip.redist[protocol]['metric']}} route-map {{rip.redist[protocol]['route_map']}}
+{% elif rip.redist[protocol]['metric'] -%}
+redistribute {{protocol}} metric {{rip.redist[protocol]['metric']}}
+{% elif rip.redist[protocol]['route_map'] -%}
+redistribute {{protocol}} route-map {{rip.redist[protocol]['route_map']}}
+{% else -%}
+redistribute {{protocol}}
+{% endif -%}
+{% endfor -%}
+{% for iface in old_rip.distribute -%}
+{% if old_rip.distribute[iface].iface_access_list_in -%}
+no distribute-list {{old_rip.distribute[iface].iface_access_list_in}} in {{iface}}
+{% endif -%}
+{% if old_rip.distribute[iface].iface_access_list_out -%}
+no distribute-list {{old_rip.distribute[iface].iface_access_list_out}} out {{iface}}
+{% endif -%}
+{% if old_rip.distribute[iface].iface_prefix_list_in -%}
+no distribute-list prefix {{old_rip.distribute[iface].iface_prefix_list_in}} in {{iface}}
+{% endif -%}
+{% if old_rip.distribute[iface].iface_prefix_list_out -%}
+no distribute-list prefix {{old_rip.distribute[iface].iface_prefix_list_out}} out {{iface}}
+{% endif -%}
+{% endfor -%}
+{% for iface in rip.distribute -%}
+{% if rip.distribute[iface].iface_access_list_in -%}
+distribute-list {{rip.distribute[iface].iface_access_list_in}} in {{iface}}
+{% endif -%}
+{% if rip.distribute[iface].iface_access_list_out -%}
+distribute-list {{rip.distribute[iface].iface_access_list_out}} out {{iface}}
+{% endif -%}
+{% if rip.distribute[iface].iface_prefix_list_in -%}
+distribute-list prefix {{rip.distribute[iface].iface_prefix_list_in}} in {{iface}}
+{% endif -%}
+{% if rip.distribute[iface].iface_prefix_list_out -%}
+distribute-list prefix {{rip.distribute[iface].iface_prefix_list_out}} out {{iface}}
+{% endif -%}
+{% endfor -%}
+{% if old_rip.dist_acl_in -%}
+no distribute-list {{old_rip.dist_acl_in}} in
+{% endif -%}
+{% if rip.dist_acl_in -%}
+distribute-list {{rip.dist_acl_in}} in
+{% endif -%}
+{% if old_rip.dist_acl_out -%}
+no distribute-list {{old_rip.dist_acl_out}} out
+{% endif -%}
+{% if rip.dist_acl_out -%}
+distribute-list {{rip.dist_acl_out}} out
+{% endif -%}
+{% if old_rip.dist_prfx_in -%}
+no distribute-list prefix {{old_rip.dist_prfx_in}} in
+{% endif -%}
+{% if rip.dist_prfx_in -%}
+distribute-list prefix {{rip.dist_prfx_in}} in
+{% endif -%}
+{% if old_rip.dist_prfx_out -%}
+no distribute-list prefix {{old_rip.dist_prfx_out}} out
+{% endif -%}
+{% if rip.dist_prfx_out -%}
+distribute-list prefix {{rip.dist_prfx_out}} out
+{% endif -%}
+{% for network in old_rip.networks -%}
+no network {{network}}
+{% endfor -%}
+{% for network in rip.networks -%}
+network {{network}}
+{% endfor -%}
+{% for iface in old_rip.ifaces -%}
+no network {{iface}}
+{% endfor -%}
+{% for iface in rip.ifaces -%}
+network {{iface}}
+{% endfor -%}
+{% for neighbor in old_rip.neighbors -%}
+no neighbor {{neighbor}}
+{% endfor -%}
+{% for neighbor in rip.neighbors -%}
+neighbor {{neighbor}}
+{% endfor -%}
+{% for net in rip.net_distance -%}
+{% if rip.net_distance[net].access_list and rip.net_distance[net].distance -%}
+distance {{rip.net_distance[net].distance}} {{net}} {{rip.net_distance[net].access_list}}
+{% else -%}
+distance {{rip.net_distance[net].distance}} {{net}}
+{% endif -%}
+{% endfor -%}
+{% for passive_iface in old_rip.passive_iface -%}
+no passive-interface {{passive_iface}}
+{% endfor -%}
+{% for passive_iface in rip.passive_iface -%}
+passive-interface {{passive_iface}}
+{% endfor -%}
+{% for route in old_rip.route -%}
+no route {{route}}
+{% endfor -%}
+{% for route in rip.route -%}
+route {{route}}
+{% endfor -%}
+{% if old_rip.timer_update or old_rip.timer_timeout or old_rip.timer_garbage -%}
+no timers basic
+{% endif -%}
+{% if rip.timer_update or rip.timer_timeout or rip.timer_garbage -%}
+timers basic {{rip.timer_update}} {{rip.timer_timeout}} {{rip.timer_garbage}}
+{% endif -%}
+!
+{% else -%}
+no router rip
+!
+{% endif -%}
diff --git a/interface-definitions/protocols-rip.xml.in b/interface-definitions/protocols-rip.xml.in
index a9c295f4c..107f0e0d5 100644
--- a/interface-definitions/protocols-rip.xml.in
+++ b/interface-definitions/protocols-rip.xml.in
@@ -2,7 +2,7 @@
<interfaceDefinition>
<node name="protocols">
<children>
- <node name="nrip" owner="${vyos_conf_scripts_dir}/protocols_rip.py">
+ <node name="rip" owner="${vyos_conf_scripts_dir}/protocols_rip.py">
<properties>
<help>Routing Information Protocol (RIP) parameters</help>
</properties>
diff --git a/src/conf_mode/protocols_rip.py b/src/conf_mode/protocols_rip.py
new file mode 100755
index 000000000..c5ac26806
--- /dev/null
+++ b/src/conf_mode/protocols_rip.py
@@ -0,0 +1,317 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 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
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+
+from sys import exit
+
+from vyos import ConfigError
+from vyos.config import Config
+from vyos.util import call
+from vyos.template import render
+
+from vyos import airbag
+airbag.enable()
+
+config_file = r'/tmp/ripd.frr'
+
+def get_config():
+ conf = Config()
+ base = ['protocols', 'rip']
+ rip_conf = {
+ 'rip_conf' : False,
+ 'default_distance' : [],
+ 'default_originate' : False,
+ 'old_rip' : {
+ 'default_metric' : [],
+ 'distribute' : {},
+ 'neighbors' : {},
+ 'networks' : {},
+ 'net_distance' : {},
+ 'passive_iface' : {},
+ 'redist' : {},
+ 'route' : {},
+ 'ifaces' : {},
+ 'timer_garbage' : 120,
+ 'timer_timeout' : 180,
+ 'timer_update' : 30
+ },
+ 'rip' : {
+ 'default_metric' : None,
+ 'distribute' : {},
+ 'neighbors' : {},
+ 'networks' : {},
+ 'net_distance' : {},
+ 'passive_iface' : {},
+ 'redist' : {},
+ 'route' : {},
+ 'ifaces' : {},
+ 'timer_garbage' : 120,
+ 'timer_timeout' : 180,
+ 'timer_update' : 30
+ }
+ }
+
+ if not (conf.exists(base) or conf.exists_effective(base)):
+ return None
+
+ if conf.exists(base):
+ rip_conf['rip_conf'] = True
+
+ conf.set_level(base)
+
+ # Get default distance
+ if conf.exists_effective('default-distance'):
+ rip_conf['old_default_distance'] = conf.return_effective_value('default-distance')
+
+ if conf.exists('default-distance'):
+ rip_conf['default_distance'] = conf.return_value('default-distance')
+
+ # Get default information originate (originate default route)
+ if conf.exists_effective('default-information originate'):
+ rip_conf['old_default_originate'] = True
+
+ if conf.exists('default-information originate'):
+ rip_conf['default_originate'] = True
+
+ # Get default-metric
+ if conf.exists_effective('default-metric'):
+ rip_conf['old_rip']['default_metric'] = conf.return_effective_value('default-metric')
+
+ if conf.exists('default-metric'):
+ rip_conf['rip']['default_metric'] = conf.return_value('default-metric')
+
+ # Get distribute list interface old_rip
+ for dist_iface in conf.list_effective_nodes('distribute-list interface'):
+ # Set level 'distribute-list interface ethX'
+ conf.set_level((str(base)) + ' distribute-list interface ' + dist_iface)
+ rip_conf['rip']['distribute'].update({
+ dist_iface : {
+ 'iface_access_list_in': conf.return_effective_value('access-list in'.format(dist_iface)),
+ 'iface_access_list_out': conf.return_effective_value('access-list out'.format(dist_iface)),
+ 'iface_prefix_list_in': conf.return_effective_value('prefix-list in'.format(dist_iface)),
+ 'iface_prefix_list_out': conf.return_effective_value('prefix-list out'.format(dist_iface))
+ }
+ })
+
+ # Access-list in old_rip
+ if conf.exists_effective('access-list in'.format(dist_iface)):
+ rip_conf['old_rip']['iface_access_list_in'] = conf.return_effective_value('access-list in'.format(dist_iface))
+ # Access-list out old_rip
+ if conf.exists_effective('access-list out'.format(dist_iface)):
+ rip_conf['old_rip']['iface_access_list_out'] = conf.return_effective_value('access-list out'.format(dist_iface))
+ # Prefix-list in old_rip
+ if conf.exists_effective('prefix-list in'.format(dist_iface)):
+ rip_conf['old_rip']['iface_prefix_list_in'] = conf.return_effective_value('prefix-list in'.format(dist_iface))
+ # Prefix-list out old_rip
+ if conf.exists_effective('prefix-list out'.format(dist_iface)):
+ rip_conf['old_rip']['iface_prefix_list_out'] = conf.return_effective_value('prefix-list out'.format(dist_iface))
+
+ conf.set_level(base)
+
+ # Get distribute list interface
+ for dist_iface in conf.list_nodes('distribute-list interface'):
+ # Set level 'distribute-list interface ethX'
+ conf.set_level((str(base)) + ' distribute-list interface ' + dist_iface)
+ rip_conf['rip']['distribute'].update({
+ dist_iface : {
+ 'iface_access_list_in': conf.return_value('access-list in'.format(dist_iface)),
+ 'iface_access_list_out': conf.return_value('access-list out'.format(dist_iface)),
+ 'iface_prefix_list_in': conf.return_value('prefix-list in'.format(dist_iface)),
+ 'iface_prefix_list_out': conf.return_value('prefix-list out'.format(dist_iface))
+ }
+ })
+
+ # Access-list in
+ if conf.exists('access-list in'.format(dist_iface)):
+ rip_conf['rip']['iface_access_list_in'] = conf.return_value('access-list in'.format(dist_iface))
+ # Access-list out
+ if conf.exists('access-list out'.format(dist_iface)):
+ rip_conf['rip']['iface_access_list_out'] = conf.return_value('access-list out'.format(dist_iface))
+ # Prefix-list in
+ if conf.exists('prefix-list in'.format(dist_iface)):
+ rip_conf['rip']['iface_prefix_list_in'] = conf.return_value('prefix-list in'.format(dist_iface))
+ # Prefix-list out
+ if conf.exists('prefix-list out'.format(dist_iface)):
+ rip_conf['rip']['iface_prefix_list_out'] = conf.return_value('prefix-list out'.format(dist_iface))
+
+ conf.set_level((str(base)) + ' distribute-list')
+
+ # Get distribute list, access-list in
+ if conf.exists_effective('access-list in'):
+ rip_conf['old_rip']['dist_acl_in'] = conf.return_effective_value('access-list in')
+
+ if conf.exists('access-list in'):
+ rip_conf['rip']['dist_acl_in'] = conf.return_value('access-list in')
+
+ # Get distribute list, access-list out
+ if conf.exists_effective('access-list out'):
+ rip_conf['old_rip']['dist_acl_out'] = conf.return_effective_value('access-list out')
+
+ if conf.exists('access-list out'):
+ rip_conf['rip']['dist_acl_out'] = conf.return_value('access-list out')
+
+ # Get ditstribute list, prefix-list in
+ if conf.exists_effective('prefix-list in'):
+ rip_conf['old_rip']['dist_prfx_in'] = conf.return_effective_value('prefix-list in')
+
+ if conf.exists('prefix-list in'):
+ rip_conf['rip']['dist_prfx_in'] = conf.return_value('prefix-list in')
+
+ # Get distribute list, prefix-list out
+ if conf.exists_effective('prefix-list out'):
+ rip_conf['old_rip']['dist_prfx_out'] = conf.return_effective_value('prefix-list out')
+
+ if conf.exists('prefix-list out'):
+ rip_conf['rip']['dist_prfx_out'] = conf.return_value('prefix-list out')
+
+ conf.set_level(base)
+
+ # Get network Interfaces
+ if conf.exists_effective('interface'):
+ rip_conf['old_rip']['ifaces'] = conf.return_effective_values('interface')
+
+ if conf.exists('interface'):
+ rip_conf['rip']['ifaces'] = conf.return_values('interface')
+
+ # Get neighbors
+ if conf.exists_effective('neighbor'):
+ rip_conf['old_rip']['neighbors'] = conf.return_effective_values('neighbor')
+
+ if conf.exists('neighbor'):
+ rip_conf['rip']['neighbors'] = conf.return_values('neighbor')
+
+ # Get networks
+ if conf.exists_effective('network'):
+ rip_conf['old_rip']['networks'] = conf.return_effective_values('network')
+
+ if conf.exists('network'):
+ rip_conf['rip']['networks'] = conf.return_values('network')
+
+ # Get network-distance old_rip
+ for net_dist in conf.list_effective_nodes('network-distance'):
+ rip_conf['old_rip']['net_distance'].update({
+ net_dist : {
+ 'access_list' : conf.return_effective_value('network-distance {0} access-list'.format(net_dist)),
+ 'distance' : conf.return_effective_value('network-distance {0} distance'.format(net_dist)),
+ }
+ })
+
+ # Get network-distance
+ for net_dist in conf.list_nodes('network-distance'):
+ rip_conf['rip']['net_distance'].update({
+ net_dist : {
+ 'access_list' : conf.return_value('network-distance {0} access-list'.format(net_dist)),
+ 'distance' : conf.return_value('network-distance {0} distance'.format(net_dist)),
+ }
+ })
+
+ # Get passive-interface
+ if conf.exists_effective('passive-interface'):
+ rip_conf['old_rip']['passive_iface'] = conf.return_effective_values('passive-interface')
+
+ if conf.exists('passive-interface'):
+ rip_conf['rip']['passive_iface'] = conf.return_values('passive-interface')
+
+ # Get redistribute for old_rip
+ for protocol in conf.list_effective_nodes('redistribute'):
+ rip_conf['old_rip']['redist'].update({
+ protocol : {
+ 'metric' : conf.return_effective_value('redistribute {0} metric'.format(protocol)),
+ 'route_map' : conf.return_effective_value('redistribute {0} route-map'.format(protocol)),
+ }
+ })
+
+ # Get redistribute
+ for protocol in conf.list_nodes('redistribute'):
+ rip_conf['rip']['redist'].update({
+ protocol : {
+ 'metric' : conf.return_value('redistribute {0} metric'.format(protocol)),
+ 'route_map' : conf.return_value('redistribute {0} route-map'.format(protocol)),
+ }
+ })
+
+ conf.set_level(base)
+
+ # Get route
+ if conf.exists_effective('route'):
+ rip_conf['old_rip']['route'] = conf.return_effective_values('route')
+
+ if conf.exists('route'):
+ rip_conf['rip']['route'] = conf.return_values('route')
+
+ # Get timers garbage
+ if conf.exists_effective('timers garbage-collection'):
+ rip_conf['old_rip']['timer_garbage'] = conf.return_effective_value('timers garbage-collection')
+
+ if conf.exists('timers garbage-collection'):
+ rip_conf['rip']['timer_garbage'] = conf.return_value('timers garbage-collection')
+
+ # Get timers timeout
+ if conf.exists_effective('timers timeout'):
+ rip_conf['old_rip']['timer_timeout'] = conf.return_effective_value('timers timeout')
+
+ if conf.exists('timers timeout'):
+ rip_conf['rip']['timer_timeout'] = conf.return_value('timers timeout')
+
+ # Get timers update
+ if conf.exists_effective('timers update'):
+ rip_conf['old_rip']['timer_update'] = conf.return_effective_value('timers update')
+
+ if conf.exists('timers update'):
+ rip_conf['rip']['timer_update'] = conf.return_value('timers update')
+
+ return rip_conf
+
+def verify(rip):
+ if rip is None:
+ return None
+
+ # Check for network. If network-distance acl is set and distance not set
+ for net in rip['rip']['net_distance']:
+ if not rip['rip']['net_distance'][net]['distance']:
+ raise ConfigError(f"Must specify distance for network {net}")
+
+def generate(rip):
+ if rip is None:
+ return None
+
+ render(config_file, 'frr/rip.frr.tmpl', rip)
+ return None
+
+def apply(rip):
+ if rip is None:
+ return None
+
+ if os.path.exists(config_file):
+ call("sudo vtysh -d ripd -f " + config_file)
+ os.remove(config_file)
+ else:
+ print("File {0} not found".format(config_file))
+
+
+ return None
+
+if __name__ == '__main__':
+ try:
+ c = get_config()
+ verify(c)
+ generate(c)
+ apply(c)
+ except ConfigError as e:
+ print(e)
+ exit(1)
+