isisd: refactor handling of SR Prefix-SIDs

Embed Prefix-SID information inside SPF data structures so that
Prefix-SIDs can be installed together with their associated routes
at the end of the SPF algorithm. This is different from the current
implementation where Prefix-SIDs are parsed and processed separately,
which is vastly suboptimal.

Advantages of the new code:
* No need to parse the LSPDB an additional time to detect and process
  SR-related changes;
* Routes are installed with their Prefix-SID labels in the same ZAPI
  message. This can prevent packet dropping for a few milliseconds
  after each SPF run if there are BGP-labeled routes (e.g. L3VPN) that
  recurse on IGP labeled routes;
* Much easier to support Anycast-SIDs, as the SPF code will naturally
  figure out the best nexthops and use only them (that can't be done
  in any reasonable way if the Prefix-SID Sub-TVLs are processed
  separately);
* Less code to maintain and reduced memory footprint;

The "show isis segment-routing prefix-sids" command was removed as
it doesn't make sense anymore now that "show isis route" exists.
Prefix-SIDs are a property of routes, so what was done was to extend
the "show isis route" command with a new "prefix-sid" option that
changes the output table to show the Prefix-SID information associated
to each route.

Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
This commit is contained in:
Renato Westphal 2020-09-20 02:39:28 -03:00
parent d4fcd8bd82
commit d47d6089e0
15 changed files with 870 additions and 1848 deletions

View File

@ -423,8 +423,8 @@ Showing ISIS information
Show topology IS-IS paths to Intermediate Systems, globally, in area Show topology IS-IS paths to Intermediate Systems, globally, in area
(level-1) or domain (level-2). (level-1) or domain (level-2).
.. index:: show isis route [level-1|level-2] [backup] .. index:: show isis route [level-1|level-2] [prefix-sid|backup]
.. clicmd:: show isis route [level-1|level-2] [backup] .. clicmd:: show isis route [level-1|level-2] [prefix-sid|backup]
Show the ISIS routing table, as determined by the most recent SPF Show the ISIS routing table, as determined by the most recent SPF
calculation. calculation.

View File

