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 <mwinter@opensourcerouting.org>
This commit is contained in:
Martin Winter 2017-04-08 03:49:43 -07:00 committed by Donald Sharp
parent 80eeefb7da
commit 4501fbcaa8
22 changed files with 1241 additions and 0 deletions

View File

@ -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
!

View File

@ -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
!

View File

@ -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
!

View File

@ -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
!

View File

@ -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
!

View File

@ -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)

View File

@ -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
!

View File

@ -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

View File

@ -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
!

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
!

View File

@ -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"];
}

View File

@ -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)