tests: add remote LFA unit tests

Extend the existing SPF unit testing infrastructure so that it can
test RLFA as well.

These new unit tests are useful to test the RLFA PQ node
computation on several different network topologies in a timely
manner. Artificial LDP labels (starting from 50000) are used to
activate the computed RLFAs.

It's worth mentioning that the computed backup routing tables
contain both local LFAs and remote LFAs, as running RLFA separately
isn't possible.

Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
This commit is contained in:
Renato Westphal 2020-12-01 00:12:08 -03:00
parent 16fe8cffa1
commit c40de29448
5 changed files with 1355 additions and 0 deletions

View file

@ -69,6 +69,24 @@ test_find_adjacency(const struct isis_test_node *tnode, const char *hostname)
return NULL;
}
mpls_label_t test_topology_node_ldp_label(const struct isis_topology *topology,
struct in_addr router_id)
{
for (size_t i = 0; topology->nodes[i].hostname[0]; i++) {
const struct isis_test_node *tnode = &topology->nodes[i];
struct in_addr node_router_id;
if (!tnode->router_id)
continue;
(void)inet_pton(AF_INET, tnode->router_id, &node_router_id);
if (IPV4_ADDR_SAME(&router_id, &node_router_id))
return (50000 + (i + 1) * 100);
}
return MPLS_INVALID_LABEL;
}
static struct isis_lsp *lsp_add(struct lspdb_head *lspdb,
struct isis_area *area, int level,
const uint8_t *sysid, uint8_t pseudonode_id)

View file

@ -70,6 +70,9 @@ test_topology_find_node(const struct isis_topology *topology,
const char *hostname, uint8_t pseudonode_id);
extern const struct isis_topology *
test_topology_find(struct isis_topology *test_topologies, uint16_t number);
extern mpls_label_t
test_topology_node_ldp_label(const struct isis_topology *topology,
struct in_addr router_id);
extern int test_topology_load(const struct isis_topology *topology,
struct isis_area *area,
struct lspdb_head lspdb[]);

View file

