]>
Commit | Line | Data |
---|---|---|
4501fbca MW |
1 | #!/usr/bin/env python |
2 | ||
3 | # | |
4 | # test_all_protocol_startup.py | |
5 | # Part of NetDEF Topology Tests | |
6 | # | |
7 | # Copyright (c) 2017 by | |
8 | # Network Device Education Foundation, Inc. ("NetDEF") | |
9 | # | |
10 | # Permission to use, copy, modify, and/or distribute this software | |
11 | # for any purpose with or without fee is hereby granted, provided | |
12 | # that the above copyright notice and this permission notice appear | |
13 | # in all copies. | |
14 | # | |
15 | # THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES | |
16 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
17 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR | |
18 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY | |
19 | # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | |
20 | # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS | |
21 | # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |
22 | # OF THIS SOFTWARE. | |
23 | # | |
24 | ||
25 | """ | |
26 | test_all_protocol_startup.py: Test of all protocols at same time | |
27 | ||
28 | """ | |
29 | ||
30 | import os | |
31 | import re | |
32 | import sys | |
4501fbca | 33 | import pytest |
6a57e103 | 34 | import glob |
4501fbca MW |
35 | from time import sleep |
36 | ||
37 | from mininet.topo import Topo | |
38 | from mininet.net import Mininet | |
39 | from mininet.node import Node, OVSSwitch, Host | |
40 | from mininet.log import setLogLevel, info | |
41 | from mininet.cli import CLI | |
42 | from mininet.link import Intf | |
43 | ||
44 | from functools import partial | |
45 | ||
46 | sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | |
47 | from lib import topotest | |
48 | ||
49 | fatal_error = "" | |
50 | ||
51 | ||
52 | ##################################################### | |
53 | ## | |
54 | ## Network Topology Definition | |
55 | ## | |
56 | ##################################################### | |
57 | ||
701a0192 | 58 | |
4501fbca MW |
59 | class NetworkTopo(Topo): |
60 | "All Protocol Startup Test" | |
61 | ||
62 | def build(self, **_opts): | |
63 | ||
64 | # Setup Routers | |
65 | router = {} | |
66 | # | |
67 | # Setup Main Router | |
701a0192 | 68 | router[1] = topotest.addRouter(self, "r1") |
4501fbca MW |
69 | # |
70 | ||
71 | # Setup Switches | |
72 | switch = {} | |
73 | # | |
74 | for i in range(0, 10): | |
701a0192 | 75 | switch[i] = self.addSwitch("sw%s" % i, cls=topotest.LegacySwitch) |
76 | self.addLink(switch[i], router[1], intfName2="r1-eth%s" % i) | |
4501fbca MW |
77 | |
78 | ||
79 | ##################################################### | |
80 | ## | |
81 | ## Tests starting | |
82 | ## | |
83 | ##################################################### | |
84 | ||
701a0192 | 85 | |
4501fbca MW |
86 | def setup_module(module): |
87 | global topo, net | |
88 | global fatal_error | |
89 | ||
90 | print("\n\n** %s: Setup Topology" % module.__name__) | |
91 | print("******************************************\n") | |
92 | ||
93 | print("Cleanup old Mininet runs") | |
701a0192 | 94 | os.system("sudo mn -c > /dev/null 2>&1") |
95 | os.system("sudo rm /tmp/r* > /dev/null 2>&1") | |
4501fbca MW |
96 | |
97 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
98 | topo = NetworkTopo() | |
99 | ||
100 | net = Mininet(controller=None, topo=topo) | |
101 | net.start() | |
102 | ||
701a0192 | 103 | if net["r1"].get_routertype() != "frr": |
4501fbca | 104 | fatal_error = "Test is only implemented for FRR" |
701a0192 | 105 | sys.stderr.write("\n\nTest is only implemented for FRR - Skipping\n\n") |
4501fbca | 106 | pytest.skip(fatal_error) |
701a0192 | 107 | |
4501fbca MW |
108 | # Starting Routers |
109 | # | |
110 | # Main router | |
111 | for i in range(1, 2): | |
701a0192 | 112 | net["r%s" % i].loadConf("zebra", "%s/r%s/zebra.conf" % (thisDir, i)) |
113 | net["r%s" % i].loadConf("ripd", "%s/r%s/ripd.conf" % (thisDir, i)) | |
114 | net["r%s" % i].loadConf("ripngd", "%s/r%s/ripngd.conf" % (thisDir, i)) | |
115 | net["r%s" % i].loadConf("ospfd", "%s/r%s/ospfd.conf" % (thisDir, i)) | |
116 | if net["r1"].checkRouterVersion("<", "4.0"): | |
117 | net["r%s" % i].loadConf( | |
118 | "ospf6d", "%s/r%s/ospf6d.conf-pre-v4" % (thisDir, i) | |
119 | ) | |
11761ab0 | 120 | else: |
701a0192 | 121 | net["r%s" % i].loadConf("ospf6d", "%s/r%s/ospf6d.conf" % (thisDir, i)) |
122 | net["r%s" % i].loadConf("isisd", "%s/r%s/isisd.conf" % (thisDir, i)) | |
123 | net["r%s" % i].loadConf("bgpd", "%s/r%s/bgpd.conf" % (thisDir, i)) | |
124 | if net["r%s" % i].daemon_available("ldpd"): | |
4501fbca | 125 | # Only test LDPd if it's installed and Kernel >= 4.5 |
701a0192 | 126 | net["r%s" % i].loadConf("ldpd", "%s/r%s/ldpd.conf" % (thisDir, i)) |
127 | net["r%s" % i].loadConf("sharpd") | |
128 | net["r%s" % i].loadConf("nhrpd", "%s/r%s/nhrpd.conf" % (thisDir, i)) | |
129 | net["r%s" % i].loadConf("babeld", "%s/r%s/babeld.conf" % (thisDir, i)) | |
130 | net["r%s" % i].loadConf("pbrd", "%s/r%s/pbrd.conf" % (thisDir, i)) | |
131 | net["r%s" % i].startRouter() | |
4501fbca | 132 | |
622c4996 | 133 | # For debugging after starting FRR daemons, uncomment the next line |
4501fbca MW |
134 | # CLI(net) |
135 | ||
136 | ||
137 | def teardown_module(module): | |
138 | global net | |
139 | ||
140 | print("\n\n** %s: Shutdown Topology" % module.__name__) | |
141 | print("******************************************\n") | |
142 | ||
143 | # End - Shutdown network | |
144 | net.stop() | |
145 | ||
146 | ||
147 | def test_router_running(): | |
148 | global fatal_error | |
149 | global net | |
150 | ||
151 | # Skip if previous fatal error condition is raised | |
701a0192 | 152 | if fatal_error != "": |
4501fbca MW |
153 | pytest.skip(fatal_error) |
154 | ||
622c4996 | 155 | print("\n\n** Check if FRR is running on each Router node") |
4501fbca MW |
156 | print("******************************************\n") |
157 | sleep(5) | |
158 | ||
159 | # Starting Routers | |
160 | for i in range(1, 2): | |
701a0192 | 161 | fatal_error = net["r%s" % i].checkRouterRunning() |
4501fbca MW |
162 | assert fatal_error == "", fatal_error |
163 | ||
622c4996 | 164 | # For debugging after starting FRR daemons, uncomment the next line |
4501fbca MW |
165 | # CLI(net) |
166 | ||
167 | ||
168 | def test_error_messages_vtysh(): | |
169 | global fatal_error | |
170 | global net | |
171 | ||
172 | # Skip if previous fatal error condition is raised | |
701a0192 | 173 | if fatal_error != "": |
4501fbca MW |
174 | pytest.skip(fatal_error) |
175 | ||
176 | print("\n\n** Check for error messages on VTYSH") | |
177 | print("******************************************\n") | |
178 | ||
179 | failures = 0 | |
180 | for i in range(1, 2): | |
181 | # | |
182 | # First checking Standard Output | |
183 | # | |
184 | ||
185 | # VTYSH output from router | |
701a0192 | 186 | vtystdout = net["r%s" % i].cmd('vtysh -c "show version" 2> /dev/null').rstrip() |
4501fbca MW |
187 | |
188 | # Fix newlines (make them all the same) | |
701a0192 | 189 | vtystdout = ("\n".join(vtystdout.splitlines()) + "\n").rstrip() |
4501fbca MW |
190 | # Drop everything starting with "FRRouting X.xx" message |
191 | vtystdout = re.sub(r"FRRouting [0-9]+.*", "", vtystdout, flags=re.DOTALL) | |
192 | ||
701a0192 | 193 | if vtystdout == "": |
4501fbca MW |
194 | print("r%s StdOut ok" % i) |
195 | ||
701a0192 | 196 | assert vtystdout == "", "Vtysh StdOut Output check failed for router r%s" % i |
798fb593 | 197 | |
4501fbca MW |
198 | # |
199 | # Second checking Standard Error | |
200 | # | |
201 | ||
202 | # VTYSH StdErr output from router | |
701a0192 | 203 | vtystderr = net["r%s" % i].cmd('vtysh -c "show version" > /dev/null').rstrip() |
4501fbca MW |
204 | |
205 | # Fix newlines (make them all the same) | |
701a0192 | 206 | vtystderr = ("\n".join(vtystderr.splitlines()) + "\n").rstrip() |
4501fbca | 207 | # # Drop everything starting with "FRRouting X.xx" message |
701a0192 | 208 | # vtystderr = re.sub(r"FRRouting [0-9]+.*", "", vtystderr, flags=re.DOTALL) |
4501fbca | 209 | |
701a0192 | 210 | if vtystderr == "": |
4501fbca MW |
211 | print("r%s StdErr ok" % i) |
212 | ||
701a0192 | 213 | assert vtystderr == "", "Vtysh StdErr Output check failed for router r%s" % i |
4501fbca | 214 | |
7e7fc73b MW |
215 | # Make sure that all daemons are running |
216 | for i in range(1, 2): | |
701a0192 | 217 | fatal_error = net["r%s" % i].checkRouterRunning() |
7e7fc73b MW |
218 | assert fatal_error == "", fatal_error |
219 | ||
622c4996 | 220 | # For debugging after starting FRR daemons, uncomment the next line |
4501fbca MW |
221 | # CLI(net) |
222 | ||
223 | ||
224 | def test_error_messages_daemons(): | |
225 | global fatal_error | |
226 | global net | |
227 | ||
228 | # Skip if previous fatal error condition is raised | |
701a0192 | 229 | if fatal_error != "": |
4501fbca MW |
230 | pytest.skip(fatal_error) |
231 | ||
232 | print("\n\n** Check for error messages in daemons") | |
233 | print("******************************************\n") | |
234 | ||
235 | error_logs = "" | |
236 | ||
237 | for i in range(1, 2): | |
701a0192 | 238 | log = net["r%s" % i].getStdErr("ripd") |
4501fbca MW |
239 | if log: |
240 | error_logs += "r%s RIPd StdErr Output:\n" % i | |
241 | error_logs += log | |
701a0192 | 242 | log = net["r%s" % i].getStdErr("ripngd") |
4501fbca MW |
243 | if log: |
244 | error_logs += "r%s RIPngd StdErr Output:\n" % i | |
245 | error_logs += log | |
701a0192 | 246 | log = net["r%s" % i].getStdErr("ospfd") |
4501fbca MW |
247 | if log: |
248 | error_logs += "r%s OSPFd StdErr Output:\n" % i | |
249 | error_logs += log | |
701a0192 | 250 | log = net["r%s" % i].getStdErr("ospf6d") |
4501fbca MW |
251 | if log: |
252 | error_logs += "r%s OSPF6d StdErr Output:\n" % i | |
253 | error_logs += log | |
701a0192 | 254 | log = net["r%s" % i].getStdErr("isisd") |
4501fbca MW |
255 | # ISIS shows debugging enabled status on StdErr |
256 | # Remove these messages | |
257 | log = re.sub(r"^IS-IS .* debugging is on.*", "", log).rstrip() | |
258 | if log: | |
259 | error_logs += "r%s ISISd StdErr Output:\n" % i | |
260 | error_logs += log | |
701a0192 | 261 | log = net["r%s" % i].getStdErr("bgpd") |
4501fbca MW |
262 | if log: |
263 | error_logs += "r%s BGPd StdErr Output:\n" % i | |
264 | error_logs += log | |
701a0192 | 265 | if net["r%s" % i].daemon_available("ldpd"): |
266 | log = net["r%s" % i].getStdErr("ldpd") | |
4501fbca MW |
267 | if log: |
268 | error_logs += "r%s LDPd StdErr Output:\n" % i | |
269 | error_logs += log | |
af39fbe7 | 270 | |
701a0192 | 271 | log = net["r1"].getStdErr("nhrpd") |
af39fbe7 MS |
272 | if log: |
273 | error_logs += "r%s NHRPd StdErr Output:\n" % i | |
274 | error_logs += log | |
275 | ||
701a0192 | 276 | log = net["r1"].getStdErr("babeld") |
af39fbe7 MS |
277 | if log: |
278 | error_logs += "r%s BABELd StdErr Output:\n" % i | |
279 | error_logs += log | |
280 | ||
701a0192 | 281 | log = net["r1"].getStdErr("pbrd") |
af39fbe7 MS |
282 | if log: |
283 | error_logs += "r%s PBRd StdErr Output:\n" % i | |
284 | error_logs += log | |
285 | ||
701a0192 | 286 | log = net["r%s" % i].getStdErr("zebra") |
4501fbca MW |
287 | if log: |
288 | error_logs += "r%s Zebra StdErr Output:\n" | |
289 | error_logs += log | |
290 | ||
291 | if error_logs: | |
701a0192 | 292 | sys.stderr.write( |
293 | "Failed check for StdErr Output on daemons:\n%s\n" % error_logs | |
294 | ) | |
4501fbca | 295 | |
08fa1af7 | 296 | # Ignoring the issue if told to ignore (ie not yet fixed) |
701a0192 | 297 | if error_logs != "": |
298 | if os.environ.get("bamboo_TOPOTESTS_ISSUE_349") == "IGNORE": | |
299 | sys.stderr.write( | |
300 | "Known issue - IGNORING. See https://github.com/FRRouting/frr/issues/349\n" | |
301 | ) | |
302 | pytest.skip( | |
303 | "Known issue - IGNORING. See https://github.com/FRRouting/frr/issues/349" | |
304 | ) | |
08fa1af7 | 305 | |
4501fbca MW |
306 | assert error_logs == "", "Daemons report errors to StdErr" |
307 | ||
622c4996 | 308 | # For debugging after starting FRR daemons, uncomment the next line |
4501fbca MW |
309 | # CLI(net) |
310 | ||
311 | ||
312 | def test_converge_protocols(): | |
313 | global fatal_error | |
314 | global net | |
315 | ||
316 | # Skip if previous fatal error condition is raised | |
701a0192 | 317 | if fatal_error != "": |
4501fbca MW |
318 | pytest.skip(fatal_error) |
319 | ||
320 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
321 | ||
322 | print("\n\n** Waiting for protocols convergence") | |
323 | print("******************************************\n") | |
324 | ||
325 | # Not really implemented yet - just sleep 60 secs for now | |
326 | sleep(60) | |
327 | ||
7e7fc73b | 328 | # Make sure that all daemons are running |
556f76e1 | 329 | failures = 0 |
7e7fc73b | 330 | for i in range(1, 2): |
701a0192 | 331 | fatal_error = net["r%s" % i].checkRouterRunning() |
7e7fc73b MW |
332 | assert fatal_error == "", fatal_error |
333 | ||
701a0192 | 334 | print("Show that v4 routes are right\n") |
335 | v4_routesFile = "%s/r%s/ipv4_routes.ref" % (thisDir, i) | |
556f76e1 | 336 | expected = open(v4_routesFile).read().rstrip() |
701a0192 | 337 | expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1) |
338 | ||
339 | actual = ( | |
340 | net["r%s" % i] | |
341 | .cmd( | |
342 | 'vtysh -c "show ip route" | /usr/bin/tail -n +7 | env LC_ALL=en_US.UTF-8 sort 2> /dev/null' | |
343 | ) | |
344 | .rstrip() | |
345 | ) | |
556f76e1 DS |
346 | # Drop time in last update |
347 | actual = re.sub(r" [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", " XX:XX:XX", actual) | |
701a0192 | 348 | actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) |
349 | diff = topotest.get_textdiff( | |
350 | actual, | |
351 | expected, | |
352 | title1="Actual IP Routing Table", | |
353 | title2="Expected IP RoutingTable", | |
354 | ) | |
556f76e1 | 355 | if diff: |
701a0192 | 356 | sys.stderr.write("r%s failed IP Routing table check:\n%s\n" % (i, diff)) |
556f76e1 DS |
357 | failures += 1 |
358 | else: | |
701a0192 | 359 | print("r%s ok" % i) |
556f76e1 DS |
360 | |
361 | assert failures == 0, "IP Routing table failed for r%s\n%s" % (i, diff) | |
362 | ||
363 | failures = 0 | |
364 | ||
365 | print("Show that v6 routes are right\n") | |
701a0192 | 366 | v6_routesFile = "%s/r%s/ipv6_routes.ref" % (thisDir, i) |
556f76e1 | 367 | expected = open(v6_routesFile).read().rstrip() |
701a0192 | 368 | expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1) |
369 | ||
370 | actual = ( | |
371 | net["r%s" % i] | |
372 | .cmd( | |
373 | 'vtysh -c "show ipv6 route" | /usr/bin/tail -n +7 | env LC_ALL=en_US.UTF-8 sort 2> /dev/null' | |
374 | ) | |
375 | .rstrip() | |
376 | ) | |
556f76e1 DS |
377 | # Drop time in last update |
378 | actual = re.sub(r" [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", " XX:XX:XX", actual) | |
701a0192 | 379 | actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) |
380 | diff = topotest.get_textdiff( | |
381 | actual, | |
382 | expected, | |
383 | title1="Actual IPv6 Routing Table", | |
384 | title2="Expected IPv6 RoutingTable", | |
385 | ) | |
556f76e1 | 386 | if diff: |
701a0192 | 387 | sys.stderr.write("r%s failed IPv6 Routing table check:\n%s\n" % (i, diff)) |
556f76e1 DS |
388 | failures += 1 |
389 | else: | |
701a0192 | 390 | print("r%s ok" % i) |
556f76e1 DS |
391 | |
392 | assert failures == 0, "IPv6 Routing table failed for r%s\n%s" % (i, diff) | |
393 | ||
622c4996 | 394 | # For debugging after starting FRR daemons, uncomment the next line |
4501fbca MW |
395 | ## CLI(net) |
396 | ||
701a0192 | 397 | |
887a232c SW |
398 | def route_get_nhg_id(route_str): |
399 | output = net["r1"].cmd('vtysh -c "show ip route %s nexthop-group"' % route_str) | |
400 | match = re.search(r"Nexthop Group ID: (\d+)", output) | |
701a0192 | 401 | assert match is not None, ( |
402 | "Nexthop Group ID not found for sharpd route %s" % route_str | |
403 | ) | |
887a232c SW |
404 | |
405 | nhg_id = int(match.group(1)) | |
406 | return nhg_id | |
407 | ||
701a0192 | 408 | |
8f4d7212 | 409 | def verify_nexthop_group(nhg_id, recursive=False, ecmp=0): |
887a232c SW |
410 | # Verify NHG is valid/installed |
411 | output = net["r1"].cmd('vtysh -c "show nexthop-group rib %d"' % nhg_id) | |
412 | ||
413 | match = re.search(r"Valid", output) | |
414 | assert match is not None, "Nexthop Group ID=%d not marked Valid" % nhg_id | |
415 | ||
8f4d7212 SW |
416 | if ecmp or recursive: |
417 | match = re.search(r"Depends:.*\n", output) | |
418 | assert match is not None, "Nexthop Group ID=%d has no depends" % nhg_id | |
419 | ||
420 | # list of IDs in group | |
421 | depends = re.findall(r"\((\d+)\)", match.group(0)) | |
422 | ||
423 | if ecmp: | |
701a0192 | 424 | assert len(depends) == ecmp, ( |
425 | "Nexthop Group ID=%d doesn't match ecmp size" % nhg_id | |
426 | ) | |
8f4d7212 SW |
427 | else: |
428 | # If recursive, we need to look at its resolved group | |
701a0192 | 429 | assert len(depends) == 1, ( |
430 | "Nexthop Group ID=%d should only have one recursive depend" % nhg_id | |
431 | ) | |
8f4d7212 SW |
432 | resolved_id = int(depends[0]) |
433 | verify_nexthop_group(resolved_id, False) | |
434 | ||
887a232c SW |
435 | else: |
436 | match = re.search(r"Installed", output) | |
437 | assert match is not None, "Nexthop Group ID=%d not marked Installed" % nhg_id | |
438 | ||
701a0192 | 439 | |
8f4d7212 | 440 | def verify_route_nexthop_group(route_str, recursive=False, ecmp=0): |
887a232c SW |
441 | # Verify route and that zebra created NHGs for and they are valid/installed |
442 | nhg_id = route_get_nhg_id(route_str) | |
8f4d7212 | 443 | verify_nexthop_group(nhg_id, recursive, ecmp) |
887a232c | 444 | |
701a0192 | 445 | |
8058df22 SW |
446 | def test_nexthop_groups(): |
447 | global fatal_error | |
448 | global net | |
449 | ||
450 | # Skip if previous fatal error condition is raised | |
701a0192 | 451 | if fatal_error != "": |
8058df22 SW |
452 | pytest.skip(fatal_error) |
453 | ||
454 | print("\n\n** Verifying Nexthop Groups") | |
455 | print("******************************************\n") | |
456 | ||
887a232c SW |
457 | ### Nexthop Group Tests |
458 | ||
459 | ## Basic test | |
460 | ||
8058df22 | 461 | # Create a lib nexthop-group |
701a0192 | 462 | net["r1"].cmd( |
463 | 'vtysh -c "c t" -c "nexthop-group basic" -c "nexthop 1.1.1.1" -c "nexthop 1.1.1.2"' | |
464 | ) | |
8058df22 SW |
465 | |
466 | # Create with sharpd using nexthop-group | |
887a232c | 467 | net["r1"].cmd('vtysh -c "sharp install routes 2.2.2.1 nexthop-group basic 1"') |
8058df22 | 468 | |
887a232c | 469 | verify_route_nexthop_group("2.2.2.1/32") |
8058df22 | 470 | |
887a232c | 471 | ## Connected |
8058df22 | 472 | |
701a0192 | 473 | net["r1"].cmd( |
474 | 'vtysh -c "c t" -c "nexthop-group connected" -c "nexthop r1-eth1" -c "nexthop r1-eth2"' | |
475 | ) | |
8058df22 | 476 | |
887a232c SW |
477 | net["r1"].cmd('vtysh -c "sharp install routes 2.2.2.2 nexthop-group connected 1"') |
478 | ||
479 | verify_route_nexthop_group("2.2.2.2/32") | |
480 | ||
481 | ## Recursive | |
482 | ||
701a0192 | 483 | net["r1"].cmd( |
484 | 'vtysh -c "c t" -c "nexthop-group basic-recursive" -c "nexthop 2.2.2.1"' | |
485 | ) | |
887a232c | 486 | |
701a0192 | 487 | net["r1"].cmd( |
488 | 'vtysh -c "sharp install routes 3.3.3.1 nexthop-group basic-recursive 1"' | |
489 | ) | |
887a232c SW |
490 | |
491 | verify_route_nexthop_group("3.3.3.1/32", True) | |
492 | ||
493 | ## Duplicate | |
494 | ||
701a0192 | 495 | net["r1"].cmd( |
496 | 'vtysh -c "c t" -c "nexthop-group duplicate" -c "nexthop 2.2.2.1" -c "nexthop 1.1.1.1"' | |
497 | ) | |
887a232c SW |
498 | |
499 | net["r1"].cmd('vtysh -c "sharp install routes 3.3.3.2 nexthop-group duplicate 1"') | |
500 | ||
501 | verify_route_nexthop_group("3.3.3.2/32") | |
502 | ||
503 | ## Two 4-Way ECMP | |
504 | ||
701a0192 | 505 | net["r1"].cmd( |
506 | 'vtysh -c "c t" -c "nexthop-group fourA" -c "nexthop 1.1.1.1" -c "nexthop 1.1.1.2" \ | |
507 | -c "nexthop 1.1.1.3" -c "nexthop 1.1.1.4"' | |
508 | ) | |
887a232c SW |
509 | |
510 | net["r1"].cmd('vtysh -c "sharp install routes 4.4.4.1 nexthop-group fourA 1"') | |
511 | ||
512 | verify_route_nexthop_group("4.4.4.1/32") | |
513 | ||
701a0192 | 514 | net["r1"].cmd( |
515 | 'vtysh -c "c t" -c "nexthop-group fourB" -c "nexthop 1.1.1.5" -c "nexthop 1.1.1.6" \ | |
516 | -c "nexthop 1.1.1.7" -c "nexthop 1.1.1.8"' | |
517 | ) | |
887a232c SW |
518 | |
519 | net["r1"].cmd('vtysh -c "sharp install routes 4.4.4.2 nexthop-group fourB 1"') | |
520 | ||
521 | verify_route_nexthop_group("4.4.4.2/32") | |
522 | ||
523 | ## Recursive to 8-Way ECMP | |
524 | ||
701a0192 | 525 | net["r1"].cmd( |
526 | 'vtysh -c "c t" -c "nexthop-group eight-recursive" -c "nexthop 4.4.4.1" -c "nexthop 4.4.4.2"' | |
527 | ) | |
887a232c | 528 | |
701a0192 | 529 | net["r1"].cmd( |
530 | 'vtysh -c "sharp install routes 5.5.5.1 nexthop-group eight-recursive 1"' | |
531 | ) | |
887a232c SW |
532 | |
533 | verify_route_nexthop_group("5.5.5.1/32") | |
534 | ||
535 | ##CLI(net) | |
536 | ||
537 | ## Remove all NHG routes | |
538 | ||
539 | net["r1"].cmd('vtysh -c "sharp remove routes 2.2.2.1 1"') | |
540 | net["r1"].cmd('vtysh -c "sharp remove routes 2.2.2.2 1"') | |
541 | net["r1"].cmd('vtysh -c "sharp remove routes 3.3.3.1 1"') | |
542 | net["r1"].cmd('vtysh -c "sharp remove routes 3.3.3.2 1"') | |
543 | net["r1"].cmd('vtysh -c "sharp remove routes 4.4.4.1 1"') | |
544 | net["r1"].cmd('vtysh -c "sharp remove routes 4.4.4.2 1"') | |
545 | net["r1"].cmd('vtysh -c "sharp remove routes 5.5.5.1 1"') | |
4501fbca | 546 | |
701a0192 | 547 | |
4501fbca MW |
548 | def test_rip_status(): |
549 | global fatal_error | |
550 | global net | |
551 | ||
552 | # Skip if previous fatal error condition is raised | |
701a0192 | 553 | if fatal_error != "": |
4501fbca MW |
554 | pytest.skip(fatal_error) |
555 | ||
556 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
557 | ||
b2764f90 | 558 | print("\n\n** Verifying RIP status") |
4501fbca MW |
559 | print("******************************************\n") |
560 | failures = 0 | |
561 | for i in range(1, 2): | |
701a0192 | 562 | refTableFile = "%s/r%s/rip_status.ref" % (thisDir, i) |
4501fbca MW |
563 | if os.path.isfile(refTableFile): |
564 | # Read expected result from file | |
565 | expected = open(refTableFile).read().rstrip() | |
566 | # Fix newlines (make them all the same) | |
701a0192 | 567 | expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1) |
4501fbca MW |
568 | |
569 | # Actual output from router | |
701a0192 | 570 | actual = ( |
571 | net["r%s" % i] | |
572 | .cmd('vtysh -c "show ip rip status" 2> /dev/null') | |
573 | .rstrip() | |
574 | ) | |
575 | # Drop time in next due | |
4501fbca MW |
576 | actual = re.sub(r"in [0-9]+ seconds", "in XX seconds", actual) |
577 | # Drop time in last update | |
578 | actual = re.sub(r" [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", " XX:XX:XX", actual) | |
579 | # Fix newlines (make them all the same) | |
701a0192 | 580 | actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) |
4501fbca MW |
581 | |
582 | # Generate Diff | |
701a0192 | 583 | diff = topotest.get_textdiff( |
584 | actual, | |
585 | expected, | |
17070436 | 586 | title1="actual IP RIP status", |
701a0192 | 587 | title2="expected IP RIP status", |
588 | ) | |
4501fbca MW |
589 | |
590 | # Empty string if it matches, otherwise diff contains unified diff | |
591 | if diff: | |
701a0192 | 592 | sys.stderr.write("r%s failed IP RIP status check:\n%s\n" % (i, diff)) |
4501fbca MW |
593 | failures += 1 |
594 | else: | |
595 | print("r%s ok" % i) | |
596 | ||
597 | assert failures == 0, "IP RIP status failed for router r%s:\n%s" % (i, diff) | |
598 | ||
7e7fc73b MW |
599 | # Make sure that all daemons are running |
600 | for i in range(1, 2): | |
701a0192 | 601 | fatal_error = net["r%s" % i].checkRouterRunning() |
7e7fc73b MW |
602 | assert fatal_error == "", fatal_error |
603 | ||
622c4996 | 604 | # For debugging after starting FRR daemons, uncomment the next line |
4501fbca MW |
605 | # CLI(net) |
606 | ||
607 | ||
608 | def test_ripng_status(): | |
609 | global fatal_error | |
610 | global net | |
611 | ||
612 | # Skip if previous fatal error condition is raised | |
701a0192 | 613 | if fatal_error != "": |
4501fbca MW |
614 | pytest.skip(fatal_error) |
615 | ||
616 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
617 | ||
b2764f90 | 618 | print("\n\n** Verifying RIPng status") |
4501fbca MW |
619 | print("******************************************\n") |
620 | failures = 0 | |
621 | for i in range(1, 2): | |
701a0192 | 622 | refTableFile = "%s/r%s/ripng_status.ref" % (thisDir, i) |
4501fbca MW |
623 | if os.path.isfile(refTableFile): |
624 | # Read expected result from file | |
625 | expected = open(refTableFile).read().rstrip() | |
626 | # Fix newlines (make them all the same) | |
701a0192 | 627 | expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1) |
4501fbca MW |
628 | |
629 | # Actual output from router | |
701a0192 | 630 | actual = ( |
631 | net["r%s" % i] | |
632 | .cmd('vtysh -c "show ipv6 ripng status" 2> /dev/null') | |
633 | .rstrip() | |
634 | ) | |
4501fbca MW |
635 | # Mask out Link-Local mac address portion. They are random... |
636 | actual = re.sub(r" fe80::[0-9a-f:]+", " fe80::XXXX:XXXX:XXXX:XXXX", actual) | |
701a0192 | 637 | # Drop time in next due |
4501fbca MW |
638 | actual = re.sub(r"in [0-9]+ seconds", "in XX seconds", actual) |
639 | # Drop time in last update | |
640 | actual = re.sub(r" [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", " XX:XX:XX", actual) | |
641 | # Fix newlines (make them all the same) | |
701a0192 | 642 | actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) |
4501fbca MW |
643 | |
644 | # Generate Diff | |
701a0192 | 645 | diff = topotest.get_textdiff( |
646 | actual, | |
647 | expected, | |
17070436 | 648 | title1="actual IPv6 RIPng status", |
701a0192 | 649 | title2="expected IPv6 RIPng status", |
650 | ) | |
4501fbca MW |
651 | |
652 | # Empty string if it matches, otherwise diff contains unified diff | |
653 | if diff: | |
701a0192 | 654 | sys.stderr.write( |
655 | "r%s failed IPv6 RIPng status check:\n%s\n" % (i, diff) | |
656 | ) | |
4501fbca MW |
657 | failures += 1 |
658 | else: | |
659 | print("r%s ok" % i) | |
660 | ||
701a0192 | 661 | assert failures == 0, "IPv6 RIPng status failed for router r%s:\n%s" % ( |
662 | i, | |
663 | diff, | |
664 | ) | |
4501fbca | 665 | |
7e7fc73b MW |
666 | # Make sure that all daemons are running |
667 | for i in range(1, 2): | |
701a0192 | 668 | fatal_error = net["r%s" % i].checkRouterRunning() |
7e7fc73b MW |
669 | assert fatal_error == "", fatal_error |
670 | ||
622c4996 | 671 | # For debugging after starting FRR daemons, uncomment the next line |
4501fbca MW |
672 | # CLI(net) |
673 | ||
674 | ||
675 | def test_ospfv2_interfaces(): | |
676 | global fatal_error | |
677 | global net | |
678 | ||
679 | # Skip if previous fatal error condition is raised | |
701a0192 | 680 | if fatal_error != "": |
4501fbca MW |
681 | pytest.skip(fatal_error) |
682 | ||
683 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
684 | ||
b2764f90 | 685 | print("\n\n** Verifying OSPFv2 interfaces") |
4501fbca MW |
686 | print("******************************************\n") |
687 | failures = 0 | |
688 | for i in range(1, 2): | |
701a0192 | 689 | refTableFile = "%s/r%s/show_ip_ospf_interface.ref" % (thisDir, i) |
4501fbca MW |
690 | if os.path.isfile(refTableFile): |
691 | # Read expected result from file | |
692 | expected = open(refTableFile).read().rstrip() | |
693 | # Fix newlines (make them all the same) | |
701a0192 | 694 | expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1) |
4501fbca MW |
695 | |
696 | # Actual output from router | |
701a0192 | 697 | actual = ( |
698 | net["r%s" % i] | |
699 | .cmd('vtysh -c "show ip ospf interface" 2> /dev/null') | |
700 | .rstrip() | |
701 | ) | |
4501fbca MW |
702 | # Mask out Bandwidth portion. They may change.. |
703 | actual = re.sub(r"BW [0-9]+ Mbit", "BW XX Mbit", actual) | |
11761ab0 | 704 | actual = re.sub(r"ifindex [0-9]", "ifindex X", actual) |
c9d72a0b | 705 | |
701a0192 | 706 | # Drop time in next due |
4501fbca | 707 | actual = re.sub(r"Hello due in [0-9\.]+s", "Hello due in XX.XXXs", actual) |
701a0192 | 708 | actual = re.sub( |
709 | r"Hello due in [0-9\.]+ usecs", "Hello due in XX.XXXs", actual | |
710 | ) | |
985e6d50 | 711 | # Fix 'MTU mismatch detection: enabled' vs 'MTU mismatch detection:enabled' - accept both |
701a0192 | 712 | actual = re.sub( |
713 | r"MTU mismatch detection:([a-z]+.*)", | |
714 | r"MTU mismatch detection: \1", | |
715 | actual, | |
716 | ) | |
4501fbca | 717 | # Fix newlines (make them all the same) |
701a0192 | 718 | actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) |
4501fbca MW |
719 | |
720 | # Generate Diff | |
701a0192 | 721 | diff = topotest.get_textdiff( |
722 | actual, | |
723 | expected, | |
17070436 | 724 | title1="actual SHOW IP OSPF INTERFACE", |
701a0192 | 725 | title2="expected SHOW IP OSPF INTERFACE", |
726 | ) | |
4501fbca MW |
727 | |
728 | # Empty string if it matches, otherwise diff contains unified diff | |
729 | if diff: | |
701a0192 | 730 | sys.stderr.write( |
731 | "r%s failed SHOW IP OSPF INTERFACE check:\n%s\n" % (i, diff) | |
732 | ) | |
4501fbca MW |
733 | failures += 1 |
734 | else: | |
735 | print("r%s ok" % i) | |
736 | ||
08fa1af7 | 737 | # Ignoring the issue if told to ignore (ie not yet fixed) |
701a0192 | 738 | if failures != 0: |
739 | if os.environ.get("bamboo_TOPOTESTS_ISSUE_348") == "IGNORE": | |
740 | sys.stderr.write( | |
741 | "Known issue - IGNORING. See https://github.com/FRRouting/frr/issues/348\n" | |
742 | ) | |
743 | pytest.skip( | |
744 | "Known issue - IGNORING. See https://github.com/FRRouting/frr/issues/348" | |
745 | ) | |
746 | ||
747 | assert ( | |
748 | failures == 0 | |
749 | ), "SHOW IP OSPF INTERFACE failed for router r%s:\n%s" % (i, diff) | |
4501fbca | 750 | |
7e7fc73b MW |
751 | # Make sure that all daemons are running |
752 | for i in range(1, 2): | |
701a0192 | 753 | fatal_error = net["r%s" % i].checkRouterRunning() |
7e7fc73b MW |
754 | assert fatal_error == "", fatal_error |
755 | ||
622c4996 | 756 | # For debugging after starting FRR daemons, uncomment the next line |
4501fbca MW |
757 | # CLI(net) |
758 | ||
759 | ||
760 | def test_isis_interfaces(): | |
761 | global fatal_error | |
762 | global net | |
763 | ||
764 | # Skip if previous fatal error condition is raised | |
701a0192 | 765 | if fatal_error != "": |
4501fbca MW |
766 | pytest.skip(fatal_error) |
767 | ||
768 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
769 | ||
b2764f90 | 770 | print("\n\n** Verifying ISIS interfaces") |
4501fbca MW |
771 | print("******************************************\n") |
772 | failures = 0 | |
773 | for i in range(1, 2): | |
701a0192 | 774 | refTableFile = "%s/r%s/show_isis_interface_detail.ref" % (thisDir, i) |
4501fbca MW |
775 | if os.path.isfile(refTableFile): |
776 | # Read expected result from file | |
777 | expected = open(refTableFile).read().rstrip() | |
778 | # Fix newlines (make them all the same) | |
701a0192 | 779 | expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1) |
4501fbca MW |
780 | |
781 | # Actual output from router | |
701a0192 | 782 | actual = ( |
783 | net["r%s" % i] | |
784 | .cmd('vtysh -c "show isis interface detail" 2> /dev/null') | |
785 | .rstrip() | |
786 | ) | |
4501fbca MW |
787 | # Mask out Link-Local mac address portion. They are random... |
788 | actual = re.sub(r"fe80::[0-9a-f:]+", "fe80::XXXX:XXXX:XXXX:XXXX", actual) | |
789 | # Mask out SNPA mac address portion. They are random... | |
790 | actual = re.sub(r"SNPA: [0-9a-f\.]+", "SNPA: XXXX.XXXX.XXXX", actual) | |
6ae351e8 | 791 | # Mask out Circuit ID number |
701a0192 | 792 | actual = re.sub(r"Circuit Id: 0x[0-9a-f]+", "Circuit Id: 0xXX", actual) |
4501fbca | 793 | # Fix newlines (make them all the same) |
701a0192 | 794 | actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) |
4501fbca MW |
795 | |
796 | # Generate Diff | |
701a0192 | 797 | diff = topotest.get_textdiff( |
798 | actual, | |
799 | expected, | |
17070436 | 800 | title1="actual SHOW ISIS INTERFACE DETAIL", |
701a0192 | 801 | title2="expected SHOW ISIS OSPF6 INTERFACE DETAIL", |
802 | ) | |
4501fbca MW |
803 | |
804 | # Empty string if it matches, otherwise diff contains unified diff | |
805 | if diff: | |
701a0192 | 806 | sys.stderr.write( |
807 | "r%s failed SHOW ISIS INTERFACE DETAIL check:\n%s\n" % (i, diff) | |
808 | ) | |
4501fbca MW |
809 | failures += 1 |
810 | else: | |
811 | print("r%s ok" % i) | |
812 | ||
701a0192 | 813 | assert ( |
814 | failures == 0 | |
815 | ), "SHOW ISIS INTERFACE DETAIL failed for router r%s:\n%s" % (i, diff) | |
4501fbca | 816 | |
7e7fc73b MW |
817 | # Make sure that all daemons are running |
818 | for i in range(1, 2): | |
701a0192 | 819 | fatal_error = net["r%s" % i].checkRouterRunning() |
7e7fc73b MW |
820 | assert fatal_error == "", fatal_error |
821 | ||
622c4996 | 822 | # For debugging after starting FRR daemons, uncomment the next line |
4501fbca MW |
823 | # CLI(net) |
824 | ||
825 | ||
826 | def test_bgp_summary(): | |
827 | global fatal_error | |
828 | global net | |
829 | ||
830 | # Skip if previous fatal error condition is raised | |
701a0192 | 831 | if fatal_error != "": |
4501fbca MW |
832 | pytest.skip(fatal_error) |
833 | ||
834 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
835 | ||
b2764f90 | 836 | print("\n\n** Verifying BGP Summary") |
4501fbca MW |
837 | print("******************************************\n") |
838 | failures = 0 | |
839 | for i in range(1, 2): | |
701a0192 | 840 | refTableFile = "%s/r%s/show_ip_bgp_summary.ref" % (thisDir, i) |
4501fbca MW |
841 | if os.path.isfile(refTableFile): |
842 | # Read expected result from file | |
843 | expected = open(refTableFile).read().rstrip() | |
844 | # Fix newlines (make them all the same) | |
701a0192 | 845 | expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1) |
4501fbca MW |
846 | |
847 | # Actual output from router | |
701a0192 | 848 | actual = ( |
849 | net["r%s" % i] | |
850 | .cmd('vtysh -c "show ip bgp summary" 2> /dev/null') | |
851 | .rstrip() | |
852 | ) | |
4501fbca MW |
853 | # Mask out "using XXiXX bytes" portion. They are random... |
854 | actual = re.sub(r"using [0-9]+ bytes", "using XXXX bytes", actual) | |
855 | # Mask out "using XiXXX KiB" portion. They are random... | |
856 | actual = re.sub(r"using [0-9]+ KiB", "using XXXX KiB", actual) | |
08fa1af7 MW |
857 | # |
858 | # Remove extra summaries which exist with newer versions | |
859 | # | |
860 | # Remove summary lines (changed recently) | |
701a0192 | 861 | actual = re.sub(r"Total number.*", "", actual) |
862 | actual = re.sub(r"Displayed.*", "", actual) | |
08fa1af7 | 863 | # Remove IPv4 Unicast Summary (Title only) |
701a0192 | 864 | actual = re.sub(r"IPv4 Unicast Summary:", "", actual) |
08fa1af7 | 865 | # Remove IPv4 Multicast Summary (all of it) |
701a0192 | 866 | actual = re.sub(r"IPv4 Multicast Summary:", "", actual) |
867 | actual = re.sub(r"No IPv4 Multicast neighbor is configured", "", actual) | |
08fa1af7 | 868 | # Remove IPv4 VPN Summary (all of it) |
701a0192 | 869 | actual = re.sub(r"IPv4 VPN Summary:", "", actual) |
870 | actual = re.sub(r"No IPv4 VPN neighbor is configured", "", actual) | |
08fa1af7 | 871 | # Remove IPv4 Encap Summary (all of it) |
701a0192 | 872 | actual = re.sub(r"IPv4 Encap Summary:", "", actual) |
873 | actual = re.sub(r"No IPv4 Encap neighbor is configured", "", actual) | |
08fa1af7 | 874 | # Remove Unknown Summary (all of it) |
701a0192 | 875 | actual = re.sub(r"Unknown Summary:", "", actual) |
876 | actual = re.sub(r"No Unknown neighbor is configured", "", actual) | |
8b2e59e9 | 877 | |
701a0192 | 878 | actual = re.sub(r"IPv4 labeled-unicast Summary:", "", actual) |
879 | actual = re.sub( | |
880 | r"No IPv4 labeled-unicast neighbor is configured", "", actual | |
881 | ) | |
8b2e59e9 | 882 | |
08fa1af7 MW |
883 | # Strip empty lines |
884 | actual = actual.lstrip() | |
885 | actual = actual.rstrip() | |
886 | # | |
4501fbca | 887 | # Fix newlines (make them all the same) |
701a0192 | 888 | actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) |
4501fbca MW |
889 | |
890 | # Generate Diff | |
701a0192 | 891 | diff = topotest.get_textdiff( |
892 | actual, | |
893 | expected, | |
17070436 | 894 | title1="actual SHOW IP BGP SUMMARY", |
701a0192 | 895 | title2="expected SHOW IP BGP SUMMARY", |
896 | ) | |
4501fbca MW |
897 | |
898 | # Empty string if it matches, otherwise diff contains unified diff | |
899 | if diff: | |
701a0192 | 900 | sys.stderr.write( |
901 | "r%s failed SHOW IP BGP SUMMARY check:\n%s\n" % (i, diff) | |
902 | ) | |
4501fbca MW |
903 | failures += 1 |
904 | else: | |
905 | print("r%s ok" % i) | |
906 | ||
701a0192 | 907 | assert failures == 0, "SHOW IP BGP SUMMARY failed for router r%s:\n%s" % ( |
908 | i, | |
909 | diff, | |
910 | ) | |
4501fbca | 911 | |
7e7fc73b MW |
912 | # Make sure that all daemons are running |
913 | for i in range(1, 2): | |
701a0192 | 914 | fatal_error = net["r%s" % i].checkRouterRunning() |
7e7fc73b MW |
915 | assert fatal_error == "", fatal_error |
916 | ||
622c4996 | 917 | # For debugging after starting FRR daemons, uncomment the next line |
4501fbca MW |
918 | # CLI(net) |
919 | ||
920 | ||
921 | def test_bgp_ipv6_summary(): | |
922 | global fatal_error | |
923 | global net | |
924 | ||
925 | # Skip if previous fatal error condition is raised | |
701a0192 | 926 | if fatal_error != "": |
4501fbca MW |
927 | pytest.skip(fatal_error) |
928 | ||
929 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
930 | ||
b2764f90 | 931 | print("\n\n** Verifying BGP IPv6 Summary") |
4501fbca MW |
932 | print("******************************************\n") |
933 | failures = 0 | |
934 | for i in range(1, 2): | |
701a0192 | 935 | refTableFile = "%s/r%s/show_bgp_ipv6_summary.ref" % (thisDir, i) |
4501fbca MW |
936 | if os.path.isfile(refTableFile): |
937 | # Read expected result from file | |
938 | expected = open(refTableFile).read().rstrip() | |
939 | # Fix newlines (make them all the same) | |
701a0192 | 940 | expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1) |
4501fbca MW |
941 | |
942 | # Actual output from router | |
701a0192 | 943 | actual = ( |
944 | net["r%s" % i] | |
945 | .cmd('vtysh -c "show bgp ipv6 summary" 2> /dev/null') | |
946 | .rstrip() | |
947 | ) | |
4501fbca MW |
948 | # Mask out "using XXiXX bytes" portion. They are random... |
949 | actual = re.sub(r"using [0-9]+ bytes", "using XXXX bytes", actual) | |
950 | # Mask out "using XiXXX KiB" portion. They are random... | |
951 | actual = re.sub(r"using [0-9]+ KiB", "using XXXX KiB", actual) | |
08fa1af7 MW |
952 | # |
953 | # Remove extra summaries which exist with newer versions | |
954 | # | |
955 | # Remove summary lines (changed recently) | |
701a0192 | 956 | actual = re.sub(r"Total number.*", "", actual) |
957 | actual = re.sub(r"Displayed.*", "", actual) | |
08fa1af7 | 958 | # Remove IPv4 Unicast Summary (Title only) |
701a0192 | 959 | actual = re.sub(r"IPv6 Unicast Summary:", "", actual) |
08fa1af7 | 960 | # Remove IPv4 Multicast Summary (all of it) |
701a0192 | 961 | actual = re.sub(r"IPv6 Multicast Summary:", "", actual) |
962 | actual = re.sub(r"No IPv6 Multicast neighbor is configured", "", actual) | |
08fa1af7 | 963 | # Remove IPv4 VPN Summary (all of it) |
701a0192 | 964 | actual = re.sub(r"IPv6 VPN Summary:", "", actual) |
965 | actual = re.sub(r"No IPv6 VPN neighbor is configured", "", actual) | |
08fa1af7 | 966 | # Remove IPv4 Encap Summary (all of it) |
701a0192 | 967 | actual = re.sub(r"IPv6 Encap Summary:", "", actual) |
968 | actual = re.sub(r"No IPv6 Encap neighbor is configured", "", actual) | |
08fa1af7 | 969 | # Remove Unknown Summary (all of it) |
701a0192 | 970 | actual = re.sub(r"Unknown Summary:", "", actual) |
971 | actual = re.sub(r"No Unknown neighbor is configured", "", actual) | |
8b2e59e9 DS |
972 | |
973 | # Remove Labeled Unicast Summary (all of it) | |
701a0192 | 974 | actual = re.sub(r"IPv6 labeled-unicast Summary:", "", actual) |
975 | actual = re.sub( | |
976 | r"No IPv6 labeled-unicast neighbor is configured", "", actual | |
977 | ) | |
8b2e59e9 | 978 | |
08fa1af7 MW |
979 | # Strip empty lines |
980 | actual = actual.lstrip() | |
981 | actual = actual.rstrip() | |
982 | # | |
4501fbca | 983 | # Fix newlines (make them all the same) |
701a0192 | 984 | actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) |
4501fbca MW |
985 | |
986 | # Generate Diff | |
701a0192 | 987 | diff = topotest.get_textdiff( |
988 | actual, | |
989 | expected, | |
17070436 | 990 | title1="actual SHOW BGP IPv6 SUMMARY", |
701a0192 | 991 | title2="expected SHOW BGP IPv6 SUMMARY", |
992 | ) | |
4501fbca MW |
993 | |
994 | # Empty string if it matches, otherwise diff contains unified diff | |
995 | if diff: | |
701a0192 | 996 | sys.stderr.write( |
997 | "r%s failed SHOW BGP IPv6 SUMMARY check:\n%s\n" % (i, diff) | |
998 | ) | |
4501fbca MW |
999 | failures += 1 |
1000 | else: | |
1001 | print("r%s ok" % i) | |
1002 | ||
701a0192 | 1003 | assert failures == 0, "SHOW BGP IPv6 SUMMARY failed for router r%s:\n%s" % ( |
1004 | i, | |
1005 | diff, | |
1006 | ) | |
4501fbca | 1007 | |
7e7fc73b MW |
1008 | # Make sure that all daemons are running |
1009 | for i in range(1, 2): | |
701a0192 | 1010 | fatal_error = net["r%s" % i].checkRouterRunning() |
7e7fc73b MW |
1011 | assert fatal_error == "", fatal_error |
1012 | ||
622c4996 | 1013 | # For debugging after starting FRR daemons, uncomment the next line |
4501fbca MW |
1014 | # CLI(net) |
1015 | ||
1016 | ||
1017 | def test_bgp_ipv4(): | |
1018 | global fatal_error | |
1019 | global net | |
1020 | ||
1021 | # Skip if previous fatal error condition is raised | |
701a0192 | 1022 | if fatal_error != "": |
4501fbca MW |
1023 | pytest.skip(fatal_error) |
1024 | ||
1025 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
1026 | ||
b2764f90 | 1027 | print("\n\n** Verifying BGP IPv4") |
4501fbca | 1028 | print("******************************************\n") |
6a57e103 | 1029 | diffresult = {} |
4501fbca | 1030 | for i in range(1, 2): |
11761ab0 | 1031 | success = 0 |
701a0192 | 1032 | for refTableFile in glob.glob("%s/r%s/show_bgp_ipv4*.ref" % (thisDir, i)): |
11761ab0 MS |
1033 | if os.path.isfile(refTableFile): |
1034 | # Read expected result from file | |
1035 | expected = open(refTableFile).read().rstrip() | |
1036 | # Fix newlines (make them all the same) | |
701a0192 | 1037 | expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1) |
11761ab0 MS |
1038 | |
1039 | # Actual output from router | |
701a0192 | 1040 | actual = ( |
1041 | net["r%s" % i].cmd('vtysh -c "show bgp ipv4" 2> /dev/null').rstrip() | |
1042 | ) | |
11761ab0 | 1043 | # Remove summary line (changed recently) |
701a0192 | 1044 | actual = re.sub(r"Total number.*", "", actual) |
1045 | actual = re.sub(r"Displayed.*", "", actual) | |
11761ab0 MS |
1046 | actual = actual.rstrip() |
1047 | # Fix newlines (make them all the same) | |
701a0192 | 1048 | actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) |
11761ab0 MS |
1049 | |
1050 | # Generate Diff | |
701a0192 | 1051 | diff = topotest.get_textdiff( |
1052 | actual, | |
1053 | expected, | |
11761ab0 | 1054 | title1="actual SHOW BGP IPv4", |
701a0192 | 1055 | title2="expected SHOW BGP IPv4", |
1056 | ) | |
11761ab0 MS |
1057 | |
1058 | # Empty string if it matches, otherwise diff contains unified diff | |
1059 | if diff: | |
1060 | diffresult[refTableFile] = diff | |
1061 | else: | |
1062 | success = 1 | |
1063 | print("template %s matched: r%s ok" % (refTableFile, i)) | |
1064 | break | |
1065 | ||
1066 | if not success: | |
701a0192 | 1067 | resultstr = "No template matched.\n" |
11761ab0 | 1068 | for f in diffresult.iterkeys(): |
701a0192 | 1069 | resultstr += "template %s: r%s failed SHOW BGP IPv4 check:\n%s\n" % ( |
1070 | f, | |
1071 | i, | |
1072 | diffresult[f], | |
1073 | ) | |
11761ab0 | 1074 | raise AssertionError( |
701a0192 | 1075 | "SHOW BGP IPv4 failed for router r%s:\n%s" % (i, resultstr) |
1076 | ) | |
4501fbca | 1077 | |
7e7fc73b MW |
1078 | # Make sure that all daemons are running |
1079 | for i in range(1, 2): | |
701a0192 | 1080 | fatal_error = net["r%s" % i].checkRouterRunning() |
7e7fc73b MW |
1081 | assert fatal_error == "", fatal_error |
1082 | ||
622c4996 | 1083 | # For debugging after starting FRR daemons, uncomment the next line |
4501fbca MW |
1084 | # CLI(net) |
1085 | ||
1086 | ||
1087 | def test_bgp_ipv6(): | |
1088 | global fatal_error | |
1089 | global net | |
1090 | ||
1091 | # Skip if previous fatal error condition is raised | |
701a0192 | 1092 | if fatal_error != "": |
4501fbca MW |
1093 | pytest.skip(fatal_error) |
1094 | ||
1095 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
1096 | ||
b2764f90 | 1097 | print("\n\n** Verifying BGP IPv6") |
4501fbca | 1098 | print("******************************************\n") |
6a57e103 | 1099 | diffresult = {} |
4501fbca | 1100 | for i in range(1, 2): |
11761ab0 | 1101 | success = 0 |
701a0192 | 1102 | for refTableFile in glob.glob("%s/r%s/show_bgp_ipv6*.ref" % (thisDir, i)): |
11761ab0 MS |
1103 | if os.path.isfile(refTableFile): |
1104 | # Read expected result from file | |
1105 | expected = open(refTableFile).read().rstrip() | |
1106 | # Fix newlines (make them all the same) | |
701a0192 | 1107 | expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1) |
11761ab0 MS |
1108 | |
1109 | # Actual output from router | |
701a0192 | 1110 | actual = ( |
1111 | net["r%s" % i].cmd('vtysh -c "show bgp ipv6" 2> /dev/null').rstrip() | |
1112 | ) | |
11761ab0 | 1113 | # Remove summary line (changed recently) |
701a0192 | 1114 | actual = re.sub(r"Total number.*", "", actual) |
1115 | actual = re.sub(r"Displayed.*", "", actual) | |
11761ab0 MS |
1116 | actual = actual.rstrip() |
1117 | # Fix newlines (make them all the same) | |
701a0192 | 1118 | actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) |
11761ab0 MS |
1119 | |
1120 | # Generate Diff | |
701a0192 | 1121 | diff = topotest.get_textdiff( |
1122 | actual, | |
1123 | expected, | |
11761ab0 | 1124 | title1="actual SHOW BGP IPv6", |
701a0192 | 1125 | title2="expected SHOW BGP IPv6", |
1126 | ) | |
11761ab0 MS |
1127 | |
1128 | # Empty string if it matches, otherwise diff contains unified diff | |
1129 | if diff: | |
1130 | diffresult[refTableFile] = diff | |
1131 | else: | |
1132 | success = 1 | |
1133 | print("template %s matched: r%s ok" % (refTableFile, i)) | |
1134 | ||
1135 | if not success: | |
701a0192 | 1136 | resultstr = "No template matched.\n" |
11761ab0 | 1137 | for f in diffresult.iterkeys(): |
701a0192 | 1138 | resultstr += "template %s: r%s failed SHOW BGP IPv6 check:\n%s\n" % ( |
1139 | f, | |
1140 | i, | |
1141 | diffresult[f], | |
1142 | ) | |
11761ab0 | 1143 | raise AssertionError( |
701a0192 | 1144 | "SHOW BGP IPv6 failed for router r%s:\n%s" % (i, resultstr) |
1145 | ) | |
4501fbca | 1146 | |
7e7fc73b MW |
1147 | # Make sure that all daemons are running |
1148 | for i in range(1, 2): | |
701a0192 | 1149 | fatal_error = net["r%s" % i].checkRouterRunning() |
7e7fc73b MW |
1150 | assert fatal_error == "", fatal_error |
1151 | ||
622c4996 | 1152 | # For debugging after starting FRR daemons, uncomment the next line |
4501fbca MW |
1153 | # CLI(net) |
1154 | ||
701a0192 | 1155 | |
41fce07c DS |
1156 | def test_route_map(): |
1157 | global fatal_error | |
1158 | global net | |
1159 | ||
701a0192 | 1160 | if fatal_error != "": |
41fce07c DS |
1161 | pytest.skip(fatal_error) |
1162 | ||
1163 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
1164 | ||
1165 | print("\n\n** Verifying some basic routemap forward references\n") | |
1166 | print("*******************************************************\n") | |
1167 | failures = 0 | |
1168 | for i in range(1, 2): | |
701a0192 | 1169 | refroutemap = "%s/r%s/show_route_map.ref" % (thisDir, i) |
41fce07c DS |
1170 | if os.path.isfile(refroutemap): |
1171 | expected = open(refroutemap).read().rstrip() | |
701a0192 | 1172 | expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1) |
41fce07c | 1173 | |
701a0192 | 1174 | actual = ( |
1175 | net["r%s" % i].cmd('vtysh -c "show route-map" 2> /dev/null').rstrip() | |
1176 | ) | |
1177 | actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) | |
41fce07c | 1178 | |
701a0192 | 1179 | diff = topotest.get_textdiff( |
1180 | actual, | |
1181 | expected, | |
1182 | title1="actual show route-map", | |
1183 | title2="expected show route-map", | |
1184 | ) | |
41fce07c DS |
1185 | |
1186 | if diff: | |
701a0192 | 1187 | sys.stderr.write( |
1188 | "r%s failed show route-map command Check:\n%s\n" % (i, diff) | |
1189 | ) | |
41fce07c DS |
1190 | failures += 1 |
1191 | else: | |
701a0192 | 1192 | print("r%s ok" % i) |
1193 | ||
1194 | assert ( | |
1195 | failures == 0 | |
1196 | ), "Show route-map command failed for router r%s:\n%s" % (i, diff) | |
4501fbca MW |
1197 | |
1198 | ||
887a232c SW |
1199 | def test_nexthop_groups_with_route_maps(): |
1200 | global fatal_error | |
1201 | global net | |
1202 | ||
1203 | # Skip if previous fatal error condition is raised | |
701a0192 | 1204 | if fatal_error != "": |
887a232c SW |
1205 | pytest.skip(fatal_error) |
1206 | ||
1207 | print("\n\n** Verifying Nexthop Groups With Route-Maps") | |
1208 | print("******************************************\n") | |
1209 | ||
1210 | ### Nexthop Group With Route-Map Tests | |
1211 | ||
1212 | # Create a lib nexthop-group | |
701a0192 | 1213 | net["r1"].cmd( |
1214 | 'vtysh -c "c t" -c "nexthop-group test" -c "nexthop 1.1.1.1" -c "nexthop 1.1.1.2"' | |
1215 | ) | |
887a232c SW |
1216 | |
1217 | ## Route-Map Proto Source | |
1218 | ||
1219 | route_str = "2.2.2.1" | |
1220 | src_str = "192.168.0.1" | |
1221 | ||
701a0192 | 1222 | net["r1"].cmd( |
1223 | 'vtysh -c "c t" -c "route-map NH-SRC permit 111" -c "set src %s"' % src_str | |
1224 | ) | |
887a232c SW |
1225 | net["r1"].cmd('vtysh -c "c t" -c "ip protocol sharp route-map NH-SRC"') |
1226 | ||
1227 | net["r1"].cmd('vtysh -c "sharp install routes %s nexthop-group test 1"' % route_str) | |
1228 | ||
1229 | verify_route_nexthop_group("%s/32" % route_str) | |
1230 | ||
1231 | # Only a valid test on linux using nexthop objects | |
1232 | if sys.platform.startswith("linux"): | |
701a0192 | 1233 | output = net["r1"].cmd("ip route show %s/32" % route_str) |
887a232c | 1234 | match = re.search(r"src %s" % src_str, output) |
701a0192 | 1235 | assert match is not None, "Route %s/32 not installed with src %s" % ( |
1236 | route_str, | |
1237 | src_str, | |
1238 | ) | |
887a232c SW |
1239 | |
1240 | # Remove NHG routes and route-map | |
1241 | net["r1"].cmd('vtysh -c "sharp remove routes %s 1"' % route_str) | |
1242 | net["r1"].cmd('vtysh -c "c t" -c "no ip protocol sharp route-map NH-SRC"') | |
701a0192 | 1243 | net["r1"].cmd( |
1244 | 'vtysh -c "c t" -c "no route-map NH-SRC permit 111" -c "set src %s"' % src_str | |
1245 | ) | |
887a232c SW |
1246 | net["r1"].cmd('vtysh -c "c t" -c "no route-map NH-SRC"') |
1247 | ||
1248 | ## Route-Map Deny/Permit with same nexthop group | |
1249 | ||
1250 | permit_route_str = "3.3.3.1" | |
1251 | deny_route_str = "3.3.3.2" | |
1252 | ||
701a0192 | 1253 | net["r1"].cmd( |
1254 | 'vtysh -c "c t" -c "ip prefix-list NOPE seq 5 permit %s/32"' % permit_route_str | |
1255 | ) | |
1256 | net["r1"].cmd( | |
1257 | 'vtysh -c "c t" -c "route-map NOPE permit 111" -c "match ip address prefix-list NOPE"' | |
1258 | ) | |
887a232c SW |
1259 | net["r1"].cmd('vtysh -c "c t" -c "route-map NOPE deny 222"') |
1260 | net["r1"].cmd('vtysh -c "c t" -c "ip protocol sharp route-map NOPE"') | |
1261 | ||
1262 | # This route should be permitted | |
701a0192 | 1263 | net["r1"].cmd( |
1264 | 'vtysh -c "sharp install routes %s nexthop-group test 1"' % permit_route_str | |
1265 | ) | |
887a232c SW |
1266 | |
1267 | verify_route_nexthop_group("%s/32" % permit_route_str) | |
1268 | ||
1269 | # This route should be denied | |
701a0192 | 1270 | net["r1"].cmd( |
1271 | 'vtysh -c "sharp install routes %s nexthop-group test 1"' % deny_route_str | |
1272 | ) | |
887a232c SW |
1273 | |
1274 | nhg_id = route_get_nhg_id(deny_route_str) | |
1275 | output = net["r1"].cmd('vtysh -c "show nexthop-group rib %d"' % nhg_id) | |
1276 | ||
1277 | match = re.search(r"Valid", output) | |
1278 | assert match is None, "Nexthop Group ID=%d should not be marked Valid" % nhg_id | |
1279 | ||
1280 | match = re.search(r"Installed", output) | |
1281 | assert match is None, "Nexthop Group ID=%d should not be marked Installed" % nhg_id | |
1282 | ||
1283 | # Remove NHG routes and route-map | |
1284 | net["r1"].cmd('vtysh -c "sharp remove routes %s 1"' % permit_route_str) | |
1285 | net["r1"].cmd('vtysh -c "sharp remove routes %s 1"' % deny_route_str) | |
1286 | net["r1"].cmd('vtysh -c "c t" -c "no ip protocol sharp route-map NOPE"') | |
1287 | net["r1"].cmd('vtysh -c "c t" -c "no route-map NOPE permit 111"') | |
1288 | net["r1"].cmd('vtysh -c "c t" -c "no route-map NOPE deny 222"') | |
1289 | net["r1"].cmd('vtysh -c "c t" -c "no route-map NOPE"') | |
701a0192 | 1290 | net["r1"].cmd( |
1291 | 'vtysh -c "c t" -c "no ip prefix-list NOPE seq 5 permit %s/32"' | |
1292 | % permit_route_str | |
1293 | ) | |
1294 | ||
887a232c | 1295 | |
8f4d7212 SW |
1296 | def test_nexthop_group_replace(): |
1297 | global fatal_error | |
1298 | global net | |
1299 | ||
1300 | # Skip if previous fatal error condition is raised | |
701a0192 | 1301 | if fatal_error != "": |
8f4d7212 SW |
1302 | pytest.skip(fatal_error) |
1303 | ||
1304 | print("\n\n** Verifying Nexthop Groups") | |
1305 | print("******************************************\n") | |
1306 | ||
1307 | ### Nexthop Group Tests | |
1308 | ||
1309 | ## 2-Way ECMP Directly Connected | |
1310 | ||
701a0192 | 1311 | net["r1"].cmd( |
1312 | 'vtysh -c "c t" -c "nexthop-group replace" -c "nexthop 1.1.1.1 r1-eth1 onlink" -c "nexthop 1.1.1.2 r1-eth2 onlink"' | |
1313 | ) | |
8f4d7212 SW |
1314 | |
1315 | # Create with sharpd using nexthop-group | |
1316 | net["r1"].cmd('vtysh -c "sharp install routes 3.3.3.1 nexthop-group replace 1"') | |
1317 | ||
1318 | verify_route_nexthop_group("3.3.3.1/32") | |
1319 | ||
1320 | # Change the nexthop group | |
701a0192 | 1321 | net["r1"].cmd( |
1322 | 'vtysh -c "c t" -c "nexthop-group replace" -c "no nexthop 1.1.1.1 r1-eth1 onlink" -c "nexthop 1.1.1.3 r1-eth1 onlink" -c "nexthop 1.1.1.4 r1-eth4 onlink"' | |
1323 | ) | |
8f4d7212 SW |
1324 | |
1325 | # Verify it updated. We can just check install and ecmp count here. | |
1326 | verify_route_nexthop_group("3.3.3.1/32", False, 3) | |
1327 | ||
701a0192 | 1328 | |
4501fbca MW |
1329 | def test_mpls_interfaces(): |
1330 | global fatal_error | |
1331 | global net | |
1332 | ||
1333 | # Skip if previous fatal error condition is raised | |
701a0192 | 1334 | if fatal_error != "": |
4501fbca MW |
1335 | pytest.skip(fatal_error) |
1336 | ||
1337 | # Skip if no LDP installed or old kernel | |
701a0192 | 1338 | if net["r1"].daemon_available("ldpd") == False: |
4501fbca MW |
1339 | pytest.skip("No MPLS or kernel < 4.5") |
1340 | ||
1341 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
1342 | ||
b2764f90 | 1343 | print("\n\n** Verifying MPLS Interfaces") |
4501fbca MW |
1344 | print("******************************************\n") |
1345 | failures = 0 | |
1346 | for i in range(1, 2): | |
701a0192 | 1347 | refTableFile = "%s/r%s/show_mpls_ldp_interface.ref" % (thisDir, i) |
4501fbca MW |
1348 | if os.path.isfile(refTableFile): |
1349 | # Read expected result from file | |
1350 | expected = open(refTableFile).read().rstrip() | |
1351 | # Fix newlines (make them all the same) | |
701a0192 | 1352 | expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1) |
4501fbca MW |
1353 | |
1354 | # Actual output from router | |
701a0192 | 1355 | actual = ( |
1356 | net["r%s" % i] | |
1357 | .cmd('vtysh -c "show mpls ldp interface" 2> /dev/null') | |
1358 | .rstrip() | |
1359 | ) | |
4501fbca MW |
1360 | # Mask out Timer in Uptime |
1361 | actual = re.sub(r" [0-9][0-9]:[0-9][0-9]:[0-9][0-9] ", " xx:xx:xx ", actual) | |
1362 | # Fix newlines (make them all the same) | |
701a0192 | 1363 | actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) |
4501fbca MW |
1364 | |
1365 | # Generate Diff | |
701a0192 | 1366 | diff = topotest.get_textdiff( |
1367 | actual, | |
1368 | expected, | |
17070436 | 1369 | title1="actual MPLS LDP interface status", |
701a0192 | 1370 | title2="expected MPLS LDP interface status", |
1371 | ) | |
4501fbca MW |
1372 | |
1373 | # Empty string if it matches, otherwise diff contains unified diff | |
1374 | if diff: | |
701a0192 | 1375 | sys.stderr.write( |
1376 | "r%s failed MPLS LDP Interface status Check:\n%s\n" % (i, diff) | |
1377 | ) | |
4501fbca MW |
1378 | failures += 1 |
1379 | else: | |
1380 | print("r%s ok" % i) | |
1381 | ||
701a0192 | 1382 | if failures > 0: |
4501fbca MW |
1383 | fatal_error = "MPLS LDP Interface status failed" |
1384 | ||
701a0192 | 1385 | assert ( |
1386 | failures == 0 | |
1387 | ), "MPLS LDP Interface status failed for router r%s:\n%s" % (i, diff) | |
4501fbca | 1388 | |
7e7fc73b MW |
1389 | # Make sure that all daemons are running |
1390 | for i in range(1, 2): | |
701a0192 | 1391 | fatal_error = net["r%s" % i].checkRouterRunning() |
7e7fc73b MW |
1392 | assert fatal_error == "", fatal_error |
1393 | ||
622c4996 | 1394 | # For debugging after starting FRR daemons, uncomment the next line |
4501fbca MW |
1395 | # CLI(net) |
1396 | ||
1397 | ||
1398 | def test_shutdown_check_stderr(): | |
1399 | global fatal_error | |
1400 | global net | |
1401 | ||
1402 | # Skip if previous fatal error condition is raised | |
701a0192 | 1403 | if fatal_error != "": |
4501fbca MW |
1404 | pytest.skip(fatal_error) |
1405 | ||
b2764f90 | 1406 | print("\n\n** Verifying unexpected STDERR output from daemons") |
4501fbca MW |
1407 | print("******************************************\n") |
1408 | ||
701a0192 | 1409 | if os.environ.get("TOPOTESTS_CHECK_STDERR") is None: |
1410 | print( | |
1411 | "SKIPPED final check on StdErr output: Disabled (TOPOTESTS_CHECK_STDERR undefined)\n" | |
1412 | ) | |
1413 | pytest.skip("Skipping test for Stderr output") | |
4501fbca MW |
1414 | |
1415 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
1416 | ||
50c40bde MW |
1417 | print("thisDir=" + thisDir) |
1418 | ||
701a0192 | 1419 | net["r1"].stopRouter() |
4501fbca | 1420 | |
701a0192 | 1421 | log = net["r1"].getStdErr("ripd") |
8e957dbb MW |
1422 | if log: |
1423 | print("\nRIPd StdErr Log:\n" + log) | |
701a0192 | 1424 | log = net["r1"].getStdErr("ripngd") |
8e957dbb MW |
1425 | if log: |
1426 | print("\nRIPngd StdErr Log:\n" + log) | |
701a0192 | 1427 | log = net["r1"].getStdErr("ospfd") |
8e957dbb MW |
1428 | if log: |
1429 | print("\nOSPFd StdErr Log:\n" + log) | |
701a0192 | 1430 | log = net["r1"].getStdErr("ospf6d") |
8e957dbb MW |
1431 | if log: |
1432 | print("\nOSPF6d StdErr Log:\n" + log) | |
701a0192 | 1433 | log = net["r1"].getStdErr("isisd") |
8e957dbb MW |
1434 | if log: |
1435 | print("\nISISd StdErr Log:\n" + log) | |
701a0192 | 1436 | log = net["r1"].getStdErr("bgpd") |
8e957dbb MW |
1437 | if log: |
1438 | print("\nBGPd StdErr Log:\n" + log) | |
af39fbe7 | 1439 | |
701a0192 | 1440 | log = net["r1"].getStdErr("nhrpd") |
af39fbe7 MS |
1441 | if log: |
1442 | print("\nNHRPd StdErr Log:\n" + log) | |
1443 | ||
701a0192 | 1444 | log = net["r1"].getStdErr("pbrd") |
af39fbe7 MS |
1445 | if log: |
1446 | print("\nPBRd StdErr Log:\n" + log) | |
1447 | ||
701a0192 | 1448 | log = net["r1"].getStdErr("babeld") |
af39fbe7 MS |
1449 | if log: |
1450 | print("\nBABELd StdErr Log:\n" + log) | |
1451 | ||
701a0192 | 1452 | if net["r1"].daemon_available("ldpd"): |
1453 | log = net["r1"].getStdErr("ldpd") | |
8e957dbb MW |
1454 | if log: |
1455 | print("\nLDPd StdErr Log:\n" + log) | |
701a0192 | 1456 | log = net["r1"].getStdErr("zebra") |
8e957dbb MW |
1457 | if log: |
1458 | print("\nZebra StdErr Log:\n" + log) | |
4501fbca MW |
1459 | |
1460 | ||
50c40bde MW |
1461 | def test_shutdown_check_memleak(): |
1462 | global fatal_error | |
1463 | global net | |
1464 | ||
1465 | # Skip if previous fatal error condition is raised | |
701a0192 | 1466 | if fatal_error != "": |
50c40bde MW |
1467 | pytest.skip(fatal_error) |
1468 | ||
701a0192 | 1469 | if os.environ.get("TOPOTESTS_CHECK_MEMLEAK") is None: |
1470 | print( | |
1471 | "SKIPPED final check on Memory leaks: Disabled (TOPOTESTS_CHECK_MEMLEAK undefined)\n" | |
1472 | ) | |
1473 | pytest.skip("Skipping test for memory leaks") | |
1474 | ||
50c40bde MW |
1475 | thisDir = os.path.dirname(os.path.realpath(__file__)) |
1476 | ||
1477 | for i in range(1, 2): | |
701a0192 | 1478 | net["r%s" % i].stopRouter() |
1479 | net["r%s" % i].report_memory_leaks( | |
1480 | os.environ.get("TOPOTESTS_CHECK_MEMLEAK"), os.path.basename(__file__) | |
1481 | ) | |
50c40bde MW |
1482 | |
1483 | ||
701a0192 | 1484 | if __name__ == "__main__": |
4501fbca | 1485 | |
701a0192 | 1486 | setLogLevel("info") |
4501fbca MW |
1487 | # To suppress tracebacks, either use the following pytest call or add "--tb=no" to cli |
1488 | # retval = pytest.main(["-s", "--tb=no"]) | |
1489 | retval = pytest.main(["-s"]) | |
1490 | sys.exit(retval) |