]> git.proxmox.com Git - mirror_frr.git/blame - tests/topotests/eigrp_topo1/test_eigrp_topo1.py
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / tests / topotests / eigrp_topo1 / test_eigrp_topo1.py
CommitLineData
a4e471cf 1#!/usr/bin/env python
acddc0ed 2# SPDX-License-Identifier: ISC
a4e471cf
DS
3
4#
5# test_eigrp_topo1.py
6#
7# Copyright (c) 2017 by
8# Cumulus Networks, Inc.
9# Donald Sharp
10#
a4e471cf
DS
11
12"""
13test_eigrp_topo1.py: Testing EIGRP
14
15"""
16
17import os
18import re
19import sys
a4e471cf 20import pytest
ee4523a2 21import json
a4e471cf 22
6907ac7e
DS
23pytestmark = [pytest.mark.eigrpd]
24
e5355a01
RZ
25# Save the Current Working Directory to find configuration files.
26CWD = os.path.dirname(os.path.realpath(__file__))
787e7624 27sys.path.append(os.path.join(CWD, "../"))
a4e471cf 28
e5355a01
RZ
29# pylint: disable=C0413
30# Import topogen and topotest helpers
a4e471cf 31from lib import topotest
e5355a01
RZ
32from lib.topogen import Topogen, TopoRouter, get_topogen
33from lib.topolog import logger
a4e471cf 34
e5355a01 35# Required to instantiate the topology builder class.
a4e471cf
DS
36
37#####################################################
38##
39## Network Topology Definition
40##
41#####################################################
42
787e7624 43
e82b531d
CH
44def build_topo(tgen):
45 for routern in range(1, 4):
46 tgen.add_router("r{}".format(routern))
a4e471cf 47
e82b531d
CH
48 # On main router
49 # First switch is for a dummy interface (for local network)
50 switch = tgen.add_switch("sw1")
51 switch.add_link(tgen.gears["r1"])
e5355a01 52
e82b531d
CH
53 # Switches for EIGRP
54 # switch 2 switch is for connection to EIGRP router
55 switch = tgen.add_switch("sw2")
56 switch.add_link(tgen.gears["r1"])
57 switch.add_link(tgen.gears["r2"])
e5355a01 58
e82b531d
CH
59 # switch 4 is stub on remote EIGRP router
60 switch = tgen.add_switch("sw4")
61 switch.add_link(tgen.gears["r3"])
a4e471cf 62
e82b531d
CH
63 # switch 3 is between EIGRP routers
64 switch = tgen.add_switch("sw3")
65 switch.add_link(tgen.gears["r2"])
66 switch.add_link(tgen.gears["r3"])
a4e471cf
DS
67
68
69#####################################################
70##
71## Tests starting
72##
73#####################################################
74
6907ac7e 75
a4e471cf 76def setup_module(module):
e5355a01 77 "Setup topology"
e82b531d 78 tgen = Topogen(build_topo, module.__name__)
e5355a01 79 tgen.start_topology()
a4e471cf 80
e5355a01
RZ
81 # This is a sample of configuration loading.
82 router_list = tgen.routers()
e5f0ed14 83 for rname, router in router_list.items():
e5355a01 84 router.load_config(
787e7624 85 TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
e5355a01
RZ
86 )
87 router.load_config(
787e7624 88 TopoRouter.RD_EIGRP, os.path.join(CWD, "{}/eigrpd.conf".format(rname))
e5355a01 89 )
a4e471cf 90
e5355a01 91 tgen.start_router()
a4e471cf 92
a4e471cf 93
e5355a01
RZ
94def teardown_module(_mod):
95 "Teardown the pytest environment"
96 tgen = get_topogen()
a4e471cf 97
e5355a01
RZ
98 # This function tears down the whole topology.
99 tgen.stop_topology()
a4e471cf
DS
100
101
e5355a01
RZ
102def test_converge_protocols():
103 "Wait for protocol convergence"
a4e471cf 104
e5355a01
RZ
105 tgen = get_topogen()
106 # Don't run this test if we have any failure.
107 if tgen.routers_have_failure():
108 pytest.skip(tgen.errors)
a4e471cf 109
787e7624 110 topotest.sleep(5, "Waiting for EIGRP convergence")
a4e471cf 111
a4e471cf 112
e5355a01
RZ
113def test_eigrp_routes():
114 "Test EIGRP 'show ip eigrp'"
a4e471cf 115
e5355a01
RZ
116 tgen = get_topogen()
117 # Don't run this test if we have any failure.
118 if tgen.routers_have_failure():
119 pytest.skip(tgen.errors)
a4e471cf 120
e5355a01
RZ
121 # Verify EIGRP Status
122 logger.info("Verifying EIGRP routes")
a4e471cf 123
e5355a01
RZ
124 router_list = tgen.routers().values()
125 for router in router_list:
787e7624 126 refTableFile = "{}/{}/show_ip_eigrp.json".format(CWD, router.name)
a4e471cf 127
e5355a01 128 # Read expected result from file
7c1f9631 129 expected = json.loads(open(refTableFile).read())
a4e471cf 130
e5355a01 131 # Actual output from router
7c1f9631 132 actual = ip_eigrp_topo(router)
a4e471cf 133
7c1f9631
RZ
134 assertmsg = '"show ip eigrp topo" mismatches on {}'.format(router.name)
135 assert topotest.json_cmp(actual, expected) is None, assertmsg
a4e471cf 136
787e7624 137
e5355a01
RZ
138def test_zebra_ipv4_routingTable():
139 "Test 'show ip route'"
a4e471cf 140
e5355a01
RZ
141 tgen = get_topogen()
142 # Don't run this test if we have any failure.
143 if tgen.routers_have_failure():
144 pytest.skip(tgen.errors)
a4e471cf 145
a4e471cf 146 failures = 0
e5355a01
RZ
147 router_list = tgen.routers().values()
148 for router in router_list:
787e7624 149 output = router.vtysh_cmd("show ip route json", isjson=True)
150 refTableFile = "{}/{}/show_ip_route.json_ref".format(CWD, router.name)
ee4523a2 151 expected = json.loads(open(refTableFile).read())
a4e471cf 152
787e7624 153 assertmsg = "Zebra IPv4 Routing Table verification failed for router {}".format(
154 router.name
155 )
ee4523a2 156 assert topotest.json_cmp(output, expected) is None, assertmsg
a4e471cf 157
787e7624 158
84b5e534
DS
159def test_shut_interface_and_recover():
160 "Test shutdown of an interface and recovery of the interface"
161
162 tgen = get_topogen()
787e7624 163 router = tgen.gears["r1"]
164 router.run("ip link set r1-eth1 down")
165 topotest.sleep(5, "Waiting for EIGRP convergence")
166 router.run("ip link set r1-eth1 up")
84b5e534 167
a4e471cf
DS
168
169def test_shutdown_check_stderr():
787e7624 170 if os.environ.get("TOPOTESTS_CHECK_STDERR") is None:
171 pytest.skip("Skipping test for Stderr output and memory leaks")
a4e471cf 172
e5355a01
RZ
173 tgen = get_topogen()
174 # Don't run this test if we have any failure.
175 if tgen.routers_have_failure():
176 pytest.skip(tgen.errors)
a4e471cf 177
e5355a01 178 logger.info("Verifying unexpected STDERR output from daemons")
a4e471cf 179
e5355a01
RZ
180 router_list = tgen.routers().values()
181 for router in router_list:
182 router.stop()
a4e471cf 183
787e7624 184 log = tgen.net[router.name].getStdErr("eigrpd")
8e957dbb 185 if log:
787e7624 186 logger.error("EIGRPd StdErr Log:" + log)
187 log = tgen.net[router.name].getStdErr("zebra")
8e957dbb 188 if log:
787e7624 189 logger.error("Zebra StdErr Log:" + log)
a4e471cf
DS
190
191
787e7624 192if __name__ == "__main__":
e5355a01
RZ
193 args = ["-s"] + sys.argv[1:]
194 sys.exit(pytest.main(args))
7c1f9631
RZ
195
196#
197# Auxiliary Functions
198#
199def ip_eigrp_topo(node):
200 """
201 Parse 'show ip eigrp topo' from `node` and returns a dict with the
202 result.
203
204 Example:
205 {
206 'P': {
207 '192.168.1.0/24': {
208 'sucessors': 1,
209 'fd': 112233,
210 'serno': 0,
211 'via': 'Connected',
212 'interface': 'eth0',
213 },
214 '192.168.2.0/24': {
215 'sucessors': 1,
216 'fd': 112234,
217 'serno': 0,
218 'via': 'Connected',
219 'interface': 'eth1',
220 }
221 }
222 }
223 """
787e7624 224 output = topotest.normalize_text(node.vtysh_cmd("show ip eigrp topo")).splitlines()
7c1f9631
RZ
225 result = {}
226 for idx, line in enumerate(output):
787e7624 227 columns = line.split(" ", 1)
7c1f9631
RZ
228
229 # Parse the following format into python dicts
230 # code A.B.C.D/E, X successors, FD is Y, serno: Z
231 # via FOO, interface-name
232 code = columns[0]
787e7624 233 if code not in ["P", "A", "U", "Q", "R", "r", "s"]:
7c1f9631
RZ
234 continue
235
11761ab0 236 if code not in result:
7c1f9631
RZ
237 result[code] = {}
238
239 # Split network from the rest
787e7624 240 columns = columns[1].split(",")
7c1f9631
RZ
241
242 # Parse first line data
243 network = columns[0]
244 result[code][network] = {}
245 for column in columns:
246 # Skip the network column
247 if column == columns[0]:
248 continue
249
787e7624 250 match = re.search(r"(\d+) successors", column)
7c1f9631 251 if match is not None:
787e7624 252 result[code][network]["successors"] = match.group(1)
7c1f9631
RZ
253 continue
254
787e7624 255 match = re.search(r"FD is (\d+)", column)
7c1f9631 256 if match is not None:
787e7624 257 result[code][network]["fd"] = match.group(1)
7c1f9631
RZ
258 continue
259
787e7624 260 match = re.search(r"serno: (\d+)", column)
7c1f9631 261 if match is not None:
787e7624 262 result[code][network]["serno"] = match.group(1)
7c1f9631
RZ
263 continue
264
265 # Parse second line data
266 nextline = output[idx + 1]
787e7624 267 columns = topotest.normalize_text(nextline).split(",")
7c1f9631 268 for column in columns:
787e7624 269 match = re.search(r"via (.+)", column)
7c1f9631 270 if match is not None:
787e7624 271 result[code][network]["via"] = match.group(1)
7c1f9631
RZ
272 continue
273
787e7624 274 match = re.search(r"(.+)", column)
7c1f9631 275 if match is not None:
787e7624 276 result[code][network]["interface"] = match.group(1)
7c1f9631
RZ
277 continue
278
279 return result