]>
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") |
960c3f25 MW |
272 | # NHRPD shows YANG model not embedded messages |
273 | # Ignore these | |
274 | log = re.sub(r".*YANG model.*not embedded.*", "", log).rstrip() | |
af39fbe7 MS |
275 | if log: |
276 | error_logs += "r%s NHRPd StdErr Output:\n" % i | |
277 | error_logs += log | |
278 | ||
701a0192 | 279 | log = net["r1"].getStdErr("babeld") |
af39fbe7 MS |
280 | if log: |
281 | error_logs += "r%s BABELd StdErr Output:\n" % i | |
282 | error_logs += log | |
283 | ||
701a0192 | 284 | log = net["r1"].getStdErr("pbrd") |
af39fbe7 MS |
285 | if log: |
286 | error_logs += "r%s PBRd StdErr Output:\n" % i | |
287 | error_logs += log | |
288 | ||
701a0192 | 289 | log = net["r%s" % i].getStdErr("zebra") |
4501fbca | 290 | if log: |
960c3f25 | 291 | error_logs += "r%s Zebra StdErr Output:\n" % i |
4501fbca MW |
292 | error_logs += log |
293 | ||
294 | if error_logs: | |
701a0192 | 295 | sys.stderr.write( |
296 | "Failed check for StdErr Output on daemons:\n%s\n" % error_logs | |
297 | ) | |
4501fbca | 298 | |
08fa1af7 | 299 | # Ignoring the issue if told to ignore (ie not yet fixed) |
701a0192 | 300 | if error_logs != "": |
301 | if os.environ.get("bamboo_TOPOTESTS_ISSUE_349") == "IGNORE": | |
302 | sys.stderr.write( | |
303 | "Known issue - IGNORING. See https://github.com/FRRouting/frr/issues/349\n" | |
304 | ) | |
305 | pytest.skip( | |
306 | "Known issue - IGNORING. See https://github.com/FRRouting/frr/issues/349" | |
307 | ) | |
08fa1af7 | 308 | |
4501fbca MW |
309 | assert error_logs == "", "Daemons report errors to StdErr" |
310 | ||
622c4996 | 311 | # For debugging after starting FRR daemons, uncomment the next line |
4501fbca MW |
312 | # CLI(net) |
313 | ||
314 | ||
315 | def test_converge_protocols(): | |
316 | global fatal_error | |
317 | global net | |
318 | ||
319 | # Skip if previous fatal error condition is raised | |
701a0192 | 320 | if fatal_error != "": |
4501fbca MW |
321 | pytest.skip(fatal_error) |
322 | ||
323 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
324 | ||
325 | print("\n\n** Waiting for protocols convergence") | |
326 | print("******************************************\n") | |
327 | ||
328 | # Not really implemented yet - just sleep 60 secs for now | |
329 | sleep(60) | |
330 | ||
7e7fc73b | 331 | # Make sure that all daemons are running |
556f76e1 | 332 | failures = 0 |
7e7fc73b | 333 | for i in range(1, 2): |
701a0192 | 334 | fatal_error = net["r%s" % i].checkRouterRunning() |
7e7fc73b MW |
335 | assert fatal_error == "", fatal_error |
336 | ||
701a0192 | 337 | print("Show that v4 routes are right\n") |
338 | v4_routesFile = "%s/r%s/ipv4_routes.ref" % (thisDir, i) | |
556f76e1 | 339 | expected = open(v4_routesFile).read().rstrip() |
701a0192 | 340 | expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1) |
341 | ||
342 | actual = ( | |
343 | net["r%s" % i] | |
344 | .cmd( | |
345 | 'vtysh -c "show ip route" | /usr/bin/tail -n +7 | env LC_ALL=en_US.UTF-8 sort 2> /dev/null' | |
346 | ) | |
347 | .rstrip() | |
348 | ) | |
556f76e1 DS |
349 | # Drop time in last update |
350 | actual = re.sub(r" [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", " XX:XX:XX", actual) | |
701a0192 | 351 | actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) |
352 | diff = topotest.get_textdiff( | |
353 | actual, | |
354 | expected, | |
355 | title1="Actual IP Routing Table", | |
356 | title2="Expected IP RoutingTable", | |
357 | ) | |
556f76e1 | 358 | if diff: |
701a0192 | 359 | sys.stderr.write("r%s failed IP Routing table check:\n%s\n" % (i, diff)) |
556f76e1 DS |
360 | failures += 1 |
361 | else: | |
701a0192 | 362 | print("r%s ok" % i) |
556f76e1 DS |
363 | |
364 | assert failures == 0, "IP Routing table failed for r%s\n%s" % (i, diff) | |
365 | ||
366 | failures = 0 | |
367 | ||
368 | print("Show that v6 routes are right\n") | |
701a0192 | 369 | v6_routesFile = "%s/r%s/ipv6_routes.ref" % (thisDir, i) |
556f76e1 | 370 | expected = open(v6_routesFile).read().rstrip() |
701a0192 | 371 | expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1) |
372 | ||
373 | actual = ( | |
374 | net["r%s" % i] | |
375 | .cmd( | |
376 | 'vtysh -c "show ipv6 route" | /usr/bin/tail -n +7 | env LC_ALL=en_US.UTF-8 sort 2> /dev/null' | |
377 | ) | |
378 | .rstrip() | |
379 | ) | |
556f76e1 DS |
380 | # Drop time in last update |
381 | actual = re.sub(r" [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", " XX:XX:XX", actual) | |
701a0192 | 382 | actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) |
383 | diff = topotest.get_textdiff( | |
384 | actual, | |
385 | expected, | |
386 | title1="Actual IPv6 Routing Table", | |
387 | title2="Expected IPv6 RoutingTable", | |
388 | ) | |
556f76e1 | 389 | if diff: |
701a0192 | 390 | sys.stderr.write("r%s failed IPv6 Routing table check:\n%s\n" % (i, diff)) |
556f76e1 DS |
391 | failures += 1 |
392 | else: | |
701a0192 | 393 | print("r%s ok" % i) |
556f76e1 DS |
394 | |
395 | assert failures == 0, "IPv6 Routing table failed for r%s\n%s" % (i, diff) | |
396 | ||
622c4996 | 397 | # For debugging after starting FRR daemons, uncomment the next line |
4501fbca MW |
398 | ## CLI(net) |
399 | ||
701a0192 | 400 | |
887a232c SW |
401 | def route_get_nhg_id(route_str): |
402 | output = net["r1"].cmd('vtysh -c "show ip route %s nexthop-group"' % route_str) | |
403 | match = re.search(r"Nexthop Group ID: (\d+)", output) | |
701a0192 | 404 | assert match is not None, ( |
405 | "Nexthop Group ID not found for sharpd route %s" % route_str | |
406 | ) | |
887a232c SW |
407 | |
408 | nhg_id = int(match.group(1)) | |
409 | return nhg_id | |
410 | ||
701a0192 | 411 | |
8f4d7212 | 412 | def verify_nexthop_group(nhg_id, recursive=False, ecmp=0): |
887a232c SW |
413 | # Verify NHG is valid/installed |
414 | output = net["r1"].cmd('vtysh -c "show nexthop-group rib %d"' % nhg_id) | |
415 | ||
416 | match = re.search(r"Valid", output) | |
417 | assert match is not None, "Nexthop Group ID=%d not marked Valid" % nhg_id | |
418 | ||
8f4d7212 SW |
419 | if ecmp or recursive: |
420 | match = re.search(r"Depends:.*\n", output) | |
421 | assert match is not None, "Nexthop Group ID=%d has no depends" % nhg_id | |
422 | ||
423 | # list of IDs in group | |
424 | depends = re.findall(r"\((\d+)\)", match.group(0)) | |
425 | ||
426 | if ecmp: | |
701a0192 | 427 | assert len(depends) == ecmp, ( |
428 | "Nexthop Group ID=%d doesn't match ecmp size" % nhg_id | |
429 | ) | |
8f4d7212 SW |
430 | else: |
431 | # If recursive, we need to look at its resolved group | |
701a0192 | 432 | assert len(depends) == 1, ( |
433 | "Nexthop Group ID=%d should only have one recursive depend" % nhg_id | |
434 | ) | |
8f4d7212 SW |
435 | resolved_id = int(depends[0]) |
436 | verify_nexthop_group(resolved_id, False) | |
437 | ||
887a232c SW |
438 | else: |
439 | match = re.search(r"Installed", output) | |
440 | assert match is not None, "Nexthop Group ID=%d not marked Installed" % nhg_id | |
441 | ||
701a0192 | 442 | |
8f4d7212 | 443 | def verify_route_nexthop_group(route_str, recursive=False, ecmp=0): |
887a232c SW |
444 | # Verify route and that zebra created NHGs for and they are valid/installed |
445 | nhg_id = route_get_nhg_id(route_str) | |
8f4d7212 | 446 | verify_nexthop_group(nhg_id, recursive, ecmp) |
887a232c | 447 | |
701a0192 | 448 | |
8058df22 SW |
449 | def test_nexthop_groups(): |
450 | global fatal_error | |
451 | global net | |
452 | ||
453 | # Skip if previous fatal error condition is raised | |
701a0192 | 454 | if fatal_error != "": |
8058df22 SW |
455 | pytest.skip(fatal_error) |
456 | ||
457 | print("\n\n** Verifying Nexthop Groups") | |
458 | print("******************************************\n") | |
459 | ||
887a232c SW |
460 | ### Nexthop Group Tests |
461 | ||
462 | ## Basic test | |
463 | ||
8058df22 | 464 | # Create a lib nexthop-group |
701a0192 | 465 | net["r1"].cmd( |
466 | 'vtysh -c "c t" -c "nexthop-group basic" -c "nexthop 1.1.1.1" -c "nexthop 1.1.1.2"' | |
467 | ) | |
8058df22 SW |
468 | |
469 | # Create with sharpd using nexthop-group | |
887a232c | 470 | net["r1"].cmd('vtysh -c "sharp install routes 2.2.2.1 nexthop-group basic 1"') |
8058df22 | 471 | |
887a232c | 472 | verify_route_nexthop_group("2.2.2.1/32") |
8058df22 | 473 | |
887a232c | 474 | ## Connected |
8058df22 | 475 | |
701a0192 | 476 | net["r1"].cmd( |
477 | 'vtysh -c "c t" -c "nexthop-group connected" -c "nexthop r1-eth1" -c "nexthop r1-eth2"' | |
478 | ) | |
8058df22 | 479 | |
887a232c SW |
480 | net["r1"].cmd('vtysh -c "sharp install routes 2.2.2.2 nexthop-group connected 1"') |
481 | ||
482 | verify_route_nexthop_group("2.2.2.2/32") | |
483 | ||
484 | ## Recursive | |
485 | ||
701a0192 | 486 | net["r1"].cmd( |
487 | 'vtysh -c "c t" -c "nexthop-group basic-recursive" -c "nexthop 2.2.2.1"' | |
488 | ) | |
887a232c | 489 | |
701a0192 | 490 | net["r1"].cmd( |
491 | 'vtysh -c "sharp install routes 3.3.3.1 nexthop-group basic-recursive 1"' | |
492 | ) | |
887a232c SW |
493 | |
494 | verify_route_nexthop_group("3.3.3.1/32", True) | |
495 | ||
496 | ## Duplicate | |
497 | ||
701a0192 | 498 | net["r1"].cmd( |
499 | 'vtysh -c "c t" -c "nexthop-group duplicate" -c "nexthop 2.2.2.1" -c "nexthop 1.1.1.1"' | |
500 | ) | |
887a232c SW |
501 | |
502 | net["r1"].cmd('vtysh -c "sharp install routes 3.3.3.2 nexthop-group duplicate 1"') | |
503 | ||
504 | verify_route_nexthop_group("3.3.3.2/32") | |
505 | ||
506 | ## Two 4-Way ECMP | |
507 | ||
701a0192 | 508 | net["r1"].cmd( |
509 | 'vtysh -c "c t" -c "nexthop-group fourA" -c "nexthop 1.1.1.1" -c "nexthop 1.1.1.2" \ | |
510 | -c "nexthop 1.1.1.3" -c "nexthop 1.1.1.4"' | |
511 | ) | |
887a232c SW |
512 | |
513 | net["r1"].cmd('vtysh -c "sharp install routes 4.4.4.1 nexthop-group fourA 1"') | |
514 | ||
515 | verify_route_nexthop_group("4.4.4.1/32") | |
516 | ||
701a0192 | 517 | net["r1"].cmd( |
518 | 'vtysh -c "c t" -c "nexthop-group fourB" -c "nexthop 1.1.1.5" -c "nexthop 1.1.1.6" \ | |
519 | -c "nexthop 1.1.1.7" -c "nexthop 1.1.1.8"' | |
520 | ) | |
887a232c SW |
521 | |
522 | net["r1"].cmd('vtysh -c "sharp install routes 4.4.4.2 nexthop-group fourB 1"') | |
523 | ||
524 | verify_route_nexthop_group("4.4.4.2/32") | |
525 | ||
526 | ## Recursive to 8-Way ECMP | |
527 | ||
701a0192 | 528 | net["r1"].cmd( |
529 | 'vtysh -c "c t" -c "nexthop-group eight-recursive" -c "nexthop 4.4.4.1" -c "nexthop 4.4.4.2"' | |
530 | ) | |
887a232c | 531 | |
701a0192 | 532 | net["r1"].cmd( |
533 | 'vtysh -c "sharp install routes 5.5.5.1 nexthop-group eight-recursive 1"' | |
534 | ) | |
887a232c SW |
535 | |
536 | verify_route_nexthop_group("5.5.5.1/32") | |
537 | ||
538 | ##CLI(net) | |
539 | ||
540 | ## Remove all NHG routes | |
541 | ||
542 | net["r1"].cmd('vtysh -c "sharp remove routes 2.2.2.1 1"') | |
543 | net["r1"].cmd('vtysh -c "sharp remove routes 2.2.2.2 1"') | |
544 | net["r1"].cmd('vtysh -c "sharp remove routes 3.3.3.1 1"') | |
545 | net["r1"].cmd('vtysh -c "sharp remove routes 3.3.3.2 1"') | |
546 | net["r1"].cmd('vtysh -c "sharp remove routes 4.4.4.1 1"') | |
547 | net["r1"].cmd('vtysh -c "sharp remove routes 4.4.4.2 1"') | |
548 | net["r1"].cmd('vtysh -c "sharp remove routes 5.5.5.1 1"') | |
4501fbca | 549 | |
701a0192 | 550 | |
4501fbca MW |
551 | def test_rip_status(): |
552 | global fatal_error | |
553 | global net | |
554 | ||
555 | # Skip if previous fatal error condition is raised | |
701a0192 | 556 | if fatal_error != "": |
4501fbca MW |
557 | pytest.skip(fatal_error) |
558 | ||
559 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
560 | ||
b2764f90 | 561 | print("\n\n** Verifying RIP status") |
4501fbca MW |
562 | print("******************************************\n") |
563 | failures = 0 | |
564 | for i in range(1, 2): | |
701a0192 | 565 | refTableFile = "%s/r%s/rip_status.ref" % (thisDir, i) |
4501fbca MW |
566 | if os.path.isfile(refTableFile): |
567 | # Read expected result from file | |
568 | expected = open(refTableFile).read().rstrip() | |
569 | # Fix newlines (make them all the same) | |
701a0192 | 570 | expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1) |
4501fbca MW |
571 | |
572 | # Actual output from router | |
701a0192 | 573 | actual = ( |
574 | net["r%s" % i] | |
575 | .cmd('vtysh -c "show ip rip status" 2> /dev/null') | |
576 | .rstrip() | |
577 | ) | |
578 | # Drop time in next due | |
4501fbca MW |
579 | actual = re.sub(r"in [0-9]+ seconds", "in XX seconds", actual) |
580 | # Drop time in last update | |
581 | actual = re.sub(r" [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", " XX:XX:XX", actual) | |
582 | # Fix newlines (make them all the same) | |
701a0192 | 583 | actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) |
4501fbca MW |
584 | |
585 | # Generate Diff | |
701a0192 | 586 | diff = topotest.get_textdiff( |
587 | actual, | |
588 | expected, | |
17070436 | 589 | title1="actual IP RIP status", |
701a0192 | 590 | title2="expected IP RIP status", |
591 | ) | |
4501fbca MW |
592 | |
593 | # Empty string if it matches, otherwise diff contains unified diff | |
594 | if diff: | |
701a0192 | 595 | sys.stderr.write("r%s failed IP RIP status check:\n%s\n" % (i, diff)) |
4501fbca MW |
596 | failures += 1 |
597 | else: | |
598 | print("r%s ok" % i) | |
599 | ||
600 | assert failures == 0, "IP RIP status failed for router r%s:\n%s" % (i, diff) | |
601 | ||
7e7fc73b MW |
602 | # Make sure that all daemons are running |
603 | for i in range(1, 2): | |
701a0192 | 604 | fatal_error = net["r%s" % i].checkRouterRunning() |
7e7fc73b MW |
605 | assert fatal_error == "", fatal_error |
606 | ||
622c4996 | 607 | # For debugging after starting FRR daemons, uncomment the next line |
4501fbca MW |
608 | # CLI(net) |
609 | ||
610 | ||
611 | def test_ripng_status(): | |
612 | global fatal_error | |
613 | global net | |
614 | ||
615 | # Skip if previous fatal error condition is raised | |
701a0192 | 616 | if fatal_error != "": |
4501fbca MW |
617 | pytest.skip(fatal_error) |
618 | ||
619 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
620 | ||
b2764f90 | 621 | print("\n\n** Verifying RIPng status") |
4501fbca MW |
622 | print("******************************************\n") |
623 | failures = 0 | |
624 | for i in range(1, 2): | |
701a0192 | 625 | refTableFile = "%s/r%s/ripng_status.ref" % (thisDir, i) |
4501fbca MW |
626 | if os.path.isfile(refTableFile): |
627 | # Read expected result from file | |
628 | expected = open(refTableFile).read().rstrip() | |
629 | # Fix newlines (make them all the same) | |
701a0192 | 630 | expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1) |
4501fbca MW |
631 | |
632 | # Actual output from router | |
701a0192 | 633 | actual = ( |
634 | net["r%s" % i] | |
635 | .cmd('vtysh -c "show ipv6 ripng status" 2> /dev/null') | |
636 | .rstrip() | |
637 | ) | |
4501fbca MW |
638 | # Mask out Link-Local mac address portion. They are random... |
639 | actual = re.sub(r" fe80::[0-9a-f:]+", " fe80::XXXX:XXXX:XXXX:XXXX", actual) | |
701a0192 | 640 | # Drop time in next due |
4501fbca MW |
641 | actual = re.sub(r"in [0-9]+ seconds", "in XX seconds", actual) |
642 | # Drop time in last update | |
643 | actual = re.sub(r" [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", " XX:XX:XX", actual) | |
644 | # Fix newlines (make them all the same) | |
701a0192 | 645 | actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) |
4501fbca MW |
646 | |
647 | # Generate Diff | |
701a0192 | 648 | diff = topotest.get_textdiff( |
649 | actual, | |
650 | expected, | |
17070436 | 651 | title1="actual IPv6 RIPng status", |
701a0192 | 652 | title2="expected IPv6 RIPng status", |
653 | ) | |
4501fbca MW |
654 | |
655 | # Empty string if it matches, otherwise diff contains unified diff | |
656 | if diff: | |
701a0192 | 657 | sys.stderr.write( |
658 | "r%s failed IPv6 RIPng status check:\n%s\n" % (i, diff) | |
659 | ) | |
4501fbca MW |
660 | failures += 1 |
661 | else: | |
662 | print("r%s ok" % i) | |
663 | ||
701a0192 | 664 | assert failures == 0, "IPv6 RIPng status failed for router r%s:\n%s" % ( |
665 | i, | |
666 | diff, | |
667 | ) | |
4501fbca | 668 | |
7e7fc73b MW |
669 | # Make sure that all daemons are running |
670 | for i in range(1, 2): | |
701a0192 | 671 | fatal_error = net["r%s" % i].checkRouterRunning() |
7e7fc73b MW |
672 | assert fatal_error == "", fatal_error |
673 | ||
622c4996 | 674 | # For debugging after starting FRR daemons, uncomment the next line |
4501fbca MW |
675 | # CLI(net) |
676 | ||
677 | ||
678 | def test_ospfv2_interfaces(): | |
679 | global fatal_error | |
680 | global net | |
681 | ||
682 | # Skip if previous fatal error condition is raised | |
701a0192 | 683 | if fatal_error != "": |
4501fbca MW |
684 | pytest.skip(fatal_error) |
685 | ||
686 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
687 | ||
b2764f90 | 688 | print("\n\n** Verifying OSPFv2 interfaces") |
4501fbca MW |
689 | print("******************************************\n") |
690 | failures = 0 | |
691 | for i in range(1, 2): | |
701a0192 | 692 | refTableFile = "%s/r%s/show_ip_ospf_interface.ref" % (thisDir, i) |
4501fbca MW |
693 | if os.path.isfile(refTableFile): |
694 | # Read expected result from file | |
695 | expected = open(refTableFile).read().rstrip() | |
696 | # Fix newlines (make them all the same) | |
701a0192 | 697 | expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1) |
4501fbca MW |
698 | |
699 | # Actual output from router | |
701a0192 | 700 | actual = ( |
701 | net["r%s" % i] | |
702 | .cmd('vtysh -c "show ip ospf interface" 2> /dev/null') | |
703 | .rstrip() | |
704 | ) | |
4501fbca MW |
705 | # Mask out Bandwidth portion. They may change.. |
706 | actual = re.sub(r"BW [0-9]+ Mbit", "BW XX Mbit", actual) | |
11761ab0 | 707 | actual = re.sub(r"ifindex [0-9]", "ifindex X", actual) |
c9d72a0b | 708 | |
701a0192 | 709 | # Drop time in next due |
4501fbca | 710 | actual = re.sub(r"Hello due in [0-9\.]+s", "Hello due in XX.XXXs", actual) |
701a0192 | 711 | actual = re.sub( |
712 | r"Hello due in [0-9\.]+ usecs", "Hello due in XX.XXXs", actual | |
713 | ) | |
985e6d50 | 714 | # Fix 'MTU mismatch detection: enabled' vs 'MTU mismatch detection:enabled' - accept both |
701a0192 | 715 | actual = re.sub( |
716 | r"MTU mismatch detection:([a-z]+.*)", | |
717 | r"MTU mismatch detection: \1", | |
718 | actual, | |
719 | ) | |
4501fbca | 720 | # Fix newlines (make them all the same) |
701a0192 | 721 | actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) |
4501fbca MW |
722 | |
723 | # Generate Diff | |
701a0192 | 724 | diff = topotest.get_textdiff( |
725 | actual, | |
726 | expected, | |
17070436 | 727 | title1="actual SHOW IP OSPF INTERFACE", |
701a0192 | 728 | title2="expected SHOW IP OSPF INTERFACE", |
729 | ) | |
4501fbca MW |
730 | |
731 | # Empty string if it matches, otherwise diff contains unified diff | |
732 | if diff: | |
701a0192 | 733 | sys.stderr.write( |
734 | "r%s failed SHOW IP OSPF INTERFACE check:\n%s\n" % (i, diff) | |
735 | ) | |
4501fbca MW |
736 | failures += 1 |
737 | else: | |
738 | print("r%s ok" % i) | |
739 | ||
08fa1af7 | 740 | # Ignoring the issue if told to ignore (ie not yet fixed) |
701a0192 | 741 | if failures != 0: |
742 | if os.environ.get("bamboo_TOPOTESTS_ISSUE_348") == "IGNORE": | |
743 | sys.stderr.write( | |
744 | "Known issue - IGNORING. See https://github.com/FRRouting/frr/issues/348\n" | |
745 | ) | |
746 | pytest.skip( | |
747 | "Known issue - IGNORING. See https://github.com/FRRouting/frr/issues/348" | |
748 | ) | |
749 | ||
750 | assert ( | |
751 | failures == 0 | |
752 | ), "SHOW IP OSPF INTERFACE failed for router r%s:\n%s" % (i, diff) | |
4501fbca | 753 | |
7e7fc73b MW |
754 | # Make sure that all daemons are running |
755 | for i in range(1, 2): | |
701a0192 | 756 | fatal_error = net["r%s" % i].checkRouterRunning() |
7e7fc73b MW |
757 | assert fatal_error == "", fatal_error |
758 | ||
622c4996 | 759 | # For debugging after starting FRR daemons, uncomment the next line |
4501fbca MW |
760 | # CLI(net) |
761 | ||
762 | ||
763 | def test_isis_interfaces(): | |
764 | global fatal_error | |
765 | global net | |
766 | ||
767 | # Skip if previous fatal error condition is raised | |
701a0192 | 768 | if fatal_error != "": |
4501fbca MW |
769 | pytest.skip(fatal_error) |
770 | ||
771 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
772 | ||
b2764f90 | 773 | print("\n\n** Verifying ISIS interfaces") |
4501fbca MW |
774 | print("******************************************\n") |
775 | failures = 0 | |
776 | for i in range(1, 2): | |
701a0192 | 777 | refTableFile = "%s/r%s/show_isis_interface_detail.ref" % (thisDir, i) |
4501fbca MW |
778 | if os.path.isfile(refTableFile): |
779 | # Read expected result from file | |
780 | expected = open(refTableFile).read().rstrip() | |
781 | # Fix newlines (make them all the same) | |
701a0192 | 782 | expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1) |
4501fbca MW |
783 | |
784 | # Actual output from router | |
701a0192 | 785 | actual = ( |
786 | net["r%s" % i] | |
787 | .cmd('vtysh -c "show isis interface detail" 2> /dev/null') | |
788 | .rstrip() | |
789 | ) | |
4501fbca MW |
790 | # Mask out Link-Local mac address portion. They are random... |
791 | actual = re.sub(r"fe80::[0-9a-f:]+", "fe80::XXXX:XXXX:XXXX:XXXX", actual) | |
792 | # Mask out SNPA mac address portion. They are random... | |
793 | actual = re.sub(r"SNPA: [0-9a-f\.]+", "SNPA: XXXX.XXXX.XXXX", actual) | |
6ae351e8 | 794 | # Mask out Circuit ID number |
701a0192 | 795 | actual = re.sub(r"Circuit Id: 0x[0-9a-f]+", "Circuit Id: 0xXX", actual) |
4501fbca | 796 | # Fix newlines (make them all the same) |
701a0192 | 797 | actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) |
4501fbca MW |
798 | |
799 | # Generate Diff | |
701a0192 | 800 | diff = topotest.get_textdiff( |
801 | actual, | |
802 | expected, | |
17070436 | 803 | title1="actual SHOW ISIS INTERFACE DETAIL", |
701a0192 | 804 | title2="expected SHOW ISIS OSPF6 INTERFACE DETAIL", |
805 | ) | |
4501fbca MW |
806 | |
807 | # Empty string if it matches, otherwise diff contains unified diff | |
808 | if diff: | |
701a0192 | 809 | sys.stderr.write( |
810 | "r%s failed SHOW ISIS INTERFACE DETAIL check:\n%s\n" % (i, diff) | |
811 | ) | |
4501fbca MW |
812 | failures += 1 |
813 | else: | |
814 | print("r%s ok" % i) | |
815 | ||
701a0192 | 816 | assert ( |
817 | failures == 0 | |
818 | ), "SHOW ISIS INTERFACE DETAIL failed for router r%s:\n%s" % (i, diff) | |
4501fbca | 819 | |
7e7fc73b MW |
820 | # Make sure that all daemons are running |
821 | for i in range(1, 2): | |
701a0192 | 822 | fatal_error = net["r%s" % i].checkRouterRunning() |
7e7fc73b MW |
823 | assert fatal_error == "", fatal_error |
824 | ||
622c4996 | 825 | # For debugging after starting FRR daemons, uncomment the next line |
4501fbca MW |
826 | # CLI(net) |
827 | ||
828 | ||
829 | def test_bgp_summary(): | |
830 | global fatal_error | |
831 | global net | |
832 | ||
833 | # Skip if previous fatal error condition is raised | |
701a0192 | 834 | if fatal_error != "": |
4501fbca MW |
835 | pytest.skip(fatal_error) |
836 | ||
837 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
838 | ||
b2764f90 | 839 | print("\n\n** Verifying BGP Summary") |
4501fbca MW |
840 | print("******************************************\n") |
841 | failures = 0 | |
842 | for i in range(1, 2): | |
701a0192 | 843 | refTableFile = "%s/r%s/show_ip_bgp_summary.ref" % (thisDir, i) |
4501fbca MW |
844 | if os.path.isfile(refTableFile): |
845 | # Read expected result from file | |
846 | expected = open(refTableFile).read().rstrip() | |
847 | # Fix newlines (make them all the same) | |
701a0192 | 848 | expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1) |
4501fbca MW |
849 | |
850 | # Actual output from router | |
701a0192 | 851 | actual = ( |
852 | net["r%s" % i] | |
853 | .cmd('vtysh -c "show ip bgp summary" 2> /dev/null') | |
854 | .rstrip() | |
855 | ) | |
4501fbca MW |
856 | # Mask out "using XXiXX bytes" portion. They are random... |
857 | actual = re.sub(r"using [0-9]+ bytes", "using XXXX bytes", actual) | |
858 | # Mask out "using XiXXX KiB" portion. They are random... | |
859 | actual = re.sub(r"using [0-9]+ KiB", "using XXXX KiB", actual) | |
08fa1af7 MW |
860 | # |
861 | # Remove extra summaries which exist with newer versions | |
862 | # | |
863 | # Remove summary lines (changed recently) | |
701a0192 | 864 | actual = re.sub(r"Total number.*", "", actual) |
865 | actual = re.sub(r"Displayed.*", "", actual) | |
08fa1af7 | 866 | # Remove IPv4 Unicast Summary (Title only) |
701a0192 | 867 | actual = re.sub(r"IPv4 Unicast Summary:", "", actual) |
08fa1af7 | 868 | # Remove IPv4 Multicast Summary (all of it) |
701a0192 | 869 | actual = re.sub(r"IPv4 Multicast Summary:", "", actual) |
870 | actual = re.sub(r"No IPv4 Multicast neighbor is configured", "", actual) | |
08fa1af7 | 871 | # Remove IPv4 VPN Summary (all of it) |
701a0192 | 872 | actual = re.sub(r"IPv4 VPN Summary:", "", actual) |
873 | actual = re.sub(r"No IPv4 VPN neighbor is configured", "", actual) | |
08fa1af7 | 874 | # Remove IPv4 Encap Summary (all of it) |
701a0192 | 875 | actual = re.sub(r"IPv4 Encap Summary:", "", actual) |
876 | actual = re.sub(r"No IPv4 Encap neighbor is configured", "", actual) | |
08fa1af7 | 877 | # Remove Unknown Summary (all of it) |
701a0192 | 878 | actual = re.sub(r"Unknown Summary:", "", actual) |
879 | actual = re.sub(r"No Unknown neighbor is configured", "", actual) | |
8b2e59e9 | 880 | |
701a0192 | 881 | actual = re.sub(r"IPv4 labeled-unicast Summary:", "", actual) |
882 | actual = re.sub( | |
883 | r"No IPv4 labeled-unicast neighbor is configured", "", actual | |
884 | ) | |
8b2e59e9 | 885 | |
08fa1af7 MW |
886 | # Strip empty lines |
887 | actual = actual.lstrip() | |
888 | actual = actual.rstrip() | |
889 | # | |
4501fbca | 890 | # Fix newlines (make them all the same) |
701a0192 | 891 | actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) |
4501fbca MW |
892 | |
893 | # Generate Diff | |
701a0192 | 894 | diff = topotest.get_textdiff( |
895 | actual, | |
896 | expected, | |
17070436 | 897 | title1="actual SHOW IP BGP SUMMARY", |
701a0192 | 898 | title2="expected SHOW IP BGP SUMMARY", |
899 | ) | |
4501fbca MW |
900 | |
901 | # Empty string if it matches, otherwise diff contains unified diff | |
902 | if diff: | |
701a0192 | 903 | sys.stderr.write( |
904 | "r%s failed SHOW IP BGP SUMMARY check:\n%s\n" % (i, diff) | |
905 | ) | |
4501fbca MW |
906 | failures += 1 |
907 | else: | |
908 | print("r%s ok" % i) | |
909 | ||
701a0192 | 910 | assert failures == 0, "SHOW IP BGP SUMMARY failed for router r%s:\n%s" % ( |
911 | i, | |
912 | diff, | |
913 | ) | |
4501fbca | 914 | |
7e7fc73b MW |
915 | # Make sure that all daemons are running |
916 | for i in range(1, 2): | |
701a0192 | 917 | fatal_error = net["r%s" % i].checkRouterRunning() |
7e7fc73b MW |
918 | assert fatal_error == "", fatal_error |
919 | ||
622c4996 | 920 | # For debugging after starting FRR daemons, uncomment the next line |
4501fbca MW |
921 | # CLI(net) |
922 | ||
923 | ||
924 | def test_bgp_ipv6_summary(): | |
925 | global fatal_error | |
926 | global net | |
927 | ||
928 | # Skip if previous fatal error condition is raised | |
701a0192 | 929 | if fatal_error != "": |
4501fbca MW |
930 | pytest.skip(fatal_error) |
931 | ||
932 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
933 | ||
b2764f90 | 934 | print("\n\n** Verifying BGP IPv6 Summary") |
4501fbca MW |
935 | print("******************************************\n") |
936 | failures = 0 | |
937 | for i in range(1, 2): | |
701a0192 | 938 | refTableFile = "%s/r%s/show_bgp_ipv6_summary.ref" % (thisDir, i) |
4501fbca MW |
939 | if os.path.isfile(refTableFile): |
940 | # Read expected result from file | |
941 | expected = open(refTableFile).read().rstrip() | |
942 | # Fix newlines (make them all the same) | |
701a0192 | 943 | expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1) |
4501fbca MW |
944 | |
945 | # Actual output from router | |
701a0192 | 946 | actual = ( |
947 | net["r%s" % i] | |
948 | .cmd('vtysh -c "show bgp ipv6 summary" 2> /dev/null') | |
949 | .rstrip() | |
950 | ) | |
4501fbca MW |
951 | # Mask out "using XXiXX bytes" portion. They are random... |
952 | actual = re.sub(r"using [0-9]+ bytes", "using XXXX bytes", actual) | |
953 | # Mask out "using XiXXX KiB" portion. They are random... | |
954 | actual = re.sub(r"using [0-9]+ KiB", "using XXXX KiB", actual) | |
08fa1af7 MW |
955 | # |
956 | # Remove extra summaries which exist with newer versions | |
957 | # | |
958 | # Remove summary lines (changed recently) | |
701a0192 | 959 | actual = re.sub(r"Total number.*", "", actual) |
960 | actual = re.sub(r"Displayed.*", "", actual) | |
08fa1af7 | 961 | # Remove IPv4 Unicast Summary (Title only) |
701a0192 | 962 | actual = re.sub(r"IPv6 Unicast Summary:", "", actual) |
08fa1af7 | 963 | # Remove IPv4 Multicast Summary (all of it) |
701a0192 | 964 | actual = re.sub(r"IPv6 Multicast Summary:", "", actual) |
965 | actual = re.sub(r"No IPv6 Multicast neighbor is configured", "", actual) | |
08fa1af7 | 966 | # Remove IPv4 VPN Summary (all of it) |
701a0192 | 967 | actual = re.sub(r"IPv6 VPN Summary:", "", actual) |
968 | actual = re.sub(r"No IPv6 VPN neighbor is configured", "", actual) | |
08fa1af7 | 969 | # Remove IPv4 Encap Summary (all of it) |
701a0192 | 970 | actual = re.sub(r"IPv6 Encap Summary:", "", actual) |
971 | actual = re.sub(r"No IPv6 Encap neighbor is configured", "", actual) | |
08fa1af7 | 972 | # Remove Unknown Summary (all of it) |
701a0192 | 973 | actual = re.sub(r"Unknown Summary:", "", actual) |
974 | actual = re.sub(r"No Unknown neighbor is configured", "", actual) | |
8b2e59e9 DS |
975 | |
976 | # Remove Labeled Unicast Summary (all of it) | |
701a0192 | 977 | actual = re.sub(r"IPv6 labeled-unicast Summary:", "", actual) |
978 | actual = re.sub( | |
979 | r"No IPv6 labeled-unicast neighbor is configured", "", actual | |
980 | ) | |
8b2e59e9 | 981 | |
08fa1af7 MW |
982 | # Strip empty lines |
983 | actual = actual.lstrip() | |
984 | actual = actual.rstrip() | |
985 | # | |
4501fbca | 986 | # Fix newlines (make them all the same) |
701a0192 | 987 | actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) |
4501fbca MW |
988 | |
989 | # Generate Diff | |
701a0192 | 990 | diff = topotest.get_textdiff( |
991 | actual, | |
992 | expected, | |
17070436 | 993 | title1="actual SHOW BGP IPv6 SUMMARY", |
701a0192 | 994 | title2="expected SHOW BGP IPv6 SUMMARY", |
995 | ) | |
4501fbca MW |
996 | |
997 | # Empty string if it matches, otherwise diff contains unified diff | |
998 | if diff: | |
701a0192 | 999 | sys.stderr.write( |
1000 | "r%s failed SHOW BGP IPv6 SUMMARY check:\n%s\n" % (i, diff) | |
1001 | ) | |
4501fbca MW |
1002 | failures += 1 |
1003 | else: | |
1004 | print("r%s ok" % i) | |
1005 | ||
701a0192 | 1006 | assert failures == 0, "SHOW BGP IPv6 SUMMARY failed for router r%s:\n%s" % ( |
1007 | i, | |
1008 | diff, | |
1009 | ) | |
4501fbca | 1010 | |
7e7fc73b MW |
1011 | # Make sure that all daemons are running |
1012 | for i in range(1, 2): | |
701a0192 | 1013 | fatal_error = net["r%s" % i].checkRouterRunning() |
7e7fc73b MW |
1014 | assert fatal_error == "", fatal_error |
1015 | ||
622c4996 | 1016 | # For debugging after starting FRR daemons, uncomment the next line |
4501fbca MW |
1017 | # CLI(net) |
1018 | ||
1019 | ||
1020 | def test_bgp_ipv4(): | |
1021 | global fatal_error | |
1022 | global net | |
1023 | ||
1024 | # Skip if previous fatal error condition is raised | |
701a0192 | 1025 | if fatal_error != "": |
4501fbca MW |
1026 | pytest.skip(fatal_error) |
1027 | ||
1028 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
1029 | ||
b2764f90 | 1030 | print("\n\n** Verifying BGP IPv4") |
4501fbca | 1031 | print("******************************************\n") |
6a57e103 | 1032 | diffresult = {} |
4501fbca | 1033 | for i in range(1, 2): |
11761ab0 | 1034 | success = 0 |
701a0192 | 1035 | for refTableFile in glob.glob("%s/r%s/show_bgp_ipv4*.ref" % (thisDir, i)): |
11761ab0 MS |
1036 | if os.path.isfile(refTableFile): |
1037 | # Read expected result from file | |
1038 | expected = open(refTableFile).read().rstrip() | |
1039 | # Fix newlines (make them all the same) | |
701a0192 | 1040 | expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1) |
11761ab0 MS |
1041 | |
1042 | # Actual output from router | |
701a0192 | 1043 | actual = ( |
1044 | net["r%s" % i].cmd('vtysh -c "show bgp ipv4" 2> /dev/null').rstrip() | |
1045 | ) | |
11761ab0 | 1046 | # Remove summary line (changed recently) |
701a0192 | 1047 | actual = re.sub(r"Total number.*", "", actual) |
1048 | actual = re.sub(r"Displayed.*", "", actual) | |
11761ab0 MS |
1049 | actual = actual.rstrip() |
1050 | # Fix newlines (make them all the same) | |
701a0192 | 1051 | actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) |
11761ab0 MS |
1052 | |
1053 | # Generate Diff | |
701a0192 | 1054 | diff = topotest.get_textdiff( |
1055 | actual, | |
1056 | expected, | |
11761ab0 | 1057 | title1="actual SHOW BGP IPv4", |
701a0192 | 1058 | title2="expected SHOW BGP IPv4", |
1059 | ) | |
11761ab0 MS |
1060 | |
1061 | # Empty string if it matches, otherwise diff contains unified diff | |
1062 | if diff: | |
1063 | diffresult[refTableFile] = diff | |
1064 | else: | |
1065 | success = 1 | |
1066 | print("template %s matched: r%s ok" % (refTableFile, i)) | |
1067 | break | |
1068 | ||
1069 | if not success: | |
701a0192 | 1070 | resultstr = "No template matched.\n" |
e7294b32 | 1071 | for f in diffresult.keys(): |
701a0192 | 1072 | resultstr += "template %s: r%s failed SHOW BGP IPv4 check:\n%s\n" % ( |
1073 | f, | |
1074 | i, | |
1075 | diffresult[f], | |
1076 | ) | |
11761ab0 | 1077 | raise AssertionError( |
701a0192 | 1078 | "SHOW BGP IPv4 failed for router r%s:\n%s" % (i, resultstr) |
1079 | ) | |
4501fbca | 1080 | |
7e7fc73b MW |
1081 | # Make sure that all daemons are running |
1082 | for i in range(1, 2): | |
701a0192 | 1083 | fatal_error = net["r%s" % i].checkRouterRunning() |
7e7fc73b MW |
1084 | assert fatal_error == "", fatal_error |
1085 | ||
622c4996 | 1086 | # For debugging after starting FRR daemons, uncomment the next line |
4501fbca MW |
1087 | # CLI(net) |
1088 | ||
1089 | ||
1090 | def test_bgp_ipv6(): | |
1091 | global fatal_error | |
1092 | global net | |
1093 | ||
1094 | # Skip if previous fatal error condition is raised | |
701a0192 | 1095 | if fatal_error != "": |
4501fbca MW |
1096 | pytest.skip(fatal_error) |
1097 | ||
1098 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
1099 | ||
b2764f90 | 1100 | print("\n\n** Verifying BGP IPv6") |
4501fbca | 1101 | print("******************************************\n") |
6a57e103 | 1102 | diffresult = {} |
4501fbca | 1103 | for i in range(1, 2): |
11761ab0 | 1104 | success = 0 |
701a0192 | 1105 | for refTableFile in glob.glob("%s/r%s/show_bgp_ipv6*.ref" % (thisDir, i)): |
11761ab0 MS |
1106 | if os.path.isfile(refTableFile): |
1107 | # Read expected result from file | |
1108 | expected = open(refTableFile).read().rstrip() | |
1109 | # Fix newlines (make them all the same) | |
701a0192 | 1110 | expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1) |
11761ab0 MS |
1111 | |
1112 | # Actual output from router | |
701a0192 | 1113 | actual = ( |
1114 | net["r%s" % i].cmd('vtysh -c "show bgp ipv6" 2> /dev/null').rstrip() | |
1115 | ) | |
11761ab0 | 1116 | # Remove summary line (changed recently) |
701a0192 | 1117 | actual = re.sub(r"Total number.*", "", actual) |
1118 | actual = re.sub(r"Displayed.*", "", actual) | |
11761ab0 MS |
1119 | actual = actual.rstrip() |
1120 | # Fix newlines (make them all the same) | |
701a0192 | 1121 | actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) |
11761ab0 MS |
1122 | |
1123 | # Generate Diff | |
701a0192 | 1124 | diff = topotest.get_textdiff( |
1125 | actual, | |
1126 | expected, | |
11761ab0 | 1127 | title1="actual SHOW BGP IPv6", |
701a0192 | 1128 | title2="expected SHOW BGP IPv6", |
1129 | ) | |
11761ab0 MS |
1130 | |
1131 | # Empty string if it matches, otherwise diff contains unified diff | |
1132 | if diff: | |
1133 | diffresult[refTableFile] = diff | |
1134 | else: | |
1135 | success = 1 | |
1136 | print("template %s matched: r%s ok" % (refTableFile, i)) | |
1137 | ||
1138 | if not success: | |
701a0192 | 1139 | resultstr = "No template matched.\n" |
e7294b32 | 1140 | for f in diffresult.keys(): |
701a0192 | 1141 | resultstr += "template %s: r%s failed SHOW BGP IPv6 check:\n%s\n" % ( |
1142 | f, | |
1143 | i, | |
1144 | diffresult[f], | |
1145 | ) | |
11761ab0 | 1146 | raise AssertionError( |
701a0192 | 1147 | "SHOW BGP IPv6 failed for router r%s:\n%s" % (i, resultstr) |
1148 | ) | |
4501fbca | 1149 | |
7e7fc73b MW |
1150 | # Make sure that all daemons are running |
1151 | for i in range(1, 2): | |
701a0192 | 1152 | fatal_error = net["r%s" % i].checkRouterRunning() |
7e7fc73b MW |
1153 | assert fatal_error == "", fatal_error |
1154 | ||
622c4996 | 1155 | # For debugging after starting FRR daemons, uncomment the next line |
4501fbca MW |
1156 | # CLI(net) |
1157 | ||
701a0192 | 1158 | |
41fce07c DS |
1159 | def test_route_map(): |
1160 | global fatal_error | |
1161 | global net | |
1162 | ||
701a0192 | 1163 | if fatal_error != "": |
41fce07c DS |
1164 | pytest.skip(fatal_error) |
1165 | ||
1166 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
1167 | ||
1168 | print("\n\n** Verifying some basic routemap forward references\n") | |
1169 | print("*******************************************************\n") | |
1170 | failures = 0 | |
1171 | for i in range(1, 2): | |
701a0192 | 1172 | refroutemap = "%s/r%s/show_route_map.ref" % (thisDir, i) |
41fce07c DS |
1173 | if os.path.isfile(refroutemap): |
1174 | expected = open(refroutemap).read().rstrip() | |
701a0192 | 1175 | expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1) |
41fce07c | 1176 | |
701a0192 | 1177 | actual = ( |
1178 | net["r%s" % i].cmd('vtysh -c "show route-map" 2> /dev/null').rstrip() | |
1179 | ) | |
1180 | actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) | |
41fce07c | 1181 | |
701a0192 | 1182 | diff = topotest.get_textdiff( |
1183 | actual, | |
1184 | expected, | |
1185 | title1="actual show route-map", | |
1186 | title2="expected show route-map", | |
1187 | ) | |
41fce07c DS |
1188 | |
1189 | if diff: | |
701a0192 | 1190 | sys.stderr.write( |
1191 | "r%s failed show route-map command Check:\n%s\n" % (i, diff) | |
1192 | ) | |
41fce07c DS |
1193 | failures += 1 |
1194 | else: | |
701a0192 | 1195 | print("r%s ok" % i) |
1196 | ||
1197 | assert ( | |
1198 | failures == 0 | |
1199 | ), "Show route-map command failed for router r%s:\n%s" % (i, diff) | |
4501fbca MW |
1200 | |
1201 | ||
887a232c SW |
1202 | def test_nexthop_groups_with_route_maps(): |
1203 | global fatal_error | |
1204 | global net | |
1205 | ||
1206 | # Skip if previous fatal error condition is raised | |
701a0192 | 1207 | if fatal_error != "": |
887a232c SW |
1208 | pytest.skip(fatal_error) |
1209 | ||
1210 | print("\n\n** Verifying Nexthop Groups With Route-Maps") | |
1211 | print("******************************************\n") | |
1212 | ||
1213 | ### Nexthop Group With Route-Map Tests | |
1214 | ||
1215 | # Create a lib nexthop-group | |
701a0192 | 1216 | net["r1"].cmd( |
1217 | 'vtysh -c "c t" -c "nexthop-group test" -c "nexthop 1.1.1.1" -c "nexthop 1.1.1.2"' | |
1218 | ) | |
887a232c SW |
1219 | |
1220 | ## Route-Map Proto Source | |
1221 | ||
1222 | route_str = "2.2.2.1" | |
1223 | src_str = "192.168.0.1" | |
1224 | ||
701a0192 | 1225 | net["r1"].cmd( |
1226 | 'vtysh -c "c t" -c "route-map NH-SRC permit 111" -c "set src %s"' % src_str | |
1227 | ) | |
887a232c SW |
1228 | net["r1"].cmd('vtysh -c "c t" -c "ip protocol sharp route-map NH-SRC"') |
1229 | ||
1230 | net["r1"].cmd('vtysh -c "sharp install routes %s nexthop-group test 1"' % route_str) | |
1231 | ||
1232 | verify_route_nexthop_group("%s/32" % route_str) | |
1233 | ||
1234 | # Only a valid test on linux using nexthop objects | |
1235 | if sys.platform.startswith("linux"): | |
701a0192 | 1236 | output = net["r1"].cmd("ip route show %s/32" % route_str) |
887a232c | 1237 | match = re.search(r"src %s" % src_str, output) |
701a0192 | 1238 | assert match is not None, "Route %s/32 not installed with src %s" % ( |
1239 | route_str, | |
1240 | src_str, | |
1241 | ) | |
887a232c SW |
1242 | |
1243 | # Remove NHG routes and route-map | |
1244 | net["r1"].cmd('vtysh -c "sharp remove routes %s 1"' % route_str) | |
1245 | net["r1"].cmd('vtysh -c "c t" -c "no ip protocol sharp route-map NH-SRC"') | |
701a0192 | 1246 | net["r1"].cmd( |
1247 | 'vtysh -c "c t" -c "no route-map NH-SRC permit 111" -c "set src %s"' % src_str | |
1248 | ) | |
887a232c SW |
1249 | net["r1"].cmd('vtysh -c "c t" -c "no route-map NH-SRC"') |
1250 | ||
1251 | ## Route-Map Deny/Permit with same nexthop group | |
1252 | ||
1253 | permit_route_str = "3.3.3.1" | |
1254 | deny_route_str = "3.3.3.2" | |
1255 | ||
701a0192 | 1256 | net["r1"].cmd( |
1257 | 'vtysh -c "c t" -c "ip prefix-list NOPE seq 5 permit %s/32"' % permit_route_str | |
1258 | ) | |
1259 | net["r1"].cmd( | |
1260 | 'vtysh -c "c t" -c "route-map NOPE permit 111" -c "match ip address prefix-list NOPE"' | |
1261 | ) | |
887a232c SW |
1262 | net["r1"].cmd('vtysh -c "c t" -c "route-map NOPE deny 222"') |
1263 | net["r1"].cmd('vtysh -c "c t" -c "ip protocol sharp route-map NOPE"') | |
1264 | ||
1265 | # This route should be permitted | |
701a0192 | 1266 | net["r1"].cmd( |
1267 | 'vtysh -c "sharp install routes %s nexthop-group test 1"' % permit_route_str | |
1268 | ) | |
887a232c SW |
1269 | |
1270 | verify_route_nexthop_group("%s/32" % permit_route_str) | |
1271 | ||
1272 | # This route should be denied | |
701a0192 | 1273 | net["r1"].cmd( |
1274 | 'vtysh -c "sharp install routes %s nexthop-group test 1"' % deny_route_str | |
1275 | ) | |
887a232c SW |
1276 | |
1277 | nhg_id = route_get_nhg_id(deny_route_str) | |
1278 | output = net["r1"].cmd('vtysh -c "show nexthop-group rib %d"' % nhg_id) | |
1279 | ||
1280 | match = re.search(r"Valid", output) | |
1281 | assert match is None, "Nexthop Group ID=%d should not be marked Valid" % nhg_id | |
1282 | ||
1283 | match = re.search(r"Installed", output) | |
1284 | assert match is None, "Nexthop Group ID=%d should not be marked Installed" % nhg_id | |
1285 | ||
1286 | # Remove NHG routes and route-map | |
1287 | net["r1"].cmd('vtysh -c "sharp remove routes %s 1"' % permit_route_str) | |
1288 | net["r1"].cmd('vtysh -c "sharp remove routes %s 1"' % deny_route_str) | |
1289 | net["r1"].cmd('vtysh -c "c t" -c "no ip protocol sharp route-map NOPE"') | |
1290 | net["r1"].cmd('vtysh -c "c t" -c "no route-map NOPE permit 111"') | |
1291 | net["r1"].cmd('vtysh -c "c t" -c "no route-map NOPE deny 222"') | |
1292 | net["r1"].cmd('vtysh -c "c t" -c "no route-map NOPE"') | |
701a0192 | 1293 | net["r1"].cmd( |
1294 | 'vtysh -c "c t" -c "no ip prefix-list NOPE seq 5 permit %s/32"' | |
1295 | % permit_route_str | |
1296 | ) | |
1297 | ||
887a232c | 1298 | |
8f4d7212 SW |
1299 | def test_nexthop_group_replace(): |
1300 | global fatal_error | |
1301 | global net | |
1302 | ||
1303 | # Skip if previous fatal error condition is raised | |
701a0192 | 1304 | if fatal_error != "": |
8f4d7212 SW |
1305 | pytest.skip(fatal_error) |
1306 | ||
1307 | print("\n\n** Verifying Nexthop Groups") | |
1308 | print("******************************************\n") | |
1309 | ||
1310 | ### Nexthop Group Tests | |
1311 | ||
1312 | ## 2-Way ECMP Directly Connected | |
1313 | ||
701a0192 | 1314 | net["r1"].cmd( |
1315 | '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"' | |
1316 | ) | |
8f4d7212 SW |
1317 | |
1318 | # Create with sharpd using nexthop-group | |
1319 | net["r1"].cmd('vtysh -c "sharp install routes 3.3.3.1 nexthop-group replace 1"') | |
1320 | ||
1321 | verify_route_nexthop_group("3.3.3.1/32") | |
1322 | ||
1323 | # Change the nexthop group | |
701a0192 | 1324 | net["r1"].cmd( |
1325 | '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"' | |
1326 | ) | |
8f4d7212 SW |
1327 | |
1328 | # Verify it updated. We can just check install and ecmp count here. | |
1329 | verify_route_nexthop_group("3.3.3.1/32", False, 3) | |
1330 | ||
701a0192 | 1331 | |
4501fbca MW |
1332 | def test_mpls_interfaces(): |
1333 | global fatal_error | |
1334 | global net | |
1335 | ||
1336 | # Skip if previous fatal error condition is raised | |
701a0192 | 1337 | if fatal_error != "": |
4501fbca MW |
1338 | pytest.skip(fatal_error) |
1339 | ||
1340 | # Skip if no LDP installed or old kernel | |
701a0192 | 1341 | if net["r1"].daemon_available("ldpd") == False: |
4501fbca MW |
1342 | pytest.skip("No MPLS or kernel < 4.5") |
1343 | ||
1344 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
1345 | ||
b2764f90 | 1346 | print("\n\n** Verifying MPLS Interfaces") |
4501fbca MW |
1347 | print("******************************************\n") |
1348 | failures = 0 | |
1349 | for i in range(1, 2): | |
701a0192 | 1350 | refTableFile = "%s/r%s/show_mpls_ldp_interface.ref" % (thisDir, i) |
4501fbca MW |
1351 | if os.path.isfile(refTableFile): |
1352 | # Read expected result from file | |
1353 | expected = open(refTableFile).read().rstrip() | |
1354 | # Fix newlines (make them all the same) | |
701a0192 | 1355 | expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1) |
4501fbca MW |
1356 | |
1357 | # Actual output from router | |
701a0192 | 1358 | actual = ( |
1359 | net["r%s" % i] | |
1360 | .cmd('vtysh -c "show mpls ldp interface" 2> /dev/null') | |
1361 | .rstrip() | |
1362 | ) | |
4501fbca MW |
1363 | # Mask out Timer in Uptime |
1364 | actual = re.sub(r" [0-9][0-9]:[0-9][0-9]:[0-9][0-9] ", " xx:xx:xx ", actual) | |
1365 | # Fix newlines (make them all the same) | |
701a0192 | 1366 | actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) |
4501fbca MW |
1367 | |
1368 | # Generate Diff | |
701a0192 | 1369 | diff = topotest.get_textdiff( |
1370 | actual, | |
1371 | expected, | |
17070436 | 1372 | title1="actual MPLS LDP interface status", |
701a0192 | 1373 | title2="expected MPLS LDP interface status", |
1374 | ) | |
4501fbca MW |
1375 | |
1376 | # Empty string if it matches, otherwise diff contains unified diff | |
1377 | if diff: | |
701a0192 | 1378 | sys.stderr.write( |
1379 | "r%s failed MPLS LDP Interface status Check:\n%s\n" % (i, diff) | |
1380 | ) | |
4501fbca MW |
1381 | failures += 1 |
1382 | else: | |
1383 | print("r%s ok" % i) | |
1384 | ||
701a0192 | 1385 | if failures > 0: |
4501fbca MW |
1386 | fatal_error = "MPLS LDP Interface status failed" |
1387 | ||
701a0192 | 1388 | assert ( |
1389 | failures == 0 | |
1390 | ), "MPLS LDP Interface status failed for router r%s:\n%s" % (i, diff) | |
4501fbca | 1391 | |
7e7fc73b MW |
1392 | # Make sure that all daemons are running |
1393 | for i in range(1, 2): | |
701a0192 | 1394 | fatal_error = net["r%s" % i].checkRouterRunning() |
7e7fc73b MW |
1395 | assert fatal_error == "", fatal_error |
1396 | ||
622c4996 | 1397 | # For debugging after starting FRR daemons, uncomment the next line |
4501fbca MW |
1398 | # CLI(net) |
1399 | ||
1400 | ||
1401 | def test_shutdown_check_stderr(): | |
1402 | global fatal_error | |
1403 | global net | |
1404 | ||
1405 | # Skip if previous fatal error condition is raised | |
701a0192 | 1406 | if fatal_error != "": |
4501fbca MW |
1407 | pytest.skip(fatal_error) |
1408 | ||
b2764f90 | 1409 | print("\n\n** Verifying unexpected STDERR output from daemons") |
4501fbca MW |
1410 | print("******************************************\n") |
1411 | ||
701a0192 | 1412 | if os.environ.get("TOPOTESTS_CHECK_STDERR") is None: |
1413 | print( | |
1414 | "SKIPPED final check on StdErr output: Disabled (TOPOTESTS_CHECK_STDERR undefined)\n" | |
1415 | ) | |
1416 | pytest.skip("Skipping test for Stderr output") | |
4501fbca MW |
1417 | |
1418 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
1419 | ||
50c40bde MW |
1420 | print("thisDir=" + thisDir) |
1421 | ||
701a0192 | 1422 | net["r1"].stopRouter() |
4501fbca | 1423 | |
701a0192 | 1424 | log = net["r1"].getStdErr("ripd") |
8e957dbb MW |
1425 | if log: |
1426 | print("\nRIPd StdErr Log:\n" + log) | |
701a0192 | 1427 | log = net["r1"].getStdErr("ripngd") |
8e957dbb MW |
1428 | if log: |
1429 | print("\nRIPngd StdErr Log:\n" + log) | |
701a0192 | 1430 | log = net["r1"].getStdErr("ospfd") |
8e957dbb MW |
1431 | if log: |
1432 | print("\nOSPFd StdErr Log:\n" + log) | |
701a0192 | 1433 | log = net["r1"].getStdErr("ospf6d") |
8e957dbb MW |
1434 | if log: |
1435 | print("\nOSPF6d StdErr Log:\n" + log) | |
701a0192 | 1436 | log = net["r1"].getStdErr("isisd") |
8e957dbb MW |
1437 | if log: |
1438 | print("\nISISd StdErr Log:\n" + log) | |
701a0192 | 1439 | log = net["r1"].getStdErr("bgpd") |
8e957dbb MW |
1440 | if log: |
1441 | print("\nBGPd StdErr Log:\n" + log) | |
af39fbe7 | 1442 | |
701a0192 | 1443 | log = net["r1"].getStdErr("nhrpd") |
af39fbe7 MS |
1444 | if log: |
1445 | print("\nNHRPd StdErr Log:\n" + log) | |
1446 | ||
701a0192 | 1447 | log = net["r1"].getStdErr("pbrd") |
af39fbe7 MS |
1448 | if log: |
1449 | print("\nPBRd StdErr Log:\n" + log) | |
1450 | ||
701a0192 | 1451 | log = net["r1"].getStdErr("babeld") |
af39fbe7 MS |
1452 | if log: |
1453 | print("\nBABELd StdErr Log:\n" + log) | |
1454 | ||
701a0192 | 1455 | if net["r1"].daemon_available("ldpd"): |
1456 | log = net["r1"].getStdErr("ldpd") | |
8e957dbb MW |
1457 | if log: |
1458 | print("\nLDPd StdErr Log:\n" + log) | |
701a0192 | 1459 | log = net["r1"].getStdErr("zebra") |
8e957dbb MW |
1460 | if log: |
1461 | print("\nZebra StdErr Log:\n" + log) | |
4501fbca MW |
1462 | |
1463 | ||
50c40bde MW |
1464 | def test_shutdown_check_memleak(): |
1465 | global fatal_error | |
1466 | global net | |
1467 | ||
1468 | # Skip if previous fatal error condition is raised | |
701a0192 | 1469 | if fatal_error != "": |
50c40bde MW |
1470 | pytest.skip(fatal_error) |
1471 | ||
701a0192 | 1472 | if os.environ.get("TOPOTESTS_CHECK_MEMLEAK") is None: |
1473 | print( | |
1474 | "SKIPPED final check on Memory leaks: Disabled (TOPOTESTS_CHECK_MEMLEAK undefined)\n" | |
1475 | ) | |
1476 | pytest.skip("Skipping test for memory leaks") | |
1477 | ||
50c40bde MW |
1478 | thisDir = os.path.dirname(os.path.realpath(__file__)) |
1479 | ||
1480 | for i in range(1, 2): | |
701a0192 | 1481 | net["r%s" % i].stopRouter() |
1482 | net["r%s" % i].report_memory_leaks( | |
1483 | os.environ.get("TOPOTESTS_CHECK_MEMLEAK"), os.path.basename(__file__) | |
1484 | ) | |
50c40bde MW |
1485 | |
1486 | ||
701a0192 | 1487 | if __name__ == "__main__": |
4501fbca | 1488 | |
701a0192 | 1489 | setLogLevel("info") |
4501fbca MW |
1490 | # To suppress tracebacks, either use the following pytest call or add "--tb=no" to cli |
1491 | # retval = pytest.main(["-s", "--tb=no"]) | |
1492 | retval = pytest.main(["-s"]) | |
1493 | sys.exit(retval) |