summaryrefslogtreecommitdiff
path: root/isisd/isis_spf.c
diff options
context:
space:
mode:
Diffstat (limited to 'isisd/isis_spf.c')
-rw-r--r--isisd/isis_spf.c141
1 files changed, 102 insertions, 39 deletions
diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c
index 57b1d66c22..22dfee994f 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 "isis_zebra.h"
#include "fabricd.h"
#include "isis_spf_private.h"
@@ -354,7 +355,10 @@ struct isis_spftree *isis_spftree_new(struct isis_area *area,
tree->tree_id = tree_id;
tree->family = (tree->tree_id == SPFTREE_IPV4) ? AF_INET : AF_INET6;
tree->flags = flags;
- if (tree->type == SPF_TYPE_TI_LFA) {
+ isis_rlfa_list_init(tree);
+ tree->lfa.remote.pc_spftrees = list_new();
+ tree->lfa.remote.pc_spftrees->del = (void (*)(void *))isis_spftree_del;
+ if (tree->type == SPF_TYPE_RLFA || tree->type == SPF_TYPE_TI_LFA) {
isis_spf_node_list_init(&tree->lfa.p_space);
isis_spf_node_list_init(&tree->lfa.q_space);
}
@@ -366,7 +370,11 @@ void isis_spftree_del(struct isis_spftree *spftree)
{
hash_clean(spftree->prefix_sids, NULL);
hash_free(spftree->prefix_sids);
- if (spftree->type == SPF_TYPE_TI_LFA) {
+ isis_zebra_rlfa_unregister_all(spftree);
+ isis_rlfa_list_clear(spftree);
+ list_delete(&spftree->lfa.remote.pc_spftrees);
+ if (spftree->type == SPF_TYPE_RLFA
+ || spftree->type == SPF_TYPE_TI_LFA) {
isis_spf_node_list_clear(&spftree->lfa.q_space);
isis_spf_node_list_clear(&spftree->lfa.p_space);
}
@@ -820,7 +828,8 @@ lspfragloop:
#endif /* EXTREME_DEBUG */
if (no_overload) {
- if (pseudo_lsp || spftree->mtid == ISIS_MT_IPV4_UNICAST) {
+ if ((pseudo_lsp || spftree->mtid == ISIS_MT_IPV4_UNICAST)
+ && spftree->area->oldmetric) {
struct isis_oldstyle_reach *r;
for (r = (struct isis_oldstyle_reach *)
lsp->tlvs->oldstyle_reach.head;
@@ -848,42 +857,47 @@ lspfragloop:
}
}
- struct isis_item_list *te_neighs = NULL;
- if (pseudo_lsp || spftree->mtid == ISIS_MT_IPV4_UNICAST)
- te_neighs = &lsp->tlvs->extended_reach;
- else
- te_neighs = isis_lookup_mt_items(&lsp->tlvs->mt_reach,
- spftree->mtid);
-
- struct isis_extended_reach *er;
- for (er = te_neighs
- ? (struct isis_extended_reach *)
- te_neighs->head
- : NULL;
- er; er = er->next) {
- /* 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
- + (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,
- (void *)er->id, dist, depth + 1, NULL,
- parent);
+ if (spftree->area->newmetric) {
+ struct isis_item_list *te_neighs = NULL;
+ if (pseudo_lsp || spftree->mtid == ISIS_MT_IPV4_UNICAST)
+ te_neighs = &lsp->tlvs->extended_reach;
+ else
+ te_neighs = isis_lookup_mt_items(
+ &lsp->tlvs->mt_reach, spftree->mtid);
+
+ struct isis_extended_reach *er;
+ for (er = te_neighs ? (struct isis_extended_reach *)
+ te_neighs->head
+ : NULL;
+ er; er = er->next) {
+ /* 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
+ + (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,
+ (void *)er->id, dist, depth + 1, NULL,
+ parent);
+ }
}
}
if (!fabricd && !pseudo_lsp && spftree->family == AF_INET
- && spftree->mtid == ISIS_MT_IPV4_UNICAST) {
+ && spftree->mtid == ISIS_MT_IPV4_UNICAST
+ && spftree->area->oldmetric) {
struct isis_item_list *reachs[] = {
&lsp->tlvs->oldstyle_ip_reach,
&lsp->tlvs->oldstyle_ip_reach_ext};
@@ -908,6 +922,10 @@ lspfragloop:
}
}
+ /* we can skip all the rest if we're using metric style narrow */
+ if (!spftree->area->newmetric)
+ goto end;
+
if (!pseudo_lsp && spftree->family == AF_INET) {
struct isis_item_list *ipv4_reachs;
if (spftree->mtid == ISIS_MT_IPV4_UNICAST)
@@ -1027,6 +1045,35 @@ lspfragloop:
}
}
+end:
+
+ /* if attach bit set in LSP, attached-bit receive ignore is
+ * not configured, we are a level-1 area and we have no other
+ * level-2 | level1-2 areas then add a default route toward
+ * this neighbor
+ */
+ if ((lsp->hdr.lsp_bits & LSPBIT_ATT) == LSPBIT_ATT
+ && !spftree->area->attached_bit_rcv_ignore
+ && spftree->area->is_type == IS_LEVEL_1
+ && !isis_area_count(spftree->area->isis, IS_LEVEL_2)) {
+ struct prefix_pair ip_info = { {0} };
+ if (IS_DEBUG_RTE_EVENTS)
+ zlog_debug("ISIS-Spf (%s): add default %s route",
+ rawlspid_print(lsp->hdr.lsp_id),
+ spftree->family == AF_INET ? "ipv4"
+ : "ipv6");
+
+ if (spftree->family == AF_INET) {
+ ip_info.dest.family = AF_INET;
+ vtype = VTYPE_IPREACH_INTERNAL;
+ } else {
+ ip_info.dest.family = AF_INET6;
+ vtype = VTYPE_IP6REACH_INTERNAL;
+ }
+ process_N(spftree, vtype, &ip_info, cost, depth + 1, NULL,
+ parent);
+ }
+
if (fragnode == NULL)
fragnode = listhead(lsp->lspu.frags);
else
@@ -1429,6 +1476,9 @@ static void init_spt(struct isis_spftree *spftree, int mtid)
list_delete_all_node(spftree->sadj_list);
isis_vertex_queue_clear(&spftree->tents);
isis_vertex_queue_clear(&spftree->paths);
+ isis_zebra_rlfa_unregister_all(spftree);
+ isis_rlfa_list_clear(spftree);
+ list_delete_all_node(spftree->lfa.remote.pc_spftrees);
memset(&spftree->lfa.protection_counters, 0,
sizeof(spftree->lfa.protection_counters));
@@ -1502,12 +1552,13 @@ static void spf_path_process(struct isis_spftree *spftree,
priority = spf_prefix_priority(spftree, vertex);
vertex->N.ip.priority = priority;
if (vertex->depth == 1 || listcount(vertex->Adj_N) > 0) {
+ struct isis_spftree *pre_spftree;
struct route_table *route_table;
bool allow_ecmp;
- if (spftree->type == SPF_TYPE_TI_LFA) {
- struct isis_spftree *pre_spftree;
-
+ switch (spftree->type) {
+ case SPF_TYPE_RLFA:
+ case SPF_TYPE_TI_LFA:
if (priority
> area->lfa_priority_limit[level - 1]) {
if (IS_DEBUG_LFA)
@@ -1520,7 +1571,16 @@ static void spf_path_process(struct isis_spftree *spftree,
sizeof(buff)));
return;
}
+ break;
+ default:
+ break;
+ }
+ switch (spftree->type) {
+ case SPF_TYPE_RLFA:
+ isis_rlfa_check(spftree, vertex);
+ return;
+ case SPF_TYPE_TI_LFA:
if (isis_tilfa_check(spftree, vertex) != 0)
return;
@@ -1529,7 +1589,8 @@ static void spf_path_process(struct isis_spftree *spftree,
allow_ecmp = area->lfa_load_sharing[level - 1];
pre_spftree->lfa.protection_counters
.tilfa[vertex->N.ip.priority] += 1;
- } else {
+ break;
+ default:
route_table = spftree->route_table;
allow_ecmp = true;
@@ -1544,6 +1605,7 @@ static void spf_path_process(struct isis_spftree *spftree,
spftree->lfa.protection_counters
.ecmp[priority] += 1;
}
+ break;
}
isis_route_create(
@@ -1834,6 +1896,7 @@ int _isis_spf_schedule(struct isis_area *area, int level,
area->area_tag, level, diff, func, file, line);
}
+ thread_cancel(&area->t_rlfa_rib_update);
if (area->spf_delay_ietf[level - 1]) {
/* Need to call schedule function also if spf delay is running
* to