summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Breunig <christian@breunig.cc>2026-03-04 20:27:21 +0100
committerGitHub <noreply@github.com>2026-03-04 20:27:21 +0100
commitddaae274187916b3a7932372ee8944ddce8c5423 (patch)
tree3d06206bb683bf87a57b64a84e33f5c707135521
parentd69bff60c25781ffe52ba744ba5b5d7e8c6ddeea (diff)
parentf831da31dd0c02238a8e045087e1ab53173cb05f (diff)
downloadvyos-1x-ddaae274187916b3a7932372ee8944ddce8c5423.tar.gz
vyos-1x-ddaae274187916b3a7932372ee8944ddce8c5423.zip
Merge pull request #4962 from jvoss/srv6_isis
isis: T6978: add IS-IS SRv6 node-msd configuration
-rw-r--r--data/templates/frr/isisd.frr.j223
-rw-r--r--interface-definitions/include/isis/protocol-common-config.xml.i107
-rw-r--r--op-mode-definitions/include/isis-common.xml.i15
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_isis.py46
-rw-r--r--src/completion/list_srv6_locators.sh21
-rwxr-xr-xsrc/conf_mode/protocols_isis.py7
6 files changed, 198 insertions, 21 deletions
diff --git a/data/templates/frr/isisd.frr.j2 b/data/templates/frr/isisd.frr.j2
index 8df8e90d1..8128c6711 100644
--- a/data/templates/frr/isisd.frr.j2
+++ b/data/templates/frr/isisd.frr.j2
@@ -152,9 +152,30 @@ advertise-passive-only
{% if segment_routing.maximum_label_depth is vyos_defined %}
segment-routing node-msd {{ segment_routing.maximum_label_depth }}
{% endif %}
-{% if segment_routing.srv6.locator is vyos_defined %}
+{% if segment_routing.srv6 is vyos_defined %}
segment-routing srv6
+{% if segment_routing.srv6.locator is vyos_defined %}
locator {{ segment_routing.srv6.locator }}
+{% endif %}
+{% if segment_routing.srv6.node_msd is vyos_defined %}
+ node-msd
+{% if segment_routing.srv6.node_msd.max_end_d is vyos_defined %}
+ max-end-d {{ segment_routing.srv6.node_msd.max_end_d }}
+{% endif %}
+{% if segment_routing.srv6.node_msd.max_end_pop is vyos_defined %}
+ max-end-pop {{ segment_routing.srv6.node_msd.max_end_pop }}
+{% endif %}
+{% if segment_routing.srv6.node_msd.max_h_encaps is vyos_defined %}
+ max-h-encaps {{ segment_routing.srv6.node_msd.max_h_encaps }}
+{% endif %}
+{% if segment_routing.srv6.node_msd.max_segs_left is vyos_defined %}
+ max-segs-left {{ segment_routing.srv6.node_msd.max_segs_left }}
+{% endif %}
+ exit
+{% endif %}
+{% if segment_routing.srv6.interface is vyos_defined %}
+ interface {{ segment_routing.srv6.interface }}
+{% endif %}
exit
{% endif %}
{% if segment_routing.global_block is vyos_defined %}
diff --git a/interface-definitions/include/isis/protocol-common-config.xml.i b/interface-definitions/include/isis/protocol-common-config.xml.i
index 1b5b41ad2..6a7388c99 100644
--- a/interface-definitions/include/isis/protocol-common-config.xml.i
+++ b/interface-definitions/include/isis/protocol-common-config.xml.i
@@ -298,25 +298,6 @@
#include <include/segment-routing-label-value.xml.i>
</children>
</node>
- <node name="srv6">
- <properties>
- <help>Segment-Routing SRv6 configuration</help>
- </properties>
- <children>
- <leafNode name="locator">
- <properties>
- <help>Specify SRv6 locator</help>
- <valueHelp>
- <format>txt</format>
- <description>SRv6 locator name</description>
- </valueHelp>
- <constraint>
- #include <include/constraint/alpha-numeric-hyphen-underscore.xml.i>
- </constraint>
- </properties>
- </leafNode>
- </children>
- </node>
<leafNode name="maximum-label-depth">
<properties>
<help>Maximum MPLS labels allowed for this router</help>
@@ -410,6 +391,94 @@
</node>
</children>
</tagNode>
+ <node name="srv6">
+ <properties>
+ <help>Segment-Routing over IPv6 (SRv6) configuration</help>
+ </properties>
+ <children>
+ <leafNode name="locator">
+ <properties>
+ <help>Specify SRv6 locator</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>SRv6 locator name</description>
+ </valueHelp>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_srv6_locators.sh</script>
+ </completionHelp>
+ <constraint>
+ #include <include/constraint/alpha-numeric-hyphen-underscore.xml.i>
+ </constraint>
+ </properties>
+ </leafNode>
+ <node name="node-msd">
+ <properties>
+ <help>SRv6 Maximum Segment ID (SID) Depth (MSD)</help>
+ </properties>
+ <children>
+ <leafNode name="max-end-d">
+ <properties>
+ <help>Maximum Segment Identifier for End-of-Data</help>
+ <valueHelp>
+ <format>u32:0-255</format>
+ <description>Maximum End D MSD</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-255"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="max-end-pop">
+ <properties>
+ <help>Maximum number of SIDs in Segment-Routing Header (SRH) for segment pop</help>
+ <valueHelp>
+ <format>u32:0-255</format>
+ <description>Maximum End Pop MSD</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-255"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="max-h-encaps">
+ <properties>
+ <help>Maximum Headend Encapsulation in MSD</help>
+ <valueHelp>
+ <format>u32:0-255</format>
+ <description>Maximum Headend encaps in MSD</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-255"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="max-segs-left">
+ <properties>
+ <help>Maximum Segments left in MSD</help>
+ <valueHelp>
+ <format>u32:0-255</format>
+ <description>Maximum Segments Left</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-255"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ <leafNode name="interface">
+ <properties>
+ <help>Interface for Segment-Routing over IPv6 (SRv6)</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_interfaces</script>
+ </completionHelp>
+ <constraint>
+ #include <include/constraint/interface-name.xml.i>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
</children>
</node>
<node name="redistribute">
diff --git a/op-mode-definitions/include/isis-common.xml.i b/op-mode-definitions/include/isis-common.xml.i
index cda46736d..17132b857 100644
--- a/op-mode-definitions/include/isis-common.xml.i
+++ b/op-mode-definitions/include/isis-common.xml.i
@@ -143,7 +143,7 @@
</node>
<node name="segment-routing">
<properties>
- <help>Show IS-IS Segment-Routing (SPRING) information</help>
+ <help>Show IS-IS Segment Routing (SPRING) information</help>
</properties>
<children>
<leafNode name="node">
@@ -152,6 +152,19 @@
</properties>
<command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
</leafNode>
+ <node name="srv6">
+ <properties>
+ <help>Segment Routing over IPv6 (SRv6)</help>
+ </properties>
+ <children>
+ <leafNode name="node">
+ <properties>
+ <help>SRv6 node information</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ </children>
+ </node>
</children>
</node>
<leafNode name="spf-delay-ietf">
diff --git a/smoketest/scripts/cli/test_protocols_isis.py b/smoketest/scripts/cli/test_protocols_isis.py
index 58ba77ea0..5d61f4ce0 100755
--- a/smoketest/scripts/cli/test_protocols_isis.py
+++ b/smoketest/scripts/cli/test_protocols_isis.py
@@ -420,10 +420,15 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase):
def test_isis_11_srv6(self):
locator = "TEST"
interface = 'lo'
+ srv6_iface = 'dum6'
+
+ # The dummy interface used to install SRv6 SIDs in the Linux data plane
+ self.cli_set(['interfaces', 'dummy', srv6_iface])
self.cli_set(base_path + ['net', net])
self.cli_set(base_path + ['interface', interface])
self.cli_set(base_path + ['segment-routing', 'srv6', 'locator', locator])
+ self.cli_set(base_path + ['segment-routing', 'srv6', 'interface', srv6_iface])
# Commit main ISIS changes
self.cli_commit()
@@ -476,5 +481,46 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase):
tmp = self.getFRRconfig(f'interface {interface}', stop_section='^exit')
self.assertIn(f' isis fast-reroute ti-lfa level-1 node-protection link-fallback', tmp)
+ def test_isis_14_segment_routing_srv6_advanced(self):
+ # Configure system SRv6 locator and interface
+ locator = 'TEST'
+ sr_base = ['protocols', 'segment-routing']
+ self.cli_set(sr_base + ['srv6', 'locator', 'TEST', 'prefix', '2001:db8::/64'])
+ self.cli_set(sr_base + ['interface', 'lo'])
+
+ # The dummy interface used to install SRv6 SIDs in the Linux data plane
+ dum_iface = 'dum6'
+ self.cli_set(['interfaces', 'dummy', dum_iface])
+
+ # Set a basic IS-IS config
+ self.cli_set(base_path + ['net', net])
+ self.cli_set(base_path + ['interface', 'lo'])
+
+ # Configure IS-IS SRv6
+ srv6_base_path = base_path + ['segment-routing', 'srv6']
+ self.cli_set(srv6_base_path + ['locator', locator])
+ self.cli_set(srv6_base_path + ['interface', dum_iface])
+ self.cli_commit()
+
+ tmp = self.getFRRconfig(f'router isis {domain}', stop_section='^exit')
+ self.assertIn(' segment-routing srv6', tmp)
+ self.assertIn(f' locator {locator}', tmp)
+ self.assertIn(f' interface {dum_iface}', tmp)
+
+ # Test node-msd configuration
+ self.cli_set(srv6_base_path + ['node-msd', 'max-end-d', '40'])
+ self.cli_set(srv6_base_path + ['node-msd', 'max-end-pop', '50'])
+ self.cli_set(srv6_base_path + ['node-msd', 'max-h-encaps', '60'])
+ self.cli_set(srv6_base_path + ['node-msd', 'max-segs-left', '70'])
+ self.cli_commit()
+
+ tmp = self.getFRRconfig(f'router isis {domain}', stop_section='^exit')
+ self.assertIn(' node-msd', tmp)
+ self.assertIn(' max-end-d 40', tmp)
+ self.assertIn(' max-end-pop 50', tmp)
+ self.assertIn(' max-h-encaps 60', tmp)
+ self.assertIn(' max-segs-left 70', tmp)
+
+
if __name__ == '__main__':
unittest.main(verbosity=2, failfast=VyOSUnitTestSHIM.TestCase.debug_on())
diff --git a/src/completion/list_srv6_locators.sh b/src/completion/list_srv6_locators.sh
new file mode 100644
index 000000000..03ca499d8
--- /dev/null
+++ b/src/completion/list_srv6_locators.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+#
+# Copyright (C) VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# This script is completion helper to list all configured SRv6 locators that
+# are visible to FRR
+
+seg6LocatorsJson=$(vtysh -c 'show segment-routing srv6 locator json')
+echo "$(echo "$seg6LocatorsJson" | jq -r '[.locators[].name][]')"
diff --git a/src/conf_mode/protocols_isis.py b/src/conf_mode/protocols_isis.py
index 151c5450a..3d172087e 100755
--- a/src/conf_mode/protocols_isis.py
+++ b/src/conf_mode/protocols_isis.py
@@ -261,6 +261,13 @@ def verify(config_dict):
f'max-lsp-lifetime must be greater or equal to lsp-refresh-interval + 300'
)
+ # Check IS-IS SRv6
+ if dict_search('segment_routing.srv6', isis):
+ # The interface used to install SRv6 SIDs in the Linux data plane.
+ # https://docs.frrouting.org/en/stable-10.2/isisd.html#clicmd-interface-NAME
+ if not dict_search('segment_routing.srv6.interface', isis):
+ raise ConfigError('Missing interface used for installing SRv6 SIDs')
+
return None
def generate(config_dict):