From d6ef0c54ad8c8f9f2c5f1811781dba6111201fe4 Mon Sep 17 00:00:00 2001
From: Cheeze_It <none@none.com>
Date: Sun, 19 Mar 2023 19:24:50 -0600
Subject: T5081: ISIS and OSPF syncronization with IGP-LDP sync

---
 data/templates/frr/isisd.frr.j2                    | 11 ++++++
 data/templates/frr/ospfd.frr.j2                    | 11 ++++++
 .../include/isis/protocol-common-config.xml.i      |  4 +-
 .../include/ldp-sync-interface.xml.i               | 22 +++++++++++
 .../include/ldp-sync-protocol.xml.i                | 21 +++++++++++
 .../include/ospf/protocol-common-config.xml.i      |  4 +-
 op-mode-definitions/include/isis-common.xml.i      | 26 ++++++++++++-
 op-mode-definitions/include/ospf-common.xml.i      | 26 ++++++++++++-
 smoketest/scripts/cli/test_protocols_isis.py       | 43 ++++++++++++++++++++++
 smoketest/scripts/cli/test_protocols_ospf.py       | 41 +++++++++++++++++++++
 10 files changed, 205 insertions(+), 4 deletions(-)
 create mode 100644 interface-definitions/include/ldp-sync-interface.xml.i
 create mode 100644 interface-definitions/include/ldp-sync-protocol.xml.i

diff --git a/data/templates/frr/isisd.frr.j2 b/data/templates/frr/isisd.frr.j2
index 8df1e9513..3c37e28b9 100644
--- a/data/templates/frr/isisd.frr.j2
+++ b/data/templates/frr/isisd.frr.j2
@@ -25,6 +25,12 @@ interface {{ iface }}
 {%         if iface_config.hello_padding is vyos_defined %}
  isis hello padding
 {%         endif %}
+{%         if iface_config.ldp_sync.disable is vyos_defined %}
+ no isis mpls ldp-sync
+{%         elif iface_config.ldp_sync.holddown is vyos_defined %}
+ isis mpls ldp-sync
+ isis mpls ldp-sync holddown {{ iface_config.ldp_sync.holddown }}
+{%         endif %}
 {%         if iface_config.metric is vyos_defined %}
  isis metric {{ iface_config.metric }}
 {%         endif %}
@@ -84,6 +90,11 @@ router isis VyOS {{ 'vrf ' + vrf if vrf is vyos_defined }}
 {% if max_lsp_lifetime is vyos_defined %}
  max-lsp-lifetime {{ max_lsp_lifetime }}
 {% endif %}
+{% if ldp_sync.holddown is vyos_defined %}
+ mpls ldp-sync holddown {{ ldp_sync.holddown }}
+{% elif ldp_sync is vyos_defined %}
+ mpls ldp-sync
+{% endif %}
 {% if spf_interval is vyos_defined %}
  spf-interval {{ spf_interval }}
 {% endif %}
diff --git a/data/templates/frr/ospfd.frr.j2 b/data/templates/frr/ospfd.frr.j2
index 8c4a81c57..3f97b7325 100644
--- a/data/templates/frr/ospfd.frr.j2
+++ b/data/templates/frr/ospfd.frr.j2
@@ -44,6 +44,12 @@ interface {{ iface }}
 {%         if iface_config.bfd.profile is vyos_defined %}
  ip ospf bfd profile {{ iface_config.bfd.profile }}
 {%         endif %}
+{%         if iface_config.ldp_sync.disable is vyos_defined %}
+ no ip ospf mpls ldp-sync
+{%         elif iface_config.ldp_sync.holddown is vyos_defined %}
+ ip ospf mpls ldp-sync
+ ip ospf mpls ldp-sync holddown {{ iface_config.ldp_sync.holddown }}
+{%         endif %}
 {%         if iface_config.mtu_ignore is vyos_defined %}
  ip ospf mtu-ignore
 {%         endif %}
@@ -133,6 +139,11 @@ router ospf {{ 'vrf ' ~ vrf if vrf is vyos_defined }}
 {% if maximum_paths is vyos_defined %}
  maximum-paths {{ maximum_paths }}
 {% endif %}
