rip_topo1: Adding new test for RIPv2 Topology

Signed-off-by: Martin Winter <mwinter@opensourcerouting.org>
This commit is contained in:
Martin Winter 2017-04-07 17:22:03 -07:00 committed by Donald Sharp
parent 9f3e0f6493
commit d6df723b10
18 changed files with 593 additions and 0 deletions

View File

@ -0,0 +1,16 @@
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:
193.1.1.0/26
Routing Information Sources:
Gateway BadPackets BadRoutes Distance Last Update
193.1.1.2 0 0 120 XX:XX:XX
Distance: (default is 120)

View File

@ -0,0 +1,9 @@
log file /tmp/r1-ripd.log
!
router rip
version 2
network 193.1.1.0/26
!
line vty
!

View File

@ -0,0 +1,10 @@
Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP
Sub-codes:
(n) - normal, (s) - static, (d) - default, (r) - redistribute,
(i) - interface
Network Next Hop Metric From Tag Time
R(n) 192.168.2.0/24 193.1.1.2 3 193.1.1.2 0 XX:XX
R(n) 192.168.3.0/24 193.1.1.2 3 193.1.1.2 0 XX:XX
C(i) 193.1.1.0/26 0.0.0.0 1 self 0
R(n) 193.1.2.0/24 193.1.1.2 2 193.1.1.2 0 XX:XX

View File

@ -0,0 +1,3 @@
R>* 192.168.2.0/24 [120/3] via 193.1.1.2, r1-eth1
R>* 192.168.3.0/24 [120/3] via 193.1.1.2, r1-eth1
R>* 193.1.2.0/24 [120/2] via 193.1.1.2, r1-eth1

View File

@ -0,0 +1,19 @@
log file /tmp/r1-zebra.log
!
hostname r1
!
interface r1-eth0
ip address 192.168.1.1/24
!
interface r1-eth1
description to sw2 - RIPv2 interface
ip address 193.1.1.1/26
no link-detect
!
ip forwarding
ipv6 forwarding
!
!
line vty
!

View File

@ -0,0 +1,18 @@
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
r2-eth0 2 2
r2-eth1 2 2
Routing for Networks:
193.1.1.0/26
193.1.2.0/24
Routing Information Sources:
Gateway BadPackets BadRoutes Distance Last Update
193.1.2.2 0 0 120 XX:XX:XX
Distance: (default is 120)

View File

@ -0,0 +1,11 @@
log file /tmp/r2-ripd.log
!
!
router rip
version 2
network 193.1.1.0/26
network 193.1.2.0/24
!
line vty
!

View File

@ -0,0 +1,10 @@
Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP
Sub-codes:
(n) - normal, (s) - static, (d) - default, (r) - redistribute,
(i) - interface
Network Next Hop Metric From Tag Time
R(n) 192.168.2.0/24 193.1.2.2 2 193.1.2.2 0 XX:XX
R(n) 192.168.3.0/24 193.1.2.2 2 193.1.2.2 0 XX:XX
C(i) 193.1.1.0/26 0.0.0.0 1 self 0
C(i) 193.1.2.0/24 0.0.0.0 1 self 0

View File

@ -0,0 +1,2 @@
R>* 192.168.2.0/24 [120/2] via 193.1.2.2, r2-eth1
R>* 192.168.3.0/24 [120/2] via 193.1.2.2, r2-eth1

View File

@ -0,0 +1,21 @@
log file /tmp/r2-zebra.log
!
hostname r2
!
interface r2-eth0
description to sw2 - RIPv2 interface
ip address 193.1.1.2/26
no link-detect
!
interface r2-eth1
description to sw3 - RIPv1 interface
ip address 193.1.2.1/24
no link-detect
!
ip forwarding
ipv6 forwarding
!
!
line vty
!

View File

@ -0,0 +1,16 @@
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: connected static
Default version control: send version 2, receive version 2
Interface Send Recv Key-chain
r3-eth1 2 2
Routing for Networks:
193.1.2.0/24
Routing Information Sources:
Gateway BadPackets BadRoutes Distance Last Update
193.1.2.1 0 0 120 XX:XX:XX
Distance: (default is 120)

