]> git.proxmox.com Git - mirror_frr.git/blame - tests/topotests/ldp-topo1/test_ldp_topo1.py
bgp_l3vpn_to_bgp_direct: use new ltemplate common functions
[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
25"""
26test_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 \ / \
55r3-eth1 .3 | | .3 r3-eth0 | .4 r4-eth0
56 +----+--+---+ +----+----+
57 | r3 | | r4 |
58 | 3.3.3.3 | | 4.4.4.4 |
59 +-----------+ +---------+
60"""
61
62import os
63import re
64import sys
594b1259
MW
65import pytest
66from time import sleep
f03e38f3
MW
67
68from mininet.topo import Topo
69from mininet.net import Mininet
70from mininet.node import Node, OVSSwitch, Host
71from mininet.log import setLogLevel, info
72from mininet.cli import CLI
73from mininet.link import Intf
74
594b1259
MW
75sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
76from lib import topotest
f03e38f3
MW
77
78fatal_error = ""
79
3eaafbd9
MW
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)
83cli_version = ""
84
85
f03e38f3
MW
86#####################################################
87##
88## Network Topology Definition
89##
90#####################################################
91
92class NetworkTopo(Topo):
594b1259 93 "LDP Test Topology 1"
f03e38f3
MW
94
95 def build(self, **_opts):
96
f03e38f3
MW
97 # Setup Routers
98 router = {}
99 for i in range(1, 5):
594b1259 100 router[i] = topotest.addRouter(self, 'r%s' % i)
f03e38f3 101
594b1259 102 # Setup Switches, add Interfaces and Connections
f03e38f3
MW
103 switch = {}
104 # First switch
594b1259 105 switch[0] = self.addSwitch('sw0', cls=topotest.LegacySwitch)
f03e38f3
MW
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
594b1259 109 switch[1] = self.addSwitch('sw1', cls=topotest.LegacySwitch)
f03e38f3
MW
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
594b1259 114 switch[2] = self.addSwitch('sw2', cls=topotest.LegacySwitch)
f03e38f3
MW
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
594b1259 118
f03e38f3
MW
119#####################################################
120##
121## Tests starting
122##
123#####################################################
124
125def setup_module(module):
126 global topo, net
594b1259 127 global fatal_error
f03e38f3
MW
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))
594b1259
MW
146 fatal_error = net['r%s' % i].startRouter()
147
148 if fatal_error != "":
149 break
f03e38f3
MW
150
151 # For debugging after starting FRR/Quagga daemons, uncomment the next line
152 # CLI(net)
153
154def 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
594b1259 164def test_router_running():
f03e38f3
MW
165 global fatal_error
166 global net
3eaafbd9 167 global cli_version
f03e38f3
MW
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):
594b1259
MW
179 fatal_error = net['r%s' % i].checkRouterRunning()
180 assert fatal_error == "", fatal_error
f03e38f3 181
3eaafbd9
MW
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
594b1259
MW
204 # For debugging after starting FRR/Quagga daemons, uncomment the next line
205 # CLI(net)
f03e38f3
MW
206
207def test_mpls_interfaces():
208 global fatal_error
209 global net
3eaafbd9 210 global cli_version
f03e38f3
MW
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
b2764f90 219 print("\n\n** Verifying MPLS Interfaces")
f03e38f3
MW
220 print("******************************************\n")
221 failures = 0
222 for i in range(1, 5):
3eaafbd9 223 refTableFile = '%s/r%s/show_mpls_ldp_interface.ref%s' % (thisDir, i, cli_version)
f03e38f3
MW
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
17070436
MW
238 diff = topotest.get_textdiff(actual, expected,
239 title1="actual MPLS LDP interface status",
240 title2="expected MPLS LDP interface status")
f03e38f3
MW
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
594b1259
MW
249 if failures>0:
250 fatal_error = "MPLS LDP Interface status failed"
251
f03e38f3
MW
252 assert failures == 0, "MPLS LDP Interface status failed for router r%s:\n%s" % (i, diff)
253
7e7fc73b
MW
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
f03e38f3
MW
259 # For debugging after starting FRR/Quagga daemons, uncomment the next line
260 # CLI(net)
261
262
263def test_mpls_ldp_neighbor_establish():
264 global fatal_error
265 global net
3eaafbd9 266 global cli_version
f03e38f3
MW
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):
3eaafbd9
MW
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
f03e38f3
MW
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
7e7fc73b
MW
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
f03e38f3
MW
325
326def test_mpls_ldp_discovery():
327 global fatal_error
328 global net
3eaafbd9 329 global cli_version
f03e38f3
MW
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
b2764f90 338 print("\n\n** Verifying MPLS LDP discovery")
f03e38f3
MW
339 print("******************************************\n")
340 failures = 0
341 for i in range(1, 5):
3eaafbd9 342 refTableFile = '%s/r%s/show_mpls_ldp_discovery.ref%s' % (thisDir, i, cli_version)
f03e38f3 343 if os.path.isfile(refTableFile):
3eaafbd9
MW
344 # Actual output from router
345 actual = net['r%s' % i].cmd('vtysh -c "show mpls ldp discovery" 2> /dev/null').rstrip()
346
f03e38f3
MW
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
17070436
MW
359 diff = topotest.get_textdiff(actual, expected,
360 title1="actual MPLS LDP discovery output",
361 title2="expected MPLS LDP discovery output")
f03e38f3
MW
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
7e7fc73b
MW
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
f03e38f3
MW
377 # For debugging after starting FRR/Quagga daemons, uncomment the next line
378 # CLI(net)
379
380
381def test_mpls_ldp_neighbor():
382 global fatal_error
383 global net
3eaafbd9 384 global cli_version
f03e38f3
MW
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
b2764f90 393 print("\n\n** Verifying MPLS LDP neighbor")
f03e38f3
MW
394 print("******************************************\n")
395 failures = 0
396 for i in range(1, 5):
3eaafbd9 397 refTableFile = '%s/r%s/show_mpls_ldp_neighbor.ref%s' % (thisDir, i, cli_version)
f03e38f3
MW
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()
3eaafbd9
MW
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)
f03e38f3
MW
419
420 # Fix newlines (make them all the same)
421 actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
422
423 # Generate Diff
17070436
MW
424 diff = topotest.get_textdiff(actual, expected,
425 title1="actual MPLS LDP neighbor output",
426 title2="expected MPLS LDP neighbor output")
f03e38f3
MW
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
7e7fc73b
MW
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
f03e38f3
MW
442 # For debugging after starting FRR/Quagga daemons, uncomment the next line
443 #CLI(net)
444
445
446def test_mpls_ldp_binding():
447 global fatal_error
448 global net
3eaafbd9 449 global cli_version
f03e38f3
MW
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
b2764f90 462 print("\n\n** Verifying MPLS LDP binding")
f03e38f3
MW
463 print("******************************************\n")
464 failures = 0
465 for i in range(1, 5):
3eaafbd9 466 refTableFile = '%s/r%s/show_mpls_ldp_binding.ref%s' % (thisDir, i, cli_version)
f03e38f3
MW
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()
3eaafbd9
MW
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
f03e38f3
MW
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
17070436
MW
505 diff = topotest.get_textdiff(actual, expected,
506 title1="actual MPLS LDP binding output",
507 title2="expected MPLS LDP binding output")
f03e38f3
MW
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
7e7fc73b
MW
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
f03e38f3
MW
523 # For debugging after starting FRR/Quagga daemons, uncomment the next line
524 #CLI(net)
525
526
527def test_zebra_ipv4_routingTable():
528 global fatal_error
529 global net
3eaafbd9 530 global cli_version
f03e38f3
MW
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
b2764f90 539 print("\n\n** Verifying Zebra IPv4 Routing Table")
f03e38f3
MW
540 print("******************************************\n")
541 failures = 0
542 for i in range(1, 5):
3eaafbd9 543 refTableFile = '%s/r%s/show_ipv4_route.ref%s' % (thisDir, i, cli_version)
f03e38f3
MW
544 if os.path.isfile(refTableFile):
545 # Read expected result from file
546 expected = open(refTableFile).read().rstrip()
f03e38f3
MW
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)
6c97c0cb
MW
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)
be7286cc
MW
556 # and translating remaining implicit (single-digit) labels to label implicit-null
557 actual = re.sub(r" label [0-9]+", " label implicit-null", actual)
6c97c0cb 558 # Check if we have implicit labels - if not, then remove them from reference
be7286cc
MW
559 if (not re.search(r" label implicit-null", actual)):
560 expected = re.sub(r", label implicit-null", "", expected)
6c97c0cb
MW
561
562 # now fix newlines of expected (make them all the same)
563 expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1)
564
faf94e5a 565 # Add missing comma before label (for old version)
6c97c0cb 566 actual = re.sub(r"([0-9]) label ", r"\1, label ", actual)
f03e38f3
MW
567
568 # Fix newlines (make them all the same)
569 actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
570
571 # Generate Diff
17070436
MW
572 diff = topotest.get_textdiff(actual, expected,
573 title1="actual IPv4 zebra routing table",
574 title2="expected IPv4 zebra routing table")
f03e38f3
MW
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
7e7fc73b
MW
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
f03e38f3
MW
590 # For debugging after starting FRR/Quagga daemons, uncomment the next line
591 # CLI(net)
592
593
594def test_mpls_table():
595 global fatal_error
596 global net
3eaafbd9 597 global cli_version
f03e38f3
MW
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
b2764f90 606 print("\n\n** Verifying MPLS table")
f03e38f3
MW
607 print("******************************************\n")
608 failures = 0
609 for i in range(1, 5):
3eaafbd9 610 refTableFile = '%s/r%s/show_mpls_table.ref%s' % (thisDir, i, cli_version)
f03e38f3
MW
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
17070436
MW
642 diff = topotest.get_textdiff(actual, expected,
643 title1="actual MPLS table output",
644 title2="expected MPLS table output")
f03e38f3
MW
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
7e7fc73b
MW
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
f03e38f3
MW
660 # For debugging after starting FRR/Quagga daemons, uncomment the next line
661 # CLI(net)
662
663
664def test_linux_mpls_routes():
665 global fatal_error
666 global net
3eaafbd9 667 global cli_version
f03e38f3
MW
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
b2764f90 676 print("\n\n** Verifying Linux Kernel MPLS routes")
f03e38f3
MW
677 print("******************************************\n")
678 failures = 0
679 for i in range(1, 5):
3eaafbd9 680 refTableFile = '%s/r%s/ip_mpls_route.ref%s' % (thisDir, i, cli_version)
f03e38f3
MW
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)
13e8bc06 691 actual = re.sub(r"[0-9][0-9] proto", "xx proto", actual)
f03e38f3 692 actual = re.sub(r"[0-9][0-9] as to ", "xx as to ", actual)
dd3ddc06 693 actual = re.sub(r"[ ]+proto \w+", " proto xx", actual)
f03e38f3
MW
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
17070436
MW
746 diff = topotest.get_textdiff(actual, expected,
747 title1="actual Linux Kernel MPLS route",
748 title2="expected Linux Kernel MPLS route")
f03e38f3
MW
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
7e7fc73b
MW
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
f03e38f3
MW
764 # For debugging after starting FRR/Quagga daemons, uncomment the next line
765 # CLI(net)
766
767
99561211
MW
768def 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:
50c40bde
MW
777 print("SKIPPED final check on StdErr output: Disabled (TOPOTESTS_CHECK_STDERR undefined)\n")
778 pytest.skip('Skipping test for Stderr output')
99561211
MW
779
780 thisDir = os.path.dirname(os.path.realpath(__file__))
781
b2764f90 782 print("\n\n** Verifying unexpected STDERR output from daemons")
99561211
MW
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')
8e957dbb
MW
788 if log:
789 print("\nRouter r%s LDPd StdErr Log:\n%s" % (i, log))
99561211 790 log = net['r%s' % i].getStdErr('ospfd')
8e957dbb
MW
791 if log:
792 print("\nRouter r%s OSPFd StdErr Log:\n%s" % (i, log))
99561211 793 log = net['r%s' % i].getStdErr('zebra')
8e957dbb
MW
794 if log:
795 print("\nRouter r%s Zebra StdErr Log:\n%s" % (i, log))
99561211
MW
796
797
50c40bde
MW
798def test_shutdown_check_memleak():
799 global fatal_error
800 global net
801
802 # Skip if previous fatal error condition is raised
803 if (fatal_error != ""):
804 pytest.skip(fatal_error)
805
806 if os.environ.get('TOPOTESTS_CHECK_MEMLEAK') is None:
807 print("SKIPPED final check on Memory leaks: Disabled (TOPOTESTS_CHECK_MEMLEAK undefined)\n")
808 pytest.skip('Skipping test for memory leaks')
809
810 thisDir = os.path.dirname(os.path.realpath(__file__))
811
812 for i in range(1, 5):
813 net['r%s' % i].stopRouter()
814 net['r%s' % i].report_memory_leaks(os.environ.get('TOPOTESTS_CHECK_MEMLEAK'), os.path.basename(__file__))
815
99561211 816
f03e38f3
MW
817if __name__ == '__main__':
818
819 setLogLevel('info')
820 # To suppress tracebacks, either use the following pytest call or add "--tb=no" to cli
821 # retval = pytest.main(["-s", "--tb=no"])
822 retval = pytest.main(["-s"])
823 sys.exit(retval)