@ -31,6 +31,7 @@
#include "isisd/isisd.h"
#include "isisd/isis_dynhn.h"
#include "isisd/isis_misc.h"
#include "isisd/isis_route.h"
#include "isisd/isis_spf.h"
#include "isisd/isis_spf_private.h"
@ -40,6 +41,7 @@ enum test_type {
TEST_SPF = 1,
TEST_REVERSE_SPF,
TEST_LFA,
TEST_RLFA,
TEST_TI_LFA,
};
@ -105,6 +107,86 @@ static void test_run_lfa(struct vty *vty, const struct isis_topology *topology,
isis_spftree_del(spftree_self);
}
static void test_run_rlfa(struct vty *vty, const struct isis_topology *topology,
const struct isis_test_node *root,
struct isis_area *area, struct lspdb_head *lspdb,
int level, int tree,
struct lfa_protected_resource *protected_resource)
{
struct isis_spftree *spftree_self;
struct isis_spftree *spftree_reverse;
struct isis_spftree *spftree_pc;
struct isis_spf_node *spf_node, *node;
struct rlfa *rlfa;
uint8_t flags;
/* Run forward SPF in the root node. */
flags = F_SPFTREE_NO_ADJACENCIES;
spftree_self = isis_spftree_new(area, lspdb, root->sysid, level, tree,
SPF_TYPE_FORWARD, flags);
isis_run_spf(spftree_self);
/* Run reverse SPF in the root node. */
spftree_reverse = isis_spf_reverse_run(spftree_self);
/* Run forward SPF on all adjacent routers. */
isis_spf_run_neighbors(spftree_self);
/* Compute the local LFA repair paths. */
isis_lfa_compute(area, NULL, spftree_self, protected_resource);
/* Compute the remote LFA repair paths. */
spftree_pc = isis_rlfa_compute(area, spftree_self, spftree_reverse, 0,
protected_resource);
/* Print the extended P-space and Q-space. */
vty_out(vty, "P-space (self):\n");
RB_FOREACH (node, isis_spf_nodes, &spftree_pc->lfa.p_space)
vty_out(vty, " %s\n", print_sys_hostname(node->sysid));
vty_out(vty, "\n");
RB_FOREACH (spf_node, isis_spf_nodes, &spftree_self->adj_nodes) {
if (RB_EMPTY(isis_spf_nodes, &spf_node->lfa.p_space))
continue;
vty_out(vty, "P-space (%s):\n",
print_sys_hostname(spf_node->sysid));
RB_FOREACH (node, isis_spf_nodes, &spf_node->lfa.p_space)
vty_out(vty, " %s\n", print_sys_hostname(node->sysid));
vty_out(vty, "\n");
}
vty_out(vty, "Q-space:\n");
RB_FOREACH (node, isis_spf_nodes, &spftree_pc->lfa.q_space)
vty_out(vty, " %s\n", print_sys_hostname(node->sysid));
vty_out(vty, "\n");
/* Print the post-convergence SPT. */
isis_print_spftree(vty, spftree_pc);
/*
* Activate the computed RLFAs (if any) using artificial LDP labels for
* the PQ nodes.
*/
frr_each_safe (rlfa_tree, &spftree_self->lfa.remote.rlfas, rlfa) {
struct zapi_rlfa_response response = {};
response.pq_label = test_topology_node_ldp_label(
topology, rlfa->pq_address);
assert(response.pq_label != MPLS_INVALID_LABEL);
isis_rlfa_activate(spftree_self, rlfa, &response);
}
/* Print the SPT and the corresponding main/backup routing tables. */
isis_print_spftree(vty, spftree_self);
vty_out(vty, "Main:\n");
isis_print_routes(vty, spftree_self, false, false);
vty_out(vty, "Backup:\n");
isis_print_routes(vty, spftree_self, false, true);
/* Cleanup everything. */
isis_spftree_del(spftree_self);
isis_spftree_del(spftree_reverse);
isis_spftree_del(spftree_pc);
}
static void test_run_ti_lfa(struct vty *vty,
const struct isis_topology *topology,
const struct isis_test_node *root,
@ -242,6 +324,11 @@ static int test_run(struct vty *vty, const struct isis_topology *topology,
&area->lspdb[level - 1], level,
tree, &protected_resource);
break;
case TEST_RLFA:
test_run_rlfa(vty, topology, root, area,
&area->lspdb[level - 1], level,
tree, &protected_resource);
break;
case TEST_TI_LFA:
test_run_ti_lfa(vty, topology, root, area,
&area->lspdb[level - 1], level,
@ -266,6 +353,7 @@ DEFUN(test_isis, test_isis_cmd,
spf\
|reverse-spf\
|lfa system-id WORD [pseudonode-id <1-255>]\
|remote-lfa system-id WORD [pseudonode-id <1-255>]\
|ti-lfa system-id WORD [pseudonode-id <1-255>] [node-protection]\
>\
[display-lspdb] [<ipv4-only|ipv6-only>] [<level-1-only|level-2-only>]",
@ -282,6 +370,11 @@ DEFUN(test_isis, test_isis_cmd,
"System ID\n"
"Pseudonode-ID\n"
"Pseudonode-ID\n"
"Remote LFA\n"
"System ID\n"
"System ID\n"
"Pseudonode-ID\n"
"Pseudonode-ID\n"
"Topology Independent LFA\n"
"System ID\n"
"System ID\n"
@ -330,6 +423,14 @@ DEFUN(test_isis, test_isis_cmd,
else if (argv_find(argv, argc, "lfa", &idx)) {
test_type = TEST_LFA;
fail_sysid_str = argv[idx + 2]->arg;
if (argv_find(argv, argc, "pseudonode-id", &idx))
fail_pseudonode_id =
strtoul(argv[idx + 1]->arg, NULL, 10);
protection_type = LFA_LINK_PROTECTION;
} else if (argv_find(argv, argc, "remote-lfa", &idx)) {
test_type = TEST_RLFA;
fail_sysid_str = argv[idx + 2]->arg;
if (argv_find(argv, argc, "pseudonode-id", &idx))
fail_pseudonode_id =

View file

@ -31,6 +31,18 @@ test isis topology 14 root rt1 lfa system-id rt1 pseudonode-id 1
test isis topology 14 root rt1 lfa system-id rt2
test isis topology 14 root rt5 lfa system-id rt4
test isis topology 1 root rt1 remote-lfa system-id rt2
test isis topology 2 root rt5 remote-lfa system-id rt1 pseudonode-id 1
test isis topology 3 root rt5 remote-lfa system-id rt4 ipv4-only
test isis topology 3 root rt5 remote-lfa system-id rt3 ipv4-only
test isis topology 5 root rt1 remote-lfa system-id rt2 ipv4-only
test isis topology 6 root rt4 remote-lfa system-id rt3 ipv4-only
test isis topology 7 root rt11 remote-lfa system-id rt8 ipv4-only
test isis topology 7 root rt6 remote-lfa system-id rt5 ipv4-only
test isis topology 8 root rt2 remote-lfa system-id rt5 ipv4-only
test isis topology 11 root rt2 remote-lfa system-id rt4
test isis topology 13 root rt1 remote-lfa system-id rt3 ipv4-only
test isis topology 1 root rt1 ti-lfa system-id rt2
test isis topology 2 root rt1 ti-lfa system-id rt3
test isis topology 2 root rt1 ti-lfa system-id rt1 pseudonode-id 1

File diff suppressed because it is too large Load diff