diff --git a/dockers/docker-fpm-frr/docker_init.sh b/dockers/docker-fpm-frr/docker_init.sh index d8058e9b5d8d..db6d1c939326 100755 --- a/dockers/docker-fpm-frr/docker_init.sh +++ b/dockers/docker-fpm-frr/docker_init.sh @@ -15,6 +15,9 @@ CFGGEN_PARAMS=" \ FRR_VARS=$(sonic-cfggen $CFGGEN_PARAMS) CONFIG_TYPE=$(echo $FRR_VARS | jq -r '.docker_routing_config_mode') +CONFIG_DB_JSON=/etc/sonic/config_db.json +TMP_ISIS_COPP_CONFIG_DB_JSON=/tmp/isis_copp_config_db.json +ISIS_COPP_CONFIG_TEMPLATE=/usr/local/sonic/frrcfgd/isis_copp_trap_config.j2 update_default_gw() { @@ -41,6 +44,26 @@ update_default_gw() fi } +# Create and load requested configuration profile +load_config() +{ + if [ "$1" = "isis" ]; then + DEST_FILE=${TMP_ISIS_COPP_CONFIG_DB_JSON} + rm -f ${TMP_ISIS_COPP_CONFIG_DB_JSON} + sonic-cfggen -d -t ${ISIS_COPP_CONFIG_TEMPLATE} > ${DEST_FILE} + fi + + if [ -e ${DEST_FILE} ]; then + sonic-cfggen -j ${DEST_FILE} -w + config reload ${CONFIG_DB_JSON} -y -f + rm -f ${DEST_FILE} + return 0 + else + echo "Failed to generate and apply ${1} configuration profile." + fi + return 1 +} + write_default_zebra_config() { FILE_NAME=${1} @@ -55,6 +78,8 @@ if [[ ! -z "$NAMESPACE_ID" ]]; then update_default_gw 6 fi +load_config isis + if [ -z "$CONFIG_TYPE" ] || [ "$CONFIG_TYPE" == "separated" ]; then CFGGEN_PARAMS=" \ -d \ @@ -68,9 +93,10 @@ if [ -z "$CONFIG_TYPE" ] || [ "$CONFIG_TYPE" == "separated" ]; then CFGGEN_PARAMS="$CFGGEN_PARAMS \ -t /usr/local/sonic/frrcfgd/bfdd.conf.j2,/etc/frr/bfdd.conf \ -t /usr/local/sonic/frrcfgd/ospfd.conf.j2,/etc/frr/ospfd.conf \ + -t /usr/local/sonic/frrcfgd/isisd.conf.j2,/etc/frr/isisd.conf \ " else - rm -f /etc/frr/bfdd.conf /etc/frr/ospfd.conf + rm -f /etc/frr/bfdd.conf /etc/frr/ospfd.conf /etc/frr/isisd.conf fi sonic-cfggen $CFGGEN_PARAMS echo "no service integrated-vtysh-config" > /etc/frr/vtysh.conf @@ -92,7 +118,7 @@ elif [ "$CONFIG_TYPE" == "unified" ]; then sonic-cfggen $CFGGEN_PARAMS echo "service integrated-vtysh-config" > /etc/frr/vtysh.conf rm -f /etc/frr/bgpd.conf /etc/frr/zebra.conf /etc/frr/staticd.conf \ - /etc/frr/bfdd.conf /etc/frr/ospfd.conf /etc/frr/pimd.conf + /etc/frr/bfdd.conf /etc/frr/ospfd.conf /etc/frr/pimd.conf /etc/frr/isisd.conf fi chown -R frr:frr /etc/frr/ diff --git a/dockers/docker-fpm-frr/frr/supervisord/critical_processes.j2 b/dockers/docker-fpm-frr/frr/supervisord/critical_processes.j2 index 69f4e8e6931e..7f9be45fed67 100644 --- a/dockers/docker-fpm-frr/frr/supervisord/critical_processes.j2 +++ b/dockers/docker-fpm-frr/frr/supervisord/critical_processes.j2 @@ -3,6 +3,7 @@ program:staticd program:bgpd program:fpmsyncd {% if DEVICE_METADATA.localhost.frr_mgmt_framework_config is defined and DEVICE_METADATA.localhost.frr_mgmt_framework_config == "true" %} +program:isisd program:bfdd program:ospfd program:pimd diff --git a/dockers/docker-fpm-frr/frr/supervisord/supervisord.conf.j2 b/dockers/docker-fpm-frr/frr/supervisord/supervisord.conf.j2 index f6edc17a5529..3ac7bb4a7f77 100644 --- a/dockers/docker-fpm-frr/frr/supervisord/supervisord.conf.j2 +++ b/dockers/docker-fpm-frr/frr/supervisord/supervisord.conf.j2 @@ -89,6 +89,18 @@ dependent_startup=true dependent_startup_wait_for=zsocket:exited {% if DEVICE_METADATA.localhost.frr_mgmt_framework_config is defined and DEVICE_METADATA.localhost.frr_mgmt_framework_config == "true" %} +[program:isisd] +command=/usr/lib/frr/isisd -A 127.0.0.1 -M snmp +priority=5 +stopsignal=KILL +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=zsocket:exited + [program:ospfd] command=/usr/lib/frr/ospfd -A 127.0.0.1 -M snmp priority=5 diff --git a/src/sonic-frr-mgmt-framework/frrcfgd/frrcfgd.py b/src/sonic-frr-mgmt-framework/frrcfgd/frrcfgd.py index 8db49bf327f5..977d5a798568 100755 --- a/src/sonic-frr-mgmt-framework/frrcfgd/frrcfgd.py +++ b/src/sonic-frr-mgmt-framework/frrcfgd/frrcfgd.py @@ -75,7 +75,7 @@ def extract_cmd_daemons(cmd_str): class BgpdClientMgr(threading.Thread): VTYSH_MARK = 'vtysh ' PROXY_SERVER_ADDR = '/etc/frr/bgpd_client_sock' - ALL_DAEMONS = ['bgpd', 'zebra', 'staticd', 'bfdd', 'ospfd', 'pimd'] + ALL_DAEMONS = ['bgpd', 'zebra', 'staticd', 'bfdd', 'ospfd', 'pimd', 'isisd'] TABLE_DAEMON = { 'DEVICE_METADATA': ['bgpd'], 'BGP_GLOBALS': ['bgpd'], @@ -118,6 +118,9 @@ class BgpdClientMgr(threading.Thread): 'PIM_INTERFACE': ['pimd'], 'IGMP_INTERFACE': ['pimd'], 'IGMP_INTERFACE_QUERY': ['pimd'], + 'ISIS_GLOBAL': ['isisd'], + 'ISIS_LEVELS': ['isisd'], + 'ISIS_INTERFACE': ['isisd'], } VTYSH_CMD_DAEMON = [(r'show (ip|ipv6) route($|\s+\S+)', ['zebra']), (r'show ip mroute($|\s+\S+)', ['pimd']), @@ -1441,6 +1444,70 @@ def hdl_static_route(daemon, cmd_str, op, st_idx, args, data): daemon.upd_nh_set = ip_nh_set return cmd_list +def handle_isis_if_nwtype(daemon, cmd_str, op, st_idx, args, data): + cmd_list = [] + + no_op = '' + if op == CachedDataWithOp.OP_DELETE or args[0] == 'BROADCAST': + no_op = 'no ' + + nwtype = '' + if args[0] == 'POINT_TO_POINT': + nwtype = 'point-to-point' + else : + syslog.syslog(syslog.LOG_ERR, 'handle_isis_if_nwtype invalid nw type args {}'.format(args)) + + syslog.syslog(syslog.LOG_INFO, 'handle_isis_if_nwtype cmd_str {} op {} st_idx {} args {} data {}'.format( + cmd_str, op, st_idx, args, data)) + + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, no_op), + CommandArgument(daemon, True, nwtype))) + return cmd_list + +def handle_isis_if_auth(daemon, cmd_str, op, st_idx, args, data): + cmd_list = [] + no_op = 'no ' if op == CachedDataWithOp.OP_DELETE else '' + + authtype = '' + if args[0] == 'TEXT': + authtype = 'clear' + elif args[0] == 'MD5': + authtype = 'md5' + else : + syslog.syslog(syslog.LOG_ERR, 'handle_isis_if_auth invalid nw type args {}'.format(args)) + + authkey = args[1] + + syslog.syslog(syslog.LOG_INFO, 'handle_isis_if_auth cmd_str {} op {} st_idx {} args {} data {}'.format( + cmd_str, op, st_idx, args, data)) + + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, no_op), + CommandArgument(daemon, True, authtype), + CommandArgument(daemon, True, authkey))) + return cmd_list + +def handle_isis_level_capability(daemon, cmd_str, op, st_idx, args, data): + cmd_list = [] + no_op = 'no ' if op == CachedDataWithOp.OP_DELETE else '' + + level = '' + if args[0] == 'LEVEL_1': + level = 'level-1' + elif args[0] == 'LEVEL_2': + level = 'level-2' + elif args[0] == 'LEVEL_1_2': + level = 'level-1-2' + else : + syslog.syslog(syslog.LOG_ERR, 'handle_isis_level_capability invalid level type args {}'.format(args)) + + syslog.syslog(syslog.LOG_INFO, 'handle_isis_level_capability cmd_str {} op {} st_idx {} args {} data {}'.format( + cmd_str, op, st_idx, args, data)) + + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, no_op), + CommandArgument(daemon, True, level))) + return cmd_list + + class ExtConfigDBConnector(ConfigDBConnector): def __init__(self, ns_attrs = None): super(ExtConfigDBConnector, self).__init__() @@ -2026,6 +2093,45 @@ class BGPConfigDaemon: ('icmp_tos', 'tos {}', handle_ip_sla_common), ] + isis_global_key_map = [ + ('net', '{no:no-prefix}net {}'), + ('level_capability', '{}is-type {}', handle_isis_level_capability), + ('dynamic_hostname', '{no:no-prefix}hostname dynamic', ['true', 'false', True]), + ('attach_send', '{no:no-prefix}attached-bit send', ['true', 'false', True]), + ('attach_receive_ignore', '{no:no-prefix}attached-bit receive ignore', ['true', 'false', False]), + ('set_overload_bit', '{no:no-prefix}set-overload-bit', ['true', 'false']), + ('lsp_mtu_size', '{no:no-prefix}lsp-mtu {}'), + (['spf_init_delay', + '+spf_short_delay', + '+spf_long_delay', + '+spf_hold_down', + '+spf_time_to_learn'], '{no:no-prefix}spf-delay-ietf init-delay {} short-delay {} long-delay {} holddown {} time-to-learn {}'), + ('log_adjacency_changes', '{no:no-prefix}log-adjacency-changes', ['true', 'false', False]) + ] + + isis_levels_key_map = [ + ('lsp_maximum_lifetime', '{no:no-prefix}max-lsp-lifetime {} {}'), + ('lsp_refresh_interval', '{no:no-prefix}lsp-refresh-interval {} {}'), + ('lsp_generation_interval', '{no:no-prefix}lsp-gen-interval {} {}'), + ('spf_minimum_interval', '{no:no-prefix}spf-interval {} {}') + ] + + isis_interface_key_map = [ + ('ipv4_routing_instance', '{no:no-prefix}ip router isis {}'), + ('ipv6_routing_instance', '{no:no-prefix}ipv6 router isis {}'), + ('passive', '{no:no-prefix}isis passive',['true', 'false', False]), + ('hello_padding', '{no:no-prefix}isis hello padding', ['true', 'false', True]), + ('network_type', '{}isis network {}', handle_isis_if_nwtype), + (['authentication_type', + '+authentication_key'], '{}isis password {} {}', handle_isis_if_auth), + ('enable_bfd', '{no:no-prefix}isis bfd',['true', 'false', False]), + ('bfd_profile', '{no:no-prefix}isis bfd profile {}'), + ('metric', '{no:no-prefix}isis metric {}'), + ('csnp_interval', '{no:no-prefix}isis csnp-interval {}'), + ('psnp_interval', '{no:no-prefix}isis psnp-interval {}'), + ('hello_interval', '{no:no-prefix}isis hello-interval {}'), + ('hello_multiplier', '{no:no-prefix}isis hello-multiplier {}') + ] tbl_to_key_map = {'BGP_GLOBALS': global_key_map, 'BGP_GLOBALS_AF': global_af_key_map, @@ -2054,7 +2160,10 @@ class BGPConfigDaemon: 'PIM_GLOBALS': pim_global_key_map, 'PIM_INTERFACE': pim_interface_key_map, 'IGMP_INTERFACE': igmp_mcast_grp_key_map, - 'IGMP_INTERFACE_QUERY': igmp_interface_config_key_map + 'IGMP_INTERFACE_QUERY': igmp_interface_config_key_map, + 'ISIS_GLOBAL': isis_global_key_map, + 'ISIS_LEVELS': isis_levels_key_map, + 'ISIS_INTERFACE': isis_interface_key_map } vrf_tables = {'BGP_GLOBALS', 'BGP_GLOBALS_AF', @@ -2251,7 +2360,10 @@ def __init__(self): ('PIM_GLOBALS', self.bgp_table_handler_common), ('PIM_INTERFACE', self.bgp_table_handler_common), ('IGMP_INTERFACE', self.bgp_table_handler_common), - ('IGMP_INTERFACE_QUERY', self.bgp_table_handler_common) + ('IGMP_INTERFACE_QUERY', self.bgp_table_handler_common), + ('ISIS_GLOBAL', self.bgp_table_handler_common), + ('ISIS_LEVELS', self.bgp_table_handler_common), + ('ISIS_INTERFACE', self.bgp_table_handler_common) ] self.bgp_message = queue.Queue(0) self.table_data_cache = self.config_db.get_table_data([tbl for tbl, _ in self.table_handler_list]) @@ -3687,22 +3799,195 @@ def __update_bgp(self, data_list): if not key_map.run_command(self, table, data, cmd_prefix): syslog.syslog(syslog.LOG_ERR, 'failed running ip igmp interface config command') continue + + elif table == 'ISIS_GLOBAL': + vrf = prefix + instance = key + + if not del_table: + syslog.syslog(syslog.LOG_INFO, 'Create router isis {} vrf {}'.format(instance, vrf)) + + cmd_prefix = ['configure terminal', + 'router isis {} vrf {}'.format(instance, vrf)] + + if not key_map.run_command(self, table, data, cmd_prefix): + syslog.syslog(syslog.LOG_ERR, 'failed running isis config command') + continue + else: + syslog.syslog(syslog.LOG_INFO, 'Delete ISIS_GLOBAL {} vrf {} data {}'.format(instance, vrf, data)) + + cmd_data = {} + cache_tbl_key = 'ISIS_GLOBAL&&{}|{}'.format(vrf, instance) + cache_tbl_l1 = 'ISIS_LEVELS&&{}|{}|{}'.format(vrf, instance, '1') + cache_tbl_l2 = 'ISIS_LEVELS&&{}|{}|{}'.format(vrf, instance, '2') + + del_isis_instance = True + if (cache_tbl_l1 in self.table_data_cache.keys() or cache_tbl_l2 in self.table_data_cache.keys()): + del_isis_instance = False + + if cache_tbl_key in self.table_data_cache.keys(): + cache_tbl_data = self.table_data_cache[cache_tbl_key] + + for key, data in cache_tbl_data.items() : + cached_op_data = CachedDataWithOp(data, CachedDataWithOp.OP_DELETE) + cmd_data.update({key : cached_op_data}) + + if len(cmd_data) : + cmd_prefix = ['configure terminal', + 'router isis {} vrf {}'.format(instance, vrf)] + + syslog.syslog(syslog.LOG_INFO, 'Row delete cmd data {}'.format(cmd_data)) + if not key_map.run_command(self, table, cmd_data, cmd_prefix): + syslog.syslog(syslog.LOG_ERR, 'failed running isis {} vrf {} global config command'.format(instance, vrf)) + continue + + # force delete all ISIS_GLOBAL instance attributes in cache + syslog.syslog(syslog.LOG_INFO, 'Row delete key {}'.format(cache_tbl_key)) + syslog.syslog(syslog.LOG_INFO, 'Row delete cached data {}'.format(cache_tbl_data)) + + del(self.table_data_cache[cache_tbl_key]) + self.upd_data_list = [(table, '{}|{}'.format(vrf, instance), {})] + + if del_isis_instance: + command = "vtysh -c 'configure terminal' -c 'no router isis {} vrf {}'".format(instance, vrf) + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed to delete isis local_asn {} vrf ()'.format(instance, vrf)) + + elif table == 'ISIS_LEVELS': + vrf = prefix + + keyvals = key.split('|') + instance = keyvals[0] + level_number = keyvals[1] + level = 'level-{}'.format(level_number) + + if not del_table: + syslog.syslog(syslog.LOG_INFO, 'Create router isis {} vrf {}, Level: {}, Command: {}'.format(instance, vrf, level, data)) + + cmd_prefix = ['configure terminal', + 'router isis {} vrf {}'.format(instance, vrf)] + + if not key_map.run_command(self, table, data, cmd_prefix, level): + syslog.syslog(syslog.LOG_ERR, 'failed running isis {} vrf {} level config command for Level: {}, Command: {}'.format(instance, vrf, level, data)) + continue + + else: + syslog.syslog(syslog.LOG_INFO, 'Delete ISIS_LEVELS {} vrf {} {} data {}'.format(instance, vrf, level, data)) + + cmd_data = {} + cache_tbl_key = 'ISIS_LEVELS&&{}|{}|{}'.format(vrf, instance, level_number) + cache_tbl_global = 'ISIS_GLOBAL&&{}|{}'.format(vrf, instance) + + del_isis_instance = True + if cache_tbl_global in self.table_data_cache.keys(): + del_isis_instance = False + + if cache_tbl_key in self.table_data_cache.keys(): + cache_tbl_data = self.table_data_cache[cache_tbl_key] + for k, data in cache_tbl_data.items() : + cached_op_data = CachedDataWithOp(data, CachedDataWithOp.OP_DELETE) + cmd_data.update({k : cached_op_data}) + + if len(cmd_data) : + cmd_prefix = ['configure terminal', + 'router isis {} vrf {}'.format(instance, vrf)] + + syslog.syslog(syslog.LOG_INFO, 'Row delete cmd data {} '.format(cmd_data)) + if not key_map.run_command(self, table, cmd_data, cmd_prefix, level): + syslog.syslog(syslog.LOG_ERR, 'failed running isis {} vrf {} level config command for Level: {}, Command: {}'.format(instance, vrf, level, cmd_data)) + continue + + # force delete all ISIS_LEVELS level attributes in cache + syslog.syslog(syslog.LOG_INFO, 'Row delete key {}'.format(cache_tbl_key)) + syslog.syslog(syslog.LOG_INFO, 'Row delete cached data {}'.format(cache_tbl_data)) + + del(self.table_data_cache[cache_tbl_key]) + self.upd_data_list = [(table, '{}|{}|{}'.format(vrf, instance, level_number), {})] + + if del_isis_instance: + command = "vtysh -c 'configure terminal' -c 'no router isis {} vrf {}'".format(instance, vrf) + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed to delete isis local_asn {} vrf {}'.format(instance, vrf)) + + elif table == 'ISIS_INTERFACE': + instance = prefix + ifname = key + + # In FRR, if ipv4 or ipv6 is not enabled, all isis related interface configs are removed + if 'ipv4_routing_instance' in data.keys() and 'ipv6_routing_instance' in data.keys(): + if data['ipv4_routing_instance'].op == CachedDataWithOp.OP_DELETE and \ + data['ipv6_routing_instance'].op == CachedDataWithOp.OP_DELETE: + del_table = True + elif 'ipv4_routing_instance' in data.keys() and \ + ('ipv6_routing_instance' not in data.keys() ): + if data['ipv4_routing_instance'].op == CachedDataWithOp.OP_DELETE: + del_table = True + elif 'ipv6_routing_instance' in data.keys() and \ + ('ipv4_routing_instance' not in data.keys() ): + if data['ipv6_routing_instance'].op == CachedDataWithOp.OP_DELETE: + del_table = True + + if not del_table: + syslog.syslog(syslog.LOG_INFO, 'Create router isis {}, Interface: {}, Command: {}'.format(instance, ifname, data)) + + cmd_prefix = ['configure terminal', + 'interface {}'.format(ifname)] + + if not key_map.run_command(self, table, data, cmd_prefix): + syslog.syslog(syslog.LOG_ERR, 'failed running isis {} interface config command for interface: {}, Command: {}'.format(instance, ifname, data)) + continue + else: + syslog.syslog(syslog.LOG_INFO, 'Delete ISIS_INTERFACE {} {} data {}'.format(instance, ifname, data)) + + cmd_data = {} + cache_tbl_key = 'ISIS_INTERFACE&&{}|{}'.format(instance, ifname) + + if cache_tbl_key in self.table_data_cache.keys(): + cache_tbl_data = self.table_data_cache[cache_tbl_key] + + for key, data in cache_tbl_data.items() : + cached_op_data = CachedDataWithOp(data, CachedDataWithOp.OP_DELETE) + cmd_data.update({key : cached_op_data}) + + if len(cmd_data) : + cmd_prefix = ['configure terminal', + 'interface {}'.format(ifname)] + + syslog.syslog(syslog.LOG_INFO, 'Row delete cmd data {}'.format(cmd_data)) + if not key_map.run_command(self, table, cmd_data, cmd_prefix): + syslog.syslog(syslog.LOG_ERR, 'failed running isis {} interface config command for Interface: {}, Command: {}'.format(instance, ifname, cmd_data)) + continue + + # force delete all ISIS_INTERFACE level attributes in cache + syslog.syslog(syslog.LOG_INFO, 'Row delete key {}'.format(cache_tbl_key)) + syslog.syslog(syslog.LOG_INFO, 'Row delete cached data {}'.format(cache_tbl_data)) + + del(self.table_data_cache[cache_tbl_key]) + self.upd_data_list = [(table, '{}|{}'.format(instance, ifname), {})] def __add_op_to_data(self, table_key, data, comb_attr_list): cached_data = self.table_data_cache.setdefault(table_key, {}) for key in cached_data: if key in data: + # if the value is null, delete + if data[key] == 'None': + data[key] = CachedDataWithOp(cached_data[key], CachedDataWithOp.OP_DELETE) # both in cache and data, update/none - data[key] = (CachedDataWithOp(data[key], CachedDataWithOp.OP_NONE) if data[key] == cached_data[key] else - CachedDataWithOp(data[key], CachedDataWithOp.OP_UPDATE)) + else: + data[key] = (CachedDataWithOp(data[key], CachedDataWithOp.OP_NONE) if data[key] == cached_data[key] else + CachedDataWithOp(data[key], CachedDataWithOp.OP_UPDATE)) else: # in cache but not in data, delete data[key] = CachedDataWithOp(cached_data[key], CachedDataWithOp.OP_DELETE) for key in data: if not isinstance(data[key], CachedDataWithOp): + # if the value is null, none + if data[key] == 'None': + data[key] = CachedDataWithOp(data[key], CachedDataWithOp.OP_NONE) # in data but not in cache, add - data[key] = CachedDataWithOp(data[key], CachedDataWithOp.OP_ADD) + else: + data[key] = CachedDataWithOp(data[key], CachedDataWithOp.OP_ADD) # combo attributes handling op_list = [CachedDataWithOp.OP_DELETE, CachedDataWithOp.OP_ADD, CachedDataWithOp.OP_UPDATE, CachedDataWithOp.OP_NONE] for key_set in comb_attr_list: @@ -3762,9 +4047,9 @@ def bgp_table_handler_common(self, table, key, data, comb_attr_list = []): table_key = ExtConfigDBConnector.get_table_key(table, key) self.__add_op_to_data(table_key, data, comb_attr_list) self.bgp_message.put((key, del_table, table, data)) - upd_data_list = [] - self.__update_bgp(upd_data_list) - for table, key, data in upd_data_list: + self.upd_data_list = [] + self.__update_bgp(self.upd_data_list) + for table, key, data in self.upd_data_list: table_key = ExtConfigDBConnector.get_table_key(table, key) self.__update_cache_data(table_key, data) diff --git a/src/sonic-frr-mgmt-framework/setup.py b/src/sonic-frr-mgmt-framework/setup.py index d3c9f1dae173..7cdef5aae532 100755 --- a/src/sonic-frr-mgmt-framework/setup.py +++ b/src/sonic-frr-mgmt-framework/setup.py @@ -46,6 +46,9 @@ 'templates/staticd/staticd.conf.j2', 'templates/staticd/staticd.db.conf.j2', 'templates/staticd/staticd.db.default_route.conf.j2', - 'templates/frr/frr.conf.j2']) + 'templates/frr/frr.conf.j2', + 'templates/isisd/isisd.conf.j2', + 'templates/isisd/isisd.conf.db.j2', + 'templates/isisd/isis_copp_trap_config.j2']) ] ) diff --git a/src/sonic-frr-mgmt-framework/templates/frr/frr.conf.j2 b/src/sonic-frr-mgmt-framework/templates/frr/frr.conf.j2 index f1f015a6e7a6..32e5ca818c61 100644 --- a/src/sonic-frr-mgmt-framework/templates/frr/frr.conf.j2 +++ b/src/sonic-frr-mgmt-framework/templates/frr/frr.conf.j2 @@ -28,3 +28,5 @@ agentx ! {% include "bfdd.conf.j2" %} ! +{% include "isisd.conf.j2" %} +! diff --git a/src/sonic-frr-mgmt-framework/templates/isisd/isis_copp_trap_config.j2 b/src/sonic-frr-mgmt-framework/templates/isisd/isis_copp_trap_config.j2 new file mode 100644 index 000000000000..a193cb2bc121 --- /dev/null +++ b/src/sonic-frr-mgmt-framework/templates/isisd/isis_copp_trap_config.j2 @@ -0,0 +1,12 @@ +{ + "COPP_TRAP": { + "bgp": { +{% if DEVICE_METADATA.localhost.frr_mgmt_framework_config is defined and DEVICE_METADATA.localhost.frr_mgmt_framework_config == "true" %} + + "trap_ids": "bgp,bgpv6,isis" +{% else %} + "trap_ids": "bgp,bgpv6" +{% endif %} + } + } +} diff --git a/src/sonic-frr-mgmt-framework/templates/isisd/isisd.conf.db.j2 b/src/sonic-frr-mgmt-framework/templates/isisd/isisd.conf.db.j2 new file mode 100644 index 000000000000..23e565a538ec --- /dev/null +++ b/src/sonic-frr-mgmt-framework/templates/isisd/isisd.conf.db.j2 @@ -0,0 +1,168 @@ +! template: isisd/isisd.conf.db.j2 +! +! ISIS configuration +! +{% if ISIS_GLOBAL is defined and ISIS_GLOBAL|length > 0 %} +{% for keys, isis_instance in ISIS_GLOBAL.items() %} +{% set vrf = keys[0] %} +{% set instance = keys[1] %} +{% if instance and instance.lower() != 'null' and vrf and vrf.lower() != 'null' %} +router isis {{ instance }} vrf {{vrf}} +{% if 'net' in isis_instance and isis_instance['net'] != 'None' %} +net {{ isis_instance['net'] }} +{% endif %} +{% if 'level_capability' in isis_instance %} +{% if isis_instance['level_capability'] == 'LEVEL_1' %} +is-type level-1 +{% elif isis_instance['level_capability'] == 'LEVEL_2' %} +is-type level-2-only +{% elif isis_instance['level_capability'] == 'LEVEL_1_2' %} +is-type level-1-2 +{% endif %} +{% endif %} +{% if 'dynamic_hostname' in isis_instance %} +{% if isis_instance['dynamic_hostname'] == 'true' %} +hostname dynamic +{% elif isis_instance['dynamic_hostname'] == 'false' %} +no hostname dynamic +{% endif %} +{% endif %} +{% if 'attach_send' in isis_instance %} +{% if isis_instance['attach_send'] == 'true' %} +attached-bit send +{% elif isis_instance['attach_send'] == 'false' %} +no attached-bit send +{% endif %} +{% endif %} +{% if 'attach_receive_ignore' in isis_instance %} +{% if isis_instance['attach_receive_ignore'] == 'true' %} +attached-bit receive ignore +{% elif isis_instance['attach_receive_ignore'] == 'false' %} +no attached-bit receive ignore +{% endif %} +{% endif %} +{% if 'set_overload_bit' in isis_instance %} +{% if isis_instance['set_overload_bit'] == 'true' %} +set-overload-bit +{% elif isis_instance['set_overload_bit'] == 'false' %} +no set-overload-bit +{% endif %} +{% endif %} +{% if 'lsp_mtu_size' in isis_instance %} +lsp-mtu {{ isis_instance['lsp_mtu_size'] }} +{% endif %} +{% if 'spf_init_delay' in isis_instance and 'spf_short_delay' in isis_instance and 'spf_long_delay' in isis_instance and 'spf_hold_down' in isis_instance and 'spf_time_to_learn' in isis_instance %} +spf-delay-ietf init-delay {{ isis_instance['spf_init_delay'] }} short-delay {{ isis_instance['spf_short_delay'] }} long-delay {{ isis_instance['spf_long_delay'] }} holddown {{ isis_instance['spf_hold_down'] }} time-to-learn {{ isis_instance['spf_time_to_learn'] }} +{% endif %} +{% if 'log_adjacency_changes' in isis_instance %} +{% if isis_instance['log_adjacency_changes'] == 'true' %} +log-adjacency-changes +{% elif isis_instance['log_adjacency_changes'] == 'false' %} +no log-adjacency-changes +{% endif %} +{% endif %} +{% endif %} +{% endfor %} +{% endif %} +! +{% if ISIS_LEVELS is defined and ISIS_LEVELS|length > 0 %} +{% for keys, isis_level_data in ISIS_LEVELS.items() %} +{% set vrf = keys[0] %} +{% set instance = keys[1] %} +{% set level_number = keys[2] %} +{% if instance and instance.lower() != 'null' and vrf and vrf.lower() != 'null' and level_number and (level_number == '1' or level_number == '2') %} +router isis {{ instance }} vrf {{vrf}} +{% if level_number == '1' %} +{% set level = 'level-1' %} +{% elif level_number == '2' %} +{% set level = 'level-2' %} +{% endif %} +{% if 'lsp_refresh_interval' in isis_level_data %} +lsp-refresh-interval {{ level }} {{ isis_level_data['lsp_refresh_interval'] }} +{% endif %} +{% if 'lsp_maximum_lifetime' in isis_level_data %} +max-lsp-lifetime {{ level }} {{ isis_level_data['lsp_maximum_lifetime'] }} +{% endif %} +{% if 'lsp_generation_interval' in isis_level_data %} +lsp-gen-interval {{ level }} {{ isis_level_data['lsp_generation_interval'] }} +{% endif %} +{% if 'spf_minimum_interval' in isis_level_data %} +spf-interval {{ level }} {{ isis_level_data['spf_minimum_interval'] }} +{% endif %} +{% endif %} +{% endfor %} +{% endif %} +! +{% if ISIS_INTERFACE is defined and ISIS_INTERFACE|length > 0 %} +{% for keys, isis_interface_data in ISIS_INTERFACE.items() %} +{% set instance = keys[0] %} +{% set interface = keys[1] %} +{% if instance and instance.lower() != 'null' and interface and interface.lower() != 'null' %} +interface {{ interface }} +{% if (('ipv4_routing_instance' in isis_interface_data and not (isis_interface_data['ipv4_routing_instance'] == 'None' or isis_interface_data['ipv4_routing_instance'].lower() == 'null' )) or + ('ipv6_routing_instance' in isis_interface_data and not (isis_interface_data['ipv6_routing_instance'] == 'None' or isis_interface_data['ipv6_routing_instance'].lower() == 'null'))) %} +{% if 'ipv4_routing_instance' in isis_interface_data and not (isis_interface_data['ipv4_routing_instance'] == 'None' or isis_interface_data['ipv4_routing_instance'].lower() == 'null' ) %} +ip router isis {{ isis_interface_data['ipv4_routing_instance'] }} +{% endif %} +{% if 'ipv6_routing_instance' in isis_interface_data and not (isis_interface_data['ipv6_routing_instance'] == 'None' or isis_interface_data['ipv6_routing_instance'].lower() == 'null') %} +ipv6 router isis {{ isis_interface_data['ipv6_routing_instance'] }} +{% endif %} +{% if 'passive' in isis_interface_data %} +{% if isis_interface_data['passive'] == 'true' %} +isis passive +{% elif isis_interface_data['passive'] == 'false' %} +no isis passive +{% endif %} +{% endif %} +{% if 'hello_padding' in isis_interface_data %} +{% if isis_interface_data['hello_padding'] == 'true' %} +isis hello padding +{% elif isis_interface_data['hello_padding'] == 'false' %} +no isis hello padding +{% endif %} +{% endif %} +{% if 'network_type' in isis_interface_data %} +{% if isis_interface_data['network_type'] == 'POINT_TO_POINT' %} +isis network point-to-point +{% endif %} +{% endif %} +{% if 'authentication_key' in isis_interface_data and 'authentication_type' in isis_interface_data and not + (isis_interface_data['authentication_key'] == 'None' or isis_interface_data['authentication_key'].lower() == 'null') %} +{% if isis_interface_data['authentication_type'] == 'TEXT' %} +isis password clear {{ isis_interface_data['authentication_key'] }} +{% elif isis_interface_data['authentication_type'] == 'MD5' %} +isis password md5 {{ isis_interface_data['authentication_key'] }} +{% endif %} +{% endif %} +{% if 'enable_bfd' in isis_interface_data %} +{% if isis_interface_data['enable_bfd'] == 'true' %} +isis bfd +{% elif isis_interface_data['enable_bfd'] == 'false' %} +no isis bfd +{% endif %} +{% endif %} +{% if 'bfd_profile' in isis_interface_data and not (isis_interface_data['bfd_profile'] == 'None' or isis_interface_data['bfd_profile'].lower() == 'null') %} +isis bfd profile {{ isis_interface_data['bfd_profile'] }} +{% endif %} +{% if 'metric' in isis_interface_data %} +isis metric {{ isis_interface_data['metric'] }} +{% endif %} +{% if 'csnp_interval' in isis_interface_data %} +isis csnp-interval {{ isis_interface_data['csnp_interval'] }} +{% endif %} +{% if 'psnp_interval' in isis_interface_data %} +isis psnp-interval {{ isis_interface_data['psnp_interval'] }} +{% endif %} +{% if 'hello_interval' in isis_interface_data %} +isis hello-interval {{ isis_interface_data['hello_interval'] }} +{% endif %} +{% if 'hello_multiplier' in isis_interface_data %} +isis hello-multiplier {{ isis_interface_data['hello_multiplier'] }} +{% endif %} +{% endif %} +{% endif %} +{% endfor %} +{% endif %} +! +! end of template: isisd/isisd.conf.db.j2 +! diff --git a/src/sonic-frr-mgmt-framework/templates/isisd/isisd.conf.j2 b/src/sonic-frr-mgmt-framework/templates/isisd/isisd.conf.j2 new file mode 100644 index 000000000000..81b5aeb13cdb --- /dev/null +++ b/src/sonic-frr-mgmt-framework/templates/isisd/isisd.conf.j2 @@ -0,0 +1,10 @@ +! template: isisd/isisd.conf.j2 +! +! ISIS configuration using config DB ISIS instance tables +! +{% include "common/daemons.common.conf.j2" %} +! +{% include "isisd.conf.db.j2" %} +! +! end of template: isisd/isisd.conf.j2 +! diff --git a/src/sonic-frr-mgmt-framework/tests/test_config.py b/src/sonic-frr-mgmt-framework/tests/test_config.py index 02dbf391e99d..cf392054f06a 100644 --- a/src/sonic-frr-mgmt-framework/tests/test_config.py +++ b/src/sonic-frr-mgmt-framework/tests/test_config.py @@ -149,6 +149,82 @@ def hdl_confed_peers_cmd(is_del, cmd_list, chk_data): conf_bgp_af_cmd('Vrf_red', 200, 'ipv6') + ['{}import vrf route-map test_map']), ] +conf_isis_cmd = lambda vrf, instance: [conf_cmd, 'router isis %s vrf %s' % (instance, vrf)] +conf_isis_if_cmd = lambda instance, ifname: [conf_cmd, 'interface %s' % (ifname)] +conf_isis_level_cmd = lambda vrf, instance, level: conf_isis_cmd(vrf, instance) + +isis_data = [ + CmdMapTestInfo('ISIS_GLOBAL', 'default|100', {'net': '49.0001.1040.4400.0249.00'}, + conf_isis_cmd('default', 100) + ['{}net 49.0001.1040.4400.0249.00']), + CmdMapTestInfo('ISIS_GLOBAL', 'default|100', {'level_capability': 'LEVEL_2'}, + conf_isis_cmd('default', 100) + ['{}is-type level-2']), + CmdMapTestInfo('ISIS_GLOBAL', 'default|100', {'dynamic_hostname': 'true'}, + conf_isis_cmd('default', 100) + ['{}hostname dynamic'], True), + CmdMapTestInfo('ISIS_GLOBAL', 'default|100', {'dynamic_hostname': 'None'}, + conf_isis_cmd('default', 100) + ['{}hostname dynamic'], True), + CmdMapTestInfo('ISIS_GLOBAL', 'default|100', {'attach_send': 'true'}, + conf_isis_cmd('default', 100) + ['{}attached-bit send'], True), + CmdMapTestInfo('ISIS_GLOBAL', 'default|100', {'attach_send': 'None'}, + conf_isis_cmd('default', 100) + ['{}attached-bit send'], True), + CmdMapTestInfo('ISIS_GLOBAL', 'default|100', {'attach_receive_ignore': 'true'}, + conf_isis_cmd('default', 100) + ['{}attached-bit receive ignore'], True), + CmdMapTestInfo('ISIS_GLOBAL', 'default|100', {'attach_receive_ignore': 'None'}, + conf_isis_cmd('default', 100) + ['no attached-bit receive ignore'], True), + CmdMapTestInfo('ISIS_GLOBAL', 'default|100', {'set_overload_bit': 'true'}, + conf_isis_cmd('default', 100) + ['{}set-overload-bit']), + CmdMapTestInfo('ISIS_GLOBAL', 'default|100', {'lsp_mtu_size': '1500'}, + conf_isis_cmd('default', 100) + ['{}lsp-mtu 1500']), + CmdMapTestInfo('ISIS_GLOBAL', 'default|100', {'log_adjacency_changes': 'true'}, + conf_isis_cmd('default', 100) + ['{}log-adjacency-changes']), + CmdMapTestInfo('ISIS_GLOBAL', 'default|100', {'spf_init_delay': 15, + 'spf_short_delay': 15, + 'spf_long_delay': 5, + 'spf_hold_down': 15, + 'spf_time_to_learn': 5}, + conf_isis_cmd('default', 100) + ['{}spf-delay-ietf init-delay 15 short-delay 15 long-delay 5 holddown 15 time-to-learn 5']), + + CmdMapTestInfo('ISIS_LEVELS', 'default|100|2', {'lsp_refresh_interval': '4'}, + conf_isis_level_cmd('default', 100, '2') + ['{}lsp-refresh-interval level-2 4']), + CmdMapTestInfo('ISIS_LEVELS', 'default|100|2', {'lsp_maximum_lifetime': '4'}, + conf_isis_level_cmd('default', 100, '2') + ['{}max-lsp-lifetime level-2 4']), + CmdMapTestInfo('ISIS_LEVELS', 'default|100|2', {'lsp_generation_interval': '4'}, + conf_isis_level_cmd('default', 100, '2') + ['{}lsp-gen-interval level-2 4']), + CmdMapTestInfo('ISIS_LEVELS', 'default|100|2', {'spf_minimum_interval': '4'}, + conf_isis_level_cmd('default', 100, '2') + ['{}spf-interval level-2 4']), + + CmdMapTestInfo('ISIS_INTERFACE', '100|ethernet2', {'ipv4_routing_instance': '100'}, + conf_isis_if_cmd(100, 'ethernet2') + ['{}ip router isis 100']), + CmdMapTestInfo('ISIS_INTERFACE', '100|ethernet2', {'ipv6_routing_instance': '100'}, + conf_isis_if_cmd(100, 'ethernet2') + ['{}ipv6 router isis 100']), + CmdMapTestInfo('ISIS_INTERFACE', '100|ethernet2', {'passive': 'true'}, + conf_isis_if_cmd(100, 'ethernet2') + ['{}isis passive']), + CmdMapTestInfo('ISIS_INTERFACE', '100|ethernet2', {'hello_padding': 'true'}, + conf_isis_if_cmd(100, 'ethernet2') + ['{}isis hello padding'], True), + CmdMapTestInfo('ISIS_INTERFACE', '100|ethernet2', {'hello_padding': 'None'}, + conf_isis_if_cmd(100, 'ethernet2') + ['{}isis hello padding'], True), + CmdMapTestInfo('ISIS_INTERFACE', '100|ethernet2', {'network_type': 'POINT_TO_POINT'}, + conf_isis_if_cmd(100, 'ethernet2') + ['{}isis network point-to-point']), + CmdMapTestInfo('ISIS_INTERFACE', '100|ethernet2', {'authentication_type': 'TEXT', + 'authentication_key': 'password'}, + conf_isis_if_cmd(100, 'ethernet2') + ['{}isis password clear password']), + CmdMapTestInfo('ISIS_INTERFACE', '100|ethernet2', {'enable_bfd': 'true'}, + conf_isis_if_cmd(100, 'ethernet2') + ['{}isis bfd'], True), + CmdMapTestInfo('ISIS_INTERFACE', '100|ethernet2', {'enable_bfd': 'None'}, + conf_isis_if_cmd(100, 'ethernet2') + ['no isis bfd'], True), + CmdMapTestInfo('ISIS_INTERFACE', '100|ethernet2', {'bfd_profile': 'PROFILE'}, + conf_isis_if_cmd(100, 'ethernet2') + ['{}isis bfd profile PROFILE']), + CmdMapTestInfo('ISIS_INTERFACE', '100|ethernet2', {'metric': '500'}, + conf_isis_if_cmd(100, 'ethernet2') + ['{}isis metric 500']), + CmdMapTestInfo('ISIS_INTERFACE', '100|ethernet2', {'csnp_interval': '4'}, + conf_isis_if_cmd(100, 'ethernet2') + ['{}isis csnp-interval 4']), + CmdMapTestInfo('ISIS_INTERFACE', '100|ethernet2', {'psnp_interval': '4'}, + conf_isis_if_cmd(100, 'ethernet2') + ['{}isis psnp-interval 4']), + CmdMapTestInfo('ISIS_INTERFACE', '100|ethernet2', {'hello_interval': '4'}, + conf_isis_if_cmd(100, 'ethernet2') + ['{}isis hello-interval 4']), + CmdMapTestInfo('ISIS_INTERFACE', '100|ethernet2', {'hello_multiplier': '4'}, + conf_isis_if_cmd(100, 'ethernet2') + ['{}isis hello-multiplier 4']) +] + @patch.dict('sys.modules', **mockmapping) @patch('frrcfgd.frrcfgd.g_run_command') def data_set_del_test(test_data, run_cmd): @@ -176,3 +252,4 @@ def data_set_del_test(test_data, run_cmd): def test_bgp_globals(): data_set_del_test(bgp_globals_data) + data_set_del_test(isis_data) diff --git a/src/sonic-yang-models/setup.py b/src/sonic-yang-models/setup.py index eab62ddcab6c..9a8b674fcc15 100644 --- a/src/sonic-yang-models/setup.py +++ b/src/sonic-yang-models/setup.py @@ -123,6 +123,7 @@ def run(self): './yang-models/sonic-hash.yang', './yang-models/sonic-system-defaults.yang', './yang-models/sonic-interface.yang', + './yang-models/sonic-isis.yang', './yang-models/sonic-kdump.yang', './yang-models/sonic-kubernetes_master.yang', './yang-models/sonic-loopback-interface.yang', @@ -214,6 +215,7 @@ def run(self): './cvlyang-models/sonic-hash.yang', './cvlyang-models/sonic-system-defaults.yang', './cvlyang-models/sonic-interface.yang', + './cvlyang-models/sonic-isis.yang', './cvlyang-models/sonic-kdump.yang', './cvlyang-models/sonic-kubernetes_master.yang', './cvlyang-models/sonic-loopback-interface.yang', diff --git a/src/sonic-yang-models/tests/files/sample_config_db.json b/src/sonic-yang-models/tests/files/sample_config_db.json index 9d4c291cb081..182588c81ec6 100644 --- a/src/sonic-yang-models/tests/files/sample_config_db.json +++ b/src/sonic-yang-models/tests/files/sample_config_db.json @@ -2357,6 +2357,49 @@ "nexthop-vrf": "default" } }, + "ISIS_GLOBAL": { + "default|100": { + "net": "49.0001.1040.4400.0249.00", + "level_capability": "LEVEL_2", + "dynamic_hostname": "true", + "attach_send": "true", + "attach_receive_ignore": "true", + "set_overload_bit": "false", + "lsp_mtu_size": "1500", + "spf_init_delay": "15", + "spf_short_delay": "15", + "spf_long_delay": "15", + "spf_hold_down": "15", + "spf_time_to_learn": "15", + "log_adjacency_changes": "true" + } + }, + "ISIS_LEVELS": { + "default|100|2": { + "lsp_refresh_interval": "600", + "lsp_maximum_lifetime": "900", + "lsp_generation_interval": "30", + "spf_minimum_interval": "5" + } + }, + "ISIS_INTERFACE": { + "100|Ethernet2": { + "ipv4_routing_instance": "100", + "ipv6_routing_instance": "100", + "passive": "false", + "hello_padding": "true", + "network_type": "POINT_TO_POINT", + "authentication_type": "TEXT", + "authentication_key": "password", + "enable_bfd": "true", + "bfd_profile": "PROFILE", + "metric": "5000", + "csnp_interval": "15", + "psnp_interval": "2", + "hello_interval": "5", + "hello_multiplier": "10" + } + }, "KUBERNETES_MASTER": { "SERVER": { "disable": "True", diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests/isis.json b/src/sonic-yang-models/tests/yang_model_tests/tests/isis.json new file mode 100644 index 000000000000..866a2c1fceec --- /dev/null +++ b/src/sonic-yang-models/tests/yang_model_tests/tests/isis.json @@ -0,0 +1,121 @@ +{ + "ISIS_GLOBAL_TABLE": { + "desc": "ISIS_GLOBAL_TABLE correct config pattern." + }, + "ISIS_GLOBAL_INSTANCE_MUST": { + "desc": "ISIS_GLOBAL and ISIS_LEVELS invalidated instance must statement", + "eStr": ["The value of ISIS_GLOBAL 'instance' must be the same as 'instance' in ISIS_LEVELS."] + }, + "ISIS_GLOBAL_VRF_MUST": { + "desc": "ISIS_GLOBAL and ISIS_LEVELS invalidated vrf must statement", + "eStr": ["The value of ISIS_GLOBAL 'vrf_name' must be the same as 'vrf_name' in ISIS_LEVELS."] + }, + "ISIS_GLOBAL_NET_INCORRECT_PATTERN": { + "desc": "ISIS_GLOBAL_NET_INCORRECT_PATTERN pattern failure.", + "eStrKey" : "Pattern", + "eStr" : ["1.1.1.1"] + }, + "ISIS_GLOBAL_INCORRECT_VALUE_MTU_SIZE": { + "desc": "ISIS_GLOBAL incorrect value for lsp_mtu_size field", + "eStrKey" : "InvalidValue", + "eStr" : ["mtu"] + }, + "ISIS_GLOBAL_INCORRECT_VALUE_HOSTNAME": { + "desc": "ISIS_GLOBAL incorrect value for dynamic_hostname field", + "eStrKey" : "InvalidValue", + "eStr" : ["string"] + }, + "ISIS_GLOBAL_MISSING_KEY_VRF": { + "desc": "ISIS_GLOBAL missing mandatory key value vrf_name", + "eStrKey" : "Mandatory", + "eStr" : ["vrf_name"] + }, + "ISIS_GLOBAL_MISSING_KEY_INSTANCE": { + "desc": "ISIS_GLOBAL missing mandatory key value instance", + "eStrKey" : "Mandatory", + "eStr" : ["instance"] + }, + "ISIS_GLOBAL_SPF_MUST": { + "desc": "ISIS_GLOBAL invalidated SPF must statement", + "eStr": ["must only be specified if all other SPF parameters are specified"] + }, + "ISIS_LEVELS_TABLE": { + "desc": "ISIS_LEVELS correct config pattern." + }, + "ISIS_LEVELS_INSTANCE_MUST": { + "desc": "ISIS_LEVELS and ISIS_GLOBAL invalidated instance must statement", + "eStr": ["The value of ISIS_LEVELS 'instance' must be the same as 'instance' in ISIS_GLOBAL."] + }, + "ISIS_LEVELS_VRF_MUST": { + "desc": "ISIS_LEVELS and ISIS_GLOBAL invalidated vrf must statement", + "eStr": ["The value of ISIS_LEVELS 'vrf_name' must be the same as 'vrf_name' in ISIS_GLOBAL."] + }, + "ISIS_LEVELS_INCORRECT_VALUE_LEVEL_NUMBER": { + "desc": "ISIS_LEVELS incorrect value for level_number field", + "eStrKey" : "InvalidValue", + "eStr" : ["level-2"] + }, + "ISIS_LEVELS_INCORRECT_VALUE_LSP_REFRESH_INTERVAL": { + "desc": "ISIS_LEVELS incorrect value for lsp_refresh_interval field", + "eStrKey" : "InvalidValue", + "eStr" : ["string"] + }, + "ISIS_LEVELS_INCORRECT_VALUE_SPF_REFRESH_INTERVAL": { + "desc": "ISIS_LEVELS incorrect value for spf_minimum_interval field", + "eStrKey" : "Range", + "eStr" : ["500"] + }, + "ISIS_LEVELS_MISSING_KEY_LEVEL": { + "desc": "ISIS_LEVELS missing mandatory key value", + "eStrKey" : "Mandatory", + "eStr" : ["level_number"] + }, + "ISIS_LEVELS_INCORRECT_MUST_MAX_REFRESH": { + "desc": "ISIS_LEVELS must statement unsatisfied for lsp_refresh_interval", + "eStr" : ["lsp_maximum_lifetime must be at least 300 seconds greater than lsp_refresh_interval"] + }, + "ISIS_LEVELS_INCORRECT_MUST_GEN_REFRESH": { + "desc": "ISIS_LEVELS must statement unsatisfied for lsp_generation_interval", + "eStr" : ["lsp_generation_interval must be greater than lsp_refresh_interval"] + }, + "ISIS_INTERFACE_TABLE": { + "desc": "ISIS_INTERFACE correct config pattern." + }, + "ISIS_INTERFACE_INCORRECT_VALUE_PASSIVE": { + "desc": "ISIS_INTEFACE incorrect value for passive field", + "eStrKey" : "InvalidValue", + "eStr" : ["passive"] + }, + "ISIS_INTERFACE_INCORRECT_VALUE_NETWORK_TYPE": { + "desc": "ISIS_INTERFACE incorrect value for network_type field", + "eStrKey" : "InvalidValue", + "eStr" : ["network_type"] + }, + "ISIS_INTERFACE_INCORRECT_VALUE_AUTHENTICATION_TYPE": { + "desc": "ISIS_INTERFACE incorrect value for authentication_type field", + "eStr" : ["Failed to resolve identityref"] + }, + "ISIS_INTERFACE_INVALID_MUST_AUTHENTICATION_TYPE": { + "desc": "ISIS_INTERFACE must statement unsatisfied for authentication_type field", + "eStr" : ["If authentication_type is specified, then authentication_key must also be specified."] + }, + "ISIS_INTERFACE_INCORRECT_VALUE_METRIC": { + "desc": "ISIS_INTERFACE incorrect value for metric field", + "eStrKey" : "InvalidValue", + "eStr" : ["metric"] + }, + "ISIS_INTERFACE_INCORRECT_VALUE_HELLO_INTERVAL": { + "desc": "ISIS_INTERFACE incorrect value for hello_interval field", + "eStrKey" : "Range", + "eStr" : ["800"] + }, + "ISIS_INTERFACE_MISSING_KEY": { + "desc": "ISIS_INTERFACE missing mandatory key value", + "eStrKey" : "Mandatory", + "eStr" : ["ifname"] + }, + "ISIS_INTERFACE_INSTANCE_MUST": { + "desc": "ISIS_INTERFACE instance validation", + "eStr" : ["non-existing leaf"] + } +} diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests_config/isis.json b/src/sonic-yang-models/tests/yang_model_tests/tests_config/isis.json new file mode 100644 index 000000000000..c0b7961d04b8 --- /dev/null +++ b/src/sonic-yang-models/tests/yang_model_tests/tests_config/isis.json @@ -0,0 +1,697 @@ +{ + "ISIS_GLOBAL_TABLE": { + "sonic-isis:sonic-isis": { + "sonic-isis:ISIS_GLOBAL": { + "ISIS_GLOBAL_LIST": [ + { + "vrf_name": "default", + "instance":"1", + "net": "49.0001.1040.4400.0249.00", + "level_capability": "LEVEL_2", + "dynamic_hostname": "true", + "attach_send": "true", + "attach_receive_ignore": "true", + "set_overload_bit": "false", + "lsp_mtu_size": "1500", + "spf_init_delay": "15", + "spf_short_delay": "15", + "spf_long_delay": "5", + "spf_hold_down": "15", + "spf_time_to_learn": "5", + "log_adjacency_changes": "true" + } + ] + } + } + }, + "ISIS_GLOBAL_INSTANCE_MUST": { + "sonic-isis:sonic-isis": { + "sonic-isis:ISIS_GLOBAL": { + "ISIS_GLOBAL_LIST": [ + { + "vrf_name": "default", + "instance":"2", + "net": "49.0001.1040.4400.0249.00" + } + ] + }, + "sonic-isis:ISIS_LEVELS": { + "ISIS_LEVELS_LIST": [ + { + "vrf_name": "default", + "instance":"1", + "level_number": "2", + "spf_minimum_interval": "5" + } + ] + } + } + }, + "ISIS_GLOBAL_VRF_MUST": { + "sonic-vrf:sonic-vrf": { + "sonic-vrf:VRF": { + "VRF_LIST": [{ + "name": "Vrf_blue" + }] + } + }, + "sonic-isis:sonic-isis": { + "sonic-isis:ISIS_GLOBAL": { + "ISIS_GLOBAL_LIST": [ + { + "vrf_name": "Vrf_blue", + "instance":"1", + "net": "49.0001.1040.4400.0249.00" + } + ] + }, + "sonic-isis:ISIS_LEVELS": { + "ISIS_LEVELS_LIST": [ + { + "vrf_name": "default", + "instance":"1", + "level_number": "2", + "spf_minimum_interval": "5" + } + ] + } + } + }, + "ISIS_GLOBAL_NET_INCORRECT_PATTERN": { + "sonic-isis:sonic-isis": { + "sonic-isis:ISIS_GLOBAL": { + "ISIS_GLOBAL_LIST": [ + { + "vrf_name": "default", + "instance": "1", + "net": "1.1.1.1" + } + ] + } + } + }, + "ISIS_GLOBAL_INCORRECT_VALUE_MTU_SIZE": { + "sonic-isis:sonic-isis": { + "sonic-isis:ISIS_GLOBAL": { + "ISIS_GLOBAL_LIST": [ + { + "vrf_name": "default", + "instance": "1", + "level_capability": "LEVEL_2", + "lsp_mtu_size": "mtu" + } + ] + } + } + }, + "ISIS_GLOBAL_INCORRECT_VALUE_HOSTNAME": { + "sonic-isis:sonic-isis": { + "sonic-isis:ISIS_GLOBAL": { + "ISIS_GLOBAL_LIST": [ + { + "vrf_name": "default", + "instance": "1", + "level_capability": "LEVEL_2", + "dynamic_hostname": "string" + } + ] + } + } + }, + "ISIS_GLOBAL_MISSING_KEY_VRF": { + "sonic-isis:sonic-isis": { + "sonic-isis:ISIS_GLOBAL": { + "ISIS_GLOBAL_LIST": [ + { + "instance": "1", + "net": "49.0001.1040.4400.0249.00" + } + ] + } + } + }, + "ISIS_GLOBAL_MISSING_KEY_INSTANCE": { + "sonic-isis:sonic-isis": { + "sonic-isis:ISIS_GLOBAL": { + "ISIS_GLOBAL_LIST": [ + { + "vrf_name": "default", + "net": "49.0001.1040.4400.0249.00" + } + ] + } + } + }, + "ISIS_GLOBAL_SPF_MUST": { + "sonic-isis:sonic-isis": { + "sonic-isis:ISIS_GLOBAL": { + "ISIS_GLOBAL_LIST": [ + { + "vrf_name": "default", + "instance":"1", + "net": "49.0001.1040.4400.0249.00", + "level_capability": "LEVEL_2", + "dynamic_hostname": "true", + "attach_send": "true", + "attach_receive_ignore": "true", + "set_overload_bit": "false", + "lsp_mtu_size": "1500", + "spf_init_delay": "15", + "spf_short_delay": "15" + } + ] + } + } + }, + "ISIS_LEVELS_TABLE": { + "sonic-isis:sonic-isis": { + "sonic-isis:ISIS_LEVELS": { + "ISIS_LEVELS_LIST": [ + { + "vrf_name": "default", + "instance":"1", + "level_number": "2", + "lsp_refresh_interval": "600", + "lsp_maximum_lifetime": "900", + "lsp_generation_interval": "30", + "spf_minimum_interval": "5" + } + ] + } + } + }, + "ISIS_LEVELS_INSTANCE_MUST": { + "sonic-isis:sonic-isis": { + "sonic-isis:ISIS_LEVELS": { + "ISIS_LEVELS_LIST": [ + { + "vrf_name": "default", + "instance":"1", + "level_number": "2", + "spf_minimum_interval": "5" + } + ] + }, + "sonic-isis:ISIS_GLOBAL": { + "ISIS_GLOBAL_LIST": [ + { + "vrf_name": "default", + "instance":"2", + "net": "49.0001.1040.4400.0249.00" + } + ] + } + } + }, + "ISIS_LEVELS_VRF_MUST": { + "sonic-vrf:sonic-vrf": { + "sonic-vrf:VRF": { + "VRF_LIST": [{ + "name": "Vrf_blue" + }] + } + }, + "sonic-isis:sonic-isis": { + "sonic-isis:ISIS_LEVELS": { + "ISIS_LEVELS_LIST": [ + { + "vrf_name": "Vrf_blue", + "instance":"1", + "level_number": "2", + "spf_minimum_interval": "5" + } + ] + }, + "sonic-isis:ISIS_GLOBAL": { + "ISIS_GLOBAL_LIST": [ + { + "vrf_name": "default", + "instance":"1", + "net": "49.0001.1040.4400.0249.00" + } + ] + } + } + }, + "ISIS_LEVELS_INCORRECT_VALUE_LEVEL_NUMBER": { + "sonic-isis:sonic-isis": { + "sonic-isis:ISIS_LEVELS": { + "ISIS_LEVELS_LIST": [ + { + "vrf_name": "default", + "instance":"1", + "level_number": "level-2", + "lsp_refresh_interval": "string" + } + ] + } + } + }, + "ISIS_LEVELS_INCORRECT_VALUE_LSP_REFRESH_INTERVAL": { + "sonic-isis:sonic-isis": { + "sonic-isis:ISIS_LEVELS": { + "ISIS_LEVELS_LIST": [ + { + "vrf_name": "default", + "instance":"1", + "level_number": "2", + "lsp_refresh_interval": "string" + } + ] + } + } + }, + "ISIS_LEVELS_INCORRECT_VALUE_SPF_REFRESH_INTERVAL": { + "sonic-isis:sonic-isis": { + "sonic-isis:ISIS_LEVELS": { + "ISIS_LEVELS_LIST": [ + { + "vrf_name": "default", + "instance":"1", + "level_number": "2", + "spf_minimum_interval": "500" + } + ] + } + } + }, + "ISIS_LEVELS_MISSING_KEY_LEVEL": { + "sonic-isis:sonic-isis": { + "sonic-isis:ISIS_LEVELS": { + "ISIS_LEVELS_LIST": [ + { + "vrf_name": "default", + "instance":"1", + "lsp_refresh_interval": "600", + "spf_minimum_interval": "5" + } + ] + } + } + }, + "ISIS_LEVELS_INCORRECT_MUST_MAX_REFRESH": { + "sonic-isis:sonic-isis": { + "sonic-isis:ISIS_LEVELS": { + "ISIS_LEVELS_LIST": [ + { + "vrf_name": "default", + "instance":"1", + "level_number": "2", + "lsp_refresh_interval": "600", + "lsp_maximum_lifetime": "700", + "lsp_generation_interval": "30", + "spf_minimum_interval": "5" + } + ] + } + } + }, + "ISIS_LEVELS_INCORRECT_MUST_GEN_REFRESH": { + "sonic-isis:sonic-isis": { + "sonic-isis:ISIS_LEVELS": { + "ISIS_LEVELS_LIST": [ + { + "vrf_name": "default", + "instance":"1", + "level_number": "2", + "lsp_refresh_interval": "50", + "lsp_maximum_lifetime": "900", + "lsp_generation_interval": "100", + "spf_minimum_interval": "5" + } + ] + } + } + }, + "ISIS_INTERFACE_TABLE": { + "sonic-port:sonic-port": { + "sonic-port:PORT": { + "PORT_LIST": [ + { + "admin_status": "up", + "alias": "eth8", + "description": "Ethernet2", + "lanes": "65", + "mtu": 9000, + "name": "Ethernet2", + "speed": 25000 + } + ] + } + }, + "sonic-isis:sonic-isis": { + "sonic-isis:ISIS_GLOBAL": { + "ISIS_GLOBAL_LIST": [ + { + "vrf_name": "default", + "instance":"1", + "net": "49.0001.1040.4400.0249.00" + } + ] + }, + "sonic-isis:ISIS_INTERFACE": { + "ISIS_INTERFACE_LIST": [ + { + "instance":"1", + "ifname": "Ethernet2", + "ipv4_routing_instance": "1", + "ipv6_routing_instance": "1", + "passive": "false", + "hello_padding": "true", + "network_type": "POINT_TO_POINT", + "authentication_type": "TEXT", + "authentication_key": "password", + "enable_bfd": "true", + "bfd_profile": "PROFILE", + "metric": "5000", + "csnp_interval": "15", + "psnp_interval": "2", + "hello_interval": "5", + "hello_multiplier": "10" + } + ] + } + } + }, + "ISIS_INTERFACE_INCORRECT_VALUE_PASSIVE": { + "sonic-port:sonic-port": { + "sonic-port:PORT": { + "PORT_LIST": [ + { + "admin_status": "up", + "alias": "eth8", + "description": "Ethernet2", + "lanes": "65", + "mtu": 9000, + "name": "Ethernet2", + "speed": 25000 + } + ] + } + }, + "sonic-isis:sonic-isis": { + "sonic-isis:ISIS_GLOBAL": { + "ISIS_GLOBAL_LIST": [ + { + "vrf_name": "default", + "instance":"1", + "net": "49.0001.1040.4400.0249.00" + } + ] + }, + "sonic-isis:ISIS_INTERFACE": { + "ISIS_INTERFACE_LIST": [ + { + "instance":"1", + "ifname": "Ethernet2", + "ipv4_routing_instance": "1", + "ipv6_routing_instance": "1", + "passive": "1" + } + ] + } + } + }, + "ISIS_INTERFACE_INCORRECT_VALUE_NETWORK_TYPE": { + "sonic-port:sonic-port": { + "sonic-port:PORT": { + "PORT_LIST": [ + { + "admin_status": "up", + "alias": "eth2", + "description": "Ethernet2", + "lanes": "65", + "mtu": 9000, + "name": "Ethernet2", + "speed": 25000 + } + ] + } + }, + "sonic-isis:sonic-isis": { + "sonic-isis:ISIS_GLOBAL": { + "ISIS_GLOBAL_LIST": [ + { + "vrf_name": "default", + "instance":"1", + "net": "49.0001.1040.4400.0249.00" + } + ] + }, + "sonic-isis:ISIS_INTERFACE": { + "ISIS_INTERFACE_LIST": [ + { + "instance":"1", + "ifname": "Ethernet2", + "ipv4_routing_instance": "1", + "ipv6_routing_instance": "1", + "network_type": "NETWORK" + } + ] + } + } + }, + "ISIS_INTERFACE_INCORRECT_VALUE_AUTHENTICATION_TYPE": { + "sonic-port:sonic-port": { + "sonic-port:PORT": { + "PORT_LIST": [ + { + "admin_status": "up", + "alias": "eth2", + "description": "Ethernet2", + "lanes": "65", + "mtu": 9000, + "name": "Ethernet2", + "speed": 25000 + } + ] + } + }, + "sonic-isis:sonic-isis": { + "sonic-isis:ISIS_GLOBAL": { + "ISIS_GLOBAL_LIST": [ + { + "vrf_name": "default", + "instance":"1", + "net": "49.0001.1040.4400.0249.00" + } + ] + }, + "sonic-isis:ISIS_INTERFACE": { + "ISIS_INTERFACE_LIST": [ + { + "instance":"1", + "ifname": "Ethernet2", + "ipv4_routing_instance": "1", + "ipv6_routing_instance": "1", + "authentication_type": "sha1" + } + ] + } + } + }, + "ISIS_INTERFACE_INVALID_MUST_AUTHENTICATION_TYPE": { + "sonic-port:sonic-port": { + "sonic-port:PORT": { + "PORT_LIST": [ + { + "admin_status": "up", + "alias": "eth2", + "description": "Ethernet2", + "lanes": "65", + "mtu": 9000, + "name": "Ethernet2", + "speed": 25000 + } + ] + } + }, + "sonic-isis:sonic-isis": { + "sonic-isis:ISIS_GLOBAL": { + "ISIS_GLOBAL_LIST": [ + { + "vrf_name": "default", + "instance":"1", + "net": "49.0001.1040.4400.0249.00" + } + ] + }, + "sonic-isis:ISIS_INTERFACE": { + "ISIS_INTERFACE_LIST": [ + { + "instance":"1", + "ifname": "Ethernet2", + "ipv4_routing_instance": "1", + "ipv6_routing_instance": "1", + "authentication_type": "TEXT" + } + ] + } + } + }, + "ISIS_INTERFACE_INCORRECT_VALUE_METRIC": { + "sonic-port:sonic-port": { + "sonic-port:PORT": { + "PORT_LIST": [ + { + "admin_status": "up", + "alias": "eth2", + "description": "Ethernet2", + "lanes": "65", + "mtu": 9000, + "name": "Ethernet2", + "speed": 25000 + } + ] + } + }, + "sonic-isis:sonic-isis": { + "sonic-isis:ISIS_LEVELS": { + "ISIS_LEVELS_LIST": [ + { + "vrf_name": "default", + "instance":"1", + "level_number": "2", + "spf_minimum_interval": "5" + } + ] + }, + "sonic-isis:ISIS_INTERFACE": { + "ISIS_INTERFACE_LIST": [ + { + "instance":"1", + "ifname": "Ethernet2", + "ipv6_routing_instance": "1", + "metric": "str" + } + ] + } + } + }, + "ISIS_INTERFACE_INCORRECT_VALUE_HELLO_INTERVAL": { + "sonic-port:sonic-port": { + "sonic-port:PORT": { + "PORT_LIST": [ + { + "admin_status": "up", + "alias": "eth2", + "description": "Ethernet2", + "lanes": "65", + "mtu": 9000, + "name": "Ethernet2", + "speed": 25000 + } + ] + } + }, + "sonic-isis:sonic-isis": { + "sonic-isis:ISIS_LEVELS": { + "ISIS_LEVELS_LIST": [ + { + "vrf_name": "default", + "instance":"1", + "level_number": "2", + "spf_minimum_interval": "5" + } + ] + }, + "sonic-isis:ISIS_INTERFACE": { + "ISIS_INTERFACE_LIST": [ + { + "instance":"1", + "ifname": "Ethernet2", + "ipv4_routing_instance": "1", + "hello_interval": "800" + } + ] + } + } + }, + "ISIS_INTERFACE_MISSING_KEY": { + "sonic-port:sonic-port": { + "sonic-port:PORT": { + "PORT_LIST": [ + { + "admin_status": "up", + "alias": "eth2", + "description": "Ethernet2", + "lanes": "65", + "mtu": 9000, + "name": "Ethernet2", + "speed": 25000 + } + ] + } + }, + "sonic-isis:sonic-isis": { + "sonic-isis:ISIS_LEVELS": { + "ISIS_LEVELS_LIST": [ + { + "vrf_name": "default", + "instance":"1", + "level_number": "2", + "spf_minimum_interval": "5" + } + ] + }, + "sonic-isis:ISIS_INTERFACE": { + "ISIS_INTERFACE_LIST": [ + { + "instance":"1", + "ipv4_routing_instance": "1", + "ipv6_routing_instance": "1", + "passive": "false", + "hello_padding": "true", + "network_type": "POINT_TO_POINT", + "enable_bfd": "true", + "bfd_profile": "PROFILE", + "metric": "5000", + "csnp_interval": "15", + "psnp_interval": "2", + "hello_interval": "5", + "hello_multiplier": "10" + } + ] + } + } + }, + "ISIS_INTERFACE_INSTANCE_MUST": { + "sonic-port:sonic-port": { + "sonic-port:PORT": { + "PORT_LIST": [ + { + "admin_status": "up", + "alias": "eth2", + "description": "Ethernet2", + "lanes": "65", + "mtu": 9000, + "name": "Ethernet2", + "speed": 25000 + } + ] + } + }, + "sonic-isis:sonic-isis": { + "sonic-isis:ISIS_INTERFACE": { + "ISIS_INTERFACE_LIST": [ + { + "instance":"1", + "ifname": "Ethernet2", + "ipv4_routing_instance": "1", + "ipv6_routing_instance": "1", + "passive": "false", + "hello_padding": "true", + "network_type": "POINT_TO_POINT", + "enable_bfd": "true", + "bfd_profile": "PROFILE", + "metric": "5000", + "csnp_interval": "15", + "psnp_interval": "2", + "hello_interval": "5", + "hello_multiplier": "10" + } + ] + } + } + } +} diff --git a/src/sonic-yang-models/yang-models/sonic-isis.yang b/src/sonic-yang-models/yang-models/sonic-isis.yang new file mode 100644 index 000000000000..f5cbb7df8488 --- /dev/null +++ b/src/sonic-yang-models/yang-models/sonic-isis.yang @@ -0,0 +1,532 @@ + +module sonic-isis { + + namespace "http://github.com/Azure/sonic-isis"; + + prefix "s-isis"; + + yang-version 1.1; + + import sonic-vrf { + prefix vrf; + } + + import sonic-port { + prefix port; + } + + import sonic-portchannel { + prefix lag; + } + + import sonic-loopback-interface { + prefix lo; + } + + organization + "SONiC"; + + contact + "SONiC"; + + description + "Intermediate System to Intermediate System Protocol"; + + revision 2023-03-16 { + description "Initial revision."; + } + + identity AUTH_MODE { + description + "Base identify to define the authentication mode"; + } + + identity TEXT { + base AUTH_MODE; + description + "Simple Text Authentication"; + reference "RFC1195"; + } + + identity MD5 { + base AUTH_MODE; + description + "HMAC-MD5 Authentication"; + reference "RFC5304"; + } + + typedef circuit-type { + type enumeration { + enum POINT_TO_POINT { + description + "This enum describes a point-to-point interface"; + } + enum BROADCAST { + description + "This enum describes a broadcast interface"; + } + } + description + "This type defines IS-IS interface types "; + } + + typedef net { + type string { + pattern '[a-fA-F0-9]{2}(\.[a-fA-F0-9]{4}){3,9}\.[a-fA-F0-9]{2}'; + } + description + "This type defines OSI NET address. A NET should should be in + the form xx.yyyy.yyyy.yyyy.00 with up to 9 sets of yyyy."; + } + + typedef level-type { + type enumeration { + enum LEVEL_1 { + description + "This enum describes IS-IS level 1"; + } + enum LEVEL_2 { + description + "This enum describes IS-IS level 2"; + } + enum LEVEL_1_2 { + description + "This enum describes IS-IS level 1-2"; + } + } + description + "This type defines IS-IS level types"; + } + + grouping isis-authentication { + leaf authentication_key { + type string { + length "1..254"; + } + must "(../authentication_type or not(../authentication_key))" { + error-message + "If authentication_key is specified, then authentication_type must also be specified."; + } + description + "Authentication password."; + } + + leaf authentication_type { + type identityref { + base AUTH_MODE; + } + must "(../authentication_key or not(../authentication_type))" { + error-message + "If authentication_type is specified, then authentication_key must also be specified."; + } + description + "This grouping defines keychain configuration type (TEXT, MD5)."; + } + } + + + container sonic-isis { + + container ISIS_GLOBAL { + + list ISIS_GLOBAL_LIST { + + max-elements "1"; + + key "vrf_name instance"; + + leaf vrf_name { + type union { + type string { + pattern "default"; + } + type leafref { + path "/vrf:sonic-vrf/vrf:VRF/vrf:VRF_LIST/vrf:name"; + } + } + must "not(../../../ISIS_LEVELS/ISIS_LEVELS_LIST) or (../../../ISIS_LEVELS/ISIS_LEVELS_LIST[vrf_name=current()/../vrf_name])" { + error-message + "The value of ISIS_GLOBAL 'vrf_name' must be the same as 'vrf_name' in ISIS_LEVELS."; + } + description + "VRF name"; + } + + leaf instance { + type string; + description + "The identifier for this instance of IS-IS. Area-tag"; + must "not(../../../ISIS_LEVELS/ISIS_LEVELS_LIST) or (../../../ISIS_LEVELS/ISIS_LEVELS_LIST[instance=current()/../instance])" { + error-message + "The value of ISIS_GLOBAL 'instance' must be the same as 'instance' in ISIS_LEVELS."; + } + } + + leaf net { + type net; + description + "IS-IS OSI network entity title (NET) address."; + } + + leaf level_capability { + type level-type; + default "LEVEL_1_2"; + description + "IS-IS level capability (LEVEL_1, LEVEL_2, LEVEL_1_2)."; + } + + leaf dynamic_hostname { + type boolean; + default "true"; + description + "Dynamic hostname support for IS-IS."; + } + + leaf attach_send { + type boolean; + default "true"; + description + "For an L1 or L2 router, attached bits are sent in an LSP when set to true."; + } + + leaf attach_receive_ignore { + type boolean; + default "false"; + description + "For an L1 router, attached bits received in an LSP create a default route when set to false"; + } + + leaf set_overload_bit { + type boolean; + default "false"; + description + "Administratively enable the overload bit."; + } + + leaf lsp_mtu_size { + type uint16 { + range "128..4352"; + } + default "1497"; + description + "LSP MTU."; + } + + leaf spf_init_delay { + type uint16 { + range "0..60000"; + } + units "msec"; + must "../spf_short_delay and ../spf_long_delay and ../spf_hold_down and ../spf_time_to_learn or not(../spf_init_delay)" { + error-message + "SPF init delay must only be specified if all other SPF parameters are specified"; + } + description + "Delay used during QUIET state"; + } + + leaf spf_short_delay { + type uint16 { + range "0..60000"; + } + units "msec"; + must "../spf_init_delay and ../spf_long_delay and ../spf_hold_down and ../spf_time_to_learn or not(../spf_short_delay)" { + error-message + "SPF short delay must only be specified if all other SPF parameters are specified"; + } + description + "Delay used during SHORT_WAIT state"; + } + + leaf spf_long_delay { + type uint16 { + range "0..60000"; + } + units "msec"; + must "../spf_init_delay and ../spf_short_delay and ../spf_hold_down and ../spf_time_to_learn or not(../spf_long_delay)" { + error-message + "SPF long delay must only be specified if all other SPF parameters are specified"; + } + description + "Delay used during LONG_WAIT state"; + } + + leaf spf_hold_down { + type uint16 { + range "0..60000"; + } + units "msec"; + must "../spf_init_delay and ../spf_short_delay and ../spf_long_delay and ../spf_time_to_learn or not(../spf_hold_down)" { + error-message + "SPF hold down must only be specified if all other SPF parameters are specified"; + } + description + "Period of time without IGP events before considering IGP stable"; + } + + leaf spf_time_to_learn { + type uint16 { + range "0..60000"; + } + units "msec"; + must "../spf_init_delay and ../spf_short_delay and ../spf_long_delay and ../spf_hold_down or not(../spf_time_to_learn)" { + error-message + "SPF time_to_learn must only be specified if all other SPF parameters are specified"; + } + description + "Maximum time needed to learn all of the events related to a failure"; + } + + leaf log_adjacency_changes { + type boolean; + default "false"; + description + "Log changes to this instance's IS-IS adjacencies."; + } + + } // list ISIS_GLOBAL_LIST + + } // container ISIS_GLOBAL + + container ISIS_LEVELS { + + list ISIS_LEVELS_LIST { + + description + "Configuration parameters related to a particular level within the + IS-IS protocol instance"; + + key "vrf_name instance level_number"; + + leaf vrf_name { + type union { + type string { + pattern "default"; + } + type leafref { + path "/vrf:sonic-vrf/vrf:VRF/vrf:VRF_LIST/vrf:name"; + } + } + must "not(../../../ISIS_GLOBAL/ISIS_GLOBAL_LIST) or (../../../ISIS_GLOBAL/ISIS_GLOBAL_LIST[vrf_name=current()/../vrf_name])" { + error-message + "The value of ISIS_LEVELS 'vrf_name' must be the same as 'vrf_name' in ISIS_GLOBAL."; + } + description + "VRF name"; + } + + leaf instance { + type string; + must "not(../../../ISIS_GLOBAL/ISIS_GLOBAL_LIST) or (../../../ISIS_GLOBAL/ISIS_GLOBAL_LIST[instance=current()/../instance])" { + error-message + "The value of ISIS_LEVELS 'instance' must be the same as 'instance' in ISIS_GLOBAL."; + } + description + "The identifier for this instance of IS-IS. Area-tag"; + } + + leaf level_number { + type uint8 { + range "1..2"; + } + description + "IS-IS level number (1..2)."; + } + + leaf lsp_refresh_interval { + type uint16; + units "seconds"; + default "900"; + description + "LSP refresh interval."; + } + + leaf lsp_maximum_lifetime { + type uint16 { + range "350..65535"; + } + units "seconds"; + must "(. >= ../lsp_refresh_interval + 300)" { + error-message + "lsp_maximum_lifetime must be at least 300 seconds greater than lsp_refresh_interval"; + } + default "1200"; + description + "Maximum LSP lifetime."; + } + + leaf lsp_generation_interval { + type uint16 { + range "1..120"; + } + units "seconds"; + must "(. < ../lsp_refresh_interval)" { + error-message + "lsp_generation_interval must be greater than lsp_refresh_interval"; + } + default "30"; + description + "Minimum time before an LSP retransmissions."; + } + + leaf spf_minimum_interval { + type uint16 { + range "1..120"; + } + units "seconds"; + default "1"; + description + "Minimum time between consecutive SPFs."; + } + + } // list ISIS_LEVELS_LIST + + } // container ISIS_LEVELS + + container ISIS_INTERFACE { + + list ISIS_INTERFACE_LIST { + + description + "Configuration parameters related to a particular interface within the + IS-IS protocol instance"; + + key "instance ifname"; + + leaf instance { + type union { + type leafref { + path "../../../ISIS_GLOBAL/ISIS_GLOBAL_LIST/instance"; + } + type leafref { + path "../../../ISIS_LEVELS/ISIS_LEVELS_LIST/instance"; + } + } + description + "The identifier for this instance of IS-IS. Area-tag"; + } + + leaf ifname { + type union { + type leafref { + path "/port:sonic-port/port:PORT/port:PORT_LIST/port:name"; + } + type leafref { + path "/lag:sonic-portchannel/lag:PORTCHANNEL/lag:PORTCHANNEL_LIST/lag:name"; + } + type leafref { + path "/lo:sonic-loopback-interface/lo:LOOPBACK_INTERFACE/lo:LOOPBACK_INTERFACE_LIST/lo:name"; + } + } + description + "Interface for which IS-IS configuration is to be applied."; + } + + leaf ipv4_routing_instance { + type leafref { + path "../../../ISIS_GLOBAL/ISIS_GLOBAL_LIST/instance"; + } + description + "Routing IS-IS IPv4 traffic over this interface for the given instance."; + } + + leaf ipv6_routing_instance { + type leafref { + path "../../../ISIS_GLOBAL/ISIS_GLOBAL_LIST/instance"; + } + description + "Routing IS-IS IPv6 traffic over this interface for the given instance."; + } + + leaf passive { + type boolean; + default "false"; + description + "When set to true, the referenced interface is a passive interface + such that it is not eligible to establish adjacencies with other + systems, but is advertised into the IS-IS topology."; + } + + leaf hello_padding { + type boolean; + default "true"; + description + "When true, padding is added to IS-IS hello PDUs."; + } + + leaf network_type { + type circuit-type; + description + "IS-IS interface type (POINT_TO_POINT, BROADCAST)."; + } + + leaf enable_bfd { + type boolean; + default "false"; + description + "Monitor IS-IS peers on this interface."; + } + + leaf bfd_profile { + type string; + description + "Set BFD to use a pre-configured profile."; + } + + leaf metric { + type uint32 { + range "0..16777215"; + } + default "0"; + description + "The metric value of this interface."; + } + + leaf csnp_interval { + type uint16 { + range "1..600"; + } + units "seconds"; + default "10"; + description + "Complete Sequence Number PDU (CSNP) generation interval."; + } + + leaf psnp_interval { + type uint16 { + range "1..120"; + } + units "seconds"; + default "2"; + description + "Partial Sequence Number PDU (PSNP) generation interval."; + } + + leaf hello_interval { + type uint32 { + range "1..600"; + } + units "seconds"; + default "3"; + description + "Hello interval between consecutive hello messages. Interval will depend on multiplier."; + } + + leaf hello_multiplier { + type uint16 { + range "2..100"; + } + default "10"; + description + "Multiplier for the hello holding time."; + } + + uses isis-authentication; + + } // list ISIS_INTERFACE + + } // container ISIS_INTERFACE + + } // container sonic-isis + +} //module sonic-isis