+{% if ldp_sync.holddown is vyos_defined %}
+ mpls ldp-sync holddown {{ ldp_sync.holddown }}
+{% elif ldp_sync is vyos_defined %}
+ mpls ldp-sync
+{% endif %}
 {% if distance.global is vyos_defined %}
  distance {{ distance.global }}
 {% endif %}
diff --git a/interface-definitions/include/isis/protocol-common-config.xml.i b/interface-definitions/include/isis/protocol-common-config.xml.i
index 0e6f19480..983a085ec 100644
--- a/interface-definitions/include/isis/protocol-common-config.xml.i
+++ b/interface-definitions/include/isis/protocol-common-config.xml.i
@@ -152,6 +152,7 @@
     </constraint>
   </properties>
 </leafNode>
+#include <include/ldp-sync-protocol.xml.i>
 <leafNode name="net">
   <properties>
     <help>A Network Entity Title for this process (ISO only)</help>
@@ -172,7 +173,7 @@
 </leafNode>
 <node name="traffic-engineering">
   <properties>
-    <help>Show IS-IS neighbor adjacencies</help>
+    <help>IS-IS traffic engineering extensions</help>
   </properties>
   <children>
     <leafNode name="enable">
@@ -631,6 +632,7 @@
       </properties>
     </leafNode>
     #include <include/isis/metric.xml.i>
+    #include <include/ldp-sync-interface.xml.i>
     <node name="network">
       <properties>
         <help>Set network type</help>
diff --git a/interface-definitions/include/ldp-sync-interface.xml.i b/interface-definitions/include/ldp-sync-interface.xml.i
new file mode 100644
index 000000000..b24831bbe
--- /dev/null
+++ b/interface-definitions/include/ldp-sync-interface.xml.i
@@ -0,0 +1,22 @@
+<!-- include start from ldp-igp-sync.xml.i -->
+<node name="ldp-sync">
+  <properties>
+    <help>LDP-IGP synchronization configuration for interface</help>
+  </properties>
+  <children>
+    #include <include/generic-disable-node.xml.i>
+    <leafNode name="holddown">
+      <properties>
+        <help>Hold down timer for LDP-IGP cost restoration</help>
+        <valueHelp>
+          <format>u32:0-10000</format>
+          <description>Time to wait in seconds for LDP-IGP synchronization to occur before restoring interface cost</description>
+        </valueHelp>
+        <constraint>
+          <validator name="numeric" argument="--range 0-10000"/>
+        </constraint>
+      </properties>
+    </leafNode>
+  </children>
+</node>
+<!-- include end -->
diff --git a/interface-definitions/include/ldp-sync-protocol.xml.i b/interface-definitions/include/ldp-sync-protocol.xml.i
new file mode 100644
index 000000000..c82c811f6
--- /dev/null
+++ b/interface-definitions/include/ldp-sync-protocol.xml.i
@@ -0,0 +1,21 @@
+<!-- include start from ldp-igp-sync.xml.i -->
+<node name="ldp-sync">
+  <properties>
+    <help>Protocol wide LDP-IGP synchronization configuration</help>
+  </properties>
+  <children>
+    <leafNode name="holddown">
+      <properties>
+        <help>Protocol wide hold down timer for LDP-IGP cost restoration</help>
+        <valueHelp>
+          <format>u32:0-10000</format>
+          <description>Time to wait in seconds for LDP-IGP synchronization to occur before restoring interface cost</description>
+        </valueHelp>
+        <constraint>
+          <validator name="numeric" argument="--range 0-10000"/>
+        </constraint>
+      </properties>
+    </leafNode>
+  </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 25b54b181..c2a910710 100644
--- a/interface-definitions/include/ospf/protocol-common-config.xml.i
+++ b/interface-definitions/include/ospf/protocol-common-config.xml.i
@@ -331,6 +331,7 @@
     </constraint>
   </properties>
 </leafNode>
+#include <include/ldp-sync-protocol.xml.i>
 <node name="distance">
   <properties>
     <help>Administrative distance</help>
