diff options
author | Christian Poessinger <christian@poessinger.com> | 2021-12-26 10:55:34 +0100 |
---|---|---|
committer | Christian Poessinger <christian@poessinger.com> | 2021-12-26 11:07:21 +0100 |
commit | 945a5ed22adab59314c8c0854c7cabae4e78d8d4 (patch) | |
tree | 8eb6760ecd32f108f791d1232be361f5f4f45b37 | |
parent | 48cc27d9446abb4dfa5e78a42c591ac553e85d3e (diff) | |
download | vyos-1x-945a5ed22adab59314c8c0854c7cabae4e78d8d4.tar.gz vyos-1x-945a5ed22adab59314c8c0854c7cabae4e78d8d4.zip |
ospfv3: T4107: add support for "default-information originate"
6 files changed, 86 insertions, 24 deletions
diff --git a/data/templates/frr/ospf6d.frr.tmpl b/data/templates/frr/ospf6d.frr.tmpl index 1149e640c..8279e5abb 100644 --- a/data/templates/frr/ospf6d.frr.tmpl +++ b/data/templates/frr/ospf6d.frr.tmpl @@ -69,7 +69,10 @@ router ospf6 {{ 'vrf ' + vrf if vrf is defined and vrf is not none }} area {{ area_id }} import-list {{ area_config.import_list }} {% endif %} {% endfor %} +{% endif %} auto-cost reference-bandwidth {{ auto_cost.reference_bandwidth }} +{% if default_information is defined and default_information.originate is defined and default_information.originate is not none %} + default-information originate {{ 'always' if default_information.originate.always is defined }} {{ 'metric ' + default_information.originate.metric if default_information.originate.metric is defined }} {{ 'metric-type ' + default_information.originate.metric_type if default_information.originate.metric_type is defined }} {{ 'route-map ' + default_information.originate.route_map if default_information.originate.route_map is defined }} {% endif %} {% if distance is defined and distance is not none %} {% if distance.global is defined and distance.global is not none %} diff --git a/interface-definitions/include/ospf/default-information.xml.i b/interface-definitions/include/ospf/default-information.xml.i new file mode 100644 index 000000000..50cda54a4 --- /dev/null +++ b/interface-definitions/include/ospf/default-information.xml.i @@ -0,0 +1,25 @@ +<!-- include start from ospf/intervals.xml.i --> +<node name="default-information"> + <properties> + <help>Default route advertisment settings</help> + </properties> + <children> + <node name="originate"> + <properties> + <help>Distribute a default route</help> + </properties> + <children> + <leafNode name="always"> + <properties> + <help>Always advertise a default route</help> + <valueless/> + </properties> + </leafNode> + #include <include/ospf/metric.xml.i> + #include <include/ospf/metric-type.xml.i> + #include <include/route-map.xml.i> + </children> + </node> + </children> +</node> +<!-- include end --> diff --git a/interface-definitions/include/ospf/protocol-common-config.xml.i b/interface-definitions/include/ospf/protocol-common-config.xml.i index 655f30ad3..688e78034 100644 --- a/interface-definitions/include/ospf/protocol-common-config.xml.i +++ b/interface-definitions/include/ospf/protocol-common-config.xml.i @@ -275,30 +275,8 @@ </tagNode> </children> </tagNode> -<node name="default-information"> - <properties> - <help>Default route advertisment settings</help> - </properties> - <children> - <node name="originate"> - <properties> - <help>Distribute a default route</help> - </properties> - <children> - <leafNode name="always"> - <properties> - <help>Always advertise a default route</help> - <valueless/> - </properties> - </leafNode> - #include <include/ospf/metric.xml.i> - #include <include/ospf/metric-type.xml.i> - #include <include/route-map.xml.i> - </children> - </node> - </children> -</node> #include <include/ospf/auto-cost.xml.i> +#include <include/ospf/default-information.xml.i> <leafNode name="default-metric"> <properties> <help>Metric of redistributed routes</help> diff --git a/interface-definitions/include/ospfv3/protocol-common-config.xml.i b/interface-definitions/include/ospfv3/protocol-common-config.xml.i index 6f9f8fd9d..5d08debda 100644 --- a/interface-definitions/include/ospfv3/protocol-common-config.xml.i +++ b/interface-definitions/include/ospfv3/protocol-common-config.xml.i @@ -90,6 +90,7 @@ </children> </tagNode> #include <include/ospf/auto-cost.xml.i> +#include <include/ospf/default-information.xml.i> <node name="distance"> <properties> <help>Administrative distance</help> diff --git a/smoketest/scripts/cli/test_protocols_ospfv3.py b/smoketest/scripts/cli/test_protocols_ospfv3.py index fa9d49b4b..1327fd910 100755 --- a/smoketest/scripts/cli/test_protocols_ospfv3.py +++ b/smoketest/scripts/cli/test_protocols_ospfv3.py @@ -25,10 +25,24 @@ from vyos.util import process_named_running PROCESS_NAME = 'ospf6d' base_path = ['protocols', 'ospfv3'] +route_map = 'foo-bar-baz-0815' + router_id = '192.0.2.1' default_area = '0' class TestProtocolsOSPFv3(VyOSUnitTestSHIM.TestCase): + @classmethod + def setUpClass(cls): + super(cls, cls).setUpClass() + + cls.cli_set(cls, ['policy', 'route-map', route_map, 'rule', '10', 'action', 'permit']) + cls.cli_set(cls, ['policy', 'route-map', route_map, 'rule', '20', 'action', 'permit']) + + @classmethod + def tearDownClass(cls): + cls.cli_delete(cls, ['policy', 'route-map', route_map]) + super(cls, cls).tearDownClass() + def tearDown(self): # Check for running process self.assertTrue(process_named_running(PROCESS_NAME)) @@ -199,7 +213,33 @@ class TestProtocolsOSPFv3(VyOSUnitTestSHIM.TestCase): self.assertIn(f' area {area_nssa_default} nssa default-information-originate', frrconfig) - def test_ospfv3_07_vrfs(self): + def test_ospfv3_07_default_originate(self): + seq = '100' + metric = '50' + metric_type = '1' + + self.cli_set(base_path + ['default-information', 'originate', 'metric', metric]) + self.cli_set(base_path + ['default-information', 'originate', 'metric-type', metric_type]) + self.cli_set(base_path + ['default-information', 'originate', 'route-map', route_map]) + + # commit changes + self.cli_commit() + + # Verify FRR ospfd configuration + frrconfig = self.getFRRconfig('router ospf6') + self.assertIn(f'router ospf6', frrconfig) + self.assertIn(f' default-information originate metric {metric} metric-type {metric_type} route-map {route_map}', frrconfig) + + # Now set 'always' + self.cli_set(base_path + ['default-information', 'originate', 'always']) + self.cli_commit() + + # Verify FRR ospfd configuration + frrconfig = self.getFRRconfig('router ospf6') + self.assertIn(f' default-information originate always metric {metric} metric-type {metric_type} route-map {route_map}', frrconfig) + + + def test_ospfv3_08_vrfs(self): # It is safe to assume that when the basic VRF test works, all # other OSPF related features work, as we entirely inherit the CLI # templates and Jinja2 FRR template. diff --git a/src/conf_mode/protocols_ospfv3.py b/src/conf_mode/protocols_ospfv3.py index ac86be4e6..f8e733ba5 100755 --- a/src/conf_mode/protocols_ospfv3.py +++ b/src/conf_mode/protocols_ospfv3.py @@ -23,6 +23,8 @@ from vyos.config import Config from vyos.configdict import dict_merge from vyos.configdict import node_changed from vyos.configverify import verify_common_route_maps +from vyos.configverify import verify_route_map +from vyos.configverify import verify_interface_exists from vyos.template import render_to_string from vyos.ifconfig import Interface from vyos.util import dict_search @@ -74,6 +76,14 @@ def get_config(config=None): # both the non-vrf and vrf version this is absolutely safe! default_values = defaults(base_path) + # We have to cleanup the default dict, as default values could enable features + # which are not explicitly enabled on the CLI. Example: default-information + # originate comes with a default metric-type of 2, which will enable the + # entire default-information originate tree, even when not set via CLI so we + # need to check this first and probably drop that key. + if dict_search('default_information.originate', ospfv3) is None: + del default_values['default_information'] + # XXX: T2665: we currently have no nice way for defaults under tag nodes, # clean them out and add them manually :( del default_values['interface'] @@ -98,6 +108,10 @@ def verify(ospfv3): verify_common_route_maps(ospfv3) + # As we can have a default-information route-map, we need to validate it! + route_map_name = dict_search('default_information.originate.route_map', ospfv3) + if route_map_name: verify_route_map(route_map_name, ospfv3) + if 'area' in ospfv3: for area, area_config in ospfv3['area'].items(): if 'area_type' in area_config: @@ -106,6 +120,7 @@ def verify(ospfv3): if 'interface' in ospfv3: for interface, interface_config in ospfv3['interface'].items(): + verify_interface_exists(interface) if 'ifmtu' in interface_config: mtu = Interface(interface).get_mtu() if int(interface_config['ifmtu']) > int(mtu): |