Merge pull request #6385 from GalaxyGorilla/bfd_igp_topotest

isis: tests: Fast RIB recovery from BFD recognized link failures
This commit is contained in:
Renato Westphal 2020-07-08 14:38:09 -03:00 committed by GitHub
commit 4030687aab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 1346 additions and 20 deletions

View File

@ -143,7 +143,7 @@ BFD peers and profiles share the same BFD session configuration commands.
.. clicmd:: transmit-interval (10-60000)
The minimum transmission interval (less jitter) that this system
wants to use to send BFD control packets.
wants to use to send BFD control packets. Defaults to 300ms.
.. index:: echo-interval (10-60000)
.. clicmd:: echo-interval (10-60000)
@ -159,7 +159,7 @@ BFD peers and profiles share the same BFD session configuration commands.
It is recommended that the transmission interval of control packets
to be increased after enabling echo-mode to reduce bandwidth usage.
For example: `transmission-interval 2000`.
For example: `transmit-interval 2000`.
Echo mode is not supported on multi-hop setups (see :rfc:`5883`
section 3).
@ -246,6 +246,30 @@ The following commands are available inside the BGP configuration node.
Removes the BFD profile configuration from peer session(s).
.. _bfd-isis-peer-config:
IS-IS BFD Configuration
-----------------------
The following commands are available inside the interface configuration node.
.. index:: isis bfd
.. clicmd:: ip isis bfd
Listen for BFD events on peers created on the interface. Every time
a new neighbor is found a BFD peer is created to monitor the link
status for fast convergence.
.. index:: no isis bfd
.. clicmd:: no isis bfd
Removes any notification registration for this interface peers.
Note that there will be just one BFD session per interface. In case both
IPv4 and IPv6 support are configured then just a IPv6 based session is
created.
.. _bfd-ospf-peer-config:
OSPF BFD Configuration

View File

@ -171,14 +171,14 @@ void isis_delete_adj(void *arg)
return;
THREAD_TIMER_OFF(adj->t_expire);
if (adj->adj_state != ISIS_ADJ_DOWN) {
if (adj->adj_state != ISIS_ADJ_DOWN)
adj->adj_state = ISIS_ADJ_DOWN;
hook_call(isis_adj_state_change_hook, adj);
}
/* remove from SPF trees */
spftree_area_adj_del(adj->circuit->area, adj);
hook_call(isis_adj_state_change_hook, adj);
XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->area_addresses);
XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->ipv4_addresses);
XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->ipv6_addresses);

View File

@ -138,6 +138,8 @@ static void bfd_adj_event(struct isis_adjacency *adj, struct prefix *dst,
return;
}
adj->circuit->area->bfd_signalled_down = true;
isis_adj_state_change(&adj, ISIS_ADJ_DOWN, "bfd session went down");
}

View File

