summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCheeze_It <none@none.com>2023-08-31 12:16:29 -0600
committerMergify <37929162+mergify[bot]@users.noreply.github.com>2024-01-10 07:27:04 +0000
commit2d778c4cb468352c6ff4ea9d984951f6bb12586c (patch)
tree71fef61ab2336e55ff062f8bedf441c66c4897e1
parenta9ed12de93425a9e9637a61e5b7f17ae01575242 (diff)
downloadvyos-1x-2d778c4cb468352c6ff4ea9d984951f6bb12586c.tar.gz
vyos-1x-2d778c4cb468352c6ff4ea9d984951f6bb12586c.zip
T5530: isis: Adding loop free alternate feature
(cherry picked from commit 7a2b70bd73c8579a885348b93b8addfb20fb006c)
-rw-r--r--data/templates/frr/isisd.frr.j242
-rw-r--r--interface-definitions/include/isis/level-1-2-leaf.xml.i13
-rw-r--r--interface-definitions/include/isis/lfa-local.xml.i128
-rw-r--r--interface-definitions/include/isis/lfa-protocol.xml.i11
-rw-r--r--interface-definitions/include/isis/lfa-remote.xml.i28
-rw-r--r--interface-definitions/include/isis/protocol-common-config.xml.i8
-rw-r--r--op-mode-definitions/include/isis-common.xml.i27
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_isis.py62
-rwxr-xr-xsrc/conf_mode/protocols_isis.py37
9 files changed, 353 insertions, 3 deletions
diff --git a/data/templates/frr/isisd.frr.j2 b/data/templates/frr/isisd.frr.j2
index dbb8c7305..1e1cc3c27 100644
--- a/data/templates/frr/isisd.frr.j2
+++ b/data/templates/frr/isisd.frr.j2
@@ -165,6 +165,48 @@ advertise-passive-only
{% endfor %}
{% endfor %}
{% endif %}
+{% if fast_reroute.lfa is vyos_defined %}
+{% if fast_reroute.lfa.local is vyos_defined %}
+{% if fast_reroute.lfa.local.load_sharing.disable.level_1 is vyos_defined %}
+ fast-reroute load-sharing disable level-1
+{% elif fast_reroute.lfa.local.load_sharing.disable.level_2 is vyos_defined %}
+ fast-reroute load-sharing disable level-2
+{% elif fast_reroute.lfa.local.load_sharing.disable is vyos_defined %}
+ fast-reroute load-sharing disable
+{% endif %}
+{% if fast_reroute.lfa.local.priority_limit is vyos_defined %}
+{% for priority, priority_limit_options in fast_reroute.lfa.local.priority_limit.items() %}
+{% for level in priority_limit_options %}
+ fast-reroute priority-limit {{ priority }} {{ level | replace('_', '-') }}
+{% endfor %}
+{% endfor %}
+{% endif %}
+{% if fast_reroute.lfa.local.tiebreaker is vyos_defined %}
+{% for tiebreaker, tiebreaker_options in fast_reroute.lfa.local.tiebreaker.items() %}
+{% for index, index_options in tiebreaker_options.items() %}
+{% for index_value, index_value_options in index_options.items() %}
+{% for level in index_value_options %}
+ fast-reroute lfa tiebreaker {{ tiebreaker | replace('_', '-') }} index {{ index_value }} {{ level | replace('_', '-') }}
+{% endfor %}
+{% endfor %}
+{% endfor %}
+{% endfor %}
+{% endif %}
+{% endif %}
+{% if fast_reroute.lfa.remote.prefix_list is vyos_defined %}
+{% for prefix_list, prefix_list_options in fast_reroute.lfa.remote.prefix_list.items() %}
+{% if prefix_list_options.level_1 is vyos_defined %}
+fast-reroute remote-lfa prefix-list {{ prefix_list }} level-1
+{% endif %}
+{% if prefix_list_options.level_2 is vyos_defined %}
+fast-reroute remote-lfa prefix-list {{ prefix_list }} level-2
+{% endif %}
+{% if prefix_list is vyos_defined and prefix_list_options.level_1 is not vyos_defined and prefix_list_options.level_2 is not vyos_defined %}
+fast-reroute remote-lfa prefix-list {{ prefix_list }}
+{% endif %}
+{% endfor %}
+{% endif %}
+{% endif %}
{% if redistribute.ipv4 is vyos_defined %}
{% for protocol, protocol_options in redistribute.ipv4.items() %}
{% for level, level_config in protocol_options.items() %}
diff --git a/interface-definitions/include/isis/level-1-2-leaf.xml.i b/interface-definitions/include/isis/level-1-2-leaf.xml.i
new file mode 100644
index 000000000..3703da1ed
--- /dev/null
+++ b/interface-definitions/include/isis/level-1-2-leaf.xml.i
@@ -0,0 +1,13 @@
+<!-- include start from isis/level-1-2-leaf.xml.i -->
+<leafNode name="level-1">
+ <properties>
+ <help>Match on IS-IS level-1 routes</help>
+ <valueless/>
+ </properties>
+</leafNode>
+<leafNode name="level-2">
+ <properties>
+ <help>Match on IS-IS level-2 routes</help>
+ <valueless/>
+ </properties>
+</leafNode> \ No newline at end of file
diff --git a/interface-definitions/include/isis/lfa-local.xml.i b/interface-definitions/include/isis/lfa-local.xml.i
new file mode 100644
index 000000000..c5bf6a3eb
--- /dev/null
+++ b/interface-definitions/include/isis/lfa-local.xml.i
@@ -0,0 +1,128 @@
+<!-- include start from isis/lfa-local.xml.i -->
+<node name="local">
+ <properties>
+ <help>Local loop free alternate options</help>
+ </properties>
+ <children>
+ <node name="load-sharing">
+ <properties>
+ <help>Load share prefixes across multiple backups</help>
+ </properties>
+ <children>
+ <node name="disable">
+ <properties>
+ <help>Disable load sharing</help>
+ </properties>
+ <children>
+ #include <include/isis/level-1-2-leaf.xml.i>
+ </children>
+ </node>
+ </children>
+ </node>
+ <node name="priority-limit">
+ <properties>
+ <help>Limit backup computation up to the prefix priority</help>
+ </properties>
+ <children>
+ <node name="medium">
+ <properties>
+ <help>Compute for critical, high, and medium priority prefixes</help>
+ </properties>
+ <children>
+ #include <include/isis/level-1-2-leaf.xml.i>
+ </children>
+ </node>
+ <node name="high">
+ <properties>
+ <help>Compute for critical, and high priority prefixes</help>
+ </properties>
+ <children>
+ #include <include/isis/level-1-2-leaf.xml.i>
+ </children>
+ </node>
+ <node name="critical">
+ <properties>
+ <help>Compute for critical priority prefixes only</help>
+ </properties>
+ <children>
+ #include <include/isis/level-1-2-leaf.xml.i>
+ </children>
+ </node>
+ </children>
+ </node>
+ <node name="tiebreaker">
+ <properties>
+ <help>Configure tiebreaker for multiple backups</help>
+ </properties>
+ <children>
+ <node name="downstream">
+ <properties>
+ <help>Prefer backup path via downstream node</help>
+ </properties>
+ <children>
+ <tagNode name="index">
+ <properties>
+ <help>Set preference order among tiebreakers</help>
+ <valueHelp>
+ <format>u32:1-255</format>
+ <description>The index integer value</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-255"/>
+ </constraint>
+ </properties>
+ <children>
+ #include <include/isis/level-1-2-leaf.xml.i>
+ </children>
+ </tagNode>
+ </children>
+ </node>
+ <node name="lowest-backup-metric">
+ <properties>
+ <help>Prefer backup path with lowest total metric</help>
+ </properties>
+ <children>
+ <tagNode name="index">
+ <properties>
+ <help>Set preference order among tiebreakers</help>
+ <valueHelp>
+ <format>u32:1-255</format>
+ <description>The index integer value</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-255"/>
+ </constraint>
+ </properties>
+ <children>
+ #include <include/isis/level-1-2-leaf.xml.i>
+ </children>
+ </tagNode>
+ </children>
+ </node>
+ <node name="node-protecting">
+ <properties>
+ <help>Prefer node protecting backup path</help>
+ </properties>
+ <children>
+ <tagNode name="index">
+ <properties>
+ <help>Set preference order among tiebreakers</help>
+ <valueHelp>
+ <format>u32:1-255</format>
+ <description>The index integer value</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-255"/>
+ </constraint>
+ </properties>
+ <children>
+ #include <include/isis/level-1-2-leaf.xml.i>
+ </children>
+ </tagNode>
+ </children>
+ </node>
+ </children>
+ </node>
+ </children>
+</node>
+<!-- include end --> \ No newline at end of file
diff --git a/interface-definitions/include/isis/lfa-protocol.xml.i b/interface-definitions/include/isis/lfa-protocol.xml.i
new file mode 100644
index 000000000..cfb1a6dc1
--- /dev/null
+++ b/interface-definitions/include/isis/lfa-protocol.xml.i
@@ -0,0 +1,11 @@
+<!-- include start from isis/lfa-protocol.xml.i -->
+<node name="lfa">
+ <properties>
+ <help>Loop free alternate functionality</help>
+ </properties>
+ <children>
+ #include <include/isis/lfa-remote.xml.i>
+ #include <include/isis/lfa-local.xml.i>
+ </children>
+</node>
+<!-- include end --> \ No newline at end of file
diff --git a/interface-definitions/include/isis/lfa-remote.xml.i b/interface-definitions/include/isis/lfa-remote.xml.i
new file mode 100644
index 000000000..8434e35bf
--- /dev/null
+++ b/interface-definitions/include/isis/lfa-remote.xml.i
@@ -0,0 +1,28 @@
+<!-- include start from isis/lfa-remote.xml.i -->
+<node name="remote">
+ <properties>
+ <help>Remote loop free alternate options</help>
+ </properties>
+ <children>
+ <tagNode name="prefix-list">
+ <properties>
+ <help>Filter PQ node router ID based on prefix list</help>
+ <completionHelp>
+ <path>policy prefix-list</path>
+ </completionHelp>
+ <valueHelp>
+ <format>txt</format>
+ <description>Name of IPv4/IPv6 prefix-list</description>
+ </valueHelp>
+ <constraint>
+ #include <include/constraint/alpha-numeric-hyphen-underscore.xml.i>
+ </constraint>
+ <constraintErrorMessage>Name of prefix-list can only contain alpha-numeric letters, hyphen and underscores</constraintErrorMessage>
+ </properties>
+ <children>
+ #include <include/isis/level-1-2-leaf.xml.i>
+ </children>
+ </tagNode>
+ </children>
+</node>
+<!-- include end --> \ No newline at end of file
diff --git a/interface-definitions/include/isis/protocol-common-config.xml.i b/interface-definitions/include/isis/protocol-common-config.xml.i
index 648f2b319..404f03cb5 100644
--- a/interface-definitions/include/isis/protocol-common-config.xml.i
+++ b/interface-definitions/include/isis/protocol-common-config.xml.i
@@ -165,6 +165,14 @@
</properties>
</leafNode>
#include <include/isis/ldp-sync-protocol.xml.i>
+<node name="fast-reroute">
+ <properties>
+ <help>IS-IS fast reroute configuration</help>
+ </properties>
+ <children>
+ #include <include/isis/lfa-protocol.xml.i>
+ </children>
+</node>
<leafNode name="net">
<properties>
<help>A Network Entity Title for this process (ISO only)</help>
diff --git a/op-mode-definitions/include/isis-common.xml.i b/op-mode-definitions/include/isis-common.xml.i
index e94d868e8..493a56633 100644
--- a/op-mode-definitions/include/isis-common.xml.i
+++ b/op-mode-definitions/include/isis-common.xml.i
@@ -17,6 +17,33 @@
</properties>
<command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
</tagNode>
+<node name="fast-reroute">
+ <properties>
+ <help>Show IS-IS fast reroute/loop free alternate (lfa) information</help>
+ </properties>
+ <children>
+ <node name="summary">
+ <properties>
+ <help>Show summary of fast reroute/loop free alternate (lfa) information</help>
+ </properties>
+ <children>
+ <leafNode name="level-1">
+ <properties>
+ <help>Show level-1 specific fast reroute/loop free alternate (lfa) information</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="level-2">
+ <properties>
+ <help>Show level-2 specific fast reroute/loop free alternate (lfa) information</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ </children>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </node>
+ </children>
+</node>
<leafNode name="hostname">
<properties>
<help>Show IS-IS dynamic hostname mapping</help>
diff --git a/smoketest/scripts/cli/test_protocols_isis.py b/smoketest/scripts/cli/test_protocols_isis.py
index c82836b72..94f4ec5c9 100755
--- a/smoketest/scripts/cli/test_protocols_isis.py
+++ b/smoketest/scripts/cli/test_protocols_isis.py
@@ -329,5 +329,65 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase):
self.assertIn(f' ipv6 router isis {domain}', tmp)
self.assertIn(f' no isis mpls ldp-sync', tmp)
+ def test_isis_09_lfa(self):
+ prefix_list = 'lfa-prefix-list-test-1'
+ prefix_list_address = '192.168.255.255/32'
+ interface = 'lo'
+
+ self.cli_set(base_path + ['net', net])
+ self.cli_set(base_path + ['interface', interface])
+ self.cli_set(['policy', 'prefix-list', prefix_list, 'rule', '1', 'action', 'permit'])
+ self.cli_set(['policy', 'prefix-list', prefix_list, 'rule', '1', 'prefix', prefix_list_address])
+
+ # Commit main ISIS changes
+ self.cli_commit()
+
+ # Add remote portion of LFA with prefix list with validation
+ for level in ['level-1', 'level-2']:
+ self.cli_set(base_path + ['fast-reroute', 'lfa', 'remote', 'prefix-list', prefix_list, level])
+ self.cli_commit()
+ tmp = self.getFRRconfig(f'router isis {domain}', daemon='isisd')
+ self.assertIn(f' net {net}', tmp)
+ self.assertIn(f' fast-reroute remote-lfa prefix-list {prefix_list} {level}', tmp)
+ self.cli_delete(base_path + ['fast-reroute'])
+ self.cli_commit()
+
+ # Add local portion of LFA load-sharing portion with validation
+ for level in ['level-1', 'level-2']:
+ self.cli_set(base_path + ['fast-reroute', 'lfa', 'local', 'load-sharing', 'disable', level])
+ self.cli_commit()
+ tmp = self.getFRRconfig(f'router isis {domain}', daemon='isisd')
+ self.assertIn(f' net {net}', tmp)
+ self.assertIn(f' fast-reroute load-sharing disable {level}', tmp)
+ self.cli_delete(base_path + ['fast-reroute'])
+ self.cli_commit()
+
+ # Add local portion of LFA priority-limit portion with validation
+ for priority in ['critical', 'high', 'medium']:
+ for level in ['level-1', 'level-2']:
+ self.cli_set(base_path + ['fast-reroute', 'lfa', 'local', 'priority-limit', priority, level])
+ self.cli_commit()
+ tmp = self.getFRRconfig(f'router isis {domain}', daemon='isisd')
+ self.assertIn(f' net {net}', tmp)
+ self.assertIn(f' fast-reroute priority-limit {priority} {level}', tmp)
+ self.cli_delete(base_path + ['fast-reroute'])
+ self.cli_commit()
+
+ # Add local portion of LFA tiebreaker portion with validation
+ index = '100'
+ for tiebreaker in ['downstream','lowest-backup-metric','node-protecting']:
+ for level in ['level-1', 'level-2']:
+ self.cli_set(base_path + ['fast-reroute', 'lfa', 'local', 'tiebreaker', tiebreaker, 'index', index, level])
+ self.cli_commit()
+ tmp = self.getFRRconfig(f'router isis {domain}', daemon='isisd')
+ self.assertIn(f' net {net}', tmp)
+ self.assertIn(f' fast-reroute lfa tiebreaker {tiebreaker} index {index} {level}', tmp)
+ self.cli_delete(base_path + ['fast-reroute'])
+ self.cli_commit()
+
+ # Clean up and remove prefix list
+ self.cli_delete(['policy', 'prefix-list', prefix_list])
+ self.cli_commit()
+
if __name__ == '__main__':
- unittest.main(verbosity=2)
+ unittest.main(verbosity=2) \ No newline at end of file
diff --git a/src/conf_mode/protocols_isis.py b/src/conf_mode/protocols_isis.py
index e00c58ee4..ce67ccff7 100755
--- a/src/conf_mode/protocols_isis.py
+++ b/src/conf_mode/protocols_isis.py
@@ -48,7 +48,8 @@ def get_config(config=None):
# eqivalent of the C foo ? 'a' : 'b' statement
base = vrf and ['vrf', 'name', vrf, 'protocols', 'isis'] or base_path
isis = conf.get_config_dict(base, key_mangling=('-', '_'),
- get_first_key=True)
+ get_first_key=True,
+ no_tag_node_value_mangle=True)
# Assign the name of our VRF context. This MUST be done before the return
# statement below, else on deletion we will delete the default instance
@@ -219,6 +220,38 @@ def verify(isis):
if ("explicit_null" in prefix_config['index']) and ("no_php_flag" in prefix_config['index']):
raise ConfigError(f'Segment routing prefix {prefix} cannot have both explicit-null '\
f'and no-php-flag configured at the same time.')
+
+ # Check for LFA tiebreaker index duplication
+ if dict_search('fast_reroute.lfa.local.tiebreaker', isis):
+ comparison_dictionary = {}
+ for item, item_options in isis['fast_reroute']['lfa']['local']['tiebreaker'].items():
+ for index, index_options in item_options.items():
+ for index_value, index_value_options in index_options.items():
+ if index_value not in comparison_dictionary.keys():
+ comparison_dictionary[index_value] = [item]
+ else:
+ comparison_dictionary[index_value].append(item)
+ for index, index_length in comparison_dictionary.items():
+ if int(len(index_length)) > 1:
+ raise ConfigError(f'LFA index {index} cannot have more than one tiebreaker configured.')
+
+ # Check for LFA priority-limit configured multiple times per level
+ if dict_search('fast_reroute.lfa.local.priority_limit', isis):
+ comparison_dictionary = {}
+ for priority, priority_options in isis['fast_reroute']['lfa']['local']['priority_limit'].items():
+ for level, level_options in priority_options.items():
+ if level not in comparison_dictionary.keys():
+ comparison_dictionary[level] = [priority]
+ else:
+ comparison_dictionary[level].append(priority)
+ for level, level_length in comparison_dictionary.items():
+ if int(len(level_length)) > 1:
+ raise ConfigError(f'LFA priority-limit on {level.replace("_", "-")} cannot have more than one priority configured.')
+
+ # Check for LFA remote prefix list configured with more than one list
+ if dict_search('fast_reroute.lfa.remote.prefix_list', isis):
+ if int(len(isis['fast_reroute']['lfa']['remote']['prefix_list'].items())) > 1:
+ raise ConfigError(f'LFA remote prefix-list has more than one configured. Cannot have more than one configured.')
return None
@@ -265,4 +298,4 @@ if __name__ == '__main__':
apply(c)
except ConfigError as e:
print(e)
- exit(1)
+ exit(1) \ No newline at end of file