diff options
Diffstat (limited to 'isisd/isis_lfa.c')
| -rw-r--r-- | isisd/isis_lfa.c | 65 |
1 files changed, 37 insertions, 28 deletions
diff --git a/isisd/isis_lfa.c b/isisd/isis_lfa.c index 8ca432f895..f22e4a7085 100644 --- a/isisd/isis_lfa.c +++ b/isisd/isis_lfa.c @@ -180,23 +180,6 @@ bool isis_lfa_excise_node_check(const struct isis_spftree *spftree, return false; } -/* Find SRGB associated to a System ID. */ -static struct isis_sr_block *tilfa_find_srgb(struct lspdb_head *lspdb, - const uint8_t *sysid) -{ - struct isis_lsp *lsp; - - lsp = isis_root_system_lsp(lspdb, sysid); - if (!lsp) - return NULL; - - if (!lsp->tlvs->router_cap - || lsp->tlvs->router_cap->srgb.range_size == 0) - return NULL; - - return &lsp->tlvs->router_cap->srgb; -} - struct tilfa_find_pnode_prefix_sid_args { uint32_t sid_index; }; @@ -308,25 +291,30 @@ tilfa_compute_label_stack(struct lspdb_head *lspdb, label_stack->num_labels = listcount(repair_list); for (ALL_LIST_ELEMENTS_RO(repair_list, node, sid)) { + const uint8_t *target_node; struct isis_sr_block *srgb; mpls_label_t label; switch (sid->type) { case TILFA_SID_PREFIX: - srgb = tilfa_find_srgb(lspdb, sadj->id); + if (sid->value.index.remote) + target_node = sid->value.index.remote_sysid; + else + target_node = sadj->id; + srgb = isis_sr_find_srgb(lspdb, target_node); if (!srgb) { zlog_warn("%s: SRGB not found for node %s", __func__, - print_sys_hostname(sadj->id)); + print_sys_hostname(target_node)); goto error; } /* Check if the SID index falls inside the SRGB. */ - if (sid->value.index >= srgb->range_size) { + if (sid->value.index.value >= srgb->range_size) { flog_warn( EC_ISIS_SID_OVERFLOW, "%s: SID index %u falls outside remote SRGB range", - __func__, sid->value.index); + __func__, sid->value.index.value); goto error; } @@ -334,7 +322,7 @@ tilfa_compute_label_stack(struct lspdb_head *lspdb, * Prefix-SID: map SID index to label value within the * SRGB. */ - label = srgb->lower_bound + sid->value.index; + label = srgb->lower_bound + sid->value.index.value; break; case TILFA_SID_ADJ: /* Adj-SID: absolute label value can be used directly */ @@ -446,7 +434,8 @@ static int tilfa_build_repair_list(struct isis_spftree *spftree_pc, struct listnode *node; bool is_pnode, is_qnode; char buf[VID2STR_BUFFER]; - struct isis_tilfa_sid sid_qnode, sid_pnode; + struct isis_tilfa_sid sid_dest = {}, sid_qnode = {}, sid_pnode = {}; + uint32_t sid_index; mpls_label_t label_qnode; if (IS_DEBUG_TILFA) { @@ -455,6 +444,24 @@ static int tilfa_build_repair_list(struct isis_spftree *spftree_pc, vtype2string(vertex->type), buf); } + /* Push original Prefix-SID label when necessary. */ + if (VTYPE_IP(vertex->type) && vertex->N.ip.sr.present) { + pvertex = listnode_head(vertex->parents); + assert(pvertex); + + sid_index = vertex->N.ip.sr.sid.value; + if (IS_DEBUG_TILFA) + zlog_debug( + "ISIS-TI-LFA: pushing Prefix-SID to %pFX (index %u)", + &vertex->N.ip.p.dest, sid_index); + sid_dest.type = TILFA_SID_PREFIX; + sid_dest.value.index.value = sid_index; + sid_dest.value.index.remote = true; + memcpy(sid_dest.value.index.remote_sysid, pvertex->N.id, + sizeof(sid_dest.value.index.remote_sysid)); + listnode_add_head(repair_list, &sid_dest); + } + if (!vertex_child) goto parents; if (vertex->type != VTYPE_NONPSEUDO_IS @@ -492,8 +499,6 @@ static int tilfa_build_repair_list(struct isis_spftree *spftree_pc, /* Push Prefix-SID label when necessary. */ if (is_pnode) { - uint32_t sid_index; - /* The same P-node can't be used more than once. */ if (isis_spf_node_find(used_pnodes, vertex->N.id)) { if (IS_DEBUG_TILFA) @@ -521,10 +526,10 @@ static int tilfa_build_repair_list(struct isis_spftree *spftree_pc, if (IS_DEBUG_TILFA) zlog_debug( - "ISIS-TI-LFA: pushing Prefix-SID to %s (index %u)", + "ISIS-TI-LFA: pushing Node-SID to %s (index %u)", print_sys_hostname(vertex->N.id), sid_index); sid_pnode.type = TILFA_SID_PREFIX; - sid_pnode.value.index = sid_index; + sid_pnode.value.index.value = sid_index; listnode_add_head(repair_list, &sid_pnode); /* Apply repair list. */ @@ -614,6 +619,10 @@ static bool lfa_check_needs_protection(const struct isis_spftree *spftree_pc, size_t affected_nhs = 0; struct isis_vertex_adj *vadj; + /* Local routes don't need protection. */ + if (VTYPE_IP(vertex->type) && vertex->depth == 1) + return false; + /* Only local adjacencies need Adj-SID protection. */ if (VTYPE_IS(vertex->type) && !isis_adj_find(spftree_pc->area, spftree_pc->level, @@ -700,7 +709,7 @@ int isis_lfa_check(struct isis_spftree *spftree_pc, struct isis_vertex *vertex) struct route_table *route_table; route_table = spftree_pc->lfa.old.spftree->route_table_backup; - if (route_node_lookup(route_table, &vertex->N.ip.dest)) { + if (route_node_lookup(route_table, &vertex->N.ip.p.dest)) { if (IS_DEBUG_TILFA) zlog_debug( "ISIS-TI-LFA: %s %s already covered by node protection", |
