summaryrefslogtreecommitdiffstats
path: root/tests/topotests/nhrp_redundancy
diff options
context:
space:
mode:
Diffstat (limited to 'tests/topotests/nhrp_redundancy')
-rw-r--r--tests/topotests/nhrp_redundancy/r1/nhrp_cache.json40
-rw-r--r--tests/topotests/nhrp_redundancy/r1/nhrp_route.json48
-rw-r--r--tests/topotests/nhrp_redundancy/r1/nhrpd.conf9
-rw-r--r--tests/topotests/nhrp_redundancy/r1/zebra.conf12
-rw-r--r--tests/topotests/nhrp_redundancy/r2/nhrp_cache.json40
-rw-r--r--tests/topotests/nhrp_redundancy/r2/nhrp_route.json48
-rw-r--r--tests/topotests/nhrp_redundancy/r2/nhrpd.conf9
-rw-r--r--tests/topotests/nhrp_redundancy/r2/zebra.conf12
-rw-r--r--tests/topotests/nhrp_redundancy/r3/nhrp_cache.json40
-rw-r--r--tests/topotests/nhrp_redundancy/r3/nhrp_route.json48
-rw-r--r--tests/topotests/nhrp_redundancy/r3/nhrpd.conf9
-rw-r--r--tests/topotests/nhrp_redundancy/r3/zebra.conf12
-rw-r--r--tests/topotests/nhrp_redundancy/r4/nhrp_cache.json51
-rw-r--r--tests/topotests/nhrp_redundancy/r4/nhrp_route.json71
-rw-r--r--tests/topotests/nhrp_redundancy/r4/nhrp_route_shortcut.json118
-rw-r--r--tests/topotests/nhrp_redundancy/r4/nhrpd.conf11
-rw-r--r--tests/topotests/nhrp_redundancy/r4/zebra.conf16
-rw-r--r--tests/topotests/nhrp_redundancy/r5/nhrp_cache.json51
-rw-r--r--tests/topotests/nhrp_redundancy/r5/nhrp_route.json71
-rw-r--r--tests/topotests/nhrp_redundancy/r5/nhrpd.conf11
-rw-r--r--tests/topotests/nhrp_redundancy/r5/zebra.conf16
-rw-r--r--tests/topotests/nhrp_redundancy/r6/zebra.conf7
-rw-r--r--tests/topotests/nhrp_redundancy/r7/zebra.conf4
-rw-r--r--tests/topotests/nhrp_redundancy/test_nhrp_redundancy.dot103
-rw-r--r--tests/topotests/nhrp_redundancy/test_nhrp_redundancy.py423
25 files changed, 1280 insertions, 0 deletions
diff --git a/tests/topotests/nhrp_redundancy/r1/nhrp_cache.json b/tests/topotests/nhrp_redundancy/r1/nhrp_cache.json
new file mode 100644
index 0000000..a94dd9f
--- /dev/null
+++ b/tests/topotests/nhrp_redundancy/r1/nhrp_cache.json
@@ -0,0 +1,40 @@
+{
+ "attr": {
+ "entriesCount": 3
+ },
+ "table": [
+ {
+ "interface": "r1-gre0",
+ "type": "dynamic",
+ "protocol": "176.16.1.4",
+ "nbma": "192.168.2.4",
+ "claimed_nbma": "192.168.2.4",
+ "used": false,
+ "timeout": true,
+ "auth": false,
+ "identity": ""
+ },
+ {
+ "interface": "r1-gre0",
+ "type": "local",
+ "protocol": "176.16.1.1",
+ "nbma": "192.168.1.1",
+ "claimed_nbma": "192.168.1.1",
+ "used": false,
+ "timeout": false,
+ "auth": false,
+ "identity": "-"
+ },
+ {
+ "interface": "r1-gre0",
+ "type": "dynamic",
+ "protocol": "176.16.1.5",
+ "nbma": "192.168.2.5",
+ "claimed_nbma": "192.168.2.5",
+ "used": false,
+ "timeout": true,
+ "auth": false,
+ "identity": ""
+ }
+ ]
+} \ No newline at end of file
diff --git a/tests/topotests/nhrp_redundancy/r1/nhrp_route.json b/tests/topotests/nhrp_redundancy/r1/nhrp_route.json
new file mode 100644
index 0000000..b5f3e29
--- /dev/null
+++ b/tests/topotests/nhrp_redundancy/r1/nhrp_route.json
@@ -0,0 +1,48 @@
+{
+ "176.16.1.4\/32": [
+ {
+ "prefix": "176.16.1.4\/32",
+ "protocol": "nhrp",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 10,
+ "metric": 0,
+ "installed": true,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "r1-gre0",
+ "active": true
+ }
+ ]
+ }
+ ],
+ "176.16.1.5\/32": [
+ {
+ "prefix": "176.16.1.5\/32",
+ "protocol": "nhrp",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 10,
+ "metric": 0,
+ "installed": true,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "r1-gre0",
+ "active": true
+ }
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/tests/topotests/nhrp_redundancy/r1/nhrpd.conf b/tests/topotests/nhrp_redundancy/r1/nhrpd.conf
new file mode 100644
index 0000000..ad48ce3
--- /dev/null
+++ b/tests/topotests/nhrp_redundancy/r1/nhrpd.conf
@@ -0,0 +1,9 @@
+!debug nhrp all
+nhrp nflog-group 1
+interface r1-gre0
+ ip nhrp holdtime 10
+ ip nhrp network-id 42
+ ip nhrp registration no-unique
+ ip nhrp redirect
+ tunnel source r1-eth0
+exit
diff --git a/tests/topotests/nhrp_redundancy/r1/zebra.conf b/tests/topotests/nhrp_redundancy/r1/zebra.conf
new file mode 100644
index 0000000..0f11563
--- /dev/null
+++ b/tests/topotests/nhrp_redundancy/r1/zebra.conf
@@ -0,0 +1,12 @@
+ip forwarding
+interface r1-eth0
+ ip address 192.168.1.1/24
+!
+ip route 192.168.2.0/24 192.168.1.6
+interface r1-gre0
+ ip address 176.16.1.1/32
+ no link-detect
+ ipv6 nd suppress-ra
+!
+ip route 4.4.4.0/24 176.16.1.4
+ip route 5.5.5.0/24 176.16.1.5
diff --git a/tests/topotests/nhrp_redundancy/r2/nhrp_cache.json b/tests/topotests/nhrp_redundancy/r2/nhrp_cache.json
new file mode 100644
index 0000000..91557a1
--- /dev/null
+++ b/tests/topotests/nhrp_redundancy/r2/nhrp_cache.json
@@ -0,0 +1,40 @@
+{
+ "attr": {
+ "entriesCount": 3
+ },
+ "table": [
+ {
+ "interface": "r2-gre0",
+ "type": "local",
+ "protocol": "176.16.1.2",
+ "nbma": "192.168.1.2",
+ "claimed_nbma": "192.168.1.2",
+ "used": false,
+ "timeout": false,
+ "auth": false,
+ "identity": "-"
+ },
+ {
+ "interface": "r2-gre0",
+ "type": "dynamic",
+ "protocol": "176.16.1.4",
+ "nbma": "192.168.2.4",
+ "claimed_nbma": "192.168.2.4",
+ "used": false,
+ "timeout": true,
+ "auth": false,
+ "identity": ""
+ },
+ {
+ "interface": "r2-gre0",
+ "type": "dynamic",
+ "protocol": "176.16.1.5",
+ "nbma": "192.168.2.5",
+ "claimed_nbma": "192.168.2.5",
+ "used": false,
+ "timeout": true,
+ "auth": false,
+ "identity": ""
+ }
+ ]
+} \ No newline at end of file
diff --git a/tests/topotests/nhrp_redundancy/r2/nhrp_route.json b/tests/topotests/nhrp_redundancy/r2/nhrp_route.json
new file mode 100644
index 0000000..f1fa6e5
--- /dev/null
+++ b/tests/topotests/nhrp_redundancy/r2/nhrp_route.json
@@ -0,0 +1,48 @@
+{
+ "176.16.1.4\/32": [
+ {
+ "prefix": "176.16.1.4\/32",
+ "protocol": "nhrp",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 10,
+ "metric": 0,
+ "installed": true,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "r2-gre0",
+ "active": true
+ }
+ ]
+ }
+ ],
+ "176.16.1.5\/32": [
+ {
+ "prefix": "176.16.1.5\/32",
+ "protocol": "nhrp",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 10,
+ "metric": 0,
+ "installed": true,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "r2-gre0",
+ "active": true
+ }
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/tests/topotests/nhrp_redundancy/r2/nhrpd.conf b/tests/topotests/nhrp_redundancy/r2/nhrpd.conf
new file mode 100644
index 0000000..4d63f07
--- /dev/null
+++ b/tests/topotests/nhrp_redundancy/r2/nhrpd.conf
@@ -0,0 +1,9 @@
+!debug nhrp all
+nhrp nflog-group 1
+interface r2-gre0
+ ip nhrp holdtime 10
+ ip nhrp network-id 42
+ ip nhrp registration no-unique
+ ip nhrp redirect
+ tunnel source r2-eth0
+exit
diff --git a/tests/topotests/nhrp_redundancy/r2/zebra.conf b/tests/topotests/nhrp_redundancy/r2/zebra.conf
new file mode 100644
index 0000000..1a9c4ff
--- /dev/null
+++ b/tests/topotests/nhrp_redundancy/r2/zebra.conf
@@ -0,0 +1,12 @@
+ip forwarding
+interface r2-eth0
+ ip address 192.168.1.2/24
+!
+ip route 192.168.2.0/24 192.168.1.6
+interface r2-gre0
+ ip address 176.16.1.2/32
+ no link-detect
+ ipv6 nd suppress-ra
+!
+ip route 4.4.4.0/24 176.16.1.4
+ip route 5.5.5.0/24 176.16.1.5
diff --git a/tests/topotests/nhrp_redundancy/r3/nhrp_cache.json b/tests/topotests/nhrp_redundancy/r3/nhrp_cache.json
new file mode 100644
index 0000000..ef3ab69
--- /dev/null
+++ b/tests/topotests/nhrp_redundancy/r3/nhrp_cache.json
@@ -0,0 +1,40 @@
+{
+ "attr": {
+ "entriesCount": 3
+ },
+ "table": [
+ {
+ "interface": "r3-gre0",
+ "type": "dynamic",
+ "protocol": "176.16.1.4",
+ "nbma": "192.168.2.4",
+ "claimed_nbma": "192.168.2.4",
+ "used": false,
+ "timeout": true,
+ "auth": false,
+ "identity": ""
+ },
+ {
+ "interface": "r3-gre0",
+ "type": "local",
+ "protocol": "176.16.1.3",
+ "nbma": "192.168.1.3",
+ "claimed_nbma": "192.168.1.3",
+ "used": false,
+ "timeout": false,
+ "auth": false,
+ "identity": "-"
+ },
+ {
+ "interface": "r3-gre0",
+ "type": "dynamic",
+ "protocol": "176.16.1.5",
+ "nbma": "192.168.2.5",
+ "claimed_nbma": "192.168.2.5",
+ "used": false,
+ "timeout": true,
+ "auth": false,
+ "identity": ""
+ }
+ ]
+} \ No newline at end of file
diff --git a/tests/topotests/nhrp_redundancy/r3/nhrp_route.json b/tests/topotests/nhrp_redundancy/r3/nhrp_route.json
new file mode 100644
index 0000000..3d548c0
--- /dev/null
+++ b/tests/topotests/nhrp_redundancy/r3/nhrp_route.json
@@ -0,0 +1,48 @@
+{
+ "176.16.1.4\/32": [
+ {
+ "prefix": "176.16.1.4\/32",
+ "protocol": "nhrp",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 10,
+ "metric": 0,
+ "installed": true,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "r3-gre0",
+ "active": true
+ }
+ ]
+ }
+ ],
+ "176.16.1.5\/32": [
+ {
+ "prefix": "176.16.1.5\/32",
+ "protocol": "nhrp",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 10,
+ "metric": 0,
+ "installed": true,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "r3-gre0",
+ "active": true
+ }
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/tests/topotests/nhrp_redundancy/r3/nhrpd.conf b/tests/topotests/nhrp_redundancy/r3/nhrpd.conf
new file mode 100644
index 0000000..87cc216
--- /dev/null
+++ b/tests/topotests/nhrp_redundancy/r3/nhrpd.conf
@@ -0,0 +1,9 @@
+!debug nhrp all
+nhrp nflog-group 1
+interface r3-gre0
+ ip nhrp holdtime 10
+ ip nhrp network-id 42
+ ip nhrp registration no-unique
+ ip nhrp redirect
+ tunnel source r3-eth0
+exit
diff --git a/tests/topotests/nhrp_redundancy/r3/zebra.conf b/tests/topotests/nhrp_redundancy/r3/zebra.conf
new file mode 100644
index 0000000..980cfbc
--- /dev/null
+++ b/tests/topotests/nhrp_redundancy/r3/zebra.conf
@@ -0,0 +1,12 @@
+ip forwarding
+interface r3-eth0
+ ip address 192.168.1.3/24
+!
+ip route 192.168.2.0/24 192.168.1.6
+interface r3-gre0
+ ip address 176.16.1.3/32
+ no link-detect
+ ipv6 nd suppress-ra
+!
+ip route 4.4.4.0/24 176.16.1.4
+ip route 5.5.5.0/24 176.16.1.5 \ No newline at end of file
diff --git a/tests/topotests/nhrp_redundancy/r4/nhrp_cache.json b/tests/topotests/nhrp_redundancy/r4/nhrp_cache.json
new file mode 100644
index 0000000..f87ebcf
--- /dev/null
+++ b/tests/topotests/nhrp_redundancy/r4/nhrp_cache.json
@@ -0,0 +1,51 @@
+{
+ "attr": {
+ "entriesCount": 4
+ },
+ "table": [
+ {
+ "interface": "r4-gre0",
+ "type": "nhs",
+ "protocol": "176.16.1.2",
+ "nbma": "192.168.1.2",
+ "claimed_nbma": "192.168.1.2",
+ "used": false,
+ "timeout": true,
+ "auth": false,
+ "identity": ""
+ },
+ {
+ "interface": "r4-gre0",
+ "type": "local",
+ "protocol": "176.16.1.4",
+ "nbma": "192.168.2.4",
+ "claimed_nbma": "192.168.2.4",
+ "used": false,
+ "timeout": false,
+ "auth": false,
+ "identity": "-"
+ },
+ {
+ "interface": "r4-gre0",
+ "type": "nhs",
+ "protocol": "176.16.1.3",
+ "nbma": "192.168.1.3",
+ "claimed_nbma": "192.168.1.3",
+ "used": false,
+ "timeout": true,
+ "auth": false,
+ "identity": ""
+ },
+ {
+ "interface": "r4-gre0",
+ "type": "nhs",
+ "protocol": "176.16.1.1",
+ "nbma": "192.168.1.1",
+ "claimed_nbma": "192.168.1.1",
+ "used": false,
+ "timeout": true,
+ "auth": false,
+ "identity": ""
+ }
+ ]
+} \ No newline at end of file
diff --git a/tests/topotests/nhrp_redundancy/r4/nhrp_route.json b/tests/topotests/nhrp_redundancy/r4/nhrp_route.json
new file mode 100644
index 0000000..4f1faee
--- /dev/null
+++ b/tests/topotests/nhrp_redundancy/r4/nhrp_route.json
@@ -0,0 +1,71 @@
+{
+ "176.16.1.1\/32": [
+ {
+ "prefix": "176.16.1.1\/32",
+ "protocol": "nhrp",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 10,
+ "metric": 0,
+ "installed": true,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "r4-gre0",
+ "active": true
+ }
+ ]
+ }
+ ],
+ "176.16.1.2\/32": [
+ {
+ "prefix": "176.16.1.2\/32",
+ "protocol": "nhrp",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 10,
+ "metric": 0,
+ "installed": true,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "r4-gre0",
+ "active": true
+ }
+ ]
+ }
+ ],
+ "176.16.1.3\/32": [
+ {
+ "prefix": "176.16.1.3\/32",
+ "protocol": "nhrp",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 10,
+ "metric": 0,
+ "installed": true,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "r4-gre0",
+ "active": true
+ }
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/tests/topotests/nhrp_redundancy/r4/nhrp_route_shortcut.json b/tests/topotests/nhrp_redundancy/r4/nhrp_route_shortcut.json
new file mode 100644
index 0000000..f8efff2
--- /dev/null
+++ b/tests/topotests/nhrp_redundancy/r4/nhrp_route_shortcut.json
@@ -0,0 +1,118 @@
+{
+ "5.5.5.5\/32": [
+ {
+ "prefix": "5.5.5.5\/32",
+ "protocol": "nhrp",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 10,
+ "metric": 0,
+ "installed": true,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "fib": true,
+ "ip": "176.16.1.5",
+ "afi": "ipv4",
+ "interfaceName": "r4-gre0",
+ "active": true
+ }
+ ]
+ }
+ ],
+ "176.16.1.1\/32": [
+ {
+ "prefix": "176.16.1.1\/32",
+ "protocol": "nhrp",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 10,
+ "metric": 0,
+ "installed": true,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "r4-gre0",
+ "active": true
+ }
+ ]
+ }
+ ],
+ "176.16.1.2\/32": [
+ {
+ "prefix": "176.16.1.2\/32",
+ "protocol": "nhrp",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 10,
+ "metric": 0,
+ "installed": true,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "r4-gre0",
+ "active": true
+ }
+ ]
+ }
+ ],
+ "176.16.1.3\/32": [
+ {
+ "prefix": "176.16.1.3\/32",
+ "protocol": "nhrp",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 10,
+ "metric": 0,
+ "installed": true,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "r4-gre0",
+ "active": true
+ }
+ ]
+ }
+ ],
+ "176.16.1.5\/32": [
+ {
+ "prefix": "176.16.1.5\/32",
+ "protocol": "nhrp",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 10,
+ "metric": 0,
+ "installed": true,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "r4-gre0",
+ "active": true
+ }
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/tests/topotests/nhrp_redundancy/r4/nhrpd.conf b/tests/topotests/nhrp_redundancy/r4/nhrpd.conf
new file mode 100644
index 0000000..8a52f33
--- /dev/null
+++ b/tests/topotests/nhrp_redundancy/r4/nhrpd.conf
@@ -0,0 +1,11 @@
+!debug nhrp all
+interface r4-gre0
+ ip nhrp holdtime 10
+ ip nhrp network-id 42
+ ip nhrp registration no-unique
+ ip nhrp nhs dynamic nbma 192.168.1.1
+ ip nhrp nhs dynamic nbma 192.168.1.2
+ ip nhrp nhs dynamic nbma 192.168.1.3
+ ip nhrp shortcut
+ tunnel source r4-eth0
+exit
diff --git a/tests/topotests/nhrp_redundancy/r4/zebra.conf b/tests/topotests/nhrp_redundancy/r4/zebra.conf
new file mode 100644
index 0000000..e4a9a6f
--- /dev/null
+++ b/tests/topotests/nhrp_redundancy/r4/zebra.conf
@@ -0,0 +1,16 @@
+ip forwarding
+interface r4-eth0
+ ip address 192.168.2.4/24
+!
+ip route 192.168.1.0/24 192.168.2.6
+interface r4-gre0
+ ip address 176.16.1.4/32
+ no link-detect
+ ipv6 nd suppress-ra
+!
+interface r4-eth1
+ ip address 4.4.4.4/24
+!
+ip route 0.0.0.0/0 176.16.1.1 50
+ip route 0.0.0.0/0 176.16.1.2 60
+ip route 0.0.0.0/0 176.16.1.3 70 \ No newline at end of file
diff --git a/tests/topotests/nhrp_redundancy/r5/nhrp_cache.json b/tests/topotests/nhrp_redundancy/r5/nhrp_cache.json
new file mode 100644
index 0000000..bc041c6
--- /dev/null
+++ b/tests/topotests/nhrp_redundancy/r5/nhrp_cache.json
@@ -0,0 +1,51 @@
+{
+ "attr": {
+ "entriesCount": 4
+ },
+ "table": [
+ {
+ "interface": "r5-gre0",
+ "type": "nhs",
+ "protocol": "176.16.1.2",
+ "nbma": "192.168.1.2",
+ "claimed_nbma": "192.168.1.2",
+ "used": false,
+ "timeout": true,
+ "auth": false,
+ "identity": ""
+ },
+ {
+ "interface": "r5-gre0",
+ "type": "nhs",
+ "protocol": "176.16.1.3",
+ "nbma": "192.168.1.3",
+ "claimed_nbma": "192.168.1.3",
+ "used": false,
+ "timeout": true,
+ "auth": false,
+ "identity": ""
+ },
+ {
+ "interface": "r5-gre0",
+ "type": "nhs",
+ "protocol": "176.16.1.1",
+ "nbma": "192.168.1.1",
+ "claimed_nbma": "192.168.1.1",
+ "used": false,
+ "timeout": true,
+ "auth": false,
+ "identity": ""
+ },
+ {
+ "interface": "r5-gre0",
+ "type": "local",
+ "protocol": "176.16.1.5",
+ "nbma": "192.168.2.5",
+ "claimed_nbma": "192.168.2.5",
+ "used": false,
+ "timeout": false,
+ "auth": false,
+ "identity": "-"
+ }
+ ]
+} \ No newline at end of file
diff --git a/tests/topotests/nhrp_redundancy/r5/nhrp_route.json b/tests/topotests/nhrp_redundancy/r5/nhrp_route.json
new file mode 100644
index 0000000..1d1c16f
--- /dev/null
+++ b/tests/topotests/nhrp_redundancy/r5/nhrp_route.json
@@ -0,0 +1,71 @@
+{
+ "176.16.1.1\/32": [
+ {
+ "prefix": "176.16.1.1\/32",
+ "protocol": "nhrp",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 10,
+ "metric": 0,
+ "installed": true,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "r5-gre0",
+ "active": true
+ }
+ ]
+ }
+ ],
+ "176.16.1.2\/32": [
+ {
+ "prefix": "176.16.1.2\/32",
+ "protocol": "nhrp",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 10,
+ "metric": 0,
+ "installed": true,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "r5-gre0",
+ "active": true
+ }
+ ]
+ }
+ ],
+ "176.16.1.3\/32": [
+ {
+ "prefix": "176.16.1.3\/32",
+ "protocol": "nhrp",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 10,
+ "metric": 0,
+ "installed": true,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "r5-gre0",
+ "active": true
+ }
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/tests/topotests/nhrp_redundancy/r5/nhrpd.conf b/tests/topotests/nhrp_redundancy/r5/nhrpd.conf
new file mode 100644
index 0000000..7241ed5
--- /dev/null
+++ b/tests/topotests/nhrp_redundancy/r5/nhrpd.conf
@@ -0,0 +1,11 @@
+!debug nhrp all
+interface r5-gre0
+ ip nhrp holdtime 10
+ ip nhrp network-id 42
+ ip nhrp nhs dynamic nbma 192.168.1.1
+ ip nhrp nhs dynamic nbma 192.168.1.2
+ ip nhrp nhs dynamic nbma 192.168.1.3
+ ip nhrp registration no-unique
+ ip nhrp shortcut
+ tunnel source r5-eth0
+exit
diff --git a/tests/topotests/nhrp_redundancy/r5/zebra.conf b/tests/topotests/nhrp_redundancy/r5/zebra.conf
new file mode 100644
index 0000000..9b1e1c0
--- /dev/null
+++ b/tests/topotests/nhrp_redundancy/r5/zebra.conf
@@ -0,0 +1,16 @@
+ip forwarding
+interface r5-eth0
+ ip address 192.168.2.5/24
+!
+ip route 192.168.1.0/24 192.168.2.6
+interface r5-gre0
+ ip address 176.16.1.5/32
+ no link-detect
+ ipv6 nd suppress-ra
+!
+interface r5-eth1
+ ip address 5.5.5.5/24
+!
+ip route 0.0.0.0/0 176.16.1.1 50
+ip route 0.0.0.0/0 176.16.1.2 60
+ip route 0.0.0.0/0 176.16.1.3 70
diff --git a/tests/topotests/nhrp_redundancy/r6/zebra.conf b/tests/topotests/nhrp_redundancy/r6/zebra.conf
new file mode 100644
index 0000000..63a37cd
--- /dev/null
+++ b/tests/topotests/nhrp_redundancy/r6/zebra.conf
@@ -0,0 +1,7 @@
+ip forwarding
+interface r6-eth0
+ ip address 192.168.1.6/24
+!
+interface r6-eth1
+ ip address 192.168.2.6/24
+exit
diff --git a/tests/topotests/nhrp_redundancy/r7/zebra.conf b/tests/topotests/nhrp_redundancy/r7/zebra.conf
new file mode 100644
index 0000000..5747b40
--- /dev/null
+++ b/tests/topotests/nhrp_redundancy/r7/zebra.conf
@@ -0,0 +1,4 @@
+interface r7-eth0
+ ip address 4.4.4.7/24
+!
+ip route 0.0.0.0/0 4.4.4.4
diff --git a/tests/topotests/nhrp_redundancy/test_nhrp_redundancy.dot b/tests/topotests/nhrp_redundancy/test_nhrp_redundancy.dot
new file mode 100644
index 0000000..c169436
--- /dev/null
+++ b/tests/topotests/nhrp_redundancy/test_nhrp_redundancy.dot
@@ -0,0 +1,103 @@
+## 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="nhrp-topo-redundant-nhs";
+
+ # Routers
+ r1 [
+ shape=doubleoctagon,
+ label="NHS 1",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r2 [
+ shape=doubleoctagon
+ label="NHS 2",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r3 [
+ shape=doubleoctagon
+ label="NHS 3",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r4 [
+ shape=doubleoctagon
+ label="NHC 1",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r5 [
+ shape=doubleoctagon
+ label="NHC 2",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r6 [
+ shape=doubleoctagon
+ label="router",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r7 [
+ shape=doubleoctagon
+ label="host",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+
+ # Switches
+ sw1 [
+ shape=oval,
+ label="sw1\n192.168.1.0/24",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+ sw2 [
+ shape=oval,
+ label="sw2\n192.168.2.0/24",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+ sw3 [
+ shape=oval,
+ label="sw3\n4.4.4.0/24",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+ sw4 [
+ shape=oval,
+ label="sw4\n5.5.5.0/24",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+
+ # Connections
+ r1 -- sw1 [label="eth0"];
+ r2 -- sw1 [label="eth0"];
+ r3 -- sw1 [label="eth0"];
+ r6 -- sw1 [label="eth0"];
+
+ r4 -- sw2 [label="eth0"];
+ r5 -- sw2 [label="eth0"];
+ r6 -- sw2 [label="eth1"];
+
+ r4 -- sw3 [label="eth1"];
+ r7 -- sw3 [label="eth0"];
+
+ r5 -- sw4 [label="eth1"];
+
+}
diff --git a/tests/topotests/nhrp_redundancy/test_nhrp_redundancy.py b/tests/topotests/nhrp_redundancy/test_nhrp_redundancy.py
new file mode 100644
index 0000000..81a22eb
--- /dev/null
+++ b/tests/topotests/nhrp_redundancy/test_nhrp_redundancy.py
@@ -0,0 +1,423 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# test_nhrp_redundancy.py
+#
+# Copyright 2024, LabN Consulting, L.L.C.
+# Dave LeRoy
+#
+
+import os
+import sys
+import json
+from time import sleep
+from functools import partial
+import pytest
+
+# 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
+from lib.common_config import (
+ required_linux_kernel_version,
+ shutdown_bringup_interface,
+ retry,
+)
+
+"""
+test_nhrp_redundancy.py: Test NHS redundancy for NHRP
+"""
+
+TOPOLOGY = """
++------------+ +------------+ +------------+
+| | | | | |
+| | | | | |
+| NHS 1 | | NHS 2 | | NHS 3 |
+| | | | | |
++-----+------+ +-----+------+ +-----+------+
+ |.1 |.2 |.3
+ | | |
+ | | 192.168.1.0/24 |
+------+-------------------------------+------------------+-------------+------
+ |
+ |.6
+ GRE P2MP between all NHS and NHC +-----+------+
+ 172.16.1.x/32 | |
+ | |
+ | Router |
+ | |
+ +-----+------+
+ |
+ |
+ ---------+----------------+-------------+------
+ | 192.168.2.0/24 |
+ | |
+ | |.4 |.5
++------------+ | +-------+----+ +------+-----+ |
+| | | | | | | |
+| | +--------+ | | | |
+| Host |.7 | | NHC 1 | | NHC 2 +-----+5.5.5.0/24
+| +---------+ | | | | |
++------------+ | +------------+ +------------+ |
+ | |
+ 4.4.4.0/24
+"""
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# Required to instantiate the topology builder class.
+
+pytestmark = [pytest.mark.nhrpd]
+
+
+def build_topo(tgen):
+ "Build function"
+
+ # Create 7 routers
+ for routern in range(1, 8):
+ tgen.add_router("r{}".format(routern))
+
+ # Interconnect routers 1, 2, 3, 6
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+ switch.add_link(tgen.gears["r3"])
+ switch.add_link(tgen.gears["r6"])
+
+ # Interconnect routers 4, 5, 6
+ switch = tgen.add_switch("s2")
+ switch.add_link(tgen.gears["r4"])
+ switch.add_link(tgen.gears["r5"])
+ switch.add_link(tgen.gears["r6"])
+
+ # Connect router 4, 7
+ switch = tgen.add_switch("s3")
+ switch.add_link(tgen.gears["r4"])
+ switch.add_link(tgen.gears["r7"])
+
+ # Connect router 5
+ switch = tgen.add_switch("s4")
+ switch.add_link(tgen.gears["r5"])
+
+
+def _populate_iface():
+ tgen = get_topogen()
+ cmds_tot_hub = [
+ "ip tunnel add {0}-gre0 mode gre ttl 64 key 42 dev {0}-eth0 local 192.168.1.{1} remote 0.0.0.0",
+ "ip link set dev {0}-gre0 up",
+ "echo 0 > /proc/sys/net/ipv4/ip_forward_use_pmtu",
+ "echo 1 > /proc/sys/net/ipv6/conf/{0}-eth0/disable_ipv6",
+ "echo 1 > /proc/sys/net/ipv6/conf/{0}-gre0/disable_ipv6",
+ "iptables -A FORWARD -i {0}-gre0 -o {0}-gre0 -m hashlimit --hashlimit-upto 4/minute --hashlimit-burst 1 --hashlimit-mode srcip,dstip --hashlimit-srcmask 24 --hashlimit-dstmask 24 --hashlimit-name loglimit-0 -j NFLOG --nflog-group 1 --nflog-range 128",
+ ]
+
+ cmds_tot = [
+ "ip tunnel add {0}-gre0 mode gre ttl 64 key 42 dev {0}-eth0 local 192.168.2.{1} remote 0.0.0.0",
+ "ip link set dev {0}-gre0 up",
+ "echo 0 > /proc/sys/net/ipv4/ip_forward_use_pmtu",
+ "echo 1 > /proc/sys/net/ipv6/conf/{0}-eth0/disable_ipv6",
+ "echo 1 > /proc/sys/net/ipv6/conf/{0}-gre0/disable_ipv6",
+ ]
+
+ for cmd in cmds_tot_hub:
+ # Router 1
+ input = cmd.format("r1", "1")
+ logger.info("input: " + input)
+ output = tgen.net["r1"].cmd(input)
+ logger.info("output: " + output)
+
+ # Router 2
+ input = cmd.format("r2", "2")
+ logger.info("input: " + input)
+ output = tgen.net["r2"].cmd(input)
+ logger.info("output: " + output)
+
+ # Router 3
+ input = cmd.format("r3", "3")
+ logger.info("input: " + input)
+ output = tgen.net["r3"].cmd(input)
+ logger.info("output: " + output)
+
+ for cmd in cmds_tot:
+ input = cmd.format("r4", "4")
+ logger.info("input: " + input)
+ output = tgen.net["r4"].cmd(input)
+ logger.info("output: " + output)
+
+ input = cmd.format("r5", "5")
+ logger.info("input: " + input)
+ output = tgen.net["r5"].cmd(input)
+ logger.info("output: " + output)
+
+
+def _verify_iptables():
+ tgen = get_topogen()
+ # Verify iptables is installed. Required for shortcuts
+ rc, _, _ = tgen.net["r1"].cmd_status("iptables")
+ return False if rc == 127 else True
+
+
+def setup_module(mod):
+ logger.info("NHRP Redundant NHS:\n {}".format(TOPOLOGY))
+
+ result = required_linux_kernel_version("5.0")
+ if result is not True:
+ pytest.skip("Kernel requirements are not met")
+
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ # Starting Routers
+ router_list = tgen.routers()
+ _populate_iface()
+
+ for rname, router in router_list.items():
+ router.load_config(
+ TopoRouter.RD_ZEBRA,
+ os.path.join(CWD, "{}/zebra.conf".format(rname)),
+ )
+ if rname in ("r1", "r2", "r3", "r4", "r5"):
+ router.load_config(
+ TopoRouter.RD_NHRP, os.path.join(CWD, "{}/nhrpd.conf".format(rname))
+ )
+
+ # Initialize all routers.
+ tgen.start_router()
+
+
+def teardown_module(_mod):
+ "Teardown the pytest environment"
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_protocols_convergence():
+ """
+ Assert that all protocols have converged before checking for the NHRP
+ statuses as they depend on it.
+ """
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Checking NHRP cache and IPv4 routes for convergence")
+ router_list = tgen.routers()
+
+ # Check NHRP cache on servers and clients
+ for rname, router in router_list.items():
+
+ json_file = "{}/{}/nhrp_cache.json".format(CWD, router.name)
+ if not os.path.isfile(json_file):
+ logger.info("skipping file {}".format(json_file))
+ continue
+
+ expected = json.loads(open(json_file).read())
+ test_func = partial(
+ topotest.router_json_cmp, router, "show ip nhrp cache json", expected
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=40, wait=0.5)
+
+ output = router.vtysh_cmd("show ip nhrp cache")
+ logger.info(output)
+
+ assertmsg = '"{}" JSON output mismatches'.format(router.name)
+ assert result is None, assertmsg
+
+ # Check NHRP IPV4 routes on servers and clients
+ for rname, router in router_list.items():
+
+ json_file = "{}/{}/nhrp_route.json".format(CWD, router.name)
+ if not os.path.isfile(json_file):
+ logger.info("skipping file {}".format(json_file))
+ continue
+
+ expected = json.loads(open(json_file).read())
+ test_func = partial(
+ topotest.router_json_cmp, router, "show ip route nhrp json", expected
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=40, wait=0.5)
+
+ output = router.vtysh_cmd("show ip route nhrp")
+ logger.info(output)
+
+ assertmsg = '"{}" JSON output mismatches'.format(router.name)
+ assert result is None, assertmsg
+
+ # Test connectivity from 1 NHRP server to all clients
+ pingrouter = tgen.gears["r1"]
+ logger.info("Check Ping IPv4 from R1 to R4 = 176.16.1.4)")
+ output = pingrouter.run("ping 176.16.1.4 -f -c 1000")
+ logger.info(output)
+ if "1000 packets transmitted, 1000 received" not in output:
+ assertmsg = "expected ping IPv4 from R1 to R4 should be ok"
+ assert 0, assertmsg
+ else:
+ logger.info("Check Ping IPv4 from R1 to R4 OK")
+
+ logger.info("Check Ping IPv4 from R1 to R5 = 176.16.1.5)")
+ output = pingrouter.run("ping 176.16.1.5 -f -c 1000")
+ logger.info(output)
+ if "1000 packets transmitted, 1000 received" not in output:
+ assertmsg = "expected ping IPv4 from R1 to R5 should be ok"
+ assert 0, assertmsg
+ else:
+ logger.info("Check Ping IPv4 from R1 to R5 OK")
+
+ # Test connectivity from 1 NHRP client to all servers
+ pingrouter = tgen.gears["r4"]
+ logger.info("Check Ping IPv4 from R4 to R1 = 176.16.1.1)")
+ output = pingrouter.run("ping 176.16.1.1 -f -c 1000")
+ logger.info(output)
+ if "1000 packets transmitted, 1000 received" not in output:
+ assertmsg = "expected ping IPv4 from R4 to R1 should be ok"
+ assert 0, assertmsg
+ else:
+ logger.info("Check Ping IPv4 from R4 to R1 OK")
+
+ logger.info("Check Ping IPv4 from R4 to R2 = 176.16.1.2)")
+ output = pingrouter.run("ping 176.16.1.2 -f -c 1000")
+ logger.info(output)
+ if "1000 packets transmitted, 1000 received" not in output:
+ assertmsg = "expected ping IPv4 from R4 to R2 should be ok"
+ assert 0, assertmsg
+ else:
+ logger.info("Check Ping IPv4 from R4 to R2 OK")
+
+ logger.info("Check Ping IPv4 from R4 to R3 = 176.16.1.3)")
+ output = pingrouter.run("ping 176.16.1.3 -f -c 1000")
+ logger.info(output)
+ if "1000 packets transmitted, 1000 received" not in output:
+ assertmsg = "expected ping IPv4 from R4 to R3 should be ok"
+ assert 0, assertmsg
+ else:
+ logger.info("Check Ping IPv4 from R4 to R3 OK")
+
+
+@retry(retry_timeout=30, initial_wait=5)
+def verify_shortcut_path():
+ """
+ Verifying that traffic flows through shortcut path
+ """
+ tgen = get_topogen()
+ pingrouter = tgen.gears["r7"]
+ logger.info("Check Ping IPv4 from R7 to R5 = 5.5.5.5")
+
+ output = pingrouter.run("ping 5.5.5.5 -f -c 1000")
+ logger.info(output)
+ if "1000 packets transmitted, 1000 received" not in output:
+ assertmsg = "expected ping IPv4 from R7 to R5 should be ok"
+ assert 0, assertmsg
+ else:
+ logger.info("Check Ping IPv4 from R7 to R5 OK")
+
+
+def test_redundancy_shortcut():
+ """
+ Assert that if shortcut created and then NHS goes down, there is no traffic disruption
+ Stop traffic and verify next time traffic started, shortcut is initiated by backup NHS
+ """
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ if not _verify_iptables():
+ pytest.skip("iptables not installed")
+
+ logger.info("Testing NHRP shortcuts with redundant servers")
+
+ # Verify R4 nhrp routes before shortcut creation
+ router = tgen.gears["r4"]
+ json_file = "{}/{}/nhrp_route.json".format(CWD, router.name)
+ assertmsg = "No nhrp_route file found"
+ assert os.path.isfile(json_file), assertmsg
+
+ expected = json.loads(open(json_file).read())
+ test_func = partial(
+ topotest.router_json_cmp, router, "show ip route nhrp json", expected
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=40, wait=0.5)
+
+ output = router.vtysh_cmd("show ip route nhrp")
+ logger.info(output)
+
+ assertmsg = '"{}" JSON output mismatches'.format(router.name)
+ assert result is None, assertmsg
+
+ # Initiate shortcut by pinging between clients
+ pingrouter = tgen.gears["r7"]
+ logger.info("Check Ping IPv4 from R7 to R5 via shortcut = 5.5.5.5")
+
+ output = pingrouter.run("ping 5.5.5.5 -f -c 1000")
+ logger.info(output)
+ if "1000 packets transmitted, 1000 received" not in output:
+ assertmsg = "expected ping IPv4 from R7 to R5 via shortcut should be ok"
+ assert 0, assertmsg
+ else:
+ logger.info("Check Ping IPv4 from R7 to R5 via shortcut OK")
+
+ # Now check that NHRP shortcut route installed
+ json_file = "{}/{}/nhrp_route_shortcut.json".format(CWD, router.name)
+ assertmsg = "No nhrp_route file found"
+ assert os.path.isfile(json_file), assertmsg
+
+ expected = json.loads(open(json_file).read())
+ test_func = partial(
+ topotest.router_json_cmp, router, "show ip route nhrp json", expected
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=40, wait=0.5)
+
+ output = router.vtysh_cmd("show ip route nhrp")
+ logger.info(output)
+
+ assertmsg = '"{}" JSON output mismatches'.format(router.name)
+ assert result is None, assertmsg
+
+ # Bring down primary GRE interface and verify shortcut is not disturbed
+ logger.info("Bringing down R1, primary NHRP server.")
+ shutdown_bringup_interface(tgen, "r1", "r1-gre0", False)
+
+ # Verify shortcut is still active
+ pingrouter = tgen.gears["r7"]
+ logger.info("Check Ping IPv4 from R7 to R5 via shortcut = 5.5.5.5")
+
+ output = pingrouter.run("ping 5.5.5.5 -f -c 1000")
+ logger.info(output)
+ if "1000 packets transmitted, 1000 received" not in output:
+ assertmsg = "expected ping IPv4 from R7 to R5 via shortcut should be ok"
+ assert 0, assertmsg
+ else:
+ logger.info("Check Ping IPv4 from R7 to R5 via shortcut OK")
+
+ # Now verify shortcut is purged with lack of traffic
+ json_file = "{}/{}/nhrp_route.json".format(CWD, router.name)
+ assertmsg = "No nhrp_route file found"
+ assert os.path.isfile(json_file), assertmsg
+
+ expected = json.loads(open(json_file).read())
+ test_func = partial(
+ topotest.router_json_cmp, router, "show ip route nhrp json", expected
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=40, wait=0.5)
+
+ output = router.vtysh_cmd("show ip route nhrp")
+ logger.info(output)
+
+ assertmsg = '"{}" JSON output mismatches'.format(router.name)
+ assert result 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))