From 0ddd684ff12b297313331a1c87f36d8308eade8d Mon Sep 17 00:00:00 2001
From: Christian Poessinger <christian@poessinger.com>
Date: Fri, 22 Jan 2021 16:31:20 +0100
Subject: ospf: T3236: add default values

---
 interface-definitions/include/ospf-metric.xml.i |  6 +-
 interface-definitions/protocols-ospf.xml.in     | 95 ++++++++++---------------
 src/conf_mode/protocols_ospf.py                 | 25 +++++++
 3 files changed, 68 insertions(+), 58 deletions(-)
 mode change 100644 => 100755 src/conf_mode/protocols_ospf.py

diff --git a/interface-definitions/include/ospf-metric.xml.i b/interface-definitions/include/ospf-metric.xml.i
index 771fda02d..b2812ba36 100644
--- a/interface-definitions/include/ospf-metric.xml.i
+++ b/interface-definitions/include/ospf-metric.xml.i
@@ -13,15 +13,16 @@
 </leafNode>
 <leafNode name="metric-type">
   <properties>
-    <help>OSPF metric type for default routes</help>
+    <help>OSPF metric type for default routes (default: 2)</help>
     <valueHelp>
       <format>u32:1-2</format>
-      <description>Metric type for default routes (default 2)</description>
+      <description>Metric type for default routes</description>
     </valueHelp>
     <constraint>
       <validator name="numeric" argument="--range 1-2"/>
     </constraint>
   </properties>
+  <defaultValue>2</defaultValue>
 </leafNode>
 <leafNode name="route-map">
   <properties>
@@ -31,3 +32,4 @@
     </completionHelp>
   </properties>
 </leafNode>
+<!-- included end -->
diff --git a/interface-definitions/protocols-ospf.xml.in b/interface-definitions/protocols-ospf.xml.in
index 4d5b84be0..04ad39732 100644
--- a/interface-definitions/protocols-ospf.xml.in
+++ b/interface-definitions/protocols-ospf.xml.in
@@ -3,7 +3,7 @@
 <interfaceDefinition>
   <node name="protocols">
     <children>
-      <node name="nospf" owner="${vyos_conf_scripts_dir}/protocols_ospf.py">
+      <node name="ospf" owner="${vyos_conf_scripts_dir}/protocols_ospf.py">
         <properties>
           <help>Open Shortest Path First protocol (OSPF) parameters</help>
           <priority>620</priority>
@@ -109,7 +109,7 @@
                       </leafNode>
                       <leafNode name="translate">
                         <properties>
-                          <help>Nssa-abr</help>
+                          <help>Configure NSSA-ABR (default: candidate)</help>
                           <completionHelp>
                             <list>always candidate never</list>
                           </completionHelp>
@@ -129,6 +129,7 @@
                             <regex>^(always|candidate|never)$</regex>
                           </constraint>
                         </properties>
+                        <defaultValue>candidate</defaultValue>
                       </leafNode>
                     </children>
                   </node>
@@ -353,7 +354,7 @@
           </tagNode>
           <node name="auto-cost">
             <properties>
-              <help>Calculate OSPF interface cost according to bandwidth</help>
+              <help>Calculate OSPF interface cost according to bandwidth (default: 100)</help>
             </properties>
             <children>
               <leafNode name="reference-bandwidth">
@@ -361,12 +362,13 @@
                   <help>Reference bandwidth method to assign OSPF cost</help>
                   <valueHelp>
                     <format>u32:1-4294967</format>
-                    <description>Reference bandwidth cost in Mbits/sec (default 100)</description>
+                    <description>Reference bandwidth cost in Mbits/sec</description>
                   </valueHelp>
                   <constraint>
                     <validator name="numeric" argument="--range 1-4294967"/>
                   </constraint>
                 </properties>
+                <defaultValue>100</defaultValue>
               </leafNode>
             </children>
           </node>
@@ -386,38 +388,7 @@
                       <valueless/>
                     </properties>
                   </leafNode>
