]>
git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/ldp_topo1/test_ldp_topo1.py
4 # test_bgp_multiview_topo1.py
5 # Part of NetDEF Topology Tests
7 # Copyright (c) 2016 by
8 # Network Device Education Foundation, Inc. ("NetDEF")
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
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
26 test_ldp_topo1.py: Simple FRR LDP Test
45 r2-eth2 .2 | | .2 r2-eth1
48 ~~~~~~~~~~~~~ ~~~~~~~~~~~~~
50 ~~ 10.0.3.0/24 ~~ ~~ 10.0.2.0/24 ~~
51 ~~~~~~~~~~~~~ ~~~~~~~~~~~~~
55 r3-eth1 .3 | | .3 r3-eth0 | .4 r4-eth0
56 +----+--+---+ +----+----+
58 | 3.3.3.3 | | 4.4.4.4 |
59 +-----------+ +---------+
66 from time
import sleep
67 from lib
.topolog
import logger
69 sys
.path
.append(os
.path
.dirname(os
.path
.dirname(os
.path
.abspath(__file__
))))
70 from lib
import topotest
71 from lib
.topogen
import Topogen
, get_topogen
75 pytestmark
= [pytest
.mark
.ldpd
, pytest
.mark
.ospfd
]
77 #####################################################
79 ## Network Topology Definition
81 #####################################################
88 tgen
.add_router("r%s" % i
)
91 switch
= tgen
.add_switch("sw0")
92 switch
.add_link(tgen
.gears
["r1"])
93 switch
.add_link(tgen
.gears
["r2"])
95 switch
= tgen
.add_switch("sw1")
96 switch
.add_link(tgen
.gears
["r2"])
97 switch
.add_link(tgen
.gears
["r3"])
98 switch
.add_link(tgen
.gears
["r4"])
100 switch
= tgen
.add_switch("sw2")
101 switch
.add_link(tgen
.gears
["r2"])
102 switch
.add_link(tgen
.gears
["r3"])
105 #####################################################
109 #####################################################
112 def setup_module(module
):
113 print("\n\n** %s: Setup Topology" % module
.__name
__)
114 print("******************************************\n")
116 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
117 tgen
= Topogen(build_topo
, module
.__name
__)
118 tgen
.start_topology()
123 for i
in range(1, 5):
124 net
["r%s" % i
].loadConf("zebra", "%s/r%s/zebra.conf" % (thisDir
, i
))
125 net
["r%s" % i
].loadConf("ospfd", "%s/r%s/ospfd.conf" % (thisDir
, i
))
126 net
["r%s" % i
].loadConf("ldpd", "%s/r%s/ldpd.conf" % (thisDir
, i
))
127 tgen
.gears
["r%s" % i
].start()
129 # For debugging after starting FRR daemons, uncomment the next line
133 def teardown_module(module
):
134 print("\n\n** %s: Shutdown Topology" % module
.__name
__)
135 print("******************************************\n")
140 def test_router_running():
142 net
= get_topogen().net
144 # Skip if previous fatal error condition is raised
145 if fatal_error
!= "":
146 pytest
.skip(fatal_error
)
148 print("\n\n** Check if FRR is running on each Router node")
149 print("******************************************\n")
153 for i
in range(1, 5):
154 fatal_error
= net
["r%s" % i
].checkRouterRunning()
155 assert fatal_error
== "", fatal_error
158 def test_mpls_interfaces():
160 net
= get_topogen().net
162 # Skip if previous fatal error condition is raised
163 if fatal_error
!= "":
164 pytest
.skip(fatal_error
)
166 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
168 # Verify MPLS Interfaces
169 print("\n\n** Verifying MPLS Interfaces")
170 print("******************************************\n")
172 for i
in range(1, 5):
173 refTableFile
= "%s/r%s/show_mpls_ldp_interface.ref"
174 if os
.path
.isfile(refTableFile
):
175 # Read expected result from file
176 expected
= open(refTableFile
).read().rstrip()
177 # Fix newlines (make them all the same)
178 expected
= ("\n".join(expected
.splitlines()) + "\n").splitlines(1)
180 # Actual output from router
183 .cmd('vtysh -c "show mpls ldp interface" 2> /dev/null')
186 # Mask out Timer in Uptime
187 actual
= re
.sub(r
" [0-9][0-9]:[0-9][0-9]:[0-9][0-9] ", " xx:xx:xx ", actual
)
188 # Fix newlines (make them all the same)
189 actual
= ("\n".join(actual
.splitlines()) + "\n").splitlines(1)
192 diff
= topotest
.get_textdiff(
195 title1
="actual MPLS LDP interface status",
196 title2
="expected MPLS LDP interface status",
199 # Empty string if it matches, otherwise diff contains unified diff
202 "r%s failed MPLS LDP Interface status Check:\n%s\n" % (i
, diff
)
209 fatal_error
= "MPLS LDP Interface status failed"
213 ), "MPLS LDP Interface status failed for router r%s:\n%s" % (i
, diff
)
215 # Make sure that all daemons are running
216 for i
in range(1, 5):
217 fatal_error
= net
["r%s" % i
].checkRouterRunning()
218 assert fatal_error
== "", fatal_error
221 def test_mpls_ldp_neighbor_establish():
223 net
= get_topogen().net
225 # Skip if previous fatal error condition is raised
226 if fatal_error
!= "":
227 pytest
.skip(fatal_error
)
229 neighbors_operational
= {
236 # Wait for MPLS LDP neighbors to establish.
237 print("\n\n** Verify MPLS LDP neighbors to establish")
238 print("******************************************\n")
241 print("Timeout in %s: " % timeout
),
243 # Look for any node not yet converged
244 for i
in range(1, 5):
247 .cmd('vtysh -c "show mpls ldp neighbor" 2> /dev/null')
251 # On current version, we need to make sure they all turn to OPERATIONAL on all lines
253 lines
= ("\n".join(established
.splitlines()) + "\n").splitlines(1)
254 # Check all lines to be either table header (starting with ^AF or show OPERATIONAL)
256 operational
= r
"^ip.*OPERATIONAL.*"
257 found_operational
= 0
258 for j
in range(1, len(lines
)):
259 if (not re
.search(header
, lines
[j
])) and (
260 not re
.search(operational
, lines
[j
])
262 established
= "" # Empty string shows NOT established
263 if re
.search(operational
, lines
[j
]):
264 found_operational
+= 1
266 logger
.info("Found operational %d" % found_operational
)
267 if found_operational
< 1:
268 # Need at least one operational neighbor
269 established
= "" # Empty string shows NOT established
271 if found_operational
!= neighbors_operational
[i
]:
274 print("Waiting for r%s" % i
)
284 # Bail out with error if a router fails to converge
285 fatal_error
= "MPLS LDP neighbors did not establish"
286 assert False, "MPLS LDP neighbors did not establish"
288 print("MPLS LDP neighbors established.")
291 # Only wait if we actually went through a convergence
292 print("\nwaiting 15s for LDP sessions to establish")
295 # Make sure that all daemons are running
296 for i
in range(1, 5):
297 fatal_error
= net
["r%s" % i
].checkRouterRunning()
298 assert fatal_error
== "", fatal_error
301 def test_mpls_ldp_discovery():
303 net
= get_topogen().net
305 # Skip if previous fatal error condition is raised
306 if fatal_error
!= "":
307 pytest
.skip(fatal_error
)
309 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
311 # Verify MPLS LDP discovery
312 print("\n\n** Verifying MPLS LDP discovery")
313 print("******************************************\n")
315 for i
in range(1, 5):
316 refTableFile
= "%s/r%s/show_mpls_ldp_discovery.ref" % (thisDir
, i
)
317 if os
.path
.isfile(refTableFile
):
318 # Actual output from router
321 .cmd('vtysh -c "show mpls ldp discovery" 2> /dev/null')
325 # Read expected result from file
326 expected
= open(refTableFile
).read().rstrip()
327 # Fix newlines (make them all the same)
328 expected
= ("\n".join(expected
.splitlines()) + "\n").splitlines(1)
330 # Actual output from router
333 .cmd('vtysh -c "show mpls ldp discovery" 2> /dev/null')
337 # Fix newlines (make them all the same)
338 actual
= ("\n".join(actual
.splitlines()) + "\n").splitlines(1)
341 diff
= topotest
.get_textdiff(
344 title1
="actual MPLS LDP discovery output",
345 title2
="expected MPLS LDP discovery output",
348 # Empty string if it matches, otherwise diff contains unified diff
351 "r%s failed MPLS LDP discovery output Check:\n%s\n" % (i
, diff
)
359 ), "MPLS LDP Interface discovery output for router r%s:\n%s" % (i
, diff
)
361 # Make sure that all daemons are running
362 for i
in range(1, 5):
363 fatal_error
= net
["r%s" % i
].checkRouterRunning()
364 assert fatal_error
== "", fatal_error
367 def test_mpls_ldp_neighbor():
369 net
= get_topogen().net
371 # Skip if previous fatal error condition is raised
372 if fatal_error
!= "":
373 pytest
.skip(fatal_error
)
375 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
377 # Verify MPLS LDP neighbor
378 print("\n\n** Verifying MPLS LDP neighbor")
379 print("******************************************\n")
381 for i
in range(1, 5):
382 refTableFile
= "%s/r%s/show_mpls_ldp_neighbor.ref" % (thisDir
, i
)
383 if os
.path
.isfile(refTableFile
):
384 # Read expected result from file
385 expected
= open(refTableFile
).read().rstrip()
386 # Fix newlines (make them all the same)
387 expected
= ("\n".join(expected
.splitlines()) + "\n").splitlines(1)
389 # Actual output from router
392 .cmd('vtysh -c "show mpls ldp neighbor" 2> /dev/null')
396 # Mask out changing parts in output
397 # Mask out Timer in Uptime
399 r
"(ipv4 [0-9\.]+ +OPERATIONAL [0-9\.]+ +)[0-9][0-9]:[0-9][0-9]:[0-9][0-9]",
404 # Fix newlines (make them all the same)
405 actual
= ("\n".join(actual
.splitlines()) + "\n").splitlines(1)
408 diff
= topotest
.get_textdiff(
411 title1
="actual MPLS LDP neighbor output",
412 title2
="expected MPLS LDP neighbor output",
415 # Empty string if it matches, otherwise diff contains unified diff
418 "r%s failed MPLS LDP neighbor output Check:\n%s\n" % (i
, diff
)
426 ), "MPLS LDP Interface neighbor output for router r%s:\n%s" % (i
, diff
)
428 # Make sure that all daemons are running
429 for i
in range(1, 5):
430 fatal_error
= net
["r%s" % i
].checkRouterRunning()
431 assert fatal_error
== "", fatal_error
434 def test_mpls_ldp_binding():
436 net
= get_topogen().net
438 # Skip this test for now until proper sorting of the output
440 # pytest.skip("Skipping test_mpls_ldp_binding")
442 # Skip if previous fatal error condition is raised
443 if fatal_error
!= "":
444 pytest
.skip(fatal_error
)
446 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
448 # Verify MPLS LDP binding
449 print("\n\n** Verifying MPLS LDP binding")
450 print("******************************************\n")
452 for i
in range(1, 5):
453 refTableFile
= "%s/r%s/show_mpls_ldp_binding.ref" % (thisDir
, i
)
454 if os
.path
.isfile(refTableFile
):
455 # Read expected result from file
456 expected
= open(refTableFile
).read().rstrip()
457 # Fix newlines (make them all the same)
458 expected
= ("\n".join(expected
.splitlines()) + "\n").splitlines(1)
460 # Actual output from router
463 .cmd('vtysh -c "show mpls ldp binding" 2> /dev/null')
467 # Mask out changing parts in output
470 r
"(ipv4 [0-9\./]+ +[0-9\.]+ +)[0-9][0-9] (.*)", r
"\1xxx\2", actual
473 r
"(ipv4 [0-9\./]+ +[0-9\.]+ +[a-z\-]+ +)[0-9][0-9] (.*)",
478 # Fix newlines (make them all the same)
479 actual
= ("\n".join(actual
.splitlines()) + "\n").splitlines(1)
481 # Sort lines which start with "xx via inet "
482 pattern
= r
"^\s+[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\s+"
486 for j
in range(1, len(actual
)):
487 if re
.search(pattern
, actual
[j
]) and re
.search(
488 pattern
, actual
[j
- 1]
490 if actual
[j
- 1] > actual
[j
]:
492 actual
[j
- 1] = actual
[j
]
497 diff
= topotest
.get_textdiff(
500 title1
="actual MPLS LDP binding output",
501 title2
="expected MPLS LDP binding output",
504 # Empty string if it matches, otherwise diff contains unified diff
507 "r%s failed MPLS LDP binding output Check:\n%s\n" % (i
, diff
)
515 ), "MPLS LDP Interface binding output for router r%s:\n%s" % (i
, diff
)
517 # Make sure that all daemons are running
518 for i
in range(1, 5):
519 fatal_error
= net
["r%s" % i
].checkRouterRunning()
520 assert fatal_error
== "", fatal_error
523 def test_zebra_ipv4_routingTable():
525 net
= get_topogen().net
527 # Skip if previous fatal error condition is raised
528 if fatal_error
!= "":
529 pytest
.skip(fatal_error
)
531 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
533 # Verify Zebra IPv4 Routing Table
534 print("\n\n** Verifying Zebra IPv4 Routing Table")
535 print("******************************************\n")
537 for i
in range(1, 5):
538 refTableFile
= "%s/r%s/show_ipv4_route.ref" % (thisDir
, i
)
539 if os
.path
.isfile(refTableFile
):
540 # Read expected result from file
541 expected
= open(refTableFile
).read().rstrip()
543 # Actual output from router
546 .cmd('vtysh -c "show ip route" 2> /dev/null | grep "^O"')
549 # Drop timers on end of line
550 actual
= re
.sub(r
", [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", "", actual
)
552 # Mask out label - all LDP labels should be >= 10 (2-digit)
553 # leaving the implicit labels unmasked
554 actual
= re
.sub(r
" label [0-9][0-9]+", " label xxx", actual
)
555 # and translating remaining implicit (single-digit) labels to label implicit-null
556 actual
= re
.sub(r
" label [0-9]+", " label implicit-null", actual
)
557 # Check if we have implicit labels - if not, then remove them from reference
558 if not re
.search(r
" label implicit-null", actual
):
559 expected
= re
.sub(r
", label implicit-null", "", expected
)
561 # now fix newlines of expected (make them all the same)
562 expected
= ("\n".join(expected
.splitlines()) + "\n").splitlines(1)
564 # Fix newlines (make them all the same)
565 actual
= ("\n".join(actual
.splitlines()) + "\n").splitlines(1)
568 diff
= topotest
.get_textdiff(
571 title1
="actual IPv4 zebra routing table",
572 title2
="expected IPv4 zebra routing table",
575 # Empty string if it matches, otherwise diff contains unified diff
578 "r%s failed IPv4 Zebra Routing Table Check:\n%s\n" % (i
, diff
)
586 ), "IPv4 Zebra Routing Table verification failed for router r%s:\n%s" % (
591 # Make sure that all daemons are running
592 for i
in range(1, 5):
593 fatal_error
= net
["r%s" % i
].checkRouterRunning()
594 assert fatal_error
== "", fatal_error
597 def test_mpls_table():
599 net
= get_topogen().net
601 # Skip if previous fatal error condition is raised
602 if fatal_error
!= "":
603 pytest
.skip(fatal_error
)
605 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
608 print("\n\n** Verifying MPLS table")
609 print("******************************************\n")
612 for i
in range(1, 5):
613 refTableFile
= "%s/r%s/show_mpls_table.ref" % (thisDir
, i
)
614 if os
.path
.isfile(refTableFile
):
615 # Read expected result from file
616 expected
= open(refTableFile
).read()
617 # Fix newlines (make them all the same)
618 expected
= ("\n".join(expected
.splitlines()) + "\n").splitlines(1)
620 # Actual output from router
621 actual
= net
["r%s" % i
].cmd('vtysh -c "show mpls table" 2> /dev/null')
623 # Fix inconsistent Label numbers at beginning of line
624 actual
= re
.sub(r
"(\s+)[0-9]+(\s+LDP)", r
"\1XX\2", actual
)
625 # Fix inconsistent Label numbers at end of line
627 r
"(\s+[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\s+)[0-9][0-9]", r
"\1XX", actual
630 # Fix newlines (make them all the same)
631 actual
= ("\n".join(actual
.splitlines()) + "\n").splitlines(1)
633 # Sort lines which start with " XX LDP"
634 pattern
= r
"^\s+[0-9X]+\s+LDP"
638 for j
in range(1, len(actual
)):
639 if re
.search(pattern
, actual
[j
]) and re
.search(
640 pattern
, actual
[j
- 1]
642 if actual
[j
- 1] > actual
[j
]:
644 actual
[j
- 1] = actual
[j
]
649 diff
= topotest
.get_textdiff(
652 title1
="actual MPLS table output",
653 title2
="expected MPLS table output",
656 # Empty string if it matches, otherwise diff contains unified diff
659 "r%s failed MPLS table output Check:\n%s\n" % (i
, diff
)
665 assert failures
== 0, "MPLS table output for router r%s:\n%s" % (i
, diff
)
667 # Make sure that all daemons are running
668 for i
in range(1, 5):
669 fatal_error
= net
["r%s" % i
].checkRouterRunning()
670 assert fatal_error
== "", fatal_error
673 def test_linux_mpls_routes():
675 net
= get_topogen().net
677 # Skip if previous fatal error condition is raised
678 if fatal_error
!= "":
679 pytest
.skip(fatal_error
)
681 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
683 # Verify Linux Kernel MPLS routes
684 print("\n\n** Verifying Linux Kernel MPLS routes")
685 print("******************************************\n")
687 for i
in range(1, 5):
688 refTableFile
= "%s/r%s/ip_mpls_route.ref" % (thisDir
, i
)
689 if os
.path
.isfile(refTableFile
):
690 # Read expected result from file
691 expected
= open(refTableFile
).read().rstrip()
692 # Fix newlines (make them all the same)
693 expected
= ("\n".join(expected
.splitlines()) + "\n").splitlines(1)
695 # Actual output from router
697 net
["r%s" % i
].cmd("ip -o -family mpls route 2> /dev/null").rstrip()
700 # Mask out label and protocol
701 actual
= re
.sub(r
"[0-9][0-9] via inet ", "xx via inet ", actual
)
702 actual
= re
.sub(r
"[0-9][0-9] +proto", "xx proto", actual
)
703 actual
= re
.sub(r
"[0-9][0-9] as to ", "xx as to ", actual
)
704 actual
= re
.sub(r
"[ ]+proto \w+", " proto xx", actual
)
708 for line
in actual
.splitlines():
709 tokens
= re
.split(r
"\\\t", line
.strip())
710 nexthop_sorted
.append(
713 " ".join([token
.strip() for token
in sorted(tokens
[1:])]),
717 # Sort lines and fixup differences between old and new iproute
718 actual
= "\n".join(sorted(nexthop_sorted
))
719 actual
= re
.sub(r
"nexthop via", "nexthopvia", actual
)
720 actual
= re
.sub(r
" nexthop as to xx via inet ", " nexthopvia inet ", actual
)
721 actual
= re
.sub(r
" weight 1", "", actual
)
722 actual
= re
.sub(r
" [ ]+", " ", actual
)
724 # put \n back at line ends
725 actual
= ("\n".join(actual
.splitlines()) + "\n").splitlines(1)
728 diff
= topotest
.get_textdiff(
731 title1
="actual Linux Kernel MPLS route",
732 title2
="expected Linux Kernel MPLS route",
735 # Empty string if it matches, otherwise diff contains unified diff
738 "r%s failed Linux Kernel MPLS route output Check:\n%s\n" % (i
, diff
)
746 ), "Linux Kernel MPLS route output for router r%s:\n%s" % (i
, diff
)
748 # Make sure that all daemons are running
749 for i
in range(1, 5):
750 fatal_error
= net
["r%s" % i
].checkRouterRunning()
751 assert fatal_error
== "", fatal_error
754 def test_shutdown_check_stderr():
756 net
= get_topogen().net
758 # Skip if previous fatal error condition is raised
759 if fatal_error
!= "":
760 pytest
.skip(fatal_error
)
762 if os
.environ
.get("TOPOTESTS_CHECK_STDERR") is None:
764 "SKIPPED final check on StdErr output: Disabled (TOPOTESTS_CHECK_STDERR undefined)\n"
766 pytest
.skip("Skipping test for Stderr output")
768 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
770 print("\n\n** Verifying unexpected STDERR output from daemons")
771 print("******************************************\n")
773 for i
in range(1, 5):
774 net
["r%s" % i
].stopRouter()
775 log
= net
["r%s" % i
].getStdErr("ldpd")
777 print("\nRouter r%s LDPd StdErr Log:\n%s" % (i
, log
))
778 log
= net
["r%s" % i
].getStdErr("ospfd")
780 print("\nRouter r%s OSPFd StdErr Log:\n%s" % (i
, log
))
781 log
= net
["r%s" % i
].getStdErr("zebra")
783 print("\nRouter r%s Zebra StdErr Log:\n%s" % (i
, log
))
786 def test_shutdown_check_memleak():
788 net
= get_topogen().net
790 # Skip if previous fatal error condition is raised
791 if fatal_error
!= "":
792 pytest
.skip(fatal_error
)
794 if os
.environ
.get("TOPOTESTS_CHECK_MEMLEAK") is None:
796 "SKIPPED final check on Memory leaks: Disabled (TOPOTESTS_CHECK_MEMLEAK undefined)\n"
798 pytest
.skip("Skipping test for memory leaks")
800 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
802 for i
in range(1, 5):
803 net
["r%s" % i
].stopRouter()
804 net
["r%s" % i
].report_memory_leaks(
805 os
.environ
.get("TOPOTESTS_CHECK_MEMLEAK"), os
.path
.basename(__file__
)
809 if __name__
== "__main__":
811 # To suppress tracebacks, either use the following pytest call or add "--tb=no" to cli
812 # retval = pytest.main(["-s", "--tb=no"])
813 retval
= pytest
.main(["-s"])