]> git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/all-protocol-startup/test_all_protocol_startup.py
tests: add basic nexthop group functionality test
[mirror_frr.git] / tests / topotests / all-protocol-startup / test_all_protocol_startup.py
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
33 import pytest
34 import glob
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
58 class NetworkTopo(Topo):
59 "All Protocol Startup Test"
60
61 def build(self, **_opts):
62
63 # Setup Routers
64 router = {}
65 #
66 # Setup Main Router
67 router[1] = topotest.addRouter(self, 'r1')
68 #
69
70 # Setup Switches
71 switch = {}
72 #
73 for i in range(0, 10):
74 switch[i] = self.addSwitch('sw%s' % i, cls=topotest.LegacySwitch)
75 self.addLink(switch[i], router[1], intfName2='r1-eth%s' % i )
76
77
78 #####################################################
79 ##
80 ## Tests starting
81 ##
82 #####################################################
83
84 def setup_module(module):
85 global topo, net
86 global fatal_error
87
88 print("\n\n** %s: Setup Topology" % module.__name__)
89 print("******************************************\n")
90
91 print("Cleanup old Mininet runs")
92 os.system('sudo mn -c > /dev/null 2>&1')
93 os.system('sudo rm /tmp/r* > /dev/null 2>&1')
94
95 thisDir = os.path.dirname(os.path.realpath(__file__))
96 topo = NetworkTopo()
97
98 net = Mininet(controller=None, topo=topo)
99 net.start()
100
101 if net['r1'].get_routertype() != 'frr':
102 fatal_error = "Test is only implemented for FRR"
103 sys.stderr.write('\n\nTest is only implemented for FRR - Skipping\n\n')
104 pytest.skip(fatal_error)
105
106 # Starting Routers
107 #
108 # Main router
109 for i in range(1, 2):
110 net['r%s' % i].loadConf('zebra', '%s/r%s/zebra.conf' % (thisDir, i))
111 net['r%s' % i].loadConf('ripd', '%s/r%s/ripd.conf' % (thisDir, i))
112 net['r%s' % i].loadConf('ripngd', '%s/r%s/ripngd.conf' % (thisDir, i))
113 net['r%s' % i].loadConf('ospfd', '%s/r%s/ospfd.conf' % (thisDir, i))
114 if net['r1'].checkRouterVersion('<', '4.0'):
115 net['r%s' % i].loadConf('ospf6d', '%s/r%s/ospf6d.conf-pre-v4' % (thisDir, i))
116 else:
117 net['r%s' % i].loadConf('ospf6d', '%s/r%s/ospf6d.conf' % (thisDir, i))
118 net['r%s' % i].loadConf('isisd', '%s/r%s/isisd.conf' % (thisDir, i))
119 net['r%s' % i].loadConf('bgpd', '%s/r%s/bgpd.conf' % (thisDir, i))
120 if net['r%s' % i].daemon_available('ldpd'):
121 # Only test LDPd if it's installed and Kernel >= 4.5
122 net['r%s' % i].loadConf('ldpd', '%s/r%s/ldpd.conf' % (thisDir, i))
123 net['r%s' % i].loadConf('sharpd')
124 net['r%s' % i].startRouter()
125
126 # For debugging after starting Quagga/FRR daemons, uncomment the next line
127 # CLI(net)
128
129
130 def teardown_module(module):
131 global net
132
133 print("\n\n** %s: Shutdown Topology" % module.__name__)
134 print("******************************************\n")
135
136 # End - Shutdown network
137 net.stop()
138
139
140 def test_router_running():
141 global fatal_error
142 global net
143
144 # Skip if previous fatal error condition is raised
145 if (fatal_error != ""):
146 pytest.skip(fatal_error)
147
148 print("\n\n** Check if FRR/Quagga is running on each Router node")
149 print("******************************************\n")
150 sleep(5)
151
152 # Starting Routers
153 for i in range(1, 2):
154 fatal_error = net['r%s' % i].checkRouterRunning()
155 assert fatal_error == "", fatal_error
156
157 # For debugging after starting FRR/Quagga daemons, uncomment the next line
158 # CLI(net)
159
160
161 def test_error_messages_vtysh():
162 global fatal_error
163 global net
164
165 # Skip if previous fatal error condition is raised
166 if (fatal_error != ""):
167 pytest.skip(fatal_error)
168
169 print("\n\n** Check for error messages on VTYSH")
170 print("******************************************\n")
171
172 failures = 0
173 for i in range(1, 2):
174 #
175 # First checking Standard Output
176 #
177
178 # VTYSH output from router
179 vtystdout = net['r%s' % i].cmd('vtysh -c "show version" 2> /dev/null').rstrip()
180
181 # Fix newlines (make them all the same)
182 vtystdout = ('\n'.join(vtystdout.splitlines()) + '\n').rstrip()
183 # Drop everything starting with "FRRouting X.xx" message
184 vtystdout = re.sub(r"FRRouting [0-9]+.*", "", vtystdout, flags=re.DOTALL)
185
186 if (vtystdout == ''):
187 print("r%s StdOut ok" % i)
188
189 assert vtystdout == '', "Vtysh StdOut Output check failed for router r%s" % i
190
191 #
192 # Second checking Standard Error
193 #
194
195 # VTYSH StdErr output from router
196 vtystderr = net['r%s' % i].cmd('vtysh -c "show version" > /dev/null').rstrip()
197
198 # Fix newlines (make them all the same)
199 vtystderr = ('\n'.join(vtystderr.splitlines()) + '\n').rstrip()
200 # # Drop everything starting with "FRRouting X.xx" message
201 # vtystderr = re.sub(r"FRRouting [0-9]+.*", "", vtystderr, flags=re.DOTALL)
202
203 if (vtystderr == ''):
204 print("r%s StdErr ok" % i)
205
206 assert vtystderr == '', "Vtysh StdErr Output check failed for router r%s" % i
207
208 # Make sure that all daemons are running
209 for i in range(1, 2):
210 fatal_error = net['r%s' % i].checkRouterRunning()
211 assert fatal_error == "", fatal_error
212
213 # For debugging after starting FRR/Quagga daemons, uncomment the next line
214 # CLI(net)
215
216
217 def test_error_messages_daemons():
218 global fatal_error
219 global net
220
221 # Skip if previous fatal error condition is raised
222 if (fatal_error != ""):
223 pytest.skip(fatal_error)
224
225 print("\n\n** Check for error messages in daemons")
226 print("******************************************\n")
227
228 error_logs = ""
229
230 for i in range(1, 2):
231 log = net['r%s' % i].getStdErr('ripd')
232 if log:
233 error_logs += "r%s RIPd StdErr Output:\n" % i
234 error_logs += log
235 log = net['r%s' % i].getStdErr('ripngd')
236 if log:
237 error_logs += "r%s RIPngd StdErr Output:\n" % i
238 error_logs += log
239 log = net['r%s' % i].getStdErr('ospfd')
240 if log:
241 error_logs += "r%s OSPFd StdErr Output:\n" % i
242 error_logs += log
243 log = net['r%s' % i].getStdErr('ospf6d')
244 if log:
245 error_logs += "r%s OSPF6d StdErr Output:\n" % i
246 error_logs += log
247 log = net['r%s' % i].getStdErr('isisd')
248 # ISIS shows debugging enabled status on StdErr
249 # Remove these messages
250 log = re.sub(r"^IS-IS .* debugging is on.*", "", log).rstrip()
251 if log:
252 error_logs += "r%s ISISd StdErr Output:\n" % i
253 error_logs += log
254 log = net['r%s' % i].getStdErr('bgpd')
255 if log:
256 error_logs += "r%s BGPd StdErr Output:\n" % i
257 error_logs += log
258 if (net['r%s' % i].daemon_available('ldpd')):
259 log = net['r%s' % i].getStdErr('ldpd')
260 if log:
261 error_logs += "r%s LDPd StdErr Output:\n" % i
262 error_logs += log
263 log = net['r%s' % i].getStdErr('zebra')
264 if log:
265 error_logs += "r%s Zebra StdErr Output:\n"
266 error_logs += log
267
268 if error_logs:
269 sys.stderr.write('Failed check for StdErr Output on daemons:\n%s\n' % error_logs)
270
271 # Ignoring the issue if told to ignore (ie not yet fixed)
272 if (error_logs != ""):
273 if (os.environ.get('bamboo_TOPOTESTS_ISSUE_349') == "IGNORE"):
274 sys.stderr.write('Known issue - IGNORING. See https://github.com/FRRouting/frr/issues/349\n')
275 pytest.skip('Known issue - IGNORING. See https://github.com/FRRouting/frr/issues/349')
276
277 assert error_logs == "", "Daemons report errors to StdErr"
278
279 # For debugging after starting FRR/Quagga daemons, uncomment the next line
280 # CLI(net)
281
282
283 def test_converge_protocols():
284 global fatal_error
285 global net
286
287 # Skip if previous fatal error condition is raised
288 if (fatal_error != ""):
289 pytest.skip(fatal_error)
290
291 thisDir = os.path.dirname(os.path.realpath(__file__))
292
293 print("\n\n** Waiting for protocols convergence")
294 print("******************************************\n")
295
296 # Not really implemented yet - just sleep 60 secs for now
297 sleep(60)
298
299 # Make sure that all daemons are running
300 failures = 0
301 for i in range(1, 2):
302 fatal_error = net['r%s' % i].checkRouterRunning()
303 assert fatal_error == "", fatal_error
304
305 print("Show that v4 routes are right\n");
306 v4_routesFile = '%s/r%s/ipv4_routes.ref' % (thisDir, i)
307 expected = open(v4_routesFile).read().rstrip()
308 expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1)
309
310 actual = net['r%s' %i].cmd('vtysh -c "show ip route" | /usr/bin/tail -n +7 | sort 2> /dev/null').rstrip()
311 # Drop time in last update
312 actual = re.sub(r" [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", " XX:XX:XX", actual)
313 actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
314 diff = topotest.get_textdiff(actual, expected,
315 title1="Actual IP Routing Table",
316 title2="Expected IP RoutingTable")
317 if diff:
318 sys.stderr.write('r%s failed IP Routing table check:\n%s\n' % (i, diff))
319 failures += 1
320 else:
321 print("r%s ok" %i)
322
323 assert failures == 0, "IP Routing table failed for r%s\n%s" % (i, diff)
324
325 failures = 0
326
327 print("Show that v6 routes are right\n")
328 v6_routesFile = '%s/r%s/ipv6_routes.ref' % (thisDir, i)
329 expected = open(v6_routesFile).read().rstrip()
330 expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1)
331
332 actual = net['r%s' %i].cmd('vtysh -c "show ipv6 route" | /usr/bin/tail -n +7 | sort 2> /dev/null').rstrip()
333 # Drop time in last update
334 actual = re.sub(r" [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", " XX:XX:XX", actual)
335 actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
336 diff = topotest.get_textdiff(actual, expected,
337 title1="Actual IPv6 Routing Table",
338 title2="Expected IPv6 RoutingTable")
339 if diff:
340 sys.stderr.write('r%s failed IPv6 Routing table check:\n%s\n' % (i, diff))
341 failures += 1
342 else:
343 print("r%s ok" %i)
344
345 assert failures == 0, "IPv6 Routing table failed for r%s\n%s" % (i, diff)
346
347 # For debugging after starting FRR/Quagga daemons, uncomment the next line
348 ## CLI(net)
349
350 def test_nexthop_groups():
351 global fatal_error
352 global net
353
354 # Skip if previous fatal error condition is raised
355 if (fatal_error != ""):
356 pytest.skip(fatal_error)
357
358 print("\n\n** Verifying Nexthop Groups")
359 print("******************************************\n")
360
361 # Create a lib nexthop-group
362 net["r1"].cmd('vtysh -c "c t" -c "nexthop-group red" -c "nexthop 1.1.1.1" -c "nexthop 1.1.1.2"')
363
364 # Create with sharpd using nexthop-group
365 net["r1"].cmd('vtysh -c "sharp install routes 2.2.2.1 nexthop-group red 1"')
366
367 # Verify route and that zebra created NHGs for and they are valid/installed
368 output = net["r1"].cmd('vtysh -c "show ip route 2.2.2.1/32 nexthop-group"')
369 match = re.search(r"Nexthop Group ID: (\d+)", output);
370 assert match is not None, "Nexthop Group ID not found for sharpd route 2.2.2.1/32"
371
372 nhe_id = int(match.group(1))
373
374 output = net["r1"].cmd('vtysh -c "show nexthop-group rib %d"' % nhe_id)
375 match = re.search(r"Valid", output)
376 assert match is not None, "Nexthop Group ID=%d not marked Valid" % nhe_id
377
378 match = re.search(r"Installed", output)
379 assert match is not None, "Nexthop Group ID=%d not marked Installed" % nhe_id
380
381 def test_rip_status():
382 global fatal_error
383 global net
384
385 # Skip if previous fatal error condition is raised
386 if (fatal_error != ""):
387 pytest.skip(fatal_error)
388
389 thisDir = os.path.dirname(os.path.realpath(__file__))
390
391 print("\n\n** Verifying RIP status")
392 print("******************************************\n")
393 failures = 0
394 for i in range(1, 2):
395 refTableFile = '%s/r%s/rip_status.ref' % (thisDir, i)
396 if os.path.isfile(refTableFile):
397 # Read expected result from file
398 expected = open(refTableFile).read().rstrip()
399 # Fix newlines (make them all the same)
400 expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1)
401
402 # Actual output from router
403 actual = net['r%s' % i].cmd('vtysh -c "show ip rip status" 2> /dev/null').rstrip()
404 # Drop time in next due
405 actual = re.sub(r"in [0-9]+ seconds", "in XX seconds", actual)
406 # Drop time in last update
407 actual = re.sub(r" [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", " XX:XX:XX", actual)
408 # Fix newlines (make them all the same)
409 actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
410
411 # Generate Diff
412 diff = topotest.get_textdiff(actual, expected,
413 title1="actual IP RIP status",
414 title2="expected IP RIP status")
415
416 # Empty string if it matches, otherwise diff contains unified diff
417 if diff:
418 sys.stderr.write('r%s failed IP RIP status check:\n%s\n' % (i, diff))
419 failures += 1
420 else:
421 print("r%s ok" % i)
422
423 assert failures == 0, "IP RIP status failed for router r%s:\n%s" % (i, diff)
424
425 # Make sure that all daemons are running
426 for i in range(1, 2):
427 fatal_error = net['r%s' % i].checkRouterRunning()
428 assert fatal_error == "", fatal_error
429
430 # For debugging after starting FRR/Quagga daemons, uncomment the next line
431 # CLI(net)
432
433
434 def test_ripng_status():
435 global fatal_error
436 global net
437
438 # Skip if previous fatal error condition is raised
439 if (fatal_error != ""):
440 pytest.skip(fatal_error)
441
442 thisDir = os.path.dirname(os.path.realpath(__file__))
443
444 print("\n\n** Verifying RIPng status")
445 print("******************************************\n")
446 failures = 0
447 for i in range(1, 2):
448 refTableFile = '%s/r%s/ripng_status.ref' % (thisDir, i)
449 if os.path.isfile(refTableFile):
450 # Read expected result from file
451 expected = open(refTableFile).read().rstrip()
452 # Fix newlines (make them all the same)
453 expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1)
454
455 # Actual output from router
456 actual = net['r%s' % i].cmd('vtysh -c "show ipv6 ripng status" 2> /dev/null').rstrip()
457 # Mask out Link-Local mac address portion. They are random...
458 actual = re.sub(r" fe80::[0-9a-f:]+", " fe80::XXXX:XXXX:XXXX:XXXX", actual)
459 # Drop time in next due
460 actual = re.sub(r"in [0-9]+ seconds", "in XX seconds", actual)
461 # Drop time in last update
462 actual = re.sub(r" [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", " XX:XX:XX", actual)
463 # Fix newlines (make them all the same)
464 actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
465
466 # Generate Diff
467 diff = topotest.get_textdiff(actual, expected,
468 title1="actual IPv6 RIPng status",
469 title2="expected IPv6 RIPng status")
470
471 # Empty string if it matches, otherwise diff contains unified diff
472 if diff:
473 sys.stderr.write('r%s failed IPv6 RIPng status check:\n%s\n' % (i, diff))
474 failures += 1
475 else:
476 print("r%s ok" % i)
477
478 assert failures == 0, "IPv6 RIPng status failed for router r%s:\n%s" % (i, diff)
479
480 # Make sure that all daemons are running
481 for i in range(1, 2):
482 fatal_error = net['r%s' % i].checkRouterRunning()
483 assert fatal_error == "", fatal_error
484
485 # For debugging after starting FRR/Quagga daemons, uncomment the next line
486 # CLI(net)
487
488
489 def test_ospfv2_interfaces():
490 global fatal_error
491 global net
492
493 # Skip if previous fatal error condition is raised
494 if (fatal_error != ""):
495 pytest.skip(fatal_error)
496
497 thisDir = os.path.dirname(os.path.realpath(__file__))
498
499 print("\n\n** Verifying OSPFv2 interfaces")
500 print("******************************************\n")
501 failures = 0
502 for i in range(1, 2):
503 refTableFile = '%s/r%s/show_ip_ospf_interface.ref' % (thisDir, i)
504 if os.path.isfile(refTableFile):
505 # Read expected result from file
506 expected = open(refTableFile).read().rstrip()
507 # Fix newlines (make them all the same)
508 expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1)
509
510 # Actual output from router
511 actual = net['r%s' % i].cmd('vtysh -c "show ip ospf interface" 2> /dev/null').rstrip()
512 # Mask out Bandwidth portion. They may change..
513 actual = re.sub(r"BW [0-9]+ Mbit", "BW XX Mbit", actual)
514 actual = re.sub(r"ifindex [0-9]", "ifindex X", actual)
515
516 # Drop time in next due
517 actual = re.sub(r"Hello due in [0-9\.]+s", "Hello due in XX.XXXs", actual)
518 # Fix 'MTU mismatch detection: enabled' vs 'MTU mismatch detection:enabled' - accept both
519 actual = re.sub(r"MTU mismatch detection:([a-z]+.*)", r"MTU mismatch detection: \1", actual)
520 # Fix newlines (make them all the same)
521 actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
522
523 # Generate Diff
524 diff = topotest.get_textdiff(actual, expected,
525 title1="actual SHOW IP OSPF INTERFACE",
526 title2="expected SHOW IP OSPF INTERFACE")
527
528 # Empty string if it matches, otherwise diff contains unified diff
529 if diff:
530 sys.stderr.write('r%s failed SHOW IP OSPF INTERFACE check:\n%s\n' % (i, diff))
531 failures += 1
532 else:
533 print("r%s ok" % i)
534
535 # Ignoring the issue if told to ignore (ie not yet fixed)
536 if (failures != 0):
537 if (os.environ.get('bamboo_TOPOTESTS_ISSUE_348') == "IGNORE"):
538 sys.stderr.write('Known issue - IGNORING. See https://github.com/FRRouting/frr/issues/348\n')
539 pytest.skip('Known issue - IGNORING. See https://github.com/FRRouting/frr/issues/348')
540
541 assert failures == 0, "SHOW IP OSPF INTERFACE failed for router r%s:\n%s" % (i, diff)
542
543 # Make sure that all daemons are running
544 for i in range(1, 2):
545 fatal_error = net['r%s' % i].checkRouterRunning()
546 assert fatal_error == "", fatal_error
547
548 # For debugging after starting FRR/Quagga daemons, uncomment the next line
549 # CLI(net)
550
551
552 def test_isis_interfaces():
553 global fatal_error
554 global net
555
556 # Skip if previous fatal error condition is raised
557 if (fatal_error != ""):
558 pytest.skip(fatal_error)
559
560 thisDir = os.path.dirname(os.path.realpath(__file__))
561
562 print("\n\n** Verifying ISIS interfaces")
563 print("******************************************\n")
564 failures = 0
565 for i in range(1, 2):
566 refTableFile = '%s/r%s/show_isis_interface_detail.ref' % (thisDir, i)
567 if os.path.isfile(refTableFile):
568 # Read expected result from file
569 expected = open(refTableFile).read().rstrip()
570 # Fix newlines (make them all the same)
571 expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1)
572
573 # Actual output from router
574 actual = net['r%s' % i].cmd('vtysh -c "show isis interface detail" 2> /dev/null').rstrip()
575 # Mask out Link-Local mac address portion. They are random...
576 actual = re.sub(r"fe80::[0-9a-f:]+", "fe80::XXXX:XXXX:XXXX:XXXX", actual)
577 # Mask out SNPA mac address portion. They are random...
578 actual = re.sub(r"SNPA: [0-9a-f\.]+", "SNPA: XXXX.XXXX.XXXX", actual)
579 # Mask out Circuit ID number
580 actual = re.sub(r"Circuit Id: 0x[0-9]+", "Circuit Id: 0xXX", actual)
581 # Fix newlines (make them all the same)
582 actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
583
584 # Generate Diff
585 diff = topotest.get_textdiff(actual, expected,
586 title1="actual SHOW ISIS INTERFACE DETAIL",
587 title2="expected SHOW ISIS OSPF6 INTERFACE DETAIL")
588
589 # Empty string if it matches, otherwise diff contains unified diff
590 if diff:
591 sys.stderr.write('r%s failed SHOW ISIS INTERFACE DETAIL check:\n%s\n' % (i, diff))
592 failures += 1
593 else:
594 print("r%s ok" % i)
595
596 assert failures == 0, "SHOW ISIS INTERFACE DETAIL failed for router r%s:\n%s" % (i, diff)
597
598 # Make sure that all daemons are running
599 for i in range(1, 2):
600 fatal_error = net['r%s' % i].checkRouterRunning()
601 assert fatal_error == "", fatal_error
602
603 # For debugging after starting FRR/Quagga daemons, uncomment the next line
604 # CLI(net)
605
606
607 def test_bgp_summary():
608 global fatal_error
609 global net
610
611 # Skip if previous fatal error condition is raised
612 if (fatal_error != ""):
613 pytest.skip(fatal_error)
614
615 thisDir = os.path.dirname(os.path.realpath(__file__))
616
617 print("\n\n** Verifying BGP Summary")
618 print("******************************************\n")
619 failures = 0
620 for i in range(1, 2):
621 refTableFile = '%s/r%s/show_ip_bgp_summary.ref' % (thisDir, i)
622 if os.path.isfile(refTableFile):
623 # Read expected result from file
624 expected = open(refTableFile).read().rstrip()
625 # Fix newlines (make them all the same)
626 expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1)
627
628 # Actual output from router
629 actual = net['r%s' % i].cmd('vtysh -c "show ip bgp summary" 2> /dev/null').rstrip()
630 # Mask out "using XXiXX bytes" portion. They are random...
631 actual = re.sub(r"using [0-9]+ bytes", "using XXXX bytes", actual)
632 # Mask out "using XiXXX KiB" portion. They are random...
633 actual = re.sub(r"using [0-9]+ KiB", "using XXXX KiB", actual)
634 #
635 # Remove extra summaries which exist with newer versions
636 #
637 # Remove summary lines (changed recently)
638 actual = re.sub(r'Total number.*', '', actual)
639 actual = re.sub(r'Displayed.*', '', actual)
640 # Remove IPv4 Unicast Summary (Title only)
641 actual = re.sub(r'IPv4 Unicast Summary:', '', actual)
642 # Remove IPv4 Multicast Summary (all of it)
643 actual = re.sub(r'IPv4 Multicast Summary:', '', actual)
644 actual = re.sub(r'No IPv4 Multicast neighbor is configured', '', actual)
645 # Remove IPv4 VPN Summary (all of it)
646 actual = re.sub(r'IPv4 VPN Summary:', '', actual)
647 actual = re.sub(r'No IPv4 VPN neighbor is configured', '', actual)
648 # Remove IPv4 Encap Summary (all of it)
649 actual = re.sub(r'IPv4 Encap Summary:', '', actual)
650 actual = re.sub(r'No IPv4 Encap neighbor is configured', '', actual)
651 # Remove Unknown Summary (all of it)
652 actual = re.sub(r'Unknown Summary:', '', actual)
653 actual = re.sub(r'No Unknown neighbor is configured', '', actual)
654
655 actual = re.sub(r'IPv4 labeled-unicast Summary:', '', actual)
656 actual = re.sub(r'No IPv4 labeled-unicast neighbor is configured', '', actual)
657
658 # Strip empty lines
659 actual = actual.lstrip()
660 actual = actual.rstrip()
661 #
662 # Fix newlines (make them all the same)
663 actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
664
665 # Generate Diff
666 diff = topotest.get_textdiff(actual, expected,
667 title1="actual SHOW IP BGP SUMMARY",
668 title2="expected SHOW IP BGP SUMMARY")
669
670 # Empty string if it matches, otherwise diff contains unified diff
671 if diff:
672 sys.stderr.write('r%s failed SHOW IP BGP SUMMARY check:\n%s\n' % (i, diff))
673 failures += 1
674 else:
675 print("r%s ok" % i)
676
677 assert failures == 0, "SHOW IP BGP SUMMARY failed for router r%s:\n%s" % (i, diff)
678
679 # Make sure that all daemons are running
680 for i in range(1, 2):
681 fatal_error = net['r%s' % i].checkRouterRunning()
682 assert fatal_error == "", fatal_error
683
684 # For debugging after starting FRR/Quagga daemons, uncomment the next line
685 # CLI(net)
686
687
688 def test_bgp_ipv6_summary():
689 global fatal_error
690 global net
691
692 # Skip if previous fatal error condition is raised
693 if (fatal_error != ""):
694 pytest.skip(fatal_error)
695
696 thisDir = os.path.dirname(os.path.realpath(__file__))
697
698 print("\n\n** Verifying BGP IPv6 Summary")
699 print("******************************************\n")
700 failures = 0
701 for i in range(1, 2):
702 refTableFile = '%s/r%s/show_bgp_ipv6_summary.ref' % (thisDir, i)
703 if os.path.isfile(refTableFile):
704 # Read expected result from file
705 expected = open(refTableFile).read().rstrip()
706 # Fix newlines (make them all the same)
707 expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1)
708
709 # Actual output from router
710 actual = net['r%s' % i].cmd('vtysh -c "show bgp ipv6 summary" 2> /dev/null').rstrip()
711 # Mask out "using XXiXX bytes" portion. They are random...
712 actual = re.sub(r"using [0-9]+ bytes", "using XXXX bytes", actual)
713 # Mask out "using XiXXX KiB" portion. They are random...
714 actual = re.sub(r"using [0-9]+ KiB", "using XXXX KiB", actual)
715 #
716 # Remove extra summaries which exist with newer versions
717 #
718 # Remove summary lines (changed recently)
719 actual = re.sub(r'Total number.*', '', actual)
720 actual = re.sub(r'Displayed.*', '', actual)
721 # Remove IPv4 Unicast Summary (Title only)
722 actual = re.sub(r'IPv6 Unicast Summary:', '', actual)
723 # Remove IPv4 Multicast Summary (all of it)
724 actual = re.sub(r'IPv6 Multicast Summary:', '', actual)
725 actual = re.sub(r'No IPv6 Multicast neighbor is configured', '', actual)
726 # Remove IPv4 VPN Summary (all of it)
727 actual = re.sub(r'IPv6 VPN Summary:', '', actual)
728 actual = re.sub(r'No IPv6 VPN neighbor is configured', '', actual)
729 # Remove IPv4 Encap Summary (all of it)
730 actual = re.sub(r'IPv6 Encap Summary:', '', actual)
731 actual = re.sub(r'No IPv6 Encap neighbor is configured', '', actual)
732 # Remove Unknown Summary (all of it)
733 actual = re.sub(r'Unknown Summary:', '', actual)
734 actual = re.sub(r'No Unknown neighbor is configured', '', actual)
735
736 # Remove Labeled Unicast Summary (all of it)
737 actual = re.sub(r'IPv6 labeled-unicast Summary:', '', actual)
738 actual = re.sub(r'No IPv6 labeled-unicast neighbor is configured', '', actual)
739
740 # Strip empty lines
741 actual = actual.lstrip()
742 actual = actual.rstrip()
743 #
744 # Fix newlines (make them all the same)
745 actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
746
747 # Generate Diff
748 diff = topotest.get_textdiff(actual, expected,
749 title1="actual SHOW BGP IPv6 SUMMARY",
750 title2="expected SHOW BGP IPv6 SUMMARY")
751
752 # Empty string if it matches, otherwise diff contains unified diff
753 if diff:
754 sys.stderr.write('r%s failed SHOW BGP IPv6 SUMMARY check:\n%s\n' % (i, diff))
755 failures += 1
756 else:
757 print("r%s ok" % i)
758
759 assert failures == 0, "SHOW BGP IPv6 SUMMARY failed for router r%s:\n%s" % (i, diff)
760
761 # Make sure that all daemons are running
762 for i in range(1, 2):
763 fatal_error = net['r%s' % i].checkRouterRunning()
764 assert fatal_error == "", fatal_error
765
766 # For debugging after starting FRR/Quagga daemons, uncomment the next line
767 # CLI(net)
768
769
770 def test_bgp_ipv4():
771 global fatal_error
772 global net
773
774 # Skip if previous fatal error condition is raised
775 if (fatal_error != ""):
776 pytest.skip(fatal_error)
777
778 thisDir = os.path.dirname(os.path.realpath(__file__))
779
780 print("\n\n** Verifying BGP IPv4")
781 print("******************************************\n")
782 diffresult = {}
783 for i in range(1, 2):
784 success = 0
785 for refTableFile in (glob.glob(
786 '%s/r%s/show_bgp_ipv4*.ref' % (thisDir, i))):
787 if os.path.isfile(refTableFile):
788 # Read expected result from file
789 expected = open(refTableFile).read().rstrip()
790 # Fix newlines (make them all the same)
791 expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1)
792
793 # Actual output from router
794 actual = net['r%s' % i].cmd('vtysh -c "show bgp ipv4" 2> /dev/null').rstrip()
795 # Remove summary line (changed recently)
796 actual = re.sub(r'Total number.*', '', actual)
797 actual = re.sub(r'Displayed.*', '', actual)
798 actual = actual.rstrip()
799 # Fix newlines (make them all the same)
800 actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
801
802 # Generate Diff
803 diff = topotest.get_textdiff(actual, expected,
804 title1="actual SHOW BGP IPv4",
805 title2="expected SHOW BGP IPv4")
806
807 # Empty string if it matches, otherwise diff contains unified diff
808 if diff:
809 diffresult[refTableFile] = diff
810 else:
811 success = 1
812 print("template %s matched: r%s ok" % (refTableFile, i))
813 break
814
815 if not success:
816 resultstr = 'No template matched.\n'
817 for f in diffresult.iterkeys():
818 resultstr += (
819 'template %s: r%s failed SHOW BGP IPv4 check:\n%s\n'
820 % (f, i, diffresult[f]))
821 raise AssertionError(
822 "SHOW BGP IPv4 failed for router r%s:\n%s" % (i, resultstr))
823
824 # Make sure that all daemons are running
825 for i in range(1, 2):
826 fatal_error = net['r%s' % i].checkRouterRunning()
827 assert fatal_error == "", fatal_error
828
829 # For debugging after starting FRR/Quagga daemons, uncomment the next line
830 # CLI(net)
831
832
833 def test_bgp_ipv6():
834 global fatal_error
835 global net
836
837 # Skip if previous fatal error condition is raised
838 if (fatal_error != ""):
839 pytest.skip(fatal_error)
840
841 thisDir = os.path.dirname(os.path.realpath(__file__))
842
843 print("\n\n** Verifying BGP IPv6")
844 print("******************************************\n")
845 diffresult = {}
846 for i in range(1, 2):
847 success = 0
848 for refTableFile in (glob.glob(
849 '%s/r%s/show_bgp_ipv6*.ref' % (thisDir, i))):
850 if os.path.isfile(refTableFile):
851 # Read expected result from file
852 expected = open(refTableFile).read().rstrip()
853 # Fix newlines (make them all the same)
854 expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1)
855
856 # Actual output from router
857 actual = net['r%s' % i].cmd('vtysh -c "show bgp ipv6" 2> /dev/null').rstrip()
858 # Remove summary line (changed recently)
859 actual = re.sub(r'Total number.*', '', actual)
860 actual = re.sub(r'Displayed.*', '', actual)
861 actual = actual.rstrip()
862 # Fix newlines (make them all the same)
863 actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
864
865 # Generate Diff
866 diff = topotest.get_textdiff(actual, expected,
867 title1="actual SHOW BGP IPv6",
868 title2="expected SHOW BGP IPv6")
869
870 # Empty string if it matches, otherwise diff contains unified diff
871 if diff:
872 diffresult[refTableFile] = diff
873 else:
874 success = 1
875 print("template %s matched: r%s ok" % (refTableFile, i))
876
877 if not success:
878 resultstr = 'No template matched.\n'
879 for f in diffresult.iterkeys():
880 resultstr += (
881 'template %s: r%s failed SHOW BGP IPv6 check:\n%s\n'
882 % (f, i, diffresult[f]))
883 raise AssertionError(
884 "SHOW BGP IPv6 failed for router r%s:\n%s" % (i, resultstr))
885
886 # Make sure that all daemons are running
887 for i in range(1, 2):
888 fatal_error = net['r%s' % i].checkRouterRunning()
889 assert fatal_error == "", fatal_error
890
891 # For debugging after starting FRR/Quagga daemons, uncomment the next line
892 # CLI(net)
893
894
895
896 def test_mpls_interfaces():
897 global fatal_error
898 global net
899
900 # Skip if previous fatal error condition is raised
901 if (fatal_error != ""):
902 pytest.skip(fatal_error)
903
904 # Skip if no LDP installed or old kernel
905 if (net['r1'].daemon_available('ldpd') == False):
906 pytest.skip("No MPLS or kernel < 4.5")
907
908 thisDir = os.path.dirname(os.path.realpath(__file__))
909
910 print("\n\n** Verifying MPLS Interfaces")
911 print("******************************************\n")
912 failures = 0
913 for i in range(1, 2):
914 refTableFile = '%s/r%s/show_mpls_ldp_interface.ref' % (thisDir, i)
915 if os.path.isfile(refTableFile):
916 # Read expected result from file
917 expected = open(refTableFile).read().rstrip()
918 # Fix newlines (make them all the same)
919 expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1)
920
921 # Actual output from router
922 actual = net['r%s' % i].cmd('vtysh -c "show mpls ldp interface" 2> /dev/null').rstrip()
923 # Mask out Timer in Uptime
924 actual = re.sub(r" [0-9][0-9]:[0-9][0-9]:[0-9][0-9] ", " xx:xx:xx ", actual)
925 # Fix newlines (make them all the same)
926 actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
927
928 # Generate Diff
929 diff = topotest.get_textdiff(actual, expected,
930 title1="actual MPLS LDP interface status",
931 title2="expected MPLS LDP interface status")
932
933 # Empty string if it matches, otherwise diff contains unified diff
934 if diff:
935 sys.stderr.write('r%s failed MPLS LDP Interface status Check:\n%s\n' % (i, diff))
936 failures += 1
937 else:
938 print("r%s ok" % i)
939
940 if failures>0:
941 fatal_error = "MPLS LDP Interface status failed"
942
943 assert failures == 0, "MPLS LDP Interface status failed for router r%s:\n%s" % (i, diff)
944
945 # Make sure that all daemons are running
946 for i in range(1, 2):
947 fatal_error = net['r%s' % i].checkRouterRunning()
948 assert fatal_error == "", fatal_error
949
950 # For debugging after starting FRR/Quagga daemons, uncomment the next line
951 # CLI(net)
952
953
954 def test_shutdown_check_stderr():
955 global fatal_error
956 global net
957
958 # Skip if previous fatal error condition is raised
959 if (fatal_error != ""):
960 pytest.skip(fatal_error)
961
962 print("\n\n** Verifying unexpected STDERR output from daemons")
963 print("******************************************\n")
964
965 if os.environ.get('TOPOTESTS_CHECK_STDERR') is None:
966 print("SKIPPED final check on StdErr output: Disabled (TOPOTESTS_CHECK_STDERR undefined)\n")
967 pytest.skip('Skipping test for Stderr output')
968
969 thisDir = os.path.dirname(os.path.realpath(__file__))
970
971 print("thisDir=" + thisDir)
972
973 net['r1'].stopRouter()
974
975 log = net['r1'].getStdErr('ripd')
976 if log:
977 print("\nRIPd StdErr Log:\n" + log)
978 log = net['r1'].getStdErr('ripngd')
979 if log:
980 print("\nRIPngd StdErr Log:\n" + log)
981 log = net['r1'].getStdErr('ospfd')
982 if log:
983 print("\nOSPFd StdErr Log:\n" + log)
984 log = net['r1'].getStdErr('ospf6d')
985 if log:
986 print("\nOSPF6d StdErr Log:\n" + log)
987 log = net['r1'].getStdErr('isisd')
988 if log:
989 print("\nISISd StdErr Log:\n" + log)
990 log = net['r1'].getStdErr('bgpd')
991 if log:
992 print("\nBGPd StdErr Log:\n" + log)
993 if (net['r1'].daemon_available('ldpd')):
994 log = net['r1'].getStdErr('ldpd')
995 if log:
996 print("\nLDPd StdErr Log:\n" + log)
997 log = net['r1'].getStdErr('zebra')
998 if log:
999 print("\nZebra StdErr Log:\n" + log)
1000
1001
1002 def test_shutdown_check_memleak():
1003 global fatal_error
1004 global net
1005
1006 # Skip if previous fatal error condition is raised
1007 if (fatal_error != ""):
1008 pytest.skip(fatal_error)
1009
1010 if os.environ.get('TOPOTESTS_CHECK_MEMLEAK') is None:
1011 print("SKIPPED final check on Memory leaks: Disabled (TOPOTESTS_CHECK_MEMLEAK undefined)\n")
1012 pytest.skip('Skipping test for memory leaks')
1013
1014 thisDir = os.path.dirname(os.path.realpath(__file__))
1015
1016 for i in range(1, 2):
1017 net['r%s' % i].stopRouter()
1018 net['r%s' % i].report_memory_leaks(os.environ.get('TOPOTESTS_CHECK_MEMLEAK'), os.path.basename(__file__))
1019
1020
1021 if __name__ == '__main__':
1022
1023 setLogLevel('info')
1024 # To suppress tracebacks, either use the following pytest call or add "--tb=no" to cli
1025 # retval = pytest.main(["-s", "--tb=no"])
1026 retval = pytest.main(["-s"])
1027 sys.exit(retval)