diff --git a/doc/user/isisd.rst b/doc/user/isisd.rst index 200d00821f..1155b49eb1 100644 --- a/doc/user/isisd.rst +++ b/doc/user/isisd.rst @@ -418,8 +418,8 @@ Showing ISIS information Show topology IS-IS paths to Intermediate Systems, globally, in area (level-1) or domain (level-2). -.. index:: show ip route isis -.. clicmd:: show ip route isis +.. index:: show isis route [level-1|level-2] +.. clicmd:: show isis route [level-1|level-2] Show the ISIS routing table, as determined by the most recent SPF calculation. diff --git a/isisd/fabricd.c b/isisd/fabricd.c index ebaf14461e..1a081bbea6 100644 --- a/isisd/fabricd.c +++ b/isisd/fabricd.c @@ -221,7 +221,10 @@ struct fabricd *fabricd_new(struct isis_area *area) rv->area = area; rv->initial_sync_state = FABRICD_SYNC_PENDING; - rv->spftree = isis_spftree_new(area); + rv->spftree = + isis_spftree_new(area, &area->lspdb[IS_LEVEL_2 - 1], + area->isis->sysid, ISIS_LEVEL2, SPFTREE_IPV4, + SPF_TYPE_FORWARD, F_SPFTREE_HOPCOUNT_METRIC); rv->neighbors = skiplist_new(0, neighbor_entry_list_cmp, neighbor_entry_del_void); rv->neighbors_neighbors = hash_create(neighbor_entry_hash_key, diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c index af5258846a..f7cdd58f72 100644 --- a/isisd/isis_adjacency.c +++ b/isisd/isis_adjacency.c @@ -43,7 +43,6 @@ #include "isisd/isis_dynhn.h" #include "isisd/isis_pdu.h" #include "isisd/isis_lsp.h" -#include "isisd/isis_spf.h" #include "isisd/isis_events.h" #include "isisd/isis_mt.h" #include "isisd/isis_tlvs.h" @@ -152,9 +151,6 @@ void isis_delete_adj(void *arg) if (adj->adj_state != ISIS_ADJ_DOWN) adj->adj_state = ISIS_ADJ_DOWN; - /* remove from SPF trees */ - spftree_area_adj_del(adj->circuit->area, adj); - hook_call(isis_adj_state_change_hook, adj); XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->area_addresses); diff --git a/isisd/isis_dynhn.c b/isisd/isis_dynhn.c index e34c59be11..244f388c26 100644 --- a/isisd/isis_dynhn.c +++ b/isisd/isis_dynhn.c @@ -49,11 +49,23 @@ void dyn_cache_init(struct isis *isis) { if (dyn_cache == NULL) dyn_cache = list_new(); - thread_add_timer(master, dyn_cache_cleanup, isis, 120, - &isis->t_dync_clean); + if (!CHECK_FLAG(im->options, F_ISIS_UNIT_TEST)) + thread_add_timer(master, dyn_cache_cleanup, isis, 120, + &isis->t_dync_clean); return; } +void dyn_cache_cleanup_all(void) +{ + struct listnode *node, *nnode; + struct isis_dynhn *dyn; + + for (ALL_LIST_ELEMENTS(dyn_cache, node, nnode, dyn)) { + list_delete_node(dyn_cache, node); + XFREE(MTYPE_ISIS_DYNHN, dyn); + } +} + static int dyn_cache_cleanup(struct thread *thread) { struct listnode *node, *nnode; diff --git a/isisd/isis_dynhn.h b/isisd/isis_dynhn.h index 2cfc43fc17..973fde8307 100644 --- a/isisd/isis_dynhn.h +++ b/isisd/isis_dynhn.h @@ -31,6 +31,7 @@ struct isis_dynhn { }; void dyn_cache_init(struct isis *isis); +void dyn_cache_cleanup_all(void); void isis_dynhn_insert(const uint8_t *id, const char *hostname, int level); void isis_dynhn_remove(const uint8_t *id); struct isis_dynhn *dynhn_find_by_id(const uint8_t *id); diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 90c7c0efb5..1af6f417dc 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -2046,6 +2046,160 @@ static int lsp_handle_adj_state_change(struct isis_adjacency *adj) return 0; } +/* + * Iterate over all IP reachability TLVs in a LSP (all fragments) of the given + * address-family and MT-ID. + */ +int isis_lsp_iterate_ip_reach(struct isis_lsp *lsp, int family, uint16_t mtid, + lsp_ip_reach_iter_cb cb, void *arg) +{ + bool pseudo_lsp = LSP_PSEUDO_ID(lsp->hdr.lsp_id); + struct isis_lsp *frag; + struct listnode *node; + + if (lsp->hdr.seqno == 0 || lsp->hdr.rem_lifetime == 0) + return LSP_ITER_CONTINUE; + + /* Parse main LSP. */ + if (lsp->tlvs) { + if (!fabricd && !pseudo_lsp && family == AF_INET + && mtid == ISIS_MT_IPV4_UNICAST) { + struct isis_item_list *reachs[] = { + &lsp->tlvs->oldstyle_ip_reach, + &lsp->tlvs->oldstyle_ip_reach_ext}; + + for (unsigned int i = 0; i < array_size(reachs); i++) { + struct isis_oldstyle_ip_reach *r; + + for (r = (struct isis_oldstyle_ip_reach *) + reachs[i] + ->head; + r; r = r->next) { + bool external = i ? true : false; + + if ((*cb)((struct prefix *)&r->prefix, + r->metric, external, NULL, + arg) + == LSP_ITER_STOP) + return LSP_ITER_STOP; + } + } + } + + if (!pseudo_lsp && family == AF_INET) { + struct isis_item_list *ipv4_reachs; + + if (mtid == ISIS_MT_IPV4_UNICAST) + ipv4_reachs = &lsp->tlvs->extended_ip_reach; + else + ipv4_reachs = isis_lookup_mt_items( + &lsp->tlvs->mt_ip_reach, mtid); + + struct isis_extended_ip_reach *r; + for (r = ipv4_reachs ? (struct isis_extended_ip_reach *) + ipv4_reachs->head + : NULL; + r; r = r->next) { + if ((*cb)((struct prefix *)&r->prefix, + r->metric, false, r->subtlvs, arg) + == LSP_ITER_STOP) + return LSP_ITER_STOP; + } + } + + if (!pseudo_lsp && family == AF_INET6) { + struct isis_item_list *ipv6_reachs; + struct isis_ipv6_reach *r; + + if (mtid == ISIS_MT_IPV4_UNICAST) + ipv6_reachs = &lsp->tlvs->ipv6_reach; + else + ipv6_reachs = isis_lookup_mt_items( + &lsp->tlvs->mt_ipv6_reach, mtid); + + for (r = ipv6_reachs ? (struct isis_ipv6_reach *) + ipv6_reachs->head + : NULL; + r; r = r->next) { + if ((*cb)((struct prefix *)&r->prefix, + r->metric, r->external, r->subtlvs, + arg) + == LSP_ITER_STOP) + return LSP_ITER_STOP; + } + } + } + + /* Parse LSP fragments. */ + for (ALL_LIST_ELEMENTS_RO(lsp->lspu.frags, node, frag)) { + if (!frag->tlvs) + continue; + + isis_lsp_iterate_ip_reach(frag, family, mtid, cb, arg); + } + + return LSP_ITER_CONTINUE; +} + +/* + * Iterate over all IS reachability TLVs in a LSP (all fragments) of the given + * MT-ID. + */ +int isis_lsp_iterate_is_reach(struct isis_lsp *lsp, uint16_t mtid, + lsp_is_reach_iter_cb cb, void *arg) +{ + bool pseudo_lsp = LSP_PSEUDO_ID(lsp->hdr.lsp_id); + struct isis_lsp *frag; + struct listnode *node; + struct isis_item *head; + struct isis_item_list *te_neighs; + + if (lsp->hdr.seqno == 0 || lsp->hdr.rem_lifetime == 0) + return LSP_ITER_CONTINUE; + + /* Parse main LSP. */ + if (lsp->tlvs) { + if (pseudo_lsp || mtid == ISIS_MT_IPV4_UNICAST) { + head = lsp->tlvs->oldstyle_reach.head; + for (struct isis_oldstyle_reach *reach = + (struct isis_oldstyle_reach *)head; + reach; reach = reach->next) { + if ((*cb)(reach->id, reach->metric, true, NULL, + arg) + == LSP_ITER_STOP) + return LSP_ITER_STOP; + } + } + + if (pseudo_lsp || mtid == ISIS_MT_IPV4_UNICAST) + te_neighs = &lsp->tlvs->extended_reach; + else + te_neighs = + isis_get_mt_items(&lsp->tlvs->mt_reach, mtid); + if (te_neighs) { + head = te_neighs->head; + for (struct isis_extended_reach *reach = + (struct isis_extended_reach *)head; + reach; reach = reach->next) { + if ((*cb)(reach->id, reach->metric, false, + reach->subtlvs, arg) + == LSP_ITER_STOP) + return LSP_ITER_STOP; + } + } + } + + /* Parse LSP fragments. */ + for (ALL_LIST_ELEMENTS_RO(lsp->lspu.frags, node, frag)) { + if (!frag->tlvs) + continue; + + isis_lsp_iterate_is_reach(frag, mtid, cb, arg); + } + + return LSP_ITER_CONTINUE; +} + void lsp_init(void) { hook_register(isis_adj_state_change_hook, diff --git a/isisd/isis_lsp.h b/isisd/isis_lsp.h index 6cbea47496..0783036e49 100644 --- a/isisd/isis_lsp.h +++ b/isisd/isis_lsp.h @@ -127,6 +127,26 @@ int lsp_print_all(struct vty *vty, struct lspdb_head *head, char detail, /* sets SRMflags for all active circuits of an lsp */ void lsp_set_all_srmflags(struct isis_lsp *lsp, bool set); +#define LSP_ITER_CONTINUE 0 +#define LSP_ITER_STOP -1 + +/* Callback used by isis_lsp_iterate_ip_reach() function. */ +struct isis_subtlvs; +typedef int (*lsp_ip_reach_iter_cb)(const struct prefix *prefix, + uint32_t metric, bool external, + struct isis_subtlvs *subtlvs, void *arg); + +/* Callback used by isis_lsp_iterate_is_reach() function. */ +typedef int (*lsp_is_reach_iter_cb)(const uint8_t *id, uint32_t metric, + bool oldmetric, + struct isis_ext_subtlvs *subtlvs, + void *arg); + +int isis_lsp_iterate_ip_reach(struct isis_lsp *lsp, int family, uint16_t mtid, + lsp_ip_reach_iter_cb cb, void *arg); +int isis_lsp_iterate_is_reach(struct isis_lsp *lsp, uint16_t mtid, + lsp_is_reach_iter_cb cb, void *arg); + #define lsp_flood(lsp, circuit) \ _lsp_flood((lsp), (circuit), __func__, __FILE__, __LINE__) void _lsp_flood(struct isis_lsp *lsp, struct isis_circuit *circuit, diff --git a/isisd/isis_main.c b/isisd/isis_main.c index ed4b206851..6352303c23 100644 --- a/isisd/isis_main.c +++ b/isisd/isis_main.c @@ -252,7 +252,7 @@ int main(int argc, char **argv, char **envp) #ifndef FABRICD isis_cli_init(); #endif /* ifdef FABRICD */ - isis_spf_cmds_init(); + isis_spf_init(); isis_redist_init(); isis_route_map_init(); isis_mpls_te_init(); diff --git a/isisd/isis_misc.c b/isisd/isis_misc.c index 3aedd8ba1f..6e9cbaf98e 100644 --- a/isisd/isis_misc.c +++ b/isisd/isis_misc.c @@ -437,7 +437,7 @@ struct in_addr newprefix2inaddr(uint8_t *prefix_start, uint8_t prefix_masklen) * Returns the dynamic hostname associated with the passed system ID. * If no dynamic hostname found then returns formatted system ID. */ -const char *print_sys_hostname(uint8_t *sysid) +const char *print_sys_hostname(const uint8_t *sysid) { struct isis_dynhn *dyn; struct isis *isis = NULL; @@ -447,8 +447,7 @@ const char *print_sys_hostname(uint8_t *sysid) /* For our system ID return our host name */ isis = isis_lookup_by_sysid(sysid); - - if (isis != NULL) + if (isis && !CHECK_FLAG(im->options, F_ISIS_UNIT_TEST)) return cmd_hostname_get(); dyn = dynhn_find_by_id(sysid); diff --git a/isisd/isis_misc.h b/isisd/isis_misc.h index c6a5832f33..5cdbbfb058 100644 --- a/isisd/isis_misc.h +++ b/isisd/isis_misc.h @@ -49,7 +49,7 @@ const char *time2string(uint32_t); const char *nlpid2str(uint8_t nlpid); /* typedef struct nlpids nlpids; */ char *nlpid2string(struct nlpids *); -const char *print_sys_hostname(uint8_t *sysid); +const char *print_sys_hostname(const uint8_t *sysid); void zlog_dump_data(void *data, int len); /* diff --git a/isisd/isis_route.c b/isisd/isis_route.c index 7b761f5cda..c83a7c04bb 100644 --- a/isisd/isis_route.c +++ b/isisd/isis_route.c @@ -46,6 +46,7 @@ #include "isis_pdu.h" #include "isis_lsp.h" #include "isis_spf.h" +#include "isis_spf_private.h" #include "isis_route.h" #include "isis_zebra.h" @@ -158,6 +159,17 @@ static void adjinfo2nexthop(int family, struct list *nexthops, } } +static void isis_route_add_dummy_nexthops(struct isis_route_info *rinfo, + const uint8_t *sysid) +{ + struct isis_nexthop *nh; + + nh = XCALLOC(MTYPE_ISIS_NEXTHOP, sizeof(struct isis_nexthop)); + memcpy(nh->sysid, sysid, sizeof(nh->sysid)); + isis_sr_nexthop_reset(&nh->sr); + listnode_add(rinfo->nexthops, nh); +} + static struct isis_route_info *isis_route_info_new(struct prefix *prefix, struct prefix_ipv6 *src_p, uint32_t cost, @@ -165,13 +177,25 @@ static struct isis_route_info *isis_route_info_new(struct prefix *prefix, struct list *adjacencies) { struct isis_route_info *rinfo; - struct isis_adjacency *adj; + struct isis_vertex_adj *vadj; struct listnode *node; rinfo = XCALLOC(MTYPE_ISIS_ROUTE_INFO, sizeof(struct isis_route_info)); rinfo->nexthops = list_new(); - for (ALL_LIST_ELEMENTS_RO(adjacencies, node, adj)) { + for (ALL_LIST_ELEMENTS_RO(adjacencies, node, vadj)) { + struct isis_spf_adj *sadj = vadj->sadj; + struct isis_adjacency *adj = sadj->adj; + + /* + * Create dummy nexthops when running SPF on a testing + * environment. + */ + if (CHECK_FLAG(im->options, F_ISIS_UNIT_TEST)) { + isis_route_add_dummy_nexthops(rinfo, sadj->id); + continue; + } + /* check for force resync this route */ if (CHECK_FLAG(adj->circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF)) diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index ebce86bed9..dd0a6ec824 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -29,6 +29,7 @@ #include "vty.h" #include "log.h" #include "command.h" +#include "termtable.h" #include "memory.h" #include "prefix.h" #include "if.h" @@ -56,6 +57,13 @@ #include "isis_spf_private.h" DEFINE_MTYPE_STATIC(ISISD, ISIS_SPF_RUN, "ISIS SPF Run Info"); +DEFINE_MTYPE_STATIC(ISISD, ISIS_SPF_ADJ, "ISIS SPF Adjacency"); +DEFINE_MTYPE_STATIC(ISISD, ISIS_VERTEX_ADJ, "ISIS SPF Vertex Adjacency"); + +static void spf_adj_list_parse_lsp(struct isis_spftree *spftree, + struct list *adj_list, struct isis_lsp *lsp, + const uint8_t *pseudo_nodeid, + uint32_t pseudo_metric); /* * supports the given af ? @@ -80,22 +88,29 @@ struct isis_spf_run { static void remove_excess_adjs(struct list *adjs) { struct listnode *node, *excess = NULL; - struct isis_adjacency *adj, *candidate = NULL; + struct isis_vertex_adj *vadj, *candidate = NULL; int comp; - for (ALL_LIST_ELEMENTS_RO(adjs, node, adj)) { + for (ALL_LIST_ELEMENTS_RO(adjs, node, vadj)) { + struct isis_adjacency *adj, *candidate_adj; + + adj = vadj->sadj->adj; + assert(adj); + if (excess == NULL) excess = node; candidate = listgetdata(excess); + candidate_adj = candidate->sadj->adj; - if (candidate->sys_type < adj->sys_type) { + if (candidate_adj->sys_type < adj->sys_type) { excess = node; continue; } - if (candidate->sys_type > adj->sys_type) + if (candidate_adj->sys_type > adj->sys_type) continue; - comp = memcmp(candidate->sysid, adj->sysid, ISIS_SYS_ID_LEN); + comp = memcmp(candidate_adj->sysid, adj->sysid, + ISIS_SYS_ID_LEN); if (comp > 0) { excess = node; continue; @@ -103,15 +118,15 @@ static void remove_excess_adjs(struct list *adjs) if (comp < 0) continue; - if (candidate->circuit->idx > adj->circuit->idx) { + if (candidate_adj->circuit->idx > adj->circuit->idx) { excess = node; continue; } - if (candidate->circuit->idx < adj->circuit->idx) + if (candidate_adj->circuit->idx < adj->circuit->idx) continue; - comp = memcmp(candidate->snpa, adj->snpa, ETH_ALEN); + comp = memcmp(candidate_adj->snpa, adj->snpa, ETH_ALEN); if (comp > 0) { excess = node; continue; @@ -155,7 +170,9 @@ static const char *vtype2string(enum vertextype vtype) const char *vid2string(struct isis_vertex *vertex, char *buff, int size) { if (VTYPE_IS(vertex->type) || VTYPE_ES(vertex->type)) { - return print_sys_hostname(vertex->N.id); + const char *hostname = print_sys_hostname(vertex->N.id); + strlcpy(buff, hostname, size); + return buff; } if (VTYPE_IP(vertex->type)) { @@ -168,6 +185,13 @@ const char *vid2string(struct isis_vertex *vertex, char *buff, int size) return "UNKNOWN"; } +static void isis_vertex_adj_free(void *arg) +{ + struct isis_vertex_adj *vadj = arg; + + XFREE(MTYPE_ISIS_VERTEX_ADJ, vadj); +} + static struct isis_vertex *isis_vertex_new(struct isis_spftree *spftree, void *id, enum vertextype vtype) @@ -179,9 +203,10 @@ static struct isis_vertex *isis_vertex_new(struct isis_spftree *spftree, isis_vertex_id_init(vertex, id, vtype); vertex->Adj_N = list_new(); + vertex->Adj_N->del = isis_vertex_adj_free; vertex->parents = list_new(); - if (spftree->hopcount_metric) { + if (CHECK_FLAG(spftree->flags, F_SPFTREE_HOPCOUNT_METRIC)) { vertex->firsthops = hash_create(isis_vertex_queue_hash_key, isis_vertex_queue_hash_cmp, NULL); @@ -190,21 +215,69 @@ static struct isis_vertex *isis_vertex_new(struct isis_spftree *spftree, return vertex; } +static struct isis_vertex_adj *isis_vertex_adj_add(struct isis_vertex *vertex, + struct isis_spf_adj *sadj) +{ + struct isis_vertex_adj *vadj; + + vadj = XCALLOC(MTYPE_ISIS_VERTEX_ADJ, sizeof(*vadj)); + vadj->sadj = sadj; + listnode_add(vertex->Adj_N, vadj); + + return vadj; +} + static void isis_vertex_adj_del(struct isis_vertex *vertex, struct isis_adjacency *adj) { + struct isis_vertex_adj *vadj; struct listnode *node, *nextnode; + if (!vertex) return; - for (node = listhead(vertex->Adj_N); node; node = nextnode) { - nextnode = listnextnode(node); - if (listgetdata(node) == adj) - list_delete_node(vertex->Adj_N, node); + + for (ALL_LIST_ELEMENTS(vertex->Adj_N, node, nextnode, vadj)) { + if (vadj->sadj->adj == adj) { + listnode_delete(vertex->Adj_N, vadj); + isis_vertex_adj_free(vadj); + } } return; } -struct isis_spftree *isis_spftree_new(struct isis_area *area) +bool isis_vertex_adj_exists(const struct isis_spftree *spftree, + const struct isis_vertex *vertex, + const struct isis_spf_adj *sadj) +{ + struct isis_vertex_adj *tmp; + struct listnode *node; + + for (ALL_LIST_ELEMENTS_RO(vertex->Adj_N, node, tmp)) { + if (CHECK_FLAG(spftree->flags, F_SPFTREE_NO_ADJACENCIES)) { + if (memcmp(sadj->id, tmp->sadj->id, sizeof(sadj->id)) + == 0) + return true; + } else { + if (sadj->adj == tmp->sadj->adj) + return true; + } + } + + return false; +} + +static void isis_spf_adj_free(void *arg) +{ + struct isis_spf_adj *sadj = arg; + + XFREE(MTYPE_ISIS_SPF_ADJ, sadj); +} + +struct isis_spftree *isis_spftree_new(struct isis_area *area, + struct lspdb_head *lspdb, + const uint8_t *sysid, int level, + enum spf_tree_id tree_id, + enum spf_type type, uint8_t flags) { struct isis_spftree *tree; @@ -214,15 +287,26 @@ struct isis_spftree *isis_spftree_new(struct isis_area *area) isis_vertex_queue_init(&tree->paths, "IS-IS SPF paths", false); tree->route_table = srcdest_table_init(); tree->area = area; + tree->lspdb = lspdb; + tree->sadj_list = list_new(); + tree->sadj_list->del = isis_spf_adj_free; tree->last_run_timestamp = 0; tree->last_run_monotime = 0; tree->last_run_duration = 0; tree->runcount = 0; + tree->type = type; + memcpy(tree->sysid, sysid, ISIS_SYS_ID_LEN); + tree->level = level; + tree->tree_id = tree_id; + tree->family = (tree->tree_id == SPFTREE_IPV4) ? AF_INET : AF_INET6; + tree->flags = flags; + return tree; } void isis_spftree_del(struct isis_spftree *spftree) { + list_delete(&spftree->sadj_list); isis_vertex_queue_free(&spftree->tents); isis_vertex_queue_free(&spftree->paths); route_table_finish(spftree->route_table); @@ -254,7 +338,10 @@ void spftree_area_init(struct isis_area *area) if (area->spftree[tree][level - 1]) continue; - area->spftree[tree][level - 1] = isis_spftree_new(area); + area->spftree[tree][level - 1] = + isis_spftree_new(area, &area->lspdb[level - 1], + area->isis->sysid, level, tree, + SPF_TYPE_FORWARD, 0); } } } @@ -273,8 +360,14 @@ void spftree_area_del(struct isis_area *area) } } -void spftree_area_adj_del(struct isis_area *area, struct isis_adjacency *adj) +static int spf_adj_state_change(struct isis_adjacency *adj) { + struct isis_area *area = adj->circuit->area; + + if (adj->adj_state == ISIS_ADJ_UP) + return 0; + + /* Remove adjacency from all SPF trees. */ for (int tree = SPFTREE_IPV4; tree < SPFTREE_COUNT; tree++) { for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) { if (!(area->is_type & level)) @@ -288,13 +381,15 @@ void spftree_area_adj_del(struct isis_area *area, struct isis_adjacency *adj) if (fabricd_spftree(area) != NULL) isis_spftree_adj_del(fabricd_spftree(area), adj); + + return 0; } /* * Find the system LSP: returns the LSP in our LSP database * associated with the given system ID. */ -static struct isis_lsp *isis_root_system_lsp(struct isis_area *area, int level, +static struct isis_lsp *isis_root_system_lsp(struct lspdb_head *lspdb, uint8_t *sysid) { struct isis_lsp *lsp; @@ -303,7 +398,7 @@ static struct isis_lsp *isis_root_system_lsp(struct isis_area *area, int level, memcpy(lspid, sysid, ISIS_SYS_ID_LEN); LSP_PSEUDO_ID(lspid) = 0; LSP_FRAGMENT(lspid) = 0; - lsp = lsp_search(&area->lspdb[level - 1], lspid); + lsp = lsp_search(lspdb, lspid); if (lsp && lsp->hdr.rem_lifetime != 0) return lsp; return NULL; @@ -312,28 +407,21 @@ static struct isis_lsp *isis_root_system_lsp(struct isis_area *area, int level, /* * Add this IS to the root of SPT */ -static struct isis_vertex *isis_spf_add_root(struct isis_spftree *spftree, - uint8_t *sysid) +static struct isis_vertex *isis_spf_add_root(struct isis_spftree *spftree) { struct isis_vertex *vertex; - struct isis_lsp *lsp; #ifdef EXTREME_DEBUG char buff[VID2STR_BUFFER]; #endif /* EXTREME_DEBUG */ - lsp = isis_root_system_lsp(spftree->area, spftree->level, sysid); - if (lsp == NULL) - zlog_warn("ISIS-Spf: could not find own l%d LSP!", - spftree->level); - - vertex = isis_vertex_new(spftree, sysid, + vertex = isis_vertex_new(spftree, spftree->sysid, spftree->area->oldmetric ? VTYPE_NONPSEUDO_IS : VTYPE_NONPSEUDO_TE_IS); isis_vertex_queue_append(&spftree->paths, vertex); #ifdef EXTREME_DEBUG - zlog_debug("ISIS-Spf: added this IS %s %s depth %d dist %d to PATHS", + zlog_debug("ISIS-Spf: added this IS %s %s depth %d dist %d to PATHS", vtype2string(vertex->type), vid2string(vertex, buff, sizeof(buff)), vertex->depth, vertex->d_N); @@ -368,12 +456,11 @@ static void vertex_update_firsthops(struct isis_vertex *vertex, static struct isis_vertex *isis_spf_add2tent(struct isis_spftree *spftree, enum vertextype vtype, void *id, uint32_t cost, int depth, - struct isis_adjacency *adj, + struct isis_spf_adj *sadj, struct isis_vertex *parent) { struct isis_vertex *vertex; struct listnode *node; - struct isis_adjacency *parent_adj; char buff[VID2STR_BUFFER]; vertex = isis_find_vertex(&spftree->paths, id, vtype); @@ -401,14 +488,16 @@ static struct isis_vertex *isis_spf_add2tent(struct isis_spftree *spftree, listnode_add(vertex->parents, parent); } - if (spftree->hopcount_metric) + if (CHECK_FLAG(spftree->flags, F_SPFTREE_HOPCOUNT_METRIC)) vertex_update_firsthops(vertex, parent); if (parent && parent->Adj_N && listcount(parent->Adj_N) > 0) { - for (ALL_LIST_ELEMENTS_RO(parent->Adj_N, node, parent_adj)) - listnode_add(vertex->Adj_N, parent_adj); - } else if (adj) { - listnode_add(vertex->Adj_N, adj); + struct isis_vertex_adj *parent_vadj; + + for (ALL_LIST_ELEMENTS_RO(parent->Adj_N, node, parent_vadj)) + isis_vertex_adj_add(vertex, parent_vadj->sadj); + } else if (sadj) { + isis_vertex_adj_add(vertex, sadj); } #ifdef EXTREME_DEBUG @@ -425,7 +514,7 @@ static struct isis_vertex *isis_spf_add2tent(struct isis_spftree *spftree, static void isis_spf_add_local(struct isis_spftree *spftree, enum vertextype vtype, void *id, - struct isis_adjacency *adj, uint32_t cost, + struct isis_spf_adj *sadj, uint32_t cost, struct isis_vertex *parent) { struct isis_vertex *vertex; @@ -435,10 +524,12 @@ static void isis_spf_add_local(struct isis_spftree *spftree, if (vertex) { /* C.2.5 c) */ if (vertex->d_N == cost) { - if (adj) - listnode_add(vertex->Adj_N, adj); + if (sadj) + isis_vertex_adj_add(vertex, sadj); /* d) */ - if (listcount(vertex->Adj_N) > ISIS_MAX_PATH_SPLITS) + if (!CHECK_FLAG(spftree->flags, + F_SPFTREE_NO_ADJACENCIES) + && listcount(vertex->Adj_N) > ISIS_MAX_PATH_SPLITS) remove_excess_adjs(vertex->Adj_N); if (parent && (listnode_lookup(vertex->parents, parent) == NULL)) @@ -454,7 +545,7 @@ static void isis_spf_add_local(struct isis_spftree *spftree, } } - isis_spf_add2tent(spftree, vtype, id, cost, 1, adj, parent); + isis_spf_add2tent(spftree, vtype, id, cost, 1, sadj, parent); return; } @@ -469,7 +560,7 @@ static void process_N(struct isis_spftree *spftree, enum vertextype vtype, assert(spftree && parent); - if (spftree->hopcount_metric + if (CHECK_FLAG(spftree->flags, F_SPFTREE_HOPCOUNT_METRIC) && !VTYPE_IS(vtype)) return; @@ -519,16 +610,20 @@ static void process_N(struct isis_spftree *spftree, enum vertextype vtype, #endif /* EXTREME_DEBUG */ if (vertex->d_N == dist) { struct listnode *node; - struct isis_adjacency *parent_adj; + struct isis_vertex_adj *parent_vadj; for (ALL_LIST_ELEMENTS_RO(parent->Adj_N, node, - parent_adj)) - if (listnode_lookup(vertex->Adj_N, parent_adj) - == NULL) - listnode_add(vertex->Adj_N, parent_adj); - if (spftree->hopcount_metric) + parent_vadj)) + if (!isis_vertex_adj_exists(spftree, vertex, + parent_vadj->sadj)) + isis_vertex_adj_add(vertex, + parent_vadj->sadj); + if (CHECK_FLAG(spftree->flags, + F_SPFTREE_HOPCOUNT_METRIC)) vertex_update_firsthops(vertex, parent); /* 2) */ - if (listcount(vertex->Adj_N) > ISIS_MAX_PATH_SPLITS) + if (!CHECK_FLAG(spftree->flags, + F_SPFTREE_NO_ADJACENCIES) + && listcount(vertex->Adj_N) > ISIS_MAX_PATH_SPLITS) remove_excess_adjs(vertex->Adj_N); if (listnode_lookup(vertex->parents, parent) == NULL) listnode_add(vertex->parents, parent); @@ -611,7 +706,9 @@ lspfragloop: /* C.2.6 a) */ /* Two way connectivity */ - if (!memcmp(r->id, root_sysid, ISIS_SYS_ID_LEN)) + if (!LSP_PSEUDO_ID(r->id) + && !memcmp(r->id, root_sysid, + ISIS_SYS_ID_LEN)) continue; if (!pseudo_lsp && !memcmp(r->id, null_sysid, @@ -640,12 +737,19 @@ lspfragloop: te_neighs->head : NULL; er; er = er->next) { - if (!memcmp(er->id, root_sysid, ISIS_SYS_ID_LEN)) + /* C.2.6 a) */ + /* Two way connectivity */ + if (!LSP_PSEUDO_ID(er->id) + && !memcmp(er->id, root_sysid, ISIS_SYS_ID_LEN)) continue; if (!pseudo_lsp && !memcmp(er->id, null_sysid, ISIS_SYS_ID_LEN)) continue; - dist = cost + (spftree->hopcount_metric ? 1 : er->metric); + dist = cost + + (CHECK_FLAG(spftree->flags, + F_SPFTREE_HOPCOUNT_METRIC) + ? 1 + : er->metric); process_N(spftree, LSP_PSEUDO_ID(er->id) ? VTYPE_PSEUDO_TE_IS : VTYPE_NONPSEUDO_TE_IS, @@ -759,236 +863,311 @@ lspfragloop: return ISIS_OK; } -static int isis_spf_preload_tent(struct isis_spftree *spftree, - uint8_t *root_sysid, - struct isis_vertex *parent) +static struct isis_adjacency *adj_find(struct list *adj_list, const uint8_t *id, + int level, uint16_t mtid, int family) { - struct isis_circuit *circuit; - struct listnode *cnode, *anode, *ipnode; struct isis_adjacency *adj; - struct isis_lsp *lsp; - struct list *adj_list; - struct list *adjdb; - struct prefix_ipv4 *ipv4; - struct prefix_pair ip_info; - int retval = ISIS_OK; - uint8_t lsp_id[ISIS_SYS_ID_LEN + 2]; - static uint8_t null_lsp_id[ISIS_SYS_ID_LEN + 2]; - struct prefix_ipv6 *ipv6; - struct isis_circuit_mt_setting *circuit_mt; + struct listnode *node; - for (ALL_LIST_ELEMENTS_RO(spftree->area->circuit_list, cnode, - circuit)) { - circuit_mt = circuit_lookup_mt_setting(circuit, spftree->mtid); - if (circuit_mt && !circuit_mt->enabled) + for (ALL_LIST_ELEMENTS_RO(adj_list, node, adj)) { + if (!(adj->level & level)) continue; - if (circuit->state != C_STATE_UP) + if (memcmp(adj->sysid, id, ISIS_SYS_ID_LEN) != 0) continue; - if (!(circuit->is_type & spftree->level)) + if (adj->adj_state != ISIS_ADJ_UP) continue; - if (spftree->family == AF_INET && !circuit->ip_router) + if (!adj_has_mt(adj, mtid)) continue; - if (spftree->family == AF_INET6 && !circuit->ipv6_router) + if (mtid == ISIS_MT_IPV4_UNICAST + && !speaks(adj->nlpids.nlpids, adj->nlpids.count, family)) continue; - /* - * Add IP(v6) addresses of this circuit - */ - if (spftree->family == AF_INET && !spftree->hopcount_metric) { - memset(&ip_info, 0, sizeof(ip_info)); - ip_info.dest.family = AF_INET; - for (ALL_LIST_ELEMENTS_RO(circuit->ip_addrs, ipnode, - ipv4)) { - ip_info.dest.u.prefix4 = ipv4->prefix; - ip_info.dest.prefixlen = ipv4->prefixlen; - apply_mask(&ip_info.dest); - isis_spf_add_local(spftree, - VTYPE_IPREACH_INTERNAL, - &ip_info, NULL, 0, parent); + return adj; + } + + return NULL; +} + +struct spf_preload_tent_ip_reach_args { + struct isis_spftree *spftree; + struct isis_vertex *parent; +}; + +static int isis_spf_preload_tent_ip_reach_cb(const struct prefix *prefix, + uint32_t metric, bool external, + struct isis_subtlvs *subtlvs, + void *arg) +{ + struct spf_preload_tent_ip_reach_args *args = arg; + struct isis_spftree *spftree = args->spftree; + struct isis_vertex *parent = args->parent; + struct prefix_pair ip_info; + enum vertextype vtype; + + if (external) + return LSP_ITER_CONTINUE; + + assert(spftree->family == prefix->family); + memset(&ip_info, 0, sizeof(ip_info)); + prefix_copy(&ip_info.dest, prefix); + apply_mask(&ip_info.dest); + + if (prefix->family == AF_INET) + vtype = VTYPE_IPREACH_INTERNAL; + else + vtype = VTYPE_IP6REACH_INTERNAL; + + isis_spf_add_local(spftree, vtype, &ip_info, NULL, 0, parent); + + return LSP_ITER_CONTINUE; +} + +static void isis_spf_preload_tent(struct isis_spftree *spftree, + uint8_t *root_sysid, + struct isis_lsp *root_lsp, + struct isis_vertex *parent) +{ + struct spf_preload_tent_ip_reach_args ip_reach_args; + struct isis_spf_adj *sadj; + struct listnode *node; + + if (!CHECK_FLAG(spftree->flags, F_SPFTREE_HOPCOUNT_METRIC)) { + ip_reach_args.spftree = spftree; + ip_reach_args.parent = parent; + isis_lsp_iterate_ip_reach( + root_lsp, spftree->family, spftree->mtid, + isis_spf_preload_tent_ip_reach_cb, &ip_reach_args); + } + + /* Iterate over adjacencies. */ + for (ALL_LIST_ELEMENTS_RO(spftree->sadj_list, node, sadj)) { + uint32_t metric; + + metric = CHECK_FLAG(spftree->flags, F_SPFTREE_HOPCOUNT_METRIC) + ? 1 + : sadj->metric; + if (!LSP_PSEUDO_ID(sadj->id)) { + isis_spf_add_local(spftree, + CHECK_FLAG(sadj->flags, + F_ISIS_SPF_ADJ_OLDMETRIC) + ? VTYPE_NONPSEUDO_IS + : VTYPE_NONPSEUDO_TE_IS, + sadj->id, sadj, metric, parent); + } else if (sadj->lan.lsp_pseudo) { + isis_spf_process_lsp(spftree, sadj->lan.lsp_pseudo, + metric, 0, spftree->sysid, parent); + } + } +} + +struct spf_adj_find_reverse_metric_args { + const uint8_t *id_self; + uint32_t reverse_metric; +}; + +static int spf_adj_find_reverse_metric_cb(const uint8_t *id, uint32_t metric, + bool oldmetric, + struct isis_ext_subtlvs *subtlvs, + void *arg) +{ + struct spf_adj_find_reverse_metric_args *args = arg; + + if (memcmp(id, args->id_self, ISIS_SYS_ID_LEN)) + return LSP_ITER_CONTINUE; + + args->reverse_metric = metric; + + return LSP_ITER_STOP; +} + +/* + * Change all SPF adjacencies to use the link cost in the direction from the + * next hop back towards root in place of the link cost in the direction away + * from root towards the next hop. + */ +static void spf_adj_get_reverse_metrics(struct isis_spftree *spftree) +{ + struct isis_spf_adj *sadj; + struct listnode *node, *nnode; + + for (ALL_LIST_ELEMENTS(spftree->sadj_list, node, nnode, sadj)) { + uint8_t lspid[ISIS_SYS_ID_LEN + 2]; + struct isis_lsp *lsp_adj; + const uint8_t *id_self; + struct spf_adj_find_reverse_metric_args args; + + /* Skip pseudonodes. */ + if (LSP_PSEUDO_ID(sadj->id)) + continue; + + /* Find LSP of the corresponding adjacency. */ + memcpy(lspid, sadj->id, ISIS_SYS_ID_LEN); + LSP_PSEUDO_ID(lspid) = 0; + LSP_FRAGMENT(lspid) = 0; + lsp_adj = lsp_search(spftree->lspdb, lspid); + if (lsp_adj == NULL || lsp_adj->hdr.rem_lifetime == 0) { + /* Delete one-way adjacency. */ + listnode_delete(spftree->sadj_list, sadj); + continue; + } + + /* Find root node in the LSP of the adjacent router. */ + if (CHECK_FLAG(sadj->flags, F_ISIS_SPF_ADJ_BROADCAST)) + id_self = sadj->lan.desig_is_id; + else + id_self = spftree->sysid; + args.id_self = id_self; + args.reverse_metric = UINT32_MAX; + isis_lsp_iterate_is_reach(lsp_adj, spftree->mtid, + spf_adj_find_reverse_metric_cb, + &args); + if (args.reverse_metric == UINT32_MAX) { + /* Delete one-way adjacency. */ + listnode_delete(spftree->sadj_list, sadj); + continue; + } + sadj->metric = args.reverse_metric; + } +} + +static void spf_adj_list_parse_tlv(struct isis_spftree *spftree, + struct list *adj_list, const uint8_t *id, + const uint8_t *desig_is_id, + uint32_t pseudo_metric, uint32_t metric, + bool oldmetric, + struct isis_ext_subtlvs *subtlvs) +{ + struct isis_spf_adj *sadj; + uint8_t flags = 0; + + /* Skip self in the pseudonode. */ + if (desig_is_id && !memcmp(id, spftree->sysid, ISIS_SYS_ID_LEN)) + return; + + sadj = XCALLOC(MTYPE_ISIS_SPF_ADJ, sizeof(*sadj)); + memcpy(sadj->id, id, sizeof(sadj->id)); + if (desig_is_id) { + memcpy(sadj->lan.desig_is_id, desig_is_id, + sizeof(sadj->lan.desig_is_id)); + SET_FLAG(flags, F_ISIS_SPF_ADJ_BROADCAST); + sadj->metric = pseudo_metric; + } else + sadj->metric = metric; + if (oldmetric) + SET_FLAG(flags, F_ISIS_SPF_ADJ_OLDMETRIC); + sadj->subtlvs = subtlvs; + sadj->flags = flags; + + /* Set real adjacency. */ + if (!CHECK_FLAG(spftree->flags, F_SPFTREE_NO_ADJACENCIES) + && !LSP_PSEUDO_ID(id)) { + struct isis_adjacency *adj; + + adj = adj_find(adj_list, id, spftree->level, spftree->mtid, + spftree->family); + if (!adj) { + XFREE(MTYPE_ISIS_SPF_ADJ, sadj); + return; + } + + listnode_delete(adj_list, adj); + sadj->adj = adj; + } + + /* Add adjacency to the list. */ + listnode_add(spftree->sadj_list, sadj); + + /* Parse pseudonode LSP too. */ + if (LSP_PSEUDO_ID(id)) { + uint8_t lspid[ISIS_SYS_ID_LEN + 2]; + struct isis_lsp *lsp_pseudo; + + memcpy(lspid, id, ISIS_SYS_ID_LEN + 1); + LSP_FRAGMENT(lspid) = 0; + lsp_pseudo = lsp_search(spftree->lspdb, lspid); + if (lsp_pseudo == NULL || lsp_pseudo->hdr.rem_lifetime == 0) { + zlog_warn( + "ISIS-Spf: No LSP found from root to L%d DR %s", + spftree->level, rawlspid_print(id)); + return; + } + + sadj->lan.lsp_pseudo = lsp_pseudo; + spf_adj_list_parse_lsp(spftree, adj_list, lsp_pseudo, id, + metric); + } +} + +static void spf_adj_list_parse_lsp(struct isis_spftree *spftree, + struct list *adj_list, struct isis_lsp *lsp, + const uint8_t *pseudo_nodeid, + uint32_t pseudo_metric) +{ + bool pseudo_lsp = LSP_PSEUDO_ID(lsp->hdr.lsp_id); + struct isis_lsp *frag; + struct listnode *node; + struct isis_item *head; + struct isis_item_list *te_neighs; + + if (lsp->hdr.seqno == 0 || lsp->hdr.rem_lifetime == 0) + return; + + /* Parse main LSP. */ + if (lsp->tlvs) { + if (pseudo_lsp || spftree->mtid == ISIS_MT_IPV4_UNICAST) { + head = lsp->tlvs->oldstyle_reach.head; + for (struct isis_oldstyle_reach *reach = + (struct isis_oldstyle_reach *)head; + reach; reach = reach->next) { + spf_adj_list_parse_tlv( + spftree, adj_list, reach->id, + pseudo_nodeid, pseudo_metric, + reach->metric, true, NULL); } } - if (spftree->family == AF_INET6 && !spftree->hopcount_metric) { - memset(&ip_info, 0, sizeof(ip_info)); - ip_info.dest.family = AF_INET6; - for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_non_link, - ipnode, ipv6)) { - ip_info.dest.u.prefix6 = ipv6->prefix; - ip_info.dest.prefixlen = ipv6->prefixlen; - apply_mask(&ip_info.dest); - isis_spf_add_local(spftree, - VTYPE_IP6REACH_INTERNAL, - &ip_info, NULL, 0, parent); + + if (pseudo_lsp || spftree->mtid == ISIS_MT_IPV4_UNICAST) + te_neighs = &lsp->tlvs->extended_reach; + else + te_neighs = isis_get_mt_items(&lsp->tlvs->mt_reach, + spftree->mtid); + if (te_neighs) { + head = te_neighs->head; + for (struct isis_extended_reach *reach = + (struct isis_extended_reach *)head; + reach; reach = reach->next) { + spf_adj_list_parse_tlv( + spftree, adj_list, reach->id, + pseudo_nodeid, pseudo_metric, + reach->metric, false, reach->subtlvs); } } - if (circuit->circ_type == CIRCUIT_T_BROADCAST) { - /* - * Add the adjacencies - */ - adj_list = list_new(); - adjdb = circuit->u.bc.adjdb[spftree->level - 1]; - isis_adj_build_up_list(adjdb, adj_list); - if (listcount(adj_list) == 0) { - list_delete(&adj_list); - if (IS_DEBUG_SPF_EVENTS) - zlog_debug( - "ISIS-Spf: no L%d adjacencies on circuit %s", - spftree->level, - circuit->interface->name); - continue; - } - for (ALL_LIST_ELEMENTS_RO(adj_list, anode, adj)) { - if (!adj_has_mt(adj, spftree->mtid)) - continue; - if (spftree->mtid == ISIS_MT_IPV4_UNICAST - && !speaks(adj->nlpids.nlpids, - adj->nlpids.count, - spftree->family)) - continue; - switch (adj->sys_type) { - case ISIS_SYSTYPE_ES: - memcpy(lsp_id, adj->sysid, - ISIS_SYS_ID_LEN); - LSP_PSEUDO_ID(lsp_id) = 0; - isis_spf_add_local( - spftree, VTYPE_ES, lsp_id, adj, - spftree->hopcount_metric ? 1 : - circuit->te_metric - [spftree->level - 1], - parent); - break; - case ISIS_SYSTYPE_IS: - case ISIS_SYSTYPE_L1_IS: - case ISIS_SYSTYPE_L2_IS: - memcpy(lsp_id, adj->sysid, - ISIS_SYS_ID_LEN); - LSP_PSEUDO_ID(lsp_id) = 0; - LSP_FRAGMENT(lsp_id) = 0; - isis_spf_add_local( - spftree, - spftree->area->oldmetric - ? VTYPE_NONPSEUDO_IS - : VTYPE_NONPSEUDO_TE_IS, - lsp_id, adj, - spftree->hopcount_metric ? 1 : - circuit->te_metric - [spftree->level - 1], - parent); - lsp = lsp_search( - &spftree->area->lspdb[spftree->level- 1], - lsp_id); - if (lsp == NULL - || lsp->hdr.rem_lifetime == 0) - zlog_warn( - "ISIS-Spf: No LSP %s found for IS adjacency L%d on %s (ID %u)", - rawlspid_print(lsp_id), - spftree->level, - circuit->interface->name, - circuit->circuit_id); - break; - case ISIS_SYSTYPE_UNKNOWN: - default: - zlog_warn( - "isis_spf_preload_tent unknown adj type"); - } - } - list_delete(&adj_list); - /* - * Add the pseudonode - */ - if (spftree->level == 1) - memcpy(lsp_id, circuit->u.bc.l1_desig_is, - ISIS_SYS_ID_LEN + 1); - else - memcpy(lsp_id, circuit->u.bc.l2_desig_is, - ISIS_SYS_ID_LEN + 1); - /* can happen during DR reboot */ - if (memcmp(lsp_id, null_lsp_id, ISIS_SYS_ID_LEN + 1) - == 0) { - if (IS_DEBUG_SPF_EVENTS) - zlog_debug( - "ISIS-Spf: No L%d DR on %s (ID %d)", - spftree->level, - circuit->interface->name, - circuit->circuit_id); - continue; - } - adj = isis_adj_lookup(lsp_id, adjdb); - /* if no adj, we are the dis or error */ - if (!adj && !circuit->u.bc.is_dr[spftree->level - 1]) { - zlog_warn( - "ISIS-Spf: No adjacency found from root to L%d DR %s on %s (ID %d)", - spftree->level, rawlspid_print(lsp_id), - circuit->interface->name, - circuit->circuit_id); - continue; - } - lsp = lsp_search( - &spftree->area->lspdb[spftree->level - 1], - lsp_id); - if (lsp == NULL || lsp->hdr.rem_lifetime == 0) { - zlog_warn( - "ISIS-Spf: No lsp (%p) found from root to L%d DR %s on %s (ID %d)", - (void *)lsp, spftree->level, - rawlspid_print(lsp_id), - circuit->interface->name, - circuit->circuit_id); - continue; - } - isis_spf_process_lsp(spftree, lsp, - spftree->hopcount_metric ? - 1 : circuit->te_metric[spftree->level - 1], - 0, root_sysid, parent); - } else if (circuit->circ_type == CIRCUIT_T_P2P) { - adj = circuit->u.p2p.neighbor; - if (!adj || adj->adj_state != ISIS_ADJ_UP) - continue; - if (!adj_has_mt(adj, spftree->mtid)) - continue; - switch (adj->sys_type) { - case ISIS_SYSTYPE_ES: - memcpy(lsp_id, adj->sysid, ISIS_SYS_ID_LEN); - LSP_PSEUDO_ID(lsp_id) = 0; - isis_spf_add_local( - spftree, VTYPE_ES, lsp_id, adj, - spftree->hopcount_metric ? 1 : - circuit->te_metric[spftree->level - 1], - parent); - break; - case ISIS_SYSTYPE_IS: - case ISIS_SYSTYPE_L1_IS: - case ISIS_SYSTYPE_L2_IS: - memcpy(lsp_id, adj->sysid, ISIS_SYS_ID_LEN); - LSP_PSEUDO_ID(lsp_id) = 0; - LSP_FRAGMENT(lsp_id) = 0; - if (spftree->mtid != ISIS_MT_IPV4_UNICAST - || speaks(adj->nlpids.nlpids, - adj->nlpids.count, - spftree->family)) - isis_spf_add_local( - spftree, - spftree->area->oldmetric - ? VTYPE_NONPSEUDO_IS - : VTYPE_NONPSEUDO_TE_IS, - lsp_id, adj, - spftree->hopcount_metric ? 1 : - circuit->te_metric - [spftree->level - 1], - parent); - break; - case ISIS_SYSTYPE_UNKNOWN: - default: - zlog_warn( - "isis_spf_preload_tent unknown adj type"); - break; - } - } else if (circuit->circ_type == CIRCUIT_T_LOOPBACK) { - continue; - } else { - zlog_warn("isis_spf_preload_tent unsupported media"); - retval = ISIS_WARNING; - } } - return retval; + /* Parse LSP fragments. */ + for (ALL_LIST_ELEMENTS_RO(lsp->lspu.frags, node, frag)) { + if (!frag->tlvs) + continue; + + spf_adj_list_parse_lsp(spftree, adj_list, frag, pseudo_nodeid, + pseudo_metric); + } +} + +static void isis_spf_build_adj_list(struct isis_spftree *spftree, + struct isis_lsp *lsp) +{ + struct list *adj_list = NULL; + + if (!CHECK_FLAG(spftree->flags, F_SPFTREE_NO_ADJACENCIES)) + adj_list = list_dup(spftree->area->adjacency_list); + + spf_adj_list_parse_lsp(spftree, adj_list, lsp, NULL, 0); + + if (!CHECK_FLAG(spftree->flags, F_SPFTREE_NO_ADJACENCIES)) + list_delete(&adj_list); + + if (spftree->type == SPF_TYPE_REVERSE) + spf_adj_get_reverse_metrics(spftree); } /* @@ -1011,10 +1190,10 @@ static void add_to_paths(struct isis_spftree *spftree, vertex->d_N); #endif /* EXTREME_DEBUG */ - if (VTYPE_IP(vertex->type)) { + if (VTYPE_IP(vertex->type) + && !CHECK_FLAG(spftree->flags, F_SPFTREE_NO_ROUTES)) { if (listcount(vertex->Adj_N) > 0) - isis_route_create(&vertex->N.ip.dest, - &vertex->N.ip.src, + isis_route_create(&vertex->N.ip.dest, &vertex->N.ip.src, vertex->d_N, vertex->depth, vertex->Adj_N, spftree->area, spftree->route_table); @@ -1028,18 +1207,14 @@ static void add_to_paths(struct isis_spftree *spftree, return; } -static void init_spt(struct isis_spftree *spftree, int mtid, int level, - int family, enum spf_tree_id tree_id, - bool hopcount_metric) +static void init_spt(struct isis_spftree *spftree, int mtid) { + /* Clear data from previous run. */ + list_delete_all_node(spftree->sadj_list); isis_vertex_queue_clear(&spftree->tents); isis_vertex_queue_clear(&spftree->paths); spftree->mtid = mtid; - spftree->level = level; - spftree->family = family; - spftree->tree_id = tree_id; - spftree->hopcount_metric = hopcount_metric; } static void isis_spf_loop(struct isis_spftree *spftree, @@ -1080,19 +1255,31 @@ struct isis_spftree *isis_run_hopcount_spf(struct isis_area *area, struct isis_spftree *spftree) { if (!spftree) - spftree = isis_spftree_new(area); - - init_spt(spftree, ISIS_MT_IPV4_UNICAST, ISIS_LEVEL2, - AF_INET, SPFTREE_IPV4, true); + spftree = isis_spftree_new(area, &area->lspdb[IS_LEVEL_2 - 1], + sysid, ISIS_LEVEL2, SPFTREE_IPV4, + SPF_TYPE_FORWARD, + F_SPFTREE_HOPCOUNT_METRIC); + init_spt(spftree, ISIS_MT_IPV4_UNICAST); if (!memcmp(sysid, area->isis->sysid, ISIS_SYS_ID_LEN)) { - /* If we are running locally, initialize with information from adjacencies */ - struct isis_vertex *root = isis_spf_add_root(spftree, sysid); - isis_spf_preload_tent(spftree, sysid, root); + struct isis_lsp *root_lsp; + struct isis_vertex *root_vertex; + + root_lsp = isis_root_system_lsp(spftree->lspdb, spftree->sysid); + if (root_lsp) { + /* + * If we are running locally, initialize with + * information from adjacencies + */ + root_vertex = isis_spf_add_root(spftree); + + isis_spf_preload_tent(spftree, sysid, root_lsp, + root_vertex); + } } else { - isis_vertex_queue_insert(&spftree->tents, isis_vertex_new( - spftree, sysid, - VTYPE_NONPSEUDO_TE_IS)); + isis_vertex_queue_insert( + &spftree->tents, + isis_vertex_new(spftree, sysid, VTYPE_NONPSEUDO_TE_IS)); } isis_spf_loop(spftree, sysid); @@ -1100,54 +1287,56 @@ struct isis_spftree *isis_run_hopcount_spf(struct isis_area *area, return spftree; } -static int isis_run_spf(struct isis_area *area, int level, - enum spf_tree_id tree_id, uint8_t *sysid) +void isis_run_spf(struct isis_spftree *spftree) { - int retval = ISIS_OK; + struct isis_lsp *root_lsp; struct isis_vertex *root_vertex; - struct isis_spftree *spftree = area->spftree[tree_id][level - 1]; struct timeval time_start; struct timeval time_end; + struct isis_mt_router_info *mt_router_info; uint16_t mtid = 0; /* Get time that can't roll backwards. */ monotime(&time_start); - int family = -1; - switch (tree_id) { + root_lsp = isis_root_system_lsp(spftree->lspdb, spftree->sysid); + if (root_lsp == NULL) { + zlog_err("ISIS-Spf: could not find own l%d LSP!", + spftree->level); + return; + } + + /* Get Multi-Topology ID. */ + switch (spftree->tree_id) { case SPFTREE_IPV4: - family = AF_INET; mtid = ISIS_MT_IPV4_UNICAST; break; case SPFTREE_IPV6: - family = AF_INET6; - mtid = isis_area_ipv6_topology(area); + mt_router_info = isis_tlvs_lookup_mt_router_info( + root_lsp->tlvs, ISIS_MT_IPV6_UNICAST); + if (mt_router_info) + mtid = ISIS_MT_IPV6_UNICAST; + else + mtid = ISIS_MT_IPV4_UNICAST; break; case SPFTREE_DSTSRC: - family = AF_INET6; mtid = ISIS_MT_IPV6_DSTSRC; break; case SPFTREE_COUNT: - assert(!"isis_run_spf should never be called with SPFTREE_COUNT as argument!"); - return ISIS_WARNING; + zlog_err( + "isis_run_spf should never be called with SPFTREE_COUNT as argument!"); + exit(1); } - assert(spftree); - assert(sysid); - /* * C.2.5 Step 0 */ - init_spt(spftree, mtid, level, family, tree_id, false); + init_spt(spftree, mtid); /* a) */ - root_vertex = isis_spf_add_root(spftree, sysid); + root_vertex = isis_spf_add_root(spftree); /* b) */ - retval = isis_spf_preload_tent(spftree, sysid, root_vertex); - if (retval != ISIS_OK) { - zlog_warn("ISIS-Spf: failed to load TENT SPF-root:%s", - print_sys_hostname(sysid)); - goto out; - } + isis_spf_build_adj_list(spftree, root_lsp); + isis_spf_preload_tent(spftree, spftree->sysid, root_lsp, root_vertex); /* * C.2.7 Step 2 @@ -1155,19 +1344,16 @@ static int isis_run_spf(struct isis_area *area, int level, if (!isis_vertex_queue_count(&spftree->tents) && (IS_DEBUG_SPF_EVENTS)) { zlog_warn("ISIS-Spf: TENT is empty SPF-root:%s", - print_sys_hostname(sysid)); + print_sys_hostname(spftree->sysid)); } - isis_spf_loop(spftree, sysid); -out: + isis_spf_loop(spftree, spftree->sysid); spftree->runcount++; spftree->last_run_timestamp = time(NULL); spftree->last_run_monotime = monotime(&time_end); spftree->last_run_duration = ((time_end.tv_sec - time_start.tv_sec) * 1000000) + (time_end.tv_usec - time_start.tv_usec); - - return retval; } void isis_spf_verify_routes(struct isis_area *area, struct isis_spftree **trees) @@ -1191,8 +1377,8 @@ static int isis_run_spf_cb(struct thread *thread) { struct isis_spf_run *run = THREAD_ARG(thread); struct isis_area *area = run->area; + struct isis_spftree *spftree; int level = run->level; - int retval = ISIS_OK; XFREE(MTYPE_ISIS_SPF_RUN, run); area->spf_timer[level - 1] = NULL; @@ -1210,15 +1396,21 @@ static int isis_run_spf_cb(struct thread *thread) zlog_debug("ISIS-Spf (%s) L%d SPF needed, periodic SPF", area->area_tag, level); - if (area->ip_circuits) - retval = isis_run_spf(area, level, SPFTREE_IPV4, - area->isis->sysid); - if (area->ipv6_circuits) - retval = isis_run_spf(area, level, SPFTREE_IPV6, - area->isis->sysid); - if (area->ipv6_circuits && isis_area_ipv6_dstsrc_enabled(area)) - retval = isis_run_spf(area, level, SPFTREE_DSTSRC, - area->isis->sysid); + if (area->ip_circuits) { + spftree = area->spftree[SPFTREE_IPV4][level - 1]; + memcpy(spftree->sysid, area->isis->sysid, ISIS_SYS_ID_LEN); + isis_run_spf(spftree); + } + if (area->ipv6_circuits) { + spftree = area->spftree[SPFTREE_IPV6][level - 1]; + memcpy(spftree->sysid, area->isis->sysid, ISIS_SYS_ID_LEN); + isis_run_spf(spftree); + } + if (area->ipv6_circuits && isis_area_ipv6_dstsrc_enabled(area)) { + spftree = area->spftree[SPFTREE_DSTSRC][level - 1]; + memcpy(spftree->sysid, area->isis->sysid, ISIS_SYS_ID_LEN); + isis_run_spf(spftree); + } isis_area_verify_routes(area); @@ -1232,7 +1424,7 @@ static int isis_run_spf_cb(struct thread *thread) fabricd_run_spf(area); - return retval; + return 0; } static struct isis_spf_run *isis_run_spf_arg(struct isis_area *area, int level) @@ -1252,6 +1444,9 @@ int _isis_spf_schedule(struct isis_area *area, int level, time_t now = monotime(NULL); int diff = now - spftree->last_run_monotime; + if (CHECK_FLAG(im->options, F_ISIS_UNIT_TEST)) + return 0; + assert(diff >= 0); assert(area->is_type & level); @@ -1331,7 +1526,7 @@ static void isis_print_paths(struct vty *vty, struct isis_vertex_queue *queue, int rows = 0; struct listnode *anode = listhead(vertex->Adj_N); struct listnode *pnode = listhead(vertex->parents); - struct isis_adjacency *adj; + struct isis_vertex_adj *vadj; struct isis_vertex *pvertex; vty_out(vty, "%-20s %-12s %-6u ", @@ -1342,10 +1537,10 @@ static void isis_print_paths(struct vty *vty, struct isis_vertex_queue *queue, vertex->parents ? listcount(vertex->parents) : 0); i++) { if (anode) { - adj = listgetdata(anode); + vadj = listgetdata(anode); anode = anode->next; } else { - adj = NULL; + vadj = NULL; } if (pnode) { @@ -1360,14 +1555,18 @@ static void isis_print_paths(struct vty *vty, struct isis_vertex_queue *queue, vty_out(vty, "%-20s %-12s %-6s ", "", "", ""); } - if (adj) { + if (vadj) { + struct isis_spf_adj *sadj = vadj->sadj; + vty_out(vty, "%-20s %-9s ", - print_sys_hostname(adj->sysid), - adj->circuit->interface->name); + print_sys_hostname(sadj->id), + sadj->adj ? sadj->adj->circuit + ->interface->name + : "-"); } if (pvertex) { - if (!adj) + if (!vadj) vty_out(vty, "%-20s %-9s ", "", ""); vty_out(vty, "%s(%d)", @@ -1381,13 +1580,14 @@ static void isis_print_paths(struct vty *vty, struct isis_vertex_queue *queue, } } -static void isis_print_spftree(struct vty *vty, int level, - struct isis_area *area, - enum spf_tree_id tree_id) +void isis_print_spftree(struct vty *vty, struct isis_spftree *spftree) { const char *tree_id_text = NULL; - switch (tree_id) { + if (!spftree || !isis_vertex_queue_count(&spftree->paths)) + return; + + switch (spftree->tree_id) { case SPFTREE_IPV4: tree_id_text = "that speak IP"; break; @@ -1402,16 +1602,9 @@ static void isis_print_spftree(struct vty *vty, int level, return; } - if (!area->spftree[tree_id][level - 1] - || !isis_vertex_queue_count( - &area->spftree[tree_id][level - 1]->paths)) - return; - - vty_out(vty, "IS-IS paths to level-%d routers %s\n", - level, tree_id_text); - isis_print_paths(vty, &area->spftree[tree_id][level - 1]->paths, - area->isis->sysid); - + vty_out(vty, "IS-IS paths to level-%d routers %s\n", spftree->level, + tree_id_text); + isis_print_paths(vty, &spftree->paths, spftree->sysid); vty_out(vty, "\n"); } @@ -1433,16 +1626,19 @@ static void show_isis_topology_common(struct vty *vty, int levels, continue; if (area->ip_circuits > 0) { - isis_print_spftree(vty, level, area, - SPFTREE_IPV4); + isis_print_spftree( + vty, + area->spftree[SPFTREE_IPV4][level - 1]); } if (area->ipv6_circuits > 0) { - isis_print_spftree(vty, level, area, - SPFTREE_IPV6); + isis_print_spftree( + vty, + area->spftree[SPFTREE_IPV6][level - 1]); } if (isis_area_ipv6_dstsrc_enabled(area)) { - isis_print_spftree(vty, level, area, - SPFTREE_DSTSRC); + isis_print_spftree(vty, + area->spftree[SPFTREE_DSTSRC] + [level - 1]); } } @@ -1474,7 +1670,7 @@ DEFUN(show_isis_topology, show_isis_topology_cmd, ) { int levels = ISIS_LEVELS; - struct listnode *inode, *nnode; + struct listnode *node; struct isis *isis = NULL; int idx = 0; const char *vrf_name = VRF_DEFAULT_NAME; @@ -1498,10 +1694,9 @@ DEFUN(show_isis_topology, show_isis_topology_cmd, if (vrf_name) { if (all_vrf) { - for (ALL_LIST_ELEMENTS(im->isis, nnode, inode, isis)) { + for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) show_isis_topology_common(vty, levels, isis); - } - return 0; + return CMD_SUCCESS; } isis = isis_lookup_by_vrfname(vrf_name); if (isis != NULL) @@ -1511,9 +1706,199 @@ DEFUN(show_isis_topology, show_isis_topology_cmd, return CMD_SUCCESS; } -void isis_spf_cmds_init(void) +void isis_print_routes(struct vty *vty, struct isis_spftree *spftree) +{ + struct ttable *tt; + struct route_node *rn; + const char *tree_id_text = NULL; + + if (!spftree) + return; + + switch (spftree->tree_id) { + case SPFTREE_IPV4: + tree_id_text = "IPv4"; + break; + case SPFTREE_IPV6: + tree_id_text = "IPv6"; + break; + case SPFTREE_DSTSRC: + tree_id_text = "IPv6 (dst-src routing)"; + break; + case SPFTREE_COUNT: + assert(!"isis_print_routes shouldn't be called with SPFTREE_COUNT as type"); + return; + } + + vty_out(vty, "IS-IS %s %s routing table:\n\n", + circuit_t2string(spftree->level), tree_id_text); + + /* Prepare table. */ + tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]); + ttable_add_row(tt, "Prefix|Metric|Interface|Nexthop|Label(s)"); + tt->style.cell.rpad = 2; + tt->style.corner = '+'; + ttable_restyle(tt); + ttable_rowseps(tt, 0, BOTTOM, true, '-'); + + for (rn = route_top(spftree->route_table); rn; rn = route_next(rn)) { + struct isis_route_info *rinfo; + struct isis_nexthop *nexthop; + struct listnode *node; + bool first = true; + char buf_prefix[BUFSIZ]; + + rinfo = rn->info; + if (!rinfo) + continue; + + (void)prefix2str(&rn->p, buf_prefix, sizeof(buf_prefix)); + for (ALL_LIST_ELEMENTS_RO(rinfo->nexthops, node, nexthop)) { + struct interface *ifp; + char buf_iface[BUFSIZ]; + char buf_nhop[BUFSIZ]; + char buf_labels[BUFSIZ] = {}; + + if (!CHECK_FLAG(spftree->flags, + F_SPFTREE_NO_ADJACENCIES)) { + inet_ntop(nexthop->family, &nexthop->ip, + buf_nhop, sizeof(buf_nhop)); + ifp = if_lookup_by_index(nexthop->ifindex, + VRF_DEFAULT); + if (ifp) + strlcpy(buf_iface, ifp->name, + sizeof(buf_iface)); + else + snprintf(buf_iface, sizeof(buf_iface), + "ifindex %u", + nexthop->ifindex); + } else { + strlcpy(buf_nhop, + print_sys_hostname(nexthop->sysid), + sizeof(buf_nhop)); + strlcpy(buf_iface, "-", sizeof(buf_iface)); + } + + if (nexthop->sr.label != MPLS_INVALID_LABEL) + label2str(nexthop->sr.label, buf_labels, + sizeof(buf_labels)); + else + strlcpy(buf_labels, "-", sizeof(buf_labels)); + + if (first) { + ttable_add_row(tt, "%s|%u|%s|%s|%s", buf_prefix, + rinfo->cost, buf_iface, buf_nhop, + buf_labels); + first = false; + } else + ttable_add_row(tt, "||%s|%s|%s", buf_iface, + buf_nhop, buf_labels); + } + } + + /* Dump the generated table. */ + if (tt->nrows > 1) { + char *table; + + table = ttable_dump(tt, "\n"); + vty_out(vty, "%s\n", table); + XFREE(MTYPE_TMP, table); + } + ttable_del(tt); +} + +static void show_isis_route_common(struct vty *vty, int levels, + struct isis *isis) +{ + struct listnode *node; + struct isis_area *area; + + if (!isis->area_list || isis->area_list->count == 0) + return; + + for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { + vty_out(vty, "Area %s:\n", + area->area_tag ? area->area_tag : "null"); + + for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++) { + if ((level & levels) == 0) + continue; + + if (area->ip_circuits > 0) { + isis_print_routes( + vty, + area->spftree[SPFTREE_IPV4][level - 1]); + } + if (area->ipv6_circuits > 0) { + isis_print_routes( + vty, + area->spftree[SPFTREE_IPV6][level - 1]); + } + if (isis_area_ipv6_dstsrc_enabled(area)) { + isis_print_routes(vty, + area->spftree[SPFTREE_DSTSRC] + [level - 1]); + } + } + } +} + +DEFUN(show_isis_route, show_isis_route_cmd, + "show " PROTO_NAME + " [vrf ] route" +#ifndef FABRICD + " []" +#endif + , + SHOW_STR PROTO_HELP VRF_FULL_CMD_HELP_STR + "IS-IS routing table\n" +#ifndef FABRICD + "level-1 routes\n" + "level-2 routes\n" +#endif +) +{ + int levels; + struct isis *isis; + struct listnode *node; + const char *vrf_name = VRF_DEFAULT_NAME; + bool all_vrf = false; + int idx = 0; + + if (argv_find(argv, argc, "level-1", &idx)) + levels = ISIS_LEVEL1; + else if (argv_find(argv, argc, "level-2", &idx)) + levels = ISIS_LEVEL2; + else + levels = ISIS_LEVEL1 | ISIS_LEVEL2; + + if (!im) { + vty_out(vty, "IS-IS Routing Process not enabled\n"); + return CMD_SUCCESS; + } + ISIS_FIND_VRF_ARGS(argv, argc, idx, vrf_name, all_vrf); + + if (vrf_name) { + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) + show_isis_route_common(vty, levels, isis); + return CMD_SUCCESS; + } + isis = isis_lookup_by_vrfname(vrf_name); + if (isis != NULL) + show_isis_route_common(vty, levels, isis); + } + + return CMD_SUCCESS; +} + +void isis_spf_init(void) { install_element(VIEW_NODE, &show_isis_topology_cmd); + install_element(VIEW_NODE, &show_isis_route_cmd); + + /* Register hook(s). */ + hook_register(isis_adj_state_change_hook, spf_adj_state_change); } void isis_spf_print(struct isis_spftree *spftree, struct vty *vty) diff --git a/isisd/isis_spf.h b/isisd/isis_spf.h index 8bf9c9978a..b2dc23496f 100644 --- a/isisd/isis_spf.h +++ b/isisd/isis_spf.h @@ -26,21 +26,46 @@ struct isis_spftree; -struct isis_spftree *isis_spftree_new(struct isis_area *area); +enum spf_type { + SPF_TYPE_FORWARD = 1, + SPF_TYPE_REVERSE, +}; + +struct isis_spf_adj { + uint8_t id[ISIS_SYS_ID_LEN + 1]; + struct isis_adjacency *adj; + uint32_t metric; + struct isis_ext_subtlvs *subtlvs; + struct { + uint8_t desig_is_id[ISIS_SYS_ID_LEN + 1]; + struct isis_lsp *lsp_pseudo; + } lan; + uint8_t flags; +#define F_ISIS_SPF_ADJ_BROADCAST 0x01 +#define F_ISIS_SPF_ADJ_OLDMETRIC 0x02 +}; + +struct isis_spftree *isis_spftree_new(struct isis_area *area, + struct lspdb_head *lspdb, + const uint8_t *sysid, int level, + enum spf_tree_id tree_id, + enum spf_type type, uint8_t flags); void isis_spf_invalidate_routes(struct isis_spftree *tree); void isis_spf_verify_routes(struct isis_area *area, struct isis_spftree **trees); void isis_spftree_del(struct isis_spftree *spftree); void spftree_area_init(struct isis_area *area); void spftree_area_del(struct isis_area *area); -void spftree_area_adj_del(struct isis_area *area, struct isis_adjacency *adj); #define isis_spf_schedule(area, level) \ _isis_spf_schedule((area), (level), __func__, \ __FILE__, __LINE__) int _isis_spf_schedule(struct isis_area *area, int level, const char *func, const char *file, int line); -void isis_spf_cmds_init(void); +void isis_print_spftree(struct vty *vty, struct isis_spftree *spftree); +void isis_print_routes(struct vty *vty, struct isis_spftree *spftree); +void isis_spf_init(void); void isis_spf_print(struct isis_spftree *spftree, struct vty *vty); +void isis_run_spf(struct isis_spftree *spftree); struct isis_spftree *isis_run_hopcount_spf(struct isis_area *area, uint8_t *sysid, struct isis_spftree *spftree); diff --git a/isisd/isis_spf_private.h b/isisd/isis_spf_private.h index 05aae14b94..1e61bf0f48 100644 --- a/isisd/isis_spf_private.h +++ b/isisd/isis_spf_private.h @@ -50,6 +50,11 @@ struct prefix_pair { struct prefix_ipv6 src; }; +struct isis_vertex_adj { + struct isis_spf_adj *sadj; + struct mpls_label_stack *label_stack; +}; + /* * Triple */ @@ -180,6 +185,10 @@ static void isis_vertex_del(struct isis_vertex *vertex) XFREE(MTYPE_ISIS_VERTEX, vertex); } +bool isis_vertex_adj_exists(const struct isis_spftree *spftree, + const struct isis_vertex *vertex, + const struct isis_spf_adj *sadj); + __attribute__((__unused__)) static void isis_vertex_queue_clear(struct isis_vertex_queue *queue) { @@ -297,18 +306,26 @@ struct isis_spftree { struct isis_vertex_queue paths; /* the SPT */ struct isis_vertex_queue tents; /* TENT */ struct route_table *route_table; + struct lspdb_head *lspdb; /* link-state db */ + struct list *sadj_list; struct isis_area *area; /* back pointer to area */ unsigned int runcount; /* number of runs since uptime */ time_t last_run_timestamp; /* last run timestamp as wall time for display */ time_t last_run_monotime; /* last run as monotime for scheduling */ time_t last_run_duration; /* last run duration in msec */ + enum spf_type type; + uint8_t sysid[ISIS_SYS_ID_LEN]; uint16_t mtid; int family; int level; enum spf_tree_id tree_id; bool hopcount_metric; + uint8_t flags; }; +#define F_SPFTREE_HOPCOUNT_METRIC 0x01 +#define F_SPFTREE_NO_ROUTES 0x02 +#define F_SPFTREE_NO_ADJACENCIES 0x04 __attribute__((__unused__)) static void isis_vertex_id_init(struct isis_vertex *vertex, const void *id, @@ -347,8 +364,7 @@ static struct isis_lsp *lsp_for_vertex(struct isis_spftree *spftree, memcpy(lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1); LSP_FRAGMENT(lsp_id) = 0; - struct lspdb_head *lspdb = &spftree->area->lspdb[spftree->level - 1]; - struct isis_lsp *lsp = lsp_search(lspdb, lsp_id); + struct isis_lsp *lsp = lsp_search(spftree->lspdb, lsp_id); if (lsp && lsp->hdr.rem_lifetime != 0) return lsp; diff --git a/isisd/isis_sr.c b/isisd/isis_sr.c index bdbdc30b4a..d05afaa630 100644 --- a/isisd/isis_sr.c +++ b/isisd/isis_sr.c @@ -210,7 +210,7 @@ int isis_sr_cfg_srlb_update(struct isis_area *area, uint32_t lower_bound, uint32_t upper_bound) { struct isis_sr_db *srdb = &area->srdb; - struct listnode *node, *nnode; + struct listnode *node; struct sr_adjacency *sra; sr_debug("ISIS-Sr (%s): Update SRLB with new range [%u/%u]", @@ -236,7 +236,7 @@ int isis_sr_cfg_srlb_update(struct isis_area *area, uint32_t lower_bound, return -1; /* Reinstall local Adjacency-SIDs with new labels. */ - for (ALL_LIST_ELEMENTS(area->srdb.adj_sids, node, nnode, sra)) + for (ALL_LIST_ELEMENTS_RO(area->srdb.adj_sids, node, sra)) sr_adj_sid_update(sra, &srdb->srlb); /* Update and Flood LSP */ @@ -1521,13 +1521,13 @@ static void sr_adj_sid_add_single(struct isis_adjacency *adj, int family, /* Determine nexthop IP address */ switch (family) { case AF_INET: - if (!circuit->ip_router) + if (!circuit->ip_router || !adj->ipv4_address_count) return; nexthop.ipv4 = adj->ipv4_addresses[0]; break; case AF_INET6: - if (!circuit->ipv6_router) + if (!circuit->ipv6_router || !adj->ipv6_address_count) return; nexthop.ipv6 = adj->ipv6_addresses[0]; @@ -1986,7 +1986,7 @@ DEFUN(show_sr_prefix_sids, show_sr_prefix_sids_cmd, "Segment-Routing\n" "Segment-Routing Prefix-SIDs\n") { - struct listnode *node, *inode, *nnode; + struct listnode *node, *inode; struct isis_area *area; struct isis *isis = NULL; const char *vrf_name = VRF_DEFAULT_NAME; @@ -1996,7 +1996,7 @@ DEFUN(show_sr_prefix_sids, show_sr_prefix_sids_cmd, ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); if (vrf_name) { if (all_vrf) { - for (ALL_LIST_ELEMENTS(im->isis, nnode, inode, isis)) { + for (ALL_LIST_ELEMENTS_RO(im->isis, inode, isis)) { for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { vty_out(vty, "Area %s:\n", @@ -2084,11 +2084,11 @@ DEFUN(show_sr_node, show_sr_node_cmd, "Segment-Routing\n" "Segment-Routing node\n") { - struct listnode *node, *inode, *nnode; + struct listnode *node, *inode; struct isis_area *area; - struct isis *isis = NULL; + struct isis *isis; - for (ALL_LIST_ELEMENTS(im->isis, inode, nnode, isis)) { + for (ALL_LIST_ELEMENTS_RO(im->isis, inode, isis)) { for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { vty_out(vty, "Area %s:\n", area->area_tag ? area->area_tag : "null"); diff --git a/isisd/isis_te.c b/isisd/isis_te.c index 016f811a72..87c4428155 100644 --- a/isisd/isis_te.c +++ b/isisd/isis_te.c @@ -311,7 +311,7 @@ DEFUN(show_isis_mpls_te_router, MPLS_TE_STR "Router information\n") { - struct listnode *anode, *nnode, *inode; + struct listnode *anode, *inode; struct isis_area *area; struct isis *isis = NULL; const char *vrf_name = VRF_DEFAULT_NAME; @@ -325,7 +325,7 @@ DEFUN(show_isis_mpls_te_router, ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); if (vrf_name) { if (all_vrf) { - for (ALL_LIST_ELEMENTS(im->isis, nnode, inode, isis)) { + for (ALL_LIST_ELEMENTS_RO(im->isis, inode, isis)) { for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) { if (!IS_MPLS_TE(area->mta)) @@ -483,7 +483,7 @@ DEFUN (show_isis_mpls_te_interface, "Interface information\n" "Interface name\n") { - struct listnode *anode, *cnode, *nnode, *inode; + struct listnode *anode, *cnode, *inode; struct isis_area *area; struct isis_circuit *circuit; struct interface *ifp; @@ -497,7 +497,7 @@ DEFUN (show_isis_mpls_te_interface, if (argc == idx_interface) { /* Show All Interfaces. */ - for (ALL_LIST_ELEMENTS(im->isis, nnode, inode, isis)) { + for (ALL_LIST_ELEMENTS_RO(im->isis, inode, isis)) { for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) { diff --git a/isisd/isisd.c b/isisd/isisd.c index 0d39aba20b..aca98bf651 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -125,33 +125,37 @@ void isis_vrf_unlink(struct isis *isis, struct vrf *vrf) struct isis *isis_lookup_by_vrfid(vrf_id_t vrf_id) { - struct isis *isis = NULL; - struct listnode *node, *nnode; + struct isis *isis; + struct listnode *node; - for (ALL_LIST_ELEMENTS(im->isis, node, nnode, isis)) + for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) if (isis->vrf_id == vrf_id) return isis; + return NULL; } struct isis *isis_lookup_by_vrfname(const char *vrfname) { - struct isis *isis = NULL; - struct listnode *node, *nnode; + struct isis *isis; + struct listnode *node; - for (ALL_LIST_ELEMENTS(im->isis, node, nnode, isis)) + for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) if (isis->name && vrfname && strcmp(isis->name, vrfname) == 0) return isis; + return NULL; } -struct isis *isis_lookup_by_sysid(uint8_t *sysid) +struct isis *isis_lookup_by_sysid(const uint8_t *sysid) { - struct isis *isis = NULL; - struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS(im->isis, node, nnode, isis)) + struct isis *isis; + struct listnode *node; + + for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) if (!memcmp(isis->sysid, sysid, ISIS_SYS_ID_LEN)) return isis; + return NULL; } @@ -165,7 +169,7 @@ void isis_master_init(struct thread_master *master) void isis_global_instance_create() { - struct isis *isis = NULL; + struct isis *isis; isis = isis_lookup_by_vrfid(VRF_DEFAULT); if (isis == NULL) { @@ -176,8 +180,8 @@ void isis_global_instance_create() struct isis *isis_new(vrf_id_t vrf_id) { - struct vrf *vrf = NULL; - struct isis *isis = NULL; + struct vrf *vrf; + struct isis *isis; isis = XCALLOC(MTYPE_ISIS, sizeof(struct isis)); isis->vrf_id = vrf_id; @@ -214,6 +218,27 @@ struct isis_area *isis_area_create(const char *area_tag, const char *vrf_name) struct vrf *vrf = NULL; area = XCALLOC(MTYPE_ISIS_AREA, sizeof(struct isis_area)); + if (vrf_name) { + vrf = vrf_lookup_by_name(vrf_name); + if (vrf) { + isis = isis_lookup_by_vrfid(vrf->vrf_id); + if (isis == NULL) { + isis = isis_new(vrf->vrf_id); + isis_add(isis); + } + } else + return NULL; + } else { + isis = isis_lookup_by_vrfid(VRF_DEFAULT); + if (isis == NULL) { + isis = isis_new(VRF_DEFAULT); + isis_add(isis); + } + } + + listnode_add(isis->area_list, area); + area->isis = isis; + /* * Fabricd runs only as level-2. * For IS-IS, the default is level-1-2 @@ -237,7 +262,8 @@ struct isis_area *isis_area_create(const char *area_tag, const char *vrf_name) area->circuit_list = list_new(); area->adjacency_list = list_new(); area->area_addrs = list_new(); - thread_add_timer(master, lsp_tick, area, 1, &area->t_tick); + if (!CHECK_FLAG(im->options, F_ISIS_UNIT_TEST)) + thread_add_timer(master, lsp_tick, area, 1, &area->t_tick); flags_initialize(&area->flags); isis_sr_area_init(area); @@ -293,27 +319,6 @@ struct isis_area *isis_area_create(const char *area_tag, const char *vrf_name) area->area_tag = strdup(area_tag); - if (vrf_name) { - vrf = vrf_lookup_by_name(vrf_name); - if (vrf) { - isis = isis_lookup_by_vrfid(vrf->vrf_id); - if (isis == NULL) { - isis = isis_new(vrf->vrf_id); - isis_add(isis); - } - } else - return NULL; - } else { - isis = isis_lookup_by_vrfid(VRF_DEFAULT); - if (isis == NULL) { - isis = isis_new(VRF_DEFAULT); - isis_add(isis); - } - } - - listnode_add(isis->area_list, area); - area->isis = isis; - if (fabricd) area->fabricd = fabricd_new(area); @@ -335,7 +340,7 @@ struct isis_area *isis_area_lookup(const char *area_tag, vrf_id_t vrf_id) { struct isis_area *area; struct listnode *node; - struct isis *isis = NULL; + struct isis *isis; isis = isis_lookup_by_vrfid(vrf_id); if (isis == NULL) @@ -414,7 +419,8 @@ void isis_area_destroy(struct isis_area *area) spf_backoff_free(area->spf_delay_ietf[0]); spf_backoff_free(area->spf_delay_ietf[1]); - isis_redist_area_finish(area); + if (!CHECK_FLAG(im->options, F_ISIS_UNIT_TEST)) + isis_redist_area_finish(area); for (ALL_LIST_ELEMENTS(area->area_addrs, node, nnode, addr)) { list_delete_node(area->area_addrs, node); @@ -464,7 +470,7 @@ void isis_finish(struct isis *isis) void isis_terminate() { - struct isis *isis = NULL; + struct isis *isis; struct listnode *node, *nnode; if (listcount(im->isis) == 0) @@ -643,10 +649,10 @@ int area_clear_net_title(struct vty *vty, const char *net_title) int show_isis_interface_common(struct vty *vty, const char *ifname, char detail, const char *vrf_name, bool all_vrf) { - struct listnode *anode, *cnode, *mnode, *inode; + struct listnode *anode, *cnode, *inode; struct isis_area *area; struct isis_circuit *circuit; - struct isis *isis = NULL; + struct isis *isis; if (!im) { vty_out(vty, "IS-IS Routing Process not enabled\n"); @@ -654,7 +660,7 @@ int show_isis_interface_common(struct vty *vty, const char *ifname, char detail, } if (vrf_name) { if (all_vrf) { - for (ALL_LIST_ELEMENTS(im->isis, mnode, inode, isis)) { + for (ALL_LIST_ELEMENTS_RO(im->isis, inode, isis)) { for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) { vty_out(vty, "Area %s:\n", @@ -677,7 +683,7 @@ int show_isis_interface_common(struct vty *vty, const char *ifname, char detail, detail); } } - return 0; + return CMD_SUCCESS; } isis = isis_lookup_by_vrfname(vrf_name); if (isis != NULL) { @@ -822,10 +828,10 @@ static void isis_neighbor_common(struct vty *vty, const char *id, char detail, int show_isis_neighbor_common(struct vty *vty, const char *id, char detail, const char *vrf_name, bool all_vrf) { - struct listnode *nnode, *inode; + struct listnode *node; struct isis_dynhn *dynhn; uint8_t sysid[ISIS_SYS_ID_LEN]; - struct isis *isis = NULL; + struct isis *isis; if (!im) { vty_out(vty, "IS-IS Routing Process not enabled\n"); @@ -846,11 +852,11 @@ int show_isis_neighbor_common(struct vty *vty, const char *id, char detail, if (vrf_name) { if (all_vrf) { - for (ALL_LIST_ELEMENTS(im->isis, nnode, inode, isis)) { + for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) { isis_neighbor_common(vty, id, detail, isis, sysid); } - return 0; + return CMD_SUCCESS; } isis = isis_lookup_by_vrfname(vrf_name); if (isis != NULL) @@ -863,7 +869,7 @@ int show_isis_neighbor_common(struct vty *vty, const char *id, char detail, static void isis_neighbor_common_clear(struct vty *vty, const char *id, uint8_t *sysid, struct isis *isis) { - struct listnode *anode, *cnode, *cnextnode, *node, *nnode; + struct listnode *anode, *cnode, *node, *nnode; struct isis_area *area; struct isis_circuit *circuit; struct list *adjdb; @@ -871,8 +877,7 @@ static void isis_neighbor_common_clear(struct vty *vty, const char *id, int i; for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) { - for (ALL_LIST_ELEMENTS(area->circuit_list, cnode, cnextnode, - circuit)) { + for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode, circuit)) { if (circuit->circ_type == CIRCUIT_T_BROADCAST) { for (i = 0; i < 2; i++) { adjdb = circuit->u.bc.adjdb[i]; @@ -910,10 +915,10 @@ static void isis_neighbor_common_clear(struct vty *vty, const char *id, int clear_isis_neighbor_common(struct vty *vty, const char *id, const char *vrf_name, bool all_vrf) { - struct listnode *nnode, *inode; + struct listnode *node; struct isis_dynhn *dynhn; uint8_t sysid[ISIS_SYS_ID_LEN]; - struct isis *isis = NULL; + struct isis *isis; if (!im) { vty_out(vty, "IS-IS Routing Process not enabled\n"); @@ -933,11 +938,10 @@ int clear_isis_neighbor_common(struct vty *vty, const char *id, const char *vrf_ } if (vrf_name) { if (all_vrf) { - for (ALL_LIST_ELEMENTS(im->isis, nnode, inode, isis)) { + for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) isis_neighbor_common_clear(vty, id, sysid, isis); - } - return 0; + return CMD_SUCCESS; } isis = isis_lookup_by_vrfname(vrf_name); if (isis != NULL) @@ -1554,19 +1558,19 @@ DEFUN(show_hostname, show_hostname_cmd, "All VRFs\n" "IS-IS Dynamic hostname mapping\n") { - struct listnode *nnode, *inode; + struct listnode *node; const char *vrf_name = VRF_DEFAULT_NAME; bool all_vrf = false; int idx_vrf = 0; - struct isis *isis = NULL; + struct isis *isis; ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); if (vrf_name) { if (all_vrf) { - for (ALL_LIST_ELEMENTS(im->isis, nnode, inode, isis)) { + for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) dynhn_print_all(vty, isis); - } - return 0; + + return CMD_SUCCESS; } isis = isis_lookup_by_vrfname(vrf_name); if (isis != NULL) @@ -1621,8 +1625,8 @@ DEFUN(show_isis_spf_ietf, show_isis_spf_ietf_cmd, "All VRFs\n" "SPF delay IETF information\n") { - struct listnode *nnode, *inode; - struct isis *isis = NULL; + struct listnode *node; + struct isis *isis; int idx_vrf = 0; const char *vrf_name = VRF_DEFAULT_NAME; bool all_vrf = false; @@ -1636,10 +1640,10 @@ DEFUN(show_isis_spf_ietf, show_isis_spf_ietf_cmd, if (vrf_name) { if (all_vrf) { - for (ALL_LIST_ELEMENTS(im->isis, nnode, inode, isis)) { + for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) isis_spf_ietf_common(vty, isis); - } - return 0; + + return CMD_SUCCESS; } isis = isis_lookup_by_vrfname(vrf_name); if (isis != NULL) @@ -1755,9 +1759,9 @@ DEFUN(show_isis_summary, show_isis_summary_cmd, "All VRFs\n" "summary\n") { - struct listnode *inode, *nnode; + struct listnode *node; int idx_vrf = 0; - struct isis *isis = NULL; + struct isis *isis; const char *vrf_name = VRF_DEFAULT_NAME; bool all_vrf = false; @@ -1768,10 +1772,10 @@ DEFUN(show_isis_summary, show_isis_summary_cmd, } if (vrf_name) { if (all_vrf) { - for (ALL_LIST_ELEMENTS(im->isis, nnode, inode, isis)) { + for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) common_isis_summary(vty, isis); - } - return 0; + + return CMD_SUCCESS; } isis = isis_lookup_by_vrfname(vrf_name); if (isis != NULL) @@ -1844,60 +1848,61 @@ struct isis_lsp *lsp_for_arg(struct lspdb_head *head, const char *argv, return lsp; } -static int show_isis_database_common(struct vty *vty, const char *argv, - int ui_level, struct isis *isis) +void show_isis_database_lspdb(struct vty *vty, struct isis_area *area, + int level, struct lspdb_head *lspdb, + const char *argv, int ui_level) +{ + struct isis_lsp *lsp; + int lsp_count; + + if (lspdb_count(lspdb) > 0) { + lsp = lsp_for_arg(lspdb, argv, area->isis); + + if (lsp != NULL || argv == NULL) { + vty_out(vty, "IS-IS Level-%d link-state database:\n", + level + 1); + + /* print the title in all cases */ + vty_out(vty, + "LSP ID PduLen SeqNumber Chksum Holdtime ATT/P/OL\n"); + } + + if (lsp) { + if (ui_level == ISIS_UI_LEVEL_DETAIL) + lsp_print_detail(lsp, vty, area->dynhostname, + area->isis); + else + lsp_print(lsp, vty, area->dynhostname, + area->isis); + } else if (argv == NULL) { + lsp_count = + lsp_print_all(vty, lspdb, ui_level, + area->dynhostname, area->isis); + + vty_out(vty, " %u LSPs\n\n", lsp_count); + } + } +} + +static void show_isis_database_common(struct vty *vty, const char *argv, + int ui_level, struct isis *isis) { struct listnode *node; struct isis_area *area; - struct isis_lsp *lsp; - int level, lsp_count; + int level; if (isis->area_list->count == 0) - return CMD_SUCCESS; + return; for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { vty_out(vty, "Area %s:\n", area->area_tag ? area->area_tag : "null"); - for (level = 0; level < ISIS_LEVELS; level++) { - if (lspdb_count(&area->lspdb[level]) > 0) { - lsp = NULL; - lsp = lsp_for_arg(&area->lspdb[level], argv, - isis); - - if (lsp != NULL || argv == NULL) { - vty_out(vty, - "IS-IS Level-%d link-state database:\n", - level + 1); - - /* print the title in all cases */ - vty_out(vty, - "LSP ID PduLen SeqNumber Chksum Holdtime ATT/P/OL\n"); - } - - if (lsp) { - if (ui_level == ISIS_UI_LEVEL_DETAIL) - lsp_print_detail( - lsp, vty, - area->dynhostname, - isis); - else - lsp_print(lsp, vty, - area->dynhostname, - isis); - } else if (argv == NULL) { - lsp_count = lsp_print_all( - vty, &area->lspdb[level], - ui_level, area->dynhostname, - isis); - - vty_out(vty, " %u LSPs\n\n", - lsp_count); - } - } - } + for (level = 0; level < ISIS_LEVELS; level++) + show_isis_database_lspdb(vty, area, level, + &area->lspdb[level], argv, + ui_level); } - return CMD_SUCCESS; } /* * This function supports following display options: @@ -1918,19 +1923,19 @@ static int show_isis_database_common(struct vty *vty, const char *argv, static int show_isis_database(struct vty *vty, const char *argv, int ui_level, const char *vrf_name, bool all_vrf) { - struct listnode *inode, *nnode; - struct isis *isis = NULL; + struct listnode *node; + struct isis *isis; if (vrf_name) { if (all_vrf) { - for (ALL_LIST_ELEMENTS(im->isis, nnode, inode, isis)) { + for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) show_isis_database_common(vty, argv, ui_level, isis); - } - return 0; + + return CMD_SUCCESS; } isis = isis_lookup_by_vrfname(vrf_name); - if (isis != NULL) + if (isis) show_isis_database_common(vty, argv, ui_level, isis); } @@ -2352,16 +2357,15 @@ static int isis_config_write(struct vty *vty) { int write = 0; struct isis_area *area; - struct listnode *node, *node2, *inode, *nnode; - struct isis *isis = NULL; + struct listnode *node, *node2, *inode; + struct isis *isis; if (!im) { vty_out(vty, "IS-IS Routing Process not enabled\n"); return CMD_SUCCESS; } - for (ALL_LIST_ELEMENTS(im->isis, nnode, inode, isis)) { - + for (ALL_LIST_ELEMENTS_RO(im->isis, inode, isis)) { for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { /* ISIS - Area name */ vty_out(vty, "router " PROTO_NAME " %s\n", area->area_tag); diff --git a/isisd/isisd.h b/isisd/isisd.h index 41b69df2bf..0c0a1eed10 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -76,6 +76,7 @@ struct isis_master { /* Various OSPF global configuration. */ uint8_t options; }; +#define F_ISIS_UNIT_TEST 0x01 struct isis { vrf_id_t vrf_id; @@ -215,7 +216,7 @@ void isis_vrf_unlink(struct isis *isis, struct vrf *vrf); void isis_global_instance_create(void); struct isis *isis_lookup_by_vrfid(vrf_id_t vrf_id); struct isis *isis_lookup_by_vrfname(const char *vrfname); -struct isis *isis_lookup_by_sysid(uint8_t *sysid); +struct isis *isis_lookup_by_sysid(const uint8_t *sysid); void isis_init(void); struct isis *isis_new(vrf_id_t vrf_id); @@ -247,6 +248,9 @@ int isis_area_passwd_cleartext_set(struct isis_area *area, int level, const char *passwd, uint8_t snp_auth); int isis_area_passwd_hmac_md5_set(struct isis_area *area, int level, const char *passwd, uint8_t snp_auth); +void show_isis_database_lspdb(struct vty *vty, struct isis_area *area, + int level, struct lspdb_head *lspdb, + const char *argv, int ui_level); /* YANG paths */ #define ISIS_INSTANCE "/frr-isisd:isis/instance" diff --git a/tests/.gitignore b/tests/.gitignore index 5414cb8cc9..5e809a81e6 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -13,6 +13,7 @@ /isisd/test_fuzz_isis_tlv /isisd/test_fuzz_isis_tlv_tests.h /isisd/test_isis_lspdb +/isisd/test_isis_spf /isisd/test_isis_vertex_queue /lib/cli/test_cli /lib/cli/test_cli_clippy.c diff --git a/tests/isisd/test_common.c b/tests/isisd/test_common.c new file mode 100644 index 0000000000..536847a1da --- /dev/null +++ b/tests/isisd/test_common.c @@ -0,0 +1,331 @@ +/* + * Copyright (C) 2020 NetDEF, Inc. + * Renato Westphal + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * 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; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "isisd/isisd.h" +#include "isisd/isis_dynhn.h" +#include "isisd/isis_mt.h" + +#include "test_common.h" + +struct thread_master *master; +struct zebra_privs_t isisd_privs; + +int isis_sock_init(struct isis_circuit *circuit) +{ + return 0; +} + +const struct isis_test_node * +test_topology_find_node(const struct isis_topology *topology, + const char *hostname, uint8_t pseudonode_id) +{ + for (size_t i = 0; topology->nodes[i].hostname[0]; i++) + if (strmatch(hostname, topology->nodes[i].hostname) + && pseudonode_id == topology->nodes[i].pseudonode_id) + return &topology->nodes[i]; + + return NULL; +} + +const struct isis_topology * +test_topology_find(struct isis_topology *test_topologies, uint16_t number) +{ + for (size_t i = 0; test_topologies[i].number; i++) + if (test_topologies[i].number == number) + return &test_topologies[i]; + + return NULL; +} + +static const struct isis_test_node * +test_find_adjacency(const struct isis_test_node *tnode, const char *hostname) +{ + for (size_t i = 0; tnode->adjacencies[i].hostname[0]; i++) { + const struct isis_test_adj *tadj; + + tadj = &tnode->adjacencies[i]; + if (strmatch(hostname, tadj->hostname)) + return tnode; + } + + return NULL; +} + +static struct isis_lsp *lsp_add(struct lspdb_head *lspdb, + struct isis_area *area, int level, + const uint8_t *sysid, uint8_t pseudonode_id) +{ + struct isis_lsp *lsp; + uint8_t lspid[ISIS_SYS_ID_LEN + 2]; + + memcpy(lspid, sysid, ISIS_SYS_ID_LEN); + LSP_PSEUDO_ID(lspid) = pseudonode_id; + LSP_FRAGMENT(lspid) = 0; + + lsp = lsp_new(area, lspid, 6000, 1, 0, 0, NULL, level); + lsp->tlvs = isis_alloc_tlvs(); + lspdb_add(lspdb, lsp); + + return lsp; +} + +static void lsp_add_ip_reach(struct isis_lsp *lsp, + const struct isis_test_node *tnode, + const char *prefix_str, uint32_t *next_sid_index) +{ + struct prefix prefix; + struct sr_prefix_cfg pcfg = {}; + struct sr_prefix_cfg *pcfg_p = NULL; + + if (str2prefix(prefix_str, &prefix) != 1) { + zlog_debug("%s: invalid network: %s", __func__, prefix_str); + return; + } + + if (CHECK_FLAG(tnode->flags, F_ISIS_TEST_NODE_SR)) { + pcfg_p = &pcfg; + + pcfg.sid = *next_sid_index; + *next_sid_index = *next_sid_index + 1; + pcfg.sid_type = SR_SID_VALUE_TYPE_INDEX; + pcfg.last_hop_behavior = SR_LAST_HOP_BEHAVIOR_PHP; + } + + if (prefix.family == AF_INET) + isis_tlvs_add_extended_ip_reach(lsp->tlvs, + (struct prefix_ipv4 *)&prefix, + 10, false, pcfg_p); + else + isis_tlvs_add_ipv6_reach(lsp->tlvs, ISIS_MT_IPV6_UNICAST, + (struct prefix_ipv6 *)&prefix, 10, + false, pcfg_p); +} + +static void lsp_add_reach(struct isis_lsp *lsp, + const struct isis_test_node *tnode, + const uint8_t *ne_id, uint8_t pseudonode_id, + uint32_t metric, int family, mpls_label_t *next_label) +{ + uint8_t nodeid[ISIS_SYS_ID_LEN + 1]; + uint16_t mtid; + struct isis_ext_subtlvs *ext = NULL; + + memcpy(nodeid, ne_id, ISIS_SYS_ID_LEN); + LSP_PSEUDO_ID(nodeid) = pseudonode_id; + + if (CHECK_FLAG(tnode->flags, F_ISIS_TEST_NODE_SR)) { + struct isis_adj_sid *adj_sid; + + adj_sid = XCALLOC(MTYPE_ISIS_SUBTLV, sizeof(*adj_sid)); + adj_sid->family = family; + SET_FLAG(adj_sid->flags, EXT_SUBTLV_LINK_ADJ_SID_VFLG); + SET_FLAG(adj_sid->flags, EXT_SUBTLV_LINK_ADJ_SID_LFLG); + if (family == AF_INET6) + SET_FLAG(adj_sid->flags, EXT_SUBTLV_LINK_ADJ_SID_FFLG); + adj_sid->weight = 0; + adj_sid->sid = *next_label; + *next_label = *next_label + 1; + + ext = isis_alloc_ext_subtlvs(); + isis_tlvs_add_adj_sid(ext, adj_sid); + } + + mtid = (family == AF_INET) ? ISIS_MT_IPV4_UNICAST + : ISIS_MT_IPV6_UNICAST; + + isis_tlvs_add_extended_reach(lsp->tlvs, mtid, nodeid, metric, ext); +} + +static void lsp_add_router_capability(struct isis_lsp *lsp, + const struct isis_test_node *tnode) +{ + struct isis_router_cap cap = {}; + + if (!tnode->router_id) + return; + + if (inet_pton(AF_INET, tnode->router_id, &cap.router_id) != 1) { + zlog_debug("%s: invalid router-id: %s", __func__, + tnode->router_id); + return; + } + + if (CHECK_FLAG(tnode->flags, F_ISIS_TEST_NODE_SR)) { + cap.srgb.flags = + ISIS_SUBTLV_SRGB_FLAG_I | ISIS_SUBTLV_SRGB_FLAG_V; + cap.srgb.lower_bound = tnode->srgb.lower_bound + ? tnode->srgb.lower_bound + : SRGB_DFTL_LOWER_BOUND; + cap.srgb.range_size = tnode->srgb.range_size + ? tnode->srgb.range_size + : SRGB_DFTL_RANGE_SIZE; + cap.algo[0] = SR_ALGORITHM_SPF; + cap.algo[1] = SR_ALGORITHM_UNSET; + } + + isis_tlvs_set_router_capability(lsp->tlvs, &cap); +} + +static void lsp_add_mt_router_info(struct isis_lsp *lsp, + const struct isis_test_node *tnode) +{ + if (tnode->protocols.ipv4) + isis_tlvs_add_mt_router_info(lsp->tlvs, ISIS_MT_IPV4_UNICAST, 0, + false); + if (tnode->protocols.ipv6) + isis_tlvs_add_mt_router_info(lsp->tlvs, ISIS_MT_IPV6_UNICAST, 0, + false); +} + +static void lsp_add_protocols_supported(struct isis_lsp *lsp, + const struct isis_test_node *tnode) +{ + struct nlpids nlpids = {}; + + if (!tnode->protocols.ipv4 && !tnode->protocols.ipv6) + return; + + if (tnode->protocols.ipv4) { + nlpids.nlpids[nlpids.count] = NLPID_IP; + nlpids.count++; + } + if (tnode->protocols.ipv6) { + nlpids.nlpids[nlpids.count] = NLPID_IPV6; + nlpids.count++; + } + isis_tlvs_set_protocols_supported(lsp->tlvs, &nlpids); +} + +static int topology_load_node_level(const struct isis_topology *topology, + const struct isis_test_node *tnode, + size_t tnode_index, struct isis_area *area, + struct lspdb_head *lspdb, int level) +{ + struct isis_lsp *lsp; + uint32_t next_sid_index = (tnode_index + 1) * 10; + mpls_label_t next_label = 16; + + lsp = lsp_add(lspdb, area, level, tnode->sysid, tnode->pseudonode_id); + lsp_add_mt_router_info(lsp, tnode); + lsp_add_protocols_supported(lsp, tnode); + lsp_add_router_capability(lsp, tnode); + + /* Add IP Reachability Information. */ + for (size_t i = 0; tnode->networks[i]; i++) { + if (i > MAX_NETWORKS) { + zlog_debug( + "%s: node has too many networks (maximum is %u)", + __func__, MAX_NETWORKS); + return -1; + } + lsp_add_ip_reach(lsp, tnode, tnode->networks[i], + &next_sid_index); + } + + /* Add IS Reachability Information. */ + for (size_t i = 0; tnode->adjacencies[i].hostname[0]; i++) { + const struct isis_test_adj *tadj; + const struct isis_test_node *tadj_node; + + if (i > MAX_ADJACENCIES) { + zlog_debug( + "%s: node has too many adjacencies (maximum is %u)", + __func__, MAX_ADJACENCIES); + return -1; + } + + tadj = &tnode->adjacencies[i]; + tadj_node = test_topology_find_node(topology, tadj->hostname, + tadj->pseudonode_id); + if (!tadj_node) { + zlog_debug( + "%s: node \"%s\" has an adjacency with non-existing node \"%s\"", + __func__, tnode->hostname, tadj->hostname); + return -1; + } + if (!test_find_adjacency(tadj_node, tnode->hostname)) { + zlog_debug( + "%s: node \"%s\" has an one-way adjacency with node \"%s\"", + __func__, tnode->hostname, tadj->hostname); + return -1; + } + + if (tnode->pseudonode_id || tadj_node->pseudonode_id + || (tnode->protocols.ipv4 && tadj_node->protocols.ipv4)) + lsp_add_reach(lsp, tnode, tadj_node->sysid, + tadj_node->pseudonode_id, tadj->metric, + AF_INET, &next_label); + if (tadj_node->pseudonode_id + || (tnode->protocols.ipv6 && tadj_node->protocols.ipv6)) + lsp_add_reach(lsp, tnode, tadj_node->sysid, + tadj_node->pseudonode_id, tadj->metric, + AF_INET6, &next_label); + } + + return 0; +} + +static int topology_load_node(const struct isis_topology *topology, + const struct isis_test_node *tnode, + size_t tnode_index, struct isis_area *area, + struct lspdb_head lspdb[]) +{ + int ret; + + isis_dynhn_insert(tnode->sysid, tnode->hostname, tnode->level); + + for (int level = IS_LEVEL_1; level <= IS_LEVEL_2; level++) { + if ((tnode->level & level) == 0) + continue; + + ret = topology_load_node_level(topology, tnode, tnode_index, + area, &lspdb[level - 1], level); + if (ret != 0) + return ret; + } + + return 0; +} + +int test_topology_load(const struct isis_topology *topology, + struct isis_area *area, struct lspdb_head lspdb[]) +{ + for (int level = IS_LEVEL_1; level <= IS_LEVEL_2; level++) + lsp_db_init(&lspdb[level - 1]); + + for (size_t i = 0; topology->nodes[i].hostname[0]; i++) { + const struct isis_test_node *tnode = &topology->nodes[i]; + int ret; + + if (i > MAX_NODES) { + zlog_debug( + "%s: topology has too many nodes (maximum is %u)", + __func__, MAX_NODES); + return -1; + } + + ret = topology_load_node(topology, tnode, i, area, lspdb); + if (ret != 0) + return ret; + } + + return 0; +} diff --git a/tests/isisd/test_common.h b/tests/isisd/test_common.h new file mode 100644 index 0000000000..6fd0d3813e --- /dev/null +++ b/tests/isisd/test_common.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2020 NetDEF, Inc. + * Renato Westphal + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * 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; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _COMMON_ISIS_H +#define _COMMON_ISIS_H + +#include "isisd/isisd.h" +#include "isisd/isis_spf.h" +#include "isisd/isis_spf_private.h" + +#define MAX_HOSTNAME 16 +#define MAX_NETWORKS 8 +#define MAX_ADJACENCIES 8 +#define MAX_NODES 12 + +#define SRGB_DFTL_LOWER_BOUND 16000 +#define SRGB_DFTL_RANGE_SIZE 8000 + +struct isis_test_adj { + char hostname[MAX_HOSTNAME]; + uint8_t pseudonode_id; + uint32_t metric; +}; + +struct isis_test_node { + char hostname[MAX_HOSTNAME]; + uint8_t sysid[ISIS_SYS_ID_LEN]; + uint8_t pseudonode_id; + int level; + struct { + bool ipv4; + bool ipv6; + } protocols; + const char *router_id; + struct { + uint32_t lower_bound; + uint32_t range_size; + } srgb; + const char *networks[MAX_NETWORKS + 1]; + struct isis_test_adj adjacencies[MAX_ADJACENCIES + 1]; + uint8_t flags; +}; +#define F_ISIS_TEST_NODE_SR 0x01 + +struct isis_topology { + uint16_t number; + struct isis_test_node nodes[MAX_NODES + 1]; +}; + +/* Prototypes. */ +extern int isis_sock_init(struct isis_circuit *circuit); +extern const struct isis_test_node * +test_topology_find_node(const struct isis_topology *topology, + const char *hostname, uint8_t pseudonode_id); +extern const struct isis_topology * +test_topology_find(struct isis_topology *test_topologies, uint16_t number); +extern int test_topology_load(const struct isis_topology *topology, + struct isis_area *area, + struct lspdb_head lspdb[]); + +/* Global variables. */ +extern struct thread_master *master; +extern struct zebra_privs_t isisd_privs; +extern struct isis_topology test_topologies[]; + +#endif /* _COMMON_ISIS_H */ diff --git a/tests/isisd/test_fuzz_isis_tlv.c b/tests/isisd/test_fuzz_isis_tlv.c index 917ea66f13..97aade6578 100644 --- a/tests/isisd/test_fuzz_isis_tlv.c +++ b/tests/isisd/test_fuzz_isis_tlv.c @@ -14,17 +14,10 @@ #include "isisd/isis_circuit.h" #include "isisd/isis_tlvs.h" +#include "test_common.h" + #define TEST_STREAM_SIZE 1500 -struct thread_master *master; -int isis_sock_init(struct isis_circuit *circuit); -int isis_sock_init(struct isis_circuit *circuit) -{ - return 0; -} - -struct zebra_privs_t isisd_privs; - static bool atexit_registered; static void show_meminfo_at_exit(void) diff --git a/tests/isisd/test_isis_lspdb.c b/tests/isisd/test_isis_lspdb.c index 6a571eaa84..244922ea4e 100644 --- a/tests/isisd/test_isis_lspdb.c +++ b/tests/isisd/test_isis_lspdb.c @@ -2,15 +2,7 @@ #include "isisd/isis_lsp.c" -struct thread_master *master; - -int isis_sock_init(struct isis_circuit *circuit); -int isis_sock_init(struct isis_circuit *circuit) -{ - return 0; -} - -struct zebra_privs_t isisd_privs; +#include "test_common.h" static void test_lsp_build_list_nonzero_ht(void) { diff --git a/tests/isisd/test_isis_spf.c b/tests/isisd/test_isis_spf.c new file mode 100644 index 0000000000..dae906b956 --- /dev/null +++ b/tests/isisd/test_isis_spf.c @@ -0,0 +1,313 @@ +/* + * Copyright (C) 2020 NetDEF, Inc. + * Renato Westphal + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * 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; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include +#include "getopt.h" +#include "thread.h" +#include "vty.h" +#include "command.h" +#include "log.h" +#include "vrf.h" +#include "yang.h" + +#include "isisd/isisd.h" +#include "isisd/isis_dynhn.h" +#include "isisd/isis_misc.h" +#include "isisd/isis_spf.h" +#include "isisd/isis_spf_private.h" + +#include "test_common.h" + +enum test_type { + TEST_SPF = 1, + TEST_REVERSE_SPF, +}; + +#define F_DISPLAY_LSPDB 0x01 +#define F_IPV4_ONLY 0x02 +#define F_IPV6_ONLY 0x04 +#define F_LEVEL1_ONLY 0x08 +#define F_LEVEL2_ONLY 0x10 + +static struct isis *isis; + +static void test_run_spf(struct vty *vty, const struct isis_topology *topology, + const struct isis_test_node *root, + struct isis_area *area, struct lspdb_head *lspdb, + int level, int tree, bool reverse) +{ + struct isis_spftree *spftree; + enum spf_type spf_type; + + /* Run SPF. */ + spf_type = reverse ? SPF_TYPE_REVERSE : SPF_TYPE_FORWARD; + spftree = isis_spftree_new(area, lspdb, root->sysid, level, tree, + spf_type, F_SPFTREE_NO_ADJACENCIES); + isis_run_spf(spftree); + + /* Print the SPT and the corresponding routing table. */ + isis_print_spftree(vty, spftree); + isis_print_routes(vty, spftree); + + /* Cleanup SPF tree. */ + isis_spftree_del(spftree); +} + +static int test_run(struct vty *vty, const struct isis_topology *topology, + const struct isis_test_node *root, enum test_type test_type, + uint8_t flags) +{ + struct isis_area *area; + + /* Init topology. */ + memcpy(isis->sysid, root->sysid, sizeof(isis->sysid)); + area = isis_area_create("1", NULL); + area->is_type = IS_LEVEL_1_AND_2; + area->srdb.enabled = true; + if (test_topology_load(topology, area, area->lspdb) != 0) { + vty_out(vty, "%% Failed to load topology\n"); + return CMD_WARNING; + } + + for (int level = IS_LEVEL_1; level <= IS_LEVEL_2; level++) { + if (level == IS_LEVEL_1 && CHECK_FLAG(flags, F_LEVEL2_ONLY)) + continue; + if (level == IS_LEVEL_2 && CHECK_FLAG(flags, F_LEVEL1_ONLY)) + continue; + if ((root->level & level) == 0) + continue; + + /* Print the LDPDB. */ + if (CHECK_FLAG(flags, F_DISPLAY_LSPDB)) + show_isis_database_lspdb(vty, area, level - 1, + &area->lspdb[level - 1], NULL, + ISIS_UI_LEVEL_DETAIL); + + for (int tree = SPFTREE_IPV4; tree <= SPFTREE_IPV6; tree++) { + if (tree == SPFTREE_IPV4 + && CHECK_FLAG(flags, F_IPV6_ONLY)) + continue; + if (tree == SPFTREE_IPV6 + && CHECK_FLAG(flags, F_IPV4_ONLY)) + continue; + + switch (test_type) { + case TEST_SPF: + test_run_spf(vty, topology, root, area, + &area->lspdb[level - 1], level, + tree, false); + break; + case TEST_REVERSE_SPF: + test_run_spf(vty, topology, root, area, + &area->lspdb[level - 1], level, + tree, true); + break; + } + } + } + + /* Cleanup IS-IS area. */ + isis_area_destroy(area); + + /* Cleanup hostnames. */ + dyn_cache_cleanup_all(); + + return CMD_SUCCESS; +} + +DEFUN(test_isis, test_isis_cmd, + "test isis topology (1-13) root HOSTNAME\ + <\ + spf\ + |reverse-spf\ + >\ + [display-lspdb] [] []", + "Test command\n" + "IS-IS routing protocol\n" + "Test topology\n" + "Test topology number\n" + "SPF root\n" + "SPF root hostname\n" + "Normal Shortest Path First\n" + "Reverse Shortest Path First\n" + "Display the LSPDB\n" + "Do IPv4 processing only\n" + "Do IPv6 processing only\n" + "Skip L2 LSPs\n" + "Skip L1 LSPs\n") +{ + uint16_t topology_number; + const struct isis_topology *topology; + const struct isis_test_node *root; + enum test_type test_type; + uint8_t flags = 0; + int idx = 0; + + /* Load topology. */ + argv_find(argv, argc, "topology", &idx); + topology_number = atoi(argv[idx + 1]->arg); + topology = test_topology_find(test_topologies, topology_number); + if (!topology) { + vty_out(vty, "%% Topology \"%s\" not found\n", + argv[idx + 1]->arg); + return CMD_WARNING; + } + + /* Find root node. */ + argv_find(argv, argc, "root", &idx); + root = test_topology_find_node(topology, argv[idx + 1]->arg, 0); + if (!root) { + vty_out(vty, "%% Node \"%s\" not found\n", argv[idx + 1]->arg); + return CMD_WARNING; + } + + /* Parse test information. */ + if (argv_find(argv, argc, "spf", &idx)) + test_type = TEST_SPF; + else if (argv_find(argv, argc, "reverse-spf", &idx)) + test_type = TEST_REVERSE_SPF; + else + return CMD_WARNING; + + /* Parse control flags. */ + if (argv_find(argv, argc, "display-lspdb", &idx)) + SET_FLAG(flags, F_DISPLAY_LSPDB); + if (argv_find(argv, argc, "ipv4-only", &idx)) + SET_FLAG(flags, F_IPV4_ONLY); + else if (argv_find(argv, argc, "ipv6-only", &idx)) + SET_FLAG(flags, F_IPV6_ONLY); + if (argv_find(argv, argc, "level-1-only", &idx)) + SET_FLAG(flags, F_LEVEL1_ONLY); + else if (argv_find(argv, argc, "level-2-only", &idx)) + SET_FLAG(flags, F_LEVEL2_ONLY); + + return test_run(vty, topology, root, test_type, flags); +} + +static void vty_do_exit(int isexit) +{ + printf("\nend.\n"); + + isis_finish(isis); + cmd_terminate(); + vty_terminate(); + yang_terminate(); + thread_master_free(master); + + log_memstats(stderr, "test-isis-spf"); + if (!isexit) + exit(0); +} + +struct option longopts[] = {{"help", no_argument, NULL, 'h'}, + {"debug", no_argument, NULL, 'd'}, + {0}}; + +/* Help information display. */ +static void usage(char *progname, int status) +{ + if (status != 0) + fprintf(stderr, "Try `%s --help' for more information.\n", + progname); + else { + printf("Usage : %s [OPTION...]\n\ +isisd SPF test program.\n\n\ +-u, --debug Enable debugging\n\ +-h, --help Display this help and exit\n\ +\n\ +Report bugs to %s\n", + progname, FRR_BUG_ADDRESS); + } + exit(status); +} + +int main(int argc, char **argv) +{ + char *p; + char *progname; + struct thread thread; + bool debug = false; + + /* Set umask before anything for security */ + umask(0027); + + /* get program name */ + progname = ((p = strrchr(argv[0], '/')) ? ++p : argv[0]); + + while (1) { + int opt; + + opt = getopt_long(argc, argv, "hd", longopts, 0); + + if (opt == EOF) + break; + + switch (opt) { + case 0: + break; + case 'd': + debug = true; + break; + case 'h': + usage(progname, 0); + break; + default: + usage(progname, 1); + break; + } + } + + /* master init. */ + master = thread_master_create(NULL); + isis_master_init(master); + + /* Library inits. */ + cmd_init(1); + cmd_hostname_set("test"); + vty_init(master, false); + yang_init(true); + if (debug) + zlog_aux_init("NONE: ", LOG_DEBUG); + else + zlog_aux_init("NONE: ", ZLOG_DISABLED); + + /* IS-IS inits. */ + yang_module_load("frr-isisd"); + isis = isis_new(VRF_DEFAULT); + listnode_add(im->isis, isis); + SET_FLAG(im->options, F_ISIS_UNIT_TEST); + debug_spf_events |= DEBUG_SPF_EVENTS; + debug_events |= DEBUG_EVENTS; + debug_rte_events |= DEBUG_RTE_EVENTS; + + /* Install test command. */ + install_element(VIEW_NODE, &test_isis_cmd); + + /* Read input from .in file. */ + vty_stdio(vty_do_exit); + + /* Fetch next active thread. */ + while (thread_fetch(master, &thread)) + thread_call(&thread); + + /* Not reached. */ + exit(0); +} diff --git a/tests/isisd/test_isis_spf.in b/tests/isisd/test_isis_spf.in new file mode 100644 index 0000000000..d9a61782e9 --- /dev/null +++ b/tests/isisd/test_isis_spf.in @@ -0,0 +1,16 @@ +test isis topology 1 root rt1 spf +test isis topology 2 root rt1 spf +test isis topology 3 root rt1 spf ipv4-only +test isis topology 4 root rt1 spf ipv4-only +test isis topology 5 root rt1 spf ipv4-only +test isis topology 6 root rt1 spf ipv4-only +test isis topology 7 root rt1 spf ipv4-only +test isis topology 8 root rt1 spf ipv4-only +test isis topology 9 root rt1 spf +test isis topology 10 root rt1 spf +test isis topology 11 root rt1 spf +test isis topology 12 root rt1 spf ipv4-only +test isis topology 13 root rt1 spf ipv4-only + +test isis topology 4 root rt1 reverse-spf ipv4-only +test isis topology 11 root rt1 reverse-spf diff --git a/tests/isisd/test_isis_spf.py b/tests/isisd/test_isis_spf.py new file mode 100644 index 0000000000..21e7ef6269 --- /dev/null +++ b/tests/isisd/test_isis_spf.py @@ -0,0 +1,4 @@ +import frrtest + +class TestIsisSPF(frrtest.TestRefOut): + program = './test_isis_spf' diff --git a/tests/isisd/test_isis_spf.refout b/tests/isisd/test_isis_spf.refout new file mode 100644 index 0000000000..ed0569947c --- /dev/null +++ b/tests/isisd/test_isis_spf.refout @@ -0,0 +1,703 @@ +test# test isis topology 1 root rt1 spf +IS-IS paths to level-1 routers that speak IP +Vertex Type Metric Next-Hop Interface Parent +rt1 +10.0.255.1/32 IP internal 0 rt1(4) +rt2 TE-IS 10 rt2 - rt1(4) +rt3 TE-IS 10 rt3 - rt1(4) +rt4 TE-IS 20 rt2 - rt2(4) +rt5 TE-IS 20 rt3 - rt3(4) +10.0.255.2/32 IP TE 20 rt2 - rt2(4) +10.0.255.3/32 IP TE 20 rt3 - rt3(4) +rt6 TE-IS 30 rt2 - rt4(4) + rt3 - rt5(4) +10.0.255.4/32 IP TE 30 rt2 - rt4(4) +10.0.255.5/32 IP TE 30 rt3 - rt5(4) +10.0.255.6/32 IP TE 40 rt2 - rt6(4) + rt3 - + +IS-IS L1 IPv4 routing table: + + Prefix Metric Interface Nexthop Label(s) + ----------------------------------------------------- + 10.0.255.2/32 20 - rt2 - + 10.0.255.3/32 20 - rt3 - + 10.0.255.4/32 30 - rt2 - + 10.0.255.5/32 30 - rt3 - + 10.0.255.6/32 40 - rt2 - + - rt3 - + +IS-IS paths to level-1 routers that speak IPv6 +Vertex Type Metric Next-Hop Interface Parent +rt1 +2001:db8::1/128 IP6 internal 0 rt1(4) +rt2 TE-IS 10 rt2 - rt1(4) +rt3 TE-IS 10 rt3 - rt1(4) +rt4 TE-IS 20 rt2 - rt2(4) +rt5 TE-IS 20 rt3 - rt3(4) +2001:db8::2/128 IP6 internal 20 rt2 - rt2(4) +2001:db8::3/128 IP6 internal 20 rt3 - rt3(4) +rt6 TE-IS 30 rt2 - rt4(4) + rt3 - rt5(4) +2001:db8::4/128 IP6 internal 30 rt2 - rt4(4) +2001:db8::5/128 IP6 internal 30 rt3 - rt5(4) +2001:db8::6/128 IP6 internal 40 rt2 - rt6(4) + rt3 - + +IS-IS L1 IPv6 routing table: + + Prefix Metric Interface Nexthop Label(s) + ------------------------------------------------------- + 2001:db8::2/128 20 - rt2 - + 2001:db8::3/128 20 - rt3 - + 2001:db8::4/128 30 - rt2 - + 2001:db8::5/128 30 - rt3 - + 2001:db8::6/128 40 - rt2 - + - rt3 - + +test# test isis topology 2 root rt1 spf +IS-IS paths to level-1 routers that speak IP +Vertex Type Metric Next-Hop Interface Parent +rt1 +10.0.255.1/32 IP internal 0 rt1(4) +rt4 TE-IS 10 rt4 - rt1(4) +rt5 TE-IS 10 rt5 - rt1(4) +rt2 TE-IS 15 rt2 - rt1(4) +rt1 +rt6 TE-IS 20 rt4 - rt4(4) + rt5 - rt5(4) +10.0.255.4/32 IP TE 20 rt4 - rt4(4) +10.0.255.5/32 IP TE 20 rt5 - rt5(4) +10.0.255.2/32 IP TE 25 rt2 - rt2(4) +rt3 TE-IS 30 rt3 - rt1(4) +10.0.255.6/32 IP TE 30 rt4 - rt6(4) + rt5 - +10.0.255.3/32 IP TE 40 rt3 - rt3(4) + +IS-IS L1 IPv4 routing table: + + Prefix Metric Interface Nexthop Label(s) + ----------------------------------------------------- + 10.0.255.2/32 25 - rt2 - + 10.0.255.3/32 40 - rt3 - + 10.0.255.4/32 20 - rt4 - + 10.0.255.5/32 20 - rt5 - + 10.0.255.6/32 30 - rt4 - + - rt5 - + +IS-IS paths to level-1 routers that speak IPv6 +Vertex Type Metric Next-Hop Interface Parent +rt1 +2001:db8::1/128 IP6 internal 0 rt1(4) +rt4 TE-IS 10 rt4 - rt1(4) +rt5 TE-IS 10 rt5 - rt1(4) +rt2 TE-IS 15 rt2 - rt1(4) +rt1 +rt6 TE-IS 20 rt4 - rt4(4) + rt5 - rt5(4) +2001:db8::4/128 IP6 internal 20 rt4 - rt4(4) +2001:db8::5/128 IP6 internal 20 rt5 - rt5(4) +2001:db8::2/128 IP6 internal 25 rt2 - rt2(4) +rt3 TE-IS 30 rt3 - rt1(4) +2001:db8::6/128 IP6 internal 30 rt4 - rt6(4) + rt5 - +2001:db8::3/128 IP6 internal 40 rt3 - rt3(4) + +IS-IS L1 IPv6 routing table: + + Prefix Metric Interface Nexthop Label(s) + ------------------------------------------------------- + 2001:db8::2/128 25 - rt2 - + 2001:db8::3/128 40 - rt3 - + 2001:db8::4/128 20 - rt4 - + 2001:db8::5/128 20 - rt5 - + 2001:db8::6/128 30 - rt4 - + - rt5 - + +test# test isis topology 3 root rt1 spf ipv4-only +IS-IS paths to level-1 routers that speak IP +Vertex Type Metric Next-Hop Interface Parent +rt1 +10.0.255.1/32 IP internal 0 rt1(4) +rt2 TE-IS 10 rt2 - rt1(4) +rt3 TE-IS 10 rt3 - rt1(4) +rt4 TE-IS 20 rt2 - rt2(4) +10.0.255.2/32 IP TE 20 rt2 - rt2(4) +10.0.255.3/32 IP TE 20 rt3 - rt3(4) +rt5 TE-IS 30 rt2 - rt4(4) +rt6 TE-IS 30 rt2 - rt4(4) +10.0.255.4/32 IP TE 30 rt2 - rt4(4) +10.0.255.5/32 IP TE 40 rt2 - rt5(4) +10.0.255.6/32 IP TE 40 rt2 - rt6(4) + +IS-IS L1 IPv4 routing table: + + Prefix Metric Interface Nexthop Label(s) + ----------------------------------------------------- + 10.0.255.2/32 20 - rt2 - + 10.0.255.3/32 20 - rt3 - + 10.0.255.4/32 30 - rt2 - + 10.0.255.5/32 40 - rt2 - + 10.0.255.6/32 40 - rt2 - + +test# test isis topology 4 root rt1 spf ipv4-only +IS-IS paths to level-1 routers that speak IP +Vertex Type Metric Next-Hop Interface Parent +rt1 +10.0.255.1/32 IP internal 0 rt1(4) +rt2 TE-IS 10 rt2 - rt1(4) +rt3 TE-IS 10 rt3 - rt1(4) +rt4 TE-IS 20 rt2 - rt2(4) +rt5 TE-IS 20 rt3 - rt3(4) +10.0.255.2/32 IP TE 20 rt2 - rt2(4) +10.0.255.3/32 IP TE 20 rt3 - rt3(4) +rt6 TE-IS 30 rt2 - rt4(4) +rt7 TE-IS 30 rt3 - rt5(4) +10.0.255.4/32 IP TE 30 rt2 - rt4(4) +10.0.255.5/32 IP TE 30 rt3 - rt5(4) +rt8 TE-IS 40 rt2 - rt6(4) +10.0.255.6/32 IP TE 40 rt2 - rt6(4) +10.0.255.7/32 IP TE 40 rt3 - rt7(4) +10.0.255.8/32 IP TE 50 rt2 - rt8(4) + +IS-IS L1 IPv4 routing table: + + Prefix Metric Interface Nexthop Label(s) + ----------------------------------------------------- + 10.0.255.2/32 20 - rt2 - + 10.0.255.3/32 20 - rt3 - + 10.0.255.4/32 30 - rt2 - + 10.0.255.5/32 30 - rt3 - + 10.0.255.6/32 40 - rt2 - + 10.0.255.7/32 40 - rt3 - + 10.0.255.8/32 50 - rt2 - + +test# test isis topology 5 root rt1 spf ipv4-only +IS-IS paths to level-1 routers that speak IP +Vertex Type Metric Next-Hop Interface Parent +rt1 +10.0.255.1/32 IP internal 0 rt1(4) +rt2 TE-IS 10 rt2 - rt1(4) +rt3 TE-IS 10 rt3 - rt1(4) +rt4 TE-IS 20 rt2 - rt2(4) +rt5 TE-IS 20 rt3 - rt3(4) +10.0.255.2/32 IP TE 20 rt2 - rt2(4) +10.0.255.3/32 IP TE 20 rt3 - rt3(4) +rt6 TE-IS 30 rt2 - rt4(4) +rt7 TE-IS 30 rt3 - rt5(4) +10.0.255.4/32 IP TE 30 rt2 - rt4(4) +10.0.255.5/32 IP TE 30 rt3 - rt5(4) +rt8 TE-IS 40 rt2 - rt6(4) + rt3 - rt7(4) +10.0.255.6/32 IP TE 40 rt2 - rt6(4) +10.0.255.7/32 IP TE 40 rt3 - rt7(4) +10.0.255.8/32 IP TE 50 rt2 - rt8(4) + rt3 - + +IS-IS L1 IPv4 routing table: + + Prefix Metric Interface Nexthop Label(s) + ----------------------------------------------------- + 10.0.255.2/32 20 - rt2 - + 10.0.255.3/32 20 - rt3 - + 10.0.255.4/32 30 - rt2 - + 10.0.255.5/32 30 - rt3 - + 10.0.255.6/32 40 - rt2 - + 10.0.255.7/32 40 - rt3 - + 10.0.255.8/32 50 - rt2 - + - rt3 - + +test# test isis topology 6 root rt1 spf ipv4-only +IS-IS paths to level-1 routers that speak IP +Vertex Type Metric Next-Hop Interface Parent +rt1 +10.0.255.1/32 IP internal 0 rt1(4) +rt2 TE-IS 10 rt2 - rt1(4) +rt3 TE-IS 10 rt3 - rt1(4) +rt4 TE-IS 20 rt2 - rt2(4) + rt3 - rt3(4) +10.0.255.2/32 IP TE 20 rt2 - rt2(4) +10.0.255.3/32 IP TE 20 rt3 - rt3(4) +rt6 TE-IS 30 rt2 - rt4(4) + rt3 - +10.0.255.4/32 IP TE 30 rt2 - rt4(4) + rt3 - +rt5 TE-IS 40 rt2 - rt6(4) + rt3 - +rt8 TE-IS 40 rt2 - rt6(4) + rt3 - +10.0.255.6/32 IP TE 40 rt2 - rt6(4) + rt3 - +rt7 TE-IS 50 rt2 - rt5(4) + rt3 - rt8(4) +10.0.255.5/32 IP TE 50 rt2 - rt5(4) + rt3 - +10.0.255.8/32 IP TE 50 rt2 - rt8(4) + rt3 - +10.0.255.7/32 IP TE 60 rt2 - rt7(4) + rt3 - + +IS-IS L1 IPv4 routing table: + + Prefix Metric Interface Nexthop Label(s) + ----------------------------------------------------- + 10.0.255.2/32 20 - rt2 - + 10.0.255.3/32 20 - rt3 - + 10.0.255.4/32 30 - rt2 - + - rt3 - + 10.0.255.5/32 50 - rt2 - + - rt3 - + 10.0.255.6/32 40 - rt2 - + - rt3 - + 10.0.255.7/32 60 - rt2 - + - rt3 - + 10.0.255.8/32 50 - rt2 - + - rt3 - + +test# test isis topology 7 root rt1 spf ipv4-only +IS-IS paths to level-1 routers that speak IP +Vertex Type Metric Next-Hop Interface Parent +rt1 +10.0.255.1/32 IP internal 0 rt1(4) +rt4 TE-IS 10 rt4 - rt1(4) +rt5 TE-IS 20 rt4 - rt4(4) +rt7 TE-IS 20 rt4 - rt4(4) +10.0.255.4/32 IP TE 20 rt4 - rt4(4) +rt2 TE-IS 30 rt4 - rt5(4) +rt6 TE-IS 30 rt4 - rt5(4) +rt8 TE-IS 30 rt4 - rt5(4) + rt7(4) +10.0.255.5/32 IP TE 30 rt4 - rt5(4) +10.0.255.7/32 IP TE 30 rt4 - rt7(4) +rt10 TE-IS 40 rt4 - rt7(4) +rt3 TE-IS 40 rt4 - rt2(4) + rt6(4) +rt9 TE-IS 40 rt4 - rt8(4) +rt11 TE-IS 40 rt4 - rt8(4) +10.0.255.2/32 IP TE 40 rt4 - rt2(4) +10.0.255.6/32 IP TE 40 rt4 - rt6(4) +10.0.255.8/32 IP TE 40 rt4 - rt8(4) +rt12 TE-IS 50 rt4 - rt9(4) + rt11(4) +10.0.255.10/32 IP TE 50 rt4 - rt10(4) +10.0.255.3/32 IP TE 50 rt4 - rt3(4) +10.0.255.9/32 IP TE 50 rt4 - rt9(4) +10.0.255.11/32 IP TE 50 rt4 - rt11(4) +10.0.255.12/32 IP TE 60 rt4 - rt12(4) + +IS-IS L1 IPv4 routing table: + + Prefix Metric Interface Nexthop Label(s) + ------------------------------------------------------ + 10.0.255.2/32 40 - rt4 - + 10.0.255.3/32 50 - rt4 - + 10.0.255.4/32 20 - rt4 - + 10.0.255.5/32 30 - rt4 - + 10.0.255.6/32 40 - rt4 - + 10.0.255.7/32 30 - rt4 - + 10.0.255.8/32 40 - rt4 - + 10.0.255.9/32 50 - rt4 - + 10.0.255.10/32 50 - rt4 - + 10.0.255.11/32 50 - rt4 - + 10.0.255.12/32 60 - rt4 - + +test# test isis topology 8 root rt1 spf ipv4-only +IS-IS paths to level-1 routers that speak IP +Vertex Type Metric Next-Hop Interface Parent +rt1 +10.0.255.1/32 IP internal 0 rt1(4) +rt2 TE-IS 10 rt2 - rt1(4) +rt4 TE-IS 10 rt4 - rt1(4) +rt3 TE-IS 20 rt2 - rt2(4) +rt5 TE-IS 20 rt2 - rt2(4) +rt7 TE-IS 20 rt4 - rt4(4) +10.0.255.2/32 IP TE 20 rt2 - rt2(4) +10.0.255.4/32 IP TE 20 rt4 - rt4(4) +rt6 TE-IS 30 rt2 - rt3(4) + rt5(4) +rt8 TE-IS 30 rt2 - rt5(4) +rt10 TE-IS 30 rt4 - rt7(4) +10.0.255.3/32 IP TE 30 rt2 - rt3(4) +10.0.255.5/32 IP TE 30 rt2 - rt5(4) +10.0.255.7/32 IP TE 30 rt4 - rt7(4) +rt9 TE-IS 40 rt2 - rt8(4) +rt11 TE-IS 40 rt2 - rt8(4) +10.0.255.6/32 IP TE 40 rt2 - rt6(4) +10.0.255.8/32 IP TE 40 rt2 - rt8(4) +10.0.255.10/32 IP TE 40 rt4 - rt10(4) +rt12 TE-IS 50 rt2 - rt9(4) + rt11(4) +10.0.255.9/32 IP TE 50 rt2 - rt9(4) +10.0.255.11/32 IP TE 50 rt2 - rt11(4) +10.0.255.12/32 IP TE 60 rt2 - rt12(4) + +IS-IS L1 IPv4 routing table: + + Prefix Metric Interface Nexthop Label(s) + ------------------------------------------------------ + 10.0.255.2/32 20 - rt2 - + 10.0.255.3/32 30 - rt2 - + 10.0.255.4/32 20 - rt4 - + 10.0.255.5/32 30 - rt2 - + 10.0.255.6/32 40 - rt2 - + 10.0.255.7/32 30 - rt4 - + 10.0.255.8/32 40 - rt2 - + 10.0.255.9/32 50 - rt2 - + 10.0.255.10/32 40 - rt4 - + 10.0.255.11/32 50 - rt2 - + 10.0.255.12/32 60 - rt2 - + +test# test isis topology 9 root rt1 spf +IS-IS paths to level-1 routers that speak IP +Vertex Type Metric Next-Hop Interface Parent +rt1 +10.0.255.1/32 IP internal 0 rt1(4) +rt2 TE-IS 10 rt2 - rt1(4) +rt3 TE-IS 10 rt3 - rt1(4) +rt4 TE-IS 20 rt2 - rt2(4) +10.0.255.2/32 IP TE 20 rt2 - rt2(4) +10.0.255.3/32 IP TE 20 rt3 - rt3(4) +rt5 TE-IS 30 rt2 - rt4(4) +10.0.255.4/32 IP TE 30 rt2 - rt4(4) +rt9 TE-IS 40 rt2 - rt5(4) +10.0.255.5/32 IP TE 40 rt2 - rt5(4) +rt6 TE-IS 50 rt2 - rt4(4) + rt9(4) +rt7 TE-IS 50 rt2 - rt4(4) + rt9(4) +rt8 TE-IS 50 rt2 - rt4(4) + rt9(4) +10.0.255.9/32 IP TE 50 rt2 - rt9(4) +10.0.255.6/32 IP TE 60 rt2 - rt6(4) +10.0.255.7/32 IP TE 60 rt2 - rt7(4) +10.0.255.8/32 IP TE 60 rt2 - rt8(4) + +IS-IS L1 IPv4 routing table: + + Prefix Metric Interface Nexthop Label(s) + ----------------------------------------------------- + 10.0.255.2/32 20 - rt2 - + 10.0.255.3/32 20 - rt3 - + 10.0.255.4/32 30 - rt2 - + 10.0.255.5/32 40 - rt2 - + 10.0.255.6/32 60 - rt2 - + 10.0.255.7/32 60 - rt2 - + 10.0.255.8/32 60 - rt2 - + 10.0.255.9/32 50 - rt2 - + +IS-IS paths to level-1 routers that speak IPv6 +Vertex Type Metric Next-Hop Interface Parent +rt1 +2001:db8::1/128 IP6 internal 0 rt1(4) +rt2 TE-IS 10 rt2 - rt1(4) +rt3 TE-IS 10 rt3 - rt1(4) +rt4 TE-IS 20 rt2 - rt2(4) +2001:db8::2/128 IP6 internal 20 rt2 - rt2(4) +2001:db8::3/128 IP6 internal 20 rt3 - rt3(4) +rt5 TE-IS 30 rt2 - rt4(4) +2001:db8::4/128 IP6 internal 30 rt2 - rt4(4) +rt9 TE-IS 40 rt2 - rt5(4) +2001:db8::5/128 IP6 internal 40 rt2 - rt5(4) +rt6 TE-IS 50 rt2 - rt4(4) + rt9(4) +rt7 TE-IS 50 rt2 - rt4(4) + rt9(4) +rt8 TE-IS 50 rt2 - rt4(4) + rt9(4) +2001:db8::9/128 IP6 internal 50 rt2 - rt9(4) +2001:db8::6/128 IP6 internal 60 rt2 - rt6(4) +2001:db8::7/128 IP6 internal 60 rt2 - rt7(4) +2001:db8::8/128 IP6 internal 60 rt2 - rt8(4) + +IS-IS L1 IPv6 routing table: + + Prefix Metric Interface Nexthop Label(s) + ------------------------------------------------------- + 2001:db8::2/128 20 - rt2 - + 2001:db8::3/128 20 - rt3 - + 2001:db8::4/128 30 - rt2 - + 2001:db8::5/128 40 - rt2 - + 2001:db8::6/128 60 - rt2 - + 2001:db8::7/128 60 - rt2 - + 2001:db8::8/128 60 - rt2 - + 2001:db8::9/128 50 - rt2 - + +test# test isis topology 10 root rt1 spf +IS-IS paths to level-1 routers that speak IP +Vertex Type Metric Next-Hop Interface Parent +rt1 +10.0.255.1/32 IP internal 0 rt1(4) +rt2 TE-IS 10 rt2 - rt1(4) +rt3 TE-IS 20 rt3 - rt1(4) +rt4 TE-IS 20 rt4 - rt1(4) +rt5 TE-IS 20 rt2 - rt2(4) +10.0.255.2/32 IP TE 20 rt2 - rt2(4) +rt6 TE-IS 30 rt3 - rt3(4) +rt7 TE-IS 30 rt4 - rt4(4) +rt8 TE-IS 30 rt2 - rt5(4) +10.0.255.3/32 IP TE 30 rt3 - rt3(4) +10.0.255.4/32 IP TE 30 rt4 - rt4(4) +10.0.255.5/32 IP TE 30 rt2 - rt5(4) +10.0.255.6/32 IP TE 40 rt3 - rt6(4) +10.0.255.7/32 IP TE 40 rt4 - rt7(4) +10.0.255.8/32 IP TE 40 rt2 - rt8(4) + +IS-IS L1 IPv4 routing table: + + Prefix Metric Interface Nexthop Label(s) + ----------------------------------------------------- + 10.0.255.2/32 20 - rt2 - + 10.0.255.3/32 30 - rt3 - + 10.0.255.4/32 30 - rt4 - + 10.0.255.5/32 30 - rt2 - + 10.0.255.6/32 40 - rt3 - + 10.0.255.7/32 40 - rt4 - + 10.0.255.8/32 40 - rt2 - + +IS-IS paths to level-1 routers that speak IPv6 +Vertex Type Metric Next-Hop Interface Parent +rt1 +2001:db8::1/128 IP6 internal 0 rt1(4) +rt2 TE-IS 10 rt2 - rt1(4) +rt3 TE-IS 20 rt3 - rt1(4) +rt4 TE-IS 20 rt4 - rt1(4) +rt5 TE-IS 20 rt2 - rt2(4) +2001:db8::2/128 IP6 internal 20 rt2 - rt2(4) +rt6 TE-IS 30 rt3 - rt3(4) +rt7 TE-IS 30 rt4 - rt4(4) +rt8 TE-IS 30 rt2 - rt5(4) +2001:db8::3/128 IP6 internal 30 rt3 - rt3(4) +2001:db8::4/128 IP6 internal 30 rt4 - rt4(4) +2001:db8::5/128 IP6 internal 30 rt2 - rt5(4) +2001:db8::6/128 IP6 internal 40 rt3 - rt6(4) +2001:db8::7/128 IP6 internal 40 rt4 - rt7(4) +2001:db8::8/128 IP6 internal 40 rt2 - rt8(4) + +IS-IS L1 IPv6 routing table: + + Prefix Metric Interface Nexthop Label(s) + ------------------------------------------------------- + 2001:db8::2/128 20 - rt2 - + 2001:db8::3/128 30 - rt3 - + 2001:db8::4/128 30 - rt4 - + 2001:db8::5/128 30 - rt2 - + 2001:db8::6/128 40 - rt3 - + 2001:db8::7/128 40 - rt4 - + 2001:db8::8/128 40 - rt2 - + +test# test isis topology 11 root rt1 spf +IS-IS paths to level-1 routers that speak IP +Vertex Type Metric Next-Hop Interface Parent +rt1 +10.0.255.1/32 IP internal 0 rt1(4) +rt2 TE-IS 10 rt2 - rt1(4) +rt3 TE-IS 10 rt3 - rt1(4) +rt2 pseudo_TE-IS 20 rt3 - rt3(4) +rt4 TE-IS 20 rt2 - rt2(4) +rt5 TE-IS 20 rt3 - rt3(4) +10.0.255.2/32 IP TE 20 rt2 - rt2(4) +10.0.255.3/32 IP TE 20 rt3 - rt3(4) +rt6 TE-IS 30 rt2 - rt4(4) + rt3 - rt5(4) +10.0.255.4/32 IP TE 30 rt2 - rt4(4) +10.0.255.5/32 IP TE 30 rt3 - rt5(4) +10.0.255.6/32 IP TE 40 rt2 - rt6(4) + rt3 - + +IS-IS L1 IPv4 routing table: + + Prefix Metric Interface Nexthop Label(s) + ----------------------------------------------------- + 10.0.255.2/32 20 - rt2 - + 10.0.255.3/32 20 - rt3 - + 10.0.255.4/32 30 - rt2 - + 10.0.255.5/32 30 - rt3 - + 10.0.255.6/32 40 - rt2 - + - rt3 - + +IS-IS paths to level-1 routers that speak IPv6 +Vertex Type Metric Next-Hop Interface Parent +rt1 +2001:db8::1/128 IP6 internal 0 rt1(4) +rt2 TE-IS 10 rt2 - rt1(4) +rt3 TE-IS 10 rt3 - rt1(4) +rt2 pseudo_TE-IS 20 rt3 - rt3(4) +rt4 TE-IS 20 rt2 - rt2(4) +rt5 TE-IS 20 rt3 - rt3(4) +2001:db8::2/128 IP6 internal 20 rt2 - rt2(4) +2001:db8::3/128 IP6 internal 20 rt3 - rt3(4) +rt6 TE-IS 30 rt2 - rt4(4) + rt3 - rt5(4) +2001:db8::4/128 IP6 internal 30 rt2 - rt4(4) +2001:db8::5/128 IP6 internal 30 rt3 - rt5(4) +2001:db8::6/128 IP6 internal 40 rt2 - rt6(4) + rt3 - + +IS-IS L1 IPv6 routing table: + + Prefix Metric Interface Nexthop Label(s) + ------------------------------------------------------- + 2001:db8::2/128 20 - rt2 - + 2001:db8::3/128 20 - rt3 - + 2001:db8::4/128 30 - rt2 - + 2001:db8::5/128 30 - rt3 - + 2001:db8::6/128 40 - rt2 - + - rt3 - + +test# test isis topology 12 root rt1 spf ipv4-only +IS-IS paths to level-1 routers that speak IP +Vertex Type Metric Next-Hop Interface Parent +rt1 +10.0.255.1/32 IP internal 0 rt1(4) +rt2 TE-IS 10 rt2 - rt1(4) +rt3 TE-IS 10 rt3 - rt1(4) +rt4 TE-IS 20 rt2 - rt2(4) +rt5 TE-IS 20 rt3 - rt3(4) +10.0.255.2/32 IP TE 20 rt2 - rt2(4) +10.0.255.3/32 IP TE 20 rt3 - rt3(4) +rt6 TE-IS 30 rt2 - rt4(4) +rt7 TE-IS 30 rt3 - rt5(4) +10.0.255.4/32 IP TE 30 rt2 - rt4(4) +10.0.255.5/32 IP TE 30 rt3 - rt5(4) +rt8 TE-IS 40 rt2 - rt6(4) +rt9 TE-IS 40 rt3 - rt7(4) +10.0.255.6/32 IP TE 40 rt2 - rt6(4) +10.0.255.7/32 IP TE 40 rt3 - rt7(4) +rt10 TE-IS 50 rt2 - rt8(4) +10.0.255.8/32 IP TE 50 rt2 - rt8(4) +10.0.255.9/32 IP TE 50 rt3 - rt9(4) +10.0.255.10/32 IP TE 60 rt2 - rt10(4) + +IS-IS L1 IPv4 routing table: + + Prefix Metric Interface Nexthop Label(s) + ------------------------------------------------------ + 10.0.255.2/32 20 - rt2 - + 10.0.255.3/32 20 - rt3 - + 10.0.255.4/32 30 - rt2 - + 10.0.255.5/32 30 - rt3 - + 10.0.255.6/32 40 - rt2 - + 10.0.255.7/32 40 - rt3 - + 10.0.255.8/32 50 - rt2 - + 10.0.255.9/32 50 - rt3 - + 10.0.255.10/32 60 - rt2 - + +test# test isis topology 13 root rt1 spf ipv4-only +IS-IS paths to level-1 routers that speak IP +Vertex Type Metric Next-Hop Interface Parent +rt1 +10.0.255.1/32 IP internal 0 rt1(4) +rt2 TE-IS 10 rt2 - rt1(4) +rt3 TE-IS 10 rt3 - rt1(4) +rt4 TE-IS 20 rt2 - rt2(4) + rt3 - rt3(4) +rt5 TE-IS 20 rt3 - rt3(4) +rt6 TE-IS 20 rt3 - rt3(4) +10.0.255.2/32 IP TE 20 rt2 - rt2(4) +10.0.255.3/32 IP TE 20 rt3 - rt3(4) +rt7 TE-IS 30 rt3 - rt5(4) + rt6(4) +10.0.255.4/32 IP TE 30 rt2 - rt4(4) + rt3 - +10.0.255.5/32 IP TE 30 rt3 - rt5(4) +10.0.255.6/32 IP TE 30 rt3 - rt6(4) +10.0.255.7/32 IP TE 40 rt3 - rt7(4) + +IS-IS L1 IPv4 routing table: + + Prefix Metric Interface Nexthop Label(s) + ----------------------------------------------------- + 10.0.255.2/32 20 - rt2 - + 10.0.255.3/32 20 - rt3 - + 10.0.255.4/32 30 - rt2 - + - rt3 - + 10.0.255.5/32 30 - rt3 - + 10.0.255.6/32 30 - rt3 - + 10.0.255.7/32 40 - rt3 - + +test# +test# test isis topology 4 root rt1 reverse-spf ipv4-only +IS-IS paths to level-1 routers that speak IP +Vertex Type Metric Next-Hop Interface Parent +rt1 +10.0.255.1/32 IP internal 0 rt1(4) +rt2 TE-IS 10 rt2 - rt1(4) +rt3 TE-IS 10 rt3 - rt1(4) +rt4 TE-IS 20 rt2 - rt2(4) +rt5 TE-IS 20 rt3 - rt3(4) +10.0.255.2/32 IP TE 20 rt2 - rt2(4) +10.0.255.3/32 IP TE 20 rt3 - rt3(4) +rt6 TE-IS 30 rt2 - rt4(4) +rt7 TE-IS 30 rt3 - rt5(4) +10.0.255.4/32 IP TE 30 rt2 - rt4(4) +10.0.255.5/32 IP TE 30 rt3 - rt5(4) +rt8 TE-IS 40 rt2 - rt6(4) +10.0.255.6/32 IP TE 40 rt2 - rt6(4) +10.0.255.7/32 IP TE 40 rt3 - rt7(4) +10.0.255.8/32 IP TE 50 rt2 - rt8(4) + +IS-IS L1 IPv4 routing table: + + Prefix Metric Interface Nexthop Label(s) + ----------------------------------------------------- + 10.0.255.2/32 20 - rt2 - + 10.0.255.3/32 20 - rt3 - + 10.0.255.4/32 30 - rt2 - + 10.0.255.5/32 30 - rt3 - + 10.0.255.6/32 40 - rt2 - + 10.0.255.7/32 40 - rt3 - + 10.0.255.8/32 50 - rt2 - + +test# test isis topology 11 root rt1 reverse-spf +IS-IS paths to level-1 routers that speak IP +Vertex Type Metric Next-Hop Interface Parent +rt1 +10.0.255.1/32 IP internal 0 rt1(4) +rt2 TE-IS 10 rt1(4) +rt3 TE-IS 10 rt3 - rt1(4) +rt2 pseudo_TE-IS 20 rt3 - rt3(4) +rt4 TE-IS 20 rt2(4) +rt5 TE-IS 20 rt3 - rt3(4) +10.0.255.2/32 IP TE 20 rt2(4) +10.0.255.3/32 IP TE 20 rt3 - rt3(4) +rt6 TE-IS 30 rt3 - rt4(4) + rt5(4) +10.0.255.4/32 IP TE 30 rt4(4) +10.0.255.5/32 IP TE 30 rt3 - rt5(4) +10.0.255.6/32 IP TE 40 rt3 - rt6(4) + +IS-IS L1 IPv4 routing table: + + Prefix Metric Interface Nexthop Label(s) + ----------------------------------------------------- + 10.0.255.3/32 20 - rt3 - + 10.0.255.5/32 30 - rt3 - + 10.0.255.6/32 40 - rt3 - + +IS-IS paths to level-1 routers that speak IPv6 +Vertex Type Metric Next-Hop Interface Parent +rt1 +2001:db8::1/128 IP6 internal 0 rt1(4) +rt2 TE-IS 10 rt1(4) +rt3 TE-IS 10 rt3 - rt1(4) +rt2 pseudo_TE-IS 20 rt3 - rt3(4) +rt4 TE-IS 20 rt2(4) +rt5 TE-IS 20 rt3 - rt3(4) +2001:db8::2/128 IP6 internal 20 rt2(4) +2001:db8::3/128 IP6 internal 20 rt3 - rt3(4) +rt6 TE-IS 30 rt3 - rt4(4) + rt5(4) +2001:db8::4/128 IP6 internal 30 rt4(4) +2001:db8::5/128 IP6 internal 30 rt3 - rt5(4) +2001:db8::6/128 IP6 internal 40 rt3 - rt6(4) + +IS-IS L1 IPv6 routing table: + + Prefix Metric Interface Nexthop Label(s) + ------------------------------------------------------- + 2001:db8::3/128 20 - rt3 - + 2001:db8::5/128 30 - rt3 - + 2001:db8::6/128 40 - rt3 - + +test# +end. diff --git a/tests/isisd/test_isis_vertex_queue.c b/tests/isisd/test_isis_vertex_queue.c index 869dd732eb..d2d9f6293a 100644 --- a/tests/isisd/test_isis_vertex_queue.c +++ b/tests/isisd/test_isis_vertex_queue.c @@ -2,14 +2,7 @@ #include "isisd/isis_spf.c" -struct thread_master *master; -int isis_sock_init(struct isis_circuit *circuit); -int isis_sock_init(struct isis_circuit *circuit) -{ - return 0; -} - -struct zebra_privs_t isisd_privs; +#include "test_common.h" static struct isis_vertex **vertices; static size_t vertex_count; diff --git a/tests/isisd/test_topologies.c b/tests/isisd/test_topologies.c new file mode 100644 index 0000000000..ee89407a79 --- /dev/null +++ b/tests/isisd/test_topologies.c @@ -0,0 +1,3307 @@ +/* + * Copyright (C) 2020 NetDEF, Inc. + * Renato Westphal + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * 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; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "isisd/isisd.h" + +#include "test_common.h" + +/* + * clang-format off + * + * All topologies have the following properties: + * - The System-ID is 0000.0000.000X, where X is the node number (in hex); + * - The Router-ID is 10.0.255.X, where X is the node number; + * - The default link metric is 10; + * - When SR is enabled, Adj-SIDs and Prefix-SIDs are generated automatically; + * - When SR is enabled, the default SRGB is [16000-23999] (can be overriden). + * + * Test topology 1: + * ================ + * + * +---------+ + * | | + * | RT1 | + * +----------+ +----------+ + * | | | | + * | +---------+ | + * | | + * | | + * | | + * +----+----+ +----+----+ + * | | | | + * | RT2 | | RT3 | + * | | | | + * | | | | + * +----+----+ +----+----+ + * | | + * | | + * | | + * +---+-+---+ +----+----+ + * | | | | + * | RT4 | | RT5 | + * | | | | + * | | | | + * +----+----+ +----+----+ + * | | + * | | + * | | + * | +---------+ | + * | | | | + * | | RT6 | | + * +----------+ +----------+ + * | | + * +---------+ + * + * Test topology 2: + * ================ + * + * +---------+ + * | | + * | RT1 | + * +----------+ +----------+ + * | | | | + * | +----+----+ | + * | | | + * 15 | | | 30 + * | | | + * +----+----+ | +----+----+ + * | | | | | + * | RT2 | | | RT3 | + * | | | | | + * | | | | | + * +----+----+ | +----+----+ + * | | | + * 40 | | | 40 + * | | | + * +----+----+ | +----+----+ + * | | | | | + * | RT4 | | | RT5 | + * | +----------+----------+ | + * | | | | + * +----+----+ +----+----+ + * | | + * | | + * | | + * | +---------+ | + * | | | | + * | | RT6 | | + * +----------+ +----------+ + * | | + * +---------+ + * + * Test topology 3: + * ================ + * + * +---------+ + * | | + * | RT1 | + * +----------+ +----------+ + * | | | | + * | +---------+ | + * | | + * | | + * | | + * +----+----+ +----+----+ + * | | | | + * | RT2 | | RT3 | + * | +---------------------+ | + * | | | | + * +----+----+ +----+----+ + * | | + * | | 30 + * | | + * +----+----+ +----+----+ + * | | | | + * | RT4 | | RT5 | + * | +---------------------+ | + * | | | | + * +----+----+ +----+----+ + * | | + * | | + * | | + * | +---------+ | + * | | | | + * | | RT6 | | + * +----------+ +----------+ + * | | + * +---------+ + * + * Test topology 4: + * ================ + * + * +---------+ +---------+ + * | | | | + * | RT1 | | RT2 | + * | +---------------------+ | + * | | | | + * +---+-----+ +------+--+ + * | | + * | | + * | | + * +---+-----+ +------+--+ + * | | | | + * | RT3 | | RT4 | + * | | | | + * | | | | + * +---+-----+ +------+--+ + * |^ | + * ||200 | + * | | + * +---+-----+ +------+--+ + * | | | | + * | RT5 | 50 | RT6 | + * | +---------------------+ | + * | | | | + * +---+-----+ +------+--+ + * | | + * | | + * | | + * +---+-----+ +------+--+ + * | | | | + * | RT7 | | RT8 | + * | | | | + * | | | | + * +---------+ +---------+ + * + * Test topology 5: + * ================ + * + * +---------+ +---------+ + * | | | | + * | RT1 | | RT2 | + * | +---------------------+ | + * | | | | + * +---+-----+ +------+--+ + * | | + * | | + * | | + * +---+-----+ +------+--+ + * | | | | + * | RT3 | | RT4 | + * | | | | + * | | | | + * +---+-----+ +------+--+ + * | | + * | | + * | | + * +---+-----+ +------+--+ + * | | | | + * | RT5 | | RT6 | + * | | | | + * | | | | + * +---+-----+ +------+--+ + * | | + * | | + * | | + * +---+-----+ +------+--+ + * | | | | + * | RT7 | | RT8 | + * | +---------------------+ | + * | | | | + * +---------+ +---------+ + * + * Test topology 6: + * ================ + * + * +---------+ +---------+ + * | | | | + * | RT1 | | RT2 | + * | +---------------------+ | + * | | | | + * +---+-----+ +------+--+ + * | | + * | | + * | | + * +---+-----+ +------+--+ + * | | | | + * | RT3 | | RT4 | + * | +---------------------+ | + * | | | | + * +---------+ +------+--+ + * | + * | + * | + * +---------+ +------+--+ + * | | | | + * | RT5 | | RT6 | + * | +---------------------+ | + * | | | | + * +---+-----+ +------+--+ + * | | + * | | + * | | + * +---+-----+ +------+--+ + * | | | | + * | RT7 | | RT8 | + * | +---------------------+ | + * | | | | + * +---------+ +---------+ + * + * Test topology 7: + * ================ + * + * +---------+ +---------+ +---------+ + * | | | | | | + * | RT1 | 40 | RT2 | | RT3 | + * | +---------------------+ +---------------------+ | + * | | | | | | + * +---+-----+ +----+----+ +------+--+ + * | | | + * | | | + * | | | + * +---+-----+ +----+----+ +------+--+ + * | | | | | | + * | RT4 | | RT5 | | RT6 | + * | +---------------------+ +---------------------+ | + * | | | | | | + * +---+-----+ +----+----+ +------+--+ + * | | | + * | | | 30 + * | | | + * +---+-----+ +----+----+ +------+--+ + * | | | | | | + * | RT7 | | RT8 | | RT9 | + * | +---------------------+ +---------------------+ | + * | | | | | | + * +---+-----+ +----+----+ +------+--+ + * | | | + * | 20 | | + * | | | + * +---+-----+ +----+----+ +------+--+ + * | | | | | | + * | RT10 | | RT11 | | RT12 | + * | +---------------------+ +---------------------+ | + * | | | | | | + * +---------+ +---------+ +---------+ + * + * Test topology 8: + * ================ + * + * +---------+ +---------+ +---------+ + * | | | | | | + * | RT1 | | RT2 | | RT3 | + * | +---------------------+ +---------------------+ | + * | | | | | | + * +---+-----+ +----+----+ +------+--+ + * | | | + * | | | + * | | | + * +---+-----+ +----+----+ +------+--+ + * | | | | | | + * | RT4 | | RT5 | | RT6 | + * | | | +---------------------+ | + * | | | | | | + * +---+-----+ +----+----+ +---------+ + * | | + * | | + * | | + * +---+-----+ +----+----+ +---------+ + * | | | | | | + * | RT7 | | RT8 | | RT9 | + * | | | +---------------------+ | + * | | | | | | + * +---+-----+ +----+----+ +------+--+ + * | | | + * | | | + * | | | + * +---+-----+ +----+----+ +------+--+ + * | | | | | | + * | RT10 | | RT11 | | RT12 | + * | +---------------------+ +---------------------+ | + * | | 30 | | | | + * +---------+ +---------+ +---------+ + * + * Test topology 9: + * ================ + * + * +---------+ + * | | + * | RT1 | + * +----------+ +----------+ + * | | | | + * | +---------+ | + * | | + * | | + * | | + * +----+----+ +----+----+ + * | | | | + * | RT2 | | RT3 | + * | | | | + * | | | | + * +----+----+ +------+--+ + * | | + * | | + * | |100 + * | +---------+ | + * | | | | + * +----------+ RT4 +------------+ + * +----------------| |----------------+ + * | +-+ +--+ | + * | | +---------+ | | + * | | | | + * | |30 |30 |30 + * | | | | + * +----+----+ +----+----+ +----+----+ +----+----+ + * | | | | | | | | + * | RT5 | | RT6 | | RT7 | | RT8 | + * | | | | | | | | + * | | | | | | | | + * +----+----+ +----+----+ +----+----+ +----+----+ + * | | | | + * | | | | + * | | | | + * | | +---------+ | | + * | +-+ +--+ | + * +----------------+ RT9 +----------------+ + * | | + * | | + * +---------+ + * + * Test topology 10: + * ================ + * + * +---------+ + * | | + * | RT1 | + * +----------+ +----------+ + * | | | | + * | +----+----+ | + * | | | + * | |20 |20 + * | | | + * +----+----+ +----+----+ +----+----+ + * | | | | | | + * | RT2 | | RT3 | | RT4 | + * | | | | | | + * | | | | | | + * +----+----+ +----+----+ +----+----+ + * | | | + * | | | + * | | | + * +----+----+ +----+----+ +----+----+ + * | | | | | | + * | RT5 | | RT6 | | RT7 | + * | | | | | | + * | | | | | | + * +----+----+ +----+----+ +----+----+ + * | | | + * | |50 |50 + * | | | + * | +----+----+ | + * | | | | + * +----------+ RT8 +----------+ + * | | + * | | + * +---------+ + * + * Test topology 11: + * ================ + * + * +---------+ + * | | + * | RT1 | + * | | + * | | + * +----+----+ + * | + * | + * | + * +---------+ | +---------+ + * | | | | | + * | RT2 |50 | | RT3 | + * | +----------+----------+ | + * | | | | + * +----+----+ +----+----+ + * | | + * | | + * | | + * +----+----+ +----+----+ + * | | | | + * | RT4 | | RT5 | + * | +---------------------+ | + * | | | | + * +----+----+ +----+----+ + * | | + * | | + * | | + * | +---------+ | + * | | | | + * | | RT6 | | + * +----------+ +----------+ + * | | + * +---------+ + * + * Test topology 12: + * ================ + * + * +---------+ +---------+ + * | | | | + * | RT1 | | RT2 | + * | +---------------------+ | + * | | | | + * +---+-----+ +------+--+ + * | | + * | | + * | | + * +---+-----+ +------+--+ + * | | | | + * | RT3 | | RT4 | + * | | | | + * | | | | + * +---+-----+ +------+--+ + * |^ | + * |400 | + * | | + * +---+-----+ +------+--+ + * | | | | + * | RT5 | | RT6 | + * | | | | + * | | | | + * +---+-----+ +------+--+ + * |^ | + * |200 | + * | | + * +---+-----+ +------+--+ + * | | | | + * | RT7 | | RT8 | + * | +---------------------+ | + * | | 100 | | + * +---+-----+ +------+--+ + * | | + * | | + * | | + * +---+-----+ +------+--+ + * | | | | + * | RT9 | | RT10 | + * | | | | + * | | | | + * +---------+ +---------+ + * + * Test topology 13: + * ================ + * + * +---------+ +---------+ + * | | | | + * | RT1 | | RT2 | + * | +---------------------+ | + * | | | | + * +---+-----+ +----+----+ + * | | + * | | + * | | + * | +----+----+ + * | | | + * | +----------+ RT4 | + * | | | | + * +---+-----+ | | | + * | | | +----+----+ + * | RT3 +----------+ | + * | +----------+ |100 + * | | | | + * +---+-----+ | +----+----+ + * | | | | + * | | | RT5 | + * | +----------+ | + * | | | + * | +----+----+ + * | | + * | | + * | | + * +---+-----+ +----+----+ + * | | | | + * | RT6 | | RT7 | + * | +---------------------+ | + * | | | | + * +---------+ +---------+ + */ + +struct isis_topology test_topologies[] = { + { + .number = 1, + .nodes = { + { + .hostname = "rt1", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.1", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.1/32", + "2001:db8::1/128", + }, + .adjacencies = { + { + .hostname = "rt2", + .metric = 10, + }, + { + .hostname = "rt3", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt2", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.2", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.2/32", + "2001:db8::2/128", + }, + .adjacencies = { + { + .hostname = "rt1", + .metric = 10, + }, + { + .hostname = "rt4", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt3", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.3", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.3/32", + "2001:db8::3/128", + }, + .adjacencies = { + { + .hostname = "rt1", + .metric = 10, + }, + { + .hostname = "rt5", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt4", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x04}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.4", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.4/32", + "2001:db8::4/128", + }, + .adjacencies = { + { + .hostname = "rt2", + .metric = 10, + }, + { + .hostname = "rt6", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt5", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x05}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.5", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.5/32", + "2001:db8::5/128", + }, + .adjacencies = { + { + .hostname = "rt3", + .metric = 10, + }, + { + .hostname = "rt6", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt6", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x06}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.6", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.6/32", + "2001:db8::6/128", + }, + .adjacencies = { + { + .hostname = "rt4", + .metric = 10, + }, + { + .hostname = "rt5", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + }, + }, + { + .number = 2, + .nodes = { + { + .hostname = "rt1", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.1", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.1/32", + "2001:db8::1/128", + }, + .adjacencies = { + { + .hostname = "rt1", + .pseudonode_id = 1, + .metric = 10, + }, + { + .hostname = "rt2", + .metric = 15, + }, + { + .hostname = "rt3", + .metric = 30, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt2", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.2", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.2/32", + "2001:db8::2/128", + }, + .adjacencies = { + { + .hostname = "rt1", + .metric = 15, + }, + { + .hostname = "rt4", + .metric = 40, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt3", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.3", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.3/32", + "2001:db8::3/128", + }, + .adjacencies = { + { + .hostname = "rt1", + .metric = 30, + }, + { + .hostname = "rt5", + .metric = 40, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt4", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x04}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.4", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.4/32", + "2001:db8::4/128", + }, + .adjacencies = { + { + .hostname = "rt1", + .pseudonode_id = 1, + .metric = 10, + }, + { + .hostname = "rt2", + .metric = 40, + }, + { + .hostname = "rt6", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt5", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x05}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.5", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.5/32", + "2001:db8::5/128", + }, + .adjacencies = { + { + .hostname = "rt1", + .pseudonode_id = 1, + .metric = 10, + }, + { + .hostname = "rt3", + .metric = 40, + }, + { + .hostname = "rt6", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt6", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x06}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.6", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.6/32", + "2001:db8::6/128", + }, + .adjacencies = { + { + .hostname = "rt4", + .metric = 10, + }, + { + .hostname = "rt5", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt1", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + .pseudonode_id = 1, + .level = IS_LEVEL_1, + .adjacencies = { + { + .hostname = "rt1", + .metric = 0, + }, + { + .hostname = "rt4", + .metric = 0, + }, + { + .hostname = "rt5", + .metric = 0, + }, + }, + }, + }, + }, + { + .number = 3, + .nodes = { + { + .hostname = "rt1", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.1", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.1/32", + }, + .adjacencies = { + { + .hostname = "rt2", + .metric = 10, + }, + { + .hostname = "rt3", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt2", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.2", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.2/32", + }, + .adjacencies = { + { + .hostname = "rt1", + .metric = 10, + }, + { + .hostname = "rt3", + .metric = 10, + }, + { + .hostname = "rt4", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt3", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.3", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.3/32", + }, + .adjacencies = { + { + .hostname = "rt1", + .metric = 10, + }, + { + .hostname = "rt2", + .metric = 10, + }, + { + .hostname = "rt5", + .metric = 30, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt4", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x04}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.4", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.4/32", + }, + .adjacencies = { + { + .hostname = "rt2", + .metric = 10, + }, + { + .hostname = "rt5", + .metric = 10, + }, + { + .hostname = "rt6", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt5", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x05}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.5", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.5/32", + }, + .adjacencies = { + { + .hostname = "rt3", + .metric = 30, + }, + { + .hostname = "rt4", + .metric = 10, + }, + { + .hostname = "rt6", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt6", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x06}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.6", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.6/32", + }, + .adjacencies = { + { + .hostname = "rt4", + .metric = 10, + }, + { + .hostname = "rt5", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + }, + }, + { + .number = 4, + .nodes = { + { + .hostname = "rt1", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.1", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.1/32", + }, + .adjacencies = { + { + .hostname = "rt2", + .metric = 10, + }, + { + .hostname = "rt3", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt2", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.2", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.2/32", + }, + .adjacencies = { + { + .hostname = "rt1", + .metric = 10, + }, + { + .hostname = "rt4", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt3", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.3", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.3/32", + }, + .adjacencies = { + { + .hostname = "rt1", + .metric = 10, + }, + { + .hostname = "rt5", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt4", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x04}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.4", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.4/32", + }, + .adjacencies = { + { + .hostname = "rt2", + .metric = 10, + }, + { + .hostname = "rt6", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt5", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x05}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.5", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.5/32", + }, + .adjacencies = { + { + .hostname = "rt3", + .metric = 200, + }, + { + .hostname = "rt6", + .metric = 50, + }, + { + .hostname = "rt7", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt6", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x06}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.6", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.6/32", + }, + .adjacencies = { + { + .hostname = "rt4", + .metric = 10, + }, + { + .hostname = "rt5", + .metric = 50, + }, + { + .hostname = "rt8", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt7", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x07}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.7", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.7/32", + }, + .adjacencies = { + { + .hostname = "rt5", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt8", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x08}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.8", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.8/32", + }, + .adjacencies = { + { + .hostname = "rt6", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + }, + }, + { + .number = 5, + .nodes = { + { + .hostname = "rt1", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.1", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.1/32", + }, + .adjacencies = { + { + .hostname = "rt2", + .metric = 10, + }, + { + .hostname = "rt3", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt2", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.2", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.2/32", + }, + .adjacencies = { + { + .hostname = "rt1", + .metric = 10, + }, + { + .hostname = "rt4", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt3", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.3", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.3/32", + }, + .adjacencies = { + { + .hostname = "rt1", + .metric = 10, + }, + { + .hostname = "rt5", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt4", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x04}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.4", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.4/32", + }, + .adjacencies = { + { + .hostname = "rt2", + .metric = 10, + }, + { + .hostname = "rt6", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt5", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x05}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.5", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.5/32", + }, + .adjacencies = { + { + .hostname = "rt3", + .metric = 10, + }, + { + .hostname = "rt7", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt6", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x06}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.6", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.6/32", + }, + .adjacencies = { + { + .hostname = "rt4", + .metric = 10, + }, + { + .hostname = "rt8", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt7", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x07}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.7", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.7/32", + }, + .adjacencies = { + { + .hostname = "rt5", + .metric = 10, + }, + { + .hostname = "rt8", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt8", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x08}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.8", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.8/32", + }, + .adjacencies = { + { + .hostname = "rt6", + .metric = 10, + }, + { + .hostname = "rt7", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + }, + }, + { + .number = 6, + .nodes = { + { + .hostname = "rt1", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.1", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.1/32", + }, + .adjacencies = { + { + .hostname = "rt2", + .metric = 10, + }, + { + .hostname = "rt3", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt2", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.2", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.2/32", + }, + .adjacencies = { + { + .hostname = "rt1", + .metric = 10, + }, + { + .hostname = "rt4", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt3", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.3", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.3/32", + }, + .adjacencies = { + { + .hostname = "rt1", + .metric = 10, + }, + { + .hostname = "rt4", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt4", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x04}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.4", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.4/32", + }, + .adjacencies = { + { + .hostname = "rt2", + .metric = 10, + }, + { + .hostname = "rt3", + .metric = 10, + }, + { + .hostname = "rt6", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt5", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x05}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.5", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.5/32", + }, + .adjacencies = { + { + .hostname = "rt6", + .metric = 10, + }, + { + .hostname = "rt7", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt6", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x06}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.6", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.6/32", + }, + .adjacencies = { + { + .hostname = "rt4", + .metric = 10, + }, + { + .hostname = "rt5", + .metric = 10, + }, + { + .hostname = "rt8", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt7", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x07}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.7", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.7/32", + }, + .adjacencies = { + { + .hostname = "rt5", + .metric = 10, + }, + { + .hostname = "rt8", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt8", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x08}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.8", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.8/32", + }, + .adjacencies = { + { + .hostname = "rt6", + .metric = 10, + }, + { + .hostname = "rt7", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + }, + }, + { + .number = 7, + .nodes = { + { + .hostname = "rt1", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.1", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.1/32", + }, + .adjacencies = { + { + .hostname = "rt2", + .metric = 40, + }, + { + .hostname = "rt4", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt2", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.2", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.2/32", + }, + .adjacencies = { + { + .hostname = "rt1", + .metric = 40, + }, + { + .hostname = "rt3", + .metric = 10, + }, + { + .hostname = "rt5", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt3", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.3", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.3/32", + }, + .adjacencies = { + { + .hostname = "rt2", + .metric = 10, + }, + { + .hostname = "rt6", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt4", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x04}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.4", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.4/32", + }, + .adjacencies = { + { + .hostname = "rt1", + .metric = 10, + }, + { + .hostname = "rt5", + .metric = 10, + }, + { + .hostname = "rt7", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt5", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x05}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.5", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.5/32", + }, + .adjacencies = { + { + .hostname = "rt2", + .metric = 10, + }, + { + .hostname = "rt4", + .metric = 10, + }, + { + .hostname = "rt6", + .metric = 10, + }, + { + .hostname = "rt8", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt6", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x06}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.6", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.6/32", + }, + .adjacencies = { + { + .hostname = "rt3", + .metric = 10, + }, + { + .hostname = "rt5", + .metric = 10, + }, + { + .hostname = "rt9", + .metric = 30, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt7", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x07}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.7", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.7/32", + }, + .adjacencies = { + { + .hostname = "rt4", + .metric = 10, + }, + { + .hostname = "rt8", + .metric = 10, + }, + { + .hostname = "rt10", + .metric = 20, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt8", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x08}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.8", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.8/32", + }, + .adjacencies = { + { + .hostname = "rt5", + .metric = 10, + }, + { + .hostname = "rt7", + .metric = 10, + }, + { + .hostname = "rt9", + .metric = 10, + }, + { + .hostname = "rt11", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt9", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x09}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.9", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.9/32", + }, + .adjacencies = { + { + .hostname = "rt6", + .metric = 30, + }, + { + .hostname = "rt8", + .metric = 10, + }, + { + .hostname = "rt12", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt10", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x0a}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.10", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.10/32", + }, + .adjacencies = { + { + .hostname = "rt7", + .metric = 20, + }, + { + .hostname = "rt11", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt11", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x0b}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.11", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.11/32", + }, + .adjacencies = { + { + .hostname = "rt8", + .metric = 10, + }, + { + .hostname = "rt10", + .metric = 10, + }, + { + .hostname = "rt12", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt12", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x0c}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.12", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.12/32", + }, + .adjacencies = { + { + .hostname = "rt9", + .metric = 10, + }, + { + .hostname = "rt11", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + }, + }, + { + .number = 8, + .nodes = { + { + .hostname = "rt1", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.1", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.1/32", + }, + .adjacencies = { + { + .hostname = "rt2", + .metric = 10, + }, + { + .hostname = "rt4", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt2", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.2", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.2/32", + }, + .adjacencies = { + { + .hostname = "rt1", + .metric = 10, + }, + { + .hostname = "rt3", + .metric = 10, + }, + { + .hostname = "rt5", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt3", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.3", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.3/32", + }, + .adjacencies = { + { + .hostname = "rt2", + .metric = 10, + }, + { + .hostname = "rt6", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt4", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x04}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.4", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.4/32", + }, + .adjacencies = { + { + .hostname = "rt1", + .metric = 10, + }, + { + .hostname = "rt7", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt5", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x05}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.5", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.5/32", + }, + .adjacencies = { + { + .hostname = "rt2", + .metric = 10, + }, + { + .hostname = "rt6", + .metric = 10, + }, + { + .hostname = "rt8", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt6", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x06}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.6", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.6/32", + }, + .adjacencies = { + { + .hostname = "rt3", + .metric = 10, + }, + { + .hostname = "rt5", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt7", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x07}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.7", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.7/32", + }, + .adjacencies = { + { + .hostname = "rt4", + .metric = 10, + }, + { + .hostname = "rt10", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt8", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x08}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.8", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.8/32", + }, + .adjacencies = { + { + .hostname = "rt5", + .metric = 10, + }, + { + .hostname = "rt9", + .metric = 10, + }, + { + .hostname = "rt11", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt9", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x09}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.9", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.9/32", + }, + .adjacencies = { + { + .hostname = "rt8", + .metric = 10, + }, + { + .hostname = "rt12", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt10", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x0a}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.10", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.10/32", + }, + .adjacencies = { + { + .hostname = "rt7", + .metric = 10, + }, + { + .hostname = "rt11", + .metric = 30, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt11", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x0b}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.11", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.11/32", + }, + .adjacencies = { + { + .hostname = "rt8", + .metric = 10, + }, + { + .hostname = "rt10", + .metric = 30, + }, + { + .hostname = "rt12", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt12", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x0c}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.12", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.12/32", + }, + .adjacencies = { + { + .hostname = "rt9", + .metric = 10, + }, + { + .hostname = "rt11", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + }, + }, + { + .number = 9, + .nodes = { + { + .hostname = "rt1", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.1", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.1/32", + "2001:db8::1/128", + }, + .adjacencies = { + { + .hostname = "rt2", + .metric = 10, + }, + { + .hostname = "rt3", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt2", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.2", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.2/32", + "2001:db8::2/128", + }, + .adjacencies = { + { + .hostname = "rt1", + .metric = 10, + }, + { + .hostname = "rt4", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt3", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.3", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.3/32", + "2001:db8::3/128", + }, + .adjacencies = { + { + .hostname = "rt1", + .metric = 10, + }, + { + .hostname = "rt4", + .metric = 100, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt4", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x04}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.4", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.4/32", + "2001:db8::4/128", + }, + .adjacencies = { + { + .hostname = "rt2", + .metric = 10, + }, + { + .hostname = "rt3", + .metric = 100, + }, + { + .hostname = "rt5", + .metric = 10, + }, + { + .hostname = "rt6", + .metric = 30, + }, + { + .hostname = "rt7", + .metric = 30, + }, + { + .hostname = "rt8", + .metric = 30, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt5", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x05}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.5", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.5/32", + "2001:db8::5/128", + }, + .adjacencies = { + { + .hostname = "rt4", + .metric = 10, + }, + { + .hostname = "rt9", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt6", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x06}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.6", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.6/32", + "2001:db8::6/128", + }, + .adjacencies = { + { + .hostname = "rt4", + .metric = 30, + }, + { + .hostname = "rt9", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt7", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x07}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.7", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.7/32", + "2001:db8::7/128", + }, + .adjacencies = { + { + .hostname = "rt4", + .metric = 30, + }, + { + .hostname = "rt9", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt8", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x08}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.8", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.8/32", + "2001:db8::8/128", + }, + .adjacencies = { + { + .hostname = "rt4", + .metric = 30, + }, + { + .hostname = "rt9", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt9", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x09}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.9", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.9/32", + "2001:db8::9/128", + }, + .adjacencies = { + { + .hostname = "rt5", + .metric = 10, + }, + { + .hostname = "rt6", + .metric = 10, + }, + { + .hostname = "rt7", + .metric = 10, + }, + { + .hostname = "rt8", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + }, + }, + { + .number = 10, + .nodes = { + { + .hostname = "rt1", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.1", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.1/32", + "2001:db8::1/128", + }, + .adjacencies = { + { + .hostname = "rt2", + .metric = 10, + }, + { + .hostname = "rt3", + .metric = 20, + }, + { + .hostname = "rt4", + .metric = 20, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt2", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.2", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.2/32", + "2001:db8::2/128", + }, + .adjacencies = { + { + .hostname = "rt1", + .metric = 10, + }, + { + .hostname = "rt5", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt3", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.3", + .srgb = { + .lower_bound = 20000, + .range_size = 8000, + }, + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.3/32", + "2001:db8::3/128", + }, + .adjacencies = { + { + .hostname = "rt1", + .metric = 20, + }, + { + .hostname = "rt6", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt4", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x04}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.4", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.4/32", + "2001:db8::4/128", + }, + .adjacencies = { + { + .hostname = "rt1", + .metric = 20, + }, + { + .hostname = "rt7", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt5", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x05}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.5", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.5/32", + "2001:db8::5/128", + }, + .adjacencies = { + { + .hostname = "rt2", + .metric = 10, + }, + { + .hostname = "rt8", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt6", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x06}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.6", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.6/32", + "2001:db8::6/128", + }, + .adjacencies = { + { + .hostname = "rt3", + .metric = 10, + }, + { + .hostname = "rt8", + .metric = 50, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt7", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x07}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.7", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.7/32", + "2001:db8::7/128", + }, + .adjacencies = { + { + .hostname = "rt4", + .metric = 10, + }, + { + .hostname = "rt8", + .metric = 50, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt8", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x08}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.8", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.8/32", + "2001:db8::8/128", + }, + .adjacencies = { + { + .hostname = "rt5", + .metric = 10, + }, + { + .hostname = "rt6", + .metric = 50, + }, + { + .hostname = "rt7", + .metric = 50, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + }, + }, + { + .number = 11, + .nodes = { + { + .hostname = "rt1", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.1", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.1/32", + "2001:db8::1/128", + }, + .adjacencies = { + { + .hostname = "rt2", + .pseudonode_id = 1, + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt2", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.2", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.2/32", + "2001:db8::2/128", + }, + .adjacencies = { + { + .hostname = "rt2", + .pseudonode_id = 1, + .metric = 50, + }, + { + .hostname = "rt4", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt3", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.3", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.3/32", + "2001:db8::3/128", + }, + .adjacencies = { + { + .hostname = "rt2", + .pseudonode_id = 1, + .metric = 10, + }, + { + .hostname = "rt5", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt4", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x04}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.4", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.4/32", + "2001:db8::4/128", + }, + .adjacencies = { + { + .hostname = "rt2", + .metric = 10, + }, + { + .hostname = "rt5", + .metric = 10, + }, + { + .hostname = "rt6", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt5", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x05}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.5", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.5/32", + "2001:db8::5/128", + }, + .adjacencies = { + { + .hostname = "rt3", + .metric = 10, + }, + { + .hostname = "rt4", + .metric = 10, + }, + { + .hostname = "rt6", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt6", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x06}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.6", + .protocols = { + .ipv4 = true, + .ipv6 = true, + }, + .networks = { + "10.0.255.6/32", + "2001:db8::6/128", + }, + .adjacencies = { + { + .hostname = "rt4", + .metric = 10, + }, + { + .hostname = "rt5", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt2", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + .pseudonode_id = 1, + .level = IS_LEVEL_1, + .adjacencies = { + { + .hostname = "rt1", + .metric = 0, + }, + { + .hostname = "rt2", + .metric = 0, + }, + { + .hostname = "rt3", + .metric = 0, + }, + }, + }, + }, + }, + { + .number = 12, + .nodes = { + { + .hostname = "rt1", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.1", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.1/32", + }, + .adjacencies = { + { + .hostname = "rt2", + .metric = 10, + }, + { + .hostname = "rt3", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt2", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.2", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.2/32", + }, + .adjacencies = { + { + .hostname = "rt1", + .metric = 10, + }, + { + .hostname = "rt4", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt3", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.3", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.3/32", + }, + .adjacencies = { + { + .hostname = "rt1", + .metric = 10, + }, + { + .hostname = "rt5", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt4", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x04}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.4", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.4/32", + }, + .adjacencies = { + { + .hostname = "rt2", + .metric = 10, + }, + { + .hostname = "rt6", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt5", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x05}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.5", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.5/32", + }, + .adjacencies = { + { + .hostname = "rt3", + .metric = 400, + }, + { + .hostname = "rt7", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt6", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x06}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.6", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.6/32", + }, + .adjacencies = { + { + .hostname = "rt4", + .metric = 10, + }, + { + .hostname = "rt8", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt7", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x07}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.7", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.7/32", + }, + .adjacencies = { + { + .hostname = "rt5", + .metric = 200, + }, + { + .hostname = "rt8", + .metric = 100, + }, + { + .hostname = "rt9", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt8", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x08}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.8", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.8/32", + }, + .adjacencies = { + { + .hostname = "rt6", + .metric = 10, + }, + { + .hostname = "rt7", + .metric = 100, + }, + { + .hostname = "rt10", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt9", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x09}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.9", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.9/32", + }, + .adjacencies = { + { + .hostname = "rt7", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt10", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x0a}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.10", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.10/32", + }, + .adjacencies = { + { + .hostname = "rt8", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + }, + }, + { + .number = 13, + .nodes = { + { + .hostname = "rt1", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.1", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.1/32", + }, + .adjacencies = { + { + .hostname = "rt2", + .metric = 10, + }, + { + .hostname = "rt3", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt2", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.2", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.2/32", + }, + .adjacencies = { + { + .hostname = "rt1", + .metric = 10, + }, + { + .hostname = "rt4", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt3", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.3", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.3/32", + }, + .adjacencies = { + { + .hostname = "rt1", + .metric = 10, + }, + { + .hostname = "rt4", + .metric = 10, + }, + { + .hostname = "rt5", + .metric = 10, + }, + { + .hostname = "rt6", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt4", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x04}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.4", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.4/32", + }, + .adjacencies = { + { + .hostname = "rt2", + .metric = 10, + }, + { + .hostname = "rt3", + .metric = 10, + }, + { + .hostname = "rt5", + .metric = 100, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt5", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x05}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.5", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.5/32", + }, + .adjacencies = { + { + .hostname = "rt3", + .metric = 10, + }, + { + .hostname = "rt4", + .metric = 100, + }, + { + .hostname = "rt7", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt6", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x06}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.6", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.6/32", + }, + .adjacencies = { + { + .hostname = "rt3", + .metric = 10, + }, + { + .hostname = "rt7", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + { + .hostname = "rt7", + .sysid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x07}, + .level = IS_LEVEL_1, + .router_id = "10.0.255.7", + .protocols = { + .ipv4 = true, + }, + .networks = { + "10.0.255.7/32", + }, + .adjacencies = { + { + .hostname = "rt5", + .metric = 10, + }, + { + .hostname = "rt6", + .metric = 10, + }, + }, + .flags = F_ISIS_TEST_NODE_SR, + }, + }, + }, + { + /* sentinel */ + }, +}; diff --git a/tests/subdir.am b/tests/subdir.am index 04053a6f46..e54bfc4a35 100644 --- a/tests/subdir.am +++ b/tests/subdir.am @@ -23,6 +23,7 @@ else TESTS_ISISD = \ tests/isisd/test_fuzz_isis_tlv \ tests/isisd/test_isis_lspdb \ + tests/isisd/test_isis_spf \ tests/isisd/test_isis_vertex_queue \ # end endif @@ -111,6 +112,7 @@ noinst_HEADERS += \ tests/helpers/c/tests.h \ tests/lib/cli/common_cli.h \ tests/lib/test_typelist.h \ + tests/isisd/test_common.h \ # end # @@ -168,16 +170,21 @@ tests_bgpd_test_peer_attr_SOURCES = tests/bgpd/test_peer_attr.c tests_isisd_test_fuzz_isis_tlv_CFLAGS = $(TESTS_CFLAGS) -I$(top_builddir)/tests/isisd tests_isisd_test_fuzz_isis_tlv_CPPFLAGS = $(TESTS_CPPFLAGS) -I$(top_builddir)/tests/isisd tests_isisd_test_fuzz_isis_tlv_LDADD = $(ISISD_TEST_LDADD) -tests_isisd_test_fuzz_isis_tlv_SOURCES = tests/isisd/test_fuzz_isis_tlv.c +tests_isisd_test_fuzz_isis_tlv_SOURCES = tests/isisd/test_fuzz_isis_tlv.c tests/isisd/test_common.c nodist_tests_isisd_test_fuzz_isis_tlv_SOURCES = tests/isisd/test_fuzz_isis_tlv_tests.h tests_isisd_test_isis_lspdb_CFLAGS = $(TESTS_CFLAGS) tests_isisd_test_isis_lspdb_CPPFLAGS = $(TESTS_CPPFLAGS) tests_isisd_test_isis_lspdb_LDADD = $(ISISD_TEST_LDADD) -tests_isisd_test_isis_lspdb_SOURCES = tests/isisd/test_isis_lspdb.c +tests_isisd_test_isis_lspdb_SOURCES = tests/isisd/test_isis_lspdb.c tests/isisd/test_common.c +tests_isisd_test_isis_spf_CFLAGS = $(TESTS_CFLAGS) +tests_isisd_test_isis_spf_CPPFLAGS = $(TESTS_CPPFLAGS) +tests_isisd_test_isis_spf_LDADD = $(ISISD_TEST_LDADD) +tests_isisd_test_isis_spf_SOURCES = tests/isisd/test_isis_spf.c tests/isisd/test_common.c tests/isisd/test_topologies.c +nodist_tests_isisd_test_isis_spf_SOURCES = yang/frr-isisd.yang.c tests_isisd_test_isis_vertex_queue_CFLAGS = $(TESTS_CFLAGS) tests_isisd_test_isis_vertex_queue_CPPFLAGS = $(TESTS_CPPFLAGS) tests_isisd_test_isis_vertex_queue_LDADD = $(ISISD_TEST_LDADD) -tests_isisd_test_isis_vertex_queue_SOURCES = tests/isisd/test_isis_vertex_queue.c +tests_isisd_test_isis_vertex_queue_SOURCES = tests/isisd/test_isis_vertex_queue.c tests/isisd/test_common.c tests_lib_cxxcompat_CFLAGS = $(TESTS_CFLAGS) $(CXX_COMPAT_CFLAGS) $(WERROR) tests_lib_cxxcompat_CPPFLAGS = $(TESTS_CPPFLAGS) @@ -327,6 +334,9 @@ EXTRA_DIST += \ tests/isisd/test_fuzz_isis_tlv.py \ tests/isisd/test_fuzz_isis_tlv_tests.h.gz \ tests/isisd/test_isis_lspdb.py \ + tests/isisd/test_isis_spf.py \ + tests/isisd/test_isis_spf.in \ + tests/isisd/test_isis_spf.refout \ tests/isisd/test_isis_vertex_queue.py \ tests/lib/cli/test_commands.in \ tests/lib/cli/test_commands.py \