@@ -385,6 +386,7 @@
     #include <include/ospf/authentication.xml.i>
     #include <include/ospf/intervals.xml.i>
     #include <include/ospf/interface-common.xml.i>
+    #include <include/ldp-sync-interface.xml.i>
     <leafNode name="bandwidth">
       <properties>
         <help>Interface bandwidth (Mbit/s)</help>
@@ -875,4 +877,4 @@
     </node>
   </children>
 </node>
-<!-- include end -->
+<!-- include end -->
\ No newline at end of file
diff --git a/op-mode-definitions/include/isis-common.xml.i b/op-mode-definitions/include/isis-common.xml.i
index 95a171515..7b4d31029 100644
--- a/op-mode-definitions/include/isis-common.xml.i
+++ b/op-mode-definitions/include/isis-common.xml.i
@@ -54,6 +54,30 @@
   </properties>
   <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
 </tagNode>
+<node name="mpls">
+  <properties>
+    <help>Show IS-IS MPLS specific information</help>
+  </properties>
+  <children>
+    <node name="ldp-sync">
+      <properties>
+        <help>Show IS-IS LDP-IGP synchronization information</help>
+      </properties>
+      <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+      <children>
+        <tagNode name="interface">
+          <properties>
+            <help>Show specific IS-IS LDP-IGP synchronization for an interface</help>
+            <completionHelp>
+              <script>${vyos_completion_dir}/list_interfaces</script>
+            </completionHelp>
+          </properties>
+          <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+        </tagNode>
+      </children>
+    </node>
+  </children>
+</node>
 <node name="mpls-te">
   <properties>
     <help>Show IS-IS MPLS traffic engineering information</help>
@@ -176,4 +200,4 @@
   </children>
   <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
 </node>
-<!-- included end -->
+<!-- included end -->
\ No newline at end of file
diff --git a/op-mode-definitions/include/ospf-common.xml.i b/op-mode-definitions/include/ospf-common.xml.i
index 098254f4e..7d9e541cf 100644
--- a/op-mode-definitions/include/ospf-common.xml.i
+++ b/op-mode-definitions/include/ospf-common.xml.i
@@ -517,6 +517,30 @@
   </properties>
   <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
 </tagNode>
+<node name="mpls">
+  <properties>
+    <help>Show OSPF MPLS specific information</help>
+  </properties>
+  <children>
+    <node name="ldp-sync">
+      <properties>
+        <help>Show OSPF LDP-IGP synchronization information</help>
+      </properties>
+      <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+      <children>
+        <tagNode name="interface">
+          <properties>
+            <help>Show specific OSPF LDP-IGP synchronization for an interface</help>
+            <completionHelp>
+              <script>${vyos_completion_dir}/list_interfaces</script>
+            </completionHelp>
+          </properties>
+          <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+        </tagNode>
+      </children>
+    </node>
+  </children>
+</node>
 <node name="neighbor">
   <properties>
     <help>Show IPv4 OSPF neighbor information</help>
@@ -547,4 +571,4 @@
   </properties>
   <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
 </leafNode>
-<!-- included end -->
+<!-- included end -->
\ No newline at end of file
diff --git a/smoketest/scripts/cli/test_protocols_isis.py b/smoketest/scripts/cli/test_protocols_isis.py
index d11d80a1f..61e29c449 100755
--- a/smoketest/scripts/cli/test_protocols_isis.py
+++ b/smoketest/scripts/cli/test_protocols_isis.py
@@ -308,5 +308,48 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase):
         self.assertIn(f' segment-routing prefix {prefix_three} absolute {prefix_three_value} explicit-null', tmp)
         self.assertIn(f' segment-routing prefix {prefix_four} absolute {prefix_four_value} no-php-flag', tmp)
 
