From 4501fbcaa8850d050a3f674f39e16eb59cf36aff Mon Sep 17 00:00:00 2001 From: Martin Winter Date: Sat, 8 Apr 2017 03:49:43 -0700 Subject: [PATCH] all-protocol-startup: Add test suite which runs all protocols at once and verifies startup and spurious errors of each Signed-off-by: Martin Winter --- .../all-protocol-startup/r1/bgpd.conf | 47 ++ .../all-protocol-startup/r1/isisd.conf | 21 + .../all-protocol-startup/r1/ldpd.conf | 25 + .../all-protocol-startup/r1/ospf6d.conf | 16 + .../all-protocol-startup/r1/ospfd.conf | 13 + .../all-protocol-startup/r1/rip_status.ref | 15 + .../all-protocol-startup/r1/ripd.conf | 12 + .../all-protocol-startup/r1/ripng_status.ref | 14 + .../all-protocol-startup/r1/ripngd.conf | 11 + .../all-protocol-startup/r1/show_bgp_ipv4.ref | 7 + .../all-protocol-startup/r1/show_bgp_ipv6.ref | 7 + .../r1/show_bgp_ipv6_summary.ref | 21 + .../r1/show_ip_bgp_summary.ref | 15 + .../r1/show_ip_ospf_interface.ref | 22 + .../r1/show_ipv6_ospf6_interface | 0 .../r1/show_ipv6_ospf6_interface.ref | 46 + .../r1/show_isis_interface_detail.ref | 28 + .../r1/show_mpls_ldp_interface.ref | 3 + .../all-protocol-startup/r1/zebra.conf | 72 ++ .../test_all_protocol_startup.dot | 61 ++ .../test_all_protocol_startup.pdf | Bin 0 -> 21760 bytes .../test_all_protocol_startup.py | 785 ++++++++++++++++++ 22 files changed, 1241 insertions(+) create mode 100644 tests/topotests/all-protocol-startup/r1/bgpd.conf create mode 100644 tests/topotests/all-protocol-startup/r1/isisd.conf create mode 100644 tests/topotests/all-protocol-startup/r1/ldpd.conf create mode 100644 tests/topotests/all-protocol-startup/r1/ospf6d.conf create mode 100644 tests/topotests/all-protocol-startup/r1/ospfd.conf create mode 100644 tests/topotests/all-protocol-startup/r1/rip_status.ref create mode 100644 tests/topotests/all-protocol-startup/r1/ripd.conf create mode 100644 tests/topotests/all-protocol-startup/r1/ripng_status.ref create mode 100644 tests/topotests/all-protocol-startup/r1/ripngd.conf create mode 100644 tests/topotests/all-protocol-startup/r1/show_bgp_ipv4.ref create mode 100644 tests/topotests/all-protocol-startup/r1/show_bgp_ipv6.ref create mode 100644 tests/topotests/all-protocol-startup/r1/show_bgp_ipv6_summary.ref create mode 100644 tests/topotests/all-protocol-startup/r1/show_ip_bgp_summary.ref create mode 100644 tests/topotests/all-protocol-startup/r1/show_ip_ospf_interface.ref create mode 100644 tests/topotests/all-protocol-startup/r1/show_ipv6_ospf6_interface create mode 100644 tests/topotests/all-protocol-startup/r1/show_ipv6_ospf6_interface.ref create mode 100644 tests/topotests/all-protocol-startup/r1/show_isis_interface_detail.ref create mode 100644 tests/topotests/all-protocol-startup/r1/show_mpls_ldp_interface.ref create mode 100644 tests/topotests/all-protocol-startup/r1/zebra.conf create mode 100644 tests/topotests/all-protocol-startup/test_all_protocol_startup.dot create mode 100644 tests/topotests/all-protocol-startup/test_all_protocol_startup.pdf create mode 100755 tests/topotests/all-protocol-startup/test_all_protocol_startup.py diff --git a/tests/topotests/all-protocol-startup/r1/bgpd.conf b/tests/topotests/all-protocol-startup/r1/bgpd.conf new file mode 100644 index 0000000000..9ef8695896 --- /dev/null +++ b/tests/topotests/all-protocol-startup/r1/bgpd.conf @@ -0,0 +1,47 @@ +log file /tmp/r1-bgpd.log +! +! +router bgp 100 + bgp router-id 192.168.0.1 + bgp log-neighbor-changes + neighbor 192.168.7.10 remote-as 100 + neighbor 192.168.7.20 remote-as 200 + neighbor fc00:0:0:8::1000 remote-as 100 + neighbor fc00:0:0:8::2000 remote-as 200 + ! + address-family ipv4 unicast + network 192.168.0.0/24 + neighbor 192.168.7.10 route-map bgp-map in + neighbor 192.168.7.10 filter-list bgp-filter-v4 out + neighbor 192.168.7.20 route-map bgp-map in + neighbor 192.168.7.20 filter-list bgp-filter-v4 out + exit-address-family + ! + address-family ipv6 unicast + network fc00::/64 + neighbor fc00:0:0:8::1000 activate + neighbor fc00:0:0:8::1000 route-map bgp-map in + neighbor fc00:0:0:8::1000 filter-list bgp-filter-v6 out + neighbor fc00:0:0:8::2000 activate + neighbor fc00:0:0:8::2000 route-map bgp-map in + neighbor fc00:0:0:8::2000 filter-list bgp-filter-v6 out + exit-address-family +! +! +ip prefix-list bgp-filter-v4 description dummy-test-prefix-list +ip prefix-list bgp-filter-v4 seq 5 permit 192.168.0.0/24 +! +ipv6 prefix-list bgp-filter-v4 seq 5 permit fc00::/64 +ipv6 prefix-list bgp-filter-v6 description dummy-test-prefix-list-v6 +! +route-map bgp-map permit 10 + set community 100:100 additive + set local-preference 100 +! +route-map bgp-map permit 20 + set metric 10 + set local-preference 200 +! +line vty +! + diff --git a/tests/topotests/all-protocol-startup/r1/isisd.conf b/tests/topotests/all-protocol-startup/r1/isisd.conf new file mode 100644 index 0000000000..b63bc3f8d3 --- /dev/null +++ b/tests/topotests/all-protocol-startup/r1/isisd.conf @@ -0,0 +1,21 @@ +log file /tmp/r1-isisd.log +! +debug isis events +! +! +interface r1-eth5 + ip router isis test + isis circuit-type level-1 +! +interface r1-eth6 + ipv6 router isis test + isis circuit-type level-2-only +! +! +router isis test + net 00.0001.00b0.64bc.43a0.00 + metric-style wide + log-adjacency-changes +! +line vty +! diff --git a/tests/topotests/all-protocol-startup/r1/ldpd.conf b/tests/topotests/all-protocol-startup/r1/ldpd.conf new file mode 100644 index 0000000000..b69007181e --- /dev/null +++ b/tests/topotests/all-protocol-startup/r1/ldpd.conf @@ -0,0 +1,25 @@ +log file /tmp/r1-ldpd.log +! +debug mpls ldp event +debug mpls ldp zebra +! +! +mpls ldp + router-id 192.168.0.1 + ! + address-family ipv4 + discovery transport-address 192.168.9.1 + ! + interface r1-eth9 + ! + ! + address-family ipv6 + discovery transport-address fc00:0:0:9::1 + ! + interface r1-eth9 + ! + ! +! +! +line vty +! diff --git a/tests/topotests/all-protocol-startup/r1/ospf6d.conf b/tests/topotests/all-protocol-startup/r1/ospf6d.conf new file mode 100644 index 0000000000..1a14eaac77 --- /dev/null +++ b/tests/topotests/all-protocol-startup/r1/ospf6d.conf @@ -0,0 +1,16 @@ +log file /tmp/r1-ospf6d.log +! +debug ospf6 lsa unknown +debug ospf6 zebra +debug ospf6 interface +debug ospf6 neighbor +! +interface r1-eth4 +! +router ospf6 + router-id 192.168.0.1 + log-adjacency-changes + interface r1-eth4 area 0.0.0.0 +! +line vty +! diff --git a/tests/topotests/all-protocol-startup/r1/ospfd.conf b/tests/topotests/all-protocol-startup/r1/ospfd.conf new file mode 100644 index 0000000000..1a901b9643 --- /dev/null +++ b/tests/topotests/all-protocol-startup/r1/ospfd.conf @@ -0,0 +1,13 @@ +log file /tmp/r1-ospfd.log +! +debug ospf event +debug ospf zebra +! +router ospf + ospf router-id 192.168.0.1 + log-adjacency-changes + network 192.168.0.0/24 area 0.0.0.0 + network 192.168.3.0/24 area 0.0.0.0 +! +line vty +! diff --git a/tests/topotests/all-protocol-startup/r1/rip_status.ref b/tests/topotests/all-protocol-startup/r1/rip_status.ref new file mode 100644 index 0000000000..4a5255fe13 --- /dev/null +++ b/tests/topotests/all-protocol-startup/r1/rip_status.ref @@ -0,0 +1,15 @@ +Routing Protocol is "rip" + Sending updates every 30 seconds with +/-50%, next due in XX seconds + Timeout after 180 seconds, garbage collect after 120 seconds + Outgoing update filter list for all interface is not set + Incoming update filter list for all interface is not set + Default redistribution metric is 1 + Redistributing: + Default version control: send version 2, receive version 2 + Interface Send Recv Key-chain + r1-eth1 2 2 + Routing for Networks: + 192.168.1.0/26 + Routing Information Sources: + Gateway BadPackets BadRoutes Distance Last Update + Distance: (default is 120) diff --git a/tests/topotests/all-protocol-startup/r1/ripd.conf b/tests/topotests/all-protocol-startup/r1/ripd.conf new file mode 100644 index 0000000000..899bfda984 --- /dev/null +++ b/tests/topotests/all-protocol-startup/r1/ripd.conf @@ -0,0 +1,12 @@ +log file /tmp/r1-ripd.log +! +debug rip events +debug rip zebra +! +router rip + version 2 + network 192.168.1.0/26 +! +line vty +! + diff --git a/tests/topotests/all-protocol-startup/r1/ripng_status.ref b/tests/topotests/all-protocol-startup/r1/ripng_status.ref new file mode 100644 index 0000000000..5d67c1467a --- /dev/null +++ b/tests/topotests/all-protocol-startup/r1/ripng_status.ref @@ -0,0 +1,14 @@ +Routing Protocol is "RIPng" + Sending updates every 30 seconds with +/-50%, next due in XX seconds + Timeout after 180 seconds, garbage collect after 120 seconds + Outgoing update filter list for all interface is not set + Incoming update filter list for all interface is not set + Default redistribution metric is 1 + Redistributing: + Default version control: send version 1, receive version 1 + Interface Send Recv + r1-eth2 1 1 + Routing for Networks: + fc00:0:0:2::/64 + Routing Information Sources: + Gateway BadPackets BadRoutes Distance Last Update diff --git a/tests/topotests/all-protocol-startup/r1/ripngd.conf b/tests/topotests/all-protocol-startup/r1/ripngd.conf new file mode 100644 index 0000000000..9b1f556277 --- /dev/null +++ b/tests/topotests/all-protocol-startup/r1/ripngd.conf @@ -0,0 +1,11 @@ +log file /tmp/r1-ripngd.log +! +debug ripng events +debug ripng zebra +! +router ripng + network fc00:0:0:2::/64 +! +line vty +! + diff --git a/tests/topotests/all-protocol-startup/r1/show_bgp_ipv4.ref b/tests/topotests/all-protocol-startup/r1/show_bgp_ipv4.ref new file mode 100644 index 0000000000..3be6cd3d7b --- /dev/null +++ b/tests/topotests/all-protocol-startup/r1/show_bgp_ipv4.ref @@ -0,0 +1,7 @@ +BGP table version is 1, local router ID is 192.168.0.1 +Status codes: s suppressed, d damped, h history, * valid, > best, = multipath, + i internal, r RIB-failure, S Stale, R Removed +Origin codes: i - IGP, e - EGP, ? - incomplete + + Network Next Hop Metric LocPrf Weight Path +*> 192.168.0.0 0.0.0.0 0 32768 i diff --git a/tests/topotests/all-protocol-startup/r1/show_bgp_ipv6.ref b/tests/topotests/all-protocol-startup/r1/show_bgp_ipv6.ref new file mode 100644 index 0000000000..fffee63c6b --- /dev/null +++ b/tests/topotests/all-protocol-startup/r1/show_bgp_ipv6.ref @@ -0,0 +1,7 @@ +BGP table version is 1, local router ID is 192.168.0.1 +Status codes: s suppressed, d damped, h history, * valid, > best, = multipath, + i internal, r RIB-failure, S Stale, R Removed +Origin codes: i - IGP, e - EGP, ? - incomplete + + Network Next Hop Metric LocPrf Weight Path +*> fc00::/64 :: 0 32768 i diff --git a/tests/topotests/all-protocol-startup/r1/show_bgp_ipv6_summary.ref b/tests/topotests/all-protocol-startup/r1/show_bgp_ipv6_summary.ref new file mode 100644 index 0000000000..2b1aff16cb --- /dev/null +++ b/tests/topotests/all-protocol-startup/r1/show_bgp_ipv6_summary.ref @@ -0,0 +1,21 @@ + +IPv6 Unicast Summary: +BGP router identifier 192.168.0.1, local AS number 100 vrf-id 0 +BGP table version 1 +RIB entries 1, using XXXX bytes of memory +Peers 4, using XXXX KiB of memory + +Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd +fc00:0:0:8::1000 4 100 0 0 0 0 0 never Active +fc00:0:0:8::2000 4 200 0 0 0 0 0 never Active + +Total number of neighbors 2 + +IPv6 Multicast Summary: +No IPv6 Multicast neighbor is configured + +IPv6 VPN Summary: +No IPv6 VPN neighbor is configured + +IPv6 Encap Summary: +No IPv6 Encap neighbor is configured diff --git a/tests/topotests/all-protocol-startup/r1/show_ip_bgp_summary.ref b/tests/topotests/all-protocol-startup/r1/show_ip_bgp_summary.ref new file mode 100644 index 0000000000..9ec43848cf --- /dev/null +++ b/tests/topotests/all-protocol-startup/r1/show_ip_bgp_summary.ref @@ -0,0 +1,15 @@ +BGP router identifier 192.168.0.1, local AS number 100 vrf-id 0 +BGP table version 1 +RIB entries 1, using XXXX bytes of memory +Peers 4, using XXXX KiB of memory + +Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/ +PfxRcd +192.168.7.10 4 100 0 0 0 0 0 never +Active +192.168.7.20 4 200 0 0 0 0 0 never +Active +fc00:0:0:8::1000 4 100 0 0 0 0 0 never +Active +fc00:0:0:8::2000 4 200 0 0 0 0 0 never +Active diff --git a/tests/topotests/all-protocol-startup/r1/show_ip_ospf_interface.ref b/tests/topotests/all-protocol-startup/r1/show_ip_ospf_interface.ref new file mode 100644 index 0000000000..d134fb1c69 --- /dev/null +++ b/tests/topotests/all-protocol-startup/r1/show_ip_ospf_interface.ref @@ -0,0 +1,22 @@ +r1-eth0 is up + ifindex 2, MTU 1500 bytes, BW XX Mbit + Internet Address 192.168.0.1/24, Broadcast 192.168.0.255, Area 0.0.0.0 + MTU mismatch detection:enabled + Router ID 192.168.0.1, Network Type BROADCAST, Cost: 10 + Transmit Delay is 1 sec, State DR, Priority 1 + No backup designated router on this network + Multicast group memberships: OSPFAllRouters OSPFDesignatedRouters + Timer intervals configured, Hello 10s, Dead 40s, Wait 40s, Retransmit 5 + Hello due in XX.XXXs + Neighbor Count is 0, Adjacent neighbor count is 0 +r1-eth3 is up + ifindex 5, MTU 1500 bytes, BW XX Mbit + Internet Address 192.168.3.1/26, Broadcast 192.168.3.63, Area 0.0.0.0 + MTU mismatch detection:enabled + Router ID 192.168.0.1, Network Type BROADCAST, Cost: 10 + Transmit Delay is 1 sec, State DR, Priority 1 + No backup designated router on this network + Multicast group memberships: OSPFAllRouters OSPFDesignatedRouters + Timer intervals configured, Hello 10s, Dead 40s, Wait 40s, Retransmit 5 + Hello due in XX.XXXs + Neighbor Count is 0, Adjacent neighbor count is 0 diff --git a/tests/topotests/all-protocol-startup/r1/show_ipv6_ospf6_interface b/tests/topotests/all-protocol-startup/r1/show_ipv6_ospf6_interface new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/topotests/all-protocol-startup/r1/show_ipv6_ospf6_interface.ref b/tests/topotests/all-protocol-startup/r1/show_ipv6_ospf6_interface.ref new file mode 100644 index 0000000000..6fbf40bbb8 --- /dev/null +++ b/tests/topotests/all-protocol-startup/r1/show_ipv6_ospf6_interface.ref @@ -0,0 +1,46 @@ +lo is up, type LOOPBACK + Interface ID: 1 + OSPF not enabled on this interface +r1-eth0 is up, type BROADCAST + Interface ID: 2 + OSPF not enabled on this interface +r1-eth1 is up, type BROADCAST + Interface ID: 3 + OSPF not enabled on this interface +r1-eth2 is up, type BROADCAST + Interface ID: 4 + OSPF not enabled on this interface +r1-eth3 is up, type BROADCAST + Interface ID: 5 + OSPF not enabled on this interface +r1-eth4 is up, type BROADCAST + Interface ID: 6 + Internet Address: + inet : 192.168.4.1/26 + inet6: fc00:0:0:4::1/64 + inet6: fe80::XXXX:XXXX:XXXX:XXXX/64 + Instance ID 0, Interface MTU 1500 (autodetect: 1500) + MTU mismatch detection: enabled + Area ID 0.0.0.0, Cost 10 + State DR, Transmit Delay 1 sec, Priority 1 + Timer intervals configured: + Hello 10, Dead 40, Retransmit 5 + DR: 192.168.0.1 BDR: 0.0.0.0 + Number of I/F scoped LSAs is 1 + 0 Pending LSAs for LSUpdate in Time 00:00:00 [thread off] + 0 Pending LSAs for LSAck in Time 00:00:00 [thread off] +r1-eth5 is up, type BROADCAST + Interface ID: 7 + OSPF not enabled on this interface +r1-eth6 is up, type BROADCAST + Interface ID: 8 + OSPF not enabled on this interface +r1-eth7 is up, type BROADCAST + Interface ID: 9 + OSPF not enabled on this interface +r1-eth8 is up, type BROADCAST + Interface ID: 10 + OSPF not enabled on this interface +r1-eth9 is up, type BROADCAST + Interface ID: 11 + OSPF not enabled on this interface diff --git a/tests/topotests/all-protocol-startup/r1/show_isis_interface_detail.ref b/tests/topotests/all-protocol-startup/r1/show_isis_interface_detail.ref new file mode 100644 index 0000000000..ebf7ab50cd --- /dev/null +++ b/tests/topotests/all-protocol-startup/r1/show_isis_interface_detail.ref @@ -0,0 +1,28 @@ +Area test: + Interface: r1-eth5, State: Up, Active, Circuit Id: 0x1 + Type: lan, Level: L1, SNPA: XXXX.XXXX.XXXX + Level-1 Information: + Metric: 10, Active neighbors: 0 + Hello interval: 3, Holddown count: 10 (pad) + CNSP interval: 10, PSNP interval: 2 + LAN Priority: 64, is not DIS + IP Prefix(es): + 192.168.5.1/26 + IPv6 Link-Locals: + fe80::XXXX:XXXX:XXXX:XXXX/64 + IPv6 Prefixes: + fc00:0:0:5::1/64 + + Interface: r1-eth6, State: Up, Active, Circuit Id: 0x1 + Type: lan, Level: L2, SNPA: XXXX.XXXX.XXXX + Level-2 Information: + Metric: 10, Active neighbors: 0 + Hello interval: 3, Holddown count: 10 (pad) + CNSP interval: 10, PSNP interval: 2 + LAN Priority: 64, is not DIS + IP Prefix(es): + 192.168.6.1/26 + IPv6 Link-Locals: + fe80::XXXX:XXXX:XXXX:XXXX/64 + IPv6 Prefixes: + fc00:0:0:6::1/64 diff --git a/tests/topotests/all-protocol-startup/r1/show_mpls_ldp_interface.ref b/tests/topotests/all-protocol-startup/r1/show_mpls_ldp_interface.ref new file mode 100644 index 0000000000..c6bb01c34b --- /dev/null +++ b/tests/topotests/all-protocol-startup/r1/show_mpls_ldp_interface.ref @@ -0,0 +1,3 @@ +AF Interface State Uptime Hello Timers ac +ipv4 r1-eth9 ACTIVE xx:xx:xx 5/15 0 +ipv6 r1-eth9 ACTIVE xx:xx:xx 5/15 0 diff --git a/tests/topotests/all-protocol-startup/r1/zebra.conf b/tests/topotests/all-protocol-startup/r1/zebra.conf new file mode 100644 index 0000000000..afb28e0768 --- /dev/null +++ b/tests/topotests/all-protocol-startup/r1/zebra.conf @@ -0,0 +1,72 @@ +log file /tmp/r1-zebra.log +! +hostname r1 +! +interface r1-eth0 + description to sw0 - no routing protocol + ip address 192.168.0.1/24 + ipv6 address fc00:0:0:0::1/64 +! +interface r1-eth1 + description to sw1 - RIP interface + ip address 192.168.1.1/26 + ipv6 address fc00:0:0:1::1/64 + no link-detect +! +interface r1-eth2 + description to sw2 - RIPng interface + ip address 192.168.2.1/26 + ipv6 address fc00:0:0:2::1/64 + no link-detect +! +interface r1-eth3 + description to sw3 - OSPFv2 interface + ip address 192.168.3.1/26 + ipv6 address fc00:0:0:3::1/64 + no link-detect +! +interface r1-eth4 + description to sw4 - OSPFv3 interface + ip address 192.168.4.1/26 + ipv6 address fc00:0:0:4::1/64 + no link-detect +! +interface r1-eth5 + description to sw5 - ISIS IPv4 interface + ip address 192.168.5.1/26 + ipv6 address fc00:0:0:5::1/64 + no link-detect +! +interface r1-eth6 + description to sw6 - ISIS IPv6 interface + ip address 192.168.6.1/26 + ipv6 address fc00:0:0:6::1/64 + no link-detect +! +interface r1-eth7 + description to sw7 - BGP IPv4 interface + ip address 192.168.7.1/26 + ipv6 address fc00:0:0:7::1/64 + no link-detect +! +interface r1-eth8 + description to sw8 - BGP IPv6 interface + ip address 192.168.8.1/26 + ipv6 address fc00:0:0:8::1/64 + no link-detect +! +interface r1-eth9 + description to sw9 - LDP interface + ip address 192.168.9.1/26 + ipv6 address fc00:0:0:9::1/64 + + no link-detect +! +! +ip forwarding +ipv6 forwarding +! +! +line vty +! + diff --git a/tests/topotests/all-protocol-startup/test_all_protocol_startup.dot b/tests/topotests/all-protocol-startup/test_all_protocol_startup.dot new file mode 100644 index 0000000000..f39f8f87b8 --- /dev/null +++ b/tests/topotests/all-protocol-startup/test_all_protocol_startup.dot @@ -0,0 +1,61 @@ +## 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 { + + // title + labelloc="t"; + label="Test Topologoy All Protocols Startup"; + + ###################### + # Routers + ###################### + + # Main FRR Router with all protocols + R1 [shape=doubleoctagon, label="R1 FRR\nMain Router", fillcolor="#f08080", style=filled]; + + ###################### + # Network Lists + ###################### + + SW0_STUB [label="SW0 (no protocol)\n192.168.1.0/24\nfc00:0:0:0::/64", fillcolor="#d0e0d0", style=filled]; + + SW1_RIP [label="SW1 RIP\n192.168.1.0/24\nfc00:0:0:1::/64", fillcolor="#19e3d9", style=filled]; + SW2_RIPNG [label="SW2 RIPng\n192.168.2.0/24\nfc00:0:0:2::/64", fillcolor="#fcb314", style=filled]; + SW3_OSPF [label="SW3 OSPFv2\n192.168.3.0/24\nfc00:0:0:3::/64", fillcolor="#32b835", style=filled]; + SW4_OSPFV3 [label="SW4 OSPFv3\n192.168.4.0/24\nfc00:0:0:4::/64", fillcolor="#19e3d9", style=filled]; + SW5_ISIS_V4 [label="SW5 ISIS IPv4\n192.168.5.0/24\nfc00:0:0:5::/64", fillcolor="#33ff99", style=filled]; + SW6_ISIS_V6 [label="SW6 ISIS IPv6\n192.168.6.0/24\nfc00:0:0:6::/64", fillcolor="#9a81ec", style=filled]; + SW7_BGP_V4 [label="SW7 BGP IPv4\n192.168.7.0/24\nfc00:0:0:7::/64", fillcolor="#eee3d3", style=filled]; + SW8_BGP_V6 [label="SW8 BGP IPv6\n192.168.8.0/24\nfc00:0:0:8::/64", fillcolor="#fdff00", style=filled]; + SW9_LDP [label="SW9 LDP\n192.168.9.0/24\nfc00:0:0:9::/64", fillcolor="#fedbe2", style=filled]; + + ###################### + # Network Connections + ###################### + R1 -- SW0_STUB [label = "eth0\n.1\n::1"]; + R1 -- SW1_RIP [label = "eth1\n.1\n::1"]; + R1 -- SW2_RIPNG [label = "eth2\n.1\n::1"]; + R1 -- SW3_OSPF [label = "eth3\n.1\n::1"]; + R1 -- SW4_OSPFV3 [label = "eth4\n.1\n::1"]; + R1 -- SW5_ISIS_V4 [label = "eth5\n.1\n::1"]; + R1 -- SW6_ISIS_V6 [label = "eth6\n.1\n::1"]; + R1 -- SW7_BGP_V4 [label = "eth7\n.1\n::1"]; + R1 -- SW8_BGP_V6 [label = "eth8\n.1\n::1"]; + R1 -- SW9_LDP [label = "eth9\n.1\n::1"]; + +} diff --git a/tests/topotests/all-protocol-startup/test_all_protocol_startup.pdf b/tests/topotests/all-protocol-startup/test_all_protocol_startup.pdf new file mode 100644 index 0000000000000000000000000000000000000000..23f69bcddf813e0f60f7a8f93cb384212bc3bba4 GIT binary patch literal 21760 zcmag^19T-_*Y^v@wrzB5+qP}nwmPE&?|aV~@2I_Nt(psS zu9`LW`2F`PQh8xf8U|V>DAIw$+rzWcyS$l!At+`7dICE`ODJw`0y=3ETQg^K0+w%+ zA_1MKg|)MZ<9BIo;A|pnVq|A*Lcq%l<>c&WVqgR14%n2T6}vHn7_$9B_3H3QsJu<* z8=1{+k3gK#$d9+j4HCH$VPIiG!5Zh6TPu!6$F+ewB{>Vqv?=6@-hP&)q%x^DA$1q& zakD69cFBvy_5R^5mWtiQiCq2O?q${0!9p98J&ST24PR4x^jPiT;B^*tX6r}q$5y(I ztyIPFaW=HFl{r6*eb>G_?pFfmWTbt1=e_&!_Lf_kd+FElMaNgVl6raX)v4gOD0i3r zdAq9%-q}4*cwgb6d-qzhu6aFux(4t0RC{GN!8dV{JBe?n0c+;F_tl)XUEoAY-bH$* z`P=1X>6d7KfzN}dX5+Hn1&yXnP4h4JoYu$5H}kEG*6H<`bw$UghVs#e;uh16=1!^N z^jsN>)~BvE8ND$dsV=NewVHX}?4X+?FCEjw0yk~8>0f`mjJj}ecC4GNq&goaU8?x6 ztnkk9+S9lmK=tAXeR4HX8jP+Oe~&Gc$Fhd6O5raz8EQ3eXqM2bnr7*{kVDTb_gGe$ zsy}ox)J~3H*43(xgJCW2t!Yi3RM%#`XnyQ3RyJX43-ec}ZQ(_&2Kd`8@-5DO@^EZ$ z-TnDgbKwLX3418|T}ykI0i2^M72P{%d%8YcO!XT+9~GH0let;(!pX!;`??dlW{=EA znlQMgF7fV<@RH;g=Lc; zI`y4!?0^t1Q7(#I<`Ro5&I%s6qs4&BKm>oe-Phs7|0xG{BimPgso@dYr)IeOgpRI6 z>dsJz9Lru5Fi_qb0lnh+=iv5sMwX3TCf$8VS8$JG7_Z8iJ@>X3x)nN-KJqAiR~=43 zid$za3kH0R5d{D^*v+U(=&usv8kg1w#85^UqaYWUpLZb;0FI|pP>v4No%VXBV_5`? zT!eu<^K6#Zr^- zqK0Eyd&!8zL1QkDc-5#5P)r?X9(!QcCe~_K6$yLkm65Ubb0a7H@A8mSo z;LIBa*Ee?tT=24|iWeThZWrce599@#!Tg20&y#6gAca(K|BI%@uCk7V9(`u~HyRnz zj1VpXCqL?p6za?}%v;({2Z9jVf*Bus58@0w7%ni+GiTRfc-a9{pswlz!;P;;ZuGv_y`d+9pB z59>Z4&n88&*+(aSe9KvJeX1d|yeHz5d}HUA&DiBg{^ocWF0RYC4*m9cuJ^=N&3P7X4`eEwv&6Y$A z!FRtQ--QxJ_R~(_A94D-yG^H==-;EBr-ivwZ|Fu#?FpZsgnWD0_>g*tuZJfDSX%JBflk{jTlxF362s#<^n9m z*1@k=jZy#rq5M;!=8Y7*RsdSKq>Nd|)q=}NEVpCcloxnce`7bLVt@niVO+$Q;lkjA zuN7~oW+QB)G+7BDYVYU?Tq7klJX?XFOG*Xq6w9%iM(f+aUuR%BG4gG9^(c|4Yr2Wb zsJm1oBL{NXToF7Q&XJ)_Ky<}T3>!h9v7I)KxluII3C*62dh_zK<)V9^6Fln+;-j{{ zwg&Bd1b3}b6Ee?9h**LOfb#sHE$HKN;dy1HvAekd&2{(&d^OvGwQbwx{6o#0`cy7r%6 z)3Jkzd&+!b#Bc+9MY}$6z&}xSsY;1a`e#H3sVtaK+3`6CE6Z6TnH1(*;c8Kn@kpMi zPucse*2FJ8F6__Hgi~`FOluZk==NEp(xVCp0qVlvH42VJ1%NOv_0>tXIF_&x%lZh%3SBL*t^#bllhUpdEyfc7hnvfnX8s#*+y4C~~F4a^0g#+tf4 z+h$i^$wVD$Y#u9=fvluL8sSa|VKsSsazq-rl8te5>nc6UKwz=% zA@%ICI$}_thjre>83;QgCNX~jStwcl!ooOrD%ac@p-c?SK)AIV_0SLjb-TZtcJ$s+ z<}EX_-OXiLTX;4+!5UBU4>`s9%pXSPn*_ej(P770u(Prw6(l!rnu8PshvFj7E9wY% zv)43zg_~Jsziw~IhOl-6HnoYpEn^{av7nht*U`lrMsXBs;TkuL2e5V%XYc68g|uVs z;h5oxJ9Gt~Rfu}_c(`vkh1`8u`&QHC_}x{E&yG4gv+W%oucaDRd8H$Ic4ZD7zWQ}`@17lr*d$(r2u9`h0 z$N})6^i~VsrO-iuRF;fjxTxz#7%)q7smVmNi>{XF+_m~6sXV3nnsdtvB%bAJ|DzS; zMpl+$skoul$Qa_oW9X5&uMe^eDAD?d;DtJ;nbxtx!m~lf>B5^mLaut%sZN?0(~Sap z#>@D<;PL`1mO6#=T+Q3(-M#|MJN@_5t(fBK&r{cw{~??l5nionOHPa@N zO<3V(+$Bat-ISjO3xe9VYXm)U;I8;`FU7>|aZj&KKgYiSyX$?LpiFFy|AWrowZFvu z7qkDCjO?t;e_Q{l|1TO>_OLf0pp!Q+`{(RvV(U!6^e>q!nmF0HI2xHa5wQMi5VEs% z{%&_7_)GKO=q_VoY+)d1=T4wS|7~DkV_+d*Vr0{S`o{PFIQl#Azt}JDXlJBk;!L3R z?M+yefKJ)O-I+j#fKJHH+RjnQ-oVI&;IBFma$+E0`)7V$-fva#?eZV9vN8h!`(N|- z?0@yae;jc9F9-k86%2oa`HoKZdmVHFf5nCEx3VCh6E<k0@8adPe_6}E^$;4g>VUfd7#i>GFM?xQ4~Z9Rb%BIK(R0)BM}tnpg_ZA z$Xf*YpE6A&Amb zB;@gdCm;+2Ksa^4o?TN@5V2=rpoRBNp7iuG@u7ytOIm;9_I2uRc`~P^FTZ#qHX#x) z04R|~R&HN1^h2N|rG`OF#xIbu`(z5nPzFY{e8_?-qWytd>&Ma~s`k;eRI-D7ER8A5 z4(6PwcKNLg(%r%+kbLbl(jBuxZ*Y@NWr+-c!>1qf^Uqn*0Q4y7dK1TF`PSi#A}E-b z;kQ5l5J>|Z9gc93FC6AM0PZDb2N59Q5{4y+%V`#eCnKh>Hw{WJh743m{W7~h-KD4R z8)0JT(fw=fQbYhrHEhz&<1ealE-o~dj?7=WSGVzel|FbzJl|Aq$j+y81fp^@wyn>r z=sM8=9!WGaaT~glRR9`o!1xb$tK_Z-0B%768n?3U@ItM169)ER$e|<8&#j#RbFFBp zPT1aZ1MSATLph$($1mShxk}La0*ED0nM_0uOG-4B*AVR8JK?18rk0D}F+5r9*GX~lso_(AFgcvk?R1Q=ETU4ty` z0Tu#0XFy~FS?$5JLDYI+?V(}(#rUB@d!^_Bw*o9600DXcH(}3m;U{?Ts z`>)n<;XsJ>jqeD%qh^7l_pI+qwxIFCHTR+KVqXJLhv@YsLhz430MCl5Ltx(s3&yFF z03s4v#S;|)m5XG=!4+Y*MvKQg8~}rbF+f?ul1PV) zhpdw@ag@_o%n?I_UstY%B$q&s6h47ZKIsP;iku{lh~TO$hh!_i2fv3i%eTVr9Hl@>!}Esa(=>s#~faZ7#VUp`YYu$$JZsLN9-> zQb1vyYQE@hV;@h5gh)m~vf)p|48w54pgopB1=5a$fP`iwxpMx~x;fHfLM*}gVvo6& zMwv#=HIp@ZTrswyxB0}=!F&9Z&U;7`QWLGiABQ-HSceT`ieP>8`p-;?n8i_vQSDK& zcg#nv)BDrwthE-pUmX<5FO;^F-pNGCrpbWGu@%xPc8e&B*%dYwatrj9WR?b&tCnwz zw3X4*rPFRX)7g5=UkC4Df9l%8JzHKaANv3B{7J;h!0N)n#8SaZWgcR|%&^TE%{a_B zW*%-d*Mx2Y(LB^VZqlVsPQRQ`HYII{(o)=8k% zViRcAZdP&=l#`-Ur_-xdxXR~M$gR#T>K5zP@*C@!Az0Io6v*r?%a6$KHpnq3+%+Pu zh_9TbEYvLI8e%v4?GSOpyRSu77oIJVAQ3$(qqMTHrL5mJ-8cp&Hk@-Re%@e5}nT@uIrbm52tweK1jjutW0jh4(_^0l*e{CScO2^1& zIMj0As9~yP^Qfu1oMzj#`@)ASL#J*NtzEW#`VsDt=#A`+0h}kyJ**S%X~o&~M|-f( zBI4P}Zp+k7)IK=57x}MwiPG(CjVX#L*r`Hj81!rO1sV*;S%=*g9LIQCW7;S^cl-PW zmG$I(&9m1DndRtX*8!V>%@v;2kCrzocq#aJvB=@1(!^t|X=vS_skLhHYPHP?Pli{P zSEan1yy3jjyvSXyU6np`&juerAFi*Pcgxquugh<8AnYJjkS9<@Afh0u;Jna`kVv2| zApO07z3qYcbaQ$n+6!nvg6~4EA>5EGFgmEOP8hV*%vEIP9xW>FzV2=yG=?I=LIdsM zu_JRMVv*5kQfO|Xqhf<1i()b&ULvU?QmN|H8Vv`cQJPT%B|K>O*r;A4u8!qTbDL6O z`{#R5`S*eaeBQP4wQJ<__*5$U*X7o<%iNW_j;{vhak&|?O|^T z$3s-d(KkBJChzeesloNZv%;wZI^jkVH4>;2`#^F6O*=02dba@wG)&vmVm_rG#G^HXX{NN`tOu=8tuHoB z8>%hWQ;BqE9}LI$BKG7+HxkaaHGI@wHYXl~FFK1Ki{IRKTp`>xHc#8`)YA<$bXR9; zc66!_CvFRFo7>gSyHpLd9Q5HWVvS=P8O!QBC2K9k7EAvW{RzN|%{c1(gipmO z`A6>K?-|Vq&HSZ}rSRWHtQKCz!}!DyfxbH5@uzKG{B<7oi`~ zOL*-$DSGF=7N<>DHl3&T4Ie4{)iGV5KF6;*Z**IaZ9a!FU)k8ekzlWvv|V0bx*I&F zK3gBN;N|eTd=sARALbuM=lccZP;!(x6@1kni_goZ<(>EEdCU6K4L{9dLtBLCzLH;R z<@!OV%crSC8%6(!Rf|nWy+mz#{<-N@ZW;i-rQ54 zdbIr%eE0T$a`!(N`VVZgGBExZSO0?TU)whWO9%-G8aSC46Z}P3MFO4wcKHk6|3&8i zVRNVdPul(q&@SJQ%s@aVWnt{}jn|C-PWZnlnStT|m{iEX*}&S)>|gSC`VaE|4_E(1 z?f>5>{vmNXB^N{Ie*}ZFql?ME;r(63zm4Le@*?W;RLT}MCQdYpb~XmK{{pe*e*LVf*c0#=z*GuK!~ZwQzKD7BV+*{8kg+y9EaSxnN-YUZR?X zv9tL|9|^J{q6I&?|;YsE!h|u30PVG zX6$e6dkz-X|J45Lh4uTsva|oq-`^g8+v%bHj`&;q+xB-B4(7jN>Hq&={>S=1=f5-l zH_rdW0rhYBU+dqJ{-5-uZ|+p6=w6aF{g|1*F8lZby4BWqyuEsXwO(`Id8 z_We|R-~Yd<75o-?P+ByM^h^Xa%#7^cQt#Uz10x&bw|tZMevT}R1Z>T$O}>572{;-3 zm5^-TH~(94{d+<4Hx+b32KM467G~zoP^@gM1awNyCN`>nN2vd6C17U#&aaGt`#&lE zcJVjef1Q7C5ScI%F#Ib@|K|z)$MD}J{#W|_N0|P5$w0us&ce?8Jb2%(i?Sg zmEC)a+U@Al>B%R(efz+6bP`H~j4Gf`hyV~MSVSYL3JgI*TVO$rGB855Cj#0Mva&as z@~4VrQ>~_+wk4I~wq=D)Ko`xy(N|V0V3S_=)zfF!_S4&?@f0tUSh`!YD{fs)ZMJZ$K$^+xV9YsyN(v&o7~MGE zu)dh81T5Mld2>ji`Yd{&TzY5 zjk8tJv%MHyID*q%Y%U(FWc<6+9pORnR3#$pVGX|cL%v{!HX^I2F+k8hAxrE@@J08B zU6J~T$3Q;mOg)HZ3ja8gxxox|S#%irL?Bl5kU%uIOP2OHe>IvVW@}1lX>oo^iWP4J z-%pQI(05Y2AacCfH(jlgyUt*(8w_Uf7yH>>uAvv*UO583xjnDLdo+pTW#6OaoExjF z2P?McrrMqM8TXSeS=nDj*tH+#9ls4ae!F(KuDD-By0b?Ju+gL&t)&{Rb)`LyrahLV z{U$Gw8QS>+Y>wj0M^XAD^{KGd9Xr>>A^EoR28Z8c`+Kk0pOA1yJ^Ze_odXc#X1uKTsM@JOJ5dL) zery|I2LONg?O?1!Z`i4k7t5^pH#J=8;oW*va4WnJ>($ zo#=PK?+0~l9PvWoKj=ux-Rnp{Fw8g-E)EMlzPaN+ObBe3T8xlnUhUsYZ~HAq-Ddl9 zb@0AaT`k_bbfF{Ng37UV3Fidn^kH@=DZV|HG{4}?SAv{bZeBgyxKfI zJ)t2B5s(wJvO6XDih4A9j(r|488Ujt8Rg8Q-Q#1GNm?Hqih=X8x;nYJ@Ojpr@8dmD zUspZ3WuB?)?yH~ArZ3H(Eg48EO-j~do3z#y80xPPjk zk(*j3J2~tl0*0%OV{5^k01gtyK*_v;+n6bnNC;r(CEaXiZV1>yTtBG--R!`_Ou6$m zn)^1oUIRlBSVHVAV2>JxJ&q=&eSX`G{B{%hZWH*5zyN1L8CX&zjpG&mv>PcL&kJcfa>^?!JV8`Xrz0Qe)}9&}`G=L1X;# zg>AYmY{MGUV+r?r*liWroDaB%D)QgY67C%CZNtbq8%>sS_ulrq>Xv=~1S*v&kt=Dz zit0hYyeyx;Gz6?Kpc!A5-`HXh7=TY}DmY(JCqGjjU|zp+&2K1?IP7X6_&{!rFkYeJ z5isv}Xl>w!{u7;hE@mtlA#(rUIlaU)Xv}CT1-9DJg3oMaFf93EvsCtjSdAbIY_Cu{7#mE_TiwWE9_|G8ikL%9=p$;o;de~7pTwTft@!H=mV#{tg@J?b zt_mmz{5kv-n~|HvyT|ZAc7}>+D8rZQQ#vKkVJyR?#_Iste*j>CY%0LC7h!9I+&U0& zM(TtezS=2g&<n$zwTpO@IU+LA-PvP!q$BJ>F|3amouQuoExu&?s!Kp3$ z0vVxlh^r`MRXnx;reQ!{$?1g+dIQ(Pd}pbGh;#<{Qe_t{Og3j(i@FScYK6xYsm+ho zukI28PU{Ey-HQXaFL$$yQUIfjbNPtY8N4NUWrlDEaYv!mZ#%{l&&B0_vGds54E_ba zl>_8M3`3;{CkD!0h$h3IC=Z?iUZ+dFKP+U<$LSvfc+SgjHdAU2a9D@F)qu0SZ}BYp z&g2c0JLFgTLo(0%dV;+vd<}Hi;Sciz;6)LSa};fX*&Nq*vXv%SUGdtZI&*pQo-@|7 zGBYz%&qg|rpyrcQpvIKjJ1aPqgDwbGWVV6F zke7Wd7*xcHI>T;CyY(Q5{Gfik5)lP`0>N8nmbBP$J zDN}l)#8SaIM7AEcFr5(eJRe`n^1V-rSe4-}@XdN!g3PRD65MSSXzG(L?Fv0R_%G<* zL(GUlp6ulUm`avGz@g$a1HeG<@GCMS!GQu7Y#%?g=*Wg`nl`1$hz8{?Td-IrCmf?t z3k78)nM1KoKR$_?J~77YOGzax1nJDoJOqWVcKVuIe%_?%^0n4LxA`(F2F5SHkBd|A zDYkJUL4Q&zCrdwP27Yeov4DN}xUU7f{@9+!IKO^+96w}m^r+Nc64XH11@cSu5h(0N zpMGR}V11%qnPYBeNbeaY@z0@52RHyQFB^^aQV?3^L;x=fh%*1<0*0OGi7W6!2p`w> zPsTErub`Jwp%e;NLb&b*JsW!|I_R0#Lx@mn;+elq82Ru1hQ#m?f>p0soeYm&54Q&i z^C@e^KN+)IQf@ByiVdSoFd?14^^IyThUhM~)oPP6EzPwO6BseqjYLI0-CfTb5hUWex-Eu|Ll zoPB-_f*U1NO9(f5eCQVe82e?cQy+8CFY@;4{W+|4chSuu>-hGHoGY}&c|)m9@8N1s zBHgger{*h;aHJ`a@PcYSz5xY*|ISI@aoDG8(tl3VN3R~M%SsLMp+)Pj!OXStH5seb z7OIJ2unR<#ZOlPv=&Zg1 zp(aF{;~xryCp$9>3c$B9@#m*e5E|4{)z`V??>MI08ly5@}W{m%Bw?zDfD zJZL9sy1=r~2&LOv9IhkyNhn0?&M97N@=4v->zzOlzAPdresb_NAapd&ID7qdbTY@QYG5Mv9{!l?L5P8@11ITqATlUlki=lI5%w zQ{{H^5E(&h#ch~vZXn6mYW<>x+wR>KO{+Ft{qNZ0GAVaU!#0TPdKZZoey&w+2_A~{ z!~?tluWYdN=IqkD@l`+*_M_1lwj|NY-|vHzP?Re6Mh}eiQgx$clCMES59ickG0C&2 zwy3j+Vw4FssQ|0=d5A|aY6O}8?4zjX@k#w0{r!0-j{k9Ea@&P5IblI0DL^mI%&rpW@#0joV=o66%6yC z_-vvuWKK!dOu-%^P={%wO(KbD+SPt@T*4z`rHIVyR@2#>n-kv3<1`R$^~uys?)GxJ zA+|oSJ8cNxqIB?*)axzU<2_-XbfBiFPG=AGT)5~dTZ;e#m56#|Y^(64eO0G^$Pt}R z)cu}z2h5j~Sd9dEnFuoyrpxHXnL^Lj}JM8%{gtA_GfC<5ozcH*UHXN;~1i>33hw{MI=xe6BUdRU9% zuEO*CQ79o4SXtyhOBPl}fmnXg?EsPNmBPKF;O$~~sj{1e9adNO0X)bUDTbT{CyHQZ z4GO$Jc5GZ*t$===2Y4xsu&>DB>ze^zxX=11?r6L>9Z50yAo=|45_U$UG@)v`H`o2O zKK{p5t7*a12!9a&wvv_W?Z>76b}Fw=mtM*}qbGlsVVJbXkw|xU$TKP7= zmg!iJS9bk8e0G%WE=Tg!9H2{dF$mm0KzryWra)@ygdOhzekmY2rKiuqOziT(&wQoz z``|JA!SVK;!Dk$$^_u;_Y{beibcY^y!s4o;5_#I4K#UeWt6SCUs|5V?av;YlU?Qj^ zG_I^*S)&}*KIx94LqS6e;A=zHpaE-GG)0uMvM?sYn|42DjG8=0e!4rs`|8jg-7fimD>Sn$zXSOReK=Y-nDkj0C*=&b(3Pr zLemFl3RO#e3rs*H;S{wpq>38qi+V@A)C4thWwjs^q`W$Hn2rFn%9{uEUtXixHm7}k zdv;geubq4cmpyjVcv=VAjxSHF-pDym_aE@nRC+bsZYM$6vBz7J)iN&Tj$g1pVCzmX z-k~@9X@P7zbSkh;)20-(N3bHClC`Ote`*cX?k?TRacx1A+Z1ft3ONITgH&&drZX>u zw4lsH3@59XOK1A$R>$4bvUYORprU!L4z?4s-!eih6J2wq=7SV-%O?Rs0T8(OzWC-q z_)iyeRc7bb0Q*A%tL3Rk=pQx$Uje_LP&b%Hj!Q}v+}8J3eo>(S5U2*8h{KFb?Di8k zx!KWPy(?Rxmu>p+op$&-RxF@%Ib8|Kv5JsS;Vosq5j;(oN% zvY-aUV`-1g7_K;JSP5ONRq|c1Qyx@F8?DWk=m|Jfor>*TF_gv&Eam7MMtzSJ?5$)! z=XwAh(Ivvre=IAWj{ z1=|FQ!1>)g@$WaP2K_Mv^! zm=_-4LVo@o@^#i?x8quLGLMCqS+~FuUNU3%&u1Ytazh-%Qc~>*ku|l5KnzLO%1V^C zbbbnR?Kptr5vkBjyRP(+Q+)u;VEc6Qc>@4waG=cV7zjdgxPjn!1oV%wWx9tW->{3X z0o3z0Vq#I-#$}RWxs`|6JJ3lvo~(zhCZk0c^^xq}!a77Z*bch2p=k4$DlWr&KgYJc zH8ZoM>MxDU$!0cWcYPFKObKTiSWVj2AF zY{aRZ`@CfJF#3Mp7-so-f}q(QHf2+TGfp`FCRugvu{gJGV-qbHy(wKWWNM5|>C+MwFTQQTii7QQ3Zou4EL- zh!97V&Sp=zObEKtGziWYcJ{XQxd!=|Jlh`8KDw?0?-Ji5%A4e(e^I%{-wdY3btaXl zL{a{k;S^Mvs1sLl#^Ty!*yP}8|EV!R>qzZLI|dc)&1z_d*(ox$Fto|5+R2r_NC(F) zMiL8Q77Fo)DrJmp(p9H+d*1XB-Ef9O!wLU4!(+JN+& zL^+CV4EWJ^(3C_Jqz8XXUJNEv2!PZutR4Z1h!iNNh8Pit17R%BD%g`itbiMbeu8;e z1f+;b$x0??B`g9wC4C|X*r=hYsH-aba9`zRGq&Q@h8|{VtIlHdz(eKeHxl*g{*|NF zM!9sc{-`JB_qdHLX$Nbawb^+(Rc|)D{eq#Bh%?V~_L!V#dWo4|k==RwyDPW0CBLE3 z;v*9KcMiMbS7?nUgfa4`HqSF{C;pNG_~Rgh#XH9v$1vy{DERz&&Ys4h=Hb@C+QAmZ zxxJ0s6|(NnZd5+vtnf3%j(%IWfp_K-jV5Aia!_7w+Z4Dn(Ld+!mx4<*CTzsOtOzu; zVKE1f-uL>K(M?~oC`|+B zH3f)wUks}n2D9&nqwsYaq5E6Cb~oAgPW#reKi%ta#1@9mxWI`YE8r{_t@#XP~;U!{cMb2%lU0F*@tYnHVO{e3X52waL zI+U~2^Carl=ep`rP}UNNY7%eeJT&a);6@ABpsCY`bVbnVEd>cR#+0ZkU6g*A6_c)P zK5Px?-9jFfkE)y1uUaAPK5lPrb6npqv)Z)TyxR21Zp-?WDXf!16=WI`gbdg0q9GD}J*-!|&i7QX0bBY||l<$}=UgX)HrB>jlvy>fTq&p$fi7H4l?8(-oJxv$FT5`)(C-zY zF2t;{q1kxiM*YbWsljS3QBs8_nFtlq#~pmxkT5$dE0gk${ZadB;U^)A$p+zr;*&=L zEi5r{_jKo7D|u2|4RnFsIBo)LCJ;R)B!`ANPzK=AuNQ|9#LCqd63iQnY3t zz_S|qtIQ&i#hyS8p^(vG42DkKzfeEIc(sENi3T+?z0w=bTuC?>b*!RdP+snnHP zBCMgpYo{qwG^QiGqV?zCOY-=Y$6W(<4rZEI=bHO?jD(!j*0R{<^G3s&Lk#6ZNb4Hv zedqWelz1_}o5UqSH~r<#Z5b)0?bixCUtK88NXJ3uT{r#0x-)aj`a6iU=%>hE5<&PmAD<%W8jjtEw zWgz;Z0Zr;W!VB{gX~Ap*Pudy5cr2lT5Z9ScxWRwD3@EkMW=1%&(b!b!$qv?Cpt}#X zJ?xjh-;W0dtK4#mycuN3%-{mtm(vBeg@K%AtcI zlP1Z%!~*%*9rSZNf_dhF0^MZo;~zNtL2PXua$qr5v{yah>@c^Ofu8UK4=Tmn*%@x@nvTrY+gw#&Mikd>)Sy32r!A>uoLWR{cQRbRpt#rB4 z-vH3PadJ{|FfG+Z%SE}M9NT?UyuPyOVzT;(MOFk+kwwtZdAMf zQ|RWyIa^J<-=JZRbIsDUvBRgE<1iSL%ft9-eR$o1OTe$0+a&PQb{S#6Wd(8#p+({i zay@QR726&@js5bycMe8oGqS-~T|l#u#tOjFPMviKt;rBrs`RciDj~#d6gaT+2+Zni}Pxq2sQlj})Z6a>^!7 zK(K19V&$P|-P++Z#egrh@m6L_cT$wbS<}?T3&;=+Xu4LBSkjVk%qj-6A4mH}yBM%+ z*DV^Q(}z*ec|eR}1-g1fa*y@1qGj&|9ftl3+up?f#n2iqYcD0p9pS$#0I?CTgn-p$ ze;D&~HwfnUAfLkIL|+jCFTFpVQF^uZL@|sIX*SxJTXaF%4Vzs{yzkt;z8(@tSAb8o zgM&r9OF4Gc{oZHL)SS!vsr|}T7!FxRYR%xt*_ZN@)eyp{y$xqp z6^$emPBIIC^Z?{nZyKS3#j|4-y`W$m51n8hz;7^sa^!$;$ue#X|7w&&lW(=o;{T;d zav$x$?sg6_)H)9S2G;F)Y+^l>lIr*HN!8kY$m@5AzCg=O{=_Ofh7AYhXm_mJM`MS> z;mNq1%H>@D^q|xd=$XBfL@k%j+CzaWOerf#W5>Sjs3eBleJ?L6aY%CzU3gz}g6e^V zpc8LAgK;e?!%SY%L7_s$78to=t}!A?++kb4GuATHZtfrRM_d~bBcc9gMa7U%F=a%9 zz_spf8hFv42_!f~nlUfS9T%?&O(BCmri`bJRholfwoSzb0w=*n?SOh#T2xk-m?D|i z7HyBC`=?1NVJ{7HQ7}Mt01R!&Cc04I5Iht#Fq#JawD3vJaLJbL83jDVlk|$~OFDMw zqK;fEL(pWa+f?{6r)U+fd-m!QjsptZdw8)S@pcEdDvu#>r=>$7hkz-s1RA47!U)|c<}P3Jr{5R_^hZn_!+os7=K_H^5ce#9UUl`4wnbC zZvd_yK>}?jA`Cq13$>7biR#~> z2cDDR&pivK+%qLU15}0klN7&d-oyl@l@|S@stzD3J4l5f4GN9nrsGTg>J4vcaDc9S z=XQ+k=oX<=b?SB1$H*=RYtrT%Q?)sml5ghjrQGZqdG^<0Yaz#*Bf@EESz>&s5%^hP zjB*UNdYtNkQZvi#q@*J{Kh(h+! zmern-o{>kf`E>o-RNMKM&`Or5=v_)KrLIcPMvHF-HBmo3ZB9MQ3(XA>RT|0T9plk* zojREZJ)@KBFT>Le4XPsyyvrStCyNv%%Li1}!q6o>4=CrMD(nf4_Qr5&$s2JU+B<4o z^$)xF$0h&spd+zue6u_mf#{dd)y}4eBV6Uk+o4R z$^biHlYx}8Jjj4@pnEkwWXNX`YtT|?Qd0{Da*d-2b@E^-_Ullrk&wC(EBu9RexNK_ zya1_S#|$S?iUe8+74(8b@t)`n6z7m5sdKCIEI{7S6(}Gy@k9%hj)13yI>X41{baCh zc&$4(CR?Iuv=_kIR-N$Eq&G2Q75-g!jDgNB@shR?HnjvUr$` zt;V(=nWO$FX~(ddArzp#y49g>06I8Dnhy9!q`1Sw(Y*cC{j~kQz()QhL1l}sFi}cg zukRjv0X3X{pB2M0DMySPd2$uTq-f8MW~DPfA{!^gU>5oM$XDjydx84al;PKP^c8ms1*@=F>_Y9&^nbkl{)LQt{qa{QY(>2p08Zf7NIVfm@n9>W1D(K^-(aMy^m=_c&Tz(fdHe$5P!`nGy>beSR z?~+5`(-M}zwF&anII4+MDN6=tLn?2uwfu>zZyAAaWnN8}d}R{ZDhO66S4JgCge;st zRV-C>7{M(b9CR>0mWqsYFCj{lQU) z>+@-Osl(^^bthtvVl6EBo>6pL7!i%C98&10j{n(D=x_?NdOUaP9EEAW22Oxqrw5rn z8Ur%Ja*GFIkK)e<4{ACp&%n{HHc!=1(Vv&jq_2mW$&I@W!d#%z& ziRV~mJyyvu{xfcPVx_~m zbZX^<6`dk+V|8(TaojD{WRmck{4Lym>kS*A0u+gx*XbGr@JI#zyCXc5O=XI9~# zuPq4M3~`W3m|{`2UVwre{2WK9WCWjRVfP@jfu5RLC$}dho>aexr`_${6|xj-aR8k% z)ID9dxiA4;i845=BCAi7R+Rh}^M=4V5Vs0fRo-e(&5xu<(nGDW=6O3aUIpI-4yF6( zdcMNkG4co~Yunt_uzF9PrC4g&WEC{hd&(mEyCdr~sl}x7mkdi6Ts1XJ)P>VFpmK8= zZk@Vrf69}>xFX9sF`eiD&k}_|nmur=KjAYHmfs zC^S4#Qh|g73@F`p6RLqfNB@KsAsXpH6FM~6?T`v;9M#oX&DBaFor^vx3sy-u3_UXE zr5aQ|i&&~wnU(&?zsktYte&Z>4-p8O}*`vH0*= z&ytN|T}SpRhP4M*eedgWH99{x(rz7lM-GFJ#oPGRYdn;v=EsTsSHg6UCl<3TMyf~!P(3y{{Iwmo>5IM?HUFF>C$@(O+t$y zfrQXSx`p1s5JD$NktT=~sUm_Dl_p3H5Ri^2N)NsFCWul6DI(H6(f#@D`^e}G4bnjG!#$_AJ;G-s>M6+37hK*a-LJU!Kzq^BlZt_nXz$@@Zn+Q<#oJZ(Y11B zft7m|m_yyHnOYlFmuGJ(ef!EZ-?ct~Gwq$FcSNV88WoJXAZoscZgJ+iMUM6PS)B|Z zTS4R;6X^TM=KlF0o7}`x`5(eQpigYhPuO2p;g-g?;V$DGF!qVm33JeA(0YyAiOdP6 zm2x?GCuliimoDI4T6ool%>{iOmQtb@H1~EHs#`Xnf0pw6F3M}D_du?68clAyN6~n` zkUI2P{29B#?Sqhk^eD5!3dX#P9XQ&zBJQ^Ea`qT1D4{XEIdj<88Kw{3}}f z*HOh=6`JDBTo;<97|5*PQs^+s|B>T0#64`w~)%nstr`}?3mjADI5yc~5}=r& z%0OA-^inyJ-(Q91Ui`D=VWKAVwwr~tWY6>no1Az=Lo;3C)7AVt!NLvCtz}U^LQB~t z`c%2?osOxSIdYzRP|;oVv@s{`V3kq$dhJ77{LEH2sR9}AeGnu2<}mU|^IIPY^37C% z@Teqhyl>-#f|Ug2#SB(mS6o>m%0}@Zrn3xkK4ocrZ6YM{8kWpAP?zk|t%=T~Cy{T~ zw=k0{wo~kuWf%{b5lkZIWr=^wNw~GSBcp+2jH(Daj?~J?u3FC&7cR$>m6Jh~n2?s} zw$t9xj*J`GVfa{Sn0b#}bIfSH;6|L8rtT!?6weERaDErLNla>^pz$1YO^Z_4yw>Yt zbP^|-EB^J^>zVGR+Pr2Gp3Sup5-$&G;P&1zi4dNQLdY_su(|ikVO~{~jgiHBO>nq{ z5Qs!%^~oJDCuLn?yFQiXhxj&?xcQR1trf!l>I1RMER7PA>33o&nOiLq%%I|X~QGS%LZ;!Pp<$4$WMu?V<{-p2VO20+j1fK-Xr||UhHx7q}?$Y<1 zbgZoS`!`5RqaE0rb2NuIsh?^eHx%p9XH1u4G-D&2P@D<^<#Lr1bhV&PUIrBhTbswF z7}I_4>=(3(A)}dEtVsImx@p02dbNuiD9cgmeP(*-pj6DI3-ub&5XvtJ78oc|Ta-}0 zu`!hIcCX+&Pup?B7qw1IaCryA8uiTy1=uW7S`L28#dEH@;(JQgl+^h@Vvvye7bg3TsoXvrGRM8P%b2wv*CKCfe?0R z!etf}3|##_bK2scK65W?X6ybb;}>vaW|-vj4+&yoSN$6U5k`DV{kp^6-;&XBm?b9Mh%T)TGrQF)W-1bEIL6NZla*s z`A^G5yJZOUCgT%B9YsWQgdI&O#QfgbH`wd(!6G2+bYp@(UrCyIvBhrOfBZNS~er z&|a^{apyE1+KaB@Ow&tza?m5<+}1MC6<=|2k)f?Ic`9ZqDWiNTWExnerT&vfFDul)S=E~DmFT=;jP^jRvIh{(A$j) z7qbmDP#lFdh5&~SjRmL}XSzNyz&Wer(fbq>f{vpMKX^UmqXze>*j+p;#;)wm2S>dE zr0fD(J}{(kj(Fs2vjsa{)EoeE$k$gazDC8>*FJ8|6KyRau{SU*V+md~dD2gm=A!`= z!;0<~CC?Nb#OCB82ZSw!HhfEpUp5b1GiR+zxzI3UpjJ3G=% zx~y-67#8AAI>WdXjv%s(odvY6~a4kVGtdvG5teZVlSBszDqgVdG zPHxLPtXzYBInr8;9zafJ_&)v||MqTTsG+;f@@{&^Z8p!2@;iZFtY15<1fkZ6G2PZ@ ztIQkfp7%odBva4c+^-+mQaI!Wl?lk^B`-}7PX;Eci{w3m*r&c~-O=+$`n&I8_EeKi zBc@id;8QgUc!Wm?8)x;Gja0qjX6qC4!7uPmQra)5$=Vb~gB{GU;~>_o`}3k}SVnB_ zGJb5zmS=_nLcPD296%gH(?KRdFWtTMHUW{nG54AL)LJ9EB#|OV$rL6N7CXTEAXJnY zE%=Q3a*J9Kg@KBdyF`2UWv3dC5pTqzRpUH^ zfujqLLJzi~H2|eAOy`s?S+i4-g`~Fi@g@c5k{>H_&@D}UVaS1jcn#f11M3EvX_wSH zKb(eekgbhmHre%4i2$ZeVtx`&3vM8#Pm1kt!=SG?cyH36hFZ=+IOoW0uZ&|y1M%6Pxt zk{j*fX-|!piVLOn=vVn=Yi-K2j)a4VYGqi_7L3e2Q9k+X5cYFD&oPUDG_V$Lf>3{i2HvY{#_3 zmlkbtY%yWFFg{}4ulqTof$gCe#q*TCvKVU8vHA;&J?RKizx)1=onm3`E}0fqZ@f3V z=UjE*+ZvZqD|eSw`e^$;*3IrWhX$7LjygZYF-7fcFO6Ll8Do1$d-a>&HRNlV0)v&a zHzk<&$tb9W25xq$O3-0&utTK`VPhQ$4Qx6~7h?g^PO@b85`L}O38OhKq^7y1tuO^2 zt=*OtN~7tG%Bzv#97d@lSt?D-NiLHiaF0c4<_J3e%QYm5Tk@Oka;~~P{D?u`n5TkT zbW?9&mF)=_aiLI)9QqazwQ79wu5^A4JW7Y;hHF=M<@0lv@E)tj9D5^t;Q7Y#0vKL!AUJ*4-&--Hi4pO-Ym-~8DIZq@_=g#;&Ceu zH$c?;KL2~uS<>6#UaXvpsOeM7>BFKHqgEr!sKVAaA&n-l#yv{iLLF1QQhaLslDv|9 zs=o8@(bw*9zce!8Bo4ikp7QZx7fSU83x5#eY!1Ehz@3D99JJHjh3clXbYuY0BRK6wrxx2mWVfdKf=l04nE zw2c*Y(HmCcGrY5@g3qhs!0O7KXpkLplY4Y$Cau;H7iw+%kXk!(zR(+r;1iD)(Gcab z&Sf;TqGn7tPG_RK_(=F(`e2QaN3~uGF!^I)ipHDP3p*p)c(okx3!@pH!H&Y#(Kh;kg(tyI)j$!At8FLp}`3a8>o|iI&xL|WQ&mx*8cHmwkt;7 z#Hg3!x%W-i(pTEepB|A{wjVGZ5%VqAFl2T>x9N2HOtFN3nHR^CMkl-Cd~Z$kd3wSC zH-MR9>)Sx^$k%N_!VA6l<(`P(>z(I4IrqeA?{1-!zZ01)P*d*qF(2BB{dmiK$S6hy zsUpIr;Z&uZMDm49?ngFH?Dg5W#)oemcfprFF35k5*`D)D#{|{2exHYaB4>=f&?8J% zv1yUk0k4U_l+jQgc=q5^oA8|V#1B4o7zp`)AgjMq8l|Mc@c%NagjAQmSVEw;{cUd~ z3WGsa*Avgm7gyffB zDKh@vf3Nus#R46@P##Xc&H(@j2nqv%|91SQQGsf55HJBglm^R6feE}I!U7B?1e1yU z?fl=^qq8>wN&HnkAq|F*K4a&DCIn6XDv=;uA>>OEh*Sb-NLcfG?(BX`?Ppkw)UT)+ z0*>fz_j6A5pZVYPp}&{C1A#x4LQsMKI{+{l8K?}v0q~awk&^nk_s;>i^&brkLC6w# z%|A66gbV@K{8Iyie=?_kY7hkMUu&UYSwegM^vNLpeJ%_vOK8oXKB$!Jzs``6Mf}SL z14I9<$^0a3|J;v&b^fzH2p9qRr;ngX|FdR-_LHOiV?PL?#RP`-pBnsst@ZXo5#Ug- zU#X&o&H;qJApn;Q+}#N@^iTSh&{geQ4(mop;AP@+Zu&}zW2G#!nrhi;V literal 0 HcmV?d00001 diff --git a/tests/topotests/all-protocol-startup/test_all_protocol_startup.py b/tests/topotests/all-protocol-startup/test_all_protocol_startup.py new file mode 100755 index 0000000000..ea70d4f53d --- /dev/null +++ b/tests/topotests/all-protocol-startup/test_all_protocol_startup.py @@ -0,0 +1,785 @@ +#!/usr/bin/env python + +# +# test_all_protocol_startup.py +# Part of NetDEF Topology Tests +# +# Copyright (c) 2017 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_all_protocol_startup.py: Test of all protocols at same time + +""" + +import os +import re +import sys +import difflib +import pytest +from time import sleep + +from mininet.topo import Topo +from mininet.net import Mininet +from mininet.node import Node, OVSSwitch, Host +from mininet.log import setLogLevel, info +from mininet.cli import CLI +from mininet.link import Intf + +from functools import partial + +sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +from lib import topotest + +fatal_error = "" + + +##################################################### +## +## Network Topology Definition +## +##################################################### + +class NetworkTopo(Topo): + "All Protocol Startup Test" + + def build(self, **_opts): + + # Setup Routers + router = {} + # + # Setup Main Router + router[1] = topotest.addRouter(self, 'r1') + # + + # Setup Switches + switch = {} + # + for i in range(0, 10): + switch[i] = self.addSwitch('sw%s' % i, cls=topotest.LegacySwitch) + self.addLink(switch[i], router[1], intfName2='r1-eth%s' % i ) + + +##################################################### +## +## Tests starting +## +##################################################### + +def setup_module(module): + global topo, net + global fatal_error + + print("\n\n** %s: Setup Topology" % module.__name__) + print("******************************************\n") + + print("Cleanup old Mininet runs") + os.system('sudo mn -c > /dev/null 2>&1') + os.system('sudo rm /tmp/r* > /dev/null 2>&1') + + thisDir = os.path.dirname(os.path.realpath(__file__)) + topo = NetworkTopo() + + net = Mininet(controller=None, topo=topo) + net.start() + + if net['r1'].get_routertype() != 'frr': + fatal_error = "Test is only implemented for FRR" + sys.stderr.write('\n\nTest is only implemented for FRR - Skipping\n\n') + pytest.skip(fatal_error) + + # Starting Routers + # + # Main router + for i in range(1, 2): + net['r%s' % i].loadConf('zebra', '%s/r%s/zebra.conf' % (thisDir, i)) + net['r%s' % i].loadConf('ripd', '%s/r%s/ripd.conf' % (thisDir, i)) + net['r%s' % i].loadConf('ripngd', '%s/r%s/ripngd.conf' % (thisDir, i)) + net['r%s' % i].loadConf('ospfd', '%s/r%s/ospfd.conf' % (thisDir, i)) + net['r%s' % i].loadConf('ospf6d', '%s/r%s/ospf6d.conf' % (thisDir, i)) + net['r%s' % i].loadConf('isisd', '%s/r%s/isisd.conf' % (thisDir, i)) + net['r%s' % i].loadConf('bgpd', '%s/r%s/bgpd.conf' % (thisDir, i)) + if net['r%s' % i].daemon_available('ldpd'): + # Only test LDPd if it's installed and Kernel >= 4.5 + net['r%s' % i].loadConf('ldpd', '%s/r%s/ldpd.conf' % (thisDir, i)) + net['r%s' % i].startRouter() + + # For debugging after starting Quagga/FRR daemons, uncomment the next line + # CLI(net) + + +def teardown_module(module): + global net + + print("\n\n** %s: Shutdown Topology" % module.__name__) + print("******************************************\n") + + # End - Shutdown network + net.stop() + + +def test_router_running(): + global fatal_error + global net + + # Skip if previous fatal error condition is raised + if (fatal_error != ""): + pytest.skip(fatal_error) + + print("\n\n** Check if FRR/Quagga is running on each Router node") + print("******************************************\n") + sleep(5) + + # Starting Routers + for i in range(1, 2): + fatal_error = net['r%s' % i].checkRouterRunning() + assert fatal_error == "", fatal_error + + # For debugging after starting FRR/Quagga daemons, uncomment the next line + # CLI(net) + + +def test_error_messages_vtysh(): + global fatal_error + global net + + # Skip if previous fatal error condition is raised + if (fatal_error != ""): + pytest.skip(fatal_error) + + print("\n\n** Check for error messages on VTYSH") + print("******************************************\n") + + failures = 0 + for i in range(1, 2): + # + # First checking Standard Output + # + + # VTYSH output from router + vtystdout = net['r%s' % i].cmd('vtysh -c "show version" 2> /dev/null').rstrip() + + # Fix newlines (make them all the same) + vtystdout = ('\n'.join(vtystdout.splitlines()) + '\n').rstrip() + # Drop everything starting with "FRRouting X.xx" message + vtystdout = re.sub(r"FRRouting [0-9]+.*", "", vtystdout, flags=re.DOTALL) + + if (vtystdout != ''): + sys.stderr.write('\nr%s created some spurious VTYSH start StdOut messages:\n%s\n' % (i, vtystdout)) + failures += 1 + else: + print("r%s StdOut ok" % i) + + # + # Second checking Standard Error + # + + # VTYSH StdErr output from router + vtystderr = net['r%s' % i].cmd('vtysh -c "show version" > /dev/null').rstrip() + + # Fix newlines (make them all the same) + vtystderr = ('\n'.join(vtystderr.splitlines()) + '\n').rstrip() + # # Drop everything starting with "FRRouting X.xx" message + # vtystderr = re.sub(r"FRRouting [0-9]+.*", "", vtystderr, flags=re.DOTALL) + + if (vtystderr != ''): + sys.stderr.write('\nr%s created some spurious VTYSH start StdErr messages:\n<%s>\n' % (i, vtystderr)) + failures += 1 + else: + print("r%s StdErr ok" % i) + + assert failures == 0, "IP RIP status failed for router r%s:\n%s" % (i, diff) + + # For debugging after starting FRR/Quagga daemons, uncomment the next line + # CLI(net) + + +def test_error_messages_daemons(): + global fatal_error + global net + + # Skip if previous fatal error condition is raised + if (fatal_error != ""): + pytest.skip(fatal_error) + + print("\n\n** Check for error messages in daemons") + print("******************************************\n") + + error_logs = "" + + for i in range(1, 2): + log = net['r%s' % i].getStdErr('ripd') + if log: + error_logs += "r%s RIPd StdErr Output:\n" % i + error_logs += log + log = net['r%s' % i].getStdErr('ripngd') + if log: + error_logs += "r%s RIPngd StdErr Output:\n" % i + error_logs += log + log = net['r%s' % i].getStdErr('ospfd') + if log: + error_logs += "r%s OSPFd StdErr Output:\n" % i + error_logs += log + log = net['r%s' % i].getStdErr('ospf6d') + if log: + error_logs += "r%s OSPF6d StdErr Output:\n" % i + error_logs += log + log = net['r%s' % i].getStdErr('isisd') + # ISIS shows debugging enabled status on StdErr + # Remove these messages + log = re.sub(r"^IS-IS .* debugging is on.*", "", log).rstrip() + if log: + error_logs += "r%s ISISd StdErr Output:\n" % i + error_logs += log + log = net['r%s' % i].getStdErr('bgpd') + if log: + error_logs += "r%s BGPd StdErr Output:\n" % i + error_logs += log + if (net['r%s' % i].daemon_available('ldpd')): + log = net['r%s' % i].getStdErr('ldpd') + if log: + error_logs += "r%s LDPd StdErr Output:\n" % i + error_logs += log + log = net['r%s' % i].getStdErr('zebra') + if log: + error_logs += "r%s Zebra StdErr Output:\n" + error_logs += log + + if error_logs: + sys.stderr.write('Failed check for StdErr Output on daemons:\n%s\n' % error_logs) + + assert error_logs == "", "Daemons report errors to StdErr" + + # For debugging after starting FRR/Quagga daemons, uncomment the next line + # CLI(net) + + +def test_converge_protocols(): + global fatal_error + global net + + # Skip if previous fatal error condition is raised + if (fatal_error != ""): + pytest.skip(fatal_error) + + thisDir = os.path.dirname(os.path.realpath(__file__)) + + print("\n\n** Waiting for protocols convergence") + print("******************************************\n") + + # Not really implemented yet - just sleep 60 secs for now + sleep(60) + + # For debugging after starting FRR/Quagga daemons, uncomment the next line + ## CLI(net) + + +def test_rip_status(): + global fatal_error + global net + + # Skip if previous fatal error condition is raised + if (fatal_error != ""): + pytest.skip(fatal_error) + + thisDir = os.path.dirname(os.path.realpath(__file__)) + + # Verify RIP Status + print("\n\n** Verifing RIP status") + print("******************************************\n") + failures = 0 + for i in range(1, 2): + refTableFile = '%s/r%s/rip_status.ref' % (thisDir, i) + if os.path.isfile(refTableFile): + # Read expected result from file + expected = open(refTableFile).read().rstrip() + # Fix newlines (make them all the same) + expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1) + + # Actual output from router + actual = net['r%s' % i].cmd('vtysh -c "show ip rip status" 2> /dev/null').rstrip() + # Drop time in next due + actual = re.sub(r"in [0-9]+ seconds", "in XX seconds", actual) + # Drop time in last update + actual = re.sub(r" [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", " XX:XX:XX", actual) + # Fix newlines (make them all the same) + actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1) + + # Generate Diff + diff = ''.join(difflib.context_diff(actual, expected, + fromfile="actual IP RIP status", + tofile="expected IP RIP status")) + + # Empty string if it matches, otherwise diff contains unified diff + if diff: + sys.stderr.write('r%s failed IP RIP status check:\n%s\n' % (i, diff)) + failures += 1 + else: + print("r%s ok" % i) + + assert failures == 0, "IP RIP status failed for router r%s:\n%s" % (i, diff) + + # For debugging after starting FRR/Quagga daemons, uncomment the next line + # CLI(net) + + +def test_ripng_status(): + global fatal_error + global net + + # Skip if previous fatal error condition is raised + if (fatal_error != ""): + pytest.skip(fatal_error) + + thisDir = os.path.dirname(os.path.realpath(__file__)) + + # Verify RIP Status + print("\n\n** Verifing RIPng status") + print("******************************************\n") + failures = 0 + for i in range(1, 2): + refTableFile = '%s/r%s/ripng_status.ref' % (thisDir, i) + if os.path.isfile(refTableFile): + # Read expected result from file + expected = open(refTableFile).read().rstrip() + # Fix newlines (make them all the same) + expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1) + + # Actual output from router + actual = net['r%s' % i].cmd('vtysh -c "show ipv6 ripng status" 2> /dev/null').rstrip() + # Mask out Link-Local mac address portion. They are random... + actual = re.sub(r" fe80::[0-9a-f:]+", " fe80::XXXX:XXXX:XXXX:XXXX", actual) + # Drop time in next due + actual = re.sub(r"in [0-9]+ seconds", "in XX seconds", actual) + # Drop time in last update + actual = re.sub(r" [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", " XX:XX:XX", actual) + # Fix newlines (make them all the same) + actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1) + + # Generate Diff + diff = ''.join(difflib.context_diff(actual, expected, + fromfile="actual IPv6 RIPng status", + tofile="expected IPv6 RIPng status")) + + # Empty string if it matches, otherwise diff contains unified diff + if diff: + sys.stderr.write('r%s failed IPv6 RIPng status check:\n%s\n' % (i, diff)) + failures += 1 + else: + print("r%s ok" % i) + + assert failures == 0, "IPv6 RIPng status failed for router r%s:\n%s" % (i, diff) + + # For debugging after starting FRR/Quagga daemons, uncomment the next line + # CLI(net) + + +def test_ospfv2_interfaces(): + global fatal_error + global net + + # Skip if previous fatal error condition is raised + if (fatal_error != ""): + pytest.skip(fatal_error) + + thisDir = os.path.dirname(os.path.realpath(__file__)) + + # Verify RIP Status + print("\n\n** Verifing OSPFv2 interfaces") + print("******************************************\n") + failures = 0 + for i in range(1, 2): + refTableFile = '%s/r%s/show_ip_ospf_interface.ref' % (thisDir, i) + if os.path.isfile(refTableFile): + # Read expected result from file + expected = open(refTableFile).read().rstrip() + # Fix newlines (make them all the same) + expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1) + + # Actual output from router + actual = net['r%s' % i].cmd('vtysh -c "show ip ospf interface" 2> /dev/null').rstrip() + # Mask out Bandwidth portion. They may change.. + actual = re.sub(r"BW [0-9]+ Mbit", "BW XX Mbit", actual) + # Drop time in next due + actual = re.sub(r"Hello due in [0-9\.]+s", "Hello due in XX.XXXs", actual) + # Fix newlines (make them all the same) + actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1) + + # Generate Diff + diff = ''.join(difflib.context_diff(actual, expected, + fromfile="actual SHOW IP OSPF INTERFACE", + tofile="expected SHOW IP OSPF INTERFACE")) + + # Empty string if it matches, otherwise diff contains unified diff + if diff: + sys.stderr.write('r%s failed SHOW IP OSPF INTERFACE check:\n%s\n' % (i, diff)) + failures += 1 + else: + print("r%s ok" % i) + + assert failures == 0, "SHOW IP OSPF INTERFACE failed for router r%s:\n%s" % (i, diff) + + # For debugging after starting FRR/Quagga daemons, uncomment the next line + # CLI(net) + + +def test_isis_interfaces(): + global fatal_error + global net + + # Skip if previous fatal error condition is raised + if (fatal_error != ""): + pytest.skip(fatal_error) + + thisDir = os.path.dirname(os.path.realpath(__file__)) + + # Verify RIP Status + print("\n\n** Verifing ISIS interfaces") + print("******************************************\n") + failures = 0 + for i in range(1, 2): + refTableFile = '%s/r%s/show_isis_interface_detail.ref' % (thisDir, i) + if os.path.isfile(refTableFile): + # Read expected result from file + expected = open(refTableFile).read().rstrip() + # Fix newlines (make them all the same) + expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1) + + # Actual output from router + actual = net['r%s' % i].cmd('vtysh -c "show isis interface detail" 2> /dev/null').rstrip() + # Mask out Link-Local mac address portion. They are random... + actual = re.sub(r"fe80::[0-9a-f:]+", "fe80::XXXX:XXXX:XXXX:XXXX", actual) + # Mask out SNPA mac address portion. They are random... + actual = re.sub(r"SNPA: [0-9a-f\.]+", "SNPA: XXXX.XXXX.XXXX", actual) + # Fix newlines (make them all the same) + actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1) + + # Generate Diff + diff = ''.join(difflib.context_diff(actual, expected, + fromfile="actual SHOW ISIS INTERFACE DETAIL", + tofile="expected SHOW ISIS OSPF6 INTERFACE DETAIL")) + + # Empty string if it matches, otherwise diff contains unified diff + if diff: + sys.stderr.write('r%s failed SHOW ISIS INTERFACE DETAIL check:\n%s\n' % (i, diff)) + failures += 1 + else: + print("r%s ok" % i) + + assert failures == 0, "SHOW ISIS INTERFACE DETAIL failed for router r%s:\n%s" % (i, diff) + + # For debugging after starting FRR/Quagga daemons, uncomment the next line + # CLI(net) + + +def test_bgp_summary(): + global fatal_error + global net + + # Skip if previous fatal error condition is raised + if (fatal_error != ""): + pytest.skip(fatal_error) + + thisDir = os.path.dirname(os.path.realpath(__file__)) + + # Verify RIP Status + print("\n\n** Verifing BGP Summary") + print("******************************************\n") + failures = 0 + for i in range(1, 2): + refTableFile = '%s/r%s/show_bgp_summary.ref' % (thisDir, i) + if os.path.isfile(refTableFile): + # Read expected result from file + expected = open(refTableFile).read().rstrip() + # Fix newlines (make them all the same) + expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1) + + # Actual output from router + actual = net['r%s' % i].cmd('vtysh -c "show bgp summary" 2> /dev/null').rstrip() + # Mask out "using XXiXX bytes" portion. They are random... + actual = re.sub(r"using [0-9]+ bytes", "using XXXX bytes", actual) + # Mask out "using XiXXX KiB" portion. They are random... + actual = re.sub(r"using [0-9]+ KiB", "using XXXX KiB", actual) + # Fix newlines (make them all the same) + actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1) + + # Generate Diff + diff = ''.join(difflib.context_diff(actual, expected, + fromfile="actual SHOW BGP SUMMARY", + tofile="expected SHOW BGP SUMMARY")) + + # Empty string if it matches, otherwise diff contains unified diff + if diff: + sys.stderr.write('r%s failed SHOW BGP SUMMARY check:\n%s\n' % (i, diff)) + failures += 1 + else: + print("r%s ok" % i) + + assert failures == 0, "SHOW SHOW BGP SUMMARY failed for router r%s:\n%s" % (i, diff) + + # For debugging after starting FRR/Quagga daemons, uncomment the next line + # CLI(net) + + +def test_bgp_ipv6_summary(): + global fatal_error + global net + + # Skip if previous fatal error condition is raised + if (fatal_error != ""): + pytest.skip(fatal_error) + + thisDir = os.path.dirname(os.path.realpath(__file__)) + + # Verify RIP Status + print("\n\n** Verifing BGP IPv6 Summary") + print("******************************************\n") + failures = 0 + for i in range(1, 2): + refTableFile = '%s/r%s/show_bgp_ipv6_summary.ref' % (thisDir, i) + if os.path.isfile(refTableFile): + # Read expected result from file + expected = open(refTableFile).read().rstrip() + # Fix newlines (make them all the same) + expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1) + + # Actual output from router + actual = net['r%s' % i].cmd('vtysh -c "show bgp ipv6 summary" 2> /dev/null').rstrip() + # Mask out "using XXiXX bytes" portion. They are random... + actual = re.sub(r"using [0-9]+ bytes", "using XXXX bytes", actual) + # Mask out "using XiXXX KiB" portion. They are random... + actual = re.sub(r"using [0-9]+ KiB", "using XXXX KiB", actual) + # Fix newlines (make them all the same) + actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1) + + # Generate Diff + diff = ''.join(difflib.context_diff(actual, expected, + fromfile="actual SHOW BGP IPv6 SUMMARY", + tofile="expected SHOW BGP IPv6 SUMMARY")) + + # Empty string if it matches, otherwise diff contains unified diff + if diff: + sys.stderr.write('r%s failed SHOW BGP IPv6 SUMMARY check:\n%s\n' % (i, diff)) + failures += 1 + else: + print("r%s ok" % i) + + assert failures == 0, "SHOW BGP IPv6 SUMMARY failed for router r%s:\n%s" % (i, diff) + + # For debugging after starting FRR/Quagga daemons, uncomment the next line + # CLI(net) + + +def test_bgp_ipv4(): + global fatal_error + global net + + # Skip if previous fatal error condition is raised + if (fatal_error != ""): + pytest.skip(fatal_error) + + thisDir = os.path.dirname(os.path.realpath(__file__)) + + # Verify RIP Status + print("\n\n** Verifing BGP IPv4") + print("******************************************\n") + failures = 0 + for i in range(1, 2): + refTableFile = '%s/r%s/show_bgp_ipv4.ref' % (thisDir, i) + if os.path.isfile(refTableFile): + # Read expected result from file + expected = open(refTableFile).read().rstrip() + # Fix newlines (make them all the same) + expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1) + + # Actual output from router + actual = net['r%s' % i].cmd('vtysh -c "show bgp ipv4" 2> /dev/null').rstrip() + # Remove summary line (changed recently) + actual = re.sub(r'Total number.*', '', actual) + actual = re.sub(r'Displayed.*', '', actual) + actual = actual.rstrip() + # Fix newlines (make them all the same) + actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1) + + # Generate Diff + diff = ''.join(difflib.context_diff(actual, expected, + fromfile="actual SHOW BGP IPv4", + tofile="expected SHOW BGP IPv4")) + + # Empty string if it matches, otherwise diff contains unified diff + if diff: + sys.stderr.write('r%s failed SHOW BGP IPv4 check:\n%s\n' % (i, diff)) + failures += 1 + else: + print("r%s ok" % i) + + assert failures == 0, "SHOW BGP IPv4 failed for router r%s:\n%s" % (i, diff) + + # For debugging after starting FRR/Quagga daemons, uncomment the next line + # CLI(net) + + +def test_bgp_ipv6(): + global fatal_error + global net + + # Skip if previous fatal error condition is raised + if (fatal_error != ""): + pytest.skip(fatal_error) + + thisDir = os.path.dirname(os.path.realpath(__file__)) + + # Verify RIP Status + print("\n\n** Verifing BGP IPv6") + print("******************************************\n") + failures = 0 + for i in range(1, 2): + refTableFile = '%s/r%s/show_bgp_ipv6.ref' % (thisDir, i) + if os.path.isfile(refTableFile): + # Read expected result from file + expected = open(refTableFile).read().rstrip() + # Fix newlines (make them all the same) + expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1) + + # Actual output from router + actual = net['r%s' % i].cmd('vtysh -c "show bgp ipv6" 2> /dev/null').rstrip() + # Remove summary line (changed recently) + actual = re.sub(r'Total number.*', '', actual) + actual = re.sub(r'Displayed.*', '', actual) + actual = actual.rstrip() + # Fix newlines (make them all the same) + actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1) + + # Generate Diff + diff = ''.join(difflib.context_diff(actual, expected, + fromfile="actual SHOW BGP IPv6", + tofile="expected SHOW BGP IPv6")) + + # Empty string if it matches, otherwise diff contains unified diff + if diff: + sys.stderr.write('r%s failed SHOW BGP IPv6 check:\n%s\n' % (i, diff)) + failures += 1 + else: + print("r%s ok" % i) + + assert failures == 0, "SHOW BGP IPv6 failed for router r%s:\n%s" % (i, diff) + + # For debugging after starting FRR/Quagga daemons, uncomment the next line + # CLI(net) + + + +def test_mpls_interfaces(): + global fatal_error + global net + + # Skip if previous fatal error condition is raised + if (fatal_error != ""): + pytest.skip(fatal_error) + + # Skip if no LDP installed or old kernel + if (net['r1'].daemon_available('ldpd') == False): + pytest.skip("No MPLS or kernel < 4.5") + + thisDir = os.path.dirname(os.path.realpath(__file__)) + + # Verify OSPFv3 Routing Table + print("\n\n** Verifing MPLS Interfaces") + print("******************************************\n") + failures = 0 + for i in range(1, 2): + refTableFile = '%s/r%s/show_mpls_ldp_interface.ref' % (thisDir, i) + if os.path.isfile(refTableFile): + # Read expected result from file + expected = open(refTableFile).read().rstrip() + # Fix newlines (make them all the same) + expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1) + + # Actual output from router + actual = net['r%s' % i].cmd('vtysh -c "show mpls ldp interface" 2> /dev/null').rstrip() + # Mask out Timer in Uptime + actual = re.sub(r" [0-9][0-9]:[0-9][0-9]:[0-9][0-9] ", " xx:xx:xx ", actual) + # Fix newlines (make them all the same) + actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1) + + # Generate Diff + diff = ''.join(difflib.context_diff(actual, expected, + fromfile="actual MPLS LDP interface status", + tofile="expected MPLS LDP interface status")) + + # Empty string if it matches, otherwise diff contains unified diff + if diff: + sys.stderr.write('r%s failed MPLS LDP Interface status Check:\n%s\n' % (i, diff)) + failures += 1 + else: + print("r%s ok" % i) + + if failures>0: + fatal_error = "MPLS LDP Interface status failed" + + assert failures == 0, "MPLS LDP Interface status failed for router r%s:\n%s" % (i, diff) + + # For debugging after starting FRR/Quagga daemons, uncomment the next line + # CLI(net) + + +def test_shutdown_check_stderr(): + global fatal_error + global net + + # Skip if previous fatal error condition is raised + if (fatal_error != ""): + pytest.skip(fatal_error) + + print("\n\n** Verifing unexpected STDERR output from daemons") + print("******************************************\n") + + if os.environ.get('TOPOTESTS_CHECK_STDERR') is None: + print("SKIPPED (Disabled) - TOPOTESTS_CHECK_STDERR undefined\n") + pytest.skip('Skipping test for Stderr output and memory leaks') + + thisDir = os.path.dirname(os.path.realpath(__file__)) + + net['r1'].stopRouter() + + log = net['r1'].getStdErr('ripd') + print("\nRIPd StdErr Log:\n" + log) + log = net['r1'].getStdErr('ripngd') + print("\nRIPngd StdErr Log:\n" + log) + log = net['r1'].getStdErr('ospfd') + print("\nOSPFd StdErr Log:\n" + log) + log = net['r1'].getStdErr('ospf6d') + print("\nOSPF6d StdErr Log:\n" + log) + log = net['r1'].getStdErr('isisd') + print("\nISISd StdErr Log:\n" + log) + log = net['r1'].getStdErr('bgpd') + print("\nBGPd StdErr Log:\n" + log) + if (net['r1'].daemon_available('ldpd')): + log = net['r1'].getStdErr('ldpd') + print("\nLDPd StdErr Log:\n" + log) + log = net['r1'].getStdErr('zebra') + print("\nZebra StdErr Log:\n" + log) + + +if __name__ == '__main__': + + setLogLevel('info') + # To suppress tracebacks, either use the following pytest call or add "--tb=no" to cli + # retval = pytest.main(["-s", "--tb=no"]) + retval = pytest.main(["-s"]) + sys.exit(retval) -- 2.39.5