summaryrefslogtreecommitdiff
path: root/isisd/isis_lfa.c
diff options
context:
space:
mode:
Diffstat (limited to 'isisd/isis_lfa.c')
-rw-r--r--isisd/isis_lfa.c65
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",