summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--isisd/fabricd.c34
-rw-r--r--isisd/fabricd.h6
-rw-r--r--isisd/isis_spf.c130
-rw-r--r--isisd/isis_spf.h4
-rw-r--r--isisd/isisd.c5
5 files changed, 137 insertions, 42 deletions
diff --git a/isisd/fabricd.c b/isisd/fabricd.c
index d37e6a71d8..853b672075 100644
--- a/isisd/fabricd.c
+++ b/isisd/fabricd.c
@@ -26,6 +26,7 @@
#include "isisd/isis_circuit.h"
#include "isisd/isis_misc.h"
#include "isisd/isis_adjacency.h"
+#include "isisd/isis_spf.h"
DEFINE_MTYPE_STATIC(ISISD, FABRICD_STATE, "ISIS OpenFabric")
@@ -45,16 +46,27 @@ struct fabricd {
time_t initial_sync_start;
struct isis_circuit *initial_sync_circuit;
struct thread *initial_sync_timeout;
+
+ struct isis_spftree *spftree;
};
-struct fabricd *fabricd_new(void)
+struct fabricd *fabricd_new(struct isis_area *area)
{
struct fabricd *rv = XCALLOC(MTYPE_FABRICD_STATE, sizeof(*rv));
rv->initial_sync_state = FABRICD_SYNC_PENDING;
+ rv->spftree = isis_spftree_new(area);
return rv;
};
+void fabricd_finish(struct fabricd *f)
+{
+ if (f->initial_sync_timeout)
+ thread_cancel(f->initial_sync_timeout);
+
+ isis_spftree_del(f->spftree);
+}
+
static int fabricd_initial_sync_timeout(struct thread *thread)
{
struct fabricd *f = THREAD_ARG(thread);
@@ -134,3 +146,23 @@ void fabricd_initial_sync_finish(struct isis_area *area)
thread_cancel(f->initial_sync_timeout);
f->initial_sync_timeout = NULL;
}
+
+void fabricd_run_spf(struct isis_area *area)
+{
+ struct fabricd *f = area->fabricd;
+
+ if (!f)
+ return;
+
+ isis_run_hopcount_spf(area, isis->sysid, f->spftree);
+}
+
+struct isis_spftree *fabricd_spftree(struct isis_area *area)
+{
+ struct fabricd *f = area->fabricd;
+
+ if (!f)
+ return NULL;
+
+ return f->spftree;
+}
diff --git a/isisd/fabricd.h b/isisd/fabricd.h
index 35a5bb6a3b..1707adf36e 100644
--- a/isisd/fabricd.h
+++ b/isisd/fabricd.h
@@ -26,11 +26,15 @@ struct fabricd;
struct isis_circuit;
struct isis_area;
+struct isis_spftree;
-struct fabricd *fabricd_new(void);
+struct fabricd *fabricd_new(struct isis_area *area);
+void fabricd_finish(struct fabricd *f);
void fabricd_initial_sync_hello(struct isis_circuit *circuit);
bool fabricd_initial_sync_is_in_progress(struct isis_area *area);
struct isis_circuit *fabricd_initial_sync_circuit(struct isis_area *area);
void fabricd_initial_sync_finish(struct isis_area *area);
+void fabricd_run_spf(struct isis_area *area);
+struct isis_spftree *fabricd_spftree(struct isis_area *area);
#endif
diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c
index 5b47d3e684..1e2052b652 100644
--- a/isisd/isis_spf.c
+++ b/isisd/isis_spf.c
@@ -56,6 +56,7 @@
#include "isis_csm.h"
#include "isis_mt.h"
#include "isis_tlvs.h"
+#include "fabricd.h"
DEFINE_MTYPE_STATIC(ISISD, ISIS_SPF_RUN, "ISIS SPF Run Info");
@@ -303,6 +304,7 @@ struct isis_spftree {
int family;
int level;
enum spf_tree_id tree_id;
+ bool hopcount_metric;
};
@@ -563,6 +565,9 @@ void spftree_area_adj_del(struct isis_area *area, struct isis_adjacency *adj)
adj);
}
}
+
+ if (fabricd_spftree(area) != NULL)
+ isis_spftree_adj_del(fabricd_spftree(area), adj);
}
/*
@@ -722,6 +727,10 @@ static void process_N(struct isis_spftree *spftree, enum vertextype vtype,
assert(spftree && parent);
+ if (spftree->hopcount_metric
+ && !VTYPE_IS(vtype))
+ return;
+
struct prefix_pair p;
if (vtype >= VTYPE_IPREACH_INTERNAL) {
memcpy(&p, id, sizeof(p));
@@ -889,7 +898,7 @@ lspfragloop:
if (!pseudo_lsp
&& !memcmp(er->id, null_sysid, ISIS_SYS_ID_LEN))
continue;
- dist = cost + er->metric;
+ dist = cost + (spftree->hopcount_metric ? 1 : er->metric);
process_N(spftree,
LSP_PSEUDO_ID(er->id) ? VTYPE_PSEUDO_TE_IS
: VTYPE_NONPSEUDO_TE_IS,
@@ -1037,7 +1046,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
/*
* Add IP(v6) addresses of this circuit
*/
- if (spftree->family == AF_INET) {
+ 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,
@@ -1050,7 +1059,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
&ip_info, NULL, 0, parent);
}
}
- if (spftree->family == AF_INET6) {
+ 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,
@@ -1094,6 +1103,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
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);
@@ -1111,6 +1121,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
? VTYPE_NONPSEUDO_IS
: VTYPE_NONPSEUDO_TE_IS,
lsp_id, adj,
+ spftree->hopcount_metric ? 1 :
circuit->te_metric
[spftree->level - 1],
parent);
@@ -1180,10 +1191,10 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
circuit->circuit_id);
continue;
}
- isis_spf_process_lsp(
- spftree, lsp,
- circuit->te_metric[spftree->level - 1], 0,
- root_sysid, parent);
+ 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)
@@ -1196,6 +1207,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
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;
@@ -1215,6 +1227,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
? VTYPE_NONPSEUDO_IS
: VTYPE_NONPSEUDO_TE_IS,
lsp_id, adj,
+ spftree->hopcount_metric ? 1 :
circuit->te_metric
[spftree->level - 1],
parent);
@@ -1275,7 +1288,8 @@ static void add_to_paths(struct isis_spftree *spftree,
}
static void init_spt(struct isis_spftree *spftree, int mtid, int level,
- int family, enum spf_tree_id tree_id)
+ int family, enum spf_tree_id tree_id,
+ bool hopcount_metric)
{
isis_vertex_queue_clear(&spftree->tents);
isis_vertex_queue_clear(&spftree->paths);
@@ -1284,7 +1298,64 @@ static void init_spt(struct isis_spftree *spftree, int mtid, int level,
spftree->level = level;
spftree->family = family;
spftree->tree_id = tree_id;
- return;
+ spftree->hopcount_metric = hopcount_metric;
+}
+
+static void isis_spf_loop(struct isis_spftree *spftree,
+ uint8_t *root_sysid)
+{
+ struct isis_vertex *vertex;
+ uint8_t lsp_id[ISIS_SYS_ID_LEN + 2];
+ struct isis_lsp *lsp;
+
+ while (isis_vertex_queue_count(&spftree->tents)) {
+ vertex = isis_vertex_queue_pop(&spftree->tents);
+
+#ifdef EXTREME_DEBUG
+ zlog_debug(
+ "ISIS-Spf: get TENT node %s %s depth %d dist %d to PATHS",
+ print_sys_hostname(vertex->N.id),
+ vtype2string(vertex->type), vertex->depth, vertex->d_N);
+#endif /* EXTREME_DEBUG */
+
+ add_to_paths(spftree, vertex);
+ if (VTYPE_IS(vertex->type)) {
+ memcpy(lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1);
+ LSP_FRAGMENT(lsp_id) = 0;
+ lsp = lsp_search(lsp_id, spftree->area->lspdb[spftree->level - 1]);
+ if (lsp && lsp->hdr.rem_lifetime != 0) {
+ isis_spf_process_lsp(spftree, lsp, vertex->d_N,
+ vertex->depth, root_sysid,
+ vertex);
+ } else {
+ zlog_warn("ISIS-Spf: No LSP found for %s",
+ rawlspid_print(lsp_id));
+ }
+ }
+ }
+}
+
+struct isis_spftree *isis_run_hopcount_spf(struct isis_area *area,
+ uint8_t *sysid,
+ 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);
+ if (!memcmp(sysid, 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);
+ } else {
+ isis_vertex_queue_insert(&spftree->tents, isis_vertex_new(
+ sysid, VTYPE_NONPSEUDO_TE_IS));
+ }
+
+ isis_spf_loop(spftree, sysid);
+
+ return spftree;
}
static int isis_run_spf(struct isis_area *area, int level,
@@ -1292,11 +1363,8 @@ static int isis_run_spf(struct isis_area *area, int level,
uint8_t *sysid, struct timeval *nowtv)
{
int retval = ISIS_OK;
- struct isis_vertex *vertex;
struct isis_vertex *root_vertex;
struct isis_spftree *spftree = area->spftree[tree_id][level - 1];
- uint8_t lsp_id[ISIS_SYS_ID_LEN + 2];
- struct isis_lsp *lsp;
struct timeval time_now;
unsigned long long start_time, end_time;
uint16_t mtid = 0;
@@ -1330,7 +1398,7 @@ static int isis_run_spf(struct isis_area *area, int level,
/*
* C.2.5 Step 0
*/
- init_spt(spftree, mtid, level, family, tree_id);
+ init_spt(spftree, mtid, level, family, tree_id, false);
/* a) */
root_vertex = isis_spf_add_root(spftree, sysid);
/* b) */
@@ -1350,32 +1418,7 @@ static int isis_run_spf(struct isis_area *area, int level,
print_sys_hostname(sysid));
}
- while (isis_vertex_queue_count(&spftree->tents)) {
- vertex = isis_vertex_queue_pop(&spftree->tents);
-
-#ifdef EXTREME_DEBUG
- zlog_debug(
- "ISIS-Spf: get TENT node %s %s depth %d dist %d to PATHS",
- print_sys_hostname(vertex->N.id),
- vtype2string(vertex->type), vertex->depth, vertex->d_N);
-#endif /* EXTREME_DEBUG */
-
- add_to_paths(spftree, vertex);
- if (VTYPE_IS(vertex->type)) {
- memcpy(lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1);
- LSP_FRAGMENT(lsp_id) = 0;
- lsp = lsp_search(lsp_id, area->lspdb[level - 1]);
- if (lsp && lsp->hdr.rem_lifetime != 0) {
- isis_spf_process_lsp(spftree, lsp, vertex->d_N,
- vertex->depth, sysid,
- vertex);
- } else {
- zlog_warn("ISIS-Spf: No LSP found for %s",
- rawlspid_print(lsp_id));
- }
- }
- }
-
+ isis_spf_loop(spftree, sysid);
out:
spftree->runcount++;
spftree->last_run_timestamp = time(NULL);
@@ -1446,6 +1489,8 @@ static int isis_run_spf_cb(struct thread *thread)
for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit))
UNSET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF);
+ fabricd_run_spf(area);
+
return retval;
}
@@ -1666,6 +1711,13 @@ DEFUN (show_isis_topology,
}
}
+ if (fabricd_spftree(area)) {
+ vty_out(vty,
+ "IS-IS paths to level-2 routers with hop-by-hop metric\n");
+ isis_print_paths(vty, &fabricd_spftree(area)->paths, isis->sysid);
+ vty_out(vty, "\n");
+ }
+
vty_out(vty, "\n");
}
diff --git a/isisd/isis_spf.h b/isisd/isis_spf.h
index 9a73ca8783..0532bd5465 100644
--- a/isisd/isis_spf.h
+++ b/isisd/isis_spf.h
@@ -37,4 +37,8 @@ void spftree_area_adj_del(struct isis_area *area, struct isis_adjacency *adj);
int isis_spf_schedule(struct isis_area *area, int level);
void isis_spf_cmds_init(void);
void isis_spf_print(struct isis_spftree *spftree, struct vty *vty);
+struct isis_spftree *isis_run_hopcount_spf(struct isis_area *area,
+ uint8_t *sysid,
+ struct isis_spftree *spftree);
+
#endif /* _ZEBRA_ISIS_SPF_H */
diff --git a/isisd/isisd.c b/isisd/isisd.c
index e8efa391e0..cc5463ffe7 100644
--- a/isisd/isisd.c
+++ b/isisd/isisd.c
@@ -159,7 +159,7 @@ struct isis_area *isis_area_create(const char *area_tag)
area->isis = isis;
if (fabricd)
- area->fabricd = fabricd_new();
+ area->fabricd = fabricd_new(area);
QOBJ_REG(area, isis_area);
return area;
@@ -216,6 +216,9 @@ int isis_area_destroy(struct vty *vty, const char *area_tag)
QOBJ_UNREG(area);
+ if (fabricd)
+ fabricd_finish(area->fabricd);
+
if (area->circuit_list) {
for (ALL_LIST_ELEMENTS(area->circuit_list, node, nnode,
circuit)) {