]> git.proxmox.com Git - mirror_frr.git/blame - tests/topotests/ldp_topo1/test_ldp_topo1.py
Merge pull request #11182 from g-balaji1/pimv6-sock-hdrincl
[mirror_frr.git] / tests / topotests / ldp_topo1 / test_ldp_topo1.py
CommitLineData
f03e38f3
MW
1#!/usr/bin/env python
2
3#
4# test_bgp_multiview_topo1.py
5# Part of NetDEF Topology Tests
6#
7# Copyright (c) 2016 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
21b5cd1d 25r"""
622c4996 26test_ldp_topo1.py: Simple FRR LDP Test
f03e38f3
MW
27
28 +---------+
29 | r1 |
30 | 1.1.1.1 |
31 +----+----+
32 | .1 r1-eth0
33 |
34 ~~~~~~~~~~~~~
35 ~~ sw0 ~~
36 ~~ 10.0.1.0/24 ~~
37 ~~~~~~~~~~~~~
38 |10.0.1.0/24
39 |
40 | .2 r2-eth0
41 +----+----+
42 | r2 |
43 | 2.2.2.2 |
44 +--+---+--+
45 r2-eth2 .2 | | .2 r2-eth1
46 ______/ \______
47 / \
48 ~~~~~~~~~~~~~ ~~~~~~~~~~~~~
49~~ sw2 ~~ ~~ sw1 ~~
50~~ 10.0.3.0/24 ~~ ~~ 10.0.2.0/24 ~~
51 ~~~~~~~~~~~~~ ~~~~~~~~~~~~~
52 | / |
53 \ _________/ |
54 \ / \
55r3-eth1 .3 | | .3 r3-eth0 | .4 r4-eth0
56 +----+--+---+ +----+----+
57 | r3 | | r4 |
58 | 3.3.3.3 | | 4.4.4.4 |
59 +-----------+ +---------+
787e7624 60"""
f03e38f3
MW
61
62import os
63import re
64import sys
594b1259 65import pytest
1c333cbe
RW
66import json
67from functools import partial
594b1259 68from time import sleep
e5369c47 69from lib.topolog import logger
f03e38f3 70
1c333cbe
RW
71# Save the Current Working Directory to find configuration files.
72CWD = os.path.dirname(os.path.realpath(__file__))
73sys.path.append(os.path.join(CWD, "../"))
74
594b1259
MW
75sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
76from lib import topotest
e82b531d 77from lib.topogen import Topogen, get_topogen
f03e38f3
MW
78
79fatal_error = ""
80
3dedee4f 81pytestmark = [pytest.mark.ldpd, pytest.mark.ospfd]
6907ac7e 82
f03e38f3
MW
83#####################################################
84##
85## Network Topology Definition
86##
87#####################################################
88
787e7624 89
e82b531d 90def build_topo(tgen):
f03e38f3 91
e82b531d
CH
92 # Setup Routers
93 for i in range(1, 5):
94 tgen.add_router("r%s" % i)
95
96 # First switch
97 switch = tgen.add_switch("sw0")
98 switch.add_link(tgen.gears["r1"])
99 switch.add_link(tgen.gears["r2"])
100 # Second switch
101 switch = tgen.add_switch("sw1")
102 switch.add_link(tgen.gears["r2"])
103 switch.add_link(tgen.gears["r3"])
104 switch.add_link(tgen.gears["r4"])
105 # Third switch
106 switch = tgen.add_switch("sw2")
107 switch.add_link(tgen.gears["r2"])
108 switch.add_link(tgen.gears["r3"])
f03e38f3 109
594b1259 110
1c333cbe
RW
111#####################################################
112##
113## Helper functions
114##
115#####################################################
116
117
118def router_compare_json_output(rname, command, reference, count=60, wait=1):
119 "Compare router JSON output"
120
121 logger.info('Comparing router "%s" "%s" output', rname, command)
122
123 tgen = get_topogen()
124 filename = "{}/{}/{}".format(CWD, rname, reference)
125 expected = json.loads(open(filename).read())
126
127 # Run test function until we get an result.
128 test_func = partial(topotest.router_json_cmp, tgen.gears[rname], command, expected)
129 _, diff = topotest.run_and_expect(test_func, None, count, wait)
130 assertmsg = '"{}" JSON output mismatches the expected result'.format(rname)
131 assert diff is None, assertmsg
132
133
f03e38f3
MW
134#####################################################
135##
136## Tests starting
137##
138#####################################################
139
6907ac7e 140
f03e38f3 141def setup_module(module):
f03e38f3
MW
142 print("\n\n** %s: Setup Topology" % module.__name__)
143 print("******************************************\n")
144
f03e38f3 145 thisDir = os.path.dirname(os.path.realpath(__file__))
e82b531d
CH
146 tgen = Topogen(build_topo, module.__name__)
147 tgen.start_topology()
f03e38f3 148
e82b531d 149 net = tgen.net
f03e38f3
MW
150
151 # Starting Routers
152 for i in range(1, 5):
787e7624 153 net["r%s" % i].loadConf("zebra", "%s/r%s/zebra.conf" % (thisDir, i))
154 net["r%s" % i].loadConf("ospfd", "%s/r%s/ospfd.conf" % (thisDir, i))
155 net["r%s" % i].loadConf("ldpd", "%s/r%s/ldpd.conf" % (thisDir, i))
e82b531d 156 tgen.gears["r%s" % i].start()
f03e38f3 157
622c4996 158 # For debugging after starting FRR daemons, uncomment the next line
a1985a2d 159 # tgen.mininet_cli()
f03e38f3 160
787e7624 161
f03e38f3 162def teardown_module(module):
f03e38f3
MW
163 print("\n\n** %s: Shutdown Topology" % module.__name__)
164 print("******************************************\n")
e82b531d
CH
165 tgen = get_topogen()
166 tgen.stop_topology()
f03e38f3
MW
167
168
594b1259 169def test_router_running():
f03e38f3 170 global fatal_error
e82b531d 171 net = get_topogen().net
f03e38f3
MW
172
173 # Skip if previous fatal error condition is raised
787e7624 174 if fatal_error != "":
f03e38f3
MW
175 pytest.skip(fatal_error)
176
622c4996 177 print("\n\n** Check if FRR is running on each Router node")
f03e38f3
MW
178 print("******************************************\n")
179 sleep(5)
180
181 # Starting Routers
182 for i in range(1, 5):
787e7624 183 fatal_error = net["r%s" % i].checkRouterRunning()
594b1259 184 assert fatal_error == "", fatal_error
f03e38f3 185
787e7624 186
f03e38f3
MW
187def test_mpls_interfaces():
188 global fatal_error
e82b531d 189 net = get_topogen().net
f03e38f3
MW
190
191 # Skip if previous fatal error condition is raised
787e7624 192 if fatal_error != "":
f03e38f3
MW
193 pytest.skip(fatal_error)
194
195 thisDir = os.path.dirname(os.path.realpath(__file__))
196
b290da1d 197 # Verify MPLS Interfaces
b2764f90 198 print("\n\n** Verifying MPLS Interfaces")
f03e38f3
MW
199 print("******************************************\n")
200 failures = 0
201 for i in range(1, 5):
787e7624 202 refTableFile = "%s/r%s/show_mpls_ldp_interface.ref"
f03e38f3
MW
203 if os.path.isfile(refTableFile):
204 # Read expected result from file
205 expected = open(refTableFile).read().rstrip()
206 # Fix newlines (make them all the same)
787e7624 207 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
f03e38f3
MW
208
209 # Actual output from router
787e7624 210 actual = (
211 net["r%s" % i]
212 .cmd('vtysh -c "show mpls ldp interface" 2> /dev/null')
213 .rstrip()
214 )
f03e38f3
MW
215 # Mask out Timer in Uptime
216 actual = re.sub(r" [0-9][0-9]:[0-9][0-9]:[0-9][0-9] ", " xx:xx:xx ", actual)
217 # Fix newlines (make them all the same)
787e7624 218 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
f03e38f3
MW
219
220 # Generate Diff
787e7624 221 diff = topotest.get_textdiff(
222 actual,
223 expected,
17070436 224 title1="actual MPLS LDP interface status",
787e7624 225 title2="expected MPLS LDP interface status",
226 )
f03e38f3
MW
227
228 # Empty string if it matches, otherwise diff contains unified diff
229 if diff:
787e7624 230 sys.stderr.write(
231 "r%s failed MPLS LDP Interface status Check:\n%s\n" % (i, diff)
232 )
f03e38f3
MW
233 failures += 1
234 else:
235 print("r%s ok" % i)
236
787e7624 237 if failures > 0:
594b1259
MW
238 fatal_error = "MPLS LDP Interface status failed"
239
787e7624 240 assert (
241 failures == 0
242 ), "MPLS LDP Interface status failed for router r%s:\n%s" % (i, diff)
f03e38f3 243
7e7fc73b
MW
244 # Make sure that all daemons are running
245 for i in range(1, 5):
787e7624 246 fatal_error = net["r%s" % i].checkRouterRunning()
7e7fc73b
MW
247 assert fatal_error == "", fatal_error
248
f03e38f3 249
1c333cbe
RW
250def test_ospf_convergence():
251 logger.info("Test: check OSPF adjacencies")
252
253 # Skip if previous fatal error condition is raised
254 if fatal_error != "":
255 pytest.skip(fatal_error)
256
257 for rname in ["r1", "r2", "r3", "r4"]:
258 router_compare_json_output(
259 rname, "show ip ospf neighbor json", "show_ip_ospf_neighbor.json"
260 )
261
262
f03e38f3
MW
263def test_mpls_ldp_neighbor_establish():
264 global fatal_error
e82b531d 265 net = get_topogen().net
f03e38f3
MW
266
267 # Skip if previous fatal error condition is raised
787e7624 268 if fatal_error != "":
f03e38f3
MW
269 pytest.skip(fatal_error)
270
e5369c47
DS
271 neighbors_operational = {
272 1: 1,
273 2: 3,
274 3: 2,
275 4: 2,
276 }
277
b290da1d 278 # Wait for MPLS LDP neighbors to establish.
f03e38f3
MW
279 print("\n\n** Verify MPLS LDP neighbors to establish")
280 print("******************************************\n")
281 timeout = 90
282 while timeout > 0:
283 print("Timeout in %s: " % timeout),
284 sys.stdout.flush()
285 # Look for any node not yet converged
286 for i in range(1, 5):
787e7624 287 established = (
288 net["r%s" % i]
289 .cmd('vtysh -c "show mpls ldp neighbor" 2> /dev/null')
290 .rstrip()
291 )
e29f8d0d
RW
292
293 # On current version, we need to make sure they all turn to OPERATIONAL on all lines
294 #
787e7624 295 lines = ("\n".join(established.splitlines()) + "\n").splitlines(1)
e29f8d0d 296 # Check all lines to be either table header (starting with ^AF or show OPERATIONAL)
787e7624 297 header = r"^AF.*"
298 operational = r"^ip.*OPERATIONAL.*"
e29f8d0d
RW
299 found_operational = 0
300 for j in range(1, len(lines)):
787e7624 301 if (not re.search(header, lines[j])) and (
302 not re.search(operational, lines[j])
303 ):
3eaafbd9 304 established = "" # Empty string shows NOT established
e29f8d0d
RW
305 if re.search(operational, lines[j]):
306 found_operational += 1
e5369c47
DS
307
308 logger.info("Found operational %d" % found_operational)
e29f8d0d
RW
309 if found_operational < 1:
310 # Need at least one operational neighbor
311 established = "" # Empty string shows NOT established
e5369c47
DS
312 else:
313 if found_operational != neighbors_operational[i]:
314 established = ""
f03e38f3 315 if not established:
787e7624 316 print("Waiting for r%s" % i)
f03e38f3
MW
317 sys.stdout.flush()
318 break
319 if not established:
320 sleep(5)
321 timeout -= 5
322 else:
787e7624 323 print("Done")
f03e38f3
MW
324 break
325 else:
326 # Bail out with error if a router fails to converge
327 fatal_error = "MPLS LDP neighbors did not establish"
d7d21c3a 328 assert False, "MPLS LDP neighbors did not establish"
f03e38f3
MW
329
330 print("MPLS LDP neighbors established.")
331
332 if timeout < 60:
333 # Only wait if we actually went through a convergence
334 print("\nwaiting 15s for LDP sessions to establish")
335 sleep(15)
787e7624 336
7e7fc73b
MW
337 # Make sure that all daemons are running
338 for i in range(1, 5):
787e7624 339 fatal_error = net["r%s" % i].checkRouterRunning()
7e7fc73b
MW
340 assert fatal_error == "", fatal_error
341
f03e38f3
MW
342
343def test_mpls_ldp_discovery():
344 global fatal_error
e82b531d 345 net = get_topogen().net
f03e38f3
MW
346
347 # Skip if previous fatal error condition is raised
787e7624 348 if fatal_error != "":
f03e38f3
MW
349 pytest.skip(fatal_error)
350
351 thisDir = os.path.dirname(os.path.realpath(__file__))
352
b290da1d 353 # Verify MPLS LDP discovery
b2764f90 354 print("\n\n** Verifying MPLS LDP discovery")
f03e38f3
MW
355 print("******************************************\n")
356 failures = 0
357 for i in range(1, 5):
787e7624 358 refTableFile = "%s/r%s/show_mpls_ldp_discovery.ref" % (thisDir, i)
f03e38f3 359 if os.path.isfile(refTableFile):
3eaafbd9 360 # Actual output from router
787e7624 361 actual = (
362 net["r%s" % i]
363 .cmd('vtysh -c "show mpls ldp discovery" 2> /dev/null')
364 .rstrip()
365 )
3eaafbd9 366
f03e38f3
MW
367 # Read expected result from file
368 expected = open(refTableFile).read().rstrip()
369 # Fix newlines (make them all the same)
787e7624 370 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
f03e38f3
MW
371
372 # Actual output from router
787e7624 373 actual = (
374 net["r%s" % i]
375 .cmd('vtysh -c "show mpls ldp discovery" 2> /dev/null')
376 .rstrip()
377 )
f03e38f3
MW
378
379 # Fix newlines (make them all the same)
787e7624 380 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
f03e38f3
MW
381
382 # Generate Diff
787e7624 383 diff = topotest.get_textdiff(
384 actual,
385 expected,
17070436 386 title1="actual MPLS LDP discovery output",
787e7624 387 title2="expected MPLS LDP discovery output",
388 )
f03e38f3
MW
389
390 # Empty string if it matches, otherwise diff contains unified diff
391 if diff:
787e7624 392 sys.stderr.write(
393 "r%s failed MPLS LDP discovery output Check:\n%s\n" % (i, diff)
394 )
f03e38f3
MW
395 failures += 1
396 else:
397 print("r%s ok" % i)
398
787e7624 399 assert (
400 failures == 0
401 ), "MPLS LDP Interface discovery output for router r%s:\n%s" % (i, diff)
f03e38f3 402
7e7fc73b
MW
403 # Make sure that all daemons are running
404 for i in range(1, 5):
787e7624 405 fatal_error = net["r%s" % i].checkRouterRunning()
7e7fc73b
MW
406 assert fatal_error == "", fatal_error
407
f03e38f3
MW
408
409def test_mpls_ldp_neighbor():
410 global fatal_error
e82b531d 411 net = get_topogen().net
f03e38f3
MW
412
413 # Skip if previous fatal error condition is raised
787e7624 414 if fatal_error != "":
f03e38f3
MW
415 pytest.skip(fatal_error)
416
417 thisDir = os.path.dirname(os.path.realpath(__file__))
418
b290da1d 419 # Verify MPLS LDP neighbor
b2764f90 420 print("\n\n** Verifying MPLS LDP neighbor")
f03e38f3
MW
421 print("******************************************\n")
422 failures = 0
423 for i in range(1, 5):
787e7624 424 refTableFile = "%s/r%s/show_mpls_ldp_neighbor.ref" % (thisDir, i)
f03e38f3
MW
425 if os.path.isfile(refTableFile):
426 # Read expected result from file
427 expected = open(refTableFile).read().rstrip()
428 # Fix newlines (make them all the same)
787e7624 429 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
f03e38f3
MW
430
431 # Actual output from router
787e7624 432 actual = (
433 net["r%s" % i]
434 .cmd('vtysh -c "show mpls ldp neighbor" 2> /dev/null')
435 .rstrip()
436 )
3eaafbd9
MW
437
438 # Mask out changing parts in output
e29f8d0d 439 # Mask out Timer in Uptime
787e7624 440 actual = re.sub(
441 r"(ipv4 [0-9\.]+ +OPERATIONAL [0-9\.]+ +)[0-9][0-9]:[0-9][0-9]:[0-9][0-9]",
442 r"\1xx:xx:xx",
443 actual,
444 )
f03e38f3
MW
445
446 # Fix newlines (make them all the same)
787e7624 447 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
f03e38f3
MW
448
449 # Generate Diff
787e7624 450 diff = topotest.get_textdiff(
451 actual,
452 expected,
17070436 453 title1="actual MPLS LDP neighbor output",
787e7624 454 title2="expected MPLS LDP neighbor output",
455 )
f03e38f3
MW
456
457 # Empty string if it matches, otherwise diff contains unified diff
458 if diff:
787e7624 459 sys.stderr.write(
460 "r%s failed MPLS LDP neighbor output Check:\n%s\n" % (i, diff)
461 )
f03e38f3
MW
462 failures += 1
463 else:
464 print("r%s ok" % i)
465
787e7624 466 assert (
467 failures == 0
468 ), "MPLS LDP Interface neighbor output for router r%s:\n%s" % (i, diff)
f03e38f3 469
7e7fc73b
MW
470 # Make sure that all daemons are running
471 for i in range(1, 5):
787e7624 472 fatal_error = net["r%s" % i].checkRouterRunning()
7e7fc73b
MW
473 assert fatal_error == "", fatal_error
474
f03e38f3
MW
475
476def test_mpls_ldp_binding():
477 global fatal_error
e82b531d 478 net = get_topogen().net
f03e38f3
MW
479
480 # Skip this test for now until proper sorting of the output
481 # is implemented
482 # pytest.skip("Skipping test_mpls_ldp_binding")
483
484 # Skip if previous fatal error condition is raised
787e7624 485 if fatal_error != "":
f03e38f3
MW
486 pytest.skip(fatal_error)
487
488 thisDir = os.path.dirname(os.path.realpath(__file__))
489
b290da1d 490 # Verify MPLS LDP binding
b2764f90 491 print("\n\n** Verifying MPLS LDP binding")
f03e38f3
MW
492 print("******************************************\n")
493 failures = 0
494 for i in range(1, 5):
787e7624 495 refTableFile = "%s/r%s/show_mpls_ldp_binding.ref" % (thisDir, i)
f03e38f3
MW
496 if os.path.isfile(refTableFile):
497 # Read expected result from file
498 expected = open(refTableFile).read().rstrip()
499 # Fix newlines (make them all the same)
787e7624 500 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
f03e38f3
MW
501
502 # Actual output from router
787e7624 503 actual = (
504 net["r%s" % i]
505 .cmd('vtysh -c "show mpls ldp binding" 2> /dev/null')
506 .rstrip()
507 )
3eaafbd9
MW
508
509 # Mask out changing parts in output
e29f8d0d 510 # Mask out label
787e7624 511 actual = re.sub(
512 r"(ipv4 [0-9\./]+ +[0-9\.]+ +)[0-9][0-9] (.*)", r"\1xxx\2", actual
513 )
514 actual = re.sub(
515 r"(ipv4 [0-9\./]+ +[0-9\.]+ +[a-z\-]+ +)[0-9][0-9] (.*)",
516 r"\1xxx\2",
517 actual,
518 )
3eaafbd9 519
f03e38f3 520 # Fix newlines (make them all the same)
787e7624 521 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
f03e38f3
MW
522
523 # Sort lines which start with "xx via inet "
787e7624 524 pattern = r"^\s+[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\s+"
f03e38f3
MW
525 swapped = True
526 while swapped:
527 swapped = False
528 for j in range(1, len(actual)):
787e7624 529 if re.search(pattern, actual[j]) and re.search(
530 pattern, actual[j - 1]
531 ):
532 if actual[j - 1] > actual[j]:
533 temp = actual[j - 1]
534 actual[j - 1] = actual[j]
f03e38f3
MW
535 actual[j] = temp
536 swapped = True
537
538 # Generate Diff
787e7624 539 diff = topotest.get_textdiff(
540 actual,
541 expected,
17070436 542 title1="actual MPLS LDP binding output",
787e7624 543 title2="expected MPLS LDP binding output",
544 )
f03e38f3
MW
545
546 # Empty string if it matches, otherwise diff contains unified diff
547 if diff:
787e7624 548 sys.stderr.write(
549 "r%s failed MPLS LDP binding output Check:\n%s\n" % (i, diff)
550 )
f03e38f3
MW
551 failures += 1
552 else:
553 print("r%s ok" % i)
554
1c333cbe
RW
555 assert failures == 0, "MPLS LDP binding output for router r%s:\n%s" % (
556 i,
557 diff,
558 )
f03e38f3 559
7e7fc73b
MW
560 # Make sure that all daemons are running
561 for i in range(1, 5):
787e7624 562 fatal_error = net["r%s" % i].checkRouterRunning()
7e7fc73b
MW
563 assert fatal_error == "", fatal_error
564
f03e38f3
MW
565
566def test_zebra_ipv4_routingTable():
567 global fatal_error
e82b531d 568 net = get_topogen().net
f03e38f3
MW
569
570 # Skip if previous fatal error condition is raised
787e7624 571 if fatal_error != "":
f03e38f3
MW
572 pytest.skip(fatal_error)
573
574 thisDir = os.path.dirname(os.path.realpath(__file__))
575
b290da1d 576 # Verify Zebra IPv4 Routing Table
b2764f90 577 print("\n\n** Verifying Zebra IPv4 Routing Table")
f03e38f3
MW
578 print("******************************************\n")
579 failures = 0
580 for i in range(1, 5):
787e7624 581 refTableFile = "%s/r%s/show_ipv4_route.ref" % (thisDir, i)
f03e38f3
MW
582 if os.path.isfile(refTableFile):
583 # Read expected result from file
584 expected = open(refTableFile).read().rstrip()
f03e38f3
MW
585
586 # Actual output from router
787e7624 587 actual = (
588 net["r%s" % i]
589 .cmd('vtysh -c "show ip route" 2> /dev/null | grep "^O"')
590 .rstrip()
591 )
622c4996 592 # Drop timers on end of line
f03e38f3 593 actual = re.sub(r", [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", "", actual)
6c97c0cb
MW
594
595 # Mask out label - all LDP labels should be >= 10 (2-digit)
596 # leaving the implicit labels unmasked
597 actual = re.sub(r" label [0-9][0-9]+", " label xxx", actual)
be7286cc
MW
598 # and translating remaining implicit (single-digit) labels to label implicit-null
599 actual = re.sub(r" label [0-9]+", " label implicit-null", actual)
6c97c0cb 600 # Check if we have implicit labels - if not, then remove them from reference
787e7624 601 if not re.search(r" label implicit-null", actual):
be7286cc 602 expected = re.sub(r", label implicit-null", "", expected)
6c97c0cb
MW
603
604 # now fix newlines of expected (make them all the same)
787e7624 605 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
6c97c0cb 606
f03e38f3 607 # Fix newlines (make them all the same)
787e7624 608 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
f03e38f3
MW
609
610 # Generate Diff
787e7624 611 diff = topotest.get_textdiff(
612 actual,
613 expected,
17070436 614 title1="actual IPv4 zebra routing table",
787e7624 615 title2="expected IPv4 zebra routing table",
616 )
f03e38f3
MW
617
618 # Empty string if it matches, otherwise diff contains unified diff
619 if diff:
787e7624 620 sys.stderr.write(
621 "r%s failed IPv4 Zebra Routing Table Check:\n%s\n" % (i, diff)
622 )
f03e38f3
MW
623 failures += 1
624 else:
625 print("r%s ok" % i)
626
9fa6ec14 627 assert (
628 failures == 0
629 ), "IPv4 Zebra Routing Table verification failed for router r%s:\n%s" % (
630 i,
631 diff,
787e7624 632 )
f03e38f3 633
7e7fc73b
MW
634 # Make sure that all daemons are running
635 for i in range(1, 5):
787e7624 636 fatal_error = net["r%s" % i].checkRouterRunning()
7e7fc73b
MW
637 assert fatal_error == "", fatal_error
638
f03e38f3
MW
639
640def test_mpls_table():
641 global fatal_error
e82b531d 642 net = get_topogen().net
f03e38f3
MW
643
644 # Skip if previous fatal error condition is raised
787e7624 645 if fatal_error != "":
f03e38f3
MW
646 pytest.skip(fatal_error)
647
648 thisDir = os.path.dirname(os.path.realpath(__file__))
649
b290da1d 650 # Verify MPLS table
b2764f90 651 print("\n\n** Verifying MPLS table")
f03e38f3
MW
652 print("******************************************\n")
653 failures = 0
d01e89f1 654
f03e38f3 655 for i in range(1, 5):
787e7624 656 refTableFile = "%s/r%s/show_mpls_table.ref" % (thisDir, i)
f03e38f3
MW
657 if os.path.isfile(refTableFile):
658 # Read expected result from file
a971aeb6 659 expected = open(refTableFile).read()
f03e38f3 660 # Fix newlines (make them all the same)
787e7624 661 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
f03e38f3
MW
662
663 # Actual output from router
787e7624 664 actual = net["r%s" % i].cmd('vtysh -c "show mpls table" 2> /dev/null')
b290da1d 665
f03e38f3
MW
666 # Fix inconsistent Label numbers at beginning of line
667 actual = re.sub(r"(\s+)[0-9]+(\s+LDP)", r"\1XX\2", actual)
668 # Fix inconsistent Label numbers at end of line
787e7624 669 actual = re.sub(
670 r"(\s+[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\s+)[0-9][0-9]", r"\1XX", actual
671 )
f03e38f3
MW
672
673 # Fix newlines (make them all the same)
787e7624 674 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
f03e38f3
MW
675
676 # Sort lines which start with " XX LDP"
787e7624 677 pattern = r"^\s+[0-9X]+\s+LDP"
f03e38f3
MW
678 swapped = True
679 while swapped:
680 swapped = False
681 for j in range(1, len(actual)):
787e7624 682 if re.search(pattern, actual[j]) and re.search(
683 pattern, actual[j - 1]
684 ):
685 if actual[j - 1] > actual[j]:
686 temp = actual[j - 1]
687 actual[j - 1] = actual[j]
f03e38f3
MW
688 actual[j] = temp
689 swapped = True
690
691 # Generate Diff
787e7624 692 diff = topotest.get_textdiff(
693 actual,
694 expected,
17070436 695 title1="actual MPLS table output",
787e7624 696 title2="expected MPLS table output",
697 )
f03e38f3
MW
698
699 # Empty string if it matches, otherwise diff contains unified diff
700 if diff:
787e7624 701 sys.stderr.write(
702 "r%s failed MPLS table output Check:\n%s\n" % (i, diff)
703 )
f03e38f3
MW
704 failures += 1
705 else:
706 print("r%s ok" % i)
707
708 assert failures == 0, "MPLS table output for router r%s:\n%s" % (i, diff)
709
7e7fc73b
MW
710 # Make sure that all daemons are running
711 for i in range(1, 5):
787e7624 712 fatal_error = net["r%s" % i].checkRouterRunning()
7e7fc73b
MW
713 assert fatal_error == "", fatal_error
714
f03e38f3
MW
715
716def test_linux_mpls_routes():
717 global fatal_error
e82b531d 718 net = get_topogen().net
f03e38f3 719
787e7624 720 # Skip if previous fatal error condition is raised
721 if fatal_error != "":
f03e38f3
MW
722 pytest.skip(fatal_error)
723
724 thisDir = os.path.dirname(os.path.realpath(__file__))
725
b290da1d 726 # Verify Linux Kernel MPLS routes
b2764f90 727 print("\n\n** Verifying Linux Kernel MPLS routes")
f03e38f3
MW
728 print("******************************************\n")
729 failures = 0
730 for i in range(1, 5):
787e7624 731 refTableFile = "%s/r%s/ip_mpls_route.ref" % (thisDir, i)
f03e38f3
MW
732 if os.path.isfile(refTableFile):
733 # Read expected result from file
734 expected = open(refTableFile).read().rstrip()
735 # Fix newlines (make them all the same)
787e7624 736 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
f03e38f3
MW
737
738 # Actual output from router
787e7624 739 actual = (
740 net["r%s" % i].cmd("ip -o -family mpls route 2> /dev/null").rstrip()
741 )
3a103f9a
CF
742
743 # Mask out label and protocol
f03e38f3 744 actual = re.sub(r"[0-9][0-9] via inet ", "xx via inet ", actual)
3a103f9a 745 actual = re.sub(r"[0-9][0-9] +proto", "xx proto", actual)
f03e38f3 746 actual = re.sub(r"[0-9][0-9] as to ", "xx as to ", actual)
dd3ddc06 747 actual = re.sub(r"[ ]+proto \w+", " proto xx", actual)
f03e38f3 748
3a103f9a
CF
749 # Sort nexthops
750 nexthop_sorted = []
751 for line in actual.splitlines():
787e7624 752 tokens = re.split(r"\\\t", line.strip())
753 nexthop_sorted.append(
754 "{} {}".format(
755 tokens[0].strip(),
756 " ".join([token.strip() for token in sorted(tokens[1:])]),
757 ).strip()
758 )
3a103f9a
CF
759
760 # Sort lines and fixup differences between old and new iproute
787e7624 761 actual = "\n".join(sorted(nexthop_sorted))
3a103f9a
CF
762 actual = re.sub(r"nexthop via", "nexthopvia", actual)
763 actual = re.sub(r" nexthop as to xx via inet ", " nexthopvia inet ", actual)
764 actual = re.sub(r" weight 1", "", actual)
765 actual = re.sub(r" [ ]+", " ", actual)
f03e38f3 766
f03e38f3 767 # put \n back at line ends
787e7624 768 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
f03e38f3
MW
769
770 # Generate Diff
787e7624 771 diff = topotest.get_textdiff(
772 actual,
773 expected,
17070436 774 title1="actual Linux Kernel MPLS route",
787e7624 775 title2="expected Linux Kernel MPLS route",
776 )
f03e38f3
MW
777
778 # Empty string if it matches, otherwise diff contains unified diff
779 if diff:
787e7624 780 sys.stderr.write(
781 "r%s failed Linux Kernel MPLS route output Check:\n%s\n" % (i, diff)
782 )
f03e38f3
MW
783 failures += 1
784 else:
785 print("r%s ok" % i)
786
787e7624 787 assert (
788 failures == 0
789 ), "Linux Kernel MPLS route output for router r%s:\n%s" % (i, diff)
f03e38f3 790
7e7fc73b
MW
791 # Make sure that all daemons are running
792 for i in range(1, 5):
787e7624 793 fatal_error = net["r%s" % i].checkRouterRunning()
7e7fc73b
MW
794 assert fatal_error == "", fatal_error
795
f03e38f3 796
99561211
MW
797def test_shutdown_check_stderr():
798 global fatal_error
e82b531d 799 net = get_topogen().net
99561211
MW
800
801 # Skip if previous fatal error condition is raised
787e7624 802 if fatal_error != "":
99561211
MW
803 pytest.skip(fatal_error)
804
787e7624 805 if os.environ.get("TOPOTESTS_CHECK_STDERR") is None:
806 print(
807 "SKIPPED final check on StdErr output: Disabled (TOPOTESTS_CHECK_STDERR undefined)\n"
808 )
809 pytest.skip("Skipping test for Stderr output")
99561211
MW
810
811 thisDir = os.path.dirname(os.path.realpath(__file__))
812
b2764f90 813 print("\n\n** Verifying unexpected STDERR output from daemons")
99561211
MW
814 print("******************************************\n")
815
816 for i in range(1, 5):
787e7624 817 net["r%s" % i].stopRouter()
818 log = net["r%s" % i].getStdErr("ldpd")
8e957dbb
MW
819 if log:
820 print("\nRouter r%s LDPd StdErr Log:\n%s" % (i, log))
787e7624 821 log = net["r%s" % i].getStdErr("ospfd")
8e957dbb
MW
822 if log:
823 print("\nRouter r%s OSPFd StdErr Log:\n%s" % (i, log))
787e7624 824 log = net["r%s" % i].getStdErr("zebra")
8e957dbb
MW
825 if log:
826 print("\nRouter r%s Zebra StdErr Log:\n%s" % (i, log))
99561211
MW
827
828
50c40bde
MW
829def test_shutdown_check_memleak():
830 global fatal_error
e82b531d 831 net = get_topogen().net
50c40bde
MW
832
833 # Skip if previous fatal error condition is raised
787e7624 834 if fatal_error != "":
50c40bde
MW
835 pytest.skip(fatal_error)
836
787e7624 837 if os.environ.get("TOPOTESTS_CHECK_MEMLEAK") is None:
838 print(
839 "SKIPPED final check on Memory leaks: Disabled (TOPOTESTS_CHECK_MEMLEAK undefined)\n"
840 )
841 pytest.skip("Skipping test for memory leaks")
842
50c40bde
MW
843 thisDir = os.path.dirname(os.path.realpath(__file__))
844
845 for i in range(1, 5):
787e7624 846 net["r%s" % i].stopRouter()
847 net["r%s" % i].report_memory_leaks(
848 os.environ.get("TOPOTESTS_CHECK_MEMLEAK"), os.path.basename(__file__)
849 )
50c40bde 850
99561211 851
787e7624 852if __name__ == "__main__":
f03e38f3 853
f03e38f3
MW
854 # To suppress tracebacks, either use the following pytest call or add "--tb=no" to cli
855 # retval = pytest.main(["-s", "--tb=no"])
856 retval = pytest.main(["-s"])
857 sys.exit(retval)