From c33e993f187f20407f2258ca08e0447c78aba885 Mon Sep 17 00:00:00 2001 From: Jonathan Voss Date: Sun, 18 Oct 2026 15:09:02 +0000 Subject: isis: T9485: only enable SR-MPLS when MPLS segment-routing options are set "segment-routing on" was rendered whenever the "protocols isis segment-routing" node existed. In FRR that statement enables SR-MPLS only, so an SRv6-only configuration also turned on SR-MPLS: isisd allocated adjacency labels and zebra logged LSP install failures on systems without MPLS label space. "segment-routing on" is now rendered only if global-block, local-block, prefix or maximum-label-depth is configured. SRv6-only configurations no longer enable SR-MPLS; SRv6 rendering is unchanged. --- data/templates/frr/isisd.frr.j2 | 4 +++ smoketest/scripts/cli/test_protocols_isis.py | 43 ++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/data/templates/frr/isisd.frr.j2 b/data/templates/frr/isisd.frr.j2 index b385e896b..f94085d33 100644 --- a/data/templates/frr/isisd.frr.j2 +++ b/data/templates/frr/isisd.frr.j2 @@ -202,7 +202,11 @@ advertise-passive-only {% endif %} {% endfor %} {% endif %} +{# "segment-routing on" enables SR-MPLS only, SRv6 does not need it #} +{% set sr_mpls_options = ['global_block', 'local_block', 'maximum_label_depth', 'prefix'] %} +{% if segment_routing | select('in', sr_mpls_options) | list %} segment-routing on +{% endif %} {% endif %} {% if spf_delay_ietf.init_delay is vyos_defined %} spf-delay-ietf init-delay {{ spf_delay_ietf.init_delay }} short-delay {{ spf_delay_ietf.short_delay }} long-delay {{ spf_delay_ietf.long_delay }} holddown {{ spf_delay_ietf.holddown }} time-to-learn {{ spf_delay_ietf.time_to_learn }} diff --git a/smoketest/scripts/cli/test_protocols_isis.py b/smoketest/scripts/cli/test_protocols_isis.py index 8296e2732..d190c23d4 100755 --- a/smoketest/scripts/cli/test_protocols_isis.py +++ b/smoketest/scripts/cli/test_protocols_isis.py @@ -462,6 +462,8 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase): self.assertIn(f' net {net}', tmp) self.assertIn(f' segment-routing srv6', tmp) self.assertIn(f' locator {locator}', tmp) + # SRv6 alone must not enable SR-MPLS + self.assertNotIn(' segment-routing on', tmp) # Commit for isis self.cli_commit() @@ -530,6 +532,8 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase): self.assertIn(' segment-routing srv6', tmp) self.assertIn(f' locator {locator}', tmp) self.assertIn(f' interface {dum_iface}', tmp) + # SRv6 alone must not enable SR-MPLS + self.assertNotIn(' segment-routing on', tmp) # Test node-msd configuration self.cli_set(srv6_base_path + ['node-msd', 'max-end-d', '40']) @@ -544,6 +548,7 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase): self.assertIn(' max-end-pop 50', tmp) self.assertIn(' max-h-encaps 60', tmp) self.assertIn(' max-segs-left 70', tmp) + self.assertNotIn(' segment-routing on', tmp) def test_isis_15_distribute_link_state(self): interface = 'lo' @@ -603,6 +608,44 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase): self.assertIn(f' mpls-te router-address {te_address}', tmp) self.assertIn(' mpls-te export', tmp) + def test_isis_16_segment_routing_srv6_and_mpls(self): + locator = 'TEST' + msd = '5' + sr_base = ['protocols', 'segment-routing'] + self.cli_set(sr_base + ['srv6', 'locator', locator, '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]) + + self.cli_set(base_path + ['net', net]) + self.cli_set(base_path + ['interface', 'lo']) + + # SRv6 and SR-MPLS side by side + sr_path = base_path + ['segment-routing'] + self.cli_set(sr_path + ['srv6', 'locator', locator]) + self.cli_set(sr_path + ['srv6', 'interface', dum_iface]) + self.cli_set(sr_path + ['maximum-label-depth', msd]) + self.cli_commit() + + tmp = self.getFRRconfig(f'router isis {domain}', stop_section='^exit') + self.assertIn(' segment-routing on', tmp) + self.assertIn(f' segment-routing node-msd {msd}', tmp) + self.assertIn(' segment-routing srv6', tmp) + self.assertIn(f' locator {locator}', tmp) + self.assertIn(f' interface {dum_iface}', tmp) + + # Removing the only SR-MPLS option must disable SR-MPLS again. Not + # global-block: FRR rejects the "no" form frr-reload.py derives for it + self.cli_delete(sr_path + ['maximum-label-depth']) + self.cli_commit() + + tmp = self.getFRRconfig(f'router isis {domain}', stop_section='^exit') + self.assertNotIn(' segment-routing on', tmp) + self.assertNotIn(' segment-routing node-msd', tmp) + self.assertIn(' segment-routing srv6', tmp) + if __name__ == '__main__': unittest.main(verbosity=2, failfast=VyOSUnitTestSHIM.TestCase.debug_on()) -- cgit v1.2.3