-                  <leafNode name="metric">
-                    <properties>
-                      <help>OSPF default metric</help>
-                      <valueHelp>
-                        <format>u32:0-16777214</format>
-                        <description>Default metric</description>
-                      </valueHelp>
-                      <constraint>
-                        <validator name="numeric" argument="--range 0-16777214"/>
-                      </constraint>
-                    </properties>
-                  </leafNode>
-                  <leafNode name="metric-type">
-                    <properties>
-                      <help>OSPF metric type for default routes</help>
-                      <valueHelp>
-                        <format>u32:1-2</format>
-                        <description>Metric type for default routes (default 2)</description>
-                      </valueHelp>
-                      <constraint>
-                        <validator name="numeric" argument="--range 1-2"/>
-                      </constraint>
-                    </properties>
-                  </leafNode>
-                  <leafNode name="route-map">
-                    <properties>
-                      <help>Route map reference</help>
-                      <completionHelp>
-                        <path>policy route-map</path>
-                      </completionHelp>
-                    </properties>
-                  </leafNode>
+                  #include <include/ospf-metric.xml.i>
                 </children>
               </node>
             </children>
@@ -589,27 +560,29 @@
             <children>
               <leafNode name="poll-interval">
                 <properties>
-                  <help>Dead neighbor polling interval</help>
+                  <help>Dead neighbor polling interval (default: 60)</help>
                   <valueHelp>
                     <format>u32:1-65535</format>
-                    <description>Seconds between dead neighbor polling interval (default 60)</description>
+                    <description>Seconds between dead neighbor polling interval</description>
                   </valueHelp>
                   <constraint>
                     <validator name="numeric" argument="--range 1-65535"/>
                   </constraint>
                 </properties>
+                <defaultValue>60</defaultValue>
               </leafNode>
               <leafNode name="priority">
                 <properties>
-                  <help>Neighbor priority in seconds</help>
+                  <help>Neighbor priority in seconds (default: 0)</help>
                   <valueHelp>
                     <format>u32:0-255</format>
-                    <description>Neighbor priority (default 0)</description>
+                    <description>Neighbor priority</description>
                   </valueHelp>
                   <constraint>
                     <validator name="numeric" argument="--range 0-255"/>
                   </constraint>
                 </properties>
+                <defaultValue>0</defaultValue>
               </leafNode>
             </children>
           </tagNode>
@@ -620,7 +593,7 @@
             <children>
               <leafNode name="abr-type">
                 <properties>
-                  <help>OSPF ABR type</help>
+                  <help>OSPF ABR type (default: cisco)</help>
                   <completionHelp>
                     <list>cisco ibm shortcut standard</list>
                   </completionHelp>
@@ -644,6 +617,7 @@
                     <regex>^(cisco|ibm|shortcut|standard)$</regex>
                   </constraint>
                 </properties>
+                <defaultValue>cisco</defaultValue>
               </leafNode>
               <leafNode name="opaque-lsa">
                 <properties>
@@ -674,31 +648,37 @@
           <leafNode name="passive-interface">
             <properties>
               <help>Suppress routing updates on an interface</help>
+              <completionHelp>
+                <list>default</list>
+                <script>${vyos_completion_dir}/list_interfaces.py</script>
+              </completionHelp>
               <valueHelp>
-                <format>&lt;interface&gt;</format>
+                <format>txt</format>
                 <description>Interface to be passive (i.e. suppress routing updates)</description>
               </valueHelp>
               <valueHelp>
                 <format>default</format>
                 <description>Default to suppress routing updates on all interfaces</description>
               </valueHelp>
-              <completionHelp>
-                <list>default</list>
-                <script>${vyos_completion_dir}/list_interfaces.py</script>
-              </completionHelp>
+              <constraint>
+                <regex>^(br|bond|dum|en|eth|gnv|peth|tun|vti|vxlan|wg|wlan)[0-9]+|lo|default$</regex>
+              </constraint>
               <multi/>
             </properties>
           </leafNode>
           <leafNode name="passive-interface-exclude">
             <properties>
               <help>Interface to exclude when using 'passive-interface default'</help>