@ -180,23 +180,6 @@ bool isis_lfa_excise_node_check(const struct isis_spftree *spftree,
return false; 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 { struct tilfa_find_pnode_prefix_sid_args {
uint32_t sid_index; uint32_t sid_index;
}; };
@ -313,7 +296,7 @@ tilfa_compute_label_stack(struct lspdb_head *lspdb,
switch (sid->type) { switch (sid->type) {
case TILFA_SID_PREFIX: case TILFA_SID_PREFIX:
srgb = tilfa_find_srgb(lspdb, sadj->id); srgb = isis_sr_find_srgb(lspdb, sadj->id);
if (!srgb) { if (!srgb) {
zlog_warn("%s: SRGB not found for node %s", zlog_warn("%s: SRGB not found for node %s",
__func__, __func__,
@ -704,7 +687,7 @@ int isis_lfa_check(struct isis_spftree *spftree_pc, struct isis_vertex *vertex)
struct route_table *route_table; struct route_table *route_table;
route_table = spftree_pc->lfa.old.spftree->route_table_backup; 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) if (IS_DEBUG_TILFA)
zlog_debug( zlog_debug(
"ISIS-TI-LFA: %s %s already covered by node protection", "ISIS-TI-LFA: %s %s already covered by node protection",

View File

@ -71,7 +71,6 @@ static struct isis_nexthop *isis_nexthop_create(int family, union g_addr *ip,
nexthop->family = family; nexthop->family = family;
nexthop->ifindex = ifindex; nexthop->ifindex = ifindex;
nexthop->ip = *ip; nexthop->ip = *ip;
isis_sr_nexthop_reset(&nexthop->sr);
return nexthop; return nexthop;
} }
@ -117,7 +116,7 @@ static struct isis_nexthop *nexthoplookup(struct list *nexthops, int family,
} }
void adjinfo2nexthop(int family, struct list *nexthops, void adjinfo2nexthop(int family, struct list *nexthops,
struct isis_adjacency *adj, struct isis_adjacency *adj, struct isis_sr_psid_info *sr,
struct mpls_label_stack *label_stack) struct mpls_label_stack *label_stack)
{ {
struct isis_nexthop *nh; struct isis_nexthop *nh;
@ -134,6 +133,8 @@ void adjinfo2nexthop(int family, struct list *nexthops,
AF_INET, &ip, AF_INET, &ip,
adj->circuit->interface->ifindex); adj->circuit->interface->ifindex);
memcpy(nh->sysid, adj->sysid, sizeof(nh->sysid)); memcpy(nh->sysid, adj->sysid, sizeof(nh->sysid));
if (sr)
nh->sr = *sr;
nh->label_stack = label_stack; nh->label_stack = label_stack;
listnode_add(nexthops, nh); listnode_add(nexthops, nh);
break; break;
@ -150,6 +151,8 @@ void adjinfo2nexthop(int family, struct list *nexthops,
AF_INET6, &ip, AF_INET6, &ip,
adj->circuit->interface->ifindex); adj->circuit->interface->ifindex);
memcpy(nh->sysid, adj->sysid, sizeof(nh->sysid)); memcpy(nh->sysid, adj->sysid, sizeof(nh->sysid));
if (sr)
nh->sr = *sr;
nh->label_stack = label_stack; nh->label_stack = label_stack;
listnode_add(nexthops, nh); listnode_add(nexthops, nh);
break; break;
@ -165,22 +168,22 @@ void adjinfo2nexthop(int family, struct list *nexthops,
static void isis_route_add_dummy_nexthops(struct isis_route_info *rinfo, static void isis_route_add_dummy_nexthops(struct isis_route_info *rinfo,
const uint8_t *sysid, const uint8_t *sysid,
struct isis_sr_psid_info *sr,
struct mpls_label_stack *label_stack) struct mpls_label_stack *label_stack)
{ {
struct isis_nexthop *nh; struct isis_nexthop *nh;
nh = XCALLOC(MTYPE_ISIS_NEXTHOP, sizeof(struct isis_nexthop)); nh = XCALLOC(MTYPE_ISIS_NEXTHOP, sizeof(struct isis_nexthop));
memcpy(nh->sysid, sysid, sizeof(nh->sysid)); memcpy(nh->sysid, sysid, sizeof(nh->sysid));
isis_sr_nexthop_reset(&nh->sr); nh->sr = *sr;
nh->label_stack = label_stack; nh->label_stack = label_stack;
listnode_add(rinfo->nexthops, nh); listnode_add(rinfo->nexthops, nh);
} }
static struct isis_route_info *isis_route_info_new(struct prefix *prefix, static struct isis_route_info *
struct prefix_ipv6 *src_p, isis_route_info_new(struct prefix *prefix, struct prefix_ipv6 *src_p,
uint32_t cost, uint32_t cost, uint32_t depth, struct isis_sr_psid_info *sr,
uint32_t depth, struct list *adjacencies)
struct list *adjacencies)
{ {
struct isis_route_info *rinfo; struct isis_route_info *rinfo;
struct isis_vertex_adj *vadj; struct isis_vertex_adj *vadj;
@ -192,6 +195,7 @@ static struct isis_route_info *isis_route_info_new(struct prefix *prefix,
for (ALL_LIST_ELEMENTS_RO(adjacencies, node, vadj)) { for (ALL_LIST_ELEMENTS_RO(adjacencies, node, vadj)) {
struct isis_spf_adj *sadj = vadj->sadj; struct isis_spf_adj *sadj = vadj->sadj;
struct isis_adjacency *adj = sadj->adj; struct isis_adjacency *adj = sadj->adj;
struct isis_sr_psid_info *sr = &vadj->sr;
struct mpls_label_stack *label_stack = vadj->label_stack; struct mpls_label_stack *label_stack = vadj->label_stack;
/* /*
@ -199,7 +203,7 @@ static struct isis_route_info *isis_route_info_new(struct prefix *prefix,
* environment. * environment.
*/ */
if (CHECK_FLAG(im->options, F_ISIS_UNIT_TEST)) { if (CHECK_FLAG(im->options, F_ISIS_UNIT_TEST)) {
isis_route_add_dummy_nexthops(rinfo, sadj->id, isis_route_add_dummy_nexthops(rinfo, sadj->id, sr,
label_stack); label_stack);
continue; continue;
} }
@ -227,12 +231,13 @@ static struct isis_route_info *isis_route_info_new(struct prefix *prefix,
prefix->family); prefix->family);
exit(1); exit(1);
} }
adjinfo2nexthop(prefix->family, rinfo->nexthops, adj, adjinfo2nexthop(prefix->family, rinfo->nexthops, adj, sr,
label_stack); label_stack);
} }
rinfo->cost = cost; rinfo->cost = cost;
rinfo->depth = depth; rinfo->depth = depth;
rinfo->sr = *sr;
return rinfo; return rinfo;
} }
@ -254,12 +259,28 @@ void isis_route_node_cleanup(struct route_table *table, struct route_node *node)
isis_route_info_delete(node->info); isis_route_info_delete(node->info);
} }
static bool isis_sr_psid_info_same(struct isis_sr_psid_info *new,
struct isis_sr_psid_info *old)
{
if (new->present != old->present)
return false;
if (new->label != old->label)
return false;
if (new->sid.flags != old->sid.flags
|| new->sid.value != old->sid.value)
return false;
return true;
}
static int isis_route_info_same(struct isis_route_info *new, static int isis_route_info_same(struct isis_route_info *new,
struct isis_route_info *old, char *buf, struct isis_route_info *old, char *buf,
size_t buf_size) size_t buf_size)
{ {
struct listnode *node; struct listnode *node;
struct isis_nexthop *nexthop; struct isis_nexthop *new_nh, *old_nh;
if (new->cost != old->cost) { if (new->cost != old->cost) {
if (buf) if (buf)
@ -275,6 +296,12 @@ static int isis_route_info_same(struct isis_route_info *new,
return 0; return 0;
} }
if (!isis_sr_psid_info_same(&new->sr, &old->sr)) {
if (buf)
snprintf(buf, buf_size, "SR input label");
return 0;
}
if (new->nexthops->count != old->nexthops->count) { if (new->nexthops->count != old->nexthops->count) {
if (buf) if (buf)
snprintf(buf, buf_size, "nhops num (old: %u, new: %u)", snprintf(buf, buf_size, "nhops num (old: %u, new: %u)",
@ -282,14 +309,20 @@ static int isis_route_info_same(struct isis_route_info *new,
return 0; return 0;
} }
for (ALL_LIST_ELEMENTS_RO(new->nexthops, node, nexthop)) { for (ALL_LIST_ELEMENTS_RO(new->nexthops, node, new_nh)) {
if (!nexthoplookup(old->nexthops, nexthop->family, &nexthop->ip, old_nh = nexthoplookup(old->nexthops, new_nh->family,
nexthop->ifindex)) { &new_nh->ip, new_nh->ifindex);
if (!old_nh) {
if (buf) if (buf)
snprintf(buf, buf_size, snprintf(buf, buf_size,
"new nhop"); /* TODO: print nhop */ "new nhop"); /* TODO: print nhop */
return 0; return 0;
} }
if (!isis_sr_psid_info_same(&new_nh->sr, &old_nh->sr)) {
if (buf)
snprintf(buf, buf_size, "nhop SR label");
return 0;
}
} }
/* only the resync flag needs to be checked */ /* only the resync flag needs to be checked */
@ -303,13 +336,11 @@ static int isis_route_info_same(struct isis_route_info *new,
return 1; return 1;
} }
struct isis_route_info *isis_route_create(struct prefix *prefix, struct isis_route_info *
struct prefix_ipv6 *src_p, isis_route_create(struct prefix *prefix, struct prefix_ipv6 *src_p,
uint32_t cost, uint32_t cost, uint32_t depth, struct isis_sr_psid_info *sr,
uint32_t depth, struct list *adjacencies, struct isis_area *area,
struct list *adjacencies, struct route_table *table)
struct isis_area *area,
struct route_table *table)
{ {
struct route_node *route_node; struct route_node *route_node;
struct isis_route_info *rinfo_new, *rinfo_old, *route_info = NULL; struct isis_route_info *rinfo_new, *rinfo_old, *route_info = NULL;
@ -318,8 +349,8 @@ struct isis_route_info *isis_route_create(struct prefix *prefix,
if (!table) if (!table)
return NULL; return NULL;
rinfo_new = isis_route_info_new(prefix, src_p, cost, rinfo_new = isis_route_info_new(prefix, src_p, cost, depth, sr,
depth, adjacencies); adjacencies);
route_node = srcdest_rnode_get(table, prefix, src_p); route_node = srcdest_rnode_get(table, prefix, src_p);
rinfo_old = route_node->info; rinfo_old = route_node->info;
@ -351,6 +382,7 @@ struct isis_route_info *isis_route_create(struct prefix *prefix,
zlog_debug( zlog_debug(
"ISIS-Rte (%s): route changed: %pFX, change: %s", "ISIS-Rte (%s): route changed: %pFX, change: %s",
area->area_tag, prefix, change_buf); area->area_tag, prefix, change_buf);
rinfo_new->sr_previous = rinfo_old->sr;
isis_route_info_delete(rinfo_old); isis_route_info_delete(rinfo_old);
route_info = rinfo_new; route_info = rinfo_new;
UNSET_FLAG(route_info->flag, UNSET_FLAG(route_info->flag,
@ -406,7 +438,25 @@ static void isis_route_update(struct isis_area *area, struct prefix *prefix,
if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED)) if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
return; return;
isis_zebra_route_add_route(area->isis, prefix, src_p, route_info); /*
* Explicitly uninstall previous Prefix-SID label if it has
* changed or was removed.
*/
if (route_info->sr_previous.present
&& (!route_info->sr.present
|| route_info->sr_previous.label
!= route_info->sr.label))
isis_zebra_prefix_sid_uninstall(
area, prefix, route_info,
&route_info->sr_previous);
/* Install route. */
isis_zebra_route_add_route(area->isis, prefix, src_p,
route_info);
/* Install/reinstall Prefix-SID label. */
if (route_info->sr.present)
isis_zebra_prefix_sid_install(area, prefix, route_info,
&route_info->sr);
hook_call(isis_route_update_hook, area, prefix, route_info); hook_call(isis_route_update_hook, area, prefix, route_info);
SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
@ -415,7 +465,13 @@ static void isis_route_update(struct isis_area *area, struct prefix *prefix,
if (!CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED)) if (!CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
return; return;
isis_zebra_route_del_route(area->isis, prefix, src_p, route_info); /* Uninstall Prefix-SID label. */
if (route_info->sr.present)
isis_zebra_prefix_sid_uninstall(
area, prefix, route_info, &route_info->sr);
/* Uninstall route. */
isis_zebra_route_del_route(area->isis, prefix, src_p,
route_info);
hook_call(isis_route_update_hook, area, prefix, route_info); hook_call(isis_route_update_hook, area, prefix, route_info);
UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);

View File

@ -32,7 +32,7 @@ struct isis_nexthop {
int family; int family;
union g_addr ip; union g_addr ip;
uint8_t sysid[ISIS_SYS_ID_LEN]; uint8_t sysid[ISIS_SYS_ID_LEN];
struct sr_nexthop_info sr; struct isis_sr_psid_info sr;
struct mpls_label_stack *label_stack; struct mpls_label_stack *label_stack;
}; };
@ -43,6 +43,8 @@ struct isis_route_info {
uint8_t flag; uint8_t flag;
uint32_t cost; uint32_t cost;
uint32_t depth; uint32_t depth;
struct isis_sr_psid_info sr;
struct isis_sr_psid_info sr_previous;
struct list *nexthops; struct list *nexthops;
struct isis_route_info *backup; struct isis_route_info *backup;
}; };
@ -54,15 +56,13 @@ DECLARE_HOOK(isis_route_update_hook,
void isis_nexthop_delete(struct isis_nexthop *nexthop); void isis_nexthop_delete(struct isis_nexthop *nexthop);
void adjinfo2nexthop(int family, struct list *nexthops, void adjinfo2nexthop(int family, struct list *nexthops,
struct isis_adjacency *adj, struct isis_adjacency *adj, struct isis_sr_psid_info *sr,
struct mpls_label_stack *label_stack); struct mpls_label_stack *label_stack);
struct isis_route_info *isis_route_create(struct prefix *prefix, struct isis_route_info *
struct prefix_ipv6 *src_p, isis_route_create(struct prefix *prefix, struct prefix_ipv6 *src_p,
uint32_t cost, uint32_t cost, uint32_t depth, struct isis_sr_psid_info *sr,
uint32_t depth, struct list *adjacencies, struct isis_area *area,
struct list *adjacencies, struct route_table *table);
struct isis_area *area,
struct route_table *table);
/* Walk the given table and install new routes to zebra and remove old ones. /* Walk the given table and install new routes to zebra and remove old ones.
* route status is tracked using ISIS_ROUTE_FLAG_ACTIVE */ * route status is tracked using ISIS_ROUTE_FLAG_ACTIVE */

View File

@ -176,9 +176,8 @@ const char *vid2string(const struct isis_vertex *vertex, char *buff, int size)
} }
if (VTYPE_IP(vertex->type)) { if (VTYPE_IP(vertex->type)) {
srcdest2str(&vertex->N.ip.dest, srcdest2str(&vertex->N.ip.p.dest, &vertex->N.ip.p.src, buff,
&vertex->N.ip.src, size);
buff, size);
return buff; return buff;
} }
@ -215,13 +214,33 @@ static struct isis_vertex *isis_vertex_new(struct isis_spftree *spftree,
return vertex; return vertex;
} }
static struct isis_vertex_adj *isis_vertex_adj_add(struct isis_vertex *vertex, static struct isis_vertex_adj *isis_vertex_adj_add(struct isis_spftree *spftree,
struct isis_spf_adj *sadj) struct isis_vertex *vertex,
struct isis_spf_adj *sadj,
struct isis_prefix_sid *psid)
{ {
struct isis_vertex_adj *vadj; struct isis_vertex_adj *vadj;
vadj = XCALLOC(MTYPE_ISIS_VERTEX_ADJ, sizeof(*vadj)); vadj = XCALLOC(MTYPE_ISIS_VERTEX_ADJ, sizeof(*vadj));
vadj->sadj = sadj; vadj->sadj = sadj;
if (psid) {
if (vertex->N.ip.sr.present
&& vertex->N.ip.sr.sid.value != psid->value)
zlog_warn(
"ISIS-SPF: ignoring different Prefix-SID for route %pFX",
&vertex->N.ip.p.dest);
else {
bool last_hop;
last_hop = (vertex->depth == 2);
vadj->sr.sid = *psid;
vadj->sr.label = sr_prefix_out_label(
spftree->lspdb, vertex->N.ip.p.dest.family,
psid, sadj->id, last_hop);
if (vadj->sr.label != MPLS_INVALID_LABEL)
vadj->sr.present = true;
}
}
listnode_add(vertex->Adj_N, vadj); listnode_add(vertex->Adj_N, vadj);
return vadj; return vadj;
@ -466,11 +485,10 @@ static void vertex_update_firsthops(struct isis_vertex *vertex,
/* /*
* Add a vertex to TENT sorted by cost and by vertextype on tie break situation * Add a vertex to TENT sorted by cost and by vertextype on tie break situation
*/ */
static struct isis_vertex *isis_spf_add2tent(struct isis_spftree *spftree, static struct isis_vertex *
enum vertextype vtype, void *id, isis_spf_add2tent(struct isis_spftree *spftree, enum vertextype vtype, void *id,
uint32_t cost, int depth, uint32_t cost, int depth, struct isis_spf_adj *sadj,
struct isis_spf_adj *sadj, struct isis_prefix_sid *psid, struct isis_vertex *parent)
struct isis_vertex *parent)
{ {
struct isis_vertex *vertex; struct isis_vertex *vertex;
struct listnode *node; struct listnode *node;
@ -496,6 +514,16 @@ static struct isis_vertex *isis_spf_add2tent(struct isis_spftree *spftree,
vertex = isis_vertex_new(spftree, id, vtype); vertex = isis_vertex_new(spftree, id, vtype);
vertex->d_N = cost; vertex->d_N = cost;
vertex->depth = depth; vertex->depth = depth;
if (VTYPE_IP(vtype) && psid) {
bool local;
local = (vertex->depth == 1);
vertex->N.ip.sr.sid = *psid;
vertex->N.ip.sr.label =
sr_prefix_in_label(spftree->area, psid, local);
if (vertex->N.ip.sr.label != MPLS_INVALID_LABEL)
vertex->N.ip.sr.present = true;
}
if (parent) { if (parent) {
listnode_add(vertex->parents, parent); listnode_add(vertex->parents, parent);
@ -508,9 +536,10 @@ static struct isis_vertex *isis_spf_add2tent(struct isis_spftree *spftree,
struct isis_vertex_adj *parent_vadj; struct isis_vertex_adj *parent_vadj;
for (ALL_LIST_ELEMENTS_RO(parent->Adj_N, node, parent_vadj)) for (ALL_LIST_ELEMENTS_RO(parent->Adj_N, node, parent_vadj))
isis_vertex_adj_add(vertex, parent_vadj->sadj); isis_vertex_adj_add(spftree, vertex, parent_vadj->sadj,
psid);
} else if (sadj) { } else if (sadj) {
isis_vertex_adj_add(vertex, sadj); isis_vertex_adj_add(spftree, vertex, sadj, psid);
} }
#ifdef EXTREME_DEBUG #ifdef EXTREME_DEBUG
@ -528,6 +557,7 @@ static struct isis_vertex *isis_spf_add2tent(struct isis_spftree *spftree,
static void isis_spf_add_local(struct isis_spftree *spftree, static void isis_spf_add_local(struct isis_spftree *spftree,
enum vertextype vtype, void *id, enum vertextype vtype, void *id,
struct isis_spf_adj *sadj, uint32_t cost, struct isis_spf_adj *sadj, uint32_t cost,
struct isis_prefix_sid *psid,
struct isis_vertex *parent) struct isis_vertex *parent)
{ {
struct isis_vertex *vertex; struct isis_vertex *vertex;
@ -538,7 +568,8 @@ static void isis_spf_add_local(struct isis_spftree *spftree,
/* C.2.5 c) */ /* C.2.5 c) */
if (vertex->d_N == cost) { if (vertex->d_N == cost) {
if (sadj) if (sadj)
isis_vertex_adj_add(vertex, sadj); isis_vertex_adj_add(spftree, vertex, sadj,
psid);
/* d) */ /* d) */
if (!CHECK_FLAG(spftree->flags, if (!CHECK_FLAG(spftree->flags,
F_SPFTREE_NO_ADJACENCIES) F_SPFTREE_NO_ADJACENCIES)
@ -558,13 +589,13 @@ static void isis_spf_add_local(struct isis_spftree *spftree,
} }
} }
isis_spf_add2tent(spftree, vtype, id, cost, 1, sadj, parent); isis_spf_add2tent(spftree, vtype, id, cost, 1, sadj, psid, parent);
return; return;
} }
static void process_N(struct isis_spftree *spftree, enum vertextype vtype, static void process_N(struct isis_spftree *spftree, enum vertextype vtype,
void *id, uint32_t dist, uint16_t depth, void *id, uint32_t dist, uint16_t depth,
struct isis_vertex *parent) struct isis_prefix_sid *psid, struct isis_vertex *parent)
{ {
struct isis_vertex *vertex; struct isis_vertex *vertex;
#ifdef EXTREME_DEBUG #ifdef EXTREME_DEBUG
@ -628,8 +659,9 @@ static void process_N(struct isis_spftree *spftree, enum vertextype vtype,
parent_vadj)) parent_vadj))
if (!isis_vertex_adj_exists(spftree, vertex, if (!isis_vertex_adj_exists(spftree, vertex,
parent_vadj->sadj)) parent_vadj->sadj))
isis_vertex_adj_add(vertex, isis_vertex_adj_add(spftree, vertex,
parent_vadj->sadj); parent_vadj->sadj,
psid);
if (CHECK_FLAG(spftree->flags, if (CHECK_FLAG(spftree->flags,
F_SPFTREE_HOPCOUNT_METRIC)) F_SPFTREE_HOPCOUNT_METRIC))
vertex_update_firsthops(vertex, parent); vertex_update_firsthops(vertex, parent);
@ -656,7 +688,7 @@ static void process_N(struct isis_spftree *spftree, enum vertextype vtype,
(parent ? print_sys_hostname(parent->N.id) : "null")); (parent ? print_sys_hostname(parent->N.id) : "null"));
#endif /* EXTREME_DEBUG */ #endif /* EXTREME_DEBUG */
isis_spf_add2tent(spftree, vtype, id, dist, depth, NULL, parent); isis_spf_add2tent(spftree, vtype, id, dist, depth, NULL, psid, parent);
return; return;
} }
@ -675,6 +707,7 @@ static int isis_spf_process_lsp(struct isis_spftree *spftree,
static const uint8_t null_sysid[ISIS_SYS_ID_LEN]; static const uint8_t null_sysid[ISIS_SYS_ID_LEN];
struct isis_mt_router_info *mt_router_info = NULL; struct isis_mt_router_info *mt_router_info = NULL;
struct prefix_pair ip_info; struct prefix_pair ip_info;
bool has_valid_psid;
if (isis_lfa_excise_node_check(spftree, lsp->hdr.lsp_id)) { if (isis_lfa_excise_node_check(spftree, lsp->hdr.lsp_id)) {
if (IS_DEBUG_TILFA) if (IS_DEBUG_TILFA)
@ -739,7 +772,7 @@ lspfragloop:
LSP_PSEUDO_ID(r->id) LSP_PSEUDO_ID(r->id)
? VTYPE_PSEUDO_IS ? VTYPE_PSEUDO_IS
: VTYPE_NONPSEUDO_IS, : VTYPE_NONPSEUDO_IS,
(void *)r->id, dist, depth + 1, (void *)r->id, dist, depth + 1, NULL,
parent); parent);
} }
} }
@ -773,7 +806,8 @@ lspfragloop:
process_N(spftree, process_N(spftree,
LSP_PSEUDO_ID(er->id) ? VTYPE_PSEUDO_TE_IS LSP_PSEUDO_ID(er->id) ? VTYPE_PSEUDO_TE_IS
: VTYPE_NONPSEUDO_TE_IS, : VTYPE_NONPSEUDO_TE_IS,
(void *)er->id, dist, depth + 1, parent); (void *)er->id, dist, depth + 1, NULL,
parent);
} }
} }
@ -798,7 +832,7 @@ lspfragloop:
ip_info.dest.u.prefix4 = r->prefix.prefix; ip_info.dest.u.prefix4 = r->prefix.prefix;
ip_info.dest.prefixlen = r->prefix.prefixlen; ip_info.dest.prefixlen = r->prefix.prefixlen;
process_N(spftree, vtype, &ip_info, process_N(spftree, vtype, &ip_info,
dist, depth + 1, parent); dist, depth + 1, NULL, parent);
} }
} }
} }
@ -823,8 +857,34 @@ lspfragloop:
dist = cost + r->metric; dist = cost + r->metric;
ip_info.dest.u.prefix4 = r->prefix.prefix; ip_info.dest.u.prefix4 = r->prefix.prefix;
ip_info.dest.prefixlen = r->prefix.prefixlen; ip_info.dest.prefixlen = r->prefix.prefixlen;
process_N(spftree, VTYPE_IPREACH_TE, &ip_info,
dist, depth + 1, parent); /* Parse list of Prefix-SID subTLVs */
has_valid_psid = false;
if (r->subtlvs) {
for (struct isis_item *i =
r->subtlvs->prefix_sids.head;
i; i = i->next) {
struct isis_prefix_sid *psid =
(struct isis_prefix_sid *)i;
if (psid->algorithm != SR_ALGORITHM_SPF)
continue;
has_valid_psid = true;
process_N(spftree, VTYPE_IPREACH_TE,
&ip_info, dist, depth + 1,
psid, parent);
/*
* Stop the Prefix-SID iteration since
* we only support the SPF algorithm for
* now.
*/
break;
}
}
if (!has_valid_psid)
process_N(spftree, VTYPE_IPREACH_TE, &ip_info,
dist, depth + 1, NULL, parent);
} }
} }
@ -865,8 +925,34 @@ lspfragloop:
} }
ip_info.src = *r->subtlvs->source_prefix; ip_info.src = *r->subtlvs->source_prefix;
} }
process_N(spftree, vtype, &ip_info, dist,
depth + 1, parent); /* Parse list of Prefix-SID subTLVs */
has_valid_psid = false;
if (r->subtlvs) {
for (struct isis_item *i =
r->subtlvs->prefix_sids.head;
i; i = i->next) {
struct isis_prefix_sid *psid =
(struct isis_prefix_sid *)i;
if (psid->algorithm != SR_ALGORITHM_SPF)
continue;
has_valid_psid = true;
process_N(spftree, vtype, &ip_info,
dist, depth + 1, psid,
parent);
/*
* Stop the Prefix-SID iteration since
* we only support the SPF algorithm for
* now.
*/
break;
}
}
if (!has_valid_psid)
process_N(spftree, vtype, &ip_info, dist,
depth + 1, NULL, parent);
} }
} }
@ -922,6 +1008,7 @@ static int isis_spf_preload_tent_ip_reach_cb(const struct prefix *prefix,
struct isis_vertex *parent = args->parent; struct isis_vertex *parent = args->parent;
struct prefix_pair ip_info; struct prefix_pair ip_info;
enum vertextype vtype; enum vertextype vtype;
bool has_valid_psid = false;
if (external) if (external)
return LSP_ITER_CONTINUE; return LSP_ITER_CONTINUE;
@ -936,7 +1023,30 @@ static int isis_spf_preload_tent_ip_reach_cb(const struct prefix *prefix,
else else
vtype = VTYPE_IP6REACH_INTERNAL; vtype = VTYPE_IP6REACH_INTERNAL;
isis_spf_add_local(spftree, vtype, &ip_info, NULL, 0, parent); /* Parse list of Prefix-SID subTLVs */
if (subtlvs) {
for (struct isis_item *i = subtlvs->prefix_sids.head; i;
i = i->next) {
struct isis_prefix_sid *psid =
(struct isis_prefix_sid *)i;
if (psid->algorithm != SR_ALGORITHM_SPF)
continue;
has_valid_psid = true;
isis_spf_add_local(spftree, vtype, &ip_info, NULL, 0,
psid, parent);
/*
* Stop the Prefix-SID iteration since we only support
* the SPF algorithm for now.
*/
break;
}
}
if (!has_valid_psid)
isis_spf_add_local(spftree, vtype, &ip_info, NULL, 0, NULL,
parent);
return LSP_ITER_CONTINUE; return LSP_ITER_CONTINUE;
} }
@ -985,7 +1095,8 @@ static void isis_spf_preload_tent(struct isis_spftree *spftree,
F_ISIS_SPF_ADJ_OLDMETRIC) F_ISIS_SPF_ADJ_OLDMETRIC)
? VTYPE_NONPSEUDO_IS ? VTYPE_NONPSEUDO_IS
: VTYPE_NONPSEUDO_TE_IS, : VTYPE_NONPSEUDO_TE_IS,
sadj->id, sadj, metric, parent); sadj->id, sadj, metric, NULL,
parent);
} else if (sadj->lan.lsp_pseudo) { } else if (sadj->lan.lsp_pseudo) {
isis_spf_process_lsp(spftree, sadj->lan.lsp_pseudo, isis_spf_process_lsp(spftree, sadj->lan.lsp_pseudo,
metric, 0, spftree->sysid, parent); metric, 0, spftree->sysid, parent);
@ -1291,8 +1402,9 @@ static void spf_path_process(struct isis_spftree *spftree,
} else } else
route_table = spftree->route_table; route_table = spftree->route_table;
isis_route_create(&vertex->N.ip.dest, &vertex->N.ip.src, isis_route_create(&vertex->N.ip.p.dest,
vertex->d_N, vertex->depth, &vertex->N.ip.p.src, vertex->d_N,
vertex->depth, &vertex->N.ip.sr,
vertex->Adj_N, area, route_table); vertex->Adj_N, area, route_table);
} else if (IS_DEBUG_SPF_EVENTS) } else if (IS_DEBUG_SPF_EVENTS)
zlog_debug( zlog_debug(
@ -1532,8 +1644,6 @@ static int isis_run_spf_cb(struct thread *thread)
isis_area_verify_routes(area); isis_area_verify_routes(area);
isis_area_verify_sr(area);
/* walk all circuits and reset any spf specific flags */ /* walk all circuits and reset any spf specific flags */
struct listnode *node; struct listnode *node;
struct isis_circuit *circuit; struct isis_circuit *circuit;
@ -1824,12 +1934,126 @@ DEFUN(show_isis_topology, show_isis_topology_cmd,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
static void isis_print_route(struct ttable *tt, const struct prefix *prefix,
struct isis_route_info *rinfo, bool prefix_sid,
bool no_adjacencies)
{
struct isis_nexthop *nexthop;
struct listnode *node;
bool first = true;
char buf_prefix[BUFSIZ];
(void)prefix2str(prefix, buf_prefix, sizeof(buf_prefix));
for (ALL_LIST_ELEMENTS_RO(rinfo->nexthops, node, nexthop)) {
struct interface *ifp;
char buf_iface[BUFSIZ];
char buf_nhop[BUFSIZ];
if (!no_adjacencies) {
inet_ntop(nexthop->family, &nexthop->ip, buf_nhop,
sizeof(buf_nhop));
ifp = if_lookup_by_index(nexthop->ifindex, VRF_DEFAULT);
if (ifp)
strlcpy(buf_iface, ifp->name,
sizeof(buf_iface));
else
snprintf(buf_iface, sizeof(buf_iface),
"ifindex %u", nexthop->ifindex);
} else {
strlcpy(buf_nhop, print_sys_hostname(nexthop->sysid),
sizeof(buf_nhop));
strlcpy(buf_iface, "-", sizeof(buf_iface));
}
if (prefix_sid) {
char buf_sid[BUFSIZ] = {};
char buf_lblop[BUFSIZ] = {};
if (nexthop->sr.present) {
snprintf(buf_sid, sizeof(buf_sid), "%u",
nexthop->sr.sid.value);
sr_op2str(buf_lblop, sizeof(buf_lblop),
rinfo->sr.label, nexthop->sr.label);
} else {
strlcpy(buf_sid, "-", sizeof(buf_sid));
strlcpy(buf_lblop, "-", sizeof(buf_lblop));
}
if (first) {
ttable_add_row(tt, "%s|%u|%s|%s|%s|%s",
buf_prefix, rinfo->cost,
buf_iface, buf_nhop, buf_sid,
buf_lblop);
first = false;
} else
ttable_add_row(tt, "||%s|%s|%s|%s", buf_iface,
buf_nhop, buf_sid, buf_lblop);
} else {
char buf_labels[BUFSIZ] = {};
if (nexthop->label_stack) {
for (int i = 0;
i < nexthop->label_stack->num_labels;
i++) {
char buf_label[BUFSIZ];
label2str(
nexthop->label_stack->label[i],
buf_label, sizeof(buf_label));
if (i != 0)
strlcat(buf_labels, "/",
sizeof(buf_labels));
strlcat(buf_labels, buf_label,
sizeof(buf_labels));
}
} else if (nexthop->sr.present)
label2str(nexthop->sr.label, buf_labels,
sizeof(buf_labels));
else
strlcpy(buf_labels, "-", sizeof(buf_labels));
if (first) {
ttable_add_row(tt, "%s|%u|%s|%s|%s", buf_prefix,
rinfo->cost, buf_iface, buf_nhop,
buf_labels);
first = false;
} else
ttable_add_row(tt, "||%s|%s|%s", buf_iface,
buf_nhop, buf_labels);
}
}
if (list_isempty(rinfo->nexthops)) {
if (prefix_sid) {
char buf_sid[BUFSIZ] = {};
char buf_lblop[BUFSIZ] = {};
if (rinfo->sr.present) {
snprintf(buf_sid, sizeof(buf_sid), "%u",
rinfo->sr.sid.value);
sr_op2str(buf_lblop, sizeof(buf_lblop),
rinfo->sr.label,
MPLS_LABEL_IMPLICIT_NULL);
} else {
strlcpy(buf_sid, "-", sizeof(buf_sid));
strlcpy(buf_lblop, "-", sizeof(buf_lblop));
}
ttable_add_row(tt, "%s|%u|%s|%s|%s|%s", buf_prefix,
rinfo->cost, "-", "-", buf_sid,
buf_lblop);
} else
ttable_add_row(tt, "%s|%u|%s|%s|%s", buf_prefix,
rinfo->cost, "-", "-", "-");
}
}
void isis_print_routes(struct vty *vty, struct isis_spftree *spftree, void isis_print_routes(struct vty *vty, struct isis_spftree *spftree,
bool backup) bool prefix_sid, bool backup)
{ {
struct route_table *route_table; struct route_table *route_table;
struct ttable *tt; struct ttable *tt;
struct route_node *rn; struct route_node *rn;
bool no_adjacencies = false;
const char *tree_id_text = NULL; const char *tree_id_text = NULL;
if (!spftree) if (!spftree)
@ -1855,82 +2079,28 @@ void isis_print_routes(struct vty *vty, struct isis_spftree *spftree,
/* Prepare table. */ /* Prepare table. */
tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]); tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
ttable_add_row(tt, "Prefix|Metric|Interface|Nexthop|Label(s)"); if (prefix_sid)
ttable_add_row(tt, "Prefix|Metric|Interface|Nexthop|SID|Label Op.");
else
ttable_add_row(tt, "Prefix|Metric|Interface|Nexthop|Label(s)");
tt->style.cell.rpad = 2; tt->style.cell.rpad = 2;
tt->style.corner = '+'; tt->style.corner = '+';
ttable_restyle(tt); ttable_restyle(tt);
ttable_rowseps(tt, 0, BOTTOM, true, '-'); ttable_rowseps(tt, 0, BOTTOM, true, '-');
if (CHECK_FLAG(spftree->flags, F_SPFTREE_NO_ADJACENCIES))
no_adjacencies = true;
route_table = route_table =
(backup) ? spftree->route_table_backup : spftree->route_table; (backup) ? spftree->route_table_backup : spftree->route_table;
for (rn = route_top(route_table); rn; rn = route_next(rn)) { for (rn = route_top(route_table); rn; rn = route_next(rn)) {
struct isis_route_info *rinfo; struct isis_route_info *rinfo;
struct isis_nexthop *nexthop;
struct listnode *node;
bool first = true;
char buf_prefix[BUFSIZ];
rinfo = rn->info; rinfo = rn->info;
if (!rinfo) if (!rinfo)
continue; continue;
(void)prefix2str(&rn->p, buf_prefix, sizeof(buf_prefix)); isis_print_route(tt, &rn->p, rinfo, prefix_sid, no_adjacencies);
for (ALL_LIST_ELEMENTS_RO(rinfo->nexthops, node, nexthop)) {
struct interface *ifp;
char buf_iface[BUFSIZ];
char buf_nhop[BUFSIZ];
char buf_labels[BUFSIZ] = {};
if (!CHECK_FLAG(spftree->flags,
F_SPFTREE_NO_ADJACENCIES)) {
inet_ntop(nexthop->family, &nexthop->ip,
buf_nhop, sizeof(buf_nhop));
ifp = if_lookup_by_index(nexthop->ifindex,
VRF_DEFAULT);
if (ifp)
strlcpy(buf_iface, ifp->name,
sizeof(buf_iface));
else
snprintf(buf_iface, sizeof(buf_iface),
"ifindex %u",
nexthop->ifindex);
} else {
strlcpy(buf_nhop,
print_sys_hostname(nexthop->sysid),
sizeof(buf_nhop));
strlcpy(buf_iface, "-", sizeof(buf_iface));
}
if (nexthop->label_stack) {
for (int i = 0;
i < nexthop->label_stack->num_labels;
i++) {
char buf_label[BUFSIZ];
label2str(
nexthop->label_stack->label[i],
buf_label, sizeof(buf_label));
if (i != 0)
strlcat(buf_labels, "/",
sizeof(buf_labels));
strlcat(buf_labels, buf_label,
sizeof(buf_labels));
}
} else if (nexthop->sr.label != MPLS_INVALID_LABEL)
label2str(nexthop->sr.label, buf_labels,
sizeof(buf_labels));
else
strlcpy(buf_labels, "-", sizeof(buf_labels));
if (first) {
ttable_add_row(tt, "%s|%u|%s|%s|%s", buf_prefix,
rinfo->cost, buf_iface, buf_nhop,
buf_labels);
first = false;
} else
ttable_add_row(tt, "||%s|%s|%s", buf_iface,
buf_nhop, buf_labels);
}
} }
/* Dump the generated table. */ /* Dump the generated table. */
@ -1945,7 +2115,8 @@ void isis_print_routes(struct vty *vty, struct isis_spftree *spftree,
} }
static void show_isis_route_common(struct vty *vty, int levels, static void show_isis_route_common(struct vty *vty, int levels,
struct isis *isis, bool backup) struct isis *isis, bool prefix_sid,
bool backup)
{ {
struct listnode *node; struct listnode *node;
struct isis_area *area; struct isis_area *area;
@ -1965,19 +2136,19 @@ static void show_isis_route_common(struct vty *vty, int levels,
isis_print_routes( isis_print_routes(
vty, vty,
area->spftree[SPFTREE_IPV4][level - 1], area->spftree[SPFTREE_IPV4][level - 1],
backup); prefix_sid, backup);
} }
if (area->ipv6_circuits > 0) { if (area->ipv6_circuits > 0) {
isis_print_routes( isis_print_routes(
vty, vty,
area->spftree[SPFTREE_IPV6][level - 1], area->spftree[SPFTREE_IPV6][level - 1],
backup); prefix_sid, backup);
} }
if (isis_area_ipv6_dstsrc_enabled(area)) { if (isis_area_ipv6_dstsrc_enabled(area)) {
isis_print_routes(vty, isis_print_routes(vty,
area->spftree[SPFTREE_DSTSRC] area->spftree[SPFTREE_DSTSRC]
[level - 1], [level - 1],
backup); prefix_sid, backup);
} }
} }
} }
@ -1989,13 +2160,14 @@ DEFUN(show_isis_route, show_isis_route_cmd,
#ifndef FABRICD #ifndef FABRICD
" [<level-1|level-2>]" " [<level-1|level-2>]"
#endif #endif
" [backup]", " [<prefix-sid|backup>]",
SHOW_STR PROTO_HELP VRF_FULL_CMD_HELP_STR SHOW_STR PROTO_HELP VRF_FULL_CMD_HELP_STR
"IS-IS routing table\n" "IS-IS routing table\n"
#ifndef FABRICD #ifndef FABRICD
"level-1 routes\n" "level-1 routes\n"
"level-2 routes\n" "level-2 routes\n"
#endif #endif
"Show Prefix-SID information\n"
"Show backup routes\n") "Show backup routes\n")
{ {
int levels; int levels;
@ -2003,6 +2175,7 @@ DEFUN(show_isis_route, show_isis_route_cmd,
struct listnode *node; struct listnode *node;
const char *vrf_name = VRF_DEFAULT_NAME; const char *vrf_name = VRF_DEFAULT_NAME;
bool all_vrf = false; bool all_vrf = false;
bool prefix_sid = false;
bool backup = false; bool backup = false;
int idx = 0; int idx = 0;
@ -2019,6 +2192,8 @@ DEFUN(show_isis_route, show_isis_route_cmd,
} }
ISIS_FIND_VRF_ARGS(argv, argc, idx, vrf_name, all_vrf); ISIS_FIND_VRF_ARGS(argv, argc, idx, vrf_name, all_vrf);
if (argv_find(argv, argc, "prefix-sid", &idx))
prefix_sid = true;
if (argv_find(argv, argc, "backup", &idx)) if (argv_find(argv, argc, "backup", &idx))
backup = true; backup = true;
@ -2026,12 +2201,13 @@ DEFUN(show_isis_route, show_isis_route_cmd,
if (all_vrf) { if (all_vrf) {
for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis))
show_isis_route_common(vty, levels, isis, show_isis_route_common(vty, levels, isis,
backup); prefix_sid, backup);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
isis = isis_lookup_by_vrfname(vrf_name); isis = isis_lookup_by_vrfname(vrf_name);
if (isis != NULL) if (isis != NULL)
show_isis_route_common(vty, levels, isis, backup); show_isis_route_common(vty, levels, isis, prefix_sid,
backup);
} }
return CMD_SUCCESS; return CMD_SUCCESS;

View File

@ -68,7 +68,7 @@ int _isis_spf_schedule(struct isis_area *area, int level,
const char *func, const char *file, int line); const char *func, const char *file, int line);
void isis_print_spftree(struct vty *vty, struct isis_spftree *spftree); void isis_print_spftree(struct vty *vty, struct isis_spftree *spftree);
void isis_print_routes(struct vty *vty, struct isis_spftree *spftree, void isis_print_routes(struct vty *vty, struct isis_spftree *spftree,
bool backup); bool prefix_sid, bool backup);
void isis_spf_init(void); void isis_spf_init(void);
void isis_spf_print(struct isis_spftree *spftree, struct vty *vty); void isis_spf_print(struct isis_spftree *spftree, struct vty *vty);
void isis_run_spf(struct isis_spftree *spftree); void isis_run_spf(struct isis_spftree *spftree);

