]> git.puffer.fish Git - mirror/frr.git/commitdiff
all-protocol-startup: Add test suite which runs all protocols at once and verifies...
authorMartin Winter <mwinter@opensourcerouting.org>
Sat, 8 Apr 2017 10:49:43 +0000 (03:49 -0700)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 28 Nov 2018 01:22:11 +0000 (20:22 -0500)
Signed-off-by: Martin Winter <mwinter@opensourcerouting.org>
22 files changed:
tests/topotests/all-protocol-startup/r1/bgpd.conf [new file with mode: 0644]
tests/topotests/all-protocol-startup/r1/isisd.conf [new file with mode: 0644]
tests/topotests/all-protocol-startup/r1/ldpd.conf [new file with mode: 0644]
tests/topotests/all-protocol-startup/r1/ospf6d.conf [new file with mode: 0644]
tests/topotests/all-protocol-startup/r1/ospfd.conf [new file with mode: 0644]
tests/topotests/all-protocol-startup/r1/rip_status.ref [new file with mode: 0644]
tests/topotests/all-protocol-startup/r1/ripd.conf [new file with mode: 0644]
tests/topotests/all-protocol-startup/r1/ripng_status.ref [new file with mode: 0644]
tests/topotests/all-protocol-startup/r1/ripngd.conf [new file with mode: 0644]
tests/topotests/all-protocol-startup/r1/show_bgp_ipv4.ref [new file with mode: 0644]
tests/topotests/all-protocol-startup/r1/show_bgp_ipv6.ref [new file with mode: 0644]
tests/topotests/all-protocol-startup/r1/show_bgp_ipv6_summary.ref [new file with mode: 0644]
tests/topotests/all-protocol-startup/r1/show_ip_bgp_summary.ref [new file with mode: 0644]
tests/topotests/all-protocol-startup/r1/show_ip_ospf_interface.ref [new file with mode: 0644]
tests/topotests/all-protocol-startup/r1/show_ipv6_ospf6_interface [new file with mode: 0644]
tests/topotests/all-protocol-startup/r1/show_ipv6_ospf6_interface.ref [new file with mode: 0644]
tests/topotests/all-protocol-startup/r1/show_isis_interface_detail.ref [new file with mode: 0644]
tests/topotests/all-protocol-startup/r1/show_mpls_ldp_interface.ref [new file with mode: 0644]
tests/topotests/all-protocol-startup/r1/zebra.conf [new file with mode: 0644]
tests/topotests/all-protocol-startup/test_all_protocol_startup.dot [new file with mode: 0644]
tests/topotests/all-protocol-startup/test_all_protocol_startup.pdf [new file with mode: 0644]
tests/topotests/all-protocol-startup/test_all_protocol_startup.py [new file with mode: 0755]

diff --git a/tests/topotests/all-protocol-startup/r1/bgpd.conf b/tests/topotests/all-protocol-startup/r1/bgpd.conf
new file mode 100644 (file)
index 0000000..9ef8695
--- /dev/null
@@ -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 (file)
index 0000000..b63bc3f
--- /dev/null
@@ -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 (file)
index 0000000..b690071
--- /dev/null
@@ -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 (file)
index 0000000..1a14eaa
--- /dev/null
@@ -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 (file)
index 0000000..1a901b9
--- /dev/null
@@ -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 (file)
index 0000000..4a5255f
--- /dev/null
@@ -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 (file)
index 0000000..899bfda
--- /dev/null
@@ -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 (file)
index 0000000..5d67c14
--- /dev/null
@@ -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 (file)
index 0000000..9b1f556
--- /dev/null
@@ -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 (file)
index 0000000..3be6cd3
--- /dev/null
@@ -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 (file)
index 0000000..fffee63
--- /dev/null
@@ -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 (file)
index 0000000..2b1aff1
--- /dev/null
@@ -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 (file)
index 0000000..9ec4384
--- /dev/null
@@ -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 (file)
index 0000000..d134fb1
--- /dev/null
@@ -0,0 +1,22 @@
+r1-eth0 is up
+  ifindex 2, MTU 1500 bytes, BW XX Mbit <UP,BROADCAST,RUNNING,MULTICAST>
+  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 <UP,BROADCAST,RUNNING,MULTICAST>
+  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 (file)
index 0000000..e69de29
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 (file)
index 0000000..6fbf40b
--- /dev/null
@@ -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 (file)
index 0000000..ebf7ab5
--- /dev/null
@@ -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 (file)
index 0000000..c6bb01c
--- /dev/null
@@ -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 (file)
index 0000000..afb28e0
--- /dev/null
@@ -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 (file)
index 0000000..f39f8f8
--- /dev/null
@@ -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 (file)
index 0000000..23f69bc
Binary files /dev/null and b/tests/topotests/all-protocol-startup/test_all_protocol_startup.pdf differ
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 (executable)
index 0000000..ea70d4f
--- /dev/null
@@ -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)