-              <valueHelp>
-                <format>&lt;interface&gt;</format>
-                <description>Interface to be passive (i.e. suppress routing updates)</description>
-              </valueHelp>
               <completionHelp>
                 <script>${vyos_completion_dir}/list_interfaces.py</script>
               </completionHelp>
+              <valueHelp>
+                <format>txt</format>
+                <description>Interface to be passive (i.e. suppress routing updates)</description>
+              </valueHelp>
+              <constraint>
+                <regex>^(br|bond|dum|en|eth|gnv|peth|tun|vti|vxlan|wg|wlan)[0-9]+|lo$</regex>
+              </constraint>
               <multi/>
             </properties>
           </leafNode>
@@ -793,39 +773,42 @@
                     <children>
                       <leafNode name="delay">
                         <properties>
-                          <help>Delay (msec) from first change received till SPF calculation</help>
+                          <help>Delay from first change received till SPF calculation (default: 200)</help>
                           <valueHelp>
                             <format>u32:0-600000</format>
-                            <description>Delay in msec (default 200)</description>
+                            <description>Delay in milliseconds</description>
                           </valueHelp>
                           <constraint>
                             <validator name="numeric" argument="--range 0-600000"/>
                           </constraint>
                         </properties>
+                        <defaultValue>200</defaultValue>
                       </leafNode>
                       <leafNode name="initial-holdtime">
                         <properties>
-                          <help>Initial hold time(msec) between consecutive SPF calculations</help>
+                          <help>Initial hold time between consecutive SPF calculations (default: 1000)</help>
                           <valueHelp>
                             <format>u32:0-600000</format>
-                            <description>Initial hold time in msec (default 1000)</description>
+                            <description>Initial hold time in milliseconds</description>
                           </valueHelp>
                           <constraint>
                             <validator name="numeric" argument="--range 0-600000"/>
                           </constraint>
                         </properties>
+                        <defaultValue>1000</defaultValue>
                       </leafNode>
                       <leafNode name="max-holdtime">
                         <properties>
-                          <help>Maximum hold time (msec)</help>
+                          <help>Maximum hold time (default: 10000)</help>
                           <valueHelp>
                             <format>u32:0-600000</format>
-                            <description>Max hold time in msec (default 10000)</description>
+                            <description>Max hold time in milliseconds</description>
                           </valueHelp>
                           <constraint>
                             <validator name="numeric" argument="--range 0-600000"/>
                           </constraint>
                         </properties>
+                        <defaultValue>10000</defaultValue>
                       </leafNode>
                     </children>
                   </node>
diff --git a/src/conf_mode/protocols_ospf.py b/src/conf_mode/protocols_ospf.py
old mode 100644
new mode 100755
index 73c244571..fc66a884c
--- a/src/conf_mode/protocols_ospf.py
+++ b/src/conf_mode/protocols_ospf.py
@@ -24,6 +24,7 @@ from vyos.template import render
 from vyos.template import render_to_string
 from vyos.util import call
 from vyos.util import dict_search
+from vyos.xml import defaults
 from vyos import ConfigError
 from vyos import frr
 from vyos import airbag
@@ -43,6 +44,30 @@ def get_config():
     conf = Config()
     base = ['protocols', 'ospf']
     ospf = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True)
+
+    # Bail out early if configuration tree does not exist
+    if not conf.exists(base):
+        return ospf
+
+    # We have gathered the dict representation of the CLI, but there are default
+    # options which we need to update into the dictionary retrived.
+    default_values = defaults(base)
+
+    # 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', ospf) is None:
+        del default_values['default_information']
+    if dict_search('area.area_type.nssa', ospf) is None:
+        del default_values['area']['area_type']['nssa']
+    for protocol in ['bgp', 'connected', 'kernel', 'rip', 'static']:
+        if dict_search(f'redistribute.{protocol}', ospf) is None:
+            del default_values['redistribute'][protocol]
+
+    ospf = dict_merge(default_values, ospf)
+
     return ospf
 
 def verify(ospf):
-- 
cgit v1.2.3