View File

@ -52,6 +52,7 @@ struct prefix_pair {
struct isis_vertex_adj { struct isis_vertex_adj {
struct isis_spf_adj *sadj; struct isis_spf_adj *sadj;
struct isis_sr_psid_info sr;
struct mpls_label_stack *label_stack; struct mpls_label_stack *label_stack;
}; };
@ -62,7 +63,10 @@ struct isis_vertex {
enum vertextype type; enum vertextype type;
union { union {
uint8_t id[ISIS_SYS_ID_LEN + 1]; uint8_t id[ISIS_SYS_ID_LEN + 1];
struct prefix_pair ip; struct {
struct prefix_pair p;
struct isis_sr_psid_info sr;
} ip;
} N; } N;
uint32_t d_N; /* d(N) Distance from this IS */ uint32_t d_N; /* d(N) Distance from this IS */
uint16_t depth; /* The depth in the imaginary tree */ uint16_t depth; /* The depth in the imaginary tree */
@ -91,8 +95,8 @@ static unsigned isis_vertex_queue_hash_key(const void *vp)
if (VTYPE_IP(vertex->type)) { if (VTYPE_IP(vertex->type)) {
uint32_t key; uint32_t key;
key = prefix_hash_key(&vertex->N.ip.dest); key = prefix_hash_key(&vertex->N.ip.p.dest);
key = jhash_1word(prefix_hash_key(&vertex->N.ip.src), key); key = jhash_1word(prefix_hash_key(&vertex->N.ip.p.src), key);
return key; return key;
} }
@ -108,11 +112,12 @@ static bool isis_vertex_queue_hash_cmp(const void *a, const void *b)
return false; return false;
if (VTYPE_IP(va->type)) { if (VTYPE_IP(va->type)) {
if (prefix_cmp(&va->N.ip.dest, &vb->N.ip.dest)) if (prefix_cmp(&va->N.ip.p.dest, &vb->N.ip.p.dest))
return false; return false;
return prefix_cmp((const struct prefix *)&va->N.ip.src, return prefix_cmp((const struct prefix *)&va->N.ip.p.src,
(const struct prefix *)&vb->N.ip.src) == 0; (const struct prefix *)&vb->N.ip.p.src)
== 0;
} }
return memcmp(va->N.id, vb->N.id, ISIS_SYS_ID_LEN + 1) == 0; return memcmp(va->N.id, vb->N.id, ISIS_SYS_ID_LEN + 1) == 0;
@ -351,7 +356,7 @@ static void isis_vertex_id_init(struct isis_vertex *vertex, const void *id,
if (VTYPE_IS(vtype) || VTYPE_ES(vtype)) { if (VTYPE_IS(vtype) || VTYPE_ES(vtype)) {
memcpy(vertex->N.id, id, ISIS_SYS_ID_LEN + 1); memcpy(vertex->N.id, id, ISIS_SYS_ID_LEN + 1);
} else if (VTYPE_IP(vtype)) { } else if (VTYPE_IP(vtype)) {
memcpy(&vertex->N.ip, id, sizeof(vertex->N.ip)); memcpy(&vertex->N.ip.p, id, sizeof(vertex->N.ip.p));
} else { } else {
flog_err(EC_LIB_DEVELOPMENT, "Unknown Vertex Type"); flog_err(EC_LIB_DEVELOPMENT, "Unknown Vertex Type");
} }

File diff suppressed because it is too large Load Diff

View File

@ -57,11 +57,25 @@
#define SRLB_UPPER_BOUND 15999 #define SRLB_UPPER_BOUND 15999
/* Segment Routing Data Base (SRDB) RB-Tree structure */ /* Segment Routing Data Base (SRDB) RB-Tree structure */
PREDECL_RBTREE_UNIQ(srdb_node)
PREDECL_RBTREE_UNIQ(srdb_node_prefix)
PREDECL_RBTREE_UNIQ(srdb_area_prefix)
PREDECL_RBTREE_UNIQ(srdb_prefix_cfg) PREDECL_RBTREE_UNIQ(srdb_prefix_cfg)
/*
* Segment Routing Prefix-SID information.
*
* This structure is intended to be embedded inside other structures that
* might or might not contain Prefix-SID information.
*/
struct isis_sr_psid_info {
/* Prefix-SID Sub-TLV information. */
struct isis_prefix_sid sid;
/* Resolved input/output label. */
mpls_label_t label;
/* Indicates whether the Prefix-SID is present or not. */
bool present;
};
/* Segment Routing Local Block allocation */ /* Segment Routing Local Block allocation */
struct sr_local_block { struct sr_local_block {
bool active; bool active;
@ -106,85 +120,6 @@ struct sr_adjacency {
struct isis_adjacency *adj; struct isis_adjacency *adj;
}; };
/* Segment Routing Prefix-SID type. */
enum sr_prefix_type {
ISIS_SR_PREFIX_LOCAL = 0,
ISIS_SR_PREFIX_REMOTE,
};
/* Segment Routing Nexthop Information. */
struct sr_nexthop_info {
mpls_label_t label;
time_t uptime;
};
/* State of Object (SR-Node and SR-Prefix) stored in SRDB */
enum srdb_state {
SRDB_STATE_VALIDATED = 0,
SRDB_STATE_NEW,
SRDB_STATE_MODIFIED,
SRDB_STATE_UNCHANGED
};
/* Segment Routing Prefix-SID. */
struct sr_prefix {
/* SRDB RB-tree entries. */
struct srdb_node_prefix_item node_entry;
struct srdb_area_prefix_item area_entry;
/* IP prefix. */
struct prefix prefix;
/* SID value, algorithm and flags subTLVs. */
struct isis_prefix_sid sid;
/* Input label value. */
mpls_label_t input_label;
/* Prefix-SID type. */
enum sr_prefix_type type;
union {
struct {
/* Information about this local Prefix-SID. */
struct sr_nexthop_info info;
} local;
struct {
/* Route associated to this remote Prefix-SID. */
struct isis_route_info *rinfo;
} remote;
} u;
/* Backpointer to Segment Routing node. */
struct sr_node *srn;
/* SR-Prefix State used while the LSPDB is being parsed. */
enum srdb_state state;
};
/* Segment Routing node. */
struct sr_node {
/* SRDB RB-tree entry. */
struct srdb_node_item entry;
/* IS-IS level: ISIS_LEVEL1 or ISIS_LEVEL2. */
int level;
/* IS-IS node identifier. */
uint8_t sysid[ISIS_SYS_ID_LEN];
/* Segment Routing node capabilities (SRGB, SR Algorithms) subTLVs. */
struct isis_router_cap cap;
/* List of Prefix-SIDs advertised by this node. */
struct srdb_node_prefix_head prefix_sids;
/* Backpointer to IS-IS area. */
struct isis_area *area;
/* SR-Node State used while the LSPDB is being parsed. */
enum srdb_state state;
};
/* SID type. NOTE: these values must be in sync with the YANG module. */ /* SID type. NOTE: these values must be in sync with the YANG module. */
enum sr_sid_value_type { enum sr_sid_value_type {
SR_SID_VALUE_TYPE_INDEX = 0, SR_SID_VALUE_TYPE_INDEX = 0,
@ -235,12 +170,6 @@ struct isis_sr_db {
/* List of local Adjacency-SIDs. */ /* List of local Adjacency-SIDs. */
struct list *adj_sids; struct list *adj_sids;
/* Segment Routing Node information per IS-IS level. */
struct srdb_node_head sr_nodes[ISIS_LEVELS];
/* Segment Routing Prefix-SIDs per IS-IS level. */
struct srdb_area_prefix_head prefix_sids[ISIS_LEVELS];
/* Management of SRLB & SRGB allocation */ /* Management of SRLB & SRGB allocation */
struct sr_local_block srlb; struct sr_local_block srlb;
bool srgb_active; bool srgb_active;
@ -267,6 +196,14 @@ struct isis_sr_db {
}; };
/* Prototypes. */ /* Prototypes. */
extern struct isis_sr_block *isis_sr_find_srgb(struct lspdb_head *lspdb,
const uint8_t *sysid);
extern mpls_label_t sr_prefix_in_label(struct isis_area *area,
struct isis_prefix_sid *psid,
bool local);
extern mpls_label_t sr_prefix_out_label(struct lspdb_head *lspdb, int family,
struct isis_prefix_sid *psid,
const uint8_t *nh_sysid, bool last_hop);
extern int isis_sr_cfg_srgb_update(struct isis_area *area, uint32_t lower_bound, extern int isis_sr_cfg_srgb_update(struct isis_area *area, uint32_t lower_bound,
uint32_t upper_bound); uint32_t upper_bound);
extern int isis_sr_cfg_srlb_update(struct isis_area *area, uint32_t lower_bound, extern int isis_sr_cfg_srlb_update(struct isis_area *area, uint32_t lower_bound,
@ -279,16 +216,14 @@ isis_sr_cfg_prefix_find(struct isis_area *area, union prefixconstptr prefix);
extern void isis_sr_prefix_cfg2subtlv(const struct sr_prefix_cfg *pcfg, extern void isis_sr_prefix_cfg2subtlv(const struct sr_prefix_cfg *pcfg,
bool external, bool external,
struct isis_prefix_sid *psid); struct isis_prefix_sid *psid);
extern void isis_sr_nexthop_update(struct sr_nexthop_info *srnh,
mpls_label_t label);
extern void isis_sr_nexthop_reset(struct sr_nexthop_info *srnh);
extern void sr_adj_sid_add_single(struct isis_adjacency *adj, int family, extern void sr_adj_sid_add_single(struct isis_adjacency *adj, int family,
bool backup, struct list *nexthops); bool backup, struct list *nexthops);
extern struct sr_adjacency *isis_sr_adj_sid_find(struct isis_adjacency *adj, extern struct sr_adjacency *isis_sr_adj_sid_find(struct isis_adjacency *adj,
int family, int family,
enum sr_adj_type type); enum sr_adj_type type);
extern void isis_area_delete_backup_adj_sids(struct isis_area *area, int level); extern void isis_area_delete_backup_adj_sids(struct isis_area *area, int level);
extern void isis_area_verify_sr(struct isis_area *area); extern char *sr_op2str(char *buf, size_t size, mpls_label_t label_in,
mpls_label_t label_out);
extern int isis_sr_start(struct isis_area *area); extern int isis_sr_start(struct isis_area *area);
extern void isis_sr_stop(struct isis_area *area); extern void isis_sr_stop(struct isis_area *area);
extern void isis_sr_area_init(struct isis_area *area); extern void isis_sr_area_init(struct isis_area *area);

View File

@ -2603,8 +2603,8 @@ static void format_tlv_router_cap(const struct isis_router_cap *router_cap,
sbuf_push( sbuf_push(
buf, indent, buf, indent,
" Segment Routing: I:%s V:%s, Global Block Base: %u Range: %u\n", " Segment Routing: I:%s V:%s, Global Block Base: %u Range: %u\n",
IS_SR_IPV4(router_cap->srgb) ? "1" : "0", IS_SR_IPV4(&router_cap->srgb) ? "1" : "0",
IS_SR_IPV6(router_cap->srgb) ? "1" : "0", IS_SR_IPV6(&router_cap->srgb) ? "1" : "0",
router_cap->srgb.lower_bound, router_cap->srgb.lower_bound,
router_cap->srgb.range_size); router_cap->srgb.range_size);

View File

@ -138,8 +138,8 @@ struct isis_threeway_adj {
/* Segment Routing subTLV's as per RFC8667 */ /* Segment Routing subTLV's as per RFC8667 */
#define ISIS_SUBTLV_SRGB_FLAG_I 0x80 #define ISIS_SUBTLV_SRGB_FLAG_I 0x80
#define ISIS_SUBTLV_SRGB_FLAG_V 0x40 #define ISIS_SUBTLV_SRGB_FLAG_V 0x40
#define IS_SR_IPV4(srgb) (srgb.flags & ISIS_SUBTLV_SRGB_FLAG_I) #define IS_SR_IPV4(srgb) ((srgb)->flags & ISIS_SUBTLV_SRGB_FLAG_I)
#define IS_SR_IPV6(srgb) (srgb.flags & ISIS_SUBTLV_SRGB_FLAG_V) #define IS_SR_IPV6(srgb) ((srgb)->flags & ISIS_SUBTLV_SRGB_FLAG_V)
#define SUBTLV_SR_BLOCK_SIZE 6 #define SUBTLV_SR_BLOCK_SIZE 6
#define SUBTLV_RANGE_INDEX_SIZE 10 #define SUBTLV_RANGE_INDEX_SIZE 10
#define SUBTLV_RANGE_LABEL_SIZE 9 #define SUBTLV_RANGE_LABEL_SIZE 9

View File

@ -155,16 +155,14 @@ static int isis_zebra_link_params(ZAPI_CALLBACK_ARGS)
} }
enum isis_zebra_nexthop_type { enum isis_zebra_nexthop_type {
ISIS_ROUTE_NEXTHOP_MAIN = 0, ISIS_NEXTHOP_MAIN = 0,
ISIS_ROUTE_NEXTHOP_BACKUP, ISIS_NEXTHOP_BACKUP,
ISIS_MPLS_NEXTHOP_MAIN,
ISIS_MPLS_NEXTHOP_BACKUP,
}; };
static int isis_zebra_add_nexthops(struct isis *isis, struct list *nexthops, static int isis_zebra_add_nexthops(struct isis *isis, struct list *nexthops,
struct zapi_nexthop zapi_nexthops[], struct zapi_nexthop zapi_nexthops[],
enum isis_zebra_nexthop_type type, enum isis_zebra_nexthop_type type,
uint8_t backup_nhs) bool mpls_lsp, uint8_t backup_nhs)
{ {
struct isis_nexthop *nexthop; struct isis_nexthop *nexthop;
struct listnode *node; struct listnode *node;
@ -210,23 +208,18 @@ static int isis_zebra_add_nexthops(struct isis *isis, struct list *nexthops,
/* Add MPLS label(s). */ /* Add MPLS label(s). */
switch (type) { switch (type) {
case ISIS_ROUTE_NEXTHOP_MAIN: case ISIS_NEXTHOP_MAIN:
case ISIS_ROUTE_NEXTHOP_BACKUP: if (nexthop->sr.present) {
/*
* SR/TI-LFA labels are installed using separate
* messages.
*/
break;
case ISIS_MPLS_NEXTHOP_MAIN:
if (nexthop->sr.label != MPLS_INVALID_LABEL) {
api_nh->label_num = 1; api_nh->label_num = 1;
api_nh->labels[0] = nexthop->sr.label; api_nh->labels[0] = nexthop->sr.label;
} else { } else if (mpls_lsp)
api_nh->label_num = 1; /*
api_nh->labels[0] = MPLS_LABEL_IMPLICIT_NULL; * Do not use non-SR enabled nexthops to prevent
} * broken LSPs from being formed.
*/
continue;
break; break;
case ISIS_MPLS_NEXTHOP_BACKUP: case ISIS_NEXTHOP_BACKUP:
if (nexthop->label_stack) { if (nexthop->label_stack) {
api_nh->label_num = api_nh->label_num =
nexthop->label_stack->num_labels; nexthop->label_stack->num_labels;
@ -234,7 +227,11 @@ static int isis_zebra_add_nexthops(struct isis *isis, struct list *nexthops,
nexthop->label_stack->label, nexthop->label_stack->label,
sizeof(mpls_label_t) sizeof(mpls_label_t)
* api_nh->label_num); * api_nh->label_num);
} else { } else if (mpls_lsp) {
/*
* This is necessary because zebra requires
* the nexthops of MPLS LSPs to be labeled.
*/
api_nh->label_num = 1; api_nh->label_num = 1;
api_nh->labels[0] = MPLS_LABEL_IMPLICIT_NULL; api_nh->labels[0] = MPLS_LABEL_IMPLICIT_NULL;
} }
@ -266,7 +263,7 @@ void isis_zebra_route_add_route(struct isis *isis, struct prefix *prefix,
struct zapi_route api; struct zapi_route api;
int count = 0; int count = 0;
if (zclient->sock < 0) if (zclient->sock < 0 || list_isempty(route_info->nexthops))
return; return;
memset(&api, 0, sizeof(api)); memset(&api, 0, sizeof(api));
@ -286,7 +283,7 @@ void isis_zebra_route_add_route(struct isis *isis, struct prefix *prefix,
if (route_info->backup) { if (route_info->backup) {
count = isis_zebra_add_nexthops( count = isis_zebra_add_nexthops(
isis, route_info->backup->nexthops, api.backup_nexthops, isis, route_info->backup->nexthops, api.backup_nexthops,
ISIS_ROUTE_NEXTHOP_BACKUP, 0); ISIS_NEXTHOP_BACKUP, false, 0);
if (count > 0) { if (count > 0) {
SET_FLAG(api.message, ZAPI_MESSAGE_BACKUP_NEXTHOPS); SET_FLAG(api.message, ZAPI_MESSAGE_BACKUP_NEXTHOPS);
api.backup_nexthop_num = count; api.backup_nexthop_num = count;
@ -295,7 +292,7 @@ void isis_zebra_route_add_route(struct isis *isis, struct prefix *prefix,
/* Add primary nexthops. */ /* Add primary nexthops. */
count = isis_zebra_add_nexthops(isis, route_info->nexthops, count = isis_zebra_add_nexthops(isis, route_info->nexthops,
api.nexthops, ISIS_ROUTE_NEXTHOP_MAIN, api.nexthops, ISIS_NEXTHOP_MAIN, false,
count); count);
if (!count) if (!count)
return; return;
@ -328,31 +325,39 @@ void isis_zebra_route_del_route(struct isis *isis,
} }
/** /**
* Install Prefix-SID in the forwarding plane through Zebra. * Install Prefix-SID label entry in the forwarding plane through Zebra.
* *
* @param srp Segment Routing Prefix-SID * @param area IS-IS area
* @param prefix Route prefix
* @param rinfo Route information
* @param psid Prefix-SID information
*/ */
static void isis_zebra_prefix_install_prefix_sid(const struct sr_prefix *srp) void isis_zebra_prefix_sid_install(struct isis_area *area,
struct prefix *prefix,
struct isis_route_info *rinfo,
struct isis_sr_psid_info *psid)
{ {
struct isis *isis = srp->srn->area->isis;
struct zapi_labels zl; struct zapi_labels zl;
struct zapi_nexthop *znh;
struct interface *ifp;
struct isis_route_info *rinfo;
int count = 0; int count = 0;
sr_debug("ISIS-Sr (%s): update label %u for prefix %pFX",
area->area_tag, psid->label, prefix);
/* Prepare message. */ /* Prepare message. */
memset(&zl, 0, sizeof(zl)); memset(&zl, 0, sizeof(zl));
zl.type = ZEBRA_LSP_ISIS_SR; zl.type = ZEBRA_LSP_ISIS_SR;
zl.local_label = srp->input_label; zl.local_label = psid->label;
/* Local routes don't have any nexthop and require special handling. */
if (list_isempty(rinfo->nexthops)) {
struct zapi_nexthop *znh;
struct interface *ifp;
switch (srp->type) {
case ISIS_SR_PREFIX_LOCAL:
ifp = if_lookup_by_name("lo", VRF_DEFAULT); ifp = if_lookup_by_name("lo", VRF_DEFAULT);
if (!ifp) { if (!ifp) {
zlog_warn( zlog_warn(
"%s: couldn't install Prefix-SID %pFX: loopback interface not found", "%s: couldn't install Prefix-SID %pFX: loopback interface not found",
__func__, &srp->prefix); __func__, prefix);
return; return;
} }
@ -361,21 +366,12 @@ static void isis_zebra_prefix_install_prefix_sid(const struct sr_prefix *srp)
znh->ifindex = ifp->ifindex; znh->ifindex = ifp->ifindex;
znh->label_num = 1; znh->label_num = 1;
znh->labels[0] = MPLS_LABEL_IMPLICIT_NULL; znh->labels[0] = MPLS_LABEL_IMPLICIT_NULL;
break; } else {
case ISIS_SR_PREFIX_REMOTE:
/* Update route in the RIB too. */
SET_FLAG(zl.message, ZAPI_LABELS_FTN);
zl.route.prefix = srp->prefix;
zl.route.type = ZEBRA_ROUTE_ISIS;
zl.route.instance = 0;
rinfo = srp->u.remote.rinfo;
/* Add backup nexthops first. */ /* Add backup nexthops first. */
if (rinfo->backup) { if (rinfo->backup) {
count = isis_zebra_add_nexthops( count = isis_zebra_add_nexthops(
isis, rinfo->backup->nexthops, area->isis, rinfo->backup->nexthops,
zl.backup_nexthops, ISIS_MPLS_NEXTHOP_BACKUP, zl.backup_nexthops, ISIS_NEXTHOP_BACKUP, true,
0); 0);
if (count > 0) { if (count > 0) {
SET_FLAG(zl.message, ZAPI_LABELS_HAS_BACKUPS); SET_FLAG(zl.message, ZAPI_LABELS_HAS_BACKUPS);
@ -384,13 +380,12 @@ static void isis_zebra_prefix_install_prefix_sid(const struct sr_prefix *srp)
} }
/* Add primary nexthops. */ /* Add primary nexthops. */
count = isis_zebra_add_nexthops(isis, rinfo->nexthops, count = isis_zebra_add_nexthops(area->isis, rinfo->nexthops,
zl.nexthops, zl.nexthops, ISIS_NEXTHOP_MAIN,
ISIS_MPLS_NEXTHOP_MAIN, count); true, count);
if (!count) if (!count)
return; return;
zl.nexthop_num = count; zl.nexthop_num = count;
break;
} }
/* Send message to zebra. */ /* Send message to zebra. */
@ -398,57 +393,32 @@ static void isis_zebra_prefix_install_prefix_sid(const struct sr_prefix *srp)
} }
/** /**
* Uninstall Prefix-SID from the forwarding plane through Zebra. * Uninstall Prefix-SID label entry from the forwarding plane through Zebra.
* *
* @param srp Segment Routing Prefix-SID * @param area IS-IS area
* @param prefix Route prefix
* @param rinfo Route information
* @param psid Prefix-SID information
*/ */
static void isis_zebra_uninstall_prefix_sid(const struct sr_prefix *srp) void isis_zebra_prefix_sid_uninstall(struct isis_area *area,
struct prefix *prefix,
struct isis_route_info *rinfo,
struct isis_sr_psid_info *psid)
{ {
struct zapi_labels zl; struct zapi_labels zl;
sr_debug("ISIS-Sr (%s): delete label %u for prefix %pFX",
area->area_tag, psid->label, prefix);
/* Prepare message. */ /* Prepare message. */
memset(&zl, 0, sizeof(zl)); memset(&zl, 0, sizeof(zl));
zl.type = ZEBRA_LSP_ISIS_SR; zl.type = ZEBRA_LSP_ISIS_SR;
zl.local_label = srp->input_label; zl.local_label = psid->label;
if (srp->type == ISIS_SR_PREFIX_REMOTE) {
/* Update route in the RIB too. */
SET_FLAG(zl.message, ZAPI_LABELS_FTN);
zl.route.prefix = srp->prefix;
zl.route.type = ZEBRA_ROUTE_ISIS;
zl.route.instance = 0;
}
/* Send message to zebra. */ /* Send message to zebra. */
(void)zebra_send_mpls_labels(zclient, ZEBRA_MPLS_LABELS_DELETE, &zl); (void)zebra_send_mpls_labels(zclient, ZEBRA_MPLS_LABELS_DELETE, &zl);
} }
/**
* Send Prefix-SID to ZEBRA for installation or deletion.
*
* @param cmd ZEBRA_MPLS_LABELS_REPLACE or ZEBRA_ROUTE_DELETE
* @param srp Segment Routing Prefix-SID
*/
void isis_zebra_send_prefix_sid(int cmd, const struct sr_prefix *srp)
{
if (cmd != ZEBRA_MPLS_LABELS_REPLACE
&& cmd != ZEBRA_MPLS_LABELS_DELETE) {
flog_warn(EC_LIB_DEVELOPMENT, "%s: wrong ZEBRA command",
__func__);
return;
}
sr_debug(" |- %s label %u for prefix %pFX",
cmd == ZEBRA_MPLS_LABELS_REPLACE ? "Update" : "Delete",
srp->input_label, &srp->prefix);
if (cmd == ZEBRA_MPLS_LABELS_REPLACE)
isis_zebra_prefix_install_prefix_sid(srp);
else
isis_zebra_uninstall_prefix_sid(srp);
}
/** /**
* Send (LAN)-Adjacency-SID to ZEBRA for installation or deletion. * Send (LAN)-Adjacency-SID to ZEBRA for installation or deletion.
* *
@ -490,7 +460,7 @@ void isis_zebra_send_adjacency_sid(int cmd, const struct sr_adjacency *sra)
count = isis_zebra_add_nexthops(isis, sra->backup_nexthops, count = isis_zebra_add_nexthops(isis, sra->backup_nexthops,
zl.backup_nexthops, zl.backup_nexthops,
ISIS_MPLS_NEXTHOP_BACKUP, 0); ISIS_NEXTHOP_BACKUP, true, 0);
if (count > 0) { if (count > 0) {
SET_FLAG(zl.message, ZAPI_LABELS_HAS_BACKUPS); SET_FLAG(zl.message, ZAPI_LABELS_HAS_BACKUPS);
zl.backup_nexthop_num = count; zl.backup_nexthop_num = count;

View File

@ -37,7 +37,6 @@ void isis_zebra_init(struct thread_master *master, int instance);
void isis_zebra_stop(void); void isis_zebra_stop(void);
struct isis_route_info; struct isis_route_info;
struct sr_prefix;
struct sr_adjacency; struct sr_adjacency;
void isis_zebra_route_add_route(struct isis *isis, void isis_zebra_route_add_route(struct isis *isis,
@ -48,7 +47,14 @@ void isis_zebra_route_del_route(struct isis *isis,
struct prefix *prefix, struct prefix *prefix,
struct prefix_ipv6 *src_p, struct prefix_ipv6 *src_p,
struct isis_route_info *route_info); struct isis_route_info *route_info);
void isis_zebra_send_prefix_sid(int cmd, const struct sr_prefix *srp); void isis_zebra_prefix_sid_install(struct isis_area *area,
struct prefix *prefix,
struct isis_route_info *rinfo,
struct isis_sr_psid_info *psid);
void isis_zebra_prefix_sid_uninstall(struct isis_area *area,
struct prefix *prefix,
struct isis_route_info *rinfo,
struct isis_sr_psid_info *psid);
void isis_zebra_send_adjacency_sid(int cmd, const struct sr_adjacency *sra); void isis_zebra_send_adjacency_sid(int cmd, const struct sr_adjacency *sra);
int isis_distribute_list_update(int routetype); int isis_distribute_list_update(int routetype);
void isis_zebra_redistribute_set(afi_t afi, int type); void isis_zebra_redistribute_set(afi_t afi, int type);

View File

@ -66,7 +66,7 @@ static void test_run_spf(struct vty *vty, const struct isis_topology *topology,
/* Print the SPT and the corresponding routing table. */ /* Print the SPT and the corresponding routing table. */
isis_print_spftree(vty, spftree); isis_print_spftree(vty, spftree);
isis_print_routes(vty, spftree, false); isis_print_routes(vty, spftree, false, false);
/* Cleanup SPF tree. */ /* Cleanup SPF tree. */
isis_spftree_del(spftree); isis_spftree_del(spftree);
@ -122,7 +122,7 @@ static void test_run_ti_lfa(struct vty *vty,
/* Print the post-convergence SPT and the correspoding routing table. */ /* Print the post-convergence SPT and the correspoding routing table. */
isis_print_spftree(vty, spftree_pc); isis_print_spftree(vty, spftree_pc);
isis_print_routes(vty, spftree_self, true); isis_print_routes(vty, spftree_self, false, true);
/* Cleanup everything. */ /* Cleanup everything. */
isis_spftree_del(spftree_self); isis_spftree_del(spftree_self);

View File

@ -18,14 +18,15 @@ rt6 TE-IS 30 rt2 - rt4(4)
IS-IS L1 IPv4 routing table: IS-IS L1 IPv4 routing table:
Prefix Metric Interface Nexthop Label(s) Prefix Metric Interface Nexthop Label(s)
----------------------------------------------------- ----------------------------------------------------------
10.0.255.2/32 20 - rt2 - 10.0.255.1/32 0 - - -
10.0.255.3/32 20 - rt3 - 10.0.255.2/32 20 - rt2 implicit-null
10.0.255.4/32 30 - rt2 - 10.0.255.3/32 20 - rt3 implicit-null
10.0.255.5/32 30 - rt3 - 10.0.255.4/32 30 - rt2 16040
10.0.255.6/32 40 - rt2 - 10.0.255.5/32 30 - rt3 16050
- rt3 - 10.0.255.6/32 40 - rt2 16060
- rt3 16060
IS-IS paths to level-1 routers that speak IPv6 IS-IS paths to level-1 routers that speak IPv6
Vertex Type Metric Next-Hop Interface Parent Vertex Type Metric Next-Hop Interface Parent
@ -46,14 +47,15 @@ rt6 TE-IS 30 rt2 - rt4(4)
IS-IS L1 IPv6 routing table: IS-IS L1 IPv6 routing table:
Prefix Metric Interface Nexthop Label(s) Prefix Metric Interface Nexthop Label(s)
------------------------------------------------------- ------------------------------------------------------------
2001:db8::2/128 20 - rt2 - 2001:db8::1/128 0 - - -
2001:db8::3/128 20 - rt3 - 2001:db8::2/128 20 - rt2 implicit-null
2001:db8::4/128 30 - rt2 - 2001:db8::3/128 20 - rt3 implicit-null
2001:db8::5/128 30 - rt3 - 2001:db8::4/128 30 - rt2 16041
2001:db8::6/128 40 - rt2 - 2001:db8::5/128 30 - rt3 16051
- rt3 - 2001:db8::6/128 40 - rt2 16061
- rt3 16061
test# test isis topology 2 root rt1 spf test# test isis topology 2 root rt1 spf
IS-IS paths to level-1 routers that speak IP IS-IS paths to level-1 routers that speak IP
@ -76,14 +78,15 @@ rt3 TE-IS 30 rt3 - rt1(4)
IS-IS L1 IPv4 routing table: IS-IS L1 IPv4 routing table:
Prefix Metric Interface Nexthop Label(s) Prefix Metric Interface Nexthop Label(s)
----------------------------------------------------- ----------------------------------------------------------
10.0.255.2/32 25 - rt2 - 10.0.255.1/32 0 - - -
10.0.255.3/32 40 - rt3 - 10.0.255.2/32 25 - rt2 implicit-null
10.0.255.4/32 20 - rt4 - 10.0.255.3/32 40 - rt3 implicit-null
10.0.255.5/32 20 - rt5 - 10.0.255.4/32 20 - rt4 implicit-null
10.0.255.6/32 30 - rt4 - 10.0.255.5/32 20 - rt5 implicit-null
- rt5 - 10.0.255.6/32 30 - rt4 16060
- rt5 16060
IS-IS paths to level-1 routers that speak IPv6 IS-IS paths to level-1 routers that speak IPv6
Vertex Type Metric Next-Hop Interface Parent Vertex Type Metric Next-Hop Interface Parent
@ -105,14 +108,15 @@ rt3 TE-IS 30 rt3 - rt1(4)
IS-IS L1 IPv6 routing table: IS-IS L1 IPv6 routing table:
Prefix Metric Interface Nexthop Label(s) Prefix Metric Interface Nexthop Label(s)
------------------------------------------------------- ------------------------------------------------------------
2001:db8::2/128 25 - rt2 - 2001:db8::1/128 0 - - -
2001:db8::3/128 40 - rt3 - 2001:db8::2/128 25 - rt2 implicit-null
2001:db8::4/128 20 - rt4 - 2001:db8::3/128 40 - rt3 implicit-null
2001:db8::5/128 20 - rt5 - 2001:db8::4/128 20 - rt4 implicit-null
2001:db8::6/128 30 - rt4 - 2001:db8::5/128 20 - rt5 implicit-null
- rt5 - 2001:db8::6/128 30 - rt4 16061
- rt5 16061
test# test isis topology 3 root rt1 spf ipv4-only test# test isis topology 3 root rt1 spf ipv4-only
IS-IS paths to level-1 routers that speak IP IS-IS paths to level-1 routers that speak IP
@ -132,13 +136,14 @@ rt6 TE-IS 30 rt2 - rt4(4)
IS-IS L1 IPv4 routing table: IS-IS L1 IPv4 routing table:
Prefix Metric Interface Nexthop Label(s) Prefix Metric Interface Nexthop Label(s)
----------------------------------------------------- ----------------------------------------------------------
10.0.255.2/32 20 - rt2 - 10.0.255.1/32 0 - - -
10.0.255.3/32 20 - rt3 - 10.0.255.2/32 20 - rt2 implicit-null
10.0.255.4/32 30 - rt2 - 10.0.255.3/32 20 - rt3 implicit-null
10.0.255.5/32 40 - rt2 - 10.0.255.4/32 30 - rt2 16040
10.0.255.6/32 40 - rt2 - 10.0.255.5/32 40 - rt2 16050
10.0.255.6/32 40 - rt2 16060
test# test isis topology 4 root rt1 spf ipv4-only test# test isis topology 4 root rt1 spf ipv4-only
IS-IS paths to level-1 routers that speak IP IS-IS paths to level-1 routers that speak IP
@ -162,15 +167,16 @@ rt8 TE-IS 40 rt2 - rt6(4)
IS-IS L1 IPv4 routing table: IS-IS L1 IPv4 routing table:
Prefix Metric Interface Nexthop Label(s) Prefix Metric Interface Nexthop Label(s)
----------------------------------------------------- ----------------------------------------------------------
10.0.255.2/32 20 - rt2 - 10.0.255.1/32 0 - - -
10.0.255.3/32 20 - rt3 - 10.0.255.2/32 20 - rt2 implicit-null
10.0.255.4/32 30 - rt2 - 10.0.255.3/32 20 - rt3 implicit-null
10.0.255.5/32 30 - rt3 - 10.0.255.4/32 30 - rt2 16040
10.0.255.6/32 40 - rt2 - 10.0.255.5/32 30 - rt3 16050
10.0.255.7/32 40 - rt3 - 10.0.255.6/32 40 - rt2 16060
10.0.255.8/32 50 - rt2 - 10.0.255.7/32 40 - rt3 16070
10.0.255.8/32 50 - rt2 16080
test# test isis topology 5 root rt1 spf ipv4-only test# test isis topology 5 root rt1 spf ipv4-only
IS-IS paths to level-1 routers that speak IP IS-IS paths to level-1 routers that speak IP
@ -196,16 +202,17 @@ rt8 TE-IS 40 rt2 - rt6(4)
IS-IS L1 IPv4 routing table: IS-IS L1 IPv4 routing table:
Prefix Metric Interface Nexthop Label(s) Prefix Metric Interface Nexthop Label(s)
----------------------------------------------------- ----------------------------------------------------------
10.0.255.2/32 20 - rt2 - 10.0.255.1/32 0 - - -
10.0.255.3/32 20 - rt3 - 10.0.255.2/32 20 - rt2 implicit-null
10.0.255.4/32 30 - rt2 - 10.0.255.3/32 20 - rt3 implicit-null
10.0.255.5/32 30 - rt3 - 10.0.255.4/32 30 - rt2 16040
10.0.255.6/32 40 - rt2 - 10.0.255.5/32 30 - rt3 16050
10.0.255.7/32 40 - rt3 - 10.0.255.6/32 40 - rt2 16060
10.0.255.8/32 50 - rt2 - 10.0.255.7/32 40 - rt3 16070
- rt3 - 10.0.255.8/32 50 - rt2 16080
- rt3 16080
test# test isis topology 6 root rt1 spf ipv4-only test# test isis topology 6 root rt1 spf ipv4-only
IS-IS paths to level-1 routers that speak IP IS-IS paths to level-1 routers that speak IP
@ -239,20 +246,21 @@ rt7 TE-IS 50 rt2 - rt5(4)
IS-IS L1 IPv4 routing table: IS-IS L1 IPv4 routing table:
Prefix Metric Interface Nexthop Label(s) Prefix Metric Interface Nexthop Label(s)
----------------------------------------------------- ----------------------------------------------------------
10.0.255.2/32 20 - rt2 - 10.0.255.1/32 0 - - -
10.0.255.3/32 20 - rt3 - 10.0.255.2/32 20 - rt2 implicit-null
10.0.255.4/32 30 - rt2 - 10.0.255.3/32 20 - rt3 implicit-null
- rt3 - 10.0.255.4/32 30 - rt2 16040
10.0.255.5/32 50 - rt2 - - rt3 16040
- rt3 - 10.0.255.5/32 50 - rt2 16050
10.0.255.6/32 40 - rt2 - - rt3 16050
- rt3 - 10.0.255.6/32 40 - rt2 16060
10.0.255.7/32 60 - rt2 - - rt3 16060
- rt3 - 10.0.255.7/32 60 - rt2 16070
10.0.255.8/32 50 - rt2 - - rt3 16070
- rt3 - 10.0.255.8/32 50 - rt2 16080
- rt3 16080
test# test isis topology 7 root rt1 spf ipv4-only test# test isis topology 7 root rt1 spf ipv4-only
IS-IS paths to level-1 routers that speak IP IS-IS paths to level-1 routers that speak IP
@ -287,19 +295,20 @@ rt12 TE-IS 50 rt4 - rt9(4)
IS-IS L1 IPv4 routing table: IS-IS L1 IPv4 routing table:
Prefix Metric Interface Nexthop Label(s) Prefix Metric Interface Nexthop Label(s)
------------------------------------------------------ -----------------------------------------------------------
10.0.255.2/32 40 - rt4 - 10.0.255.1/32 0 - - -
10.0.255.3/32 50 - rt4 - 10.0.255.2/32 40 - rt4 16020
10.0.255.4/32 20 - rt4 - 10.0.255.3/32 50 - rt4 16030
10.0.255.5/32 30 - rt4 - 10.0.255.4/32 20 - rt4 implicit-null
10.0.255.6/32 40 - rt4 - 10.0.255.5/32 30 - rt4 16050
10.0.255.7/32 30 - rt4 - 10.0.255.6/32 40 - rt4 16060
10.0.255.8/32 40 - rt4 - 10.0.255.7/32 30 - rt4 16070
10.0.255.9/32 50 - rt4 - 10.0.255.8/32 40 - rt4 16080
10.0.255.10/32 50 - rt4 - 10.0.255.9/32 50 - rt4 16090
10.0.255.11/32 50 - rt4 - 10.0.255.10/32 50 - rt4 16100
10.0.255.12/32 60 - rt4 - 10.0.255.11/32 50 - rt4 16110
10.0.255.12/32 60 - rt4 16120
test# test isis topology 8 root rt1 spf ipv4-only test# test isis topology 8 root rt1 spf ipv4-only
IS-IS paths to level-1 routers that speak IP IS-IS paths to level-1 routers that speak IP
@ -333,19 +342,20 @@ rt12 TE-IS 50 rt2 - rt9(4)
IS-IS L1 IPv4 routing table: IS-IS L1 IPv4 routing table:
Prefix Metric Interface Nexthop Label(s) Prefix Metric Interface Nexthop Label(s)
------------------------------------------------------ -----------------------------------------------------------
10.0.255.2/32 20 - rt2 - 10.0.255.1/32 0 - - -
10.0.255.3/32 30 - rt2 - 10.0.255.2/32 20 - rt2 implicit-null
10.0.255.4/32 20 - rt4 - 10.0.255.3/32 30 - rt2 16030
10.0.255.5/32 30 - rt2 - 10.0.255.4/32 20 - rt4 implicit-null
10.0.255.6/32 40 - rt2 - 10.0.255.5/32 30 - rt2 16050
10.0.255.7/32 30 - rt4 - 10.0.255.6/32 40 - rt2 16060
10.0.255.8/32 40 - rt2 - 10.0.255.7/32 30 - rt4 16070
10.0.255.9/32 50 - rt2 - 10.0.255.8/32 40 - rt2 16080
10.0.255.10/32 40 - rt4 - 10.0.255.9/32 50 - rt2 16090
10.0.255.11/32 50 - rt2 - 10.0.255.10/32 40 - rt4 16100
10.0.255.12/32 60 - rt2 - 10.0.255.11/32 50 - rt2 16110
10.0.255.12/32 60 - rt2 16120
test# test isis topology 9 root rt1 spf test# test isis topology 9 root rt1 spf
IS-IS paths to level-1 routers that speak IP IS-IS paths to level-1 routers that speak IP
@ -374,16 +384,17 @@ rt8 TE-IS 50 rt2 - rt4(4)
IS-IS L1 IPv4 routing table: IS-IS L1 IPv4 routing table:
Prefix Metric Interface Nexthop Label(s) Prefix Metric Interface Nexthop Label(s)
----------------------------------------------------- ----------------------------------------------------------
10.0.255.2/32 20 - rt2 - 10.0.255.1/32 0 - - -
10.0.255.3/32 20 - rt3 - 10.0.255.2/32 20 - rt2 implicit-null
10.0.255.4/32 30 - rt2 - 10.0.255.3/32 20 - rt3 implicit-null
10.0.255.5/32 40 - rt2 - 10.0.255.4/32 30 - rt2 16040
10.0.255.6/32 60 - rt2 - 10.0.255.5/32 40 - rt2 16050
10.0.255.7/32 60 - rt2 - 10.0.255.6/32 60 - rt2 16060
10.0.255.8/32 60 - rt2 - 10.0.255.7/32 60 - rt2 16070
10.0.255.9/32 50 - rt2 - 10.0.255.8/32 60 - rt2 16080
10.0.255.9/32 50 - rt2 16090
IS-IS paths to level-1 routers that speak IPv6 IS-IS paths to level-1 routers that speak IPv6
Vertex Type Metric Next-Hop Interface Parent Vertex Type Metric Next-Hop Interface Parent
@ -411,16 +422,17 @@ rt8 TE-IS 50 rt2 - rt4(4)
IS-IS L1 IPv6 routing table: IS-IS L1 IPv6 routing table:
Prefix Metric Interface Nexthop Label(s) Prefix Metric Interface Nexthop Label(s)
------------------------------------------------------- ------------------------------------------------------------
2001:db8::2/128 20 - rt2 - 2001:db8::1/128 0 - - -
2001:db8::3/128 20 - rt3 - 2001:db8::2/128 20 - rt2 implicit-null
2001:db8::4/128 30 - rt2 - 2001:db8::3/128 20 - rt3 implicit-null
2001:db8::5/128 40 - rt2 - 2001:db8::4/128 30 - rt2 16041
2001:db8::6/128 60 - rt2 - 2001:db8::5/128 40 - rt2 16051
2001:db8::7/128 60 - rt2 - 2001:db8::6/128 60 - rt2 16061
2001:db8::8/128 60 - rt2 - 2001:db8::7/128 60 - rt2 16071
2001:db8::9/128 50 - rt2 - 2001:db8::8/128 60 - rt2 16081
2001:db8::9/128 50 - rt2 16091
test# test isis topology 10 root rt1 spf test# test isis topology 10 root rt1 spf
IS-IS paths to level-1 routers that speak IP IS-IS paths to level-1 routers that speak IP
@ -444,15 +456,16 @@ rt8 TE-IS 30 rt2 - rt5(4)
IS-IS L1 IPv4 routing table: IS-IS L1 IPv4 routing table:
Prefix Metric Interface Nexthop Label(s) Prefix Metric Interface Nexthop Label(s)
----------------------------------------------------- ----------------------------------------------------------
10.0.255.2/32 20 - rt2 - 10.0.255.1/32 0 - - -
10.0.255.3/32 30 - rt3 - 10.0.255.2/32 20 - rt2 implicit-null
10.0.255.4/32 30 - rt4 - 10.0.255.3/32 30 - rt3 implicit-null
10.0.255.5/32 30 - rt2 - 10.0.255.4/32 30 - rt4 implicit-null
10.0.255.6/32 40 - rt3 - 10.0.255.5/32 30 - rt2 16050
10.0.255.7/32 40 - rt4 - 10.0.255.6/32 40 - rt3 20060
10.0.255.8/32 40 - rt2 - 10.0.255.7/32 40 - rt4 16070
10.0.255.8/32 40 - rt2 16080
IS-IS paths to level-1 routers that speak IPv6 IS-IS paths to level-1 routers that speak IPv6
Vertex Type Metric Next-Hop Interface Parent Vertex Type Metric Next-Hop Interface Parent
@ -475,15 +488,16 @@ rt8 TE-IS 30 rt2 - rt5(4)
IS-IS L1 IPv6 routing table: IS-IS L1 IPv6 routing table:
Prefix Metric Interface Nexthop Label(s) Prefix Metric Interface Nexthop Label(s)
------------------------------------------------------- ------------------------------------------------------------
2001:db8::2/128 20 - rt2 - 2001:db8::1/128 0 - - -
2001:db8::3/128 30 - rt3 - 2001:db8::2/128 20 - rt2 implicit-null
2001:db8::4/128 30 - rt4 - 2001:db8::3/128 30 - rt3 implicit-null
2001:db8::5/128 30 - rt2 - 2001:db8::4/128 30 - rt4 implicit-null
2001:db8::6/128 40 - rt3 - 2001:db8::5/128 30 - rt2 16051
2001:db8::7/128 40 - rt4 - 2001:db8::6/128 40 - rt3 20061
2001:db8::8/128 40 - rt2 - 2001:db8::7/128 40 - rt4 16071
2001:db8::8/128 40 - rt2 16081
test# test isis topology 11 root rt1 spf test# test isis topology 11 root rt1 spf
IS-IS paths to level-1 routers that speak IP IS-IS paths to level-1 routers that speak IP
@ -506,14 +520,15 @@ rt6 TE-IS 30 rt2 - rt4(4)
IS-IS L1 IPv4 routing table: IS-IS L1 IPv4 routing table:
Prefix Metric Interface Nexthop Label(s) Prefix Metric Interface Nexthop Label(s)
----------------------------------------------------- ----------------------------------------------------------
10.0.255.2/32 20 - rt2 - 10.0.255.1/32 0 - - -
10.0.255.3/32 20 - rt3 - 10.0.255.2/32 20 - rt2 implicit-null
10.0.255.4/32 30 - rt2 - 10.0.255.3/32 20 - rt3 implicit-null
10.0.255.5/32 30 - rt3 - 10.0.255.4/32 30 - rt2 16040
10.0.255.6/32 40 - rt2 - 10.0.255.5/32 30 - rt3 16050
- rt3 - 10.0.255.6/32 40 - rt2 16060
- rt3 16060
IS-IS paths to level-1 routers that speak IPv6 IS-IS paths to level-1 routers that speak IPv6
Vertex Type Metric Next-Hop Interface Parent Vertex Type Metric Next-Hop Interface Parent
@ -535,14 +550,15 @@ rt6 TE-IS 30 rt2 - rt4(4)
IS-IS L1 IPv6 routing table: IS-IS L1 IPv6 routing table:
Prefix Metric Interface Nexthop Label(s) Prefix Metric Interface Nexthop Label(s)
------------------------------------------------------- ------------------------------------------------------------
2001:db8::2/128 20 - rt2 - 2001:db8::1/128 0 - - -
2001:db8::3/128 20 - rt3 - 2001:db8::2/128 20 - rt2 implicit-null
2001:db8::4/128 30 - rt2 - 2001:db8::3/128 20 - rt3 implicit-null
2001:db8::5/128 30 - rt3 - 2001:db8::4/128 30 - rt2 16041
2001:db8::6/128 40 - rt2 - 2001:db8::5/128 30 - rt3 16051
- rt3 - 2001:db8::6/128 40 - rt2 16061
- rt3 16061
test# test isis topology 12 root rt1 spf ipv4-only test# test isis topology 12 root rt1 spf ipv4-only
IS-IS paths to level-1 routers that speak IP IS-IS paths to level-1 routers that speak IP
@ -570,17 +586,18 @@ rt10 TE-IS 50 rt2 - rt8(4)
IS-IS L1 IPv4 routing table: IS-IS L1 IPv4 routing table:
Prefix Metric Interface Nexthop Label(s) Prefix Metric Interface Nexthop Label(s)
------------------------------------------------------ -----------------------------------------------------------
10.0.255.2/32 20 - rt2 - 10.0.255.1/32 0 - - -
10.0.255.3/32 20 - rt3 - 10.0.255.2/32 20 - rt2 implicit-null
10.0.255.4/32 30 - rt2 - 10.0.255.3/32 20 - rt3 implicit-null
10.0.255.5/32 30 - rt3 - 10.0.255.4/32 30 - rt2 16040
10.0.255.6/32 40 - rt2 - 10.0.255.5/32 30 - rt3 16050
10.0.255.7/32 40 - rt3 - 10.0.255.6/32 40 - rt2 16060
10.0.255.8/32 50 - rt2 - 10.0.255.7/32 40 - rt3 16070
10.0.255.9/32 50 - rt3 - 10.0.255.8/32 50 - rt2 16080
10.0.255.10/32 60 - rt2 - 10.0.255.9/32 50 - rt3 16090
10.0.255.10/32 60 - rt2 16100
test# test isis topology 13 root rt1 spf ipv4-only test# test isis topology 13 root rt1 spf ipv4-only
IS-IS paths to level-1 routers that speak IP IS-IS paths to level-1 routers that speak IP
@ -605,15 +622,16 @@ rt7 TE-IS 30 rt3 - rt5(4)
IS-IS L1 IPv4 routing table: IS-IS L1 IPv4 routing table:
Prefix Metric Interface Nexthop Label(s) Prefix Metric Interface Nexthop Label(s)
----------------------------------------------------- ----------------------------------------------------------
10.0.255.2/32 20 - rt2 - 10.0.255.1/32 0 - - -
10.0.255.3/32 20 - rt3 - 10.0.255.2/32 20 - rt2 implicit-null
10.0.255.4/32 30 - rt2 - 10.0.255.3/32 20 - rt3 implicit-null
- rt3 - 10.0.255.4/32 30 - rt2 16040
10.0.255.5/32 30 - rt3 - - rt3 16040
10.0.255.6/32 30 - rt3 - 10.0.255.5/32 30 - rt3 16050
10.0.255.7/32 40 - rt3 - 10.0.255.6/32 30 - rt3 16060
10.0.255.7/32 40 - rt3 16070
test# test#
test# test isis topology 4 root rt1 reverse-spf ipv4-only test# test isis topology 4 root rt1 reverse-spf ipv4-only
@ -638,15 +656,16 @@ rt8 TE-IS 40 rt2 - rt6(4)
IS-IS L1 IPv4 routing table: IS-IS L1 IPv4 routing table:
Prefix Metric Interface Nexthop Label(s) Prefix Metric Interface Nexthop Label(s)
----------------------------------------------------- ----------------------------------------------------------
10.0.255.2/32 20 - rt2 - 10.0.255.1/32 0 - - -
10.0.255.3/32 20 - rt3 - 10.0.255.2/32 20 - rt2 implicit-null
10.0.255.4/32 30 - rt2 - 10.0.255.3/32 20 - rt3 implicit-null
10.0.255.5/32 30 - rt3 - 10.0.255.4/32 30 - rt2 16040
10.0.255.6/32 40 - rt2 - 10.0.255.5/32 30 - rt3 16050
10.0.255.7/32 40 - rt3 - 10.0.255.6/32 40 - rt2 16060
10.0.255.8/32 50 - rt2 - 10.0.255.7/32 40 - rt3 16070
10.0.255.8/32 50 - rt2 16080
test# test isis topology 11 root rt1 reverse-spf test# test isis topology 11 root rt1 reverse-spf
IS-IS paths to level-1 routers that speak IP IS-IS paths to level-1 routers that speak IP
@ -668,11 +687,12 @@ rt6 TE-IS 30 rt3 - rt4(4)
IS-IS L1 IPv4 routing table: IS-IS L1 IPv4 routing table:
Prefix Metric Interface Nexthop Label(s) Prefix Metric Interface Nexthop Label(s)
----------------------------------------------------- ----------------------------------------------------------
10.0.255.3/32 20 - rt3 - 10.0.255.1/32 0 - - -
10.0.255.5/32 30 - rt3 - 10.0.255.3/32 20 - rt3 implicit-null
10.0.255.6/32 40 - rt3 - 10.0.255.5/32 30 - rt3 16050
10.0.255.6/32 40 - rt3 16060
IS-IS paths to level-1 routers that speak IPv6 IS-IS paths to level-1 routers that speak IPv6
Vertex Type Metric Next-Hop Interface Parent Vertex Type Metric Next-Hop Interface Parent
@ -693,11 +713,12 @@ rt6 TE-IS 30 rt3 - rt4(4)
IS-IS L1 IPv6 routing table: IS-IS L1 IPv6 routing table:
Prefix Metric Interface Nexthop Label(s) Prefix Metric Interface Nexthop Label(s)
------------------------------------------------------- ------------------------------------------------------------
2001:db8::3/128 20 - rt3 - 2001:db8::1/128 0 - - -
2001:db8::5/128 30 - rt3 - 2001:db8::3/128 20 - rt3 implicit-null
2001:db8::6/128 40 - rt3 - 2001:db8::5/128 30 - rt3 16051
2001:db8::6/128 40 - rt3 16061
test# test#
test# test isis topology 1 root rt1 ti-lfa system-id rt2 test# test isis topology 1 root rt1 ti-lfa system-id rt2
@ -996,7 +1017,7 @@ IS-IS L1 IPv4 routing table:
----------------------------------------------------- -----------------------------------------------------
10.0.255.1/32 40 - rt6 16040 10.0.255.1/32 40 - rt6 16040
10.0.255.2/32 55 - rt6 16040 10.0.255.2/32 55 - rt6 16040
10.0.255.4/32 30 - rt6 - 10.0.255.4/32 30 - rt6 16040
P-space (self): P-space (self):
rt6 rt6
@ -1040,7 +1061,7 @@ IS-IS L1 IPv6 routing table:
------------------------------------------------------- -------------------------------------------------------
2001:db8::1/128 40 - rt6 16041 2001:db8::1/128 40 - rt6 16041
2001:db8::2/128 55 - rt6 16041 2001:db8::2/128 55 - rt6 16041
2001:db8::4/128 30 - rt6 - 2001:db8::4/128 30 - rt6 16041
test# test isis topology 3 root rt5 ti-lfa system-id rt4 ipv4-only test# test isis topology 3 root rt5 ti-lfa system-id rt4 ipv4-only
P-space (self): P-space (self):
@ -1088,10 +1109,10 @@ IS-IS L1 IPv4 routing table:
Prefix Metric Interface Nexthop Label(s) Prefix Metric Interface Nexthop Label(s)
----------------------------------------------------- -----------------------------------------------------
10.0.255.1/32 50 - rt3 - 10.0.255.1/32 50 - rt3 16010
- rt6 - - rt6 16010
10.0.255.2/32 40 - rt6 - 10.0.255.2/32 40 - rt6 16020
10.0.255.4/32 30 - rt6 - 10.0.255.4/32 30 - rt6 16040
test# test isis topology 3 root rt5 ti-lfa system-id rt3 ipv4-only test# test isis topology 3 root rt5 ti-lfa system-id rt3 ipv4-only
P-space (self): P-space (self):
@ -1380,13 +1401,13 @@ IS-IS L1 IPv4 routing table:
Prefix Metric Interface Nexthop Label(s) Prefix Metric Interface Nexthop Label(s)
----------------------------------------------------- -----------------------------------------------------
10.0.255.1/32 60 - rt10 - 10.0.255.1/32 60 - rt10 16010
10.0.255.2/32 60 - rt12 16090 10.0.255.2/32 60 - rt12 16090
10.0.255.3/32 70 - rt12 16090 10.0.255.3/32 70 - rt12 16090
10.0.255.4/32 50 - rt10 - 10.0.255.4/32 50 - rt10 16040
10.0.255.5/32 50 - rt12 16090 10.0.255.5/32 50 - rt12 16090
10.0.255.6/32 60 - rt12 16090 10.0.255.6/32 60 - rt12 16090
10.0.255.7/32 40 - rt10 - 10.0.255.7/32 40 - rt10 16070
10.0.255.8/32 40 - rt12 16090 10.0.255.8/32 40 - rt12 16090
test# test isis topology 7 root rt6 ti-lfa system-id rt5 ipv4-only test# test isis topology 7 root rt6 ti-lfa system-id rt5 ipv4-only
@ -1463,14 +1484,14 @@ IS-IS L1 IPv4 routing table:
10.0.255.1/32 60 - rt3 16020 10.0.255.1/32 60 - rt3 16020
10.0.255.4/32 50 - rt3 16020 10.0.255.4/32 50 - rt3 16020
10.0.255.5/32 40 - rt3 16020 10.0.255.5/32 40 - rt3 16020
10.0.255.7/32 60 - rt9 - 10.0.255.7/32 60 - rt9 16070
- rt3 - - rt3 16070
10.0.255.8/32 50 - rt9 - 10.0.255.8/32 50 - rt9 16080
- rt3 - - rt3 16080
10.0.255.10/32 70 - rt9 - 10.0.255.10/32 70 - rt9 16100
- rt3 - - rt3 16100
10.0.255.11/32 60 - rt9 - 10.0.255.11/32 60 - rt9 16110
- rt3 - - rt3 16110
test# test isis topology 8 root rt2 ti-lfa system-id rt1 ipv4-only test# test isis topology 8 root rt2 ti-lfa system-id rt1 ipv4-only
P-space (self): P-space (self):
@ -2322,13 +2343,13 @@ rt6 TE-IS 70 rt3 - rt5(4)
IS-IS L1 IPv4 routing table: IS-IS L1 IPv4 routing table:
Prefix Metric Interface Nexthop Label(s) Prefix Metric Interface Nexthop Label(s)
----------------------------------------------------- ----------------------------------------------------------
10.0.255.1/32 60 - rt1 - 10.0.255.1/32 60 - rt1 implicit-null
10.0.255.3/32 60 - rt3 - 10.0.255.3/32 60 - rt3 implicit-null
10.0.255.4/32 80 - rt3 16050 10.0.255.4/32 80 - rt3 16050
10.0.255.5/32 70 - rt3 - 10.0.255.5/32 70 - rt3 16050
10.0.255.6/32 80 - rt3 - 10.0.255.6/32 80 - rt3 16060
P-space (self): P-space (self):
@ -2368,13 +2389,13 @@ rt6 TE-IS 70 rt3 - rt5(4)
IS-IS L1 IPv6 routing table: IS-IS L1 IPv6 routing table:
Prefix Metric Interface Nexthop Label(s) Prefix Metric Interface Nexthop Label(s)
------------------------------------------------------- ------------------------------------------------------------
2001:db8::1/128 60 - rt1 - 2001:db8::1/128 60 - rt1 implicit-null
2001:db8::3/128 60 - rt3 - 2001:db8::3/128 60 - rt3 implicit-null
2001:db8::4/128 80 - rt3 16051 2001:db8::4/128 80 - rt3 16051
2001:db8::5/128 70 - rt3 - 2001:db8::5/128 70 - rt3 16051
2001:db8::6/128 80 - rt3 - 2001:db8::6/128 80 - rt3 16061
test# test isis topology 12 root rt1 ti-lfa system-id rt3 ipv4-only test# test isis topology 12 root rt1 ti-lfa system-id rt3 ipv4-only
P-space (self): P-space (self):