]> git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/ldp-topo1/test_ldp_topo1.py
ldp-topo1: Make the implicit label optional to pass old frr code as well
[mirror_frr.git] / tests / topotests / ldp-topo1 / test_ldp_topo1.py
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
25 """
26 test_ldp_topo1.py: Simple FRR/Quagga LDP Test
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 \ / \
55 r3-eth1 .3 | | .3 r3-eth0 | .4 r4-eth0
56 +----+--+---+ +----+----+
57 | r3 | | r4 |
58 | 3.3.3.3 | | 4.4.4.4 |
59 +-----------+ +---------+
60 """
61
62 import os
63 import re
64 import sys
65 import pytest
66 from time import sleep
67
68 from mininet.topo import Topo
69 from mininet.net import Mininet
70 from mininet.node import Node, OVSSwitch, Host
71 from mininet.log import setLogLevel, info
72 from mininet.cli import CLI
73 from mininet.link import Intf
74
75 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
76 from lib import topotest
77
78 fatal_error = ""
79
80 # Expected version of CLI Output - Appendix to filename
81 # empty string = current, latest output (default)
82 # "-1" ... "-NNN" previous versions (incrementing with each version)
83 cli_version = ""
84
85
86 #####################################################
87 ##
88 ## Network Topology Definition
89 ##
90 #####################################################
91
92 class NetworkTopo(Topo):
93 "LDP Test Topology 1"
94
95 def build(self, **_opts):
96
97 # Setup Routers
98 router = {}
99 for i in range(1, 5):
100 router[i] = topotest.addRouter(self, 'r%s' % i)
101
102 # Setup Switches, add Interfaces and Connections
103 switch = {}
104 # First switch
105 switch[0] = self.addSwitch('sw0', cls=topotest.LegacySwitch)
106 self.addLink(switch[0], router[1], intfName2='r1-eth0', addr1='80:AA:00:00:00:00', addr2='00:11:00:01:00:00')
107 self.addLink(switch[0], router[2], intfName2='r2-eth0', addr1='80:AA:00:00:00:01', addr2='00:11:00:02:00:00')
108 # Second switch
109 switch[1] = self.addSwitch('sw1', cls=topotest.LegacySwitch)
110 self.addLink(switch[1], router[2], intfName2='r2-eth1', addr1='80:AA:00:01:00:00', addr2='00:11:00:02:00:01')
111 self.addLink(switch[1], router[3], intfName2='r3-eth0', addr1='80:AA:00:01:00:01', addr2='00:11:00:03:00:00')
112 self.addLink(switch[1], router[4], intfName2='r4-eth0', addr1='80:AA:00:01:00:02', addr2='00:11:00:04:00:00')
113 # Third switch
114 switch[2] = self.addSwitch('sw2', cls=topotest.LegacySwitch)
115 self.addLink(switch[2], router[2], intfName2='r2-eth2', addr1='80:AA:00:02:00:00', addr2='00:11:00:02:00:02')
116 self.addLink(switch[2], router[3], intfName2='r3-eth1', addr1='80:AA:00:02:00:01', addr2='00:11:00:03:00:01')
117
118
119 #####################################################
120 ##
121 ## Tests starting
122 ##
123 #####################################################
124
125 def setup_module(module):
126 global topo, net
127 global fatal_error
128
129 print("\n\n** %s: Setup Topology" % module.__name__)
130 print("******************************************\n")
131
132 print("Cleanup old Mininet runs")
133 os.system('sudo mn -c > /dev/null 2>&1')
134
135 thisDir = os.path.dirname(os.path.realpath(__file__))
136 topo = NetworkTopo()
137
138 net = Mininet(controller=None, topo=topo)
139 net.start()
140
141 # Starting Routers
142 for i in range(1, 5):
143 net['r%s' % i].loadConf('zebra', '%s/r%s/zebra.conf' % (thisDir, i))
144 net['r%s' % i].loadConf('ospfd', '%s/r%s/ospfd.conf' % (thisDir, i))
145 net['r%s' % i].loadConf('ldpd', '%s/r%s/ldpd.conf' % (thisDir, i))
146 fatal_error = net['r%s' % i].startRouter()
147
148 if fatal_error != "":
149 break
150
151 # For debugging after starting FRR/Quagga daemons, uncomment the next line
152 # CLI(net)
153
154 def teardown_module(module):
155 global net
156
157 print("\n\n** %s: Shutdown Topology" % module.__name__)
158 print("******************************************\n")
159
160 # End - Shutdown network
161 net.stop()
162
163
164 def test_router_running():
165 global fatal_error
166 global net
167 global cli_version
168
169 # Skip if previous fatal error condition is raised
170 if (fatal_error != ""):
171 pytest.skip(fatal_error)
172
173 print("\n\n** Check if FRR/Quagga is running on each Router node")
174 print("******************************************\n")
175 sleep(5)
176
177 # Starting Routers
178 for i in range(1, 5):
179 fatal_error = net['r%s' % i].checkRouterRunning()
180 assert fatal_error == "", fatal_error
181
182 # Detect CLI Version
183 # At this time, there are only 2 possible outputs, so simple check
184 output = net['r1'].cmd('vtysh -c "show mpls ldp discovery" 2> /dev/null').rstrip()
185
186 # Check if old or new format of CLI Output. Default is to current format
187 #
188 # Old (v1) output looks like this:
189 # Local LDP Identifier: 1.1.1.1:0
190 # Discovery Sources:
191 # Interfaces:
192 # r1-eth0: xmit/recv
193 # LDP Id: 2.2.2.2:0, Transport address: 2.2.2.2
194 # Hold time: 15 sec
195 # Targeted Hellos:
196 #
197 # Current (v0) output looks like this:
198 # AF ID Type Source Holdtime
199 # ipv4 2.2.2.2 Link r1-eth0 15
200 pattern = re.compile("^Local LDP Identifier.*")
201 if pattern.match(output):
202 cli_version = "-1"
203
204 # For debugging after starting FRR/Quagga daemons, uncomment the next line
205 # CLI(net)
206
207 def test_mpls_interfaces():
208 global fatal_error
209 global net
210 global cli_version
211
212 # Skip if previous fatal error condition is raised
213 if (fatal_error != ""):
214 pytest.skip(fatal_error)
215
216 thisDir = os.path.dirname(os.path.realpath(__file__))
217
218 # Verify OSPFv3 Routing Table
219 print("\n\n** Verifying MPLS Interfaces")
220 print("******************************************\n")
221 failures = 0
222 for i in range(1, 5):
223 refTableFile = '%s/r%s/show_mpls_ldp_interface.ref%s' % (thisDir, i, cli_version)
224 if os.path.isfile(refTableFile):
225 # Read expected result from file
226 expected = open(refTableFile).read().rstrip()
227 # Fix newlines (make them all the same)
228 expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1)
229
230 # Actual output from router
231 actual = net['r%s' % i].cmd('vtysh -c "show mpls ldp interface" 2> /dev/null').rstrip()
232 # Mask out Timer in Uptime
233 actual = re.sub(r" [0-9][0-9]:[0-9][0-9]:[0-9][0-9] ", " xx:xx:xx ", actual)
234 # Fix newlines (make them all the same)
235 actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
236
237 # Generate Diff
238 diff = topotest.get_textdiff(actual, expected,
239 title1="actual MPLS LDP interface status",
240 title2="expected MPLS LDP interface status")
241
242 # Empty string if it matches, otherwise diff contains unified diff
243 if diff:
244 sys.stderr.write('r%s failed MPLS LDP Interface status Check:\n%s\n' % (i, diff))
245 failures += 1
246 else:
247 print("r%s ok" % i)
248
249 if failures>0:
250 fatal_error = "MPLS LDP Interface status failed"
251
252 assert failures == 0, "MPLS LDP Interface status failed for router r%s:\n%s" % (i, diff)
253
254 # Make sure that all daemons are running
255 for i in range(1, 5):
256 fatal_error = net['r%s' % i].checkRouterRunning()
257 assert fatal_error == "", fatal_error
258
259 # For debugging after starting FRR/Quagga daemons, uncomment the next line
260 # CLI(net)
261
262
263 def test_mpls_ldp_neighbor_establish():
264 global fatal_error
265 global net
266 global cli_version
267
268 # Skip if previous fatal error condition is raised
269 if (fatal_error != ""):
270 pytest.skip(fatal_error)
271
272 # Wait for OSPF6 to converge (All Neighbors in either Full or TwoWay State)
273 print("\n\n** Verify MPLS LDP neighbors to establish")
274 print("******************************************\n")
275 timeout = 90
276 while timeout > 0:
277 print("Timeout in %s: " % timeout),
278 sys.stdout.flush()
279 # Look for any node not yet converged
280 for i in range(1, 5):
281 established = net['r%s' % i].cmd('vtysh -c "show mpls ldp neighbor" 2> /dev/null').rstrip()
282 if cli_version != "-1":
283 # On current version, we need to make sure they all turn to OPERATIONAL on all lines
284 #
285 lines = ('\n'.join(established.splitlines()) + '\n').splitlines(1)
286 # Check all lines to be either table header (starting with ^AF or show OPERATIONAL)
287 header = r'^AF.*'
288 operational = r'^ip.*OPERATIONAL.*'
289 found_operational = 0
290 for j in range(1, len(lines)):
291 if (not re.search(header, lines[j])) and (not re.search(operational, lines[j])):
292 established = "" # Empty string shows NOT established
293 if re.search(operational, lines[j]):
294 found_operational += 1
295 if found_operational < 1:
296 # Need at least one operational neighbor
297 established = "" # Empty string shows NOT established
298 if not established:
299 print('Waiting for r%s' %i)
300 sys.stdout.flush()
301 break
302 if not established:
303 sleep(5)
304 timeout -= 5
305 else:
306 print('Done')
307 break
308 else:
309 # Bail out with error if a router fails to converge
310 fatal_error = "MPLS LDP neighbors did not establish"
311 assert False, "MPLS LDP neighbors did not establish" % ospfStatus
312
313 print("MPLS LDP neighbors established.")
314
315 if timeout < 60:
316 # Only wait if we actually went through a convergence
317 print("\nwaiting 15s for LDP sessions to establish")
318 sleep(15)
319
320 # Make sure that all daemons are running
321 for i in range(1, 5):
322 fatal_error = net['r%s' % i].checkRouterRunning()
323 assert fatal_error == "", fatal_error
324
325
326 def test_mpls_ldp_discovery():
327 global fatal_error
328 global net
329 global cli_version
330
331 # Skip if previous fatal error condition is raised
332 if (fatal_error != ""):
333 pytest.skip(fatal_error)
334
335 thisDir = os.path.dirname(os.path.realpath(__file__))
336
337 # Verify OSPFv3 Routing Table
338 print("\n\n** Verifying MPLS LDP discovery")
339 print("******************************************\n")
340 failures = 0
341 for i in range(1, 5):
342 refTableFile = '%s/r%s/show_mpls_ldp_discovery.ref%s' % (thisDir, i, cli_version)
343 if os.path.isfile(refTableFile):
344 # Actual output from router
345 actual = net['r%s' % i].cmd('vtysh -c "show mpls ldp discovery" 2> /dev/null').rstrip()
346
347 # Read expected result from file
348 expected = open(refTableFile).read().rstrip()
349 # Fix newlines (make them all the same)
350 expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1)
351
352 # Actual output from router
353 actual = net['r%s' % i].cmd('vtysh -c "show mpls ldp discovery" 2> /dev/null').rstrip()
354
355 # Fix newlines (make them all the same)
356 actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
357
358 # Generate Diff
359 diff = topotest.get_textdiff(actual, expected,
360 title1="actual MPLS LDP discovery output",
361 title2="expected MPLS LDP discovery output")
362
363 # Empty string if it matches, otherwise diff contains unified diff
364 if diff:
365 sys.stderr.write('r%s failed MPLS LDP discovery output Check:\n%s\n' % (i, diff))
366 failures += 1
367 else:
368 print("r%s ok" % i)
369
370 assert failures == 0, "MPLS LDP Interface discovery output for router r%s:\n%s" % (i, diff)
371
372 # Make sure that all daemons are running
373 for i in range(1, 5):
374 fatal_error = net['r%s' % i].checkRouterRunning()
375 assert fatal_error == "", fatal_error
376
377 # For debugging after starting FRR/Quagga daemons, uncomment the next line
378 # CLI(net)
379
380
381 def test_mpls_ldp_neighbor():
382 global fatal_error
383 global net
384 global cli_version
385
386 # Skip if previous fatal error condition is raised
387 if (fatal_error != ""):
388 pytest.skip(fatal_error)
389
390 thisDir = os.path.dirname(os.path.realpath(__file__))
391
392 # Verify OSPFv3 Routing Table
393 print("\n\n** Verifying MPLS LDP neighbor")
394 print("******************************************\n")
395 failures = 0
396 for i in range(1, 5):
397 refTableFile = '%s/r%s/show_mpls_ldp_neighbor.ref%s' % (thisDir, i, cli_version)
398 if os.path.isfile(refTableFile):
399 # Read expected result from file
400 expected = open(refTableFile).read().rstrip()
401 # Fix newlines (make them all the same)
402 expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1)
403
404 # Actual output from router
405 actual = net['r%s' % i].cmd('vtysh -c "show mpls ldp neighbor" 2> /dev/null').rstrip()
406
407 # Mask out changing parts in output
408 if cli_version == "-1":
409 # Mask out Timer in Uptime
410 actual = re.sub(r"Up time: [0-9][0-9]:[0-9][0-9]:[0-9][0-9]", "Up time: xx:xx:xx", actual)
411 # Mask out Port numbers in TCP connection
412 actual = re.sub(r"TCP connection: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]):[0-9]+ - ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]):[0-9]+",
413 r"TCP connection: \1:xxx - \2:xxx", actual)
414 else:
415 # Current Version
416 #
417 # Mask out Timer in Uptime
418 actual = re.sub(r"(ipv4 [0-9\.]+ +OPERATIONAL [0-9\.]+ +)[0-9][0-9]:[0-9][0-9]:[0-9][0-9]", r"\1xx:xx:xx", actual)
419
420 # Fix newlines (make them all the same)
421 actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
422
423 # Generate Diff
424 diff = topotest.get_textdiff(actual, expected,
425 title1="actual MPLS LDP neighbor output",
426 title2="expected MPLS LDP neighbor output")
427
428 # Empty string if it matches, otherwise diff contains unified diff
429 if diff:
430 sys.stderr.write('r%s failed MPLS LDP neighbor output Check:\n%s\n' % (i, diff))
431 failures += 1
432 else:
433 print("r%s ok" % i)
434
435 assert failures == 0, "MPLS LDP Interface neighbor output for router r%s:\n%s" % (i, diff)
436
437 # Make sure that all daemons are running
438 for i in range(1, 5):
439 fatal_error = net['r%s' % i].checkRouterRunning()
440 assert fatal_error == "", fatal_error
441
442 # For debugging after starting FRR/Quagga daemons, uncomment the next line
443 #CLI(net)
444
445
446 def test_mpls_ldp_binding():
447 global fatal_error
448 global net
449 global cli_version
450
451 # Skip this test for now until proper sorting of the output
452 # is implemented
453 # pytest.skip("Skipping test_mpls_ldp_binding")
454
455 # Skip if previous fatal error condition is raised
456 if (fatal_error != ""):
457 pytest.skip(fatal_error)
458
459 thisDir = os.path.dirname(os.path.realpath(__file__))
460
461 # Verify OSPFv3 Routing Table
462 print("\n\n** Verifying MPLS LDP binding")
463 print("******************************************\n")
464 failures = 0
465 for i in range(1, 5):
466 refTableFile = '%s/r%s/show_mpls_ldp_binding.ref%s' % (thisDir, i, cli_version)
467 if os.path.isfile(refTableFile):
468 # Read expected result from file
469 expected = open(refTableFile).read().rstrip()
470 # Fix newlines (make them all the same)
471 expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1)
472
473 # Actual output from router
474 actual = net['r%s' % i].cmd('vtysh -c "show mpls ldp binding" 2> /dev/null').rstrip()
475
476 # Mask out changing parts in output
477 if cli_version == "-1":
478 # Mask out label
479 actual = re.sub(r"label: [0-9]+", "label: xxx", actual)
480 actual = re.sub(r"(\s+[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+[ ]+)[0-9]+", r"\1xxx", actual)
481 else:
482 # Current Version
483 #
484 # Mask out label
485 actual = re.sub(r"(ipv4 [0-9\./]+ +[0-9\.]+ +)[0-9][0-9] (.*)", r"\1xxx\2", actual)
486 actual = re.sub(r"(ipv4 [0-9\./]+ +[0-9\.]+ +[a-z\-]+ +)[0-9][0-9] (.*)", r"\1xxx\2", actual)
487
488 # Fix newlines (make them all the same)
489 actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
490
491 # Sort lines which start with "xx via inet "
492 pattern = r'^\s+[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\s+'
493 swapped = True
494 while swapped:
495 swapped = False
496 for j in range(1, len(actual)):
497 if re.search(pattern, actual[j]) and re.search(pattern, actual[j-1]):
498 if actual[j-1] > actual[j]:
499 temp = actual[j-1]
500 actual[j-1] = actual[j]
501 actual[j] = temp
502 swapped = True
503
504 # Generate Diff
505 diff = topotest.get_textdiff(actual, expected,
506 title1="actual MPLS LDP binding output",
507 title2="expected MPLS LDP binding output")
508
509 # Empty string if it matches, otherwise diff contains unified diff
510 if diff:
511 sys.stderr.write('r%s failed MPLS LDP binding output Check:\n%s\n' % (i, diff))
512 failures += 1
513 else:
514 print("r%s ok" % i)
515
516 assert failures == 0, "MPLS LDP Interface binding output for router r%s:\n%s" % (i, diff)
517
518 # Make sure that all daemons are running
519 for i in range(1, 5):
520 fatal_error = net['r%s' % i].checkRouterRunning()
521 assert fatal_error == "", fatal_error
522
523 # For debugging after starting FRR/Quagga daemons, uncomment the next line
524 #CLI(net)
525
526
527 def test_zebra_ipv4_routingTable():
528 global fatal_error
529 global net
530 global cli_version
531
532 # Skip if previous fatal error condition is raised
533 if (fatal_error != ""):
534 pytest.skip(fatal_error)
535
536 thisDir = os.path.dirname(os.path.realpath(__file__))
537
538 # Verify OSPFv3 Routing Table
539 print("\n\n** Verifying Zebra IPv4 Routing Table")
540 print("******************************************\n")
541 failures = 0
542 for i in range(1, 5):
543 refTableFile = '%s/r%s/show_ipv4_route.ref%s' % (thisDir, i, cli_version)
544 if os.path.isfile(refTableFile):
545 # Read expected result from file
546 expected = open(refTableFile).read().rstrip()
547
548 # Actual output from router
549 actual = net['r%s' % i].cmd('vtysh -c "show ip route" 2> /dev/null | grep "^O"').rstrip()
550 # Drop timers on end of line (older Quagga Versions)
551 actual = re.sub(r", [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", "", actual)
552
553 # Mask out label - all LDP labels should be >= 10 (2-digit)
554 # leaving the implicit labels unmasked
555 actual = re.sub(r" label [0-9][0-9]+", " label xxx", actual)
556 # and translating remaining implicit (single-digit) labels to label y
557 actual = re.sub(r" label [0-9]+", " label y", actual)
558 # Check if we have implicit labels - if not, then remove them from reference
559 if (not re.search(r" label y", actual)):
560 expected = re.sub(r", label y", "", expected)
561
562 # now fix newlines of expected (make them all the same)
563 expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1)
564
565 # Add missing comma before label (for old version)
566 actual = re.sub(r"([0-9]) label ", r"\1, label ", actual)
567
568 # Fix newlines (make them all the same)
569 actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
570
571 # Generate Diff
572 diff = topotest.get_textdiff(actual, expected,
573 title1="actual IPv4 zebra routing table",
574 title2="expected IPv4 zebra routing table")
575
576 # Empty string if it matches, otherwise diff contains unified diff
577 if diff:
578 sys.stderr.write('r%s failed IPv4 Zebra Routing Table Check:\n%s\n' % (i, diff))
579 failures += 1
580 else:
581 print("r%s ok" % i)
582
583 assert failures == 0, "IPv4 Zebra Routing Table verification failed for router r%s:\n%s" % (i, diff)
584
585 # Make sure that all daemons are running
586 for i in range(1, 5):
587 fatal_error = net['r%s' % i].checkRouterRunning()
588 assert fatal_error == "", fatal_error
589
590 # For debugging after starting FRR/Quagga daemons, uncomment the next line
591 # CLI(net)
592
593
594 def test_mpls_table():
595 global fatal_error
596 global net
597 global cli_version
598
599 # Skip if previous fatal error condition is raised
600 if (fatal_error != ""):
601 pytest.skip(fatal_error)
602
603 thisDir = os.path.dirname(os.path.realpath(__file__))
604
605 # Verify OSPFv3 Routing Table
606 print("\n\n** Verifying MPLS table")
607 print("******************************************\n")
608 failures = 0
609 for i in range(1, 5):
610 refTableFile = '%s/r%s/show_mpls_table.ref%s' % (thisDir, i, cli_version)
611 if os.path.isfile(refTableFile):
612 # Read expected result from file
613 expected = open(refTableFile).read().rstrip()
614 # Fix newlines (make them all the same)
615 expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1)
616
617 # Actual output from router
618 actual = net['r%s' % i].cmd('vtysh -c "show mpls table" 2> /dev/null').rstrip()
619
620 # Fix inconsistent Label numbers at beginning of line
621 actual = re.sub(r"(\s+)[0-9]+(\s+LDP)", r"\1XX\2", actual)
622 # Fix inconsistent Label numbers at end of line
623 actual = re.sub(r"(\s+[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\s+)[0-9][0-9]", r"\1XX", actual)
624
625 # Fix newlines (make them all the same)
626 actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
627
628 # Sort lines which start with " XX LDP"
629 pattern = r'^\s+[0-9X]+\s+LDP'
630 swapped = True
631 while swapped:
632 swapped = False
633 for j in range(1, len(actual)):
634 if re.search(pattern, actual[j]) and re.search(pattern, actual[j-1]):
635 if actual[j-1] > actual[j]:
636 temp = actual[j-1]
637 actual[j-1] = actual[j]
638 actual[j] = temp
639 swapped = True
640
641 # Generate Diff
642 diff = topotest.get_textdiff(actual, expected,
643 title1="actual MPLS table output",
644 title2="expected MPLS table output")
645
646 # Empty string if it matches, otherwise diff contains unified diff
647 if diff:
648 sys.stderr.write('r%s failed MPLS table output Check:\n%s\n' % (i, diff))
649 failures += 1
650 else:
651 print("r%s ok" % i)
652
653 assert failures == 0, "MPLS table output for router r%s:\n%s" % (i, diff)
654
655 # Make sure that all daemons are running
656 for i in range(1, 5):
657 fatal_error = net['r%s' % i].checkRouterRunning()
658 assert fatal_error == "", fatal_error
659
660 # For debugging after starting FRR/Quagga daemons, uncomment the next line
661 # CLI(net)
662
663
664 def test_linux_mpls_routes():
665 global fatal_error
666 global net
667 global cli_version
668
669 # Skip if previous fatal error condition is raised
670 if (fatal_error != ""):
671 pytest.skip(fatal_error)
672
673 thisDir = os.path.dirname(os.path.realpath(__file__))
674
675 # Verify OSPFv3 Routing Table
676 print("\n\n** Verifying Linux Kernel MPLS routes")
677 print("******************************************\n")
678 failures = 0
679 for i in range(1, 5):
680 refTableFile = '%s/r%s/ip_mpls_route.ref%s' % (thisDir, i, cli_version)
681 if os.path.isfile(refTableFile):
682 # Read expected result from file
683 expected = open(refTableFile).read().rstrip()
684 # Fix newlines (make them all the same)
685 expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1)
686
687 # Actual output from router
688 actual = net['r%s' % i].cmd('ip -family mpls route 2> /dev/null').rstrip()
689 # Mask out label
690 actual = re.sub(r"[0-9][0-9] via inet ", "xx via inet ", actual)
691 actual = re.sub(r"[0-9][0-9] proto zebra", "xx proto zebra", actual)
692 actual = re.sub(r"[0-9][0-9] as to ", "xx as to ", actual)
693 actual = re.sub(r"proto zebra ", "proto zebra", actual)
694
695 # Fix newlines (make them all the same)
696 actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
697
698 # Sort lines which start with "xx via inet "
699 pattern = r'^xx via inet '
700 swapped = True
701 while swapped:
702 swapped = False
703 for j in range(1, len(actual)):
704 if re.search(pattern, actual[j]) and re.search(pattern, actual[j-1]):
705 if actual[j-1] > actual[j]:
706 temp = actual[j-1]
707 actual[j-1] = actual[j]
708 actual[j] = temp
709 swapped = True
710
711 # Sort lines which start with " nexthopvia"
712 pattern = r'^\snexthopvia '
713 swapped = True
714 while swapped:
715 swapped = False
716 for j in range(1, len(actual)):
717 if re.search(pattern, actual[j]) and re.search(pattern, actual[j-1]):
718 if actual[j-1] > actual[j]:
719 temp = actual[j-1]
720 actual[j-1] = actual[j]
721 actual[j] = temp
722 swapped = True
723
724 # Sort Sections of "xx proto zebra" (with all the indented lines below)
725 pattern = r'^xx via inet '
726 # Join paragraphs first
727 j = 0
728 temp = [actual[0].rstrip()]
729 for k in range(1, len(actual)):
730 if re.search(r'^\s', actual[k]):
731 # Continue line
732 temp[j] += '\n' + actual[k].rstrip()
733 else:
734 j += 1
735 temp.append(actual[k].rstrip())
736 # sort Array
737 temp.sort()
738 # Now write sort array back
739 actual = []
740 for k in range(0, len(temp)):
741 actual.extend(temp[k].splitlines())
742 # put \n back at line ends
743 actual = ('\n'.join(actual) + '\n').splitlines(1)
744
745 # Generate Diff
746 diff = topotest.get_textdiff(actual, expected,
747 title1="actual Linux Kernel MPLS route",
748 title2="expected Linux Kernel MPLS route")
749
750 # Empty string if it matches, otherwise diff contains unified diff
751 if diff:
752 sys.stderr.write('r%s failed Linux Kernel MPLS route output Check:\n%s\n' % (i, diff))
753 failures += 1
754 else:
755 print("r%s ok" % i)
756
757 assert failures == 0, "Linux Kernel MPLS route output for router r%s:\n%s" % (i, diff)
758
759 # Make sure that all daemons are running
760 for i in range(1, 5):
761 fatal_error = net['r%s' % i].checkRouterRunning()
762 assert fatal_error == "", fatal_error
763
764 # For debugging after starting FRR/Quagga daemons, uncomment the next line
765 # CLI(net)
766
767
768 def test_shutdown_check_stderr():
769 global fatal_error
770 global net
771
772 # Skip if previous fatal error condition is raised
773 if (fatal_error != ""):
774 pytest.skip(fatal_error)
775
776 if os.environ.get('TOPOTESTS_CHECK_STDERR') is None:
777 print("SKIPPED final check on StdErr output: Disabled (TOPOTESTS_CHECK_STDERR undefined)\n")
778 pytest.skip('Skipping test for Stderr output')
779
780 thisDir = os.path.dirname(os.path.realpath(__file__))
781
782 print("\n\n** Verifying unexpected STDERR output from daemons")
783 print("******************************************\n")
784
785 for i in range(1, 5):
786 net['r%s' % i].stopRouter()
787 log = net['r%s' % i].getStdErr('ldpd')
788 print("\nRouter r%s LDPd StdErr Log:\n%s" % (i, log))
789 log = net['r%s' % i].getStdErr('ospfd')
790 print("\nRouter r%s OSPFd StdErr Log:\n%s" % (i, log))
791 log = net['r%s' % i].getStdErr('zebra')
792 print("\nRouter r%s Zebra StdErr Log:\n%s" % (i, log))
793
794
795 def test_shutdown_check_memleak():
796 global fatal_error
797 global net
798
799 # Skip if previous fatal error condition is raised
800 if (fatal_error != ""):
801 pytest.skip(fatal_error)
802
803 if os.environ.get('TOPOTESTS_CHECK_MEMLEAK') is None:
804 print("SKIPPED final check on Memory leaks: Disabled (TOPOTESTS_CHECK_MEMLEAK undefined)\n")
805 pytest.skip('Skipping test for memory leaks')
806
807 thisDir = os.path.dirname(os.path.realpath(__file__))
808
809 for i in range(1, 5):
810 net['r%s' % i].stopRouter()
811 net['r%s' % i].report_memory_leaks(os.environ.get('TOPOTESTS_CHECK_MEMLEAK'), os.path.basename(__file__))
812
813
814 if __name__ == '__main__':
815
816 setLogLevel('info')
817 # To suppress tracebacks, either use the following pytest call or add "--tb=no" to cli
818 # retval = pytest.main(["-s", "--tb=no"])
819 retval = pytest.main(["-s"])
820 sys.exit(retval)