+    def test_isis_08_ldp_sync(self):
+        holddown = "500"
+        interface = 'lo'
+
+        self.cli_set(base_path + ['net', net])
+        self.cli_set(base_path + ['interface', interface])
+        self.cli_set(base_path + ['ldp-sync', 'holddown', holddown])
+        
+        # Commit main ISIS changes
+        self.cli_commit()
+        
+        # Verify main ISIS changes
+        tmp = self.getFRRconfig(f'router isis {domain}', daemon='isisd')
+        self.assertIn(f' net {net}', tmp)
+        self.assertIn(f' mpls ldp-sync', tmp)
+        self.assertIn(f' mpls ldp-sync holddown {holddown}', tmp)
+        
+        for interface in self._interfaces:
+            self.cli_set(base_path + ['interface', interface, 'ldp-sync', 'holddown', holddown])
+
+            # Commit interface changes for holddown
+            self.cli_commit()
+
+            # Verify interface changes for holddown
+            tmp = self.getFRRconfig(f'interface {interface}', daemon='isisd')
+            self.assertIn(f'interface {interface}', tmp)
+            self.assertIn(f' ip router isis {domain}', tmp)
+            self.assertIn(f' ipv6 router isis {domain}', tmp)
+            self.assertIn(f' isis mpls ldp-sync holddown {holddown}', tmp)
+            
+        for interface in self._interfaces:
+            self.cli_set(base_path + ['interface', interface, 'ldp-sync', 'disable'])
+            
+            # Commit interface changes for disable
+            self.cli_commit()
+            
+            # Verify interface changes for disable
+            tmp = self.getFRRconfig(f'interface {interface}', daemon='isisd')
+            self.assertIn(f'interface {interface}', tmp)
+            self.assertIn(f' ip router isis {domain}', tmp)
+            self.assertIn(f' ipv6 router isis {domain}', tmp)
+            self.assertIn(f' no isis mpls ldp-sync', tmp)
+
 if __name__ == '__main__':
     unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_protocols_ospf.py b/smoketest/scripts/cli/test_protocols_ospf.py
index 581959b15..d4c85f2b2 100755
--- a/smoketest/scripts/cli/test_protocols_ospf.py
+++ b/smoketest/scripts/cli/test_protocols_ospf.py
@@ -434,6 +434,47 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase):
         self.assertIn(f' segment-routing prefix {prefix_one} index {prefix_one_value} explicit-null', frrconfig)
         self.assertIn(f' segment-routing prefix {prefix_two} index {prefix_two_value} no-php-flag', frrconfig)
 
+    def test_ospf_15_ldp_sync(self):
+        holddown = "500"
+        interface = 'lo'
+        interfaces = Section.interfaces('ethernet')
+
+        self.cli_set(base_path + ['interface', interface])
+        self.cli_set(base_path + ['ldp-sync', 'holddown', holddown])
+        
+        # Commit main OSPF changes
+        self.cli_commit()
+        
+        # Verify main OSPF changes
+        frrconfig = self.getFRRconfig('router ospf')
+        self.assertIn(f'router ospf', frrconfig)
+        self.assertIn(f' timers throttle spf 200 1000 10000', frrconfig)
+        self.assertIn(f' mpls ldp-sync holddown {holddown}', frrconfig)
+        
+        for interface in interfaces:
+            self.cli_set(base_path + ['interface', interface, 'ldp-sync', 'holddown', holddown])
+
+            # Commit interface changes for holddown
+            self.cli_commit()
+
+            # Verify interface changes for holddown
+            config = self.getFRRconfig(f'interface {interface}')
+            self.assertIn(f'interface {interface}', config)
+            self.assertIn(f' ip ospf dead-interval 40', config)
+            self.assertIn(f' ip ospf mpls ldp-sync', config)
+            self.assertIn(f' ip ospf mpls ldp-sync holddown {holddown}', config)
+            
+        for interface in interfaces:
+            self.cli_set(base_path + ['interface', interface, 'ldp-sync', 'disable'])
+            
+            # Commit interface changes for disable
+            self.cli_commit()
+            
+            # Verify interface changes for disable
+            config = self.getFRRconfig(f'interface {interface}')
+            self.assertIn(f'interface {interface}', config)
+            self.assertIn(f' ip ospf dead-interval 40', config)
+            self.assertIn(f' no ip ospf mpls ldp-sync', config)
 
 if __name__ == '__main__':
     unittest.main(verbosity=2)
-- 
cgit v1.2.3