From 40bfaed4d1d427c33157136026944df80e02a5b6 Mon Sep 17 00:00:00 2001
From: Christian Poessinger <christian@poessinger.com>
Date: Sun, 29 Aug 2021 12:08:22 +0200
Subject: ospf: T3236: add possibility to redistribute "table"

Add new CLI command:
* "set protocols ospf redistribute table <n>"
---
 data/templates/frr/ospfd.frr.tmpl                       | 10 ++++++++--
 interface-definitions/include/ospf/metric-type.xml.i    |  2 +-
 .../include/ospf/protocol-common-config.xml.i           | 17 +++++++++++++++++
 src/conf_mode/protocols_ospf.py                         | 14 +++++++++++++-
 4 files changed, 39 insertions(+), 4 deletions(-)

diff --git a/data/templates/frr/ospfd.frr.tmpl b/data/templates/frr/ospfd.frr.tmpl
index be39519c3..90a6bbd56 100644
--- a/data/templates/frr/ospfd.frr.tmpl
+++ b/data/templates/frr/ospfd.frr.tmpl
@@ -172,8 +172,14 @@ router ospf {{ 'vrf ' + vrf if vrf is defined and vrf is not none }}
 {%   endfor %}
 {% endif %}
 {% if redistribute is defined and redistribute is not none %}
-{%   for protocol, options in redistribute.items() %}
- redistribute {{ protocol }} {{ 'metric ' + options.metric if options.metric is defined }} {{ 'metric-type ' + options.metric_type if options.metric_type is defined }} {{ 'route-map ' + options.route_map if options.route_map is defined }}
+{%   for protocol, protocols_options in redistribute.items() %}
+{%     if protocol == 'table' %}
+{%       for table, table_options in protocols_options.items() %}
+ redistribute {{ protocol }} {{ table }} {{ 'metric ' + table_options.metric if table_options.metric is defined }} {{ 'metric-type ' + table_options.metric_type if table_options.metric_type is defined }} {{ 'route-map ' + table_options.route_map if table_options.route_map is defined }}
+{%       endfor %}
+{%     else %}
+ redistribute {{ protocol }} {{ 'metric ' + protocols_options.metric if protocols_options.metric is defined }} {{ 'metric-type ' + protocols_options.metric_type if protocols_options.metric_type is defined }} {{ 'route-map ' + protocols_options.route_map if protocols_options.route_map is defined }}
+{%     endif %}
 {%   endfor %}
 {% endif %}
 {% if refresh is defined and refresh.timers is defined and refresh.timers is not none %}
diff --git a/interface-definitions/include/ospf/metric-type.xml.i b/interface-definitions/include/ospf/metric-type.xml.i
index 83dc24909..ef9fd8ac0 100644
--- a/interface-definitions/include/ospf/metric-type.xml.i
+++ b/interface-definitions/include/ospf/metric-type.xml.i
@@ -4,7 +4,7 @@
     <help>OSPF metric type for default routes (default: 2)</help>
     <valueHelp>
       <format>u32:1-2</format>
-      <description>Metric type for default routes</description>
+      <description>Set OSPF External Type 1/2 metrics</description>
     </valueHelp>
     <constraint>
       <validator name="numeric" argument="--range 1-2"/>
diff --git a/interface-definitions/include/ospf/protocol-common-config.xml.i b/interface-definitions/include/ospf/protocol-common-config.xml.i
index 546516a80..d8556ebf5 100644
--- a/interface-definitions/include/ospf/protocol-common-config.xml.i
+++ b/interface-definitions/include/ospf/protocol-common-config.xml.i
@@ -693,6 +693,23 @@
         #include <include/route-map.xml.i>
       </children>
     </node>
+    <tagNode name="table">
+      <properties>
+        <help>Redistribute non-main Kernel Routing Table</help>
+        <completionHelp>
+          <path>protocols static table</path>
+        </completionHelp>
+        <valueHelp>
+          <format>u32:1-200</format>
+          <description>Policy route table number</description>
+        </valueHelp>
+      </properties>
+      <children>
+        #include <include/ospf/metric.xml.i>
+        #include <include/ospf/metric-type.xml.i>
+        #include <include/route-map.xml.i>
+      </children>
+    </tagNode>
   </children>
 </node>
 <node name="refresh">
diff --git a/src/conf_mode/protocols_ospf.py b/src/conf_mode/protocols_ospf.py
index 06a29106d..92532fcb5 100755
--- a/src/conf_mode/protocols_ospf.py
+++ b/src/conf_mode/protocols_ospf.py
@@ -87,7 +87,13 @@ def get_config(config=None):
         del default_values['area']['area_type']['nssa']
     if 'mpls_te' not in ospf:
         del default_values['mpls_te']
-    for protocol in ['bgp', 'connected', 'isis', 'kernel', 'rip', 'static']:
+
+    for protocol in ['bgp', 'connected', 'isis', 'kernel', 'rip', 'static', 'table']:
+        # table is a tagNode thus we need to clean out all occurances for the
+        # default values and load them in later individually
+        if protocol == 'table':
+            del default_values['redistribute']['table']
+            continue
         if dict_search(f'redistribute.{protocol}', ospf) is None:
             del default_values['redistribute'][protocol]
 
@@ -127,6 +133,12 @@ def get_config(config=None):
             ospf['interface'][interface] = dict_merge(default_values,
                 ospf['interface'][interface])
 
+    if 'redistribute' in ospf and 'table' in ospf['redistribute']:
+        default_values = defaults(base + ['redistribute', 'table'])
+        for table in ospf['redistribute']['table']:
+            ospf['redistribute']['table'][table] = dict_merge(default_values,
+                ospf['redistribute']['table'][table])
+
     # We also need some additional information from the config, prefix-lists
     # and route-maps for instance. They will be used in verify().
     #
-- 
cgit v1.2.3