View File

@ -0,0 +1,12 @@
log file /tmp/r3-ripd.log
!
!
router rip
version 2
redistribute connected
redistribute static
network 193.1.2.0/24
!
line vty
!

View File

@ -0,0 +1,10 @@
Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP
Sub-codes:
(n) - normal, (s) - static, (d) - default, (r) - redistribute,
(i) - interface
Network Next Hop Metric From Tag Time
S(r) 192.168.2.0/24 192.168.3.10 1 self 0
C(r) 192.168.3.0/24 0.0.0.0 1 self 0
R(n) 193.1.1.0/26 193.1.2.1 2 193.1.2.1 0 XX:XX
C(i) 193.1.2.0/24 0.0.0.0 1 self 0

View File

@ -0,0 +1 @@
R>* 193.1.1.0/26 [120/2] via 193.1.2.1, r3-eth1

View File

@ -0,0 +1,22 @@
log file /tmp/r3-zebra.log
!
hostname r3
!
interface r3-eth0
description to sw4 - Stub interface
ip address 192.168.3.1/24
no link-detect
!
interface r3-eth1
description to sw3 - RIPv2 interface
ip address 193.1.2.2/24
no link-detect
!
ip route 192.168.2.0/24 192.168.3.10
!
ip forwarding
ipv6 forwarding
!
!
line vty
!

View File

@ -0,0 +1,61 @@
## GraphViz file for test_rip_topo1
##
## Color coding:
#########################
## Main FRR: #f08080 red
## Switches: #d0e0d0 gray
## RIP: #19e3d9 Cyan
## RIPng: #fcb314 dark yellow
## OSPFv2: #32b835 Green
## OSPFv3: #19e3d9 Cyan
## ISIS IPv4 #fcb314 dark yellow
## ISIS IPv6 #9a81ec purple
## BGP IPv4 #eee3d3 beige
## BGP IPv6 #fdff00 yellow
##### Colors (see http://www.color-hex.com/)
graph test_rip_topo1 {
overlap=false;
constraint=false;
// title
labelloc="t";
label="Test Topologoy RIP Topo1";
######################
# Routers
######################
# Main FRR Router with all protocols
R1 [shape=doubleoctagon, label="R1 FRR\nMain Router", fillcolor="#f08080", style=filled];
# RIP Routers
R2 [shape=doubleoctagon, label="R2 FRR\nRIP Router", fillcolor="#19e3d9", style=filled];
R3 [shape=doubleoctagon, label="R3 FRR\nRIP Router", fillcolor="#19e3d9", style=filled];
######################
# Network Lists
######################
SW1_R1_stub [label="SW1\n192.168.1.0/24", fillcolor="#d0e0d0", style=filled];
# RIP Networks
SW2_R1_R2 [label="SW2\nRIPv2\n193.1.1.0/26", fillcolor="#d0e0d0", style=filled];
SW3_R2_R3 [label="SW3\nRIPv1\n193.1.2.0/24", fillcolor="#d0e0d0", style=filled];
SW4_R3 [label="SW4\n192.168.3.0/24", fillcolor="#d0e0d0", style=filled];
Net_R3_remote [label="Static Net\n192.168.2.0/24"];
######################
# Network Connections
######################
R1 -- SW1_R1_stub [label = "eth0\n.1\n::1"];
# RIP Network
R1 -- SW2_R1_R2 [label = "eth1\n.1"];
SW2_R1_R2 -- R2 [label = "eth0\n.2"];
R2 -- SW3_R2_R3 [label = "eth1\n.1"];
SW3_R2_R3 -- R3 [label = "eth1\n.2"];
R3 -- SW4_R3 [label = "eth0\n.1"];
SW4_R3 -- Net_R3_remote [label = ".10"];
}

Binary file not shown.

View File

