summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.md2
-rw-r--r--doc/user/conf.py27
-rw-r--r--doc/user/isisd.rst4
-rw-r--r--isisd/fabricd.c5
-rw-r--r--isisd/isis_adjacency.c4
-rw-r--r--isisd/isis_dynhn.c16
-rw-r--r--isisd/isis_dynhn.h1
-rw-r--r--isisd/isis_lsp.c154
-rw-r--r--isisd/isis_lsp.h20
-rw-r--r--isisd/isis_main.c2
-rw-r--r--isisd/isis_misc.c5
-rw-r--r--isisd/isis_misc.h2
-rw-r--r--isisd/isis_route.c28
-rw-r--r--isisd/isis_spf.c1103
-rw-r--r--isisd/isis_spf.h31
-rw-r--r--isisd/isis_spf_private.h20
-rw-r--r--isisd/isis_sr.c18
-rw-r--r--isisd/isis_te.c8
-rw-r--r--isisd/isisd.c248
-rw-r--r--isisd/isisd.h6
-rw-r--r--ospfd/ospf_ext.c8
-rw-r--r--ospfd/ospf_ri.c23
-rw-r--r--ospfd/ospf_sr.c44
-rw-r--r--pimd/pim_iface.c8
-rw-r--r--pimd/pim_iface.h2
-rw-r--r--pimd/pim_igmp.c12
-rw-r--r--pimd/pim_mroute.c50
-rw-r--r--tests/.gitignore1
-rw-r--r--tests/isisd/test_common.c331
-rw-r--r--tests/isisd/test_common.h82
-rw-r--r--tests/isisd/test_fuzz_isis_tlv.c11
-rw-r--r--tests/isisd/test_isis_lspdb.c10
-rw-r--r--tests/isisd/test_isis_spf.c313
-rw-r--r--tests/isisd/test_isis_spf.in16
-rw-r--r--tests/isisd/test_isis_spf.py4
-rw-r--r--tests/isisd/test_isis_spf.refout703
-rw-r--r--tests/isisd/test_isis_vertex_queue.c9
-rw-r--r--tests/isisd/test_topologies.c3307
-rw-r--r--tests/subdir.am16
39 files changed, 6043 insertions, 611 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 1209f52e14..98c7c3d54d 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -37,7 +37,7 @@ If applicable, add screenshots to help explain your problem.
**Versions**
- OS Kernel: [e.g. Linux, OpenBSD, etc] [version]
- - FRR Version [version]
+ - FRR Version: [version]
**Additional context**
Add any other context about the problem here.
diff --git a/doc/user/conf.py b/doc/user/conf.py
index d8a188b152..1f6f050bcf 100644
--- a/doc/user/conf.py
+++ b/doc/user/conf.py
@@ -16,6 +16,7 @@ import sys
import os
import re
import pygments
+import sphinx
from sphinx.highlighting import lexers
# If extensions (or modules to document with autodoc) are in another directory,
@@ -359,14 +360,36 @@ texinfo_documents = [
with open('../extra/frrlexer.py', 'rb') as lex:
frrlexerpy = lex.read()
+# Parse version string into int array
+def vparse(s):
+ a = []
+
+ for c in s:
+ if c != '.':
+ a.append(int(c))
+
+ while len(a) < 3:
+ a.append(0)
+
+ return a[:3]
+
# custom extensions here
def setup(app):
# object type for FRR CLI commands, can be extended to document parent CLI
# node later on
app.add_object_type('clicmd', 'clicmd')
+
# css overrides for HTML theme
- app.add_stylesheet('overrides.css')
- app.add_javascript('overrides.js')
+ # Note sphinx version differences
+ sver = vparse(sphinx.__version__)
+
+ if sver < vparse('1.8.0') :
+ app.add_stylesheet('overrides.css')
+ app.add_javascript('overrides.js')
+ else:
+ app.add_css_file('overrides.css')
+ app.add_js_file('overrides.js')
+
# load Pygments lexer for FRR config syntax
#
# NB: in Pygments 2.2+ this can be done with `load_lexer_from_file`, but we
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;
-
- 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)
+ struct listnode *node;
+
+ 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);
}
- 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);
- }
+ }
+}
+
+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;
}
- 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;
+
+ /* 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);
}
- 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;
+ }
+
+ 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);
}
- } 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 <NAME|all>] route"
+#ifndef FABRICD
+ " [<level-1|level-2>]"
+#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 <N, d(N), {Adj(N)}>
*/
@@ -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/ospfd/ospf_ext.c b/ospfd/ospf_ext.c
index bc952e4ef9..90dc108c0e 100644
--- a/ospfd/ospf_ext.c
+++ b/ospfd/ospf_ext.c
@@ -563,9 +563,9 @@ static void ospf_ext_link_update_adj_sid(struct ext_itf *exti)
set_adj_sid(exti, true, bck_label, SID_LABEL);
set_adj_sid(exti, false, label, SID_LABEL);
} else {
- set_lan_adj_sid(exti, true, bck_label, SID_LABEL,
+ set_lan_adj_sid(exti, true, bck_label, SID_LABEL,
exti->lan_sid[0].neighbor_id);
- set_lan_adj_sid(exti, false, label, SID_LABEL,
+ set_lan_adj_sid(exti, false, label, SID_LABEL,
exti->lan_sid[1].neighbor_id);
}
@@ -590,8 +590,8 @@ static void ospf_ext_link_delete_adj_sid(struct ext_itf *exti)
ospf_sr_local_block_release_label(exti->adj_sid[0].value);
ospf_sr_local_block_release_label(exti->adj_sid[1].value);
} else {
- ospf_sr_local_block_release_label(exti->adj_sid[0].value);
- ospf_sr_local_block_release_label(exti->adj_sid[1].value);
+ ospf_sr_local_block_release_label(exti->lan_sid[0].value);
+ ospf_sr_local_block_release_label(exti->lan_sid[1].value);
}
/* And reset corresponding TLV */
unset_adjacency_sid(exti);
diff --git a/ospfd/ospf_ri.c b/ospfd/ospf_ri.c
index 8eeaf7be3c..fc9c8f6be6 100644
--- a/ospfd/ospf_ri.c
+++ b/ospfd/ospf_ri.c
@@ -573,20 +573,23 @@ static void initialize_params(struct ospf_router_info *ori)
return;
}
-static int is_mandated_params_set(struct ospf_router_info ori)
+static int is_mandated_params_set(struct ospf_router_info *ori)
{
int rc = 0;
- if (ntohs(ori.router_cap.header.type) == 0)
+ if (ori == NULL)
return rc;
- if ((ntohs(ori.pce_info.pce_header.header.type) == RI_TLV_PCE)
- && (ntohs(ori.pce_info.pce_address.header.type) == 0)
- && (ntohs(ori.pce_info.pce_cap_flag.header.type) == 0))
+ if (ntohs(ori->router_cap.header.type) == 0)
return rc;
- if ((ori.sr_info.enabled) && (ntohs(TLV_TYPE(ori.sr_info.algo)) == 0)
- && (ntohs(TLV_TYPE(ori.sr_info.srgb)) == 0))
+ if ((ntohs(ori->pce_info.pce_header.header.type) == RI_TLV_PCE)
+ && (ntohs(ori->pce_info.pce_address.header.type) == 0)
+ && (ntohs(ori->pce_info.pce_cap_flag.header.type) == 0))
+ return rc;
+
+ if ((ori->sr_info.enabled) && (ntohs(TLV_TYPE(ori->sr_info.algo)) == 0)
+ && (ntohs(TLV_TYPE(ori->sr_info.srgb)) == 0))
return rc;
rc = 1;
@@ -626,6 +629,10 @@ void ospf_router_info_update_sr(bool enable, struct sr_node *srn)
initialize_params(&OspfRI);
}
+ /* Check that SR node is valid */
+ if (srn == NULL)
+ return;
+
if (IS_DEBUG_OSPF_SR)
zlog_debug("RI (%s): %s Routing Information for Segment Routing",
__func__, enable ? "Enable" : "Disable");
@@ -986,7 +993,7 @@ static int ospf_router_info_lsa_originate(void *arg)
}
/* Router Information is not yet Engaged, check parameters */
- if (!is_mandated_params_set(OspfRI))
+ if (!is_mandated_params_set(&OspfRI))
flog_warn(
EC_OSPF_LSA,
"RI (%s): lacks mandated ROUTER INFORMATION parameters",
diff --git a/ospfd/ospf_sr.c b/ospfd/ospf_sr.c
index f6a190db80..eb882c5d0e 100644
--- a/ospfd/ospf_sr.c
+++ b/ospfd/ospf_sr.c
@@ -2074,13 +2074,17 @@ static int update_srgb(uint32_t lower, uint32_t size)
osr_debug("SR(%s): Got new SRGB [%u/%u]", __func__, OspfSR.srgb.start,
OspfSR.srgb.start + OspfSR.srgb.size - 1);
- /* SRGB is reserved, set Router Information parameters */
- ospf_router_info_update_sr(true, OspfSR.self);
+ /* Update Self SR-Node */
+ if (OspfSR.self != NULL) {
+ /* SRGB is reserved, set Router Information parameters */
+ ospf_router_info_update_sr(true, OspfSR.self);
- /* and update NHLFE entries */
- hash_iterate(OspfSR.neighbors,
- (void (*)(struct hash_bucket *, void *))update_in_nhlfe,
- NULL);
+ /* and update NHLFE entries */
+ hash_iterate(
+ OspfSR.neighbors,
+ (void (*)(struct hash_bucket *, void *))update_in_nhlfe,
+ NULL);
+ }
return 0;
}
@@ -2198,9 +2202,11 @@ DEFUN (sr_local_label_range,
}
/* SRLB is reserved, Update Self SR-Node and Router Information LSA */
- OspfSR.self->srlb.lower_bound = lower;
- OspfSR.self->srlb.range_size = upper - lower + 1;
- ospf_router_info_update_sr(true, OspfSR.self);
+ if (OspfSR.self != NULL) {
+ OspfSR.self->srlb.lower_bound = lower;
+ OspfSR.self->srlb.range_size = upper - lower + 1;
+ ospf_router_info_update_sr(true, OspfSR.self);
+ }
/* and update (LAN)-Adjacency SID */
ospf_ext_link_srlb_update();
@@ -2250,8 +2256,8 @@ DEFUN (no_sr_local_label_range,
if (OspfSR.self != NULL) {
OspfSR.self->srlb.lower_bound = DEFAULT_SRLB_LABEL;
OspfSR.self->srlb.range_size = DEFAULT_SRLB_SIZE;
+ ospf_router_info_update_sr(true, OspfSR.self);
}
- ospf_router_info_update_sr(true, OspfSR.self);
/* and update (LAN)-Adjacency SID */
ospf_ext_link_srlb_update();
@@ -2287,12 +2293,13 @@ DEFUN (sr_node_msd,
/* Set this router MSD */
OspfSR.msd = msd;
- if (OspfSR.self != NULL)
+ if (OspfSR.self != NULL) {
OspfSR.self->msd = msd;
- /* Set Router Information parameters if SR is UP */
- if (OspfSR.status == SR_UP)
- ospf_router_info_update_sr(true, OspfSR.self);
+ /* Set Router Information parameters if SR is UP */
+ if (OspfSR.status == SR_UP)
+ ospf_router_info_update_sr(true, OspfSR.self);
+ }
return CMD_SUCCESS;
}
@@ -2311,12 +2318,13 @@ DEFUN (no_sr_node_msd,
/* unset this router MSD */
OspfSR.msd = 0;
- if (OspfSR.self != NULL)
+ if (OspfSR.self != NULL) {
OspfSR.self->msd = 0;
- /* Set Router Information parameters if SR is UP */
- if (OspfSR.status == SR_UP)
- ospf_router_info_update_sr(true, OspfSR.self);
+ /* Set Router Information parameters if SR is UP */
+ if (OspfSR.status == SR_UP)
+ ospf_router_info_update_sr(true, OspfSR.self);
+ }
return CMD_SUCCESS;
}
diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c
index 88bcc48f80..0caa360df9 100644
--- a/pimd/pim_iface.c
+++ b/pimd/pim_iface.c
@@ -1504,14 +1504,14 @@ void pim_if_create_pimreg(struct pim_instance *pim)
}
}
-int pim_if_connected_to_source(struct interface *ifp, struct in_addr src)
+struct prefix *pim_if_connected_to_source(struct interface *ifp, struct in_addr src)
{
struct listnode *cnode;
struct connected *c;
struct prefix p;
if (!ifp)
- return 0;
+ return NULL;
p.family = AF_INET;
p.u.prefix4 = src;
@@ -1520,11 +1520,11 @@ int pim_if_connected_to_source(struct interface *ifp, struct in_addr src)
for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
if ((c->address->family == AF_INET)
&& prefix_match(CONNECTED_PREFIX(c), &p)) {
- return 1;
+ return CONNECTED_PREFIX(c);
}
}
- return 0;
+ return NULL;
}
bool pim_if_is_vrf_device(struct interface *ifp)
diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h
index 13aaf8d3b2..8decfef74d 100644
--- a/pimd/pim_iface.h
+++ b/pimd/pim_iface.h
@@ -223,7 +223,7 @@ void pim_if_update_assert_tracking_desired(struct interface *ifp);
void pim_if_create_pimreg(struct pim_instance *pim);
-int pim_if_connected_to_source(struct interface *ifp, struct in_addr src);
+struct prefix *pim_if_connected_to_source(struct interface *ifp, struct in_addr src);
int pim_update_source_set(struct interface *ifp, struct in_addr source);
bool pim_if_is_vrf_device(struct interface *ifp);
diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c
index a8612f91fa..20f339d43f 100644
--- a/pimd/pim_igmp.c
+++ b/pimd/pim_igmp.c
@@ -310,7 +310,7 @@ static int igmp_recv_query(struct igmp_sock *igmp, int query_version,
return 0;
}
- if (if_lookup_address(&from, AF_INET, ifp->vrf_id)) {
+ if (if_lookup_exact_address(&from, AF_INET, ifp->vrf_id)) {
if (PIM_DEBUG_IGMP_PACKETS)
zlog_debug("Recv IGMP query on interface: %s from ourself %s",
ifp->name, from_str);
@@ -995,6 +995,7 @@ struct igmp_sock *pim_igmp_sock_add(struct list *igmp_sock_list,
{
struct pim_interface *pim_ifp;
struct igmp_sock *igmp;
+ struct sockaddr_in sin;
int fd;
pim_ifp = ifp->info;
@@ -1006,6 +1007,15 @@ struct igmp_sock *pim_igmp_sock_add(struct list *igmp_sock_list,
return 0;
}
+ sin.sin_family = AF_INET;
+ sin.sin_addr = ifaddr;
+ sin.sin_port = 0;
+ if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) != 0) {
+ zlog_warn("Could not bind IGMP socket for %s on %s",
+ inet_ntoa(ifaddr), ifp->name);
+ return 0;
+ }
+
igmp = igmp_sock_new(fd, ifaddr, ifp, mtrace_only);
igmp_read_on(igmp);
diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c
index 9060b6a95a..0bccba397b 100644
--- a/pimd/pim_mroute.c
+++ b/pimd/pim_mroute.c
@@ -592,12 +592,9 @@ static int pim_mroute_msg(struct pim_instance *pim, const char *buf,
struct pim_interface *pim_ifp;
const struct ip *ip_hdr;
const struct igmpmsg *msg;
- char ip_src_str[INET_ADDRSTRLEN] = "";
- char ip_dst_str[INET_ADDRSTRLEN] = "";
- char src_str[INET_ADDRSTRLEN] = "<src?>";
- char grp_str[INET_ADDRSTRLEN] = "<grp?>";
struct in_addr ifaddr;
struct igmp_sock *igmp;
+ const struct prefix *connected_src;
if (buf_size < (int)sizeof(struct ip))
return 0;
@@ -617,34 +614,37 @@ static int pim_mroute_msg(struct pim_instance *pim, const char *buf,
if (!ifp || !ifp->info)
return 0;
+ connected_src = pim_if_connected_to_source(ifp, ip_hdr->ip_src);
+
+ if (!connected_src) {
+ if (PIM_DEBUG_IGMP_PACKETS) {
+ zlog_debug("Recv IGMP packet on interface: %s from a non-connected source: %pI4",
+ ifp->name, &ip_hdr->ip_src);
+ }
+ return 0;
+ }
+
pim_ifp = ifp->info;
- ifaddr = pim_find_primary_addr(ifp);
- igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list,
- ifaddr);
+ ifaddr = connected_src->u.prefix4;
+ igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, ifaddr);
if (PIM_DEBUG_MROUTE) {
- pim_inet4_dump("<src?>", ip_hdr->ip_src, ip_src_str,
- sizeof(ip_src_str));
- pim_inet4_dump("<dst?>", ip_hdr->ip_dst, ip_dst_str,
- sizeof(ip_dst_str));
-
zlog_debug(
- "%s(%s): igmp kernel upcall on %s(%p) for %s -> %s",
+ "%s(%s): igmp kernel upcall on %s(%p) for %pI4 -> %pI4",
__func__, pim->vrf->name, ifp->name, igmp,
- ip_src_str, ip_dst_str);
+ &ip_hdr->ip_src, &ip_hdr->ip_dst);
}
if (igmp)
pim_igmp_packet(igmp, (char *)buf, buf_size);
-
+ else if (PIM_DEBUG_IGMP_PACKETS) {
+ zlog_debug("No IGMP socket on interface: %s with connected source: %pFX",
+ ifp->name, connected_src);
+ }
} else if (ip_hdr->ip_p) {
if (PIM_DEBUG_MROUTE_DETAIL) {
- pim_inet4_dump("<src?>", ip_hdr->ip_src, src_str,
- sizeof(src_str));
- pim_inet4_dump("<grp?>", ip_hdr->ip_dst, grp_str,
- sizeof(grp_str));
zlog_debug(
- "%s: no kernel upcall proto=%d src: %s dst: %s msg_size=%d",
- __func__, ip_hdr->ip_p, src_str, grp_str,
+ "%s: no kernel upcall proto=%d src: %pI4 dst: %pI4 msg_size=%d",
+ __func__, ip_hdr->ip_p, &ip_hdr->ip_src, &ip_hdr->ip_dst,
buf_size);
}
@@ -656,15 +656,11 @@ static int pim_mroute_msg(struct pim_instance *pim, const char *buf,
if (!ifp)
return 0;
if (PIM_DEBUG_MROUTE) {
- pim_inet4_dump("<src?>", msg->im_src, src_str,
- sizeof(src_str));
- pim_inet4_dump("<grp?>", msg->im_dst, grp_str,
- sizeof(grp_str));
zlog_debug(
- "%s: pim kernel upcall %s type=%d ip_p=%d from fd=%d for (S,G)=(%s,%s) on %s vifi=%d size=%d",
+ "%s: pim kernel upcall %s type=%d ip_p=%d from fd=%d for (S,G)=(%pI4,%pI4) on %s vifi=%d size=%d",
__func__, igmpmsgtype2str[msg->im_msgtype],
msg->im_msgtype, ip_hdr->ip_p,
- pim->mroute_socket, src_str, grp_str, ifp->name,
+ pim->mroute_socket, &msg->im_src, &msg->im_dst, ifp->name,
msg->im_vif, buf_size);
}
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 <zebra.h>
+
+#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,16 +14,9 @@
#include "isisd/isis_circuit.h"
#include "isisd/isis_tlvs.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;
-}
+#include "test_common.h"
-struct zebra_privs_t isisd_privs;
+#define TEST_STREAM_SIZE 1500
static bool atexit_registered;
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 <zebra.h>
+
+#include <lib/version.h>
+#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] [<ipv4-only|ipv6-only>] [<level-1-only|level-2-only>]",
+ "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 <zebra.h>
+
+#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 \