summaryrefslogtreecommitdiffstats
path: root/tests/topotests/bgp_features
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--tests/topotests/bgp_features/r1/bgp_delayopen_neighbor.json6
-rw-r--r--tests/topotests/bgp_features/r1/bgp_delayopen_summary_established.json11
-rw-r--r--tests/topotests/bgp_features/r1/bgp_delayopen_summary_shutdown.json11
-rw-r--r--tests/topotests/bgp_features/r1/bgp_shutdown_summary.json19
-rw-r--r--tests/topotests/bgp_features/r1/bgp_summary.json27
-rw-r--r--tests/topotests/bgp_features/r1/bgpd.conf41
-rw-r--r--tests/topotests/bgp_features/r1/ip_route.json364
-rw-r--r--tests/topotests/bgp_features/r1/ip_route_norib.json281
-rw-r--r--tests/topotests/bgp_features/r1/ospf6d.conf21
-rw-r--r--tests/topotests/bgp_features/r1/ospf_neighbor.json16
-rw-r--r--tests/topotests/bgp_features/r1/ospfd.conf26
-rw-r--r--tests/topotests/bgp_features/r1/show_bgp.json350
-rw-r--r--tests/topotests/bgp_features/r1/show_bgp_metric_test.json57
-rw-r--r--tests/topotests/bgp_features/r1/zebra.conf28
-rw-r--r--tests/topotests/bgp_features/r2/bgp_delayopen_neighbor.json6
-rw-r--r--tests/topotests/bgp_features/r2/bgp_delayopen_summary_connect.json11
-rw-r--r--tests/topotests/bgp_features/r2/bgp_delayopen_summary_established.json11
-rw-r--r--tests/topotests/bgp_features/r2/bgp_delayopen_summary_shutdown.json11
-rw-r--r--tests/topotests/bgp_features/r2/bgp_shutdown_summary.json19
-rw-r--r--tests/topotests/bgp_features/r2/bgp_summary.json27
-rw-r--r--tests/topotests/bgp_features/r2/bgpd.conf41
-rw-r--r--tests/topotests/bgp_features/r2/ospf6d.conf21
-rw-r--r--tests/topotests/bgp_features/r2/ospf_neighbor.json16
-rw-r--r--tests/topotests/bgp_features/r2/ospfd.conf26
-rw-r--r--tests/topotests/bgp_features/r2/show_bgp.json349
-rw-r--r--tests/topotests/bgp_features/r2/show_bgp_metric_test.json57
-rw-r--r--tests/topotests/bgp_features/r2/zebra.conf28
-rw-r--r--tests/topotests/bgp_features/r3/bgp_summary.json0
-rw-r--r--tests/topotests/bgp_features/r3/ospf6d.conf21
-rw-r--r--tests/topotests/bgp_features/r3/ospf_neighbor.json16
-rw-r--r--tests/topotests/bgp_features/r3/ospfd.conf26
-rw-r--r--tests/topotests/bgp_features/r3/zebra.conf23
-rw-r--r--tests/topotests/bgp_features/r4/bgp_delayopen_summary_established.json11
-rw-r--r--tests/topotests/bgp_features/r4/bgp_delayopen_summary_shutdown.json11
-rw-r--r--tests/topotests/bgp_features/r4/bgp_shutdown_summary.json14
-rw-r--r--tests/topotests/bgp_features/r4/bgp_summary.json18
-rw-r--r--tests/topotests/bgp_features/r4/bgpd.conf34
-rw-r--r--tests/topotests/bgp_features/r4/show_bgp_metric_test.json27
-rw-r--r--tests/topotests/bgp_features/r4/zebra.conf18
-rw-r--r--tests/topotests/bgp_features/r5/bgp_delayopen_neighbor.json6
-rw-r--r--tests/topotests/bgp_features/r5/bgp_delayopen_summary_connect.json11
-rw-r--r--tests/topotests/bgp_features/r5/bgp_delayopen_summary_established.json11
-rw-r--r--tests/topotests/bgp_features/r5/bgp_delayopen_summary_shutdown.json11
-rw-r--r--tests/topotests/bgp_features/r5/bgp_summary.json19
-rw-r--r--tests/topotests/bgp_features/r5/bgpd.conf34
-rw-r--r--tests/topotests/bgp_features/r5/show_bgp_metric_test.json27
-rw-r--r--tests/topotests/bgp_features/r5/zebra.conf18
-rw-r--r--tests/topotests/bgp_features/test_bgp_features.dot83
-rw-r--r--tests/topotests/bgp_features/test_bgp_features.pdfbin0 -> 20710 bytes
-rw-r--r--tests/topotests/bgp_features/test_bgp_features.py1102
50 files changed, 3422 insertions, 0 deletions
diff --git a/tests/topotests/bgp_features/r1/bgp_delayopen_neighbor.json b/tests/topotests/bgp_features/r1/bgp_delayopen_neighbor.json
new file mode 100644
index 0000000..5caaeab
--- /dev/null
+++ b/tests/topotests/bgp_features/r1/bgp_delayopen_neighbor.json
@@ -0,0 +1,6 @@
+{
+ "192.168.101.2":{
+ "remoteAs":65100,
+ "bgpTimerDelayOpenTimeMsecs":240000
+ }
+}
diff --git a/tests/topotests/bgp_features/r1/bgp_delayopen_summary_established.json b/tests/topotests/bgp_features/r1/bgp_delayopen_summary_established.json
new file mode 100644
index 0000000..3ab3588
--- /dev/null
+++ b/tests/topotests/bgp_features/r1/bgp_delayopen_summary_established.json
@@ -0,0 +1,11 @@
+{
+"ipv4Unicast":{
+ "as":65000,
+ "peers":{
+ "192.168.101.2":{
+ "remoteAs":65100,
+ "state":"Established"
+ }
+ }
+}
+}
diff --git a/tests/topotests/bgp_features/r1/bgp_delayopen_summary_shutdown.json b/tests/topotests/bgp_features/r1/bgp_delayopen_summary_shutdown.json
new file mode 100644
index 0000000..9a41236
--- /dev/null
+++ b/tests/topotests/bgp_features/r1/bgp_delayopen_summary_shutdown.json
@@ -0,0 +1,11 @@
+{
+"ipv4Unicast":{
+ "as":65000,
+ "peers":{
+ "192.168.101.2":{
+ "remoteAs":65100,
+ "state":"Idle (Admin)"
+ }
+ }
+}
+}
diff --git a/tests/topotests/bgp_features/r1/bgp_shutdown_summary.json b/tests/topotests/bgp_features/r1/bgp_shutdown_summary.json
new file mode 100644
index 0000000..d986071
--- /dev/null
+++ b/tests/topotests/bgp_features/r1/bgp_shutdown_summary.json
@@ -0,0 +1,19 @@
+{
+"ipv4Unicast":{
+ "routerId":"192.168.0.1",
+ "as":65000,
+ "vrfName":"default",
+ "peerCount":2,
+ "peers":{
+ "192.168.0.2":{
+ "remoteAs":65000,
+ "state":"Idle (Admin)"
+ },
+ "192.168.101.2":{
+ "remoteAs":65100,
+ "state":"Idle (Admin)"
+ }
+ },
+ "totalPeers":2
+}
+}
diff --git a/tests/topotests/bgp_features/r1/bgp_summary.json b/tests/topotests/bgp_features/r1/bgp_summary.json
new file mode 100644
index 0000000..1ad7342
--- /dev/null
+++ b/tests/topotests/bgp_features/r1/bgp_summary.json
@@ -0,0 +1,27 @@
+{
+"ipv4Unicast":{
+ "routerId":"192.168.0.1",
+ "as":65000,
+ "vrfName":"default",
+ "peerCount":2,
+ "peers":{
+ "192.168.0.2":{
+ "hostname":"r2",
+ "remoteAs":65000,
+ "outq":0,
+ "inq":0,
+ "pfxRcd":7,
+ "state":"Established"
+ },
+ "192.168.101.2":{
+ "hostname":"r4",
+ "remoteAs":65100,
+ "outq":0,
+ "inq":0,
+ "pfxRcd":3,
+ "state":"Established"
+ }
+ },
+ "totalPeers":2
+}
+}
diff --git a/tests/topotests/bgp_features/r1/bgpd.conf b/tests/topotests/bgp_features/r1/bgpd.conf
new file mode 100644
index 0000000..74d1993
--- /dev/null
+++ b/tests/topotests/bgp_features/r1/bgpd.conf
@@ -0,0 +1,41 @@
+!
+hostname r1
+log file bgpd.log
+!
+router bgp 65000
+ timers bgp 3 10
+ coalesce-time 0
+ bgp router-id 192.168.0.1
+ bgp log-neighbor-changes
+ no bgp ebgp-requires-policy
+ neighbor 192.168.0.2 remote-as 65000
+ neighbor 192.168.0.2 timers 3 10
+ neighbor 192.168.0.2 description Router R2 (iBGP)
+ neighbor 192.168.0.2 update-source lo
+ neighbor 192.168.0.2 timers connect 5
+ neighbor 192.168.101.2 remote-as 65100
+ neighbor 192.168.101.2 timers 3 10
+ neighbor 192.168.101.2 description Router R4 (eBGP AS 65100)
+ neighbor 192.168.101.2 timers connect 5
+ !
+ address-family ipv4 unicast
+ network 192.168.0.0/24
+ network 192.168.1.0/24
+ network 192.168.2.0/24
+ network 192.168.3.0/24
+ network 192.168.6.0/24
+ network 192.168.8.0/24
+ neighbor 192.168.101.2 route-map testmap-in in
+ neighbor 192.168.101.2 route-map testmap-out out
+ exit-address-family
+!
+!
+!
+route-map testmap-in permit 999
+!
+route-map testmap-out permit 999
+!
+!
+line vty
+!
+
diff --git a/tests/topotests/bgp_features/r1/ip_route.json b/tests/topotests/bgp_features/r1/ip_route.json
new file mode 100644
index 0000000..34c5803
--- /dev/null
+++ b/tests/topotests/bgp_features/r1/ip_route.json
@@ -0,0 +1,364 @@
+{
+ "0.0.0.0\/0":[
+ {
+ "prefix":"0.0.0.0\/0",
+ "protocol":"bgp",
+ "selected":true,
+ "destSelected":true,
+ "distance":20,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "ip":"192.168.101.2",
+ "afi":"ipv4",
+ "interfaceName":"r1-eth3",
+ "active":true,
+ "weight":1
+ }
+ ]
+ }
+ ],
+ "192.168.0.1\/32":[
+ {
+ "prefix":"192.168.0.1\/32",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":0,
+ "nexthops":[
+ {
+ "flags":1,
+ "directlyConnected":true,
+ "interfaceName":"lo",
+ "active":true,
+ "weight":1
+ }
+ ]
+ },
+ {
+ "prefix":"192.168.0.1\/32",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"lo",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.0.2\/32":[
+ {
+ "prefix":"192.168.0.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "ip":"192.168.1.2",
+ "afi":"ipv4",
+ "interfaceName":"r1-eth1",
+ "active":true,
+ "weight":1
+ }
+ ]
+ }
+ ],
+ "192.168.0.3\/32":[
+ {
+ "prefix":"192.168.0.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "ip":"192.168.3.2",
+ "afi":"ipv4",
+ "interfaceName":"r1-eth2",
+ "active":true,
+ "weight":1
+ }
+ ]
+ }
+ ],
+ "192.168.1.0\/24":[
+ {
+ "prefix":"192.168.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "table":254,
+ "nexthops":[
+ {
+ "flags":1,
+ "directlyConnected":true,
+ "interfaceName":"r1-eth1",
+ "active":true,
+ "weight":1
+ }
+ ]
+ },
+ {
+ "prefix":"192.168.1.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"r1-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.2.0\/24":[
+ {
+ "prefix":"192.168.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "ip":"192.168.1.2",
+ "afi":"ipv4",
+ "interfaceName":"r1-eth1",
+ "active":true,
+ "weight":1
+ },
+ {
+ "flags":3,
+ "fib":true,
+ "ip":"192.168.3.2",
+ "afi":"ipv4",
+ "interfaceName":"r1-eth2",
+ "active":true,
+ "weight":1
+ }
+ ]
+ }
+ ],
+ "192.168.3.0\/24":[
+ {
+ "prefix":"192.168.3.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "flags":1,
+ "directlyConnected":true,
+ "interfaceName":"r1-eth2",
+ "active":true,
+ "weight":1
+ }
+ ]
+ },
+ {
+ "prefix":"192.168.3.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"r1-eth2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.6.0\/24":[
+ {
+ "prefix":"192.168.6.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "flags":1,
+ "directlyConnected":true,
+ "interfaceName":"r1-eth0",
+ "active":true,
+ "weight":1
+ }
+ ]
+ },
+ {
+ "prefix":"192.168.6.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"r1-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.7.0\/24":[
+ {
+ "prefix":"192.168.7.0\/24",
+ "protocol":"bgp",
+ "distance":200,
+ "metric":0,
+ "nexthops":[
+ {
+ "flags":5,
+ "ip":"192.168.0.2",
+ "afi":"ipv4",
+ "active":true,
+ "recursive":true,
+ "weight":1
+ },
+ {
+ "flags":1,
+ "ip":"192.168.1.2",
+ "afi":"ipv4",
+ "interfaceName":"r1-eth1",
+ "active":true,
+ "weight":1
+ }
+ ]
+ },
+ {
+ "prefix":"192.168.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "ip":"192.168.1.2",
+ "afi":"ipv4",
+ "interfaceName":"r1-eth1",
+ "active":true,
+ "weight":1
+ }
+ ]
+ }
+ ],
+ "192.168.8.0\/24":[
+ {
+ "prefix":"192.168.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "ip":"192.168.3.2",
+ "afi":"ipv4",
+ "interfaceName":"r1-eth2",
+ "active":true,
+ "weight":1
+ }
+ ]
+ }
+ ],
+ "192.168.101.0\/24":[
+ {
+ "prefix":"192.168.101.0\/24",
+ "protocol":"bgp",
+ "distance":20,
+ "metric":0,
+ "nexthops":[
+ {
+ "flags":0,
+ "ip":"192.168.101.2",
+ "afi":"ipv4",
+ "weight":1
+ }
+ ]
+ },
+ {
+ "prefix":"192.168.101.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"r1-eth3",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.102.0\/24":[
+ {
+ "prefix":"192.168.102.0\/24",
+ "protocol":"bgp",
+ "selected":true,
+ "destSelected":true,
+ "distance":20,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "ip":"192.168.101.2",
+ "afi":"ipv4",
+ "interfaceName":"r1-eth3",
+ "active":true,
+ "weight":1
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_features/r1/ip_route_norib.json b/tests/topotests/bgp_features/r1/ip_route_norib.json
new file mode 100644
index 0000000..f6536d1
--- /dev/null
+++ b/tests/topotests/bgp_features/r1/ip_route_norib.json
@@ -0,0 +1,281 @@
+{
+ "192.168.0.1\/32":[
+ {
+ "prefix":"192.168.0.1\/32",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":0,
+ "nexthops":[
+ {
+ "flags":1,
+ "directlyConnected":true,
+ "interfaceName":"lo",
+ "active":true,
+ "weight":1
+ }
+ ]
+ },
+ {
+ "prefix":"192.168.0.1\/32",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"lo",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.0.2\/32":[
+ {
+ "prefix":"192.168.0.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "ip":"192.168.1.2",
+ "afi":"ipv4",
+ "interfaceName":"r1-eth1",
+ "active":true,
+ "weight":1
+ }
+ ]
+ }
+ ],
+ "192.168.0.3\/32":[
+ {
+ "prefix":"192.168.0.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "ip":"192.168.3.2",
+ "afi":"ipv4",
+ "interfaceName":"r1-eth2",
+ "active":true,
+ "weight":1
+ }
+ ]
+ }
+ ],
+ "192.168.1.0\/24":[
+ {
+ "prefix":"192.168.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "flags":1,
+ "directlyConnected":true,
+ "interfaceName":"r1-eth1",
+ "active":true,
+ "weight":1
+ }
+ ]
+ },
+ {
+ "prefix":"192.168.1.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"r1-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.2.0\/24":[
+ {
+ "prefix":"192.168.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "ip":"192.168.1.2",
+ "afi":"ipv4",
+ "interfaceName":"r1-eth1",
+ "active":true,
+ "weight":1
+ },
+ {
+ "flags":3,
+ "fib":true,
+ "ip":"192.168.3.2",
+ "afi":"ipv4",
+ "interfaceName":"r1-eth2",
+ "active":true,
+ "weight":1
+ }
+ ]
+ }
+ ],
+ "192.168.3.0\/24":[
+ {
+ "prefix":"192.168.3.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "flags":1,
+ "directlyConnected":true,
+ "interfaceName":"r1-eth2",
+ "active":true,
+ "weight":1
+ }
+ ]
+ },
+ {
+ "prefix":"192.168.3.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"r1-eth2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.6.0\/24":[
+ {
+ "prefix":"192.168.6.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "flags":1,
+ "directlyConnected":true,
+ "interfaceName":"r1-eth0",
+ "active":true,
+ "weight":1
+ }
+ ]
+ },
+ {
+ "prefix":"192.168.6.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"r1-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.7.0\/24":[
+ {
+ "prefix":"192.168.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "ip":"192.168.1.2",
+ "afi":"ipv4",
+ "interfaceName":"r1-eth1",
+ "active":true,
+ "weight":1
+ }
+ ]
+ }
+ ],
+ "192.168.8.0\/24":[
+ {
+ "prefix":"192.168.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "ip":"192.168.3.2",
+ "afi":"ipv4",
+ "interfaceName":"r1-eth2",
+ "active":true,
+ "weight":1
+ }
+ ]
+ }
+ ],
+ "192.168.101.0\/24":[
+ {
+ "prefix":"192.168.101.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"r1-eth3",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_features/r1/ospf6d.conf b/tests/topotests/bgp_features/r1/ospf6d.conf
new file mode 100644
index 0000000..9afc6f4
--- /dev/null
+++ b/tests/topotests/bgp_features/r1/ospf6d.conf
@@ -0,0 +1,21 @@
+log file ospf6d.log
+!
+! debug ospf6 neighbor
+!
+interface r1-lo
+!
+interface r1-eth1
+ ipv6 ospf6 priority 10
+!
+interface r1-eth2
+ ipv6 ospf6 priority 10
+!
+router ospf6
+ ospf6 router-id 192.168.0.1
+ log-adjacency-changes
+ interface r1-lo area 0.0.0.0
+ interface r1-eth1 area 0.0.0.0
+ interface r1-eth2 area 0.0.0.0
+!
+line vty
+!
diff --git a/tests/topotests/bgp_features/r1/ospf_neighbor.json b/tests/topotests/bgp_features/r1/ospf_neighbor.json
new file mode 100644
index 0000000..3b5f46d
--- /dev/null
+++ b/tests/topotests/bgp_features/r1/ospf_neighbor.json
@@ -0,0 +1,16 @@
+{
+ "neighbors":{
+ "192.168.0.2":[
+ {
+ "priority":5,
+ "converged":"Full"
+ }
+ ],
+ "192.168.0.3":[
+ {
+ "priority":5,
+ "converged":"Full"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_features/r1/ospfd.conf b/tests/topotests/bgp_features/r1/ospfd.conf
new file mode 100644
index 0000000..aef017f
--- /dev/null
+++ b/tests/topotests/bgp_features/r1/ospfd.conf
@@ -0,0 +1,26 @@
+log file ospfd.log
+!
+! debug ospf event
+! debug ospf zebra
+!
+interface r1-eth1
+ ip ospf hello-interval 2
+ ip ospf dead-interval 10
+ ip ospf priority 10
+!
+interface r1-eth2
+ ip ospf hello-interval 2
+ ip ospf dead-interval 10
+ ip ospf priority 10
+!
+router ospf
+ ospf router-id 192.168.0.1
+ log-adjacency-changes
+ network 192.168.0.0/20 area 0.0.0.0
+ timers throttle spf 0 0 0
+ timers lsa min-arrival 10
+ timers throttle lsa all 0
+ refresh timer 10
+!
+line vty
+!
diff --git a/tests/topotests/bgp_features/r1/show_bgp.json b/tests/topotests/bgp_features/r1/show_bgp.json
new file mode 100644
index 0000000..45e0e17
--- /dev/null
+++ b/tests/topotests/bgp_features/r1/show_bgp.json
@@ -0,0 +1,350 @@
+{
+ "vrfName": "default",
+ "routerId": "192.168.0.1",
+ "defaultLocPrf": 100,
+ "localAS": 65000,
+ "routes": { "0.0.0.0/0": [
+ {
+ "valid":true,
+ "bestpath":true,
+ "pathFrom":"external",
+ "prefix":"0.0.0.0",
+ "prefixLen":0,
+ "network":"0.0.0.0\/0",
+ "weight":0,
+ "peerId":"192.168.101.2",
+ "path":"65100",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.168.101.2",
+ "hostname":"r4",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"192.168.0.0/24": [
+ {
+ "pathFrom":"external",
+ "prefix":"192.168.0.0",
+ "prefixLen":24,
+ "network":"192.168.0.0\/24",
+ "metric":0,
+ "weight":32768,
+ "peerId":"(unspec)",
+ "path":"",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"0.0.0.0",
+ "hostname":"r1",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"192.168.1.0/24": [
+ {
+ "valid":true,
+ "pathFrom":"internal",
+ "prefix":"192.168.1.0",
+ "prefixLen":24,
+ "network":"192.168.1.0\/24",
+ "metric":0,
+ "locPrf":100,
+ "weight":0,
+ "peerId":"192.168.0.2",
+ "path":"",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.168.0.2",
+ "hostname":"r2",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ },
+ {
+ "valid":true,
+ "bestpath":true,
+ "pathFrom":"external",
+ "prefix":"192.168.1.0",
+ "prefixLen":24,
+ "network":"192.168.1.0\/24",
+ "metric":0,
+ "weight":32768,
+ "peerId":"(unspec)",
+ "path":"",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"0.0.0.0",
+ "hostname":"r1",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"192.168.2.0/24": [
+ {
+ "valid":true,
+ "pathFrom":"internal",
+ "prefix":"192.168.2.0",
+ "prefixLen":24,
+ "network":"192.168.2.0\/24",
+ "metric":0,
+ "locPrf":100,
+ "weight":0,
+ "peerId":"192.168.0.2",
+ "path":"",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.168.0.2",
+ "hostname":"r2",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ },
+ {
+ "valid":true,
+ "bestpath":true,
+ "pathFrom":"external",
+ "prefix":"192.168.2.0",
+ "prefixLen":24,
+ "network":"192.168.2.0\/24",
+ "metric":0,
+ "weight":32768,
+ "peerId":"(unspec)",
+ "path":"",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"0.0.0.0",
+ "hostname":"r1",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"192.168.3.0/24": [
+ {
+ "valid":true,
+ "pathFrom":"internal",
+ "prefix":"192.168.3.0",
+ "prefixLen":24,
+ "network":"192.168.3.0\/24",
+ "metric":0,
+ "locPrf":100,
+ "weight":0,
+ "peerId":"192.168.0.2",
+ "path":"",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.168.0.2",
+ "hostname":"r2",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ },
+ {
+ "valid":true,
+ "bestpath":true,
+ "pathFrom":"external",
+ "prefix":"192.168.3.0",
+ "prefixLen":24,
+ "network":"192.168.3.0\/24",
+ "metric":0,
+ "weight":32768,
+ "peerId":"(unspec)",
+ "path":"",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"0.0.0.0",
+ "hostname":"r1",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"192.168.6.0/24": [
+ {
+ "valid":true,
+ "bestpath":true,
+ "pathFrom":"external",
+ "prefix":"192.168.6.0",
+ "prefixLen":24,
+ "network":"192.168.6.0\/24",
+ "metric":0,
+ "weight":32768,
+ "peerId":"(unspec)",
+ "path":"",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"0.0.0.0",
+ "hostname":"r1",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"192.168.7.0/24": [
+ {
+ "valid":true,
+ "bestpath":true,
+ "pathFrom":"internal",
+ "prefix":"192.168.7.0",
+ "prefixLen":24,
+ "network":"192.168.7.0\/24",
+ "metric":0,
+ "locPrf":100,
+ "weight":0,
+ "peerId":"192.168.0.2",
+ "path":"",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.168.0.2",
+ "hostname":"r2",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"192.168.8.0/24": [
+ {
+ "valid":true,
+ "pathFrom":"internal",
+ "prefix":"192.168.8.0",
+ "prefixLen":24,
+ "network":"192.168.8.0\/24",
+ "metric":0,
+ "locPrf":100,
+ "weight":0,
+ "peerId":"192.168.0.2",
+ "path":"",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.168.0.2",
+ "hostname":"r2",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ },
+ {
+ "valid":true,
+ "bestpath":true,
+ "pathFrom":"external",
+ "prefix":"192.168.8.0",
+ "prefixLen":24,
+ "network":"192.168.8.0\/24",
+ "metric":0,
+ "weight":32768,
+ "peerId":"(unspec)",
+ "path":"",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"0.0.0.0",
+ "hostname":"r1",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"192.168.101.0/24": [
+ {
+ "valid":true,
+ "bestpath":true,
+ "pathFrom":"external",
+ "prefix":"192.168.101.0",
+ "prefixLen":24,
+ "network":"192.168.101.0\/24",
+ "metric":0,
+ "weight":0,
+ "peerId":"192.168.101.2",
+ "path":"65100",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.168.101.2",
+ "hostname":"r4",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"192.168.102.0/24": [
+ {
+ "valid":true,
+ "bestpath":true,
+ "pathFrom":"external",
+ "prefix":"192.168.102.0",
+ "prefixLen":24,
+ "network":"192.168.102.0\/24",
+ "metric":0,
+ "weight":0,
+ "peerId":"192.168.101.2",
+ "path":"65100",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.168.101.2",
+ "hostname":"r4",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"192.168.201.0/24": [
+ {
+ "pathFrom":"internal",
+ "prefix":"192.168.201.0",
+ "prefixLen":24,
+ "network":"192.168.201.0\/24",
+ "metric":0,
+ "locPrf":100,
+ "weight":0,
+ "peerId":"192.168.0.2",
+ "path":"65200",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.168.201.2",
+ "hostname":"r2",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"192.168.202.0/24": [
+ {
+ "pathFrom":"internal",
+ "prefix":"192.168.202.0",
+ "prefixLen":24,
+ "network":"192.168.202.0\/24",
+ "metric":0,
+ "locPrf":100,
+ "weight":0,
+ "peerId":"192.168.0.2",
+ "path":"65200",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.168.201.2",
+ "hostname":"r2",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+] } }
diff --git a/tests/topotests/bgp_features/r1/show_bgp_metric_test.json b/tests/topotests/bgp_features/r1/show_bgp_metric_test.json
new file mode 100644
index 0000000..1720572
--- /dev/null
+++ b/tests/topotests/bgp_features/r1/show_bgp_metric_test.json
@@ -0,0 +1,57 @@
+{
+ "routerId": "192.168.0.1",
+ "routes": {
+ "192.168.1.0/24": [
+ {
+ "valid":true,
+ "prefix":"192.168.1.0",
+ "prefixLen":24,
+ "metric":11,
+ "nexthops":[
+ {
+ "ip":"192.168.0.2",
+ "used":true
+ }
+ ]
+ },
+ {
+ "valid":true,
+ "prefix":"192.168.1.0",
+ "prefixLen":24,
+ "metric":0,
+ "nexthops":[
+ {
+ "ip":"0.0.0.0",
+ "used":true
+ }
+ ]
+ }
+],"192.168.101.0/24": [
+ {
+ "prefix":"192.168.101.0",
+ "prefixLen":24,
+ "metric":111,
+ "peerId":"192.168.101.2"
+ }
+],"192.168.102.0/24": [
+ {
+ "prefix":"192.168.102.0",
+ "prefixLen":24,
+ "metric":0,
+ "peerId":"192.168.101.2"
+ }
+],"192.168.201.0/24": [
+ {
+ "prefix":"192.168.201.0",
+ "prefixLen":24,
+ "metric":210,
+ "peerId":"192.168.0.2"
+ }
+],"192.168.202.0/24": [
+ {
+ "prefix":"192.168.202.0",
+ "prefixLen":24,
+ "metric":11,
+ "peerId":"192.168.0.2"
+ }
+] } }
diff --git a/tests/topotests/bgp_features/r1/zebra.conf b/tests/topotests/bgp_features/r1/zebra.conf
new file mode 100644
index 0000000..61564f1
--- /dev/null
+++ b/tests/topotests/bgp_features/r1/zebra.conf
@@ -0,0 +1,28 @@
+!
+hostname r1
+log file zebra.log
+!
+interface lo
+ ip address 192.168.0.1/32
+ ipv6 address fc00::1/128
+!
+interface r1-eth0
+ description SW6 Stub Network
+ ip address 192.168.6.1/24
+ ipv6 address fc00:0:0:6::1/64
+!
+interface r1-eth1
+ description SW0 R1-R2 OSPF & BGP Network
+ ip address 192.168.1.1/24
+ ipv6 address fc00:0:0:1::1/64
+!
+interface r1-eth2
+ description SW2 R1-R3 OSPF Network
+ ip address 192.168.3.1/24
+ ipv6 address fc00:0:0:3::1/64
+!
+interface r1-eth3
+ description SW4 R1-R4 eBGP Network
+ ip address 192.168.101.1/24
+ ipv6 address fc00:100:0:1::1/64
+!
diff --git a/tests/topotests/bgp_features/r2/bgp_delayopen_neighbor.json b/tests/topotests/bgp_features/r2/bgp_delayopen_neighbor.json
new file mode 100644
index 0000000..a74da03
--- /dev/null
+++ b/tests/topotests/bgp_features/r2/bgp_delayopen_neighbor.json
@@ -0,0 +1,6 @@
+{
+ "192.168.201.2":{
+ "remoteAs":65200,
+ "bgpTimerDelayOpenTimeMsecs":60000
+ }
+}
diff --git a/tests/topotests/bgp_features/r2/bgp_delayopen_summary_connect.json b/tests/topotests/bgp_features/r2/bgp_delayopen_summary_connect.json
new file mode 100644
index 0000000..c2b42ec
--- /dev/null
+++ b/tests/topotests/bgp_features/r2/bgp_delayopen_summary_connect.json
@@ -0,0 +1,11 @@
+{
+"ipv4Unicast":{
+ "as":65000,
+ "peers":{
+ "192.168.201.2":{
+ "remoteAs":65200,
+ "state":"Connect"
+ }
+ }
+}
+}
diff --git a/tests/topotests/bgp_features/r2/bgp_delayopen_summary_established.json b/tests/topotests/bgp_features/r2/bgp_delayopen_summary_established.json
new file mode 100644
index 0000000..77b6944
--- /dev/null
+++ b/tests/topotests/bgp_features/r2/bgp_delayopen_summary_established.json
@@ -0,0 +1,11 @@
+{
+"ipv4Unicast":{
+ "as":65000,
+ "peers":{
+ "192.168.201.2":{
+ "remoteAs":65200,
+ "state":"Established"
+ }
+ }
+}
+}
diff --git a/tests/topotests/bgp_features/r2/bgp_delayopen_summary_shutdown.json b/tests/topotests/bgp_features/r2/bgp_delayopen_summary_shutdown.json
new file mode 100644
index 0000000..8f9476a
--- /dev/null
+++ b/tests/topotests/bgp_features/r2/bgp_delayopen_summary_shutdown.json
@@ -0,0 +1,11 @@
+{
+"ipv4Unicast":{
+ "as":65000,
+ "peers":{
+ "192.168.201.2":{
+ "remoteAs":65200,
+ "state":"Idle (Admin)"
+ }
+ }
+}
+}
diff --git a/tests/topotests/bgp_features/r2/bgp_shutdown_summary.json b/tests/topotests/bgp_features/r2/bgp_shutdown_summary.json
new file mode 100644
index 0000000..b789263
--- /dev/null
+++ b/tests/topotests/bgp_features/r2/bgp_shutdown_summary.json
@@ -0,0 +1,19 @@
+{
+"ipv4Unicast":{
+ "routerId":"192.168.0.2",
+ "as":65000,
+ "vrfName":"default",
+ "peerCount":2,
+ "peers":{
+ "192.168.0.1":{
+ "remoteAs":65000,
+ "state":"Active"
+ },
+ "192.168.201.2":{
+ "remoteAs":65200,
+ "state":"Established"
+ }
+ },
+ "totalPeers":2
+}
+}
diff --git a/tests/topotests/bgp_features/r2/bgp_summary.json b/tests/topotests/bgp_features/r2/bgp_summary.json
new file mode 100644
index 0000000..30e0ef4
--- /dev/null
+++ b/tests/topotests/bgp_features/r2/bgp_summary.json
@@ -0,0 +1,27 @@
+{
+"ipv4Unicast":{
+ "routerId":"192.168.0.2",
+ "as":65000,
+ "vrfName":"default",
+ "peerCount":2,
+ "peers":{
+ "192.168.0.1":{
+ "hostname":"r1",
+ "remoteAs":65000,
+ "outq":0,
+ "inq":0,
+ "pfxRcd":8,
+ "state":"Established"
+ },
+ "192.168.201.2":{
+ "hostname":"r5",
+ "remoteAs":65200,
+ "outq":0,
+ "inq":0,
+ "pfxRcd":2,
+ "state":"Established"
+ }
+ },
+ "totalPeers":2
+}
+}
diff --git a/tests/topotests/bgp_features/r2/bgpd.conf b/tests/topotests/bgp_features/r2/bgpd.conf
new file mode 100644
index 0000000..99cec98
--- /dev/null
+++ b/tests/topotests/bgp_features/r2/bgpd.conf
@@ -0,0 +1,41 @@
+!
+hostname r2
+log file bgpd.log
+!
+router bgp 65000
+ bgp router-id 192.168.0.2
+ timers bgp 3 10
+ coalesce-time 0
+ bgp log-neighbor-changes
+ no bgp ebgp-requires-policy
+ neighbor 192.168.0.1 remote-as 65000
+ neighbor 192.168.0.1 timers 3 10
+ neighbor 192.168.0.1 description Router R1 (iBGP)
+ neighbor 192.168.0.1 update-source lo
+ neighbor 192.168.0.1 timers connect 5
+ neighbor 192.168.201.2 remote-as 65200
+ neighbor 192.168.201.2 timers 3 10
+ neighbor 192.168.201.2 description Router R5 (eBGP AS 65200)
+ neighbor 192.168.201.2 timers connect 5
+ !
+ address-family ipv4 unicast
+ network 192.168.0.0/24
+ network 192.168.1.0/24
+ network 192.168.2.0/24
+ network 192.168.3.0/24
+ network 192.168.7.0/24
+ network 192.168.8.0/24
+ neighbor 192.168.201.2 route-map testmap-in in
+ neighbor 192.168.201.2 route-map testmap-out out
+ exit-address-family
+!
+!
+!
+route-map testmap-in permit 999
+!
+route-map testmap-out permit 999
+!
+!
+line vty
+!
+
diff --git a/tests/topotests/bgp_features/r2/ospf6d.conf b/tests/topotests/bgp_features/r2/ospf6d.conf
new file mode 100644
index 0000000..7fe5356
--- /dev/null
+++ b/tests/topotests/bgp_features/r2/ospf6d.conf
@@ -0,0 +1,21 @@
+log file ospf6d.log
+!
+! debug ospf6 neighbor
+!
+interface r2-lo
+!
+interface r2-eth1
+ ipv6 ospf6 priority 5
+!
+interface r2-eth2
+ ipv6 ospf6 priority 10
+!
+router ospf6
+ ospf6 router-id 192.168.0.2
+ log-adjacency-changes
+ interface r2-lo area 0.0.0.0
+ interface r2-eth1 area 0.0.0.0
+ interface r2-eth2 area 0.0.0.0
+!
+line vty
+!
diff --git a/tests/topotests/bgp_features/r2/ospf_neighbor.json b/tests/topotests/bgp_features/r2/ospf_neighbor.json
new file mode 100644
index 0000000..47bb57c
--- /dev/null
+++ b/tests/topotests/bgp_features/r2/ospf_neighbor.json
@@ -0,0 +1,16 @@
+{
+ "neighbors":{
+ "192.168.0.1":[
+ {
+ "priority":10,
+ "converged":"Full"
+ }
+ ],
+ "192.168.0.3":[
+ {
+ "priority":5,
+ "converged":"Full"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_features/r2/ospfd.conf b/tests/topotests/bgp_features/r2/ospfd.conf
new file mode 100644
index 0000000..7f043c9
--- /dev/null
+++ b/tests/topotests/bgp_features/r2/ospfd.conf
@@ -0,0 +1,26 @@
+log file ospfd.log
+!
+! debug ospf event
+! debug ospf zebra
+!
+int r2-eth1
+ ip ospf hello-interval 2
+ ip ospf dead-interval 10
+ ip ospf priority 5
+!
+int r2-eth2
+ ip ospf hello-interval 2
+ ip ospf dead-interval 10
+ ip ospf priority 10
+!
+router ospf
+ ospf router-id 192.168.0.2
+ log-adjacency-changes
+ network 192.168.0.0/20 area 0.0.0.0
+ timers throttle spf 0 0 0
+ timers lsa min-arrival 10
+ timers throttle lsa all 0
+ refresh timer 10
+!
+line vty
+!
diff --git a/tests/topotests/bgp_features/r2/show_bgp.json b/tests/topotests/bgp_features/r2/show_bgp.json
new file mode 100644
index 0000000..830d5a9
--- /dev/null
+++ b/tests/topotests/bgp_features/r2/show_bgp.json
@@ -0,0 +1,349 @@
+{
+ "vrfName": "default",
+ "routerId": "192.168.0.2",
+ "defaultLocPrf": 100,
+ "localAS": 65000,
+ "routes": { "0.0.0.0/0": [
+ {
+ "pathFrom":"internal",
+ "prefix":"0.0.0.0",
+ "prefixLen":0,
+ "network":"0.0.0.0\/0",
+ "locPrf":100,
+ "weight":0,
+ "peerId":"192.168.0.1",
+ "path":"65100",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.168.101.2",
+ "hostname":"r1",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"192.168.0.0/24": [
+ {
+ "pathFrom":"external",
+ "prefix":"192.168.0.0",
+ "prefixLen":24,
+ "network":"192.168.0.0\/24",
+ "metric":0,
+ "weight":32768,
+ "peerId":"(unspec)",
+ "path":"",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"0.0.0.0",
+ "hostname":"r2",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"192.168.1.0/24": [
+ {
+ "valid":true,
+ "pathFrom":"internal",
+ "prefix":"192.168.1.0",
+ "prefixLen":24,
+ "network":"192.168.1.0\/24",
+ "metric":0,
+ "locPrf":100,
+ "weight":0,
+ "peerId":"192.168.0.1",
+ "path":"",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.168.0.1",
+ "hostname":"r1",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ },
+ {
+ "valid":true,
+ "bestpath":true,
+ "pathFrom":"external",
+ "prefix":"192.168.1.0",
+ "prefixLen":24,
+ "network":"192.168.1.0\/24",
+ "metric":0,
+ "weight":32768,
+ "peerId":"(unspec)",
+ "path":"",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"0.0.0.0",
+ "hostname":"r2",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"192.168.2.0/24": [
+ {
+ "valid":true,
+ "pathFrom":"internal",
+ "prefix":"192.168.2.0",
+ "prefixLen":24,
+ "network":"192.168.2.0\/24",
+ "metric":0,
+ "locPrf":100,
+ "weight":0,
+ "peerId":"192.168.0.1",
+ "path":"",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.168.0.1",
+ "hostname":"r1",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ },
+ {
+ "valid":true,
+ "bestpath":true,
+ "pathFrom":"external",
+ "prefix":"192.168.2.0",
+ "prefixLen":24,
+ "network":"192.168.2.0\/24",
+ "metric":0,
+ "weight":32768,
+ "peerId":"(unspec)",
+ "path":"",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"0.0.0.0",
+ "hostname":"r2",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"192.168.3.0/24": [
+ {
+ "valid":true,
+ "pathFrom":"internal",
+ "prefix":"192.168.3.0",
+ "prefixLen":24,
+ "network":"192.168.3.0\/24",
+ "metric":0,
+ "locPrf":100,
+ "weight":0,
+ "peerId":"192.168.0.1",
+ "path":"",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.168.0.1",
+ "hostname":"r1",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ },
+ {
+ "valid":true,
+ "bestpath":true,
+ "pathFrom":"external",
+ "prefix":"192.168.3.0",
+ "prefixLen":24,
+ "network":"192.168.3.0\/24",
+ "metric":0,
+ "weight":32768,
+ "peerId":"(unspec)",
+ "path":"",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"0.0.0.0",
+ "hostname":"r2",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"192.168.6.0/24": [
+ {
+ "valid":true,
+ "bestpath":true,
+ "pathFrom":"internal",
+ "prefix":"192.168.6.0",
+ "prefixLen":24,
+ "network":"192.168.6.0\/24",
+ "metric":0,
+ "locPrf":100,
+ "weight":0,
+ "peerId":"192.168.0.1",
+ "path":"",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.168.0.1",
+ "hostname":"r1",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"192.168.7.0/24": [
+ {
+ "valid":true,
+ "bestpath":true,
+ "pathFrom":"external",
+ "prefix":"192.168.7.0",
+ "prefixLen":24,
+ "network":"192.168.7.0\/24",
+ "metric":0,
+ "weight":32768,
+ "peerId":"(unspec)",
+ "path":"",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"0.0.0.0",
+ "hostname":"r2",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"192.168.8.0/24": [
+ {
+ "valid":true,
+ "pathFrom":"internal",
+ "prefix":"192.168.8.0",
+ "prefixLen":24,
+ "network":"192.168.8.0\/24",
+ "metric":0,
+ "locPrf":100,
+ "weight":0,
+ "peerId":"192.168.0.1",
+ "path":"",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.168.0.1",
+ "hostname":"r1",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ },
+ {
+ "valid":true,
+ "bestpath":true,
+ "pathFrom":"external",
+ "prefix":"192.168.8.0",
+ "prefixLen":24,
+ "network":"192.168.8.0\/24",
+ "metric":0,
+ "weight":32768,
+ "peerId":"(unspec)",
+ "path":"",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"0.0.0.0",
+ "hostname":"r2",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"192.168.101.0/24": [
+ {
+ "pathFrom":"internal",
+ "prefix":"192.168.101.0",
+ "prefixLen":24,
+ "network":"192.168.101.0\/24",
+ "metric":0,
+ "locPrf":100,
+ "weight":0,
+ "peerId":"192.168.0.1",
+ "path":"65100",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.168.101.2",
+ "hostname":"r1",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"192.168.102.0/24": [
+ {
+ "pathFrom":"internal",
+ "prefix":"192.168.102.0",
+ "prefixLen":24,
+ "network":"192.168.102.0\/24",
+ "metric":0,
+ "locPrf":100,
+ "weight":0,
+ "peerId":"192.168.0.1",
+ "path":"65100",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.168.101.2",
+ "hostname":"r1",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"192.168.201.0/24": [
+ {
+ "valid":true,
+ "bestpath":true,
+ "pathFrom":"external",
+ "prefix":"192.168.201.0",
+ "prefixLen":24,
+ "network":"192.168.201.0\/24",
+ "metric":0,
+ "weight":0,
+ "peerId":"192.168.201.2",
+ "path":"65200",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.168.201.2",
+ "hostname":"r5",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"192.168.202.0/24": [
+ {
+ "valid":true,
+ "bestpath":true,
+ "pathFrom":"external",
+ "prefix":"192.168.202.0",
+ "prefixLen":24,
+ "network":"192.168.202.0\/24",
+ "metric":0,
+ "weight":0,
+ "peerId":"192.168.201.2",
+ "path":"65200",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.168.201.2",
+ "hostname":"r5",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+] } }
diff --git a/tests/topotests/bgp_features/r2/show_bgp_metric_test.json b/tests/topotests/bgp_features/r2/show_bgp_metric_test.json
new file mode 100644
index 0000000..960f13d
--- /dev/null
+++ b/tests/topotests/bgp_features/r2/show_bgp_metric_test.json
@@ -0,0 +1,57 @@
+{
+ "routerId": "192.168.0.2",
+ "routes": {
+ "192.168.2.0/24": [
+ {
+ "valid":true,
+ "prefix":"192.168.2.0",
+ "prefixLen":24,
+ "metric":0,
+ "nexthops":[
+ {
+ "ip":"192.168.0.1",
+ "used":true
+ }
+ ]
+ },
+ {
+ "valid":true,
+ "prefix":"192.168.2.0",
+ "prefixLen":24,
+ "metric":0,
+ "nexthops":[
+ {
+ "ip":"0.0.0.0",
+ "used":true
+ }
+ ]
+ }
+],"192.168.101.0/24": [
+ {
+ "prefix":"192.168.101.0",
+ "prefixLen":24,
+ "metric":101,
+ "peerId":"192.168.0.1"
+ }
+],"192.168.102.0/24": [
+ {
+ "prefix":"192.168.102.0",
+ "prefixLen":24,
+ "metric":0,
+ "peerId":"192.168.0.1"
+ }
+],"192.168.201.0/24": [
+ {
+ "prefix":"192.168.201.0",
+ "prefixLen":24,
+ "metric":222,
+ "peerId":"192.168.201.2"
+ }
+],"192.168.202.0/24": [
+ {
+ "prefix":"192.168.202.0",
+ "prefixLen":24,
+ "metric":0,
+ "peerId":"192.168.201.2"
+ }
+] } }
diff --git a/tests/topotests/bgp_features/r2/zebra.conf b/tests/topotests/bgp_features/r2/zebra.conf
new file mode 100644
index 0000000..1d427da
--- /dev/null
+++ b/tests/topotests/bgp_features/r2/zebra.conf
@@ -0,0 +1,28 @@
+!
+hostname r2
+log file zebra.log
+!
+interface lo
+ ip address 192.168.0.2/32
+ ipv6 address fc00::2/128
+!
+interface r2-eth0
+ description SW7 Stub Network
+ ip address 192.168.7.1/24
+ ipv6 address fc00:0:0:7::1/64
+!
+interface r2-eth1
+ description SW0 R1-R2 OSPF & BGP Network
+ ip address 192.168.1.2/24
+ ipv6 address fc00:0:0:1::2/64
+!
+interface r2-eth2
+ description SW1 R2-R3 OSPF Network
+ ip address 192.168.2.1/24
+ ipv6 address fc00:0:0:2::1/64
+!
+interface r2-eth3
+ description SW5 R2-R5 eBGP Network
+ ip address 192.168.201.1/24
+ ipv6 address fc00:200:0:1::1/64
+!
diff --git a/tests/topotests/bgp_features/r3/bgp_summary.json b/tests/topotests/bgp_features/r3/bgp_summary.json
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/topotests/bgp_features/r3/bgp_summary.json
diff --git a/tests/topotests/bgp_features/r3/ospf6d.conf b/tests/topotests/bgp_features/r3/ospf6d.conf
new file mode 100644
index 0000000..07325b6
--- /dev/null
+++ b/tests/topotests/bgp_features/r3/ospf6d.conf
@@ -0,0 +1,21 @@
+log file ospf6d.log
+!
+! debug ospf6 neighbor
+!
+interface r3-lo
+!
+interface r3-eth1
+ ipv6 ospf6 priority 5
+!
+interface r3-eth2
+ ipv6 ospf6 priority 5
+!
+router ospf6
+ ospf6 router-id 192.168.0.3
+ log-adjacency-changes
+ interface r3-lo area 0.0.0.0
+ interface r3-eth1 area 0.0.0.0
+ interface r3-eth2 area 0.0.0.0
+!
+line vty
+!
diff --git a/tests/topotests/bgp_features/r3/ospf_neighbor.json b/tests/topotests/bgp_features/r3/ospf_neighbor.json
new file mode 100644
index 0000000..b84974c
--- /dev/null
+++ b/tests/topotests/bgp_features/r3/ospf_neighbor.json
@@ -0,0 +1,16 @@
+{
+ "neighbors":{
+ "192.168.0.1":[
+ {
+ "priority":10,
+ "converged":"Full"
+ }
+ ],
+ "192.168.0.2":[
+ {
+ "priority":10,
+ "converged":"Full"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_features/r3/ospfd.conf b/tests/topotests/bgp_features/r3/ospfd.conf
new file mode 100644
index 0000000..c3399fd
--- /dev/null
+++ b/tests/topotests/bgp_features/r3/ospfd.conf
@@ -0,0 +1,26 @@
+log file ospfd.log
+!
+! debug ospf event
+! debug ospf zebra
+!
+int r3-eth1
+ ip ospf hello-interval 2
+ ip ospf dead-interval 10
+ ip ospf priority 5
+!
+int r3-eth2
+ ip ospf hello-interval 2
+ ip ospf dead-interval 10
+ ip ospf priority 5
+!
+router ospf
+ ospf router-id 192.168.0.3
+ log-adjacency-changes
+ network 192.168.0.0/20 area 0.0.0.0
+ timers throttle spf 0 0 0
+ timers lsa min-arrival 10
+ timers throttle lsa all 0
+ refresh timer 10
+!
+line vty
+!
diff --git a/tests/topotests/bgp_features/r3/zebra.conf b/tests/topotests/bgp_features/r3/zebra.conf
new file mode 100644
index 0000000..62ba04d
--- /dev/null
+++ b/tests/topotests/bgp_features/r3/zebra.conf
@@ -0,0 +1,23 @@
+!
+hostname r3
+log file zebra.log
+!
+interface lo
+ ip address 192.168.0.3/32
+ ipv6 address fc00::3/128
+!
+interface r3-eth0
+ description SW8 Stub Network
+ ip address 192.168.8.1/24
+ ipv6 address fc00:0:0:8::1/64
+!
+interface r3-eth1
+ description SW1 R2-R3 OSPF Network
+ ip address 192.168.2.2/24
+ ipv6 address fc00:0:0:2::2/64
+!
+interface r3-eth2
+ description SW2 R1-R3 OSPF Network
+ ip address 192.168.3.2/24
+ ipv6 address fc00:0:0:3::2/64
+!
diff --git a/tests/topotests/bgp_features/r4/bgp_delayopen_summary_established.json b/tests/topotests/bgp_features/r4/bgp_delayopen_summary_established.json
new file mode 100644
index 0000000..85caf55
--- /dev/null
+++ b/tests/topotests/bgp_features/r4/bgp_delayopen_summary_established.json
@@ -0,0 +1,11 @@
+{
+"ipv4Unicast":{
+ "as":65100,
+ "peers":{
+ "192.168.101.1":{
+ "remoteAs":65000,
+ "state":"Established"
+ }
+ }
+}
+}
diff --git a/tests/topotests/bgp_features/r4/bgp_delayopen_summary_shutdown.json b/tests/topotests/bgp_features/r4/bgp_delayopen_summary_shutdown.json
new file mode 100644
index 0000000..cf784d8
--- /dev/null
+++ b/tests/topotests/bgp_features/r4/bgp_delayopen_summary_shutdown.json
@@ -0,0 +1,11 @@
+{
+"ipv4Unicast":{
+ "as":65100,
+ "peers":{
+ "192.168.101.1":{
+ "remoteAs":65000,
+ "state":"Idle (Admin)"
+ }
+ }
+}
+}
diff --git a/tests/topotests/bgp_features/r4/bgp_shutdown_summary.json b/tests/topotests/bgp_features/r4/bgp_shutdown_summary.json
new file mode 100644
index 0000000..ede4dd6
--- /dev/null
+++ b/tests/topotests/bgp_features/r4/bgp_shutdown_summary.json
@@ -0,0 +1,14 @@
+{
+"ipv4Unicast":{
+ "routerId":"192.168.100.1",
+ "as":65100,
+ "vrfName":"default",
+ "peerCount":1,
+ "peers":{
+ "192.168.101.1":{
+ "remoteAs":65000,
+ "state":"Active" }
+ },
+ "totalPeers":1
+}
+}
diff --git a/tests/topotests/bgp_features/r4/bgp_summary.json b/tests/topotests/bgp_features/r4/bgp_summary.json
new file mode 100644
index 0000000..c0dfe78
--- /dev/null
+++ b/tests/topotests/bgp_features/r4/bgp_summary.json
@@ -0,0 +1,18 @@
+{
+"ipv4Unicast":{
+ "routerId":"192.168.100.1",
+ "as":65100,
+ "vrfName":"default",
+ "peerCount":1,
+ "peers":{
+ "192.168.101.1":{
+ "hostname":"r1",
+ "remoteAs":65000,
+ "outq":0,
+ "inq":0,
+ "pfxRcd":6,
+ "state":"Established" }
+ },
+ "totalPeers":1
+}
+}
diff --git a/tests/topotests/bgp_features/r4/bgpd.conf b/tests/topotests/bgp_features/r4/bgpd.conf
new file mode 100644
index 0000000..cdf8f4e
--- /dev/null
+++ b/tests/topotests/bgp_features/r4/bgpd.conf
@@ -0,0 +1,34 @@
+!
+hostname r4
+log file bgpd.log
+!
+router bgp 65100
+ bgp router-id 192.168.100.1
+ timers bgp 3 10
+ coalesce-time 0
+ bgp log-neighbor-changes
+ no bgp ebgp-requires-policy
+ neighbor 192.168.101.1 remote-as 65000
+ neighbor 192.168.101.1 timers 3 10
+ neighbor 192.168.101.1 description Router R1 (eBGP AS 65000)
+ neighbor 192.168.101.1 timers connect 5
+ !
+ address-family ipv4 unicast
+ network 192.168.100.0/24
+ network 192.168.101.0/24
+ network 192.168.102.0/24
+ neighbor 192.168.101.1 default-originate
+ neighbor 192.168.101.1 route-map testmap-in in
+ neighbor 192.168.101.1 route-map testmap-out out
+ exit-address-family
+!
+!
+!
+route-map testmap-in permit 999
+!
+route-map testmap-out permit 999
+!
+!
+line vty
+!
+
diff --git a/tests/topotests/bgp_features/r4/show_bgp_metric_test.json b/tests/topotests/bgp_features/r4/show_bgp_metric_test.json
new file mode 100644
index 0000000..2329498
--- /dev/null
+++ b/tests/topotests/bgp_features/r4/show_bgp_metric_test.json
@@ -0,0 +1,27 @@
+{
+ "routerId": "192.168.100.1",
+ "localAS": 65100,
+ "routes": {
+ "192.168.1.0/24": [
+ {
+ "valid":true,
+ "bestpath":true,
+ "pathFrom":"external",
+ "prefix":"192.168.1.0",
+ "prefixLen":24,
+ "network":"192.168.1.0\/24",
+ "metric":1011,
+ "weight":0,
+ "peerId":"192.168.101.1",
+ "path":"65000",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.168.101.1",
+ "hostname":"r1",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+] } }
diff --git a/tests/topotests/bgp_features/r4/zebra.conf b/tests/topotests/bgp_features/r4/zebra.conf
new file mode 100644
index 0000000..08e3e1a
--- /dev/null
+++ b/tests/topotests/bgp_features/r4/zebra.conf
@@ -0,0 +1,18 @@
+!
+hostname r4
+log file zebra.log
+!
+interface lo
+ ip address 192.168.100.1/32
+ ipv6 address fc00:100::1/128
+!
+interface r4-eth0
+ description SW5 Stub Network
+ ip address 192.168.102.1/24
+ ipv6 address fc00:100:0:2::1/64
+!
+interface r4-eth1
+ description SW0 R1-R2 OSPF & BGP Network
+ ip address 192.168.101.2/24
+ ipv6 address fc00:100:0:1::2/64
+!
diff --git a/tests/topotests/bgp_features/r5/bgp_delayopen_neighbor.json b/tests/topotests/bgp_features/r5/bgp_delayopen_neighbor.json
new file mode 100644
index 0000000..4b97254
--- /dev/null
+++ b/tests/topotests/bgp_features/r5/bgp_delayopen_neighbor.json
@@ -0,0 +1,6 @@
+{
+ "192.168.201.1":{
+ "remoteAs":65000,
+ "bgpTimerDelayOpenTimeMsecs":30000
+ }
+}
diff --git a/tests/topotests/bgp_features/r5/bgp_delayopen_summary_connect.json b/tests/topotests/bgp_features/r5/bgp_delayopen_summary_connect.json
new file mode 100644
index 0000000..d7b4e77
--- /dev/null
+++ b/tests/topotests/bgp_features/r5/bgp_delayopen_summary_connect.json
@@ -0,0 +1,11 @@
+{
+"ipv4Unicast":{
+ "as":65200,
+ "peers":{
+ "192.168.201.1":{
+ "remoteAs":65000,
+ "state":"Connect"
+ }
+ }
+}
+}
diff --git a/tests/topotests/bgp_features/r5/bgp_delayopen_summary_established.json b/tests/topotests/bgp_features/r5/bgp_delayopen_summary_established.json
new file mode 100644
index 0000000..15cfb19
--- /dev/null
+++ b/tests/topotests/bgp_features/r5/bgp_delayopen_summary_established.json
@@ -0,0 +1,11 @@
+{
+"ipv4Unicast":{
+ "as":65200,
+ "peers":{
+ "192.168.201.1":{
+ "remoteAs":65000,
+ "state":"Established"
+ }
+ }
+}
+}
diff --git a/tests/topotests/bgp_features/r5/bgp_delayopen_summary_shutdown.json b/tests/topotests/bgp_features/r5/bgp_delayopen_summary_shutdown.json
new file mode 100644
index 0000000..94aceba
--- /dev/null
+++ b/tests/topotests/bgp_features/r5/bgp_delayopen_summary_shutdown.json
@@ -0,0 +1,11 @@
+{
+"ipv4Unicast":{
+ "as":65200,
+ "peers":{
+ "192.168.201.1":{
+ "remoteAs":65000,
+ "state":"Idle (Admin)"
+ }
+ }
+}
+}
diff --git a/tests/topotests/bgp_features/r5/bgp_summary.json b/tests/topotests/bgp_features/r5/bgp_summary.json
new file mode 100644
index 0000000..b854af5
--- /dev/null
+++ b/tests/topotests/bgp_features/r5/bgp_summary.json
@@ -0,0 +1,19 @@
+{
+"ipv4Unicast":{
+ "routerId":"192.168.200.1",
+ "as":65200,
+ "vrfName":"default",
+ "peerCount":1,
+ "peers":{
+ "192.168.201.1":{
+ "hostname":"r2",
+ "remoteAs":65000,
+ "outq":0,
+ "inq":0,
+ "pfxRcd":6,
+ "state":"Established"
+ }
+ },
+ "totalPeers":1
+}
+}
diff --git a/tests/topotests/bgp_features/r5/bgpd.conf b/tests/topotests/bgp_features/r5/bgpd.conf
new file mode 100644
index 0000000..6368fed
--- /dev/null
+++ b/tests/topotests/bgp_features/r5/bgpd.conf
@@ -0,0 +1,34 @@
+!
+hostname r5
+log file bgpd.log
+!
+router bgp 65200
+ bgp router-id 192.168.200.1
+ timers bgp 3 10
+ coalesce-time 0
+ bgp log-neighbor-changes
+ no bgp ebgp-requires-policy
+ neighbor 192.168.201.1 remote-as 65000
+ neighbor 192.168.201.1 timers 3 10
+ neighbor 192.168.201.1 description Router R2 (eBGP AS 65000)
+ neighbor 192.168.201.1 timers connect 5
+ !
+ address-family ipv4 unicast
+ network 192.168.200.0/24
+ network 192.168.201.0/24
+ network 192.168.202.0/24
+ neighbor 192.168.101.1 default-originate
+ neighbor 192.168.201.1 route-map testmap-in in
+ neighbor 192.168.201.1 route-map testmap-out out
+ exit-address-family
+!
+!
+!
+route-map testmap-in permit 999
+!
+route-map testmap-out permit 999
+!
+!
+line vty
+!
+
diff --git a/tests/topotests/bgp_features/r5/show_bgp_metric_test.json b/tests/topotests/bgp_features/r5/show_bgp_metric_test.json
new file mode 100644
index 0000000..e6608b4
--- /dev/null
+++ b/tests/topotests/bgp_features/r5/show_bgp_metric_test.json
@@ -0,0 +1,27 @@
+{
+ "routerId": "192.168.200.1",
+ "localAS": 65200,
+ "routes": {
+ "192.168.2.0/24": [
+ {
+ "valid":true,
+ "bestpath":true,
+ "pathFrom":"external",
+ "prefix":"192.168.2.0",
+ "prefixLen":24,
+ "network":"192.168.2.0\/24",
+ "metric":2022,
+ "weight":0,
+ "peerId":"192.168.201.1",
+ "path":"65000",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.168.201.1",
+ "hostname":"r2",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+] } }
diff --git a/tests/topotests/bgp_features/r5/zebra.conf b/tests/topotests/bgp_features/r5/zebra.conf
new file mode 100644
index 0000000..4d9064a
--- /dev/null
+++ b/tests/topotests/bgp_features/r5/zebra.conf
@@ -0,0 +1,18 @@
+!
+hostname r5
+log file zebra.log
+!
+interface lo
+ ip address 192.168.200.1/32
+ ipv6 address fc00:200::1/128
+!
+interface r5-eth0
+ description SW6 Stub Network
+ ip address 192.168.202.1/24
+ ipv6 address fc00:200:0:2::1/64
+!
+interface r5-eth1
+ description SW0 R1-R2 OSPF & BGP Network
+ ip address 192.168.201.2/24
+ ipv6 address fc00:200:0:1::2/64
+!
diff --git a/tests/topotests/bgp_features/test_bgp_features.dot b/tests/topotests/bgp_features/test_bgp_features.dot
new file mode 100644
index 0000000..70b126c
--- /dev/null
+++ b/tests/topotests/bgp_features/test_bgp_features.dot
@@ -0,0 +1,83 @@
+## GraphViz file for test_all_protocol_startup
+##
+## Color coding:
+#########################
+## Main FRR: #f08080 red
+## No protocol: #d0e0d0 gray
+## RIP: #19e3d9 Cyan
+## RIPng: #fcb314 dark yellow
+## OSPFv2: #32b835 Green
+## OSPFv3: #19e3d9 Cyan
+## ISIS IPv4 #33ff99 light green
+## ISIS IPv6 #9a81ec purple
+## BGP IPv4 #eee3d3 beige
+## BGP IPv6 #fdff00 yellow
+## LDP IPv4 #fedbe2 light pink
+##### Colors (see http://www.color-hex.com/)
+
+graph test_all_protocol_startup {
+ overlap=false;
+ constraint=false;
+
+ // title
+ labelloc="t";
+ label="Test Topologoy BGP Features";
+ rankdir = TB;
+
+ ######################
+ # Routers
+ ######################
+
+ # Main FRR Router with all protocols
+ R4 [shape=doubleoctagon, label="R4 FRR\nAS 65100\nlo: 192.168.100.1/32\nfc00:100::1/128", fillcolor="#f08080", style=filled];
+ R5 [shape=doubleoctagon, label="R5 FRR\nAS 65200\nlo: 192.168.200.1/32\nfc00:200::1/128", fillcolor="#f08080", style=filled];
+ #{ rank = same {R4, R5}}
+
+ R1 [shape=doubleoctagon, label="R1 FRR\nAS 65000\nlo: 192.168.0.1/32\nfc00::1/128", fillcolor="#f08080", style=filled];
+ R2 [shape=doubleoctagon, label="R2 FRR\nAS 65000\nlo: 192.168.0.1/32\nfc00::1/128", fillcolor="#f08080", style=filled];
+ #{ rank = same { R1, R2}}
+
+ R3 [shape=doubleoctagon, label="R3 FRR\nAS 65000\nlo: 192.168.0.1/32\nfc00::1/128", fillcolor="#f08080", style=filled];
+
+ ######################
+ # Network Lists
+ ######################
+
+ SW1_R1_R2 [label="SW1 OSPF & iBGP\n192.168.1.0/24\nfc00:0:0:1::/64", fillcolor="#32b835", style=filled];
+ SW2_R2_R3 [label="SW2 OSPF\n192.168.2.0/24\nfc00:0:0:2::/64", fillcolor="#19e3d9", style=filled];
+ SW3_R3_R1 [label="SW3 OSPF\n192.168.3.0/24\nfc00:0:0:3::/64", fillcolor="#19e3d9", style=filled];
+
+ SW4_R4_R1 [label="SW4 eBGP\n192.168.101.0/24\nfc00:100:0:1::/64", fillcolor="#fedbe2", style=filled];
+ SW5_R5_R2 [label="SW5 eBGP\n192.168.201.0/24\nfc00:200:0:1::/64", fillcolor="#fedbe2", style=filled];
+ #{ rank = same {SW4_R4_R1, SW5_R5_R2}}
+
+ SW6_STUB_R1 [label="SW6\n192.168.6.0/24\nfc00:0:0:6::/64", fillcolor="#d0e0d0", style=filled];
+ SW7_STUB_R2 [label="SW7\n192.168.7.0/24\nfc00:0:0:7::/64", fillcolor="#d0e0d0", style=filled];
+ SW8_STUB_R3 [label="SW8\n192.168.8.0/24\nfc00:0:0:8::/64", fillcolor="#d0e0d0", style=filled];
+ SW9_STUB_R4 [label="SW9\n192.168.102.0/24\nfc00:100:0:2::/64", fillcolor="#d0e0d0", style=filled];
+ SW10_STUB_R5 [label="SW10\n192.168.202.0/24\nfc00:200:0:2::/64", fillcolor="#d0e0d0", style=filled];
+
+
+ ######################
+ # Network Connections
+ ######################
+
+ R1 -- SW6_STUB_R1 [label = "eth0\n.1\n::1"];
+ R2 -- SW7_STUB_R2 [label = "eth0\n.1\n::1"];
+ R3 -- SW8_STUB_R3 [label = "eth0\n.1\n::1"];
+ R4 -- SW9_STUB_R4 [label = "eth0\n.1\n::1"];
+ R5 -- SW10_STUB_R5 [label = "eth0\n.1\n::1"];
+
+ R1 -- SW1_R1_R2 [label = "eth1\n.1\n::1"];
+ R1 -- SW3_R3_R1 [label = "eth2\n.1\n::1"];
+ R2 -- SW1_R1_R2 [label = "eth1\n.2\n::2"];
+ R2 -- SW2_R2_R3 [label = "eth2\n.1\n::1"];
+ R3 -- SW2_R2_R3 [label = "eth1\n.2\n::2"];
+ R3 -- SW3_R3_R1 [label = "eth2\n.2\n::2"];
+
+ R1 -- SW4_R4_R1 [label = "eth3\n.1\n::1"];
+ R2 -- SW5_R5_R2 [label = "eth3\n.1\n::1"];
+ R4 -- SW4_R4_R1 [label = "eth1\n.2\n::2"];
+ R5 -- SW5_R5_R2 [label = "eth1\n.2\n::2"];
+
+}
diff --git a/tests/topotests/bgp_features/test_bgp_features.pdf b/tests/topotests/bgp_features/test_bgp_features.pdf
new file mode 100644
index 0000000..cb52a54
--- /dev/null
+++ b/tests/topotests/bgp_features/test_bgp_features.pdf
Binary files differ
diff --git a/tests/topotests/bgp_features/test_bgp_features.py b/tests/topotests/bgp_features/test_bgp_features.py
new file mode 100644
index 0000000..ab44ba3
--- /dev/null
+++ b/tests/topotests/bgp_features/test_bgp_features.py
@@ -0,0 +1,1102 @@
+#!/usr/bin/env python
+
+#
+# test_bgp_features.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_bgp_features.py: Test various BGP features.
+"""
+
+import json
+import functools
+import os
+import sys
+import pytest
+import re
+import time
+
+# 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.
+
+pytestmark = [pytest.mark.bgpd, pytest.mark.ospfd]
+
+#####################################################
+#
+# Network Topology Definition
+#
+#####################################################
+
+
+def build_topo(tgen):
+ for rtrNum in range(1, 6):
+ tgen.add_router("r{}".format(rtrNum))
+
+ # create ExaBGP peers
+ for peer_num in range(1, 5):
+ tgen.add_exabgp_peer(
+ "peer{}".format(peer_num),
+ ip="192.168.101.{}".format(peer_num + 2),
+ defaultRoute="via 192.168.101.1",
+ )
+
+ # Setup Switches and connections
+ for swNum in range(1, 11):
+ tgen.add_switch("sw{}".format(swNum))
+
+ # Add connections to stub switches
+ tgen.gears["r1"].add_link(tgen.gears["sw6"])
+ tgen.gears["r2"].add_link(tgen.gears["sw7"])
+ tgen.gears["r3"].add_link(tgen.gears["sw8"])
+ tgen.gears["r4"].add_link(tgen.gears["sw9"])
+ tgen.gears["r5"].add_link(tgen.gears["sw10"])
+
+ # Add connections to R1-R2-R3 core
+ tgen.gears["r1"].add_link(tgen.gears["sw1"])
+ tgen.gears["r1"].add_link(tgen.gears["sw3"])
+ tgen.gears["r2"].add_link(tgen.gears["sw1"])
+ tgen.gears["r2"].add_link(tgen.gears["sw2"])
+ tgen.gears["r3"].add_link(tgen.gears["sw2"])
+ tgen.gears["r3"].add_link(tgen.gears["sw3"])
+
+ # Add connections to external R4/R5 Routers
+ tgen.gears["r1"].add_link(tgen.gears["sw4"])
+ tgen.gears["r4"].add_link(tgen.gears["sw4"])
+ tgen.gears["r2"].add_link(tgen.gears["sw5"])
+ tgen.gears["r5"].add_link(tgen.gears["sw5"])
+
+ # Add ExaBGP peers to sw4
+ tgen.gears["peer1"].add_link(tgen.gears["sw4"])
+ tgen.gears["peer2"].add_link(tgen.gears["sw4"])
+ tgen.gears["peer3"].add_link(tgen.gears["sw4"])
+ tgen.gears["peer4"].add_link(tgen.gears["sw4"])
+
+
+#####################################################
+#
+# Tests starting
+#
+#####################################################
+
+
+def setup_module(module):
+ tgen = Topogen(build_topo, module.__name__)
+ tgen.start_topology()
+
+ # Starting Routers
+ router_list = tgen.routers()
+ for rname, router in router_list.items():
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ if os.path.exists(os.path.join(CWD, "{}/bgpd.conf".format(rname))):
+ logger.info("{} uses BGPd".format(rname))
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+ if os.path.exists(os.path.join(CWD, "{}/ospfd.conf".format(rname))):
+ logger.info("{} uses OSPFd".format(rname))
+ router.load_config(
+ TopoRouter.RD_OSPF, os.path.join(CWD, "{}/ospfd.conf".format(rname))
+ )
+ if os.path.exists(os.path.join(CWD, "{}/ospf6d.conf".format(rname))):
+ logger.info("{} uses OSPF6d".format(rname))
+ router.load_config(
+ TopoRouter.RD_OSPF6, os.path.join(CWD, "{}/ospf6d.conf".format(rname))
+ )
+ router.start()
+
+
+def teardown_module(module):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_ospf_convergence():
+ "Test for OSPFv2 topology convergence"
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Check Router r1, r2 & r3 OSPF
+ for rtrNum in range(1, 4):
+ logger.info("Checking OSPFv2 convergence on router r{}".format(rtrNum))
+
+ router = tgen.gears["r{}".format(rtrNum)]
+ reffile = os.path.join(CWD, "r{}/ospf_neighbor.json".format(rtrNum))
+ expected = json.loads(open(reffile).read())
+
+ test_func = functools.partial(
+ topotest.router_json_cmp, router, "show ip ospf neighbor json", expected
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=60, wait=2)
+ assertmsg = "OSPF router R{} did not converge".format(rtrNum)
+ assert res is None, assertmsg
+
+
+def test_bgp_convergence():
+ "Test for BGP topology convergence"
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Check Router r1 & r2 BGP
+ for rtrNum in [1, 2, 4, 5]:
+ logger.info("Checking BGP IPv4 convergence on router r{}".format(rtrNum))
+
+ router = tgen.gears["r{}".format(rtrNum)]
+ reffile = os.path.join(CWD, "r{}/bgp_summary.json".format(rtrNum))
+ expected = json.loads(open(reffile).read())
+
+ test_func = functools.partial(
+ topotest.router_json_cmp, router, "show ip bgp summary json", expected
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=60, wait=2)
+ assertmsg = "BGP router R{} did not converge".format(rtrNum)
+ assert res is None, assertmsg
+
+ # tgen.mininet_cli()
+
+
+def test_bgp_shutdown():
+ "Test BGP instance shutdown"
+
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ tgen.net["r1"].cmd(
+ 'vtysh -c "conf t" -c "router bgp 65000" -c "bgp shutdown message ABCDabcd"'
+ )
+
+ # Check BGP Summary on local and remote routers
+ for rtrNum in [1, 2, 4]:
+ logger.info(
+ "Checking BGP Summary after shutdown of R1 BGP on router r{}".format(rtrNum)
+ )
+
+ router = tgen.gears["r{}".format(rtrNum)]
+ reffile = os.path.join(CWD, "r{}/bgp_shutdown_summary.json".format(rtrNum))
+ expected = json.loads(open(reffile).read())
+
+ test_func = functools.partial(
+ topotest.router_json_cmp, router, "show ip bgp summary json", expected
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=60, wait=2)
+ assertmsg = "BGP sessions on router R{} are in incorrect state (not down as expected?)".format(
+ rtrNum
+ )
+ assert res is None, assertmsg
+
+
+def test_bgp_shutdown_message():
+ "Test BGP Peer Shutdown Message"
+
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ for rtrNum in [2, 4]:
+ logger.info("Checking BGP shutdown received on router r{}".format(rtrNum))
+
+ shut_message = tgen.net["r{}".format(rtrNum)].cmd(
+ 'tail bgpd.log | grep "NOTIFICATION.*Cease/Administrative Shutdown"'
+ )
+ assertmsg = "BGP shutdown message not received on router R{}".format(rtrNum)
+ assert shut_message != "", assertmsg
+
+ assertmsg = "Incorrect BGP shutdown message received on router R{}".format(
+ rtrNum
+ )
+ assert "ABCDabcd" in shut_message, assertmsg
+
+ # tgen.mininet_cli()
+
+
+def test_bgp_no_shutdown():
+ "Test BGP instance no shutdown"
+
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ tgen.net["r1"].cmd('vtysh -c "conf t" -c "router bgp 65000" -c "no bgp shutdown"')
+
+ # Check BGP Summary on local and remote routers
+ for rtrNum in [1, 2, 4]:
+ logger.info(
+ "Checking BGP Summary after removing bgp shutdown on router r1 on router r{}".format(
+ rtrNum
+ )
+ )
+
+ router = tgen.gears["r{}".format(rtrNum)]
+ reffile = os.path.join(CWD, "r{}/bgp_summary.json".format(rtrNum))
+ expected = json.loads(open(reffile).read())
+
+ test_func = functools.partial(
+ topotest.router_json_cmp, router, "show ip bgp summary json", expected
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=60, wait=2)
+ assertmsg = "BGP sessions on router R{} are in incorrect state (not down as expected?)".format(
+ rtrNum
+ )
+ assert res is None, assertmsg
+
+
+def test_bgp_metric_config():
+ "Test BGP Changing metric values in route-maps"
+
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Configuring bgp route-maps on router r1 and r2 to update metric")
+
+ # # Adding the following configuration to r1:
+ # router bgp 65000
+ # address-family ipv4 unicast
+ # neighbor 192.168.0.2 route-map addmetric-in in
+ # neighbor 192.168.0.2 route-map addmetric-out out
+ # neighbor 192.168.101.2 route-map setmetric-in in
+ # neighbor 192.168.101.2 route-map setmetric-out out
+ # exit-address-family
+ # !
+ # ip prefix-list net1 seq 10 permit 192.168.101.0/24
+ # ip prefix-list net2 seq 20 permit 192.168.1.0/24
+ # !
+ # route-map setmetric-in permit 10
+ # match ip address prefix-list net1
+ # set metric 111
+ # !
+ # route-map setmetric-in permit 20
+ # !
+ # route-map setmetric-out permit 10
+ # match ip address prefix-list net2
+ # set metric 1011
+ # !
+ # route-map setmetric-out permit 20
+ # !
+ # route-map addmetric-in permit 10
+ # set metric +11
+ # !
+ # route-map addmetric-out permit 10
+ # set metric +12
+ # !
+
+ tgen.net["r1"].cmd(
+ 'vtysh -c "conf t" -c "router bgp 65000" '
+ + '-c "address-family ipv4 unicast" '
+ + '-c "neighbor 192.168.0.2 route-map addmetric-in in" '
+ + '-c "neighbor 192.168.0.2 route-map addmetric-out out" '
+ + '-c "neighbor 192.168.101.2 route-map setmetric-in in" '
+ + '-c "neighbor 192.168.101.2 route-map setmetric-out out" '
+ )
+ tgen.net["r1"].cmd(
+ 'vtysh -c "conf t" '
+ + '-c "ip prefix-list net1 seq 10 permit 192.168.101.0/24" '
+ + '-c "ip prefix-list net2 seq 20 permit 192.168.1.0/24"'
+ )
+ tgen.net["r1"].cmd(
+ 'vtysh -c "conf t" '
+ + '-c "route-map setmetric-in permit 10" '
+ + '-c "match ip address prefix-list net1" '
+ + '-c "set metric 111" '
+ + '-c "route-map setmetric-in permit 20"'
+ )
+ tgen.net["r1"].cmd(
+ 'vtysh -c "conf t" '
+ + '-c "route-map setmetric-out permit 10" '
+ + '-c "match ip address prefix-list net2" '
+ + '-c "set metric 1011" '
+ + '-c "route-map setmetric-out permit 20"'
+ )
+ tgen.net["r1"].cmd(
+ 'vtysh -c "conf t" '
+ + '-c "route-map addmetric-in permit 10" '
+ + '-c "set metric +11"'
+ )
+ tgen.net["r1"].cmd(
+ 'vtysh -c "conf t" '
+ + '-c "route-map addmetric-out permit 10" '
+ + '-c "set metric +12"'
+ )
+
+ # # Adding the following configuration to r2:
+ # router bgp 65000
+ # address-family ipv4 unicast
+ # neighbor 192.168.0.1 route-map subtractmetric-in in
+ # neighbor 192.168.0.1 route-map subtractmetric-out out
+ # neighbor 192.168.201.2 route-map setmetric-in in
+ # neighbor 192.168.201.2 route-map setmetric-out out
+ # exit-address-family
+ # !
+ # ip prefix-list net1 seq 10 permit 192.168.201.0/24
+ # ip prefix-list net2 seq 20 permit 192.168.2.0/24
+ # !
+ # route-map setmetric-in permit 10
+ # match ip address prefix-list net1
+ # set metric 222
+ # !
+ # route-map setmetric-in permit 20
+ # !
+ # route-map setmetric-out permit 10
+ # match ip address prefix-list net2
+ # set metric 2022
+ # !
+ # route-map setmetric-out permit 20
+ # !
+ # route-map subtractmetric-in permit 10
+ # set metric -22
+ # !
+ # route-map subtractmetric-out permit 10
+ # set metric -23
+ # !
+
+ tgen.net["r2"].cmd(
+ 'vtysh -c "conf t" -c "router bgp 65000" '
+ + '-c "address-family ipv4 unicast" '
+ + '-c "neighbor 192.168.0.1 route-map subtractmetric-in in" '
+ + '-c "neighbor 192.168.0.1 route-map subtractmetric-out out" '
+ + '-c "neighbor 192.168.201.2 route-map setmetric-in in" '
+ + '-c "neighbor 192.168.201.2 route-map setmetric-out out" '
+ )
+ tgen.net["r2"].cmd(
+ 'vtysh -c "conf t" '
+ + '-c "ip prefix-list net1 seq 10 permit 192.168.201.0/24" '
+ + '-c "ip prefix-list net2 seq 20 permit 192.168.2.0/24" '
+ )
+ tgen.net["r2"].cmd(
+ 'vtysh -c "conf t" '
+ + '-c "route-map setmetric-in permit 10" '
+ + '-c "match ip address prefix-list net1" '
+ + '-c "set metric 222" '
+ + '-c "route-map setmetric-in permit 20"'
+ )
+ tgen.net["r2"].cmd(
+ 'vtysh -c "conf t" '
+ + '-c "route-map setmetric-out permit 10" '
+ + '-c "match ip address prefix-list net2" '
+ + '-c "set metric 2022" '
+ + '-c "route-map setmetric-out permit 20"'
+ )
+ tgen.net["r2"].cmd(
+ 'vtysh -c "conf t" '
+ + '-c "route-map subtractmetric-in permit 10" '
+ + '-c "set metric -22"'
+ )
+ tgen.net["r2"].cmd(
+ 'vtysh -c "conf t" '
+ + '-c "route-map subtractmetric-out permit 10" '
+ + '-c "set metric -23"'
+ )
+
+ # Clear IN the bgp neighbors to make sure the route-maps are applied
+ tgen.net["r1"].cmd(
+ 'vtysh -c "clear ip bgp 192.168.0.2 in" ' + '-c "clear ip bgp 192.168.101.2 in"'
+ )
+ tgen.net["r2"].cmd(
+ 'vtysh -c "clear ip bgp 192.168.0.1 in" ' + '-c "clear ip bgp 192.168.201.2 in"'
+ )
+
+ # tgen.mininet_cli()
+
+ # Checking BGP config - should show the bgp metric settings in the route-maps
+ logger.info("Checking BGP configuration for correct 'set metric' values")
+
+ setmetric111 = (
+ tgen.net["r1"].cmd('vtysh -c "show running" | grep "^ set metric 111"').rstrip()
+ )
+ assertmsg = (
+ "'set metric 111' configuration applied to R1, but not visible in configuration"
+ )
+ assert setmetric111 == " set metric 111", assertmsg
+
+ setmetric222 = (
+ tgen.net["r2"].cmd('vtysh -c "show running" | grep "^ set metric 222"').rstrip()
+ )
+ assertmsg = (
+ "'set metric 222' configuration applied to R2, but not visible in configuration"
+ )
+ assert setmetric222 == " set metric 222", assertmsg
+
+
+def test_bgp_metric_add_config():
+ "Test BGP Changing metric values in route-maps"
+
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Checking BGP configuration for correct 'set metric' ADD value")
+
+ setmetricP11 = (
+ tgen.net["r1"].cmd('vtysh -c "show running" | grep "^ set metric +11"').rstrip()
+ )
+ assertmsg = (
+ "'set metric +11' configuration applied to R1, but not visible in configuration"
+ )
+ assert setmetricP11 == " set metric +11", assertmsg
+
+
+def test_bgp_metric_subtract_config():
+ "Test BGP Changing metric values in route-maps"
+
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Checking BGP configuration for correct 'set metric' SUBTRACT value")
+
+ setmetricM22 = (
+ tgen.net["r2"].cmd('vtysh -c "show running" | grep "^ set metric -22"').rstrip()
+ )
+ assertmsg = (
+ "'set metric -22' configuration applied to R2, but not visible in configuration"
+ )
+ assert setmetricM22 == " set metric -22", assertmsg
+
+
+def test_bgp_set_metric():
+ "Test setting metrics"
+
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Test absolute metric")
+
+ # Check BGP Summary on local and remote routers
+ for rtrNum in [1, 2, 4, 5]:
+ logger.info("Checking metrics of BGP router on r{}".format(rtrNum))
+
+ router = tgen.gears["r{}".format(rtrNum)]
+ reffile = os.path.join(CWD, "r{}/show_bgp_metric_test.json".format(rtrNum))
+ expected = json.loads(open(reffile).read())
+
+ test_func = functools.partial(
+ topotest.router_json_cmp, router, "show ip bgp json", expected
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=60, wait=2)
+ assertmsg = "BGP metrics on router r{} wrong".format(rtrNum)
+ assert res is None, assertmsg
+
+
+def test_bgp_remove_metric_rmaps():
+ "Test removing route-maps with metric changes again"
+
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Test absolute metric")
+
+ # Remove metric route-maps and relevant comfiguration
+
+ tgen.net["r1"].cmd(
+ 'vtysh -c "conf t" -c "router bgp 65000" '
+ + '-c "address-family ipv4 unicast" '
+ + '-c "no neighbor 192.168.0.2 route-map addmetric-in in" '
+ + '-c "no neighbor 192.168.0.2 route-map addmetric-out out" '
+ + '-c "no neighbor 192.168.101.2 route-map setmetric-in in" '
+ + '-c "no neighbor 192.168.101.2 route-map setmetric-out out" '
+ )
+ tgen.net["r1"].cmd(
+ 'vtysh -c "conf t" '
+ + '-c "no ip prefix-list net1" '
+ + '-c "no ip prefix-list net2"'
+ )
+ tgen.net["r1"].cmd('vtysh -c "conf t" ' + '-c "no route-map setmetric-in" ')
+ tgen.net["r1"].cmd('vtysh -c "conf t" ' + '-c "no route-map setmetric-out" ')
+ tgen.net["r1"].cmd('vtysh -c "conf t" ' + '-c "no route-map addmetric-in" ')
+ tgen.net["r1"].cmd('vtysh -c "conf t" ' + '-c "no route-map addmetric-out" ')
+
+ tgen.net["r2"].cmd(
+ 'vtysh -c "conf t" -c "router bgp 65000" '
+ + '-c "address-family ipv4 unicast" '
+ + '-c "no neighbor 192.168.0.1 route-map subtractmetric-in in" '
+ + '-c "no neighbor 192.168.0.1 route-map subtractmetric-out out" '
+ + '-c "no neighbor 192.168.201.2 route-map setmetric-in in" '
+ + '-c "no neighbor 192.168.201.2 route-map setmetric-out out" '
+ )
+ tgen.net["r2"].cmd(
+ 'vtysh -c "conf t" '
+ + '-c "no ip prefix-list net1" '
+ + '-c "no ip prefix-list net2" '
+ )
+ tgen.net["r2"].cmd('vtysh -c "conf t" ' + '-c "no route-map setmetric-in" ')
+ tgen.net["r2"].cmd('vtysh -c "conf t" ' + '-c "no route-map setmetric-out" ')
+ tgen.net["r2"].cmd('vtysh -c "conf t" ' + '-c "no route-map addmetric-in" ')
+ tgen.net["r2"].cmd('vtysh -c "conf t" ' + '-c "no route-map addmetric-out" ')
+
+ # Clear IN the bgp neighbors to make sure the route-maps are applied
+ tgen.net["r1"].cmd(
+ 'vtysh -c "clear ip bgp 192.168.0.2 in" ' + '-c "clear ip bgp 192.168.101.2 in"'
+ )
+ tgen.net["r2"].cmd(
+ 'vtysh -c "clear ip bgp 192.168.0.1 in" ' + '-c "clear ip bgp 192.168.201.2 in"'
+ )
+
+ # tgen.mininet_cli()
+
+ # Check BGP Summary on local and remote routers
+ for rtrNum in [1, 2]:
+ logger.info("Checking metrics of BGP router on r{}".format(rtrNum))
+
+ router = tgen.gears["r{}".format(rtrNum)]
+ reffile = os.path.join(CWD, "r{}/show_bgp.json".format(rtrNum))
+ expected = json.loads(open(reffile).read())
+
+ test_func = functools.partial(
+ topotest.router_json_cmp, router, "show ip bgp json", expected
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=60, wait=2)
+ assertmsg = "BGP routes on router r{} are wrong after removing metric route-maps".format(
+ rtrNum
+ )
+ assert res is None, assertmsg
+
+
+def test_bgp_norib():
+ "Test BGP disable RIB (Zebra) Route Install"
+
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Configuring 'bgp no-rib' on router r1")
+
+ tgen.net["r1"].cmd('vtysh -c "conf t" -c "bgp no-rib"')
+
+ # Checking BGP config - should show the "bgp no-rib" under the router bgp section
+ logger.info("Checking BGP configuration for 'bgp no-rib'")
+
+ norib_cfg = (
+ tgen.net["r1"].cmd('vtysh -c "show running bgpd" | grep "^bgp no-rib"').rstrip()
+ )
+
+ assertmsg = "'bgp no-rib' configuration applied, but not visible in configuration"
+ assert norib_cfg == "bgp no-rib", assertmsg
+
+
+def test_bgp_norib_routes():
+ "Test Routes in Zebra and BGP with the 'bgp-norib' configuration"
+
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Checking local BGP routes - they need to be gone from Zebra
+ logger.info("Checking Zebra routes after removing bgp shutdown on router r1")
+
+ router = tgen.gears["r1"]
+ reffile = os.path.join(CWD, "r1/ip_route_norib.json")
+ expected = json.loads(open(reffile).read())
+
+ test_func = functools.partial(
+ topotest.router_json_cmp, router, "show ip route json", expected
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=30, wait=2)
+ assertmsg = "Zebra IPv4 Routes after configuring 'bgp no-rib' (There should be no BGP routes in Zebra anymore)"
+ assert res is None, assertmsg
+
+ # Check BGP Summary on local and remote routers
+ for rtrNum in [1, 2, 4]:
+ logger.info(
+ "Checking BGP Summary after 'bgp no-rib' on router r1 on router r{}".format(
+ rtrNum
+ )
+ )
+
+ router = tgen.gears["r{}".format(rtrNum)]
+ reffile = os.path.join(CWD, "r{}/bgp_summary.json".format(rtrNum))
+ expected = json.loads(open(reffile).read())
+
+ test_func = functools.partial(
+ topotest.router_json_cmp, router, "show ip bgp summary json", expected
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=30, wait=2)
+ assertmsg = "BGP sessions on router R{} has incorrect routes after adding 'bgp no-rib on r1'".format(
+ rtrNum
+ )
+ assert res is None, assertmsg
+
+ # tgen.mininet_cli()
+
+
+def test_bgp_disable_norib():
+ "Test BGP disabling the no-RIB (Zebra) Route Install"
+
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Configuring 'no bgp no-rib' on router r1")
+
+ tgen.net["r1"].cmd('vtysh -c "conf t" -c "no bgp no-rib"')
+
+ # Checking BGP config - should show the "bgp no-rib" under the router bgp section
+ logger.info("Checking BGP configuration for 'bgp no-rib'")
+
+ norib_cfg = (
+ tgen.net["r1"]
+ .cmd('vtysh -c "show running bgpd" | grep "^ bgp no-rib"')
+ .rstrip()
+ )
+
+ assertmsg = (
+ "'no bgp no-rib'configuration applied, but still visible in configuration"
+ )
+ assert norib_cfg == "", assertmsg
+
+
+def test_bgp_disable_norib_routes():
+ "Test Routes in Zebra and BGP with the 'bgp-norib' configuration"
+
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Checking local BGP routes - they need to be gone from Zebra
+ logger.info("Checking Zebra routes after removing bgp shutdown on router r1")
+
+ router = tgen.gears["r1"]
+ reffile = os.path.join(CWD, "r1/ip_route.json")
+ expected = json.loads(open(reffile).read())
+
+ test_func = functools.partial(
+ topotest.router_json_cmp, router, "show ip route json", expected
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=30, wait=2)
+ assertmsg = "Zebra IPv4 Routes wrong after removing the 'bgp no-rib'"
+ assert res is None, assertmsg
+
+ # Check BGP Summary on local and remote routers
+ for rtrNum in [1, 2, 4]:
+ logger.info(
+ "Checking BGP Summary after removing the 'bgp no-rib' on router r1 on router r{}".format(
+ rtrNum
+ )
+ )
+
+ router = tgen.gears["r{}".format(rtrNum)]
+ reffile = os.path.join(CWD, "r{}/bgp_summary.json".format(rtrNum))
+ expected = json.loads(open(reffile).read())
+
+ test_func = functools.partial(
+ topotest.router_json_cmp, router, "show ip bgp summary json", expected
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=30, wait=2)
+ assertmsg = "BGP sessions on router R{} has incorrect routes after removing 'bgp no-rib on r1'".format(
+ rtrNum
+ )
+ assert res is None, assertmsg
+
+ # tgen.mininet_cli()
+
+
+def test_bgp_delayopen_without():
+ "Optional test of BGP functionality and behaviour without DelayOpenTimer enabled to establish a reference for following tests"
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # part 1: no delay r1 <=> no delay r4
+ logger.info(
+ "Starting optional test of BGP functionality without DelayOpenTimer enabled to establish a reference for following tests"
+ )
+
+ # 1.1 enable peering shutdown
+ logger.info("Enable shutdown of peering between r1 and r4")
+ tgen.net["r1"].cmd(
+ 'vtysh -c "conf t" -c "router bgp 65000" -c "neighbor 192.168.101.2 shutdown"'
+ )
+ tgen.net["r4"].cmd(
+ 'vtysh -c "conf t" -c "router bgp 65100" -c "neighbor 192.168.101.1 shutdown"'
+ )
+
+ # 1.2 wait for peers to shut down (poll output)
+ for router_num in [1, 4]:
+ logger.info(
+ "Checking BGP summary after enabling shutdown of peering on r{}".format(
+ router_num
+ )
+ )
+ router = tgen.gears["r{}".format(router_num)]
+ reffile = os.path.join(
+ CWD, "r{}/bgp_delayopen_summary_shutdown.json".format(router_num)
+ )
+ expected = json.loads(open(reffile).read())
+ test_func = functools.partial(
+ topotest.router_json_cmp, router, "show ip bgp summary json", expected
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=3, wait=1)
+ assertmsg = "BGP session on r{} did not shut down peer".format(router_num)
+ assert res is None, assertmsg
+
+ # 1.3 disable peering shutdown
+ logger.info("Disable shutdown of peering between r1 and r4")
+ tgen.net["r1"].cmd(
+ 'vtysh -c "conf t" -c "router bgp 65000" -c "no neighbor 192.168.101.2 shutdown"'
+ )
+ tgen.net["r4"].cmd(
+ 'vtysh -c "conf t" -c "router bgp 65100" -c "no neighbor 192.168.101.1 shutdown"'
+ )
+
+ # 1.4 wait for peers to establish connection (poll output)
+ for router_num in [1, 4]:
+ logger.info(
+ "Checking BGP summary after disabling shutdown of peering on r{}".format(
+ router_num
+ )
+ )
+ router = tgen.gears["r{}".format(router_num)]
+ reffile = os.path.join(
+ CWD, "r{}/bgp_delayopen_summary_established.json".format(router_num)
+ )
+ expected = json.loads(open(reffile).read())
+ test_func = functools.partial(
+ topotest.router_json_cmp, router, "show ip bgp summary json", expected
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=5, wait=1)
+ assertmsg = (
+ "BGP session on r{} did not establish a connection with peer".format(
+ router_num
+ )
+ )
+ assert res is None, assertmsg
+
+ # tgen.mininet_cli()
+
+ # end test_bgp_delayopen_without
+
+
+def test_bgp_delayopen_singular():
+ "Test of BGP functionality and behaviour with DelayOpenTimer enabled on one side of the peering"
+
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # part 2: delay 240s r1 <=> no delay r4
+ logger.info(
+ "Starting test of BGP functionality and behaviour with DelayOpenTimer enabled on one side of the peering"
+ )
+
+ # 2.1 enable peering shutdown
+ logger.info("Enable shutdown of peering between r1 and r4")
+ tgen.net["r1"].cmd(
+ 'vtysh -c "conf t" -c "router bgp 65000" -c "neighbor 192.168.101.2 shutdown"'
+ )
+ tgen.net["r4"].cmd(
+ 'vtysh -c "conf t" -c "router bgp 65100" -c "neighbor 192.168.101.1 shutdown"'
+ )
+
+ # 2.2 wait for peers to shut down (poll output)
+ for router_num in [1, 4]:
+ logger.info(
+ "Checking BGP summary after disabling shutdown of peering on r{}".format(
+ router_num
+ )
+ )
+ router = tgen.gears["r{}".format(router_num)]
+ reffile = os.path.join(
+ CWD, "r{}/bgp_delayopen_summary_shutdown.json".format(router_num)
+ )
+ expected = json.loads(open(reffile).read())
+ test_func = functools.partial(
+ topotest.router_json_cmp, router, "show ip bgp summary json", expected
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=3, wait=1)
+ assertmsg = "BGP session on r{} did not shut down peer".format(router_num)
+ assert res is None, assertmsg
+
+ # 2.3 set delayopen on R1 to 240
+ logger.info("Setting DelayOpenTime for neighbor r4 to 240 seconds on r1")
+ tgen.net["r1"].cmd(
+ 'vtysh -c "conf t" -c "router bgp 65000" -c "neighbor 192.168.101.2 timers delayopen 240"'
+ )
+
+ # 2.4 check config (poll output)
+ logger.info("Checking BGP neighbor configuration after setting DelayOpenTime on r1")
+ router = tgen.gears["r1"]
+ reffile = os.path.join(CWD, "r1/bgp_delayopen_neighbor.json")
+ expected = json.loads(open(reffile).read())
+ test_func = functools.partial(
+ topotest.router_json_cmp, router, "show bgp neighbors json", expected
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=3, wait=1)
+ assertmsg = "BGP session on r1 failed to set DelayOpenTime for r4"
+ assert res is None, assertmsg
+
+ # 2.5 disable peering shutdown
+ logger.info("Disable shutdown of peering between r1 and r4")
+ tgen.net["r1"].cmd(
+ 'vtysh -c "conf t" -c "router bgp 65000" -c "no neighbor 192.168.101.2 shutdown"'
+ )
+ tgen.net["r4"].cmd(
+ 'vtysh -c "conf t" -c "router bgp 65100" -c "no neighbor 192.168.101.1 shutdown"'
+ )
+
+ # 2.6 wait for peers to establish connection (poll output)
+ for router_num in [1, 4]:
+ logger.info(
+ "Checking BGP summary after disabling shutdown of peering on r{}".format(
+ router_num
+ )
+ )
+ router = tgen.gears["r{}".format(router_num)]
+ reffile = os.path.join(
+ CWD, "r{}/bgp_delayopen_summary_established.json".format(router_num)
+ )
+ expected = json.loads(open(reffile).read())
+ test_func = functools.partial(
+ topotest.router_json_cmp, router, "show ip bgp summary json", expected
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=5, wait=1)
+ assertmsg = (
+ "BGP session on r{} did not establish a connection with peer".format(
+ router_num
+ )
+ )
+ assert res is None, assertmsg
+
+ # 2.7 unset delayopen on R1
+ logger.info("Disabling DelayOpenTimer for neighbor r4 on r1")
+ tgen.net["r1"].cmd(
+ 'vtysh -c "conf t" -c "router bgp 65000" -c "no neighbor 192.168.101.2 timers delayopen"'
+ )
+
+ # 2.8 check config (poll output)
+ logger.info(
+ "Checking BGP neighbor configuration after disabling DelayOpenTimer on r1"
+ )
+ delayopen_cfg = (
+ tgen.net["r1"]
+ .cmd('vtysh -c "show bgp neighbors json" | grep "DelayOpenTimeMsecs"')
+ .rstrip()
+ )
+ assertmsg = "BGP session on r1 failed disable DelayOpenTimer for peer r4"
+ assert delayopen_cfg == "", assertmsg
+
+ # tgen.mininet_cli()
+
+ # end test_bgp_delayopen_singular
+
+
+def test_bgp_delayopen_dual():
+ "Test of BGP functionality and behaviour with DelayOpenTimer enabled on both sides of the peering with different timer intervals"
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # part 3: delay 60s R2 <=> delay 30s R5
+ logger.info(
+ "Starting test of BGP functionality and behaviour with DelayOpenTimer enabled on both sides of the peering with different timer intervals"
+ )
+
+ # 3.1 enable peering shutdown
+ logger.info("Enable shutdown of peering between r2 and r5")
+ tgen.net["r2"].cmd(
+ 'vtysh -c "conf t" -c "router bgp 65000" -c "neighbor 192.168.201.2 shutdown"'
+ )
+ tgen.net["r5"].cmd(
+ 'vtysh -c "conf t" -c "router bgp 65200" -c "neighbor 192.168.201.1 shutdown"'
+ )
+
+ # 3.2 wait for peers to shut down (pool output)
+ for router_num in [2, 5]:
+ logger.info(
+ "Checking BGP summary after disabling shutdown of peering on r{}".format(
+ router_num
+ )
+ )
+ router = tgen.gears["r{}".format(router_num)]
+ reffile = os.path.join(
+ CWD, "r{}/bgp_delayopen_summary_shutdown.json".format(router_num)
+ )
+ expected = json.loads(open(reffile).read())
+ test_func = functools.partial(
+ topotest.router_json_cmp, router, "show ip bgp summary json", expected
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=3, wait=1)
+ assertmsg = "BGP session on r{} did not shut down peer".format(router_num)
+ assert res is None, assertmsg
+
+ # 3.3 set delayopen on R2 to 60s and on R5 to 30s
+ logger.info("Setting DelayOpenTime for neighbor r5 to 60 seconds on r2")
+ tgen.net["r2"].cmd(
+ 'vtysh -c "conf t" -c "router bgp 65000" -c "neighbor 192.168.201.2 timers delayopen 60"'
+ )
+ logger.info("Setting DelayOpenTime for neighbor r2 to 30 seconds on r5")
+ tgen.net["r5"].cmd(
+ 'vtysh -c "conf t" -c "router bgp 65200" -c "neighbor 192.168.201.1 timers delayopen 30"'
+ )
+
+ # 3.4 check config (poll output)
+ for router_num in [2, 5]:
+ logger.info(
+ "Checking BGP neighbor configuration after setting DelayOpenTime on r{}i".format(
+ router_num
+ )
+ )
+ router = tgen.gears["r{}".format(router_num)]
+ reffile = os.path.join(
+ CWD, "r{}/bgp_delayopen_neighbor.json".format(router_num)
+ )
+ expected = json.loads(open(reffile).read())
+ test_func = functools.partial(
+ topotest.router_json_cmp, router, "show bgp neighbors json", expected
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=3, wait=1)
+ assertmsg = "BGP session on r{} failed to set DelayOpenTime".format(router_num)
+ assert res is None, assertmsg
+
+ ## 3.5 disable peering shutdown
+ logger.info("Disable shutdown of peering between r2 and r5")
+ tgen.net["r2"].cmd(
+ 'vtysh -c "conf t" -c "router bgp 65000" -c "no neighbor 192.168.201.2 shutdown"'
+ )
+ tgen.net["r5"].cmd(
+ 'vtysh -c "conf t" -c "router bgp 65200" -c "no neighbor 192.168.201.1 shutdown"'
+ )
+
+ ## 3.6 wait for peers to reach connect or active state (poll output)
+ delay_start = int(time.time())
+ for router_num in [2, 5]:
+ logger.info(
+ "Checking BGP summary after disabling shutdown of peering on r{}".format(
+ router_num
+ )
+ )
+ router = tgen.gears["r{}".format(router_num)]
+ reffile = os.path.join(
+ CWD, "r{}/bgp_delayopen_summary_connect.json".format(router_num)
+ )
+ expected = json.loads(open(reffile).read())
+ test_func = functools.partial(
+ topotest.router_json_cmp, router, "show ip bgp summary json", expected
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=3, wait=1)
+ assertmsg = "BGP session on r{} did not enter Connect state with peer".format(
+ router_num
+ )
+ assert res is None, assertmsg
+
+ ## 3.7 wait for peers to establish connection (poll output)
+ for router_num in [2, 5]:
+ logger.info(
+ "Checking BGP summary after disabling shutdown of peering on r{}".format(
+ router_num
+ )
+ )
+ router = tgen.gears["r{}".format(router_num)]
+ reffile = os.path.join(
+ CWD, "r{}/bgp_delayopen_summary_established.json".format(router_num)
+ )
+ expected = json.loads(open(reffile).read())
+ test_func = functools.partial(
+ topotest.router_json_cmp, router, "show ip bgp summary json", expected
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=35, wait=1)
+ assertmsg = (
+ "BGP session on r{} did not establish a connection with peer".format(
+ router_num
+ )
+ )
+ assert res is None, assertmsg
+
+ delay_stop = int(time.time())
+ assertmsg = "BGP peering between r2 and r5 was established before DelayOpenTimer (30sec) on r2 could expire"
+ assert (delay_stop - delay_start) > 30, assertmsg
+
+ # 3.8 unset delayopen on R2 and R5
+ logger.info("Disabling DelayOpenTimer for neighbor r5 on r2")
+ tgen.net["r2"].cmd(
+ 'vtysh -c "conf t" -c "router bgp 65000" -c "no neighbor 192.168.201.2 timers delayopen"'
+ )
+ logger.info("Disabling DelayOpenTimer for neighbor r2 on r5")
+ tgen.net["r5"].cmd(
+ 'vtysh -c "conf t" -c "router bgp 65200" -c "no neighbor 192.168.201.1 timers delayopen"'
+ )
+
+ # 3.9 check config (poll output)
+ for router_num in [2, 5]:
+ logger.info(
+ "Checking BGP neighbor configuration after disabling DelayOpenTimer on r{}".format(
+ router_num
+ )
+ )
+ delayopen_cfg = (
+ tgen.net["r{}".format(router_num)]
+ .cmd('vtysh -c "show bgp neighbors json" | grep "DelayOpenTimeMsecs"')
+ .rstrip()
+ )
+ assertmsg = "BGP session on r{} failed disable DelayOpenTimer".format(
+ router_num
+ )
+ assert delayopen_cfg == "", assertmsg
+
+ # tgen.mininet_cli()
+
+ # end test_bgp_delayopen_dual
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))