@ -0,0 +1,352 @@
#!/usr/bin/env python
#
# test_rip_topo1.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_rip_topo1.py: Testing RIPv2
"""
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):
"RIP Topology 1"
def build(self, **_opts):
# Setup Routers
router = {}
#
# Setup Main Router
router[1] = topotest.addRouter(self, 'r1')
#
# Setup RIP Routers
for i in range(2, 4):
router[i] = topotest.addRouter(self, 'r%s' % i)
#
# Setup Switches
switch = {}
#
# On main router
# First switch is for a dummy interface (for local network)
switch[1] = self.addSwitch('sw1', cls=topotest.LegacySwitch)
self.addLink(switch[1], router[1], intfName2='r1-eth0')
#
# Switches for RIP
# switch 2 switch is for connection to RIP router
switch[2] = self.addSwitch('sw2', cls=topotest.LegacySwitch)
self.addLink(switch[2], router[1], intfName2='r1-eth1')
self.addLink(switch[2], router[2], intfName2='r2-eth0')
# switch 3 is between RIP routers
switch[3] = self.addSwitch('sw3', cls=topotest.LegacySwitch)
self.addLink(switch[3], router[2], intfName2='r2-eth1')
self.addLink(switch[3], router[3], intfName2='r3-eth1')
# switch 4 is stub on remote RIP router
switch[4] = self.addSwitch('sw4', cls=topotest.LegacySwitch)
self.addLink(switch[4], router[3], intfName2='r3-eth0')
#####################################################
##
## Tests starting
##
#####################################################
def setup_module(module):
global topo, net
print("\n\n** %s: Setup Topology" % module.__name__)
print("******************************************\n")
print("Cleanup old Mininet runs")
os.system('sudo mn -c > /dev/null 2>&1')
thisDir = os.path.dirname(os.path.realpath(__file__))
topo = NetworkTopo()
net = Mininet(controller=None, topo=topo)
net.start()
# Starting Routers
#
for i in range(1, 4):
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].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, 4):
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_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, 4):
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_rip_routes():
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 routes")
print("******************************************\n")
failures = 0
for i in range(1, 4):
refTableFile = '%s/r%s/show_ip_rip.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" 2> /dev/null').rstrip()
# Drop Time
actual = re.sub(r"[0-9][0-9]:[0-5][0-9]", "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 SHOW IP RIP",
tofile="expected SHOW IP RIP"))
# Empty string if it matches, otherwise diff contains unified diff
if diff:
sys.stderr.write('r%s failed SHOW IP RIP check:\n%s\n' % (i, diff))
failures += 1
else:
print("r%s ok" % i)
assert failures == 0, "SHOW IP RIP failed for router r%s:\n%s" % (i, diff)
# For debugging after starting FRR/Quagga daemons, uncomment the next line
# CLI(net)
def test_zebra_ipv4_routingTable():
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 OSPFv3 Routing Table
print("\n\n** Verifing Zebra IPv4 Routing Table")
print("******************************************\n")
failures = 0
for i in range(1, 4):
refTableFile = '%s/r%s/show_ip_route.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 route" 2> /dev/null | grep "^R"').rstrip()
# Drop timers on end of line (older Quagga Versions)
actual = re.sub(r", [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", "", 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 Zebra IPv4 routing table",
tofile="expected Zebra IPv4 routing table"))
# Empty string if it matches, otherwise diff contains unified diff
if diff:
sys.stderr.write('r%s failed Zebra IPv4 Routing Table Check:\n%s\n' % (i, diff))
failures += 1
else:
print("r%s ok" % i)
assert failures == 0, "Zebra IPv4 Routing Table verification 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)
if os.environ.get('TOPOTESTS_CHECK_STDERR') is None:
pytest.skip('Skipping test for Stderr output and memory leaks')
thisDir = os.path.dirname(os.path.realpath(__file__))
print("\n\n** Verifing unexpected STDERR output from daemons")
print("******************************************\n")
net['r1'].stopRouter()
log = net['r1'].getStdErr('ripd')
print("\nRIPd 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)