]> git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/isis_sr_te_topo1/test_isis_sr_te_topo1.py
doc: Add `show ipv6 rpf X:X::X:X` command to docs
[mirror_frr.git] / tests / topotests / isis_sr_te_topo1 / test_isis_sr_te_topo1.py
1 #!/usr/bin/env python
2
3 #
4 # test_isis_sr_topo1.py
5 # Part of NetDEF Topology Tests
6 #
7 # Copyright (c) 2019 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_isis_sr_te_topo1.py:
27
28 +---------+
29 | |
30 | RT1 |
31 | 1.1.1.1 |
32 | |
33 +---------+
34 |eth-sw1
35 |
36 |
37 |
38 +---------+ | +---------+
39 | | | | |
40 | RT2 |eth-sw1 | eth-sw1| RT3 |
41 | 2.2.2.2 +----------+----------+ 3.3.3.3 |
42 | | 10.0.1.0/24 | |
43 +---------+ +---------+
44 eth-rt4-1| |eth-rt4-2 eth-rt5-1| |eth-rt5-2
45 | | | |
46 10.0.2.0/24| |10.0.3.0/24 10.0.4.0/24| |10.0.5.0/24
47 | | | |
48 eth-rt2-1| |eth-rt2-2 eth-rt3-1| |eth-rt3-2
49 +---------+ +---------+
50 | | | |
51 | RT4 | 10.0.6.0/24 | RT5 |
52 | 4.4.4.4 +---------------------+ 5.5.5.5 |
53 | |eth-rt5 eth-rt4| |
54 +---------+ +---------+
55 eth-rt6| |eth-rt6
56 | |
57 10.0.7.0/24| |10.0.8.0/24
58 | +---------+ |
59 | | | |
60 | | RT6 | |
61 +----------+ 6.6.6.6 +-----------+
62 eth-rt4| |eth-rt5
63 +---------+
64 |eth-dst (.1)
65 |
66 |10.0.11.0/24
67 |
68 |eth-rt6 (.2)
69 +---------+
70 | |
71 | DST |
72 | 9.9.9.2 |
73 | |
74 +---------+
75
76 """
77
78 import os
79 import sys
80 import pytest
81 import json
82 from functools import partial
83
84 # Save the Current Working Directory to find configuration files.
85 CWD = os.path.dirname(os.path.realpath(__file__))
86 sys.path.append(os.path.join(CWD, "../"))
87
88 # pylint: disable=C0413
89 # Import topogen and topotest helpers
90 from lib import topotest
91 from lib.topogen import Topogen, TopoRouter, get_topogen
92 from lib.topolog import logger
93
94 # Required to instantiate the topology builder class.
95
96 pytestmark = [pytest.mark.bgpd, pytest.mark.isisd, pytest.mark.pathd]
97
98
99 def build_topo(tgen):
100 "Build function"
101
102 #
103 # Define FRR Routers
104 #
105 for router in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6", "dst"]:
106 tgen.add_router(router)
107
108 #
109 # Define connections
110 #
111 switch = tgen.add_switch("s1")
112 switch.add_link(tgen.gears["rt1"], nodeif="eth-sw1")
113 switch.add_link(tgen.gears["rt2"], nodeif="eth-sw1")
114 switch.add_link(tgen.gears["rt3"], nodeif="eth-sw1")
115
116 switch = tgen.add_switch("s2")
117 switch.add_link(tgen.gears["rt2"], nodeif="eth-rt4-1")
118 switch.add_link(tgen.gears["rt4"], nodeif="eth-rt2-1")
119
120 switch = tgen.add_switch("s3")
121 switch.add_link(tgen.gears["rt2"], nodeif="eth-rt4-2")
122 switch.add_link(tgen.gears["rt4"], nodeif="eth-rt2-2")
123
124 switch = tgen.add_switch("s4")
125 switch.add_link(tgen.gears["rt3"], nodeif="eth-rt5-1")
126 switch.add_link(tgen.gears["rt5"], nodeif="eth-rt3-1")
127
128 switch = tgen.add_switch("s5")
129 switch.add_link(tgen.gears["rt3"], nodeif="eth-rt5-2")
130 switch.add_link(tgen.gears["rt5"], nodeif="eth-rt3-2")
131
132 switch = tgen.add_switch("s6")
133 switch.add_link(tgen.gears["rt4"], nodeif="eth-rt5")
134 switch.add_link(tgen.gears["rt5"], nodeif="eth-rt4")
135
136 switch = tgen.add_switch("s7")
137 switch.add_link(tgen.gears["rt4"], nodeif="eth-rt6")
138 switch.add_link(tgen.gears["rt6"], nodeif="eth-rt4")
139
140 switch = tgen.add_switch("s8")
141 switch.add_link(tgen.gears["rt5"], nodeif="eth-rt6")
142 switch.add_link(tgen.gears["rt6"], nodeif="eth-rt5")
143
144 switch = tgen.add_switch("s9")
145 switch.add_link(tgen.gears["rt6"], nodeif="eth-dst")
146 switch.add_link(tgen.gears["dst"], nodeif="eth-rt6")
147
148
149 def setup_module(mod):
150 "Sets up the pytest environment"
151
152 tgen = Topogen(build_topo, mod.__name__)
153
154 frrdir = tgen.config.get(tgen.CONFIG_SECTION, "frrdir")
155 if not os.path.isfile(os.path.join(frrdir, "pathd")):
156 pytest.skip("pathd daemon wasn't built")
157
158 tgen.start_topology()
159
160 router_list = tgen.routers()
161
162 # For all registered routers, load the zebra configuration file
163 for rname, router in router_list.items():
164 router.load_config(
165 TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
166 )
167 router.load_config(
168 TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname))
169 )
170 router.load_config(
171 TopoRouter.RD_PATH, os.path.join(CWD, "{}/pathd.conf".format(rname))
172 )
173 router.load_config(
174 TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
175 )
176
177 tgen.start_router()
178
179
180 def teardown_module(mod):
181 "Teardown the pytest environment"
182 tgen = get_topogen()
183
184 # This function tears down the whole topology.
185 tgen.stop_topology()
186
187
188 def setup_testcase(msg):
189 logger.info(msg)
190 tgen = get_topogen()
191
192 # Skip if previous fatal error condition is raised
193 if tgen.routers_have_failure():
194 pytest.skip(tgen.errors)
195
196 return tgen
197
198
199 def print_cmd_result(rname, command):
200 print(get_topogen().gears[rname].vtysh_cmd(command, isjson=False))
201
202
203 def compare_json_test(router, command, reference, exact):
204 output = router.vtysh_cmd(command, isjson=True)
205 result = topotest.json_cmp(output, reference)
206
207 # Note: topotest.json_cmp() just checks on inclusion of keys.
208 # For exact matching also compare the other way around.
209 if not result and exact:
210 return topotest.json_cmp(reference, output)
211 else:
212 return result
213
214
215 def cmp_json_output(rname, command, reference, exact=False):
216 "Compare router JSON output"
217
218 logger.info('Comparing router "%s" "%s" output', rname, command)
219
220 tgen = get_topogen()
221 filename = "{}/{}/{}".format(CWD, rname, reference)
222 expected = json.loads(open(filename).read())
223
224 # Run test function until we get an result. Wait at most 60 seconds.
225 test_func = partial(compare_json_test, tgen.gears[rname], command, expected, exact)
226 _, diff = topotest.run_and_expect(test_func, None, count=120, wait=0.5)
227 assertmsg = '"{}" JSON output mismatches the expected result'.format(rname)
228 assert diff is None, assertmsg
229
230
231 def cmp_json_output_exact(rname, command, reference):
232 return cmp_json_output(rname, command, reference, True)
233
234
235 def compare_json_test_inverted(router, command, reference, exact):
236 "logically inverts result of compare_json_test"
237
238 # None vs something else
239 result = compare_json_test(router, command, reference, exact)
240 if result is None:
241 return "Some"
242 return None
243
244
245 def cmp_json_output_doesnt(rname, command, reference):
246 "Compare router JSON output, shouldn't include reference"
247
248 logger.info('Comparing (anti) router "%s" "%s" output', rname, command)
249
250 tgen = get_topogen()
251 filename = "{}/{}/{}".format(CWD, rname, reference)
252 expected = json.loads(open(filename).read())
253
254 # Run test function until we get an result. Wait at most 60 seconds.
255 test_func = partial(
256 compare_json_test_inverted, tgen.gears[rname], command, expected, exact=False
257 )
258 _, diff = topotest.run_and_expect(test_func, None, count=120, wait=0.5)
259 assertmsg = '"{}" JSON output mismatches the expected result'.format(rname)
260 assert diff is None, assertmsg
261
262
263 def dump_json(v):
264 if isinstance(v, (dict, list)):
265 return "\t" + "\t".join(
266 json.dumps(v, indent=4, separators=(",", ": ")).splitlines(True)
267 )
268 else:
269 return "'{}'".format(v)
270
271
272 def add_candidate_path(rname, endpoint, pref, name, segment_list="default", color=1):
273 get_topogen().net[rname].cmd(
274 """ \
275 vtysh -c "conf t" \
276 -c "segment-routing" \
277 -c "traffic-eng" \
278 -c "policy color """
279 + str(color)
280 + " endpoint "
281 + endpoint
282 + """" \
283 -c "candidate-path preference """
284 + str(pref)
285 + """ name """
286 + name
287 + """ explicit segment-list """
288 + segment_list
289 + '''"'''
290 )
291
292
293 def delete_candidate_path(rname, endpoint, pref, color=1):
294 get_topogen().net[rname].cmd(
295 """ \
296 vtysh -c "conf t" \
297 -c "segment-routing" \
298 -c "traffic-eng" \
299 -c "policy color """
300 + str(color)
301 + " endpoint "
302 + endpoint
303 + """" \
304 -c "no candidate-path preference """
305 + str(pref)
306 + '''"'''
307 )
308
309
310 def add_segment(rname, name, index, label):
311 get_topogen().net[rname].cmd(
312 """ \
313 vtysh -c "conf t" \
314 -c "segment-routing" \
315 -c "traffic-eng" \
316 -c "segment-list """
317 + name
318 + """" \
319 -c "index """
320 + str(index)
321 + """ mpls label """
322 + str(label)
323 + '''"'''
324 )
325
326
327 def delete_segment(rname, name, index):
328 get_topogen().net[rname].cmd(
329 """ \
330 vtysh -c "conf t" \
331 -c "segment-routing" \
332 -c "traffic-eng" \
333 -c "segment-list """
334 + name
335 + """" \
336 -c "no index """
337 + str(index)
338 + '''"'''
339 )
340
341
342 def create_sr_policy(rname, endpoint, bsid):
343 get_topogen().net[rname].cmd(
344 """ \
345 vtysh -c "conf t" \
346 -c "segment-routing" \
347 -c "traffic-eng" \
348 -c "policy color 1 endpoint """
349 + endpoint
350 + """" \
351 -c "name default" \
352 -c "binding-sid """
353 + str(bsid)
354 + '''"'''
355 )
356
357
358 def delete_sr_policy(rname, endpoint):
359 get_topogen().net[rname].cmd(
360 """ \
361 vtysh -c "conf t" \
362 -c "segment-routing" \
363 -c "traffic-eng" \
364 -c "no policy color 1 endpoint """
365 + endpoint
366 + '''"'''
367 )
368
369
370 def create_prefix_sid(rname, prefix, sid):
371 get_topogen().net[rname].cmd(
372 """ \
373 vtysh -c "conf t" \
374 -c "router isis 1" \
375 -c "segment-routing prefix """
376 + prefix
377 + " index "
378 + str(sid)
379 + '''"'''
380 )
381
382
383 def delete_prefix_sid(rname, prefix):
384 get_topogen().net[rname].cmd(
385 ''' \
386 vtysh -c "conf t" \
387 -c "router isis 1" \
388 -c "no segment-routing prefix "'''
389 + prefix
390 )
391
392
393 def set_route_map_color(rname, color):
394 get_topogen().net[rname].cmd(
395 ''' \
396 vtysh -c "conf t" \
397 -c "route-map SET_SR_POLICY permit 10" \
398 -c "set sr-te color "'''
399 + str(color)
400 )
401
402
403 def router_bgp_shutdown_neighbor(rname, neighbor):
404 get_topogen().net[rname].cmd(
405 """ \
406 vtysh -c "conf t" \
407 -c "router bgp 1" \
408 -c " neighbor """
409 + neighbor
410 + ' shutdown"'
411 )
412
413
414 def router_bgp_no_shutdown_neighbor(rname, neighbor):
415 get_topogen().net[rname].cmd(
416 """ \
417 vtysh -c "conf t" \
418 -c "router bgp 1" \
419 -c " no neighbor """
420 + neighbor
421 + ' shutdown"'
422 )
423
424
425 def show_running_cfg(rname):
426 output = (
427 get_topogen()
428 .net[rname]
429 .cmd(
430 """ \
431 vtysh -c "show run" """
432 )
433 )
434 logger.info(output)
435
436
437 #
438 # Step 1
439 #
440 # Checking the MPLS table using a single SR Policy and a single Candidate Path
441 #
442 def test_srte_init_step1():
443 setup_testcase("Test (step 1): wait for IS-IS convergence / label distribution")
444
445 for rname in ["rt1", "rt6"]:
446 cmp_json_output(
447 rname, "show mpls table json", "step1/show_mpls_table_without_candidate.ref"
448 )
449
450
451 def test_srte_add_candidate_check_mpls_table_step1():
452 setup_testcase("Test (step 1): check MPLS table regarding the added Candidate Path")
453
454 for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
455 add_candidate_path(rname, endpoint, 100, "default")
456 cmp_json_output(
457 rname, "show mpls table json", "step1/show_mpls_table_with_candidate.ref"
458 )
459 delete_candidate_path(rname, endpoint, 100)
460
461
462 def test_srte_reinstall_sr_policy_check_mpls_table_step1():
463 setup_testcase(
464 "Test (step 1): check MPLS table after the SR Policy was removed and reinstalled"
465 )
466
467 for rname, endpoint, bsid in [("rt1", "6.6.6.6", 1111), ("rt6", "1.1.1.1", 6666)]:
468 add_candidate_path(rname, endpoint, 100, "default")
469 delete_sr_policy(rname, endpoint)
470 cmp_json_output(
471 rname, "show mpls table json", "step1/show_mpls_table_without_candidate.ref"
472 )
473 create_sr_policy(rname, endpoint, bsid)
474 add_candidate_path(rname, endpoint, 100, "default")
475 cmp_json_output(
476 rname, "show mpls table json", "step1/show_mpls_table_with_candidate.ref"
477 )
478 delete_candidate_path(rname, endpoint, 100)
479
480
481 #
482 # Step 2
483 #
484 # Checking pathd operational data using a single SR Policy and a single Candidate Path
485 #
486 def test_srte_bare_policy_step2():
487 setup_testcase("Test (step 2): bare SR Policy should not be operational")
488
489 for rname in ["rt1", "rt6"]:
490 cmp_json_output_exact(
491 rname,
492 "show yang operational-data /frr-pathd:pathd pathd",
493 "step2/show_operational_data.ref",
494 )
495
496
497 def test_srte_add_candidate_check_operational_data_step2():
498 setup_testcase(
499 "Test (step 2): add single Candidate Path, SR Policy should be operational"
500 )
501
502 for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
503 add_candidate_path(rname, endpoint, 100, "default")
504 cmp_json_output(
505 rname,
506 "show yang operational-data /frr-pathd:pathd pathd",
507 "step2/show_operational_data_with_candidate.ref",
508 )
509
510
511 def test_srte_config_remove_candidate_check_operational_data_step2():
512 setup_testcase(
513 "Test (step 2): remove single Candidate Path, SR Policy should not be operational anymore"
514 )
515
516 for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
517 delete_candidate_path(rname, endpoint, 100)
518 cmp_json_output_exact(
519 rname,
520 "show yang operational-data /frr-pathd:pathd pathd",
521 "step2/show_operational_data.ref",
522 )
523
524
525 #
526 # Step 3
527 #
528 # Testing the Candidate Path selection
529 #
530 def test_srte_add_two_candidates_step3():
531 setup_testcase("Test (step 3): second Candidate Path has higher Priority")
532
533 for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
534 for pref, cand_name in [("100", "first"), ("200", "second")]:
535 add_candidate_path(rname, endpoint, pref, cand_name)
536 cmp_json_output(
537 rname,
538 "show yang operational-data /frr-pathd:pathd pathd",
539 "step3/show_operational_data_with_two_candidates.ref",
540 )
541
542 # cleanup
543 for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
544 for pref in ["100", "200"]:
545 delete_candidate_path(rname, endpoint, pref)
546
547
548 def test_srte_add_two_candidates_with_reverse_priority_step3():
549 setup_testcase("Test (step 3): second Candidate Path has lower Priority")
550
551 # Use reversed priorities here
552 for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
553 for pref, cand_name in [("200", "first"), ("100", "second")]:
554 add_candidate_path(rname, endpoint, pref, cand_name)
555 cmp_json_output(
556 rname,
557 "show yang operational-data /frr-pathd:pathd pathd",
558 "step3/show_operational_data_with_two_candidates.ref",
559 )
560
561 # cleanup
562 for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
563 for pref in ["100", "200"]:
564 delete_candidate_path(rname, endpoint, pref)
565
566
567 def test_srte_remove_best_candidate_step3():
568 setup_testcase("Test (step 3): delete the Candidate Path with higher priority")
569
570 for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
571 for pref, cand_name in [("100", "first"), ("200", "second")]:
572 add_candidate_path(rname, endpoint, pref, cand_name)
573
574 # Delete candidate with higher priority
575 for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
576 delete_candidate_path(rname, endpoint, 200)
577
578 # Candidate with lower priority should get active now
579 for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
580 cmp_json_output(
581 rname,
582 "show yang operational-data /frr-pathd:pathd pathd",
583 "step3/show_operational_data_with_single_candidate.ref",
584 )
585 # cleanup
586 delete_candidate_path(rname, endpoint, 100)
587
588
589 #
590 # Step 4
591 #
592 # Checking MPLS table with a single SR Policy and a Candidate Path with different Segment Lists and other modifications
593 #
594 def test_srte_change_segment_list_check_mpls_table_step4():
595 setup_testcase("Test (step 4): check MPLS table for changed Segment List")
596
597 for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
598 add_candidate_path(rname, endpoint, 100, "default")
599 # now change the segment list name
600 add_candidate_path(rname, endpoint, 100, "default", "test")
601 cmp_json_output(rname, "show mpls table json", "step4/show_mpls_table.ref")
602 delete_candidate_path(rname, endpoint, 100)
603
604
605 def test_srte_segment_list_add_segment_check_mpls_table_step4():
606 setup_testcase(
607 "Test (step 4): check MPLS table for added (then changed and finally deleted) segment"
608 )
609
610 add_candidate_path("rt1", "6.6.6.6", 100, "default", "test")
611
612 # first add a new segment
613 add_segment("rt1", "test", 25, 16050)
614 cmp_json_output(
615 "rt1", "show mpls table json", "step4/show_mpls_table_add_segment.ref"
616 )
617
618 # ... then change it ...
619 add_segment("rt1", "test", 25, 16030)
620 cmp_json_output(
621 "rt1", "show mpls table json", "step4/show_mpls_table_change_segment.ref"
622 )
623
624 # ... and finally delete it
625 delete_segment("rt1", "test", 25)
626 cmp_json_output("rt1", "show mpls table json", "step4/show_mpls_table.ref")
627 delete_candidate_path("rt1", "6.6.6.6", 100)
628
629
630 def save_rt(routername, filename):
631 save_filename = routername + "/" + filename
632 tgen = get_topogen()
633 router = tgen.gears[routername]
634
635 config_output = router.vtysh_cmd("sh run")
636
637 route_output_json = json.loads(router.vtysh_cmd("show ip route bgp json"))
638 route_output = dump_json(route_output_json)
639
640 f = open(save_filename, "w")
641 f.write(config_output)
642 f.write(route_output)
643 f.close()
644
645
646 #
647 # Step 5
648 #
649 # Checking the nexthop using a single SR Policy and a Candidate Path with configured route-map
650 #
651 def test_srte_route_map_with_sr_policy_check_nextop_step5():
652 setup_testcase(
653 "Test (step 5): recursive nexthop learned through BGP neighbour should be aligned with SR Policy from route-map"
654 )
655
656 # (re-)build the SR Policy two times to ensure that reinstalling still works
657 for i in [1, 2]:
658 cmp_json_output(
659 "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_inactive_srte.ref"
660 )
661
662 delete_sr_policy("rt1", "6.6.6.6")
663 cmp_json_output(
664 "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_inactive_srte.ref"
665 )
666
667 create_sr_policy("rt1", "6.6.6.6", 1111)
668 cmp_json_output(
669 "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_inactive_srte.ref"
670 )
671
672 add_candidate_path("rt1", "6.6.6.6", 100, "default")
673 cmp_json_output(
674 "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_active_srte.ref"
675 )
676
677 delete_candidate_path("rt1", "6.6.6.6", 100)
678
679
680 def test_srte_route_map_sr_policy_vs_route_order_step5():
681 setup_testcase(
682 "Test (step 5): Config policy first, add route after and check route validity"
683 )
684
685 #
686 # BGP route and route-map are already configured.
687 # route-map sets color 1 on BGP routes
688
689 # Developer: to force pause here
690 # tgen = get_topogen()
691 # tgen.mininet_cli()
692
693 #
694 # Configure policy/path
695 #
696 add_candidate_path("rt1", "6.6.6.6", 100, "default", "default", 1)
697
698 #
699 # Route should be valid
700 #
701 logger.info(
702 "BGP route and route-map are already configured, SR candidate path added after. Route should be valid"
703 )
704 cmp_json_output(
705 "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_active_srte.ref"
706 )
707
708 #
709 # shutdown/no-shutdown on BGP neighbor to delete/re-add BGP route
710 #
711 router_bgp_shutdown_neighbor("rt1", "6.6.6.6")
712 router_bgp_no_shutdown_neighbor("rt1", "6.6.6.6")
713
714 #
715 # Route should be valid (but isn't)
716 #
717 logger.info(
718 "After shutdown + no-shutdown neighbor. Route should be valid, but isn't"
719 )
720 cmp_json_output(
721 "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_active_srte.ref"
722 )
723
724 #
725 # delete and re-add policy/path
726 #
727 delete_candidate_path("rt1", "6.6.6.6", 100, 1)
728 add_candidate_path("rt1", "6.6.6.6", 100, "default", "default", 1)
729
730 #
731 # Route should be valid
732 #
733 logger.info("After re-add candidate path. Route should be valid")
734 cmp_json_output(
735 "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_active_srte.ref"
736 )
737
738 # Developer: to force pause here
739 # tgen = get_topogen()
740 # tgen.mininet_cli()
741
742 # clean up
743 delete_candidate_path("rt1", "6.6.6.6", 100, 2)
744
745
746 def test_srte_route_map_sr_policy_vs_routemap_order_step5():
747 setup_testcase(
748 "Test (step 5): Config policy first, set route-map after and check route validity"
749 )
750
751 #
752 # BGP route and route-map are already configured.
753 # route-map sets color 1 on BGP routes
754 #
755
756 #
757 # Configure policy/path
758 #
759 add_candidate_path("rt1", "6.6.6.6", 100, "default", "default", 1)
760
761 #
762 # Route should be valid
763 #
764 logger.info("After add candidate path. Route should be valid")
765 cmp_json_output(
766 "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_active_srte.ref"
767 )
768
769 # Developer: to force pause here
770 # tgen = get_topogen()
771 # tgen.mininet_cli()
772
773 #
774 # change route-map color to someting else and back again
775 #
776 set_route_map_color("rt1", 2)
777 logger.info("route-map color was set to 2")
778 # show_running_cfg("rt1")
779 # 220625 nexthop no longer becomes empty. Colored routes without
780 # matching SR policies now fall back to their non-colored equivalent
781 # nexthops. So the route to 9.9.9.9/32 will now be valid, but with
782 # different nexthop values.
783 logger.info("now route table will lose policy-mapped route")
784 cmp_json_output_doesnt(
785 "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_active_srte.ref"
786 )
787 set_route_map_color("rt1", 1)
788 logger.info("route-map color was set to 1")
789 # show_running_cfg("rt1")
790
791 #
792 # Route should be valid (but isn't)
793 #
794 logger.info("After change route-map color. Route should be valid, but isn't")
795 cmp_json_output(
796 "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_active_srte.ref"
797 )
798
799 #
800 # delete and re-add policy/path
801 #
802 delete_candidate_path("rt1", "6.6.6.6", 100, 1)
803 add_candidate_path("rt1", "6.6.6.6", 100, "default", "default", 1)
804
805 #
806 # Route should be valid
807 #
808 logger.info("After delete/re-add candidate path. Route should be valid")
809 cmp_json_output(
810 "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_active_srte.ref"
811 )
812
813 # Developer: force pause
814 # tgen = get_topogen()
815 # tgen.mininet_cli()
816
817 # clean up
818 delete_candidate_path("rt1", "6.6.6.6", 100, 2)
819
820
821 def test_srte_route_map_with_sr_policy_reinstall_prefix_sid_check_nextop_step5():
822 setup_testcase(
823 "Test (step 5): remove and re-install prefix SID on fist path element and check SR Policy activity"
824 )
825
826 # first add a candidate path so the SR Policy is active
827 add_candidate_path("rt1", "6.6.6.6", 100, "default")
828 cmp_json_output(
829 "rt1",
830 "show yang operational-data /frr-pathd:pathd pathd",
831 "step5/show_operational_data_active.ref",
832 )
833
834 # delete prefix SID from first element of the configured path and check
835 # if the SR Policy is inactive since the label can't be resolved anymore
836 delete_prefix_sid("rt5", "5.5.5.5/32")
837 cmp_json_output(
838 "rt1",
839 "show yang operational-data /frr-pathd:pathd pathd",
840 "step5/show_operational_data_inactive.ref",
841 )
842 cmp_json_output(
843 "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_inactive_srte.ref"
844 )
845
846 # re-create the prefix SID and check if the SR Policy is active
847 create_prefix_sid("rt5", "5.5.5.5/32", 50)
848 cmp_json_output(
849 "rt1",
850 "show yang operational-data /frr-pathd:pathd pathd",
851 "step5/show_operational_data_active.ref",
852 )
853 cmp_json_output(
854 "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_active_srte.ref"
855 )
856
857
858 # Memory leak test template
859 def test_memory_leak():
860 "Run the memory leak test and report results."
861 tgen = get_topogen()
862 if not tgen.is_memleak_enabled():
863 pytest.skip("Memory leak test/report is disabled")
864
865 tgen.report_memory_leaks()
866
867
868 if __name__ == "__main__":
869 args = ["-s"] + sys.argv[1:]
870 sys.exit(pytest.main(args))