diff options
Diffstat (limited to 'isisd/isis_spf.c')
| -rw-r--r-- | isisd/isis_spf.c | 141 |
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 |