@ -1376,7 +1376,13 @@ static int lsp_refresh(struct thread *thread)
if ((area->is_type & level) == 0)
return ISIS_ERROR;
if (monotime_since(&area->last_lsp_refresh_event[level - 1], NULL) < 100000L) {
/*
* Throttle regeneration of LSPs (but not when BFD signalled a 'down'
* message)
*/
if (monotime_since(&area->last_lsp_refresh_event[level - 1], NULL)
< 100000L
&& !(area->bfd_force_spf_refresh)) {
sched_debug("ISIS (%s): Still unstable, postpone LSP L%d refresh",
area->area_tag, level);
_lsp_regenerate_schedule(area, level, 0, false,
@ -1429,7 +1435,12 @@ int _lsp_regenerate_schedule(struct isis_area *area, int level,
"ISIS (%s): Checking whether L%d needs to be scheduled",
area->area_tag, lvl);
if (area->lsp_regenerate_pending[lvl - 1]) {
if (area->lsp_regenerate_pending[lvl - 1]
&& !(area->bfd_signalled_down)) {
/*
* Note: in case of a BFD 'down' message the refresh is
* scheduled once again just to be sure
*/
struct timeval remain = thread_timer_remain(
area->t_lsp_refresh[lvl - 1]);
sched_debug(
@ -1457,7 +1468,8 @@ int _lsp_regenerate_schedule(struct isis_area *area, int level,
(long long)now);
THREAD_TIMER_OFF(area->t_lsp_refresh[lvl - 1]);
diff = now - lsp->last_generated;
if (diff < area->lsp_gen_interval[lvl - 1]) {
if (diff < area->lsp_gen_interval[lvl - 1]
&& !(area->bfd_signalled_down)) {
timeout =
1000 * (area->lsp_gen_interval[lvl - 1] - diff);
sched_debug(
@ -1465,17 +1477,21 @@ int _lsp_regenerate_schedule(struct isis_area *area, int level,
area->area_tag, timeout);
} else {
/*
* lsps are not regenerated if lsp_regenerate function
* is called
* directly. However if the lsp_regenerate call is
* queued for
* later execution it works.
* Schedule LSP refresh ASAP
*/
timeout = 100;
sched_debug(
"ISIS (%s): Last generation was more than lsp_gen_interval ago."
" Scheduling for execution in %ld ms.",
area->area_tag, timeout);
timeout = 0;
if (area->bfd_signalled_down) {
sched_debug(
"ISIS (%s): Scheduling immediately due to BDF 'down' message.",
area->area_tag);
area->bfd_signalled_down = false;
area->bfd_force_spf_refresh = true;
} else {
sched_debug(
"ISIS (%s): Last generation was more than lsp_gen_interval ago. Scheduling for execution now.",
area->area_tag);
}
}
area->lsp_regenerate_pending[lvl - 1] = 1;

View File

@ -1288,9 +1288,20 @@ int _isis_spf_schedule(struct isis_area *area, int level,
/* wait configured min_spf_interval before doing the SPF */
long timer;
if (diff >= area->min_spf_interval[level - 1]) {
/* Last run is more than min interval ago, schedule immediate run */
if (diff >= area->min_spf_interval[level - 1]
|| area->bfd_force_spf_refresh) {
/*
* Last run is more than min interval ago or BFD signalled a
* 'down' message, schedule immediate run
*/
timer = 0;
if (area->bfd_force_spf_refresh) {
zlog_debug(
"ISIS-Spf (%s) L%d SPF scheduled immediately due to BFD 'down' message",
area->area_tag, level);
area->bfd_force_spf_refresh = false;
}
} else {
timer = area->min_spf_interval[level - 1] - diff;
}

View File

@ -203,6 +203,9 @@ struct isis_area *isis_area_create(const char *area_tag)
area->lsp_refresh_arg[1].area = area;
area->lsp_refresh_arg[1].level = IS_LEVEL_2;
area->bfd_signalled_down = false;
area->bfd_force_spf_refresh = false;
QOBJ_REG(area, isis_area);

View File

@ -127,6 +127,9 @@ struct isis_area {
*/
int lsp_regenerate_pending[ISIS_LEVELS];
bool bfd_signalled_down;
bool bfd_force_spf_refresh;
struct fabricd *fabricd;
/*

View File

@ -0,0 +1,17 @@
!
debug bfd network
debug bfd peer
debug bfd zebra
!
bfd
peer 10.0.1.2 interface eth-rt2
detect-multiplier 3
receive-interval 300
transmit-interval 300
!
peer 10.0.2.2 interface eth-rt3
detect-multiplier 3
receive-interval 300
transmit-interval 300
!
!

View File

@ -0,0 +1,35 @@
log file isisd.log
log timestamp precision 3
!
hostname rt1
!
password 1
!
debug isis events
debug isis route-events
debug isis spf-events
debug isis adj-packets
debug isis lsp-sched
!
interface lo
ip router isis 1
ipv6 router isis 1
isis passive
!
interface eth-rt2
ip router isis 1
ipv6 router isis 1
isis hello-multiplier 3
isis bfd
!
interface eth-rt3
ip router isis 1
ipv6 router isis 1
isis hello-multiplier 3
isis network point-to-point
isis bfd
!
router isis 1
net 49.0000.0000.0000.0001.00
is-type level-1
!

View File

@ -0,0 +1,74 @@
{
"2.2.2.2\/32":[
{
"prefix":"2.2.2.2\/32",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"ip":"10.0.1.2",
"afi":"ipv4",
"interfaceName":"eth-rt2",
"active":true
}
]
}
],
"3.3.3.3\/32":[
{
"prefix":"3.3.3.3\/32",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"ip":"10.0.2.2",
"afi":"ipv4",
"interfaceName":"eth-rt3",
"active":true
}
]
}
],
"4.4.4.4\/32":[
{
"prefix":"4.4.4.4\/32",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"ip":"10.0.2.2",
"afi":"ipv4",
"interfaceName":"eth-rt3",
"active":true
}
]
}
],
"5.5.5.5\/32":[
{
"prefix":"5.5.5.5\/32",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"ip":"10.0.1.2",
"afi":"ipv4",
"interfaceName":"eth-rt2",
"active":true
}
]
}
]
}

View File

@ -0,0 +1,70 @@
{
"::ffff:202:202\/128":[
{
"prefix":"::ffff:202:202\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"afi":"ipv6",
"interfaceName":"eth-rt2",
"active":true
}
]
}
],
"::ffff:303:303\/128":[
{
"prefix":"::ffff:303:303\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"afi":"ipv6",
"interfaceName":"eth-rt3",
"active":true
}
]
}
],
"::ffff:404:404\/128":[
{
"prefix":"::ffff:404:404\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"afi":"ipv6",
"interfaceName":"eth-rt3",
"active":true
}
]
}
],
"::ffff:505:505\/128":[
{
"prefix":"::ffff:505:505\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"afi":"ipv6",
"interfaceName":"eth-rt2",
"active":true
}
]
}
]
}

View File

@ -0,0 +1,16 @@
[
{
"peer": "10.0.2.2",
"interface": "eth-rt3",
"status": "up",
"diagnostic": "ok",
"remote-diagnostic": "ok"
},
{
"peer": "10.0.1.2",
"interface": "eth-rt2",
"status": "up",
"diagnostic": "ok",
"remote-diagnostic": "ok"
}
]

View File

@ -0,0 +1,16 @@
[
{
"peer": "10.0.2.2",
"interface": "eth-rt3",
"status": "up",
"diagnostic": "ok",
"remote-diagnostic": "ok"
},
{
"peer": "10.0.1.2",
"interface": "eth-rt2",
"status": "up",
"diagnostic": "ok",
"remote-diagnostic": "ok"
}
]

View File

@ -0,0 +1,9 @@
[
{
"peer": "10.0.2.2",
"interface": "eth-rt3",
"status": "up",
"diagnostic": "ok",
"remote-diagnostic": "ok"
}
]

View File

@ -0,0 +1,9 @@
[
{
"peer": "10.0.1.2",
"interface": "eth-rt2",
"status": "up",
"diagnostic": "ok",
"remote-diagnostic": "ok"
}
]

View File

@ -0,0 +1,74 @@
{
"2.2.2.2\/32":[
{
"prefix":"2.2.2.2\/32",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"ip":"10.0.1.2",
"afi":"ipv4",
"interfaceName":"eth-rt2",
"active":true
}
]
}
],
"3.3.3.3\/32":[
{
"prefix":"3.3.3.3\/32",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"ip":"10.0.2.2",
"afi":"ipv4",
"interfaceName":"eth-rt3",
"active":true
}
]
}
],
"4.4.4.4\/32":[
{
"prefix":"4.4.4.4\/32",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"ip":"10.0.2.2",
"afi":"ipv4",
"interfaceName":"eth-rt3",
"active":true
}
]
}
],
"5.5.5.5\/32":[
{
"prefix":"5.5.5.5\/32",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"ip":"10.0.1.2",
"afi":"ipv4",
"interfaceName":"eth-rt2",
"active":true
}
]
}
]
}

View File

@ -0,0 +1,74 @@
{
"2.2.2.2\/32":[
{
"prefix":"2.2.2.2\/32",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"ip":"10.0.2.2",
"afi":"ipv4",
"interfaceName":"eth-rt3",
"active":true
}
]
}
],
"3.3.3.3\/32":[
{
"prefix":"3.3.3.3\/32",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"ip":"10.0.2.2",
"afi":"ipv4",
"interfaceName":"eth-rt3",
"active":true
}
]
}
],
"4.4.4.4\/32":[
{
"prefix":"4.4.4.4\/32",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"ip":"10.0.2.2",
"afi":"ipv4",
"interfaceName":"eth-rt3",
"active":true
}
]
}
],
"5.5.5.5\/32":[
{
"prefix":"5.5.5.5\/32",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"ip":"10.0.2.2",
"afi":"ipv4",
"interfaceName":"eth-rt3",
"active":true
}
]
}
]
}

View File

@ -0,0 +1,74 @@
{
"2.2.2.2\/32":[
{
"prefix":"2.2.2.2\/32",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"ip":"10.0.1.2",
"afi":"ipv4",
"interfaceName":"eth-rt2",
"active":true
}
]
}
],
"3.3.3.3\/32":[
{
"prefix":"3.3.3.3\/32",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"ip":"10.0.1.2",
"afi":"ipv4",
"interfaceName":"eth-rt2",
"active":true
}
]
}
],
"4.4.4.4\/32":[
{
"prefix":"4.4.4.4\/32",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"ip":"10.0.1.2",
"afi":"ipv4",
"interfaceName":"eth-rt2",
"active":true
}
]
}
],
"5.5.5.5\/32":[
{
"prefix":"5.5.5.5\/32",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"ip":"10.0.1.2",
"afi":"ipv4",
"interfaceName":"eth-rt2",
"active":true
}
]
}
]
}

View File

@ -0,0 +1,70 @@
{
"::ffff:202:202\/128":[
{
"prefix":"::ffff:202:202\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"afi":"ipv6",
"interfaceName":"eth-rt2",
"active":true
}
]
}
],
"::ffff:303:303\/128":[
{
"prefix":"::ffff:303:303\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"afi":"ipv6",
"interfaceName":"eth-rt3",
"active":true
}
]
}
],
"::ffff:404:404\/128":[
{
"prefix":"::ffff:404:404\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"afi":"ipv6",
"interfaceName":"eth-rt3",
"active":true
}
]
}
],
"::ffff:505:505\/128":[
{
"prefix":"::ffff:505:505\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"afi":"ipv6",
"interfaceName":"eth-rt2",
"active":true
}
]
}
]
}

View File

@ -0,0 +1,70 @@
{
"::ffff:202:202\/128":[
{
"prefix":"::ffff:202:202\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"afi":"ipv6",
"interfaceName":"eth-rt3",
"active":true
}
]
}
],
"::ffff:303:303\/128":[
{
"prefix":"::ffff:303:303\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"afi":"ipv6",
"interfaceName":"eth-rt3",
"active":true
}
]
}
],
"::ffff:404:404\/128":[
{
"prefix":"::ffff:404:404\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"afi":"ipv6",
"interfaceName":"eth-rt3",
"active":true
}
]
}
],
"::ffff:505:505\/128":[
{
"prefix":"::ffff:505:505\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"afi":"ipv6",
"interfaceName":"eth-rt3",
"active":true
}
]
}
]
}

View File

@ -0,0 +1,70 @@
{
"::ffff:202:202\/128":[
{
"prefix":"::ffff:202:202\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"afi":"ipv6",
"interfaceName":"eth-rt2",
"active":true
}
]
}
],
"::ffff:303:303\/128":[
{
"prefix":"::ffff:303:303\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"afi":"ipv6",
"interfaceName":"eth-rt2",
"active":true
}
]
}
],
"::ffff:404:404\/128":[
{
"prefix":"::ffff:404:404\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"afi":"ipv6",
"interfaceName":"eth-rt2",
"active":true
}
]
}
],
"::ffff:505:505\/128":[
{
"prefix":"::ffff:505:505\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
"installed":true,
"nexthops":[
{
"fib":true,
"afi":"ipv6",
"interfaceName":"eth-rt2",
"active":true
}
]
}
]
}

View File

@ -0,0 +1,25 @@
log file zebra.log
log timestamp precision 3
!
hostname rt1
!
debug zebra kernel
debug zebra packet
debug zebra events
debug zebra rib
!
interface lo
ip address 1.1.1.1/32
ipv6 address ::ffff:0101:0101/128
!
interface eth-rt2
ip address 10.0.1.1/24
!
interface eth-rt3
ip address 10.0.2.1/24
!
ip forwarding
ipv6 forwarding
!
line vty
!

View File

@ -0,0 +1,12 @@
!
debug bfd network
debug bfd peer
debug bfd zebra
!
bfd
peer 10.0.1.1 interface eth-rt1
detect-multiplier 3
receive-interval 300
transmit-interval 300
!
!

View File

@ -0,0 +1,30 @@
log file isisd.log
!
hostname rt2
!
password 1
!
debug isis events
debug isis route-events
debug isis spf-events
!
interface lo
ip router isis 1
ipv6 router isis 1
isis passive
!
interface eth-rt1
ip router isis 1
ipv6 router isis 1
isis hello-multiplier 3
isis bfd
!
interface eth-rt5
ip router isis 1
ipv6 router isis 1
isis hello-multiplier 3
!
router isis 1
net 49.0000.0000.0000.0002.00
is-type level-1
!

View File

@ -0,0 +1,9 @@
[
{
"peer": "10.0.1.1",
"interface": "eth-rt1",
"status": "up",
"diagnostic": "ok",
"remote-diagnostic": "ok"
}
]

View File

@ -0,0 +1,22 @@
log file zebra.log
!
hostname rt2
!
debug zebra kernel
debug zebra packet
!
interface lo
ip address 2.2.2.2/32
ipv6 address ::ffff:0202:0202/128
!
interface eth-rt1
ip address 10.0.1.2/24
!
interface eth-rt5
ip address 10.0.3.1/24
!
ip forwarding
ipv6 forwarding
!
line vty
!

View File

@ -0,0 +1,12 @@
!
debug bfd network
debug bfd peer
debug bfd zebra
!
bfd
peer 10.0.2.1 interface eth-rt1
detect-multiplier 3
receive-interval 300
transmit-interval 300
!
!

View File

@ -0,0 +1,32 @@
log file isisd.log
!
hostname rt3
!
password 1
!
debug isis events
debug isis route-events
debug isis spf-events
!
interface lo
ip router isis 1
ipv6 router isis 1
isis passive
!
interface eth-rt1
ip router isis 1
ipv6 router isis 1
isis hello-multiplier 3
isis network point-to-point
isis bfd
!
interface eth-rt4
ip router isis 1
ipv6 router isis 1
isis hello-multiplier 3
!
router isis 1
net 49.0000.0000.0000.0003.00
is-type level-1
!

View File

@ -0,0 +1,9 @@
[
{
"peer": "10.0.2.1",
"interface": "eth-rt1",
"status": "up",
"diagnostic": "ok",
"remote-diagnostic": "ok"
}
]

View File

@ -0,0 +1,22 @@
log file zebra.log
!
hostname rt3
!
debug zebra kernel
debug zebra packet
!
interface lo
ip address 3.3.3.3/32
ipv6 address ::ffff:0303:0303/128
!
interface eth-rt1
ip address 10.0.2.2/24
!
interface eth-rt4
ip address 10.0.4.1/24
!
ip forwarding
ipv6 forwarding
!
line vty
!

View File

@ -0,0 +1,5 @@
!
debug bfd network
debug bfd peer
debug bfd zebra
!

View File

@ -0,0 +1,29 @@
log file isisd.log
!
hostname rt4
!
password 1
!
debug isis events
debug isis route-events
debug isis spf-events
!
interface lo
ip router isis 1
ipv6 router isis 1
isis passive
!
interface eth-rt3
ip router isis 1
ipv6 router isis 1
isis hello-multiplier 3
!
interface eth-rt5
ip router isis 1
ipv6 router isis 1
isis hello-multiplier 3
!
router isis 1
net 49.0000.0000.0000.0004.00
is-type level-1
!

View File

@ -0,0 +1,22 @@
log file zebra.log
!
hostname rt4
!
debug zebra kernel
debug zebra packet
!
interface lo
ip address 4.4.4.4/32
ipv6 address ::ffff:0404:0404/128
!
interface eth-rt3
ip address 10.0.4.2/24
!
interface eth-rt5
ip address 10.0.5.1/24
!
ip forwarding
ipv6 forwarding
!
line vty
!

View File

@ -0,0 +1,5 @@
!
debug bfd network
debug bfd peer
debug bfd zebra
!

View File

@ -0,0 +1,29 @@
log file isisd.log
!
hostname rt5
!
password 1
!
debug isis events
debug isis route-events
debug isis spf-events
!
interface lo
ip router isis 1
ipv6 router isis 1
isis passive
!
interface eth-rt2
ip router isis 1
ipv6 router isis 1
isis hello-multiplier 3
!
interface eth-rt4
ip router isis 1
ipv6 router isis 1
isis hello-multiplier 3
!
router isis 1
net 49.0000.0000.0000.0005.00
is-type level-1
!

View File

@ -0,0 +1,22 @@
log file zebra.log
!
hostname rt5
!
debug zebra kernel
debug zebra packet
!
interface lo
ip address 5.5.5.5/32
ipv6 address ::ffff:0505:0505/128
!
interface eth-rt2
ip address 10.0.3.2/24
!
interface eth-rt4
ip address 10.0.5.2/24
!
ip forwarding
ipv6 forwarding
!
line vty
!

View File

@ -0,0 +1,304 @@
#!/usr/bin/env python
#
# test_bfd_isis_topo1.py
# Part of NetDEF Topology Tests
#
# Copyright (c) 2020 by
# Network Device Education Foundation, Inc. ("NetDEF")
#
# 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_bfd_isis_topo1.py:
+---------+
| |
eth-rt2 (.1) | RT1 | eth-rt3 (.1)
+----------+ 1.1.1.1 +----------+
| | | |
| +---------+ |
| |
| 10.0.2.0/24 |
| |
| eth-rt1 | (.2)
| 10.0.1.0/24 +----+----+
| | |
| | RT3 |
| | 3.3.3.3 |
| | |
(.2) | eth-rt1 +----+----+
+----+----+ eth-rt4 | (.1)
| | |
| RT2 | |
| 2.2.2.2 | 10.0.4.0/24 |
| | |
+----+----+ |
(.1) | eth-rt5 eth-rt3 | (.2)
| +----+----+
| | |
| | RT4 |
| | 4.4.4.4 |
| | |
| +----+----+
| 10.0.3.0/24 eth-rt5 | (.1)
| |
| |
| 10.0.5.0/24 |
| |
| +---------+ |
| | | |
+----------+ RT5 +----------+
eth-rt2 (.2) | 5.5.5.5 | eth-rt4 (.2)
| |
+---------+
"""
import os
import sys
import pytest
import json
import re
from time import sleep
from time import time
from functools import partial
# Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
# pylint: disable=C0413
# Import topogen and topotest helpers
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
# Required to instantiate the topology builder class.
from mininet.topo import Topo
class TemplateTopo(Topo):
"Test topology builder"
def build(self, *_args, **_opts):
"Build function"
tgen = get_topogen(self)
#
# Define FRR Routers
#
for router in ["rt1", "rt2", "rt3", "rt4", "rt5"]:
tgen.add_router(router)
#
# Define connections
#
switch = tgen.add_switch("s1")
switch.add_link(tgen.gears["rt1"], nodeif="eth-rt2")
switch.add_link(tgen.gears["rt2"], nodeif="eth-rt1")
switch = tgen.add_switch("s2")
switch.add_link(tgen.gears["rt1"], nodeif="eth-rt3")
switch.add_link(tgen.gears["rt3"], nodeif="eth-rt1")
switch = tgen.add_switch("s3")
switch.add_link(tgen.gears["rt2"], nodeif="eth-rt5")
switch.add_link(tgen.gears["rt5"], nodeif="eth-rt2")
switch = tgen.add_switch("s4")
switch.add_link(tgen.gears["rt3"], nodeif="eth-rt4")
switch.add_link(tgen.gears["rt4"], nodeif="eth-rt3")
switch = tgen.add_switch("s5")
switch.add_link(tgen.gears["rt4"], nodeif="eth-rt5")
switch.add_link(tgen.gears["rt5"], nodeif="eth-rt4")
def setup_module(mod):
"Sets up the pytest environment"
tgen = Topogen(TemplateTopo, mod.__name__)
tgen.start_topology()
router_list = tgen.routers()
# For all registered routers, load the zebra configuration file
for rname, router in router_list.iteritems():
router.load_config(
TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
)
router.load_config(
TopoRouter.RD_BFD, os.path.join(CWD, "{}/bfdd.conf".format(rname))
)
router.load_config(
TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname))
)
tgen.start_router()
def teardown_module(mod):
"Teardown the pytest environment"
tgen = get_topogen()
# This function tears down the whole topology.
tgen.stop_topology()
def print_cmd_result(rname, command):
print(get_topogen().gears[rname].vtysh_cmd(command, isjson=False))
def router_compare_json_output(rname, command, reference, count=120, wait=0.5):
"Compare router JSON output"
logger.info('Comparing router "%s" "%s" output', rname, command)
tgen = get_topogen()
filename = "{}/{}/{}".format(CWD, rname, reference)
expected = json.loads(open(filename).read())
# Run test function until we get an result. Wait at most 60 seconds.
test_func = partial(topotest.router_json_cmp, tgen.gears[rname], command, expected)
_, diff = topotest.run_and_expect(test_func, None, count=count, wait=wait)
assertmsg = '"{}" JSON output mismatches the expected result'.format(rname)
assert diff is None, assertmsg
## TEST STEPS
def test_rib_isis_step1():
logger.info("Test (step 1): verify RIB (IPv4 and IPv6) for IS-IS")
tgen = get_topogen()
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
router_compare_json_output(
"rt1", "show ip route isis json", "step1/show_ip_route.ref"
)
router_compare_json_output(
"rt1", "show ipv6 route isis json", "step1/show_ipv6_route.ref"
)
def test_bfd_isis_sessions_step2():
logger.info("Test (step 2): verify BFD peers for IS-IS")
tgen = get_topogen()
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
# BFD is just used on three routers
for rt in ["rt1", "rt2", "rt3"]:
router_compare_json_output(
rt, "show bfd peers json", "step2/show_bfd_peers.ref"
)
def test_bfd_isis_interface_failure_rt2_step3():
logger.info("Test (step 2): check failover handling when RT2 goes down")
tgen = get_topogen()
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
# Let's kill the interface on rt2 and see what happens with the RIB and BFD on rt1
tgen.gears["rt2"].link_enable("eth-rt1", enabled=False)
# By default BFD provides a recovery time of 900ms plus jitter, so let's wait
# initial 2 seconds to let the CI not suffer.
# TODO: add check for array size
sleep(2)
router_compare_json_output(
"rt1", "show ip route isis json", "step3/show_ip_route_rt2_down.ref", 1, 0
)
router_compare_json_output(
"rt1", "show ipv6 route isis json", "step3/show_ipv6_route_rt2_down.ref", 1, 0
)
router_compare_json_output(
"rt1", "show bfd peers json", "step3/show_bfd_peers_rt2_down.ref", 1, 0
)
# Check recovery, this can take some time
tgen.gears["rt2"].link_enable("eth-rt1", enabled=True)
router_compare_json_output(
"rt1", "show ip route isis json", "step3/show_ip_route_healthy.ref"
)
router_compare_json_output(
"rt1", "show ipv6 route isis json", "step3/show_ipv6_route_healthy.ref"
)
router_compare_json_output(
"rt1", "show bfd peers json", "step3/show_bfd_peers_healthy.ref"
)
def test_bfd_isis_interface_failure_rt3_step3():
logger.info("Test (step 2): check failover handling when RT2 goes down")
tgen = get_topogen()
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
# Let's kill the interface on rt3 and see what happens with the RIB and BFD on rt1
tgen.gears["rt3"].link_enable("eth-rt1", enabled=False)
# By default BFD provides a recovery time of 900ms plus jitter, so let's wait
# initial 2 seconds to let the CI not suffer.
# TODO: add check for array size
sleep(2)
router_compare_json_output(
"rt1", "show ip route isis json", "step3/show_ip_route_rt3_down.ref", 1, 0
)
router_compare_json_output(
"rt1", "show ipv6 route isis json", "step3/show_ipv6_route_rt3_down.ref", 1, 0
)
router_compare_json_output(
"rt1", "show bfd peers json", "step3/show_bfd_peers_rt3_down.ref", 1, 0
)
# Check recovery, this can take some time
tgen.gears["rt3"].link_enable("eth-rt1", enabled=True)
router_compare_json_output(
"rt1", "show ip route isis json", "step3/show_ip_route_healthy.ref"
)
router_compare_json_output(
"rt1", "show ipv6 route isis json", "step3/show_ipv6_route_healthy.ref"
)
router_compare_json_output(
"rt1", "show bfd peers json", "step3/show_bfd_peers_healthy.ref"
)
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))