summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Poessinger <christian@poessinger.com>2021-12-26 10:55:34 +0100
committerChristian Poessinger <christian@poessinger.com>2021-12-26 11:07:21 +0100
commit945a5ed22adab59314c8c0854c7cabae4e78d8d4 (patch)
tree8eb6760ecd32f108f791d1232be361f5f4f45b37
parent48cc27d9446abb4dfa5e78a42c591ac553e85d3e (diff)
downloadvyos-1x-945a5ed22adab59314c8c0854c7cabae4e78d8d4.tar.gz
vyos-1x-945a5ed22adab59314c8c0854c7cabae4e78d8d4.zip
ospfv3: T4107: add support for "default-information originate"
-rw-r--r--data/templates/frr/ospf6d.frr.tmpl3
-rw-r--r--interface-definitions/include/ospf/default-information.xml.i25
-rw-r--r--interface-definitions/include/ospf/protocol-common-config.xml.i24
-rw-r--r--interface-definitions/include/ospfv3/protocol-common-config.xml.i1
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_ospfv3.py42
-rwxr-xr-xsrc/conf_mode/protocols_ospfv3.py15
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):