mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-08 10:56:37 +00:00
Merge pull request #6934 from Niral-Networks/niral_dev_vrf_isis_core_pr4
isisd, yang, doc : Support for different VRF in ISIS.
This commit is contained in:
commit
b686742e2b
@ -47,7 +47,7 @@ digraph climodes {
|
|||||||
CONFIG_NODE -> OSPF_NODE [ label="router ospf [(1-65535)] [vrf NAME]" ];
|
CONFIG_NODE -> OSPF_NODE [ label="router ospf [(1-65535)] [vrf NAME]" ];
|
||||||
CONFIG_NODE -> OSPF6_NODE [ label="router ospf6" ];
|
CONFIG_NODE -> OSPF6_NODE [ label="router ospf6" ];
|
||||||
CONFIG_NODE -> LDP_NODE [ label="mpls ldp" ];
|
CONFIG_NODE -> LDP_NODE [ label="mpls ldp" ];
|
||||||
CONFIG_NODE -> ISIS_NODE [ label="router isis WORD" ];
|
CONFIG_NODE -> ISIS_NODE [ label="router isis WORD [vrf NAME]" ];
|
||||||
CONFIG_NODE -> RMAP_NODE [ label="route-map WORD <deny|permit> (1-65535)" ];
|
CONFIG_NODE -> RMAP_NODE [ label="route-map WORD <deny|permit> (1-65535)" ];
|
||||||
CONFIG_NODE -> PW_NODE [ label="pseudowire IFNAME" ];
|
CONFIG_NODE -> PW_NODE [ label="pseudowire IFNAME" ];
|
||||||
CONFIG_NODE -> VTY_NODE [ label="line vty" ];
|
CONFIG_NODE -> VTY_NODE [ label="line vty" ];
|
||||||
|
@ -33,8 +33,8 @@ ISIS router
|
|||||||
To start the ISIS process you have to specify the ISIS router. As of this
|
To start the ISIS process you have to specify the ISIS router. As of this
|
||||||
writing, *isisd* does not support multiple ISIS processes.
|
writing, *isisd* does not support multiple ISIS processes.
|
||||||
|
|
||||||
.. index:: [no] router isis WORD
|
.. index:: [no] router isis WORD [vrf NAME]
|
||||||
.. clicmd:: [no] router isis WORD
|
.. clicmd:: [no] router isis WORD [vrf NAME]
|
||||||
|
|
||||||
Enable or disable the ISIS process by specifying the ISIS domain with
|
Enable or disable the ISIS process by specifying the ISIS domain with
|
||||||
'WORD'. *isisd* does not yet support multiple ISIS processes but you must
|
'WORD'. *isisd* does not yet support multiple ISIS processes but you must
|
||||||
@ -202,8 +202,8 @@ ISIS interface
|
|||||||
|
|
||||||
.. _ip-router-isis-word:
|
.. _ip-router-isis-word:
|
||||||
|
|
||||||
.. index:: [no] <ip|ipv6> router isis WORD
|
.. index:: [no] <ip|ipv6> router isis WORD [vrf NAME]
|
||||||
.. clicmd:: [no] <ip|ipv6> router isis WORD
|
.. clicmd:: [no] <ip|ipv6> router isis WORD [vrf NAME]
|
||||||
|
|
||||||
Activate ISIS adjacency on this interface. Note that the name of ISIS
|
Activate ISIS adjacency on this interface. Note that the name of ISIS
|
||||||
instance must be the same as the one used to configure the ISIS process (see
|
instance must be the same as the one used to configure the ISIS process (see
|
||||||
@ -751,3 +751,22 @@ A Segment Routing configuration, with IPv4, IPv6, SRGB and MSD configuration.
|
|||||||
segment-routing prefix 2001:db8:1000::1/128 index 101 explicit-null
|
segment-routing prefix 2001:db8:1000::1/128 index 101 explicit-null
|
||||||
!
|
!
|
||||||
|
|
||||||
|
ISIS Vrf Configuration Examples
|
||||||
|
===============================
|
||||||
|
|
||||||
|
A simple vrf example:
|
||||||
|
|
||||||
|
.. code-block:: frr
|
||||||
|
|
||||||
|
!
|
||||||
|
interface eth0 vrf RED
|
||||||
|
ip router isis FOO vrf RED
|
||||||
|
isis network point-to-point
|
||||||
|
isis circuit-type level-2-only
|
||||||
|
!
|
||||||
|
router isis FOO vrf RED
|
||||||
|
net 47.0023.0000.0000.0000.0000.0000.0000.1900.0004.00
|
||||||
|
metric-style wide
|
||||||
|
is-type level-2-only
|
||||||
|
|
||||||
|
|
||||||
|
@ -1244,21 +1244,24 @@ static int isis_interface_config_write(struct vty *vty)
|
|||||||
#else
|
#else
|
||||||
static int isis_interface_config_write(struct vty *vty)
|
static int isis_interface_config_write(struct vty *vty)
|
||||||
{
|
{
|
||||||
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
|
struct vrf *vrf = NULL;
|
||||||
int write = 0;
|
int write = 0;
|
||||||
struct interface *ifp;
|
|
||||||
struct lyd_node *dnode;
|
|
||||||
|
|
||||||
FOR_ALL_INTERFACES (vrf, ifp) {
|
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
|
||||||
dnode = yang_dnode_get(
|
struct interface *ifp;
|
||||||
running_config->dnode,
|
|
||||||
"/frr-interface:lib/interface[name='%s'][vrf='%s']",
|
|
||||||
ifp->name, vrf->name);
|
|
||||||
if (dnode == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
write++;
|
FOR_ALL_INTERFACES (vrf, ifp) {
|
||||||
nb_cli_show_dnode_cmds(vty, dnode, false);
|
struct lyd_node *dnode;
|
||||||
|
dnode = yang_dnode_get(
|
||||||
|
running_config->dnode,
|
||||||
|
"/frr-interface:lib/interface[name='%s'][vrf='%s']",
|
||||||
|
ifp->name, vrf->name);
|
||||||
|
if (dnode == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
write++;
|
||||||
|
nb_cli_show_dnode_cmds(vty, dnode, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return write;
|
return write;
|
||||||
}
|
}
|
||||||
@ -1268,6 +1271,7 @@ struct isis_circuit *isis_circuit_create(struct isis_area *area,
|
|||||||
struct interface *ifp)
|
struct interface *ifp)
|
||||||
{
|
{
|
||||||
struct isis_circuit *circuit = circuit_scan_by_ifp(ifp);
|
struct isis_circuit *circuit = circuit_scan_by_ifp(ifp);
|
||||||
|
|
||||||
if (circuit && circuit->area)
|
if (circuit && circuit->area)
|
||||||
return NULL;
|
return NULL;
|
||||||
circuit = isis_csm_state_change(ISIS_ENABLE, circuit, area);
|
circuit = isis_csm_state_change(ISIS_ENABLE, circuit, area);
|
||||||
@ -1446,7 +1450,7 @@ int isis_if_delete_hook(struct interface *ifp)
|
|||||||
/* Clean up the circuit data */
|
/* Clean up the circuit data */
|
||||||
if (ifp && ifp->info) {
|
if (ifp && ifp->info) {
|
||||||
circuit = ifp->info;
|
circuit = ifp->info;
|
||||||
isis_csm_state_change(IF_DOWN_FROM_Z, circuit, circuit->area);
|
isis_csm_state_change(IF_DOWN_FROM_Z, circuit, ifp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1454,10 +1458,15 @@ int isis_if_delete_hook(struct interface *ifp)
|
|||||||
|
|
||||||
static int isis_ifp_create(struct interface *ifp)
|
static int isis_ifp_create(struct interface *ifp)
|
||||||
{
|
{
|
||||||
if (if_is_operative(ifp))
|
struct vrf *vrf = NULL;
|
||||||
|
|
||||||
|
if (if_is_operative(ifp)) {
|
||||||
|
vrf = vrf_lookup_by_id(ifp->vrf_id);
|
||||||
|
if (vrf)
|
||||||
|
isis_global_instance_create(vrf->name);
|
||||||
isis_csm_state_change(IF_UP_FROM_Z, circuit_scan_by_ifp(ifp),
|
isis_csm_state_change(IF_UP_FROM_Z, circuit_scan_by_ifp(ifp),
|
||||||
ifp);
|
ifp);
|
||||||
|
}
|
||||||
hook_call(isis_if_new_hook, ifp);
|
hook_call(isis_if_new_hook, ifp);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
160
isisd/isis_cli.c
160
isisd/isis_cli.c
@ -46,16 +46,21 @@
|
|||||||
/*
|
/*
|
||||||
* XPath: /frr-isisd:isis/instance
|
* XPath: /frr-isisd:isis/instance
|
||||||
*/
|
*/
|
||||||
DEFPY_YANG_NOSH(router_isis, router_isis_cmd, "router isis WORD$tag",
|
DEFPY_YANG_NOSH(router_isis, router_isis_cmd,
|
||||||
ROUTER_STR
|
"router isis WORD$tag [vrf NAME$vrf_name]",
|
||||||
"ISO IS-IS\n"
|
ROUTER_STR
|
||||||
"ISO Routing area tag\n")
|
"ISO IS-IS\n"
|
||||||
|
"ISO Routing area tag\n" VRF_CMD_HELP_STR)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
char base_xpath[XPATH_MAXLEN];
|
char base_xpath[XPATH_MAXLEN];
|
||||||
|
|
||||||
|
if (!vrf_name)
|
||||||
|
vrf_name = VRF_DEFAULT_NAME;
|
||||||
|
|
||||||
snprintf(base_xpath, XPATH_MAXLEN,
|
snprintf(base_xpath, XPATH_MAXLEN,
|
||||||
"/frr-isisd:isis/instance[area-tag='%s']", tag);
|
"/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']", tag,
|
||||||
|
vrf_name);
|
||||||
nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
|
nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
|
||||||
/* default value in yang for is-type is level-1, but in FRR
|
/* default value in yang for is-type is level-1, but in FRR
|
||||||
* the first instance is assigned is-type level-1-2. We
|
* the first instance is assigned is-type level-1-2. We
|
||||||
@ -77,25 +82,30 @@ DEFPY_YANG_NOSH(router_isis, router_isis_cmd, "router isis WORD$tag",
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFPY_YANG(no_router_isis, no_router_isis_cmd, "no router isis WORD$tag",
|
DEFPY_YANG(no_router_isis, no_router_isis_cmd,
|
||||||
NO_STR ROUTER_STR
|
"no router isis WORD$tag [vrf NAME$vrf_name]",
|
||||||
"ISO IS-IS\n"
|
NO_STR ROUTER_STR
|
||||||
"ISO Routing area tag\n")
|
"ISO IS-IS\n"
|
||||||
|
"ISO Routing area tag\n" VRF_CMD_HELP_STR)
|
||||||
{
|
{
|
||||||
char temp_xpath[XPATH_MAXLEN];
|
char temp_xpath[XPATH_MAXLEN];
|
||||||
struct listnode *node, *nnode;
|
struct listnode *node, *nnode;
|
||||||
struct isis_circuit *circuit = NULL;
|
struct isis_circuit *circuit = NULL;
|
||||||
struct isis_area *area = NULL;
|
struct isis_area *area = NULL;
|
||||||
|
|
||||||
if (!yang_dnode_exists(vty->candidate_config->dnode,
|
if (!vrf_name)
|
||||||
"/frr-isisd:isis/instance[area-tag='%s']",
|
vrf_name = VRF_DEFAULT_NAME;
|
||||||
tag)) {
|
|
||||||
|
if (!yang_dnode_exists(
|
||||||
|
vty->candidate_config->dnode,
|
||||||
|
"/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']", tag,
|
||||||
|
vrf_name)) {
|
||||||
vty_out(vty, "ISIS area %s not found.\n", tag);
|
vty_out(vty, "ISIS area %s not found.\n", tag);
|
||||||
return CMD_ERR_NOTHING_TODO;
|
return CMD_ERR_NOTHING_TODO;
|
||||||
}
|
}
|
||||||
|
|
||||||
nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
|
nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
|
||||||
area = isis_area_lookup(tag, VRF_DEFAULT);
|
area = isis_area_lookup_by_vrf(tag, vrf_name);
|
||||||
if (area && area->circuit_list && listcount(area->circuit_list)) {
|
if (area && area->circuit_list && listcount(area->circuit_list)) {
|
||||||
for (ALL_LIST_ELEMENTS(area->circuit_list, node, nnode,
|
for (ALL_LIST_ELEMENTS(area->circuit_list, node, nnode,
|
||||||
circuit)) {
|
circuit)) {
|
||||||
@ -114,15 +124,23 @@ DEFPY_YANG(no_router_isis, no_router_isis_cmd, "no router isis WORD$tag",
|
|||||||
}
|
}
|
||||||
|
|
||||||
return nb_cli_apply_changes(
|
return nb_cli_apply_changes(
|
||||||
vty, "/frr-isisd:isis/instance[area-tag='%s']", tag);
|
vty, "/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']", tag,
|
||||||
|
vrf_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cli_show_router_isis(struct vty *vty, struct lyd_node *dnode,
|
void cli_show_router_isis(struct vty *vty, struct lyd_node *dnode,
|
||||||
bool show_defaults)
|
bool show_defaults)
|
||||||
{
|
{
|
||||||
|
const char *vrf = NULL;
|
||||||
|
|
||||||
|
vrf = yang_dnode_get_string(dnode, "./vrf");
|
||||||
|
|
||||||
vty_out(vty, "!\n");
|
vty_out(vty, "!\n");
|
||||||
vty_out(vty, "router isis %s\n",
|
vty_out(vty, "router isis %s ",
|
||||||
yang_dnode_get_string(dnode, "./area-tag"));
|
yang_dnode_get_string(dnode, "./area-tag"));
|
||||||
|
if (!strmatch(vrf, VRF_DEFAULT_NAME))
|
||||||
|
vty_out(vty, "vrf %s", yang_dnode_get_string(dnode, "./vrf"));
|
||||||
|
vty_out(vty, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -131,16 +149,18 @@ void cli_show_router_isis(struct vty *vty, struct lyd_node *dnode,
|
|||||||
* XPath: /frr-interface:lib/interface/frr-isisd:isis/ipv6-routing
|
* XPath: /frr-interface:lib/interface/frr-isisd:isis/ipv6-routing
|
||||||
* XPath: /frr-isisd:isis/instance
|
* XPath: /frr-isisd:isis/instance
|
||||||
*/
|
*/
|
||||||
DEFPY_YANG(ip_router_isis, ip_router_isis_cmd, "ip router isis WORD$tag",
|
DEFPY_YANG(ip_router_isis, ip_router_isis_cmd,
|
||||||
"Interface Internet Protocol config commands\n"
|
"ip router isis WORD$tag [vrf NAME$vrf_name]",
|
||||||
"IP router interface commands\n"
|
"Interface Internet Protocol config commands\n"
|
||||||
"IS-IS routing protocol\n"
|
"IP router interface commands\n"
|
||||||
"Routing process tag\n")
|
"IS-IS routing protocol\n"
|
||||||
|
"Routing process tag\n" VRF_CMD_HELP_STR)
|
||||||
{
|
{
|
||||||
char temp_xpath[XPATH_MAXLEN];
|
char temp_xpath[XPATH_MAXLEN];
|
||||||
const char *circ_type;
|
const char *circ_type;
|
||||||
struct isis_area *area = NULL;
|
struct isis_area *area = NULL;
|
||||||
struct interface *ifp;
|
struct interface *ifp;
|
||||||
|
struct vrf *vrf;
|
||||||
|
|
||||||
/* area will be created if it is not present. make sure the yang model
|
/* area will be created if it is not present. make sure the yang model
|
||||||
* is synced with FRR and call the appropriate NB cb.
|
* is synced with FRR and call the appropriate NB cb.
|
||||||
@ -150,16 +170,26 @@ DEFPY_YANG(ip_router_isis, ip_router_isis_cmd, "ip router isis WORD$tag",
|
|||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
|
ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
|
||||||
if (ifp)
|
|
||||||
area = isis_area_lookup(tag, ifp->vrf_id);
|
|
||||||
|
|
||||||
|
if (!vrf_name && ifp->vrf_id == VRF_DEFAULT)
|
||||||
|
vrf_name = VRF_DEFAULT_NAME;
|
||||||
|
|
||||||
|
if (ifp->vrf_id != VRF_DEFAULT) {
|
||||||
|
vrf = vrf_lookup_by_id(ifp->vrf_id);
|
||||||
|
if (vrf && !vrf_name)
|
||||||
|
vrf_name = vrf->name;
|
||||||
|
}
|
||||||
|
area = isis_area_lookup_by_vrf(tag, vrf_name);
|
||||||
if (!area) {
|
if (!area) {
|
||||||
|
isis_global_instance_create(vrf_name);
|
||||||
snprintf(temp_xpath, XPATH_MAXLEN,
|
snprintf(temp_xpath, XPATH_MAXLEN,
|
||||||
"/frr-isisd:isis/instance[area-tag='%s']", tag);
|
"/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']",
|
||||||
|
tag, vrf_name);
|
||||||
nb_cli_enqueue_change(vty, temp_xpath, NB_OP_CREATE, tag);
|
nb_cli_enqueue_change(vty, temp_xpath, NB_OP_CREATE, tag);
|
||||||
snprintf(temp_xpath, XPATH_MAXLEN,
|
snprintf(
|
||||||
"/frr-isisd:isis/instance[area-tag='%s']/is-type",
|
temp_xpath, XPATH_MAXLEN,
|
||||||
tag);
|
"/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']/is-type",
|
||||||
|
tag, vrf_name);
|
||||||
nb_cli_enqueue_change(vty, temp_xpath, NB_OP_MODIFY,
|
nb_cli_enqueue_change(vty, temp_xpath, NB_OP_MODIFY,
|
||||||
listcount(im->isis) == 0 ? "level-1-2"
|
listcount(im->isis) == 0 ? "level-1-2"
|
||||||
: NULL);
|
: NULL);
|
||||||
@ -167,6 +197,9 @@ DEFPY_YANG(ip_router_isis, ip_router_isis_cmd, "ip router isis WORD$tag",
|
|||||||
NULL);
|
NULL);
|
||||||
nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag",
|
nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag",
|
||||||
NB_OP_MODIFY, tag);
|
NB_OP_MODIFY, tag);
|
||||||
|
|
||||||
|
nb_cli_enqueue_change(vty, "./frr-isisd:isis/vrf", NB_OP_MODIFY,
|
||||||
|
vrf_name);
|
||||||
nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv4-routing",
|
nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv4-routing",
|
||||||
NB_OP_MODIFY, "true");
|
NB_OP_MODIFY, "true");
|
||||||
nb_cli_enqueue_change(
|
nb_cli_enqueue_change(
|
||||||
@ -192,6 +225,9 @@ DEFPY_YANG(ip_router_isis, ip_router_isis_cmd, "ip router isis WORD$tag",
|
|||||||
NULL);
|
NULL);
|
||||||
nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag",
|
nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag",
|
||||||
NB_OP_MODIFY, tag);
|
NB_OP_MODIFY, tag);
|
||||||
|
nb_cli_enqueue_change(vty, "./frr-isisd:isis/vrf", NB_OP_MODIFY,
|
||||||
|
vrf_name);
|
||||||
|
|
||||||
nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv4-routing",
|
nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv4-routing",
|
||||||
NB_OP_MODIFY, "true");
|
NB_OP_MODIFY, "true");
|
||||||
nb_cli_enqueue_change(vty, "./frr-isisd:isis/circuit-type",
|
nb_cli_enqueue_change(vty, "./frr-isisd:isis/circuit-type",
|
||||||
@ -206,16 +242,18 @@ DEFPY_YANG(ip_router_isis, ip_router_isis_cmd, "ip router isis WORD$tag",
|
|||||||
return nb_cli_apply_changes(vty, NULL);
|
return nb_cli_apply_changes(vty, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFPY_YANG(ip6_router_isis, ip6_router_isis_cmd, "ipv6 router isis WORD$tag",
|
DEFPY_YANG(ip6_router_isis, ip6_router_isis_cmd,
|
||||||
"Interface Internet Protocol config commands\n"
|
"ipv6 router isis WORD$tag [vrf NAME$vrf_name]",
|
||||||
"IP router interface commands\n"
|
"Interface Internet Protocol config commands\n"
|
||||||
"IS-IS routing protocol\n"
|
"IP router interface commands\n"
|
||||||
"Routing process tag\n")
|
"IS-IS routing protocol\n"
|
||||||
|
"Routing process tag\n" VRF_CMD_HELP_STR)
|
||||||
{
|
{
|
||||||
char temp_xpath[XPATH_MAXLEN];
|
char temp_xpath[XPATH_MAXLEN];
|
||||||
const char *circ_type;
|
const char *circ_type;
|
||||||
struct isis_area *area = NULL;
|
|
||||||
struct interface *ifp;
|
struct interface *ifp;
|
||||||
|
struct isis_area *area;
|
||||||
|
struct vrf *vrf;
|
||||||
|
|
||||||
/* area will be created if it is not present. make sure the yang model
|
/* area will be created if it is not present. make sure the yang model
|
||||||
* is synced with FRR and call the appropriate NB cb.
|
* is synced with FRR and call the appropriate NB cb.
|
||||||
@ -225,16 +263,25 @@ DEFPY_YANG(ip6_router_isis, ip6_router_isis_cmd, "ipv6 router isis WORD$tag",
|
|||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
|
|
||||||
ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
|
ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
|
||||||
if (ifp)
|
if (!vrf_name && ifp->vrf_id == VRF_DEFAULT)
|
||||||
area = isis_area_lookup(tag, ifp->vrf_id);
|
vrf_name = VRF_DEFAULT_NAME;
|
||||||
|
|
||||||
|
if (ifp->vrf_id != VRF_DEFAULT) {
|
||||||
|
vrf = vrf_lookup_by_id(ifp->vrf_id);
|
||||||
|
if (vrf && !vrf_name)
|
||||||
|
vrf_name = vrf->name;
|
||||||
|
}
|
||||||
|
area = isis_area_lookup_by_vrf(tag, vrf_name);
|
||||||
if (!area) {
|
if (!area) {
|
||||||
|
isis_global_instance_create(vrf_name);
|
||||||
snprintf(temp_xpath, XPATH_MAXLEN,
|
snprintf(temp_xpath, XPATH_MAXLEN,
|
||||||
"/frr-isisd:isis/instance[area-tag='%s']", tag);
|
"/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']",
|
||||||
|
tag, vrf_name);
|
||||||
nb_cli_enqueue_change(vty, temp_xpath, NB_OP_CREATE, tag);
|
nb_cli_enqueue_change(vty, temp_xpath, NB_OP_CREATE, tag);
|
||||||
snprintf(temp_xpath, XPATH_MAXLEN,
|
snprintf(
|
||||||
"/frr-isisd:isis/instance[area-tag='%s']/is-type",
|
temp_xpath, XPATH_MAXLEN,
|
||||||
tag);
|
"/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']/is-type",
|
||||||
|
tag, vrf_name);
|
||||||
nb_cli_enqueue_change(vty, temp_xpath, NB_OP_MODIFY,
|
nb_cli_enqueue_change(vty, temp_xpath, NB_OP_MODIFY,
|
||||||
listcount(im->isis) == 0 ? "level-1-2"
|
listcount(im->isis) == 0 ? "level-1-2"
|
||||||
: NULL);
|
: NULL);
|
||||||
@ -242,6 +289,9 @@ DEFPY_YANG(ip6_router_isis, ip6_router_isis_cmd, "ipv6 router isis WORD$tag",
|
|||||||
NULL);
|
NULL);
|
||||||
nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag",
|
nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag",
|
||||||
NB_OP_MODIFY, tag);
|
NB_OP_MODIFY, tag);
|
||||||
|
nb_cli_enqueue_change(vty, "./frr-isisd:isis/vrf", NB_OP_MODIFY,
|
||||||
|
vrf_name);
|
||||||
|
|
||||||
nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv6-routing",
|
nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv6-routing",
|
||||||
NB_OP_MODIFY, "true");
|
NB_OP_MODIFY, "true");
|
||||||
nb_cli_enqueue_change(
|
nb_cli_enqueue_change(
|
||||||
@ -267,6 +317,8 @@ DEFPY_YANG(ip6_router_isis, ip6_router_isis_cmd, "ipv6 router isis WORD$tag",
|
|||||||
NULL);
|
NULL);
|
||||||
nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag",
|
nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag",
|
||||||
NB_OP_MODIFY, tag);
|
NB_OP_MODIFY, tag);
|
||||||
|
nb_cli_enqueue_change(vty, "./frr-isisd:isis/vrf", NB_OP_MODIFY,
|
||||||
|
vrf_name);
|
||||||
nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv6-routing",
|
nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv6-routing",
|
||||||
NB_OP_MODIFY, "true");
|
NB_OP_MODIFY, "true");
|
||||||
nb_cli_enqueue_change(vty, "./frr-isisd:isis/circuit-type",
|
nb_cli_enqueue_change(vty, "./frr-isisd:isis/circuit-type",
|
||||||
@ -282,13 +334,13 @@ DEFPY_YANG(ip6_router_isis, ip6_router_isis_cmd, "ipv6 router isis WORD$tag",
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEFPY_YANG(no_ip_router_isis, no_ip_router_isis_cmd,
|
DEFPY_YANG(no_ip_router_isis, no_ip_router_isis_cmd,
|
||||||
"no <ip|ipv6>$ip router isis [WORD]$tag",
|
"no <ip|ipv6>$ip router isis [WORD]$tag [vrf NAME$vrf_name]",
|
||||||
NO_STR
|
NO_STR
|
||||||
"Interface Internet Protocol config commands\n"
|
"Interface Internet Protocol config commands\n"
|
||||||
"IP router interface commands\n"
|
"IP router interface commands\n"
|
||||||
"IP router interface commands\n"
|
"IP router interface commands\n"
|
||||||
"IS-IS routing protocol\n"
|
"IS-IS routing protocol\n"
|
||||||
"Routing process tag\n")
|
"Routing process tag\n")
|
||||||
{
|
{
|
||||||
const struct lyd_node *dnode;
|
const struct lyd_node *dnode;
|
||||||
|
|
||||||
@ -324,19 +376,33 @@ DEFPY_YANG(no_ip_router_isis, no_ip_router_isis_cmd,
|
|||||||
void cli_show_ip_isis_ipv4(struct vty *vty, struct lyd_node *dnode,
|
void cli_show_ip_isis_ipv4(struct vty *vty, struct lyd_node *dnode,
|
||||||
bool show_defaults)
|
bool show_defaults)
|
||||||
{
|
{
|
||||||
|
const char *vrf;
|
||||||
|
|
||||||
|
vrf = yang_dnode_get_string(dnode, "../vrf");
|
||||||
|
|
||||||
if (!yang_dnode_get_bool(dnode, NULL))
|
if (!yang_dnode_get_bool(dnode, NULL))
|
||||||
vty_out(vty, " no");
|
vty_out(vty, " no");
|
||||||
vty_out(vty, " ip router isis %s\n",
|
vty_out(vty, " ip router isis %s ",
|
||||||
yang_dnode_get_string(dnode, "../area-tag"));
|
yang_dnode_get_string(dnode, "../area-tag"));
|
||||||
|
if (!strmatch(vrf, VRF_DEFAULT_NAME))
|
||||||
|
vty_out(vty, "vrf %s", vrf);
|
||||||
|
vty_out(vty, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void cli_show_ip_isis_ipv6(struct vty *vty, struct lyd_node *dnode,
|
void cli_show_ip_isis_ipv6(struct vty *vty, struct lyd_node *dnode,
|
||||||
bool show_defaults)
|
bool show_defaults)
|
||||||
{
|
{
|
||||||
|
const char *vrf;
|
||||||
|
|
||||||
|
vrf = yang_dnode_get_string(dnode, "../vrf");
|
||||||
|
|
||||||
if (!yang_dnode_get_bool(dnode, NULL))
|
if (!yang_dnode_get_bool(dnode, NULL))
|
||||||
vty_out(vty, " no");
|
vty_out(vty, " no");
|
||||||
vty_out(vty, " ipv6 router isis %s\n",
|
vty_out(vty, " ipv6 router isis %s ",
|
||||||
yang_dnode_get_string(dnode, "../area-tag"));
|
yang_dnode_get_string(dnode, "../area-tag"));
|
||||||
|
if (!strmatch(vrf, VRF_DEFAULT_NAME))
|
||||||
|
vty_out(vty, "vrf %s", vrf);
|
||||||
|
vty_out(vty, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -236,13 +236,12 @@ int main(int argc, char **argv, char **envp)
|
|||||||
/* thread master */
|
/* thread master */
|
||||||
isis_master_init(frr_init());
|
isis_master_init(frr_init());
|
||||||
master = im->master;
|
master = im->master;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* initializations
|
* initializations
|
||||||
*/
|
*/
|
||||||
isis_error_init();
|
isis_error_init();
|
||||||
access_list_init();
|
access_list_init();
|
||||||
vrf_init(NULL, NULL, NULL, NULL, NULL);
|
isis_vrf_init();
|
||||||
prefix_list_init();
|
prefix_list_init();
|
||||||
isis_init();
|
isis_init();
|
||||||
isis_circuit_init();
|
isis_circuit_init();
|
||||||
@ -261,7 +260,7 @@ int main(int argc, char **argv, char **envp)
|
|||||||
mt_init();
|
mt_init();
|
||||||
|
|
||||||
/* create the global 'isis' instance */
|
/* create the global 'isis' instance */
|
||||||
isis_global_instance_create();
|
isis_global_instance_create(VRF_DEFAULT_NAME);
|
||||||
|
|
||||||
isis_zebra_init(master, instance);
|
isis_zebra_init(master, instance);
|
||||||
isis_bfd_init();
|
isis_bfd_init();
|
||||||
|
@ -550,6 +550,13 @@ const struct frr_yang_module_info frr_isisd_info = {
|
|||||||
.modify = lib_interface_isis_area_tag_modify,
|
.modify = lib_interface_isis_area_tag_modify,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.xpath = "/frr-interface:lib/interface/frr-isisd:isis/vrf",
|
||||||
|
.cbs = {
|
||||||
|
.modify = lib_interface_isis_vrf_modify,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
.xpath = "/frr-interface:lib/interface/frr-isisd:isis/circuit-type",
|
.xpath = "/frr-interface:lib/interface/frr-isisd:isis/circuit-type",
|
||||||
.cbs = {
|
.cbs = {
|
||||||
|
@ -168,6 +168,7 @@ int isis_instance_mpls_te_router_address_destroy(
|
|||||||
int lib_interface_isis_create(struct nb_cb_create_args *args);
|
int lib_interface_isis_create(struct nb_cb_create_args *args);
|
||||||
int lib_interface_isis_destroy(struct nb_cb_destroy_args *args);
|
int lib_interface_isis_destroy(struct nb_cb_destroy_args *args);
|
||||||
int lib_interface_isis_area_tag_modify(struct nb_cb_modify_args *args);
|
int lib_interface_isis_area_tag_modify(struct nb_cb_modify_args *args);
|
||||||
|
int lib_interface_isis_vrf_modify(struct nb_cb_modify_args *args);
|
||||||
int lib_interface_isis_ipv4_routing_modify(struct nb_cb_modify_args *args);
|
int lib_interface_isis_ipv4_routing_modify(struct nb_cb_modify_args *args);
|
||||||
int lib_interface_isis_ipv6_routing_modify(struct nb_cb_modify_args *args);
|
int lib_interface_isis_ipv6_routing_modify(struct nb_cb_modify_args *args);
|
||||||
int lib_interface_isis_circuit_type_modify(struct nb_cb_modify_args *args);
|
int lib_interface_isis_circuit_type_modify(struct nb_cb_modify_args *args);
|
||||||
|
@ -53,16 +53,19 @@ int isis_instance_create(struct nb_cb_create_args *args)
|
|||||||
{
|
{
|
||||||
struct isis_area *area;
|
struct isis_area *area;
|
||||||
const char *area_tag;
|
const char *area_tag;
|
||||||
|
const char *vrf_name;
|
||||||
|
|
||||||
if (args->event != NB_EV_APPLY)
|
if (args->event != NB_EV_APPLY)
|
||||||
return NB_OK;
|
return NB_OK;
|
||||||
|
vrf_name = yang_dnode_get_string(args->dnode, "./vrf");
|
||||||
area_tag = yang_dnode_get_string(args->dnode, "./area-tag");
|
area_tag = yang_dnode_get_string(args->dnode, "./area-tag");
|
||||||
area = isis_area_lookup(area_tag, VRF_DEFAULT);
|
isis_global_instance_create(vrf_name);
|
||||||
|
area = isis_area_lookup_by_vrf(area_tag, vrf_name);
|
||||||
if (area)
|
if (area)
|
||||||
return NB_ERR_INCONSISTENCY;
|
return NB_ERR_INCONSISTENCY;
|
||||||
|
|
||||||
area = isis_area_create(area_tag, VRF_DEFAULT_NAME);
|
area = isis_area_create(area_tag, vrf_name);
|
||||||
|
|
||||||
/* save area in dnode to avoid looking it up all the time */
|
/* save area in dnode to avoid looking it up all the time */
|
||||||
nb_running_set_entry(args->dnode, area);
|
nb_running_set_entry(args->dnode, area);
|
||||||
|
|
||||||
@ -75,7 +78,6 @@ int isis_instance_destroy(struct nb_cb_destroy_args *args)
|
|||||||
|
|
||||||
if (args->event != NB_EV_APPLY)
|
if (args->event != NB_EV_APPLY)
|
||||||
return NB_OK;
|
return NB_OK;
|
||||||
|
|
||||||
area = nb_running_unset_entry(args->dnode);
|
area = nb_running_unset_entry(args->dnode);
|
||||||
isis_area_destroy(area);
|
isis_area_destroy(area);
|
||||||
|
|
||||||
@ -116,7 +118,6 @@ int isis_instance_area_address_create(struct nb_cb_create_args *args)
|
|||||||
area = nb_running_get_entry(args->dnode, NULL, true);
|
area = nb_running_get_entry(args->dnode, NULL, true);
|
||||||
if (area == NULL)
|
if (area == NULL)
|
||||||
return NB_ERR_VALIDATION;
|
return NB_ERR_VALIDATION;
|
||||||
|
|
||||||
addr.addr_len = dotformat2buff(buff, net_title);
|
addr.addr_len = dotformat2buff(buff, net_title);
|
||||||
memcpy(addr.area_addr, buff, addr.addr_len);
|
memcpy(addr.area_addr, buff, addr.addr_len);
|
||||||
if (addr.area_addr[addr.addr_len - 1] != 0) {
|
if (addr.area_addr[addr.addr_len - 1] != 0) {
|
||||||
@ -148,6 +149,7 @@ int isis_instance_area_address_create(struct nb_cb_create_args *args)
|
|||||||
case NB_EV_APPLY:
|
case NB_EV_APPLY:
|
||||||
area = nb_running_get_entry(args->dnode, NULL, true);
|
area = nb_running_get_entry(args->dnode, NULL, true);
|
||||||
addrr = args->resource->ptr;
|
addrr = args->resource->ptr;
|
||||||
|
assert(area);
|
||||||
|
|
||||||
if (area->isis->sysid_set == 0) {
|
if (area->isis->sysid_set == 0) {
|
||||||
/*
|
/*
|
||||||
@ -1830,8 +1832,10 @@ int lib_interface_isis_create(struct nb_cb_create_args *args)
|
|||||||
{
|
{
|
||||||
struct isis_area *area = NULL;
|
struct isis_area *area = NULL;
|
||||||
struct interface *ifp;
|
struct interface *ifp;
|
||||||
struct isis_circuit *circuit;
|
struct isis_circuit *circuit = NULL;
|
||||||
|
struct vrf *vrf;
|
||||||
const char *area_tag = yang_dnode_get_string(args->dnode, "./area-tag");
|
const char *area_tag = yang_dnode_get_string(args->dnode, "./area-tag");
|
||||||
|
const char *vrf_name = yang_dnode_get_string(args->dnode, "./vrf");
|
||||||
uint32_t min_mtu, actual_mtu;
|
uint32_t min_mtu, actual_mtu;
|
||||||
|
|
||||||
switch (args->event) {
|
switch (args->event) {
|
||||||
@ -1846,8 +1850,17 @@ int lib_interface_isis_create(struct nb_cb_create_args *args)
|
|||||||
/* zebra might not know yet about the MTU - nothing we can do */
|
/* zebra might not know yet about the MTU - nothing we can do */
|
||||||
if (!ifp || ifp->mtu == 0)
|
if (!ifp || ifp->mtu == 0)
|
||||||
break;
|
break;
|
||||||
|
vrf = vrf_lookup_by_id(ifp->vrf_id);
|
||||||
|
if (ifp->vrf_id != VRF_DEFAULT && vrf
|
||||||
|
&& strcmp(vrf->name, vrf_name) != 0) {
|
||||||
|
snprintf(args->errmsg, args->errmsg_len,
|
||||||
|
"interface %s not in vrf %s\n", ifp->name,
|
||||||
|
vrf_name);
|
||||||
|
return NB_ERR_VALIDATION;
|
||||||
|
}
|
||||||
actual_mtu =
|
actual_mtu =
|
||||||
if_is_broadcast(ifp) ? ifp->mtu - LLC_LEN : ifp->mtu;
|
if_is_broadcast(ifp) ? ifp->mtu - LLC_LEN : ifp->mtu;
|
||||||
|
|
||||||
area = isis_area_lookup(area_tag, ifp->vrf_id);
|
area = isis_area_lookup(area_tag, ifp->vrf_id);
|
||||||
if (area)
|
if (area)
|
||||||
min_mtu = area->lsp_mtu;
|
min_mtu = area->lsp_mtu;
|
||||||
@ -1866,9 +1879,7 @@ int lib_interface_isis_create(struct nb_cb_create_args *args)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NB_EV_APPLY:
|
case NB_EV_APPLY:
|
||||||
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
area = isis_area_lookup_by_vrf(area_tag, vrf_name);
|
||||||
if (ifp)
|
|
||||||
area = isis_area_lookup(area_tag, ifp->vrf_id);
|
|
||||||
/* The area should have already be created. We are
|
/* The area should have already be created. We are
|
||||||
* setting the priority of the global isis area creation
|
* setting the priority of the global isis area creation
|
||||||
* slightly lower, so it should be executed first, but I
|
* slightly lower, so it should be executed first, but I
|
||||||
@ -1881,7 +1892,7 @@ int lib_interface_isis_create(struct nb_cb_create_args *args)
|
|||||||
__func__, area_tag);
|
__func__, area_tag);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
||||||
circuit = isis_circuit_create(area, ifp);
|
circuit = isis_circuit_create(area, ifp);
|
||||||
assert(circuit
|
assert(circuit
|
||||||
&& (circuit->state == C_STATE_CONF
|
&& (circuit->state == C_STATE_CONF
|
||||||
@ -1956,6 +1967,44 @@ int lib_interface_isis_area_tag_modify(struct nb_cb_modify_args *args)
|
|||||||
return NB_OK;
|
return NB_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XPath: /frr-interface:lib/interface/frr-isisd:isis/vrf
|
||||||
|
*/
|
||||||
|
int lib_interface_isis_vrf_modify(struct nb_cb_modify_args *args)
|
||||||
|
{
|
||||||
|
struct interface *ifp;
|
||||||
|
struct vrf *vrf;
|
||||||
|
const char *ifname, *vrfname, *vrf_name;
|
||||||
|
struct isis_circuit *circuit;
|
||||||
|
|
||||||
|
if (args->event == NB_EV_VALIDATE) {
|
||||||
|
/* libyang doesn't like relative paths across module boundaries
|
||||||
|
*/
|
||||||
|
ifname = yang_dnode_get_string(args->dnode->parent->parent,
|
||||||
|
"./name");
|
||||||
|
vrfname = yang_dnode_get_string(args->dnode->parent->parent,
|
||||||
|
"./vrf");
|
||||||
|
vrf = vrf_lookup_by_name(vrfname);
|
||||||
|
assert(vrf);
|
||||||
|
ifp = if_lookup_by_name(ifname, vrf->vrf_id);
|
||||||
|
|
||||||
|
if (!ifp)
|
||||||
|
return NB_OK;
|
||||||
|
|
||||||
|
vrf_name = yang_dnode_get_string(args->dnode, NULL);
|
||||||
|
circuit = circuit_scan_by_ifp(ifp);
|
||||||
|
if (circuit && circuit->area && circuit->area->isis
|
||||||
|
&& strcmp(circuit->area->isis->name, vrf_name)) {
|
||||||
|
snprintf(args->errmsg, args->errmsg_len,
|
||||||
|
"ISIS circuit is already defined on vrf %s",
|
||||||
|
circuit->area->isis->name);
|
||||||
|
return NB_ERR_VALIDATION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XPath: /frr-interface:lib/interface/frr-isisd:isis/circuit-type
|
* XPath: /frr-interface:lib/interface/frr-isisd:isis/circuit-type
|
||||||
*/
|
*/
|
||||||
|
@ -577,6 +577,20 @@ int isis_zebra_label_manager_connect(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void isis_zebra_vrf_register(struct isis *isis)
|
||||||
|
{
|
||||||
|
if (!zclient || zclient->sock < 0 || !isis)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (isis->vrf_id != VRF_UNKNOWN) {
|
||||||
|
if (IS_DEBUG_EVENTS)
|
||||||
|
zlog_debug("%s: Register VRF %s id %u", __func__,
|
||||||
|
isis->name, isis->vrf_id);
|
||||||
|
zclient_send_reg_requests(zclient, isis->vrf_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void isis_zebra_connected(struct zclient *zclient)
|
static void isis_zebra_connected(struct zclient *zclient)
|
||||||
{
|
{
|
||||||
zclient_send_reg_requests(zclient, VRF_DEFAULT);
|
zclient_send_reg_requests(zclient, VRF_DEFAULT);
|
||||||
|
@ -57,5 +57,6 @@ bool isis_zebra_label_manager_ready(void);
|
|||||||
int isis_zebra_label_manager_connect(void);
|
int isis_zebra_label_manager_connect(void);
|
||||||
int isis_zebra_request_label_range(uint32_t base, uint32_t chunk_size);
|
int isis_zebra_request_label_range(uint32_t base, uint32_t chunk_size);
|
||||||
int isis_zebra_release_label_range(uint32_t start, uint32_t end);
|
int isis_zebra_release_label_range(uint32_t start, uint32_t end);
|
||||||
|
void isis_zebra_vrf_register(struct isis *isis);
|
||||||
|
|
||||||
#endif /* _ZEBRA_ISIS_ZEBRA_H */
|
#endif /* _ZEBRA_ISIS_ZEBRA_H */
|
||||||
|
136
isisd/isisd.c
136
isisd/isisd.c
@ -35,6 +35,7 @@
|
|||||||
#include "prefix.h"
|
#include "prefix.h"
|
||||||
#include "table.h"
|
#include "table.h"
|
||||||
#include "qobj.h"
|
#include "qobj.h"
|
||||||
|
#include "zclient.h"
|
||||||
#include "vrf.h"
|
#include "vrf.h"
|
||||||
#include "spf_backoff.h"
|
#include "spf_backoff.h"
|
||||||
#include "lib/northbound_cli.h"
|
#include "lib/northbound_cli.h"
|
||||||
@ -167,29 +168,32 @@ void isis_master_init(struct thread_master *master)
|
|||||||
im->master = master;
|
im->master = master;
|
||||||
}
|
}
|
||||||
|
|
||||||
void isis_global_instance_create()
|
void isis_global_instance_create(const char *vrf_name)
|
||||||
{
|
{
|
||||||
struct isis *isis;
|
struct isis *isis;
|
||||||
|
|
||||||
isis = isis_lookup_by_vrfid(VRF_DEFAULT);
|
isis = isis_lookup_by_vrfname(vrf_name);
|
||||||
if (isis == NULL) {
|
if (isis == NULL) {
|
||||||
isis = isis_new(VRF_DEFAULT);
|
isis = isis_new(vrf_name);
|
||||||
isis_add(isis);
|
isis_add(isis);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct isis *isis_new(vrf_id_t vrf_id)
|
struct isis *isis_new(const char *vrf_name)
|
||||||
{
|
{
|
||||||
struct vrf *vrf;
|
struct vrf *vrf;
|
||||||
struct isis *isis;
|
struct isis *isis;
|
||||||
|
|
||||||
isis = XCALLOC(MTYPE_ISIS, sizeof(struct isis));
|
isis = XCALLOC(MTYPE_ISIS, sizeof(struct isis));
|
||||||
isis->vrf_id = vrf_id;
|
vrf = vrf_lookup_by_name(vrf_name);
|
||||||
vrf = vrf_lookup_by_id(vrf_id);
|
|
||||||
|
|
||||||
if (vrf) {
|
if (vrf) {
|
||||||
|
isis->vrf_id = vrf->vrf_id;
|
||||||
isis_vrf_link(isis, vrf);
|
isis_vrf_link(isis, vrf);
|
||||||
isis->name = XSTRDUP(MTYPE_ISIS, vrf->name);
|
isis->name = XSTRDUP(MTYPE_ISIS, vrf->name);
|
||||||
|
} else {
|
||||||
|
isis->vrf_id = VRF_UNKNOWN;
|
||||||
|
isis->name = XSTRDUP(MTYPE_ISIS, vrf_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_DEBUG_EVENTS)
|
if (IS_DEBUG_EVENTS)
|
||||||
@ -223,15 +227,20 @@ struct isis_area *isis_area_create(const char *area_tag, const char *vrf_name)
|
|||||||
if (vrf) {
|
if (vrf) {
|
||||||
isis = isis_lookup_by_vrfid(vrf->vrf_id);
|
isis = isis_lookup_by_vrfid(vrf->vrf_id);
|
||||||
if (isis == NULL) {
|
if (isis == NULL) {
|
||||||
isis = isis_new(vrf->vrf_id);
|
isis = isis_new(vrf_name);
|
||||||
isis_add(isis);
|
isis_add(isis);
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
return NULL;
|
isis = isis_lookup_by_vrfid(VRF_UNKNOWN);
|
||||||
|
if (isis == NULL) {
|
||||||
|
isis = isis_new(vrf_name);
|
||||||
|
isis_add(isis);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
isis = isis_lookup_by_vrfid(VRF_DEFAULT);
|
isis = isis_lookup_by_vrfid(VRF_DEFAULT);
|
||||||
if (isis == NULL) {
|
if (isis == NULL) {
|
||||||
isis = isis_new(VRF_DEFAULT);
|
isis = isis_new(VRF_DEFAULT_NAME);
|
||||||
isis_add(isis);
|
isis_add(isis);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -336,6 +345,24 @@ struct isis_area *isis_area_create(const char *area_tag, const char *vrf_name)
|
|||||||
return area;
|
return area;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct isis_area *isis_area_lookup_by_vrf(const char *area_tag,
|
||||||
|
const char *vrf_name)
|
||||||
|
{
|
||||||
|
struct isis_area *area;
|
||||||
|
struct listnode *node;
|
||||||
|
struct isis *isis = NULL;
|
||||||
|
|
||||||
|
isis = isis_lookup_by_vrfname(vrf_name);
|
||||||
|
if (isis == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area))
|
||||||
|
if (strcmp(area->area_tag, area_tag) == 0)
|
||||||
|
return area;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
struct isis_area *isis_area_lookup(const char *area_tag, vrf_id_t vrf_id)
|
struct isis_area *isis_area_lookup(const char *area_tag, vrf_id_t vrf_id)
|
||||||
{
|
{
|
||||||
struct isis_area *area;
|
struct isis_area *area;
|
||||||
@ -449,6 +476,95 @@ void isis_area_destroy(struct isis_area *area)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This is hook function for vrf create called as part of vrf_init */
|
||||||
|
static int isis_vrf_new(struct vrf *vrf)
|
||||||
|
{
|
||||||
|
if (IS_DEBUG_EVENTS)
|
||||||
|
zlog_debug("%s: VRF Created: %s(%u)", __func__, vrf->name,
|
||||||
|
vrf->vrf_id);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is hook function for vrf delete call as part of vrf_init */
|
||||||
|
static int isis_vrf_delete(struct vrf *vrf)
|
||||||
|
{
|
||||||
|
if (IS_DEBUG_EVENTS)
|
||||||
|
zlog_debug("%s: VRF Deletion: %s(%u)", __func__, vrf->name,
|
||||||
|
vrf->vrf_id);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int isis_vrf_enable(struct vrf *vrf)
|
||||||
|
{
|
||||||
|
struct isis *isis;
|
||||||
|
vrf_id_t old_vrf_id;
|
||||||
|
|
||||||
|
if (IS_DEBUG_EVENTS)
|
||||||
|
zlog_debug("%s: VRF %s id %u enabled", __func__, vrf->name,
|
||||||
|
vrf->vrf_id);
|
||||||
|
|
||||||
|
isis = isis_lookup_by_vrfname(vrf->name);
|
||||||
|
if (isis) {
|
||||||
|
if (isis->name && strmatch(vrf->name, VRF_DEFAULT_NAME)) {
|
||||||
|
XFREE(MTYPE_ISIS, isis->name);
|
||||||
|
isis->name = NULL;
|
||||||
|
}
|
||||||
|
old_vrf_id = isis->vrf_id;
|
||||||
|
/* We have instance configured, link to VRF and make it "up". */
|
||||||
|
isis_vrf_link(isis, vrf);
|
||||||
|
if (IS_DEBUG_EVENTS)
|
||||||
|
zlog_debug(
|
||||||
|
"%s: isis linked to vrf %s vrf_id %u (old id %u)",
|
||||||
|
__func__, vrf->name, isis->vrf_id, old_vrf_id);
|
||||||
|
if (old_vrf_id != isis->vrf_id) {
|
||||||
|
frr_with_privs (&isisd_privs) {
|
||||||
|
/* stop zebra redist to us for old vrf */
|
||||||
|
zclient_send_dereg_requests(zclient,
|
||||||
|
old_vrf_id);
|
||||||
|
/* start zebra redist to us for new vrf */
|
||||||
|
isis_zebra_vrf_register(isis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int isis_vrf_disable(struct vrf *vrf)
|
||||||
|
{
|
||||||
|
struct isis *isis;
|
||||||
|
vrf_id_t old_vrf_id = VRF_UNKNOWN;
|
||||||
|
|
||||||
|
if (vrf->vrf_id == VRF_DEFAULT)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (IS_DEBUG_EVENTS)
|
||||||
|
zlog_debug("%s: VRF %s id %d disabled.", __func__, vrf->name,
|
||||||
|
vrf->vrf_id);
|
||||||
|
isis = isis_lookup_by_vrfname(vrf->name);
|
||||||
|
if (isis) {
|
||||||
|
old_vrf_id = isis->vrf_id;
|
||||||
|
|
||||||
|
/* We have instance configured, unlink
|
||||||
|
* from VRF and make it "down".
|
||||||
|
*/
|
||||||
|
isis_vrf_unlink(isis, vrf);
|
||||||
|
if (IS_DEBUG_EVENTS)
|
||||||
|
zlog_debug("%s: isis old_vrf_id %d unlinked", __func__,
|
||||||
|
old_vrf_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void isis_vrf_init(void)
|
||||||
|
{
|
||||||
|
vrf_init(isis_vrf_new, isis_vrf_enable, isis_vrf_disable,
|
||||||
|
isis_vrf_delete, isis_vrf_enable);
|
||||||
|
}
|
||||||
|
|
||||||
void isis_finish(struct isis *isis)
|
void isis_finish(struct isis *isis)
|
||||||
{
|
{
|
||||||
struct vrf *vrf = NULL;
|
struct vrf *vrf = NULL;
|
||||||
|
@ -73,7 +73,6 @@ struct isis_master {
|
|||||||
struct list *isis;
|
struct list *isis;
|
||||||
/* ISIS thread master. */
|
/* ISIS thread master. */
|
||||||
struct thread_master *master;
|
struct thread_master *master;
|
||||||
/* Various OSPF global configuration. */
|
|
||||||
uint8_t options;
|
uint8_t options;
|
||||||
};
|
};
|
||||||
#define F_ISIS_UNIT_TEST 0x01
|
#define F_ISIS_UNIT_TEST 0x01
|
||||||
@ -213,15 +212,19 @@ void isis_finish(struct isis *isis);
|
|||||||
void isis_master_init(struct thread_master *master);
|
void isis_master_init(struct thread_master *master);
|
||||||
void isis_vrf_link(struct isis *isis, struct vrf *vrf);
|
void isis_vrf_link(struct isis *isis, struct vrf *vrf);
|
||||||
void isis_vrf_unlink(struct isis *isis, struct vrf *vrf);
|
void isis_vrf_unlink(struct isis *isis, struct vrf *vrf);
|
||||||
void isis_global_instance_create(void);
|
void isis_global_instance_create(const char *vrf_name);
|
||||||
struct isis *isis_lookup_by_vrfid(vrf_id_t vrf_id);
|
struct isis *isis_lookup_by_vrfid(vrf_id_t vrf_id);
|
||||||
struct isis *isis_lookup_by_vrfname(const char *vrfname);
|
struct isis *isis_lookup_by_vrfname(const char *vrfname);
|
||||||
struct isis *isis_lookup_by_sysid(const uint8_t *sysid);
|
struct isis *isis_lookup_by_sysid(const uint8_t *sysid);
|
||||||
|
|
||||||
void isis_init(void);
|
void isis_init(void);
|
||||||
struct isis *isis_new(vrf_id_t vrf_id);
|
void isis_vrf_init(void);
|
||||||
|
|
||||||
|
struct isis *isis_new(const char *vrf_name);
|
||||||
struct isis_area *isis_area_create(const char *, const char *);
|
struct isis_area *isis_area_create(const char *, const char *);
|
||||||
struct isis_area *isis_area_lookup(const char *, vrf_id_t vrf_id);
|
struct isis_area *isis_area_lookup(const char *, vrf_id_t vrf_id);
|
||||||
|
struct isis_area *isis_area_lookup_by_vrf(const char *area_tag,
|
||||||
|
const char *vrf_name);
|
||||||
int isis_area_get(struct vty *vty, const char *area_tag);
|
int isis_area_get(struct vty *vty, const char *area_tag);
|
||||||
void isis_area_destroy(struct isis_area *area);
|
void isis_area_destroy(struct isis_area *area);
|
||||||
void print_debug(struct vty *, int, int);
|
void print_debug(struct vty *, int, int);
|
||||||
|
@ -291,7 +291,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
/* IS-IS inits. */
|
/* IS-IS inits. */
|
||||||
yang_module_load("frr-isisd");
|
yang_module_load("frr-isisd");
|
||||||
isis = isis_new(VRF_DEFAULT);
|
isis = isis_new(VRF_DEFAULT_NAME);
|
||||||
listnode_add(im->isis, isis);
|
listnode_add(im->isis, isis);
|
||||||
SET_FLAG(im->options, F_ISIS_UNIT_TEST);
|
SET_FLAG(im->options, F_ISIS_UNIT_TEST);
|
||||||
debug_spf_events |= DEBUG_SPF_EVENTS;
|
debug_spf_events |= DEBUG_SPF_EVENTS;
|
||||||
|
0
tests/topotests/isis-topo1-vrf/__init__.py
Normal file
0
tests/topotests/isis-topo1-vrf/__init__.py
Normal file
15
tests/topotests/isis-topo1-vrf/r1/isisd.conf
Executable file
15
tests/topotests/isis-topo1-vrf/r1/isisd.conf
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
hostname r1
|
||||||
|
debug isis adj-packets
|
||||||
|
debug isis events
|
||||||
|
debug isis update-packets
|
||||||
|
interface r1-eth0
|
||||||
|
ip router isis 1 vrf r1-cust1
|
||||||
|
ipv6 router isis 1 vrf r1-cust1
|
||||||
|
isis circuit-type level-2-only
|
||||||
|
!
|
||||||
|
router isis 1 vrf r1-cust1
|
||||||
|
net 10.0000.0000.0000.0000.0000.0000.0000.0000.0000.00
|
||||||
|
metric-style wide
|
||||||
|
redistribute ipv4 connected level-2
|
||||||
|
redistribute ipv6 connected level-2
|
||||||
|
!
|
57
tests/topotests/isis-topo1-vrf/r1/r1_route.json
Normal file
57
tests/topotests/isis-topo1-vrf/r1/r1_route.json
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
{
|
||||||
|
"10.0.10.0/24": [
|
||||||
|
{
|
||||||
|
"distance": 115,
|
||||||
|
"metric": 20,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"afi": "ipv4",
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 2,
|
||||||
|
"interfaceName": "r1-eth0",
|
||||||
|
"ip": "10.0.20.1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "10.0.10.0/24",
|
||||||
|
"protocol": "isis",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 3,
|
||||||
|
"vrfName": "r1-cust1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"10.0.20.0/24": [
|
||||||
|
{
|
||||||
|
"distance": 115,
|
||||||
|
"metric": 20,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"afi": "ipv4",
|
||||||
|
"interfaceIndex": 2,
|
||||||
|
"interfaceName": "r1-eth0",
|
||||||
|
"ip": "10.0.20.1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "10.0.20.0/24",
|
||||||
|
"protocol": "isis",
|
||||||
|
"vrfId": 3,
|
||||||
|
"vrfName": "r1-cust1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"directlyConnected": true,
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 2,
|
||||||
|
"interfaceName": "r1-eth0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "10.0.20.0/24",
|
||||||
|
"protocol": "connected",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 3,
|
||||||
|
"vrfName": "r1-cust1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
40
tests/topotests/isis-topo1-vrf/r1/r1_route6.json
Normal file
40
tests/topotests/isis-topo1-vrf/r1/r1_route6.json
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"2001:db8:1:1::/64": [
|
||||||
|
{
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"directlyConnected": true,
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 2,
|
||||||
|
"interfaceName": "r1-eth0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "2001:db8:1:1::/64",
|
||||||
|
"protocol": "connected",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 3,
|
||||||
|
"vrfName": "r1-cust1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"2001:db8:2:1::/64": [
|
||||||
|
{
|
||||||
|
"distance": 115,
|
||||||
|
"metric": 20,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"afi": "ipv6",
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 2,
|
||||||
|
"interfaceName": "r1-eth0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "2001:db8:2:1::/64",
|
||||||
|
"protocol": "isis",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 3,
|
||||||
|
"vrfName": "r1-cust1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
14
tests/topotests/isis-topo1-vrf/r1/r1_route6_linux.json
Executable file
14
tests/topotests/isis-topo1-vrf/r1/r1_route6_linux.json
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"2001:db8:1:1::/64": {
|
||||||
|
"dev": "r1-eth0",
|
||||||
|
"metric": "256",
|
||||||
|
"pref": "medium",
|
||||||
|
"proto": "kernel"
|
||||||
|
},
|
||||||
|
"2001:db8:2:1::/64": {
|
||||||
|
"dev": "r1-eth0",
|
||||||
|
"metric": "20",
|
||||||
|
"pref": "medium",
|
||||||
|
"proto": "187"
|
||||||
|
}
|
||||||
|
}
|
13
tests/topotests/isis-topo1-vrf/r1/r1_route_linux.json
Executable file
13
tests/topotests/isis-topo1-vrf/r1/r1_route_linux.json
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"10.0.10.0/24": {
|
||||||
|
"dev": "r1-eth0",
|
||||||
|
"metric": "20",
|
||||||
|
"proto": "187",
|
||||||
|
"via": "10.0.20.1"
|
||||||
|
},
|
||||||
|
"10.0.20.0/24": {
|
||||||
|
"dev": "r1-eth0",
|
||||||
|
"proto": "kernel",
|
||||||
|
"scope": "link"
|
||||||
|
}
|
||||||
|
}
|
80
tests/topotests/isis-topo1-vrf/r1/r1_topology.json
Normal file
80
tests/topotests/isis-topo1-vrf/r1/r1_topology.json
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
{
|
||||||
|
"1": {
|
||||||
|
"level-1": {
|
||||||
|
"ipv4": [
|
||||||
|
{
|
||||||
|
"vertex": "r1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ipv6": [
|
||||||
|
{
|
||||||
|
"vertex": "r1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"level-2": {
|
||||||
|
"ipv4": [
|
||||||
|
{
|
||||||
|
"vertex": "r1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metric": "internal",
|
||||||
|
"parent": "0",
|
||||||
|
"type": "IP",
|
||||||
|
"vertex": "10.0.20.0/24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r1-eth0",
|
||||||
|
"metric": "10",
|
||||||
|
"next-hop": "r3",
|
||||||
|
"parent": "r1(4)",
|
||||||
|
"type": "TE-IS",
|
||||||
|
"vertex": "r3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r3",
|
||||||
|
"metric": "TE",
|
||||||
|
"next-hop": "20",
|
||||||
|
"parent": "r1-eth0",
|
||||||
|
"type": "IP",
|
||||||
|
"vertex": "10.0.20.0/24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r3",
|
||||||
|
"metric": "TE",
|
||||||
|
"next-hop": "20",
|
||||||
|
"parent": "r1-eth0",
|
||||||
|
"type": "IP",
|
||||||
|
"vertex": "10.0.10.0/24"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ipv6": [
|
||||||
|
{
|
||||||
|
"vertex": "r1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metric": "internal",
|
||||||
|
"parent": "0",
|
||||||
|
"type": "IP6",
|
||||||
|
"vertex": "2001:db8:1:1::/64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r1-eth0",
|
||||||
|
"metric": "10",
|
||||||
|
"next-hop": "r3",
|
||||||
|
"parent": "r1(4)",
|
||||||
|
"type": "TE-IS",
|
||||||
|
"vertex": "r3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r3",
|
||||||
|
"metric": "internal",
|
||||||
|
"next-hop": "20",
|
||||||
|
"parent": "r1-eth0",
|
||||||
|
"type": "IP6",
|
||||||
|
"vertex": "2001:db8:2:1::/64"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
9
tests/topotests/isis-topo1-vrf/r1/zebra.conf
Executable file
9
tests/topotests/isis-topo1-vrf/r1/zebra.conf
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
hostname r1
|
||||||
|
interface r1-eth0 vrf r1-cust1
|
||||||
|
ip address 10.0.20.2/24
|
||||||
|
ipv6 address 2001:db8:1:1::2/64
|
||||||
|
!
|
||||||
|
interface lo
|
||||||
|
ip address 10.254.0.1/32
|
||||||
|
ipv6 address 2001:db8:F::1/128
|
||||||
|
!
|
15
tests/topotests/isis-topo1-vrf/r2/isisd.conf
Executable file
15
tests/topotests/isis-topo1-vrf/r2/isisd.conf
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
hostname r2
|
||||||
|
debug isis adj-packets
|
||||||
|
debug isis events
|
||||||
|
debug isis update-packets
|
||||||
|
interface r2-eth0
|
||||||
|
ip router isis 1 vrf r2-cust1
|
||||||
|
ipv6 router isis 1 vrf r2-cust1
|
||||||
|
isis circuit-type level-2-only
|
||||||
|
!
|
||||||
|
router isis 1 vrf r2-cust1
|
||||||
|
net 10.0000.0000.0000.0000.0000.0000.0000.0000.0001.00
|
||||||
|
metric-style wide
|
||||||
|
redistribute ipv4 connected level-2
|
||||||
|
redistribute ipv6 connected level-2
|
||||||
|
!
|
57
tests/topotests/isis-topo1-vrf/r2/r2_route.json
Normal file
57
tests/topotests/isis-topo1-vrf/r2/r2_route.json
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
{
|
||||||
|
"10.0.11.0/24": [
|
||||||
|
{
|
||||||
|
"distance": 115,
|
||||||
|
"metric": 20,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"afi": "ipv4",
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 2,
|
||||||
|
"interfaceName": "r2-eth0",
|
||||||
|
"ip": "10.0.21.1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "10.0.11.0/24",
|
||||||
|
"protocol": "isis",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 3,
|
||||||
|
"vrfName": "r2-cust1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"10.0.21.0/24": [
|
||||||
|
{
|
||||||
|
"distance": 115,
|
||||||
|
"metric": 20,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"afi": "ipv4",
|
||||||
|
"interfaceIndex": 2,
|
||||||
|
"interfaceName": "r2-eth0",
|
||||||
|
"ip": "10.0.21.1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "10.0.21.0/24",
|
||||||
|
"protocol": "isis",
|
||||||
|
"vrfId": 3,
|
||||||
|
"vrfName": "r2-cust1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"directlyConnected": true,
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 2,
|
||||||
|
"interfaceName": "r2-eth0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "10.0.21.0/24",
|
||||||
|
"protocol": "connected",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 3,
|
||||||
|
"vrfName": "r2-cust1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
40
tests/topotests/isis-topo1-vrf/r2/r2_route6.json
Normal file
40
tests/topotests/isis-topo1-vrf/r2/r2_route6.json
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"2001:db8:1:2::/64": [
|
||||||
|
{
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"directlyConnected": true,
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 2,
|
||||||
|
"interfaceName": "r2-eth0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "2001:db8:1:2::/64",
|
||||||
|
"protocol": "connected",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 3,
|
||||||
|
"vrfName": "r2-cust1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"2001:db8:2:2::/64": [
|
||||||
|
{
|
||||||
|
"distance": 115,
|
||||||
|
"metric": 20,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"afi": "ipv6",
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 2,
|
||||||
|
"interfaceName": "r2-eth0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "2001:db8:2:2::/64",
|
||||||
|
"protocol": "isis",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 3,
|
||||||
|
"vrfName": "r2-cust1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
14
tests/topotests/isis-topo1-vrf/r2/r2_route6_linux.json
Executable file
14
tests/topotests/isis-topo1-vrf/r2/r2_route6_linux.json
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"2001:db8:1:2::/64": {
|
||||||
|
"dev": "r2-eth0",
|
||||||
|
"metric": "256",
|
||||||
|
"pref": "medium",
|
||||||
|
"proto": "kernel"
|
||||||
|
},
|
||||||
|
"2001:db8:2:2::/64": {
|
||||||
|
"dev": "r2-eth0",
|
||||||
|
"metric": "20",
|
||||||
|
"pref": "medium",
|
||||||
|
"proto": "187"
|
||||||
|
}
|
||||||
|
}
|
13
tests/topotests/isis-topo1-vrf/r2/r2_route_linux.json
Executable file
13
tests/topotests/isis-topo1-vrf/r2/r2_route_linux.json
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"10.0.11.0/24": {
|
||||||
|
"dev": "r2-eth0",
|
||||||
|
"metric": "20",
|
||||||
|
"proto": "187",
|
||||||
|
"via": "10.0.21.1"
|
||||||
|
},
|
||||||
|
"10.0.21.0/24": {
|
||||||
|
"dev": "r2-eth0",
|
||||||
|
"proto": "kernel",
|
||||||
|
"scope": "link"
|
||||||
|
}
|
||||||
|
}
|
80
tests/topotests/isis-topo1-vrf/r2/r2_topology.json
Normal file
80
tests/topotests/isis-topo1-vrf/r2/r2_topology.json
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
{
|
||||||
|
"1": {
|
||||||
|
"level-1": {
|
||||||
|
"ipv4": [
|
||||||
|
{
|
||||||
|
"vertex": "r2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ipv6": [
|
||||||
|
{
|
||||||
|
"vertex": "r2"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"level-2": {
|
||||||
|
"ipv4": [
|
||||||
|
{
|
||||||
|
"vertex": "r2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metric": "internal",
|
||||||
|
"parent": "0",
|
||||||
|
"type": "IP",
|
||||||
|
"vertex": "10.0.21.0/24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r2-eth0",
|
||||||
|
"metric": "10",
|
||||||
|
"next-hop": "r4",
|
||||||
|
"parent": "r2(4)",
|
||||||
|
"type": "TE-IS",
|
||||||
|
"vertex": "r4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r4",
|
||||||
|
"metric": "TE",
|
||||||
|
"next-hop": "20",
|
||||||
|
"parent": "r2-eth0",
|
||||||
|
"type": "IP",
|
||||||
|
"vertex": "10.0.21.0/24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r4",
|
||||||
|
"metric": "TE",
|
||||||
|
"next-hop": "20",
|
||||||
|
"parent": "r2-eth0",
|
||||||
|
"type": "IP",
|
||||||
|
"vertex": "10.0.11.0/24"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ipv6": [
|
||||||
|
{
|
||||||
|
"vertex": "r2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metric": "internal",
|
||||||
|
"parent": "0",
|
||||||
|
"type": "IP6",
|
||||||
|
"vertex": "2001:db8:1:2::/64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r2-eth0",
|
||||||
|
"metric": "10",
|
||||||
|
"next-hop": "r4",
|
||||||
|
"parent": "r2(4)",
|
||||||
|
"type": "TE-IS",
|
||||||
|
"vertex": "r4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r4",
|
||||||
|
"metric": "internal",
|
||||||
|
"next-hop": "20",
|
||||||
|
"parent": "r2-eth0",
|
||||||
|
"type": "IP6",
|
||||||
|
"vertex": "2001:db8:2:2::/64"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
9
tests/topotests/isis-topo1-vrf/r2/zebra.conf
Executable file
9
tests/topotests/isis-topo1-vrf/r2/zebra.conf
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
hostname r2
|
||||||
|
interface r2-eth0 vrf r2-cust1
|
||||||
|
ip address 10.0.21.2/24
|
||||||
|
ipv6 address 2001:db8:1:2::2/64
|
||||||
|
!
|
||||||
|
interface lo
|
||||||
|
ip address 10.254.0.2/32
|
||||||
|
ipv6 address 2001:db8:F::2/128
|
||||||
|
!
|
22
tests/topotests/isis-topo1-vrf/r3/isisd.conf
Executable file
22
tests/topotests/isis-topo1-vrf/r3/isisd.conf
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
hostname r3
|
||||||
|
debug isis adj-packets
|
||||||
|
debug isis events
|
||||||
|
debug isis update-packets
|
||||||
|
interface r3-eth0
|
||||||
|
ip router isis 1 vrf r3-cust1
|
||||||
|
ipv6 router isis 1 vrf r3-cust1
|
||||||
|
isis circuit-type level-2-only
|
||||||
|
!
|
||||||
|
interface r3-eth1
|
||||||
|
ip router isis 1 vrf r3-cust1
|
||||||
|
ipv6 router isis 1 vrf r3-cust1
|
||||||
|
isis circuit-type level-1
|
||||||
|
!
|
||||||
|
router isis 1 vrf r3-cust1
|
||||||
|
net 10.0000.0000.0000.0000.0000.0000.0000.0000.0002.00
|
||||||
|
metric-style wide
|
||||||
|
redistribute ipv4 connected level-1
|
||||||
|
redistribute ipv4 connected level-2
|
||||||
|
redistribute ipv6 connected level-1
|
||||||
|
redistribute ipv6 connected level-2
|
||||||
|
!
|
112
tests/topotests/isis-topo1-vrf/r3/r3_route.json
Normal file
112
tests/topotests/isis-topo1-vrf/r3/r3_route.json
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
{
|
||||||
|
"10.0.10.0/24": [
|
||||||
|
{
|
||||||
|
"distance": 115,
|
||||||
|
"metric": 20,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"afi": "ipv4",
|
||||||
|
"interfaceIndex": 3,
|
||||||
|
"interfaceName": "r3-eth1",
|
||||||
|
"ip": "10.0.10.1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "10.0.10.0/24",
|
||||||
|
"protocol": "isis",
|
||||||
|
"vrfId": 4,
|
||||||
|
"vrfName": "r3-cust1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"directlyConnected": true,
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 3,
|
||||||
|
"interfaceName": "r3-eth1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "10.0.10.0/24",
|
||||||
|
"protocol": "connected",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 4,
|
||||||
|
"vrfName": "r3-cust1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"10.0.11.0/24": [
|
||||||
|
{
|
||||||
|
"distance": 115,
|
||||||
|
"metric": 20,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"afi": "ipv4",
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 3,
|
||||||
|
"interfaceName": "r3-eth1",
|
||||||
|
"ip": "10.0.10.1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "10.0.11.0/24",
|
||||||
|
"protocol": "isis",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 4,
|
||||||
|
"vrfName": "r3-cust1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"10.0.20.0/24": [
|
||||||
|
{
|
||||||
|
"distance": 115,
|
||||||
|
"metric": 20,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"afi": "ipv4",
|
||||||
|
"interfaceIndex": 2,
|
||||||
|
"interfaceName": "r3-eth0",
|
||||||
|
"ip": "10.0.20.2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "10.0.20.0/24",
|
||||||
|
"protocol": "isis",
|
||||||
|
"vrfId": 4,
|
||||||
|
"vrfName": "r3-cust1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"directlyConnected": true,
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 2,
|
||||||
|
"interfaceName": "r3-eth0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "10.0.20.0/24",
|
||||||
|
"protocol": "connected",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 4,
|
||||||
|
"vrfName": "r3-cust1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"10.0.21.0/24": [
|
||||||
|
{
|
||||||
|
"distance": 115,
|
||||||
|
"metric": 30,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"afi": "ipv4",
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 3,
|
||||||
|
"interfaceName": "r3-eth1",
|
||||||
|
"ip": "10.0.10.1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "10.0.21.0/24",
|
||||||
|
"protocol": "isis",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 4,
|
||||||
|
"vrfName": "r3-cust1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
78
tests/topotests/isis-topo1-vrf/r3/r3_route6.json
Normal file
78
tests/topotests/isis-topo1-vrf/r3/r3_route6.json
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
{
|
||||||
|
"2001:db8:1:1::/64": [
|
||||||
|
{
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"directlyConnected": true,
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 2,
|
||||||
|
"interfaceName": "r3-eth0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "2001:db8:1:1::/64",
|
||||||
|
"protocol": "connected",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 4,
|
||||||
|
"vrfName": "r3-cust1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"2001:db8:1:2::/64": [
|
||||||
|
{
|
||||||
|
"distance": 115,
|
||||||
|
"metric": 30,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"afi": "ipv6",
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 3,
|
||||||
|
"interfaceName": "r3-eth1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "2001:db8:1:2::/64",
|
||||||
|
"protocol": "isis",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 4,
|
||||||
|
"vrfName": "r3-cust1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"2001:db8:2:1::/64": [
|
||||||
|
{
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"directlyConnected": true,
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 3,
|
||||||
|
"interfaceName": "r3-eth1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "2001:db8:2:1::/64",
|
||||||
|
"protocol": "connected",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 4,
|
||||||
|
"vrfName": "r3-cust1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"2001:db8:2:2::/64": [
|
||||||
|
{
|
||||||
|
"distance": 115,
|
||||||
|
"metric": 20,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"afi": "ipv6",
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 3,
|
||||||
|
"interfaceName": "r3-eth1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "2001:db8:2:2::/64",
|
||||||
|
"protocol": "isis",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 4,
|
||||||
|
"vrfName": "r3-cust1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
26
tests/topotests/isis-topo1-vrf/r3/r3_route6_linux.json
Executable file
26
tests/topotests/isis-topo1-vrf/r3/r3_route6_linux.json
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"2001:db8:1:1::/64": {
|
||||||
|
"dev": "r3-eth0",
|
||||||
|
"metric": "256",
|
||||||
|
"pref": "medium",
|
||||||
|
"proto": "kernel"
|
||||||
|
},
|
||||||
|
"2001:db8:1:2::/64": {
|
||||||
|
"dev": "r3-eth1",
|
||||||
|
"metric": "20",
|
||||||
|
"pref": "medium",
|
||||||
|
"proto": "187"
|
||||||
|
},
|
||||||
|
"2001:db8:2:1::/64": {
|
||||||
|
"dev": "r3-eth1",
|
||||||
|
"metric": "256",
|
||||||
|
"pref": "medium",
|
||||||
|
"proto": "kernel"
|
||||||
|
},
|
||||||
|
"2001:db8:2:2::/64": {
|
||||||
|
"dev": "r3-eth1",
|
||||||
|
"metric": "20",
|
||||||
|
"pref": "medium",
|
||||||
|
"proto": "187"
|
||||||
|
}
|
||||||
|
}
|
24
tests/topotests/isis-topo1-vrf/r3/r3_route_linux.json
Executable file
24
tests/topotests/isis-topo1-vrf/r3/r3_route_linux.json
Executable file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"10.0.10.0/24": {
|
||||||
|
"dev": "r3-eth1",
|
||||||
|
"proto": "kernel",
|
||||||
|
"scope": "link"
|
||||||
|
},
|
||||||
|
"10.0.11.0/24": {
|
||||||
|
"dev": "r3-eth1",
|
||||||
|
"metric": "20",
|
||||||
|
"proto": "187",
|
||||||
|
"via": "10.0.10.1"
|
||||||
|
},
|
||||||
|
"10.0.20.0/24": {
|
||||||
|
"dev": "r3-eth0",
|
||||||
|
"proto": "kernel",
|
||||||
|
"scope": "link"
|
||||||
|
},
|
||||||
|
"10.0.21.0/24": {
|
||||||
|
"dev": "r3-eth1",
|
||||||
|
"metric": "20",
|
||||||
|
"proto": "187",
|
||||||
|
"via": "10.0.10.1"
|
||||||
|
}
|
||||||
|
}
|
132
tests/topotests/isis-topo1-vrf/r3/r3_topology.json
Normal file
132
tests/topotests/isis-topo1-vrf/r3/r3_topology.json
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
{
|
||||||
|
"1": {
|
||||||
|
"level-1": {
|
||||||
|
"ipv4": [
|
||||||
|
{
|
||||||
|
"vertex": "r3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metric": "internal",
|
||||||
|
"parent": "0",
|
||||||
|
"type": "IP",
|
||||||
|
"vertex": "10.0.10.0/24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r3-eth1",
|
||||||
|
"metric": "10",
|
||||||
|
"next-hop": "r5",
|
||||||
|
"parent": "r3(4)",
|
||||||
|
"type": "TE-IS",
|
||||||
|
"vertex": "r5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r5",
|
||||||
|
"metric": "TE",
|
||||||
|
"next-hop": "20",
|
||||||
|
"parent": "r3-eth1",
|
||||||
|
"type": "IP",
|
||||||
|
"vertex": "10.0.10.0/24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r5",
|
||||||
|
"metric": "TE",
|
||||||
|
"next-hop": "20",
|
||||||
|
"parent": "r3-eth1",
|
||||||
|
"type": "IP",
|
||||||
|
"vertex": "10.0.11.0/24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r5",
|
||||||
|
"metric": "TE",
|
||||||
|
"next-hop": "30",
|
||||||
|
"parent": "r3-eth1",
|
||||||
|
"type": "IP",
|
||||||
|
"vertex": "10.0.21.0/24"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ipv6": [
|
||||||
|
{
|
||||||
|
"vertex": "r3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metric": "internal",
|
||||||
|
"parent": "0",
|
||||||
|
"type": "IP6",
|
||||||
|
"vertex": "2001:db8:2:1::/64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r3-eth1",
|
||||||
|
"metric": "10",
|
||||||
|
"next-hop": "r5",
|
||||||
|
"parent": "r3(4)",
|
||||||
|
"type": "TE-IS",
|
||||||
|
"vertex": "r5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r5",
|
||||||
|
"metric": "internal",
|
||||||
|
"next-hop": "20",
|
||||||
|
"parent": "r3-eth1",
|
||||||
|
"type": "IP6",
|
||||||
|
"vertex": "2001:db8:2:2::/64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r5",
|
||||||
|
"metric": "internal",
|
||||||
|
"next-hop": "30",
|
||||||
|
"parent": "r3-eth1",
|
||||||
|
"type": "IP6",
|
||||||
|
"vertex": "2001:db8:1:2::/64"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"level-2": {
|
||||||
|
"ipv4": [
|
||||||
|
{
|
||||||
|
"vertex": "r3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metric": "internal",
|
||||||
|
"parent": "0",
|
||||||
|
"type": "IP",
|
||||||
|
"vertex": "10.0.20.0/24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r3-eth0",
|
||||||
|
"metric": "10",
|
||||||
|
"next-hop": "r3",
|
||||||
|
"parent": "r3(4)",
|
||||||
|
"type": "TE-IS",
|
||||||
|
"vertex": "r3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r3",
|
||||||
|
"metric": "TE",
|
||||||
|
"next-hop": "20",
|
||||||
|
"parent": "r3-eth0",
|
||||||
|
"type": "IP",
|
||||||
|
"vertex": "10.0.20.0/24"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ipv6": [
|
||||||
|
{
|
||||||
|
"vertex": "r3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metric": "internal",
|
||||||
|
"parent": "0",
|
||||||
|
"type": "IP6",
|
||||||
|
"vertex": "2001:db8:1:1::/64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r3-eth0",
|
||||||
|
"metric": "10",
|
||||||
|
"next-hop": "r3",
|
||||||
|
"parent": "r3(4)",
|
||||||
|
"type": "TE-IS",
|
||||||
|
"vertex": "r3"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
tests/topotests/isis-topo1-vrf/r3/zebra.conf
Executable file
13
tests/topotests/isis-topo1-vrf/r3/zebra.conf
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
hostname r3
|
||||||
|
interface r3-eth0 vrf r3-cust1
|
||||||
|
ip address 10.0.20.1/24
|
||||||
|
ipv6 address 2001:db8:1:1::1/64
|
||||||
|
!
|
||||||
|
interface r3-eth1 vrf r3-cust1
|
||||||
|
ip address 10.0.10.2/24
|
||||||
|
ipv6 address 2001:db8:2:1::2/64
|
||||||
|
!
|
||||||
|
interface lo
|
||||||
|
ip address 10.254.0.3/32
|
||||||
|
ipv6 address 2001:db8:F::3/128
|
||||||
|
!
|
25
tests/topotests/isis-topo1-vrf/r4/isisd.conf
Executable file
25
tests/topotests/isis-topo1-vrf/r4/isisd.conf
Executable file
@ -0,0 +1,25 @@
|
|||||||
|
hostname r4
|
||||||
|
debug isis adj-packets
|
||||||
|
debug isis events
|
||||||
|
debug isis update-packets
|
||||||
|
debug isis lsp-gen
|
||||||
|
debug isis lsp-sched
|
||||||
|
|
||||||
|
interface r4-eth0
|
||||||
|
ip router isis 1 vrf r4-cust1
|
||||||
|
ipv6 router isis 1 vrf r4-cust1
|
||||||
|
isis circuit-type level-2-only
|
||||||
|
!
|
||||||
|
interface r4-eth1
|
||||||
|
ip router isis 1 vrf r4-cust1
|
||||||
|
ipv6 router isis 1 vrf r4-cust1
|
||||||
|
isis circuit-type level-1
|
||||||
|
!
|
||||||
|
router isis 1 vrf r4-cust1
|
||||||
|
net 10.0000.0000.0000.0000.0000.0000.0000.0000.0004.00
|
||||||
|
metric-style wide
|
||||||
|
redistribute ipv4 connected level-1
|
||||||
|
redistribute ipv4 connected level-2
|
||||||
|
redistribute ipv6 connected level-1
|
||||||
|
redistribute ipv6 connected level-2
|
||||||
|
!
|
105
tests/topotests/isis-topo1-vrf/r4/r4_route.json
Normal file
105
tests/topotests/isis-topo1-vrf/r4/r4_route.json
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
{
|
||||||
|
"10.0.10.0/24": [
|
||||||
|
{
|
||||||
|
"metric": 20,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"afi": "ipv4",
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 3,
|
||||||
|
"interfaceName": "r4-eth1",
|
||||||
|
"ip": "10.0.11.1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "10.0.10.0/24",
|
||||||
|
"protocol": "isis",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 4,
|
||||||
|
"vrfName": "r4-cust1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"10.0.11.0/24": [
|
||||||
|
{
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"afi": "ipv4",
|
||||||
|
"interfaceIndex": 3,
|
||||||
|
"interfaceName": "r4-eth1",
|
||||||
|
"ip": "10.0.11.1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "10.0.11.0/24",
|
||||||
|
"protocol": "isis",
|
||||||
|
"vrfId": 4,
|
||||||
|
"vrfName": "r4-cust1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"directlyConnected": true,
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 3,
|
||||||
|
"interfaceName": "r4-eth1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "10.0.11.0/24",
|
||||||
|
"protocol": "connected",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 4,
|
||||||
|
"vrfName": "r4-cust1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"10.0.20.0/24": [
|
||||||
|
{
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"afi": "ipv4",
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 3,
|
||||||
|
"interfaceName": "r4-eth1",
|
||||||
|
"ip": "10.0.11.1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "10.0.20.0/24",
|
||||||
|
"protocol": "isis",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 4,
|
||||||
|
"vrfName": "r4-cust1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"10.0.21.0/24": [
|
||||||
|
{
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"afi": "ipv4",
|
||||||
|
"interfaceIndex": 2,
|
||||||
|
"interfaceName": "r4-eth0",
|
||||||
|
"ip": "10.0.21.2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "10.0.21.0/24",
|
||||||
|
"protocol": "isis",
|
||||||
|
"vrfId": 4,
|
||||||
|
"vrfName": "r4-cust1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"directlyConnected": true,
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 2,
|
||||||
|
"interfaceName": "r4-eth0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "10.0.21.0/24",
|
||||||
|
"protocol": "connected",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 4,
|
||||||
|
"vrfName": "r4-cust1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
78
tests/topotests/isis-topo1-vrf/r4/r4_route6.json
Normal file
78
tests/topotests/isis-topo1-vrf/r4/r4_route6.json
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
{
|
||||||
|
"2001:db8:1:1::/64": [
|
||||||
|
{
|
||||||
|
"distance": 115,
|
||||||
|
"metric": 30,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"afi": "ipv6",
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 3,
|
||||||
|
"interfaceName": "r4-eth1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "2001:db8:1:1::/64",
|
||||||
|
"protocol": "isis",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 4,
|
||||||
|
"vrfName": "r4-cust1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"2001:db8:1:2::/64": [
|
||||||
|
{
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"directlyConnected": true,
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 2,
|
||||||
|
"interfaceName": "r4-eth0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "2001:db8:1:2::/64",
|
||||||
|
"protocol": "connected",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 4,
|
||||||
|
"vrfName": "r4-cust1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"2001:db8:2:1::/64": [
|
||||||
|
{
|
||||||
|
"distance": 115,
|
||||||
|
"metric": 20,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"afi": "ipv6",
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 3,
|
||||||
|
"interfaceName": "r4-eth1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "2001:db8:2:1::/64",
|
||||||
|
"protocol": "isis",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 4,
|
||||||
|
"vrfName": "r4-cust1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"2001:db8:2:2::/64": [
|
||||||
|
{
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"directlyConnected": true,
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 3,
|
||||||
|
"interfaceName": "r4-eth1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "2001:db8:2:2::/64",
|
||||||
|
"protocol": "connected",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 4,
|
||||||
|
"vrfName": "r4-cust1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
26
tests/topotests/isis-topo1-vrf/r4/r4_route6_linux.json
Executable file
26
tests/topotests/isis-topo1-vrf/r4/r4_route6_linux.json
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"2001:db8:1:1::/64": {
|
||||||
|
"dev": "r4-eth1",
|
||||||
|
"metric": "20",
|
||||||
|
"pref": "medium",
|
||||||
|
"proto": "187"
|
||||||
|
},
|
||||||
|
"2001:db8:1:2::/64": {
|
||||||
|
"dev": "r4-eth0",
|
||||||
|
"metric": "256",
|
||||||
|
"pref": "medium",
|
||||||
|
"proto": "kernel"
|
||||||
|
},
|
||||||
|
"2001:db8:2:1::/64": {
|
||||||
|
"dev": "r4-eth1",
|
||||||
|
"metric": "20",
|
||||||
|
"pref": "medium",
|
||||||
|
"proto": "187"
|
||||||
|
},
|
||||||
|
"2001:db8:2:2::/64": {
|
||||||
|
"dev": "r4-eth1",
|
||||||
|
"metric": "256",
|
||||||
|
"pref": "medium",
|
||||||
|
"proto": "kernel"
|
||||||
|
}
|
||||||
|
}
|
24
tests/topotests/isis-topo1-vrf/r4/r4_route_linux.json
Executable file
24
tests/topotests/isis-topo1-vrf/r4/r4_route_linux.json
Executable file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"10.0.10.0/24": {
|
||||||
|
"dev": "r4-eth1",
|
||||||
|
"metric": "20",
|
||||||
|
"proto": "187",
|
||||||
|
"via": "10.0.11.1"
|
||||||
|
},
|
||||||
|
"10.0.11.0/24": {
|
||||||
|
"dev": "r4-eth1",
|
||||||
|
"proto": "kernel",
|
||||||
|
"scope": "link"
|
||||||
|
},
|
||||||
|
"10.0.20.0/24": {
|
||||||
|
"dev": "r4-eth1",
|
||||||
|
"metric": "20",
|
||||||
|
"proto": "187",
|
||||||
|
"via": "10.0.11.1"
|
||||||
|
},
|
||||||
|
"10.0.21.0/24": {
|
||||||
|
"dev": "r4-eth0",
|
||||||
|
"proto": "kernel",
|
||||||
|
"scope": "link"
|
||||||
|
}
|
||||||
|
}
|
132
tests/topotests/isis-topo1-vrf/r4/r4_topology.json
Normal file
132
tests/topotests/isis-topo1-vrf/r4/r4_topology.json
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
{
|
||||||
|
"1": {
|
||||||
|
"level-1": {
|
||||||
|
"ipv4": [
|
||||||
|
{
|
||||||
|
"vertex": "r4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metric": "internal",
|
||||||
|
"parent": "0",
|
||||||
|
"type": "IP",
|
||||||
|
"vertex": "10.0.11.0/24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r4-eth1",
|
||||||
|
"metric": "10",
|
||||||
|
"next-hop": "r5",
|
||||||
|
"parent": "r4(4)",
|
||||||
|
"type": "TE-IS",
|
||||||
|
"vertex": "r5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r5",
|
||||||
|
"metric": "TE",
|
||||||
|
"next-hop": "20",
|
||||||
|
"parent": "r4-eth1",
|
||||||
|
"type": "IP",
|
||||||
|
"vertex": "10.0.10.0/24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r5",
|
||||||
|
"metric": "TE",
|
||||||
|
"next-hop": "20",
|
||||||
|
"parent": "r4-eth1",
|
||||||
|
"type": "IP",
|
||||||
|
"vertex": "10.0.11.0/24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r5",
|
||||||
|
"metric": "TE",
|
||||||
|
"next-hop": "30",
|
||||||
|
"parent": "r4-eth1",
|
||||||
|
"type": "IP",
|
||||||
|
"vertex": "10.0.20.0/24"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ipv6": [
|
||||||
|
{
|
||||||
|
"vertex": "r4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metric": "internal",
|
||||||
|
"parent": "0",
|
||||||
|
"type": "IP6",
|
||||||
|
"vertex": "2001:db8:2:2::/64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r4-eth1",
|
||||||
|
"metric": "10",
|
||||||
|
"next-hop": "r5",
|
||||||
|
"parent": "r4(4)",
|
||||||
|
"type": "TE-IS",
|
||||||
|
"vertex": "r5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r5",
|
||||||
|
"metric": "internal",
|
||||||
|
"next-hop": "20",
|
||||||
|
"parent": "r4-eth1",
|
||||||
|
"type": "IP6",
|
||||||
|
"vertex": "2001:db8:2:1::/64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r5",
|
||||||
|
"metric": "internal",
|
||||||
|
"next-hop": "30",
|
||||||
|
"parent": "r4-eth1",
|
||||||
|
"type": "IP6",
|
||||||
|
"vertex": "2001:db8:1:1::/64"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"level-2": {
|
||||||
|
"ipv4": [
|
||||||
|
{
|
||||||
|
"vertex": "r4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metric": "internal",
|
||||||
|
"parent": "0",
|
||||||
|
"type": "IP",
|
||||||
|
"vertex": "10.0.21.0/24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r4-eth0",
|
||||||
|
"metric": "10",
|
||||||
|
"next-hop": "r2",
|
||||||
|
"parent": "r4(4)",
|
||||||
|
"type": "TE-IS",
|
||||||
|
"vertex": "r2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r2",
|
||||||
|
"metric": "TE",
|
||||||
|
"next-hop": "20",
|
||||||
|
"parent": "r4-eth0",
|
||||||
|
"type": "IP",
|
||||||
|
"vertex": "10.0.21.0/24"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ipv6": [
|
||||||
|
{
|
||||||
|
"vertex": "r4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metric": "internal",
|
||||||
|
"parent": "0",
|
||||||
|
"type": "IP6",
|
||||||
|
"vertex": "2001:db8:1:2::/64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r4-eth0",
|
||||||
|
"metric": "10",
|
||||||
|
"next-hop": "r2",
|
||||||
|
"parent": "r4(4)",
|
||||||
|
"type": "TE-IS",
|
||||||
|
"vertex": "r2"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
tests/topotests/isis-topo1-vrf/r4/zebra.conf
Executable file
13
tests/topotests/isis-topo1-vrf/r4/zebra.conf
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
hostname r4
|
||||||
|
interface r4-eth0 vrf r4-cust1
|
||||||
|
ip address 10.0.21.1/24
|
||||||
|
ipv6 address 2001:db8:1:2::1/64
|
||||||
|
!
|
||||||
|
interface r4-eth1 vrf r4-cust1
|
||||||
|
ip address 10.0.11.2/24
|
||||||
|
ipv6 address 2001:db8:2:2::2/64
|
||||||
|
!
|
||||||
|
interface lo
|
||||||
|
ip address 10.254.0.4/32
|
||||||
|
ipv6 address 2001:db8:F::4/128
|
||||||
|
!
|
21
tests/topotests/isis-topo1-vrf/r5/isisd.conf
Executable file
21
tests/topotests/isis-topo1-vrf/r5/isisd.conf
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
hostname r5
|
||||||
|
debug isis adj-packets
|
||||||
|
debug isis events
|
||||||
|
debug isis update-packets
|
||||||
|
interface r5-eth0
|
||||||
|
ip router isis 1 vrf r5-cust1
|
||||||
|
ipv6 router isis 1 vrf r5-cust1
|
||||||
|
isis circuit-type level-1
|
||||||
|
!
|
||||||
|
interface r5-eth1
|
||||||
|
ip router isis 1 vrf r5-cust1
|
||||||
|
ipv6 router isis 1 vrf r5-cust1
|
||||||
|
isis circuit-type level-1
|
||||||
|
!
|
||||||
|
router isis 1 vrf r5-cust1
|
||||||
|
net 10.0000.0000.0000.0000.0000.0000.0000.0000.0005.00
|
||||||
|
metric-style wide
|
||||||
|
is-type level-1
|
||||||
|
redistribute ipv4 connected level-1
|
||||||
|
redistribute ipv6 connected level-1
|
||||||
|
!
|
106
tests/topotests/isis-topo1-vrf/r5/r5_route.json
Normal file
106
tests/topotests/isis-topo1-vrf/r5/r5_route.json
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
{
|
||||||
|
"10.0.10.0/24": [
|
||||||
|
{
|
||||||
|
"distance": 115,
|
||||||
|
"metric": 20,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"afi": "ipv4",
|
||||||
|
"interfaceIndex": 2,
|
||||||
|
"interfaceName": "r5-eth0",
|
||||||
|
"ip": "10.0.10.2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "10.0.10.0/24",
|
||||||
|
"protocol": "isis",
|
||||||
|
"vrfId": 4,
|
||||||
|
"vrfName": "r5-cust1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"directlyConnected": true,
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 2,
|
||||||
|
"interfaceName": "r5-eth0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "10.0.10.0/24",
|
||||||
|
"protocol": "connected",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 4,
|
||||||
|
"vrfName": "r5-cust1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"10.0.11.0/24": [
|
||||||
|
{
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"afi": "ipv4",
|
||||||
|
"interfaceIndex": 3,
|
||||||
|
"interfaceName": "r5-eth1",
|
||||||
|
"ip": "10.0.11.2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "10.0.11.0/24",
|
||||||
|
"protocol": "isis",
|
||||||
|
"vrfId": 4,
|
||||||
|
"vrfName": "r5-cust1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"directlyConnected": true,
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 3,
|
||||||
|
"interfaceName": "r5-eth1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "10.0.11.0/24",
|
||||||
|
"protocol": "connected",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 4,
|
||||||
|
"vrfName": "r5-cust1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"10.0.20.0/24": [
|
||||||
|
{
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"afi": "ipv4",
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 2,
|
||||||
|
"interfaceName": "r5-eth0",
|
||||||
|
"ip": "10.0.10.2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "10.0.20.0/24",
|
||||||
|
"protocol": "isis",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 4,
|
||||||
|
"vrfName": "r5-cust1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"10.0.21.0/24": [
|
||||||
|
{
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"afi": "ipv4",
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 3,
|
||||||
|
"interfaceName": "r5-eth1",
|
||||||
|
"ip": "10.0.11.2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "10.0.21.0/24",
|
||||||
|
"protocol": "isis",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 4,
|
||||||
|
"vrfName": "r5-cust1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
78
tests/topotests/isis-topo1-vrf/r5/r5_route6.json
Normal file
78
tests/topotests/isis-topo1-vrf/r5/r5_route6.json
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
{
|
||||||
|
"2001:db8:1:1::/64": [
|
||||||
|
{
|
||||||
|
"distance": 115,
|
||||||
|
"metric": 20,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"afi": "ipv6",
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 2,
|
||||||
|
"interfaceName": "r5-eth0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "2001:db8:1:1::/64",
|
||||||
|
"protocol": "isis",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 4,
|
||||||
|
"vrfName": "r5-cust1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"2001:db8:1:2::/64": [
|
||||||
|
{
|
||||||
|
"distance": 115,
|
||||||
|
"metric": 20,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"afi": "ipv6",
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 3,
|
||||||
|
"interfaceName": "r5-eth1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "2001:db8:1:2::/64",
|
||||||
|
"protocol": "isis",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 4,
|
||||||
|
"vrfName": "r5-cust1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"2001:db8:2:1::/64": [
|
||||||
|
{
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"directlyConnected": true,
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 2,
|
||||||
|
"interfaceName": "r5-eth0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "2001:db8:2:1::/64",
|
||||||
|
"protocol": "connected",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 4,
|
||||||
|
"vrfName": "r5-cust1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"2001:db8:2:2::/64": [
|
||||||
|
{
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"directlyConnected": true,
|
||||||
|
"fib": true,
|
||||||
|
"interfaceIndex": 3,
|
||||||
|
"interfaceName": "r5-eth1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefix": "2001:db8:2:2::/64",
|
||||||
|
"protocol": "connected",
|
||||||
|
"selected": true,
|
||||||
|
"vrfId": 4,
|
||||||
|
"vrfName": "r5-cust1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
26
tests/topotests/isis-topo1-vrf/r5/r5_route6_linux.json
Executable file
26
tests/topotests/isis-topo1-vrf/r5/r5_route6_linux.json
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"2001:db8:1:1::/64": {
|
||||||
|
"dev": "r5-eth0",
|
||||||
|
"metric": "20",
|
||||||
|
"pref": "medium",
|
||||||
|
"proto": "187"
|
||||||
|
},
|
||||||
|
"2001:db8:1:2::/64": {
|
||||||
|
"dev": "r5-eth1",
|
||||||
|
"metric": "20",
|
||||||
|
"pref": "medium",
|
||||||
|
"proto": "187"
|
||||||
|
},
|
||||||
|
"2001:db8:2:1::/64": {
|
||||||
|
"dev": "r5-eth0",
|
||||||
|
"metric": "256",
|
||||||
|
"pref": "medium",
|
||||||
|
"proto": "kernel"
|
||||||
|
},
|
||||||
|
"2001:db8:2:2::/64": {
|
||||||
|
"dev": "r5-eth1",
|
||||||
|
"metric": "256",
|
||||||
|
"pref": "medium",
|
||||||
|
"proto": "kernel"
|
||||||
|
}
|
||||||
|
}
|
24
tests/topotests/isis-topo1-vrf/r5/r5_route_linux.json
Executable file
24
tests/topotests/isis-topo1-vrf/r5/r5_route_linux.json
Executable file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"10.0.10.0/24": {
|
||||||
|
"dev": "r5-eth0",
|
||||||
|
"proto": "kernel",
|
||||||
|
"scope": "link"
|
||||||
|
},
|
||||||
|
"10.0.11.0/24": {
|
||||||
|
"dev": "r5-eth1",
|
||||||
|
"proto": "kernel",
|
||||||
|
"scope": "link"
|
||||||
|
},
|
||||||
|
"10.0.20.0/24": {
|
||||||
|
"dev": "r5-eth0",
|
||||||
|
"metric": "20",
|
||||||
|
"proto": "187",
|
||||||
|
"via": "10.0.10.2"
|
||||||
|
},
|
||||||
|
"10.0.21.0/24": {
|
||||||
|
"dev": "r5-eth1",
|
||||||
|
"metric": "20",
|
||||||
|
"proto": "187",
|
||||||
|
"via": "10.0.11.2"
|
||||||
|
}
|
||||||
|
}
|
124
tests/topotests/isis-topo1-vrf/r5/r5_topology.json
Normal file
124
tests/topotests/isis-topo1-vrf/r5/r5_topology.json
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
{
|
||||||
|
"1": {
|
||||||
|
"level-1": {
|
||||||
|
"ipv4": [
|
||||||
|
{
|
||||||
|
"vertex": "r5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metric": "internal",
|
||||||
|
"parent": "0",
|
||||||
|
"type": "IP",
|
||||||
|
"vertex": "10.0.10.0/24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metric": "internal",
|
||||||
|
"parent": "0",
|
||||||
|
"type": "IP",
|
||||||
|
"vertex": "10.0.11.0/24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r5-eth0",
|
||||||
|
"metric": "10",
|
||||||
|
"next-hop": "r3",
|
||||||
|
"parent": "r5(4)",
|
||||||
|
"type": "TE-IS",
|
||||||
|
"vertex": "r3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r5-eth1",
|
||||||
|
"metric": "10",
|
||||||
|
"next-hop": "r4",
|
||||||
|
"parent": "r5(4)",
|
||||||
|
"type": "TE-IS",
|
||||||
|
"vertex": "r4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r3",
|
||||||
|
"metric": "TE",
|
||||||
|
"next-hop": "20",
|
||||||
|
"parent": "r5-eth0",
|
||||||
|
"type": "IP",
|
||||||
|
"vertex": "10.0.20.0/24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r3",
|
||||||
|
"metric": "TE",
|
||||||
|
"next-hop": "20",
|
||||||
|
"parent": "r5-eth0",
|
||||||
|
"type": "IP",
|
||||||
|
"vertex": "10.0.10.0/24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r4",
|
||||||
|
"metric": "TE",
|
||||||
|
"next-hop": "20",
|
||||||
|
"parent": "r5-eth1",
|
||||||
|
"type": "IP",
|
||||||
|
"vertex": "10.0.21.0/24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r4",
|
||||||
|
"metric": "TE",
|
||||||
|
"next-hop": "20",
|
||||||
|
"parent": "r5-eth1",
|
||||||
|
"type": "IP",
|
||||||
|
"vertex": "10.0.11.0/24"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ipv6": [
|
||||||
|
{
|
||||||
|
"vertex": "r5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metric": "internal",
|
||||||
|
"parent": "0",
|
||||||
|
"type": "IP6",
|
||||||
|
"vertex": "2001:db8:2:1::/64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metric": "internal",
|
||||||
|
"parent": "0",
|
||||||
|
"type": "IP6",
|
||||||
|
"vertex": "2001:db8:2:2::/64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r5-eth0",
|
||||||
|
"metric": "10",
|
||||||
|
"next-hop": "r3",
|
||||||
|
"parent": "r5(4)",
|
||||||
|
"type": "TE-IS",
|
||||||
|
"vertex": "r3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r5-eth1",
|
||||||
|
"metric": "10",
|
||||||
|
"next-hop": "r4",
|
||||||
|
"parent": "r5(4)",
|
||||||
|
"type": "TE-IS",
|
||||||
|
"vertex": "r4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r3",
|
||||||
|
"metric": "internal",
|
||||||
|
"next-hop": "20",
|
||||||
|
"parent": "r5-eth0",
|
||||||
|
"type": "IP6",
|
||||||
|
"vertex": "2001:db8:1:1::/64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface": "r4",
|
||||||
|
"metric": "internal",
|
||||||
|
"next-hop": "20",
|
||||||
|
"parent": "r5-eth1",
|
||||||
|
"type": "IP6",
|
||||||
|
"vertex": "2001:db8:1:2::/64"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"level-2": {
|
||||||
|
"ipv4": [],
|
||||||
|
"ipv6": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
tests/topotests/isis-topo1-vrf/r5/zebra.conf
Executable file
13
tests/topotests/isis-topo1-vrf/r5/zebra.conf
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
hostname r5
|
||||||
|
interface r5-eth0 vrf r5-cust1
|
||||||
|
ip address 10.0.10.1/24
|
||||||
|
ipv6 address 2001:db8:2:1::1/64
|
||||||
|
!
|
||||||
|
interface r5-eth1 vrf r5-cust1
|
||||||
|
ip address 10.0.11.1/24
|
||||||
|
ipv6 address 2001:db8:2:2::1/64
|
||||||
|
!
|
||||||
|
interface lo
|
||||||
|
ip address 10.254.0.5/32
|
||||||
|
ipv6 address 2001:db8:F::5/128
|
||||||
|
!
|
100
tests/topotests/isis-topo1-vrf/test_isis_topo1_vrf.dot
Executable file
100
tests/topotests/isis-topo1-vrf/test_isis_topo1_vrf.dot
Executable file
@ -0,0 +1,100 @@
|
|||||||
|
## Color coding:
|
||||||
|
#########################
|
||||||
|
## Main FRR: #f08080 red
|
||||||
|
## Switches: #d0e0d0 gray
|
||||||
|
## RIP: #19e3d9 Cyan
|
||||||
|
## RIPng: #fcb314 dark yellow
|
||||||
|
## OSPFv2: #32b835 Green
|
||||||
|
## OSPFv3: #19e3d9 Cyan
|
||||||
|
## ISIS IPv4 #fcb314 dark yellow
|
||||||
|
## ISIS IPv6 #9a81ec purple
|
||||||
|
## BGP IPv4 #eee3d3 beige
|
||||||
|
## BGP IPv6 #fdff00 yellow
|
||||||
|
##### Colors (see http://www.color-hex.com/)
|
||||||
|
|
||||||
|
graph template {
|
||||||
|
label="isis topo1";
|
||||||
|
|
||||||
|
# Routers
|
||||||
|
r1 [
|
||||||
|
shape=doubleoctagon,
|
||||||
|
label="r1\n10.254.0.1\n2001:DB8:F::1",
|
||||||
|
fillcolor="#f08080",
|
||||||
|
style=filled,
|
||||||
|
];
|
||||||
|
r2 [
|
||||||
|
shape=doubleoctagon
|
||||||
|
label="r2\n10.254.0.2\n2001:DB8:F::2",
|
||||||
|
fillcolor="#f08080",
|
||||||
|
style=filled,
|
||||||
|
];
|
||||||
|
r3 [
|
||||||
|
shape=doubleoctagon
|
||||||
|
label="r3\n10.254.0.3\n2001:DB8:F::3",
|
||||||
|
fillcolor="#f08080",
|
||||||
|
style=filled,
|
||||||
|
];
|
||||||
|
r4 [
|
||||||
|
shape=doubleoctagon
|
||||||
|
label="r4\n10.254.0.4\n2001:DB8:F::4",
|
||||||
|
fillcolor="#f08080",
|
||||||
|
style=filled,
|
||||||
|
];
|
||||||
|
r5 [
|
||||||
|
shape=doubleoctagon
|
||||||
|
label="r5\n10.254.0.5\n2001:DB8:F::5",
|
||||||
|
fillcolor="#f08080",
|
||||||
|
style=filled,
|
||||||
|
];
|
||||||
|
|
||||||
|
# Switches
|
||||||
|
sw1 [
|
||||||
|
shape=oval,
|
||||||
|
label="sw1\n10.0.20.0/24\n2001:DB8:1:1::/64",
|
||||||
|
fillcolor="#d0e0d0",
|
||||||
|
style=filled,
|
||||||
|
];
|
||||||
|
sw2 [
|
||||||
|
shape=oval,
|
||||||
|
label="sw2\n10.0.21.0/24\n2001:DB8:1:2::/64",
|
||||||
|
fillcolor="#d0e0d0",
|
||||||
|
style=filled,
|
||||||
|
];
|
||||||
|
sw3 [
|
||||||
|
shape=oval,
|
||||||
|
label="sw3\n10.0.10.0/24\n2001:DB8:2:1::/64",
|
||||||
|
fillcolor="#d0e0d0",
|
||||||
|
style=filled,
|
||||||
|
];
|
||||||
|
sw4 [
|
||||||
|
shape=oval,
|
||||||
|
label="sw4\n10.0.11.0/24\n2001:DB8:2:2::/64",
|
||||||
|
fillcolor="#d0e0d0",
|
||||||
|
style=filled,
|
||||||
|
];
|
||||||
|
|
||||||
|
# Connections
|
||||||
|
subgraph cluster0 {
|
||||||
|
label="level 2";
|
||||||
|
|
||||||
|
r1 -- sw1 [label="eth0\n.2"];
|
||||||
|
r2 -- sw2 [label="eth0\n.2"];
|
||||||
|
}
|
||||||
|
|
||||||
|
subgraph cluster1 {
|
||||||
|
label="level 1/2";
|
||||||
|
|
||||||
|
r3 -- sw1 [label="eth0\n.1"];
|
||||||
|
r3 -- sw3 [label="eth1\n.2"];
|
||||||
|
|
||||||
|
r4 -- sw4 [label="eth1\n.2"];
|
||||||
|
r4 -- sw2 [label="eth0\n.1"];
|
||||||
|
}
|
||||||
|
|
||||||
|
subgraph cluster2 {
|
||||||
|
label="level 1";
|
||||||
|
|
||||||
|
r5 -- sw3 [label="eth0\n.1"];
|
||||||
|
r5 -- sw4 [label="eth1\n.1"];
|
||||||
|
}
|
||||||
|
}
|
BIN
tests/topotests/isis-topo1-vrf/test_isis_topo1_vrf.jpg
Executable file
BIN
tests/topotests/isis-topo1-vrf/test_isis_topo1_vrf.jpg
Executable file
Binary file not shown.
After Width: | Height: | Size: 73 KiB |
455
tests/topotests/isis-topo1-vrf/test_isis_topo1_vrf.py
Executable file
455
tests/topotests/isis-topo1-vrf/test_isis_topo1_vrf.py
Executable file
@ -0,0 +1,455 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright (c) 2020 by Niral Networks, Inc. ("Niral Networks")
|
||||||
|
# Used Copyright (c) 2018 by Network Device Education Foundation,
|
||||||
|
# Inc. ("NetDEF") in this file.
|
||||||
|
#
|
||||||
|
# Permission to use, copy, modify, and/or distribute this software
|
||||||
|
# for any purpose with or without fee is hereby granted, provided
|
||||||
|
# that the above copyright notice and this permission notice appear
|
||||||
|
# in all copies.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
|
||||||
|
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
|
||||||
|
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
|
||||||
|
# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||||
|
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||||
|
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
|
# OF THIS SOFTWARE.
|
||||||
|
#
|
||||||
|
|
||||||
|
"""
|
||||||
|
test_isis_topo1_vrf.py: Test ISIS vrf topology.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import collections
|
||||||
|
import functools
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import pytest
|
||||||
|
import platform
|
||||||
|
|
||||||
|
CWD = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
sys.path.append(os.path.join(CWD, "../"))
|
||||||
|
|
||||||
|
# pylint: disable=C0413
|
||||||
|
from lib import topotest
|
||||||
|
from lib.topogen import Topogen, TopoRouter, get_topogen
|
||||||
|
from lib.topolog import logger
|
||||||
|
|
||||||
|
from mininet.topo import Topo
|
||||||
|
|
||||||
|
|
||||||
|
class ISISTopo1(Topo):
|
||||||
|
"Simple two layer ISIS vrf topology"
|
||||||
|
|
||||||
|
def build(self, *_args, **_opts):
|
||||||
|
"Build function"
|
||||||
|
tgen = get_topogen(self)
|
||||||
|
|
||||||
|
# Add ISIS routers:
|
||||||
|
# r1 r2
|
||||||
|
# | sw1 | sw2
|
||||||
|
# r3 r4
|
||||||
|
# | |
|
||||||
|
# sw3 sw4
|
||||||
|
# \ /
|
||||||
|
# r5
|
||||||
|
for routern in range(1, 6):
|
||||||
|
tgen.add_router("r{}".format(routern))
|
||||||
|
|
||||||
|
# r1 <- sw1 -> r3
|
||||||
|
sw = tgen.add_switch("sw1")
|
||||||
|
sw.add_link(tgen.gears["r1"])
|
||||||
|
sw.add_link(tgen.gears["r3"])
|
||||||
|
|
||||||
|
# r2 <- sw2 -> r4
|
||||||
|
sw = tgen.add_switch("sw2")
|
||||||
|
sw.add_link(tgen.gears["r2"])
|
||||||
|
sw.add_link(tgen.gears["r4"])
|
||||||
|
|
||||||
|
# r3 <- sw3 -> r5
|
||||||
|
sw = tgen.add_switch("sw3")
|
||||||
|
sw.add_link(tgen.gears["r3"])
|
||||||
|
sw.add_link(tgen.gears["r5"])
|
||||||
|
|
||||||
|
# r4 <- sw4 -> r5
|
||||||
|
sw = tgen.add_switch("sw4")
|
||||||
|
sw.add_link(tgen.gears["r4"])
|
||||||
|
sw.add_link(tgen.gears["r5"])
|
||||||
|
|
||||||
|
def setup_module(mod):
|
||||||
|
"Sets up the pytest environment"
|
||||||
|
tgen = Topogen(ISISTopo1, mod.__name__)
|
||||||
|
tgen.start_topology()
|
||||||
|
|
||||||
|
logger.info("Testing with VRF Lite support")
|
||||||
|
krel = platform.release()
|
||||||
|
|
||||||
|
# May need to adjust handling of vrf traffic depending on kernel version
|
||||||
|
l3mdev_accept = 0
|
||||||
|
if (
|
||||||
|
topotest.version_cmp(krel, "4.15") >= 0
|
||||||
|
and topotest.version_cmp(krel, "4.18") <= 0
|
||||||
|
):
|
||||||
|
l3mdev_accept = 1
|
||||||
|
|
||||||
|
if topotest.version_cmp(krel, "5.0") >= 0:
|
||||||
|
l3mdev_accept = 1
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
"krel '{0}' setting net.ipv4.tcp_l3mdev_accept={1}".format(krel, l3mdev_accept)
|
||||||
|
)
|
||||||
|
|
||||||
|
cmds = [
|
||||||
|
"ip link add {0}-cust1 type vrf table 1001",
|
||||||
|
"ip link add loop1 type dummy",
|
||||||
|
"ip link set {0}-eth0 master {0}-cust1",
|
||||||
|
"ip link set {0}-eth1 master {0}-cust1",
|
||||||
|
]
|
||||||
|
|
||||||
|
# For all registered routers, load the zebra configuration file
|
||||||
|
for rname, router in tgen.routers().iteritems():
|
||||||
|
# create VRF rx-cust1 and link rx-eth0 to rx-cust1
|
||||||
|
for cmd in cmds:
|
||||||
|
output = tgen.net[rname].cmd(cmd.format(rname))
|
||||||
|
output = tgen.net[rname].cmd("sysctl -n net.ipv4.tcp_l3mdev_accept")
|
||||||
|
logger.info(
|
||||||
|
"router {0}: existing tcp_l3mdev_accept was {1}".format(rname, output)
|
||||||
|
)
|
||||||
|
|
||||||
|
if l3mdev_accept:
|
||||||
|
output = tgen.net[rname].cmd(
|
||||||
|
"sysctl -w net.ipv4.tcp_l3mdev_accept={}".format(l3mdev_accept)
|
||||||
|
)
|
||||||
|
|
||||||
|
for rname, router in tgen.routers().iteritems():
|
||||||
|
router.load_config(
|
||||||
|
TopoRouter.RD_ZEBRA,
|
||||||
|
os.path.join(CWD, "{}/zebra.conf".format(rname))
|
||||||
|
)
|
||||||
|
router.load_config(
|
||||||
|
TopoRouter.RD_ISIS,
|
||||||
|
os.path.join(CWD, "{}/isisd.conf".format(rname))
|
||||||
|
)
|
||||||
|
# After loading the configurations, this function loads configured daemons.
|
||||||
|
tgen.start_router()
|
||||||
|
|
||||||
|
has_version_20 = False
|
||||||
|
for router in tgen.routers().values():
|
||||||
|
if router.has_version("<", "4"):
|
||||||
|
has_version_20 = True
|
||||||
|
|
||||||
|
if has_version_20:
|
||||||
|
logger.info("Skipping ISIS vrf tests for FRR 2.0")
|
||||||
|
tgen.set_error("ISIS has convergence problems with IPv6")
|
||||||
|
|
||||||
|
def teardown_module(mod):
|
||||||
|
"Teardown the pytest environment"
|
||||||
|
tgen = get_topogen()
|
||||||
|
# move back rx-eth0 to default VRF
|
||||||
|
# delete rx-vrf
|
||||||
|
tgen.stop_topology()
|
||||||
|
|
||||||
|
def test_isis_convergence():
|
||||||
|
"Wait for the protocol to converge before starting to test"
|
||||||
|
tgen = get_topogen()
|
||||||
|
# Don't run this test if we have any failure.
|
||||||
|
if tgen.routers_have_failure():
|
||||||
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
|
logger.info("waiting for ISIS protocol to converge")
|
||||||
|
|
||||||
|
for rname, router in tgen.routers().iteritems():
|
||||||
|
filename = "{0}/{1}/{1}_topology.json".format(CWD, rname)
|
||||||
|
expected = json.loads(open(filename).read())
|
||||||
|
def compare_isis_topology(router, expected):
|
||||||
|
"Helper function to test ISIS vrf topology convergence."
|
||||||
|
actual = show_isis_topology(router)
|
||||||
|
|
||||||
|
return topotest.json_cmp(actual, expected)
|
||||||
|
|
||||||
|
test_func = functools.partial(compare_isis_topology, router, expected)
|
||||||
|
(result, diff) = topotest.run_and_expect(test_func, None, wait=0.5, count=120)
|
||||||
|
assert result, "ISIS did not converge on {}:\n{}".format(rname, diff)
|
||||||
|
|
||||||
|
def test_isis_route_installation():
|
||||||
|
"Check whether all expected routes are present"
|
||||||
|
tgen = get_topogen()
|
||||||
|
# Don't run this test if we have any failure.
|
||||||
|
if tgen.routers_have_failure():
|
||||||
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
|
logger.info("Checking routers for installed ISIS vrf routes")
|
||||||
|
# Check for routes in 'show ip route vrf {}-cust1 json'
|
||||||
|
for rname, router in tgen.routers().iteritems():
|
||||||
|
filename = "{0}/{1}/{1}_route.json".format(CWD, rname)
|
||||||
|
expected = json.loads(open(filename, "r").read())
|
||||||
|
actual = router.vtysh_cmd("show ip route vrf {0}-cust1 json".format(rname) , isjson=True)
|
||||||
|
# Older FRR versions don't list interfaces in some ISIS routes
|
||||||
|
if router.has_version("<", "3.1"):
|
||||||
|
for network, routes in expected.iteritems():
|
||||||
|
for route in routes:
|
||||||
|
if route["protocol"] != "isis":
|
||||||
|
continue
|
||||||
|
|
||||||
|
for nexthop in route["nexthops"]:
|
||||||
|
nexthop.pop("interfaceIndex", None)
|
||||||
|
nexthop.pop("interfaceName", None)
|
||||||
|
|
||||||
|
assertmsg = "Router '{}' routes mismatch".format(rname)
|
||||||
|
assert topotest.json_cmp(actual, expected) is None, assertmsg
|
||||||
|
|
||||||
|
|
||||||
|
def test_isis_linux_route_installation():
|
||||||
|
|
||||||
|
dist = platform.dist()
|
||||||
|
|
||||||
|
if (dist[1] == "16.04"):
|
||||||
|
pytest.skip("Kernel not supported for vrf")
|
||||||
|
|
||||||
|
"Check whether all expected routes are present and installed in the OS"
|
||||||
|
tgen = get_topogen()
|
||||||
|
# Don't run this test if we have any failure.
|
||||||
|
if tgen.routers_have_failure():
|
||||||
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
|
logger.info("Checking routers for installed ISIS vrf routes in OS")
|
||||||
|
# Check for routes in `ip route show vrf {}-cust1`
|
||||||
|
for rname, router in tgen.routers().iteritems():
|
||||||
|
filename = "{0}/{1}/{1}_route_linux.json".format(CWD, rname)
|
||||||
|
expected = json.loads(open(filename, "r").read())
|
||||||
|
actual = topotest.ip4_vrf_route(router)
|
||||||
|
|
||||||
|
# Older FRR versions install routes using different proto
|
||||||
|
if router.has_version("<", "3.1"):
|
||||||
|
for network, netoptions in expected.iteritems():
|
||||||
|
if "proto" in netoptions and netoptions["proto"] == "187":
|
||||||
|
netoptions["proto"] = "zebra"
|
||||||
|
|
||||||
|
assertmsg = "Router '{}' OS routes mismatch".format(rname)
|
||||||
|
assert topotest.json_cmp(actual, expected) is None, assertmsg
|
||||||
|
|
||||||
|
def test_isis_route6_installation():
|
||||||
|
"Check whether all expected routes are present"
|
||||||
|
tgen = get_topogen()
|
||||||
|
# Don't run this test if we have any failure.
|
||||||
|
if tgen.routers_have_failure():
|
||||||
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
|
logger.info("Checking routers for installed ISIS vrf IPv6 routes")
|
||||||
|
# Check for routes in 'show ipv6 route vrf {}-cust1 json'
|
||||||
|
for rname, router in tgen.routers().iteritems():
|
||||||
|
filename = "{0}/{1}/{1}_route6.json".format(CWD, rname)
|
||||||
|
expected = json.loads(open(filename, "r").read())
|
||||||
|
actual = router.vtysh_cmd("show ipv6 route vrf {}-cust1 json".format(rname) , isjson=True)
|
||||||
|
|
||||||
|
# Older FRR versions don't list interfaces in some ISIS routes
|
||||||
|
if router.has_version("<", "3.1"):
|
||||||
|
for network, routes in expected.iteritems():
|
||||||
|
for route in routes:
|
||||||
|
if route["protocol"] != "isis":
|
||||||
|
continue
|
||||||
|
|
||||||
|
for nexthop in route["nexthops"]:
|
||||||
|
nexthop.pop("interfaceIndex", None)
|
||||||
|
nexthop.pop("interfaceName", None)
|
||||||
|
|
||||||
|
assertmsg = "Router '{}' routes mismatch".format(rname)
|
||||||
|
assert topotest.json_cmp(actual, expected) is None, assertmsg
|
||||||
|
|
||||||
|
def test_isis_linux_route6_installation():
|
||||||
|
|
||||||
|
dist = platform.dist()
|
||||||
|
|
||||||
|
if (dist[1] == "16.04"):
|
||||||
|
pytest.skip("Kernel not supported for vrf")
|
||||||
|
|
||||||
|
"Check whether all expected routes are present and installed in the OS"
|
||||||
|
tgen = get_topogen()
|
||||||
|
# Don't run this test if we have any failure.
|
||||||
|
if tgen.routers_have_failure():
|
||||||
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
|
logger.info("Checking routers for installed ISIS vrf IPv6 routes in OS")
|
||||||
|
# Check for routes in `ip -6 route show vrf {}-cust1`
|
||||||
|
for rname, router in tgen.routers().iteritems():
|
||||||
|
filename = "{0}/{1}/{1}_route6_linux.json".format(CWD, rname)
|
||||||
|
expected = json.loads(open(filename, "r").read())
|
||||||
|
actual = topotest.ip6_vrf_route(router)
|
||||||
|
|
||||||
|
# Older FRR versions install routes using different proto
|
||||||
|
if router.has_version("<", "3.1"):
|
||||||
|
for network, netoptions in expected.iteritems():
|
||||||
|
if "proto" in netoptions and netoptions["proto"] == "187":
|
||||||
|
netoptions["proto"] = "zebra"
|
||||||
|
|
||||||
|
assertmsg = "Router '{}' OS routes mismatch".format(rname)
|
||||||
|
assert topotest.json_cmp(actual, expected) is None, assertmsg
|
||||||
|
|
||||||
|
def test_memory_leak():
|
||||||
|
"Run the memory leak test and report results."
|
||||||
|
tgen = get_topogen()
|
||||||
|
if not tgen.is_memleak_enabled():
|
||||||
|
pytest.skip("Memory leak test/report is disabled")
|
||||||
|
|
||||||
|
tgen.report_memory_leaks()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
args = ["-s"] + sys.argv[1:]
|
||||||
|
sys.exit(pytest.main(args))
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Auxiliary functions
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
def dict_merge(dct, merge_dct):
|
||||||
|
"""
|
||||||
|
Recursive dict merge. Inspired by :meth:``dict.update()``, instead of
|
||||||
|
updating only top-level keys, dict_merge recurses down into dicts nested
|
||||||
|
to an arbitrary depth, updating keys. The ``merge_dct`` is merged into
|
||||||
|
``dct``.
|
||||||
|
:param dct: dict onto which the merge is executed
|
||||||
|
:param merge_dct: dct merged into dct
|
||||||
|
:return: None
|
||||||
|
|
||||||
|
Source:
|
||||||
|
https://gist.github.com/angstwad/bf22d1822c38a92ec0a9
|
||||||
|
"""
|
||||||
|
for k, v in merge_dct.iteritems():
|
||||||
|
if (
|
||||||
|
k in dct
|
||||||
|
and isinstance(dct[k], dict)
|
||||||
|
and isinstance(merge_dct[k], collections.Mapping)
|
||||||
|
):
|
||||||
|
dict_merge(dct[k], merge_dct[k])
|
||||||
|
else:
|
||||||
|
dct[k] = merge_dct[k]
|
||||||
|
|
||||||
|
|
||||||
|
def parse_topology(lines, level):
|
||||||
|
"""
|
||||||
|
Parse the output of 'show isis topology level-X' into a Python dict.
|
||||||
|
"""
|
||||||
|
areas = {}
|
||||||
|
area = None
|
||||||
|
ipv = None
|
||||||
|
|
||||||
|
for line in lines:
|
||||||
|
area_match = re.match(r"Area (.+):", line)
|
||||||
|
if area_match:
|
||||||
|
area = area_match.group(1)
|
||||||
|
if area not in areas:
|
||||||
|
areas[area] = {level: {"ipv4": [], "ipv6": []}}
|
||||||
|
ipv = None
|
||||||
|
continue
|
||||||
|
elif area is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if re.match(r"IS\-IS paths to level-. routers that speak IPv6", line):
|
||||||
|
ipv = "ipv6"
|
||||||
|
continue
|
||||||
|
if re.match(r"IS\-IS paths to level-. routers that speak IP", line):
|
||||||
|
ipv = "ipv4"
|
||||||
|
continue
|
||||||
|
|
||||||
|
item_match = re.match(r"([^ ]+) ([^ ]+) ([^ ]+) ([^ ]+) ([^ ]+) ([^ ]+)", line)
|
||||||
|
if item_match is not None:
|
||||||
|
# Skip header
|
||||||
|
if (
|
||||||
|
item_match.group(1) == "Vertex"
|
||||||
|
and item_match.group(2) == "Type"
|
||||||
|
and item_match.group(3) == "Metric"
|
||||||
|
and item_match.group(4) == "Next-Hop"
|
||||||
|
and item_match.group(5) == "Interface"
|
||||||
|
and item_match.group(6) == "Parent"
|
||||||
|
):
|
||||||
|
continue
|
||||||
|
|
||||||
|
areas[area][level][ipv].append(
|
||||||
|
{
|
||||||
|
"vertex": item_match.group(1),
|
||||||
|
"type": item_match.group(2),
|
||||||
|
"metric": item_match.group(3),
|
||||||
|
"next-hop": item_match.group(4),
|
||||||
|
"interface": item_match.group(5),
|
||||||
|
"parent": item_match.group(6),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
|
item_match = re.match(r"([^ ]+) ([^ ]+) ([^ ]+) ([^ ]+)", line)
|
||||||
|
if item_match is not None:
|
||||||
|
areas[area][level][ipv].append(
|
||||||
|
{
|
||||||
|
"vertex": item_match.group(1),
|
||||||
|
"type": item_match.group(2),
|
||||||
|
"metric": item_match.group(3),
|
||||||
|
"parent": item_match.group(4),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
|
item_match = re.match(r"([^ ]+)", line)
|
||||||
|
if item_match is not None:
|
||||||
|
areas[area][level][ipv].append({"vertex": item_match.group(1)})
|
||||||
|
continue
|
||||||
|
|
||||||
|
return areas
|
||||||
|
|
||||||
|
|
||||||
|
def show_isis_topology(router):
|
||||||
|
"""
|
||||||
|
Get the ISIS vrf topology in a dictionary format.
|
||||||
|
|
||||||
|
Sample:
|
||||||
|
{
|
||||||
|
'area-name': {
|
||||||
|
'level-1': [
|
||||||
|
{
|
||||||
|
'vertex': 'r1'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'level-2': [
|
||||||
|
{
|
||||||
|
'vertex': '10.0.0.1/24',
|
||||||
|
'type': 'IP',
|
||||||
|
'parent': '0',
|
||||||
|
'metric': 'internal'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
'area-name-2': {
|
||||||
|
'level-2': [
|
||||||
|
{
|
||||||
|
"interface": "rX-ethY",
|
||||||
|
"metric": "Z",
|
||||||
|
"next-hop": "rA",
|
||||||
|
"parent": "rC(B)",
|
||||||
|
"type": "TE-IS",
|
||||||
|
"vertex": "rD"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
l1out = topotest.normalize_text(
|
||||||
|
router.vtysh_cmd("show isis vrf {}-cust1 topology level-1".format(router.name))
|
||||||
|
).splitlines()
|
||||||
|
l2out = topotest.normalize_text(
|
||||||
|
router.vtysh_cmd("show isis vrf {}-cust1 topology level-2".format(router.name))
|
||||||
|
).splitlines()
|
||||||
|
|
||||||
|
l1 = parse_topology(l1out, "level-1")
|
||||||
|
l2 = parse_topology(l2out, "level-2")
|
||||||
|
|
||||||
|
dict_merge(l1, l2)
|
||||||
|
return l1
|
||||||
|
|
@ -720,6 +720,49 @@ def ip4_route(node):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def ip4_vrf_route(node):
|
||||||
|
"""
|
||||||
|
Gets a structured return of the command 'ip route show vrf {0}-cust1'.
|
||||||
|
It can be used in conjuction with json_cmp() to provide accurate assert explanations.
|
||||||
|
|
||||||
|
Return example:
|
||||||
|
{
|
||||||
|
'10.0.1.0/24': {
|
||||||
|
'dev': 'eth0',
|
||||||
|
'via': '172.16.0.1',
|
||||||
|
'proto': '188',
|
||||||
|
},
|
||||||
|
'10.0.2.0/24': {
|
||||||
|
'dev': 'eth1',
|
||||||
|
'proto': 'kernel',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
output = normalize_text(
|
||||||
|
node.run("ip route show vrf {0}-cust1".format(node.name))).splitlines()
|
||||||
|
|
||||||
|
result = {}
|
||||||
|
for line in output:
|
||||||
|
columns = line.split(" ")
|
||||||
|
route = result[columns[0]] = {}
|
||||||
|
prev = None
|
||||||
|
for column in columns:
|
||||||
|
if prev == "dev":
|
||||||
|
route["dev"] = column
|
||||||
|
if prev == "via":
|
||||||
|
route["via"] = column
|
||||||
|
if prev == "proto":
|
||||||
|
# translate protocol names back to numbers
|
||||||
|
route["proto"] = proto_name_to_number(column)
|
||||||
|
if prev == "metric":
|
||||||
|
route["metric"] = column
|
||||||
|
if prev == "scope":
|
||||||
|
route["scope"] = column
|
||||||
|
prev = column
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def ip6_route(node):
|
def ip6_route(node):
|
||||||
"""
|
"""
|
||||||
Gets a structured return of the command 'ip -6 route'. It can be used in
|
Gets a structured return of the command 'ip -6 route'. It can be used in
|
||||||
@ -760,6 +803,47 @@ def ip6_route(node):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def ip6_vrf_route(node):
|
||||||
|
"""
|
||||||
|
Gets a structured return of the command 'ip -6 route show vrf {0}-cust1'.
|
||||||
|
It can be used in conjuction with json_cmp() to provide accurate assert explanations.
|
||||||
|
|
||||||
|
Return example:
|
||||||
|
{
|
||||||
|
'2001:db8:1::/64': {
|
||||||
|
'dev': 'eth0',
|
||||||
|
'proto': '188',
|
||||||
|
},
|
||||||
|
'2001:db8:2::/64': {
|
||||||
|
'dev': 'eth1',
|
||||||
|
'proto': 'kernel',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
output = normalize_text(
|
||||||
|
node.run("ip -6 route show vrf {0}-cust1".format(node.name))).splitlines()
|
||||||
|
result = {}
|
||||||
|
for line in output:
|
||||||
|
columns = line.split(" ")
|
||||||
|
route = result[columns[0]] = {}
|
||||||
|
prev = None
|
||||||
|
for column in columns:
|
||||||
|
if prev == "dev":
|
||||||
|
route["dev"] = column
|
||||||
|
if prev == "via":
|
||||||
|
route["via"] = column
|
||||||
|
if prev == "proto":
|
||||||
|
# translate protocol names back to numbers
|
||||||
|
route["proto"] = proto_name_to_number(column)
|
||||||
|
if prev == "metric":
|
||||||
|
route["metric"] = column
|
||||||
|
if prev == "pref":
|
||||||
|
route["pref"] = column
|
||||||
|
prev = column
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def ip_rules(node):
|
def ip_rules(node):
|
||||||
"""
|
"""
|
||||||
Gets a structured return of the command 'ip rule'. It can be used in
|
Gets a structured return of the command 'ip rule'. It can be used in
|
||||||
|
@ -1892,10 +1892,11 @@ DEFUNSH(VTYSH_LDPD, ldp_member_pseudowire_ifname,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DEFUNSH(VTYSH_ISISD, router_isis, router_isis_cmd, "router isis WORD",
|
DEFUNSH(VTYSH_ISISD, router_isis, router_isis_cmd,
|
||||||
|
"router isis WORD [vrf NAME]",
|
||||||
ROUTER_STR
|
ROUTER_STR
|
||||||
"ISO IS-IS\n"
|
"ISO IS-IS\n"
|
||||||
"ISO Routing area tag\n")
|
"ISO Routing area tag\n" VRF_CMD_HELP_STR)
|
||||||
{
|
{
|
||||||
vty->node = ISIS_NODE;
|
vty->node = ISIS_NODE;
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
|
@ -340,6 +340,13 @@ module frr-isisd {
|
|||||||
"Area-tag associated to this circuit.";
|
"Area-tag associated to this circuit.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
leaf vrf {
|
||||||
|
type string;
|
||||||
|
default "default";
|
||||||
|
description
|
||||||
|
"VRF NAME.";
|
||||||
|
}
|
||||||
|
|
||||||
leaf ipv4-routing {
|
leaf ipv4-routing {
|
||||||
type boolean;
|
type boolean;
|
||||||
default "false";
|
default "false";
|
||||||
@ -793,7 +800,7 @@ module frr-isisd {
|
|||||||
description
|
description
|
||||||
"Configuration of the IS-IS routing daemon.";
|
"Configuration of the IS-IS routing daemon.";
|
||||||
list instance {
|
list instance {
|
||||||
key "area-tag";
|
key "area-tag vrf";
|
||||||
description
|
description
|
||||||
"IS-IS routing instance.";
|
"IS-IS routing instance.";
|
||||||
leaf area-tag {
|
leaf area-tag {
|
||||||
@ -802,6 +809,12 @@ module frr-isisd {
|
|||||||
"Area-tag associated to this routing instance.";
|
"Area-tag associated to this routing instance.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
leaf vrf {
|
||||||
|
type string;
|
||||||
|
description
|
||||||
|
"VRF NAME.";
|
||||||
|
}
|
||||||
|
|
||||||
leaf is-type {
|
leaf is-type {
|
||||||
type level;
|
type level;
|
||||||
default "level-1-2";
|
default "level-1-2";
|
||||||
|
Loading…
Reference in New Issue
Block a user