]>
Commit | Line | Data |
---|---|---|
f008db91 JG |
1 | #!/usr/bin/env python |
2 | ||
3 | # | |
4 | # test_ospf_sr_te_topo1.py | |
5 | # | |
6 | # Copyright (c) 2021 by | |
7 | # Volta Networks | |
8 | # | |
9 | # Permission to use, copy, modify, and/or distribute this software | |
10 | # for any purpose with or without fee is hereby granted, provided | |
11 | # that the above copyright notice and this permission notice appear | |
12 | # in all copies. | |
13 | # | |
14 | # THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES | |
15 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
16 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR | |
17 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY | |
18 | # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | |
19 | # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS | |
20 | # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |
21 | # OF THIS SOFTWARE. | |
22 | # | |
23 | ||
24 | """ | |
25 | test_ospf_sr_te_topo1.py: | |
26 | ||
27 | +---------+ | |
28 | | | | |
29 | | RT1 | | |
30 | | 1.1.1.1 | | |
31 | | | | |
32 | +---------+ | |
33 | |eth-sw1 | |
34 | | | |
35 | | | |
36 | | | |
37 | +---------+ | +---------+ | |
38 | | | | | | | |
39 | | RT2 |eth-sw1 | eth-sw1| RT3 | | |
40 | | 2.2.2.2 +----------+ + 3.3.3.3 | | |
41 | | | 10.0.1.0/24 | | | |
42 | +---------+ +---------+ | |
43 | eth-rt4-1| eth-rt5-1| |eth-rt5-2 | |
44 | | | | | |
45 | 10.0.2.0/24| 10.0.4.0/24| |10.0.5.0/24 | |
46 | | | | | |
47 | eth-rt2-1| eth-rt3-1| |eth-rt3-2 | |
48 | +---------+ +---------+ | |
49 | | | | | | |
50 | | RT4 | 10.0.6.0/24 | RT5 | | |
51 | | 4.4.4.4 +---------------------+ 5.5.5.5 | | |
52 | | |eth-rt5 eth-rt4| | | |
53 | +---------+ +---------+ | |
54 | eth-rt6| |eth-rt6 | |
55 | | | | |
56 | 10.0.7.0/24| |10.0.8.0/24 | |
57 | | +---------+ | | |
58 | | | | | | |
59 | | | RT6 | | | |
60 | +----------+ 6.6.6.6 +-----------+ | |
61 | eth-rt4| |eth-rt5 | |
62 | +---------+ | |
63 | |eth-dst (.1) | |
64 | | | |
65 | |10.0.11.0/24 | |
66 | | | |
67 | |eth-rt6 (.2) | |
68 | +---------+ | |
69 | | | | |
70 | | DST | | |
71 | | 9.9.9.2 | | |
72 | | | | |
73 | +---------+ | |
74 | ||
75 | """ | |
76 | ||
77 | import os | |
78 | import sys | |
79 | import pytest | |
80 | import json | |
f008db91 JG |
81 | from time import sleep |
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. | |
f008db91 JG |
95 | |
96 | pytestmark = [pytest.mark.bgpd, pytest.mark.ospfd, pytest.mark.pathd] | |
97 | ||
98 | ||
e82b531d CH |
99 | def build_topo(tgen): |
100 | "Build function" | |
f008db91 | 101 | |
e82b531d CH |
102 | # |
103 | # Define FRR Routers | |
104 | # | |
105 | for router in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6", "dst"]: | |
106 | tgen.add_router(router) | |
f008db91 | 107 | |
e82b531d CH |
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") | |
a53c08bc | 114 | # switch.add_link(tgen.gears["rt3"], nodeif="eth-sw1") |
f008db91 | 115 | |
e82b531d CH |
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") | |
f008db91 | 119 | |
a53c08bc CH |
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") | |
f008db91 | 123 | |
e82b531d CH |
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") | |
f008db91 | 127 | |
e82b531d CH |
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") | |
f008db91 | 131 | |
e82b531d CH |
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") | |
f008db91 | 135 | |
e82b531d CH |
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") | |
f008db91 | 139 | |
e82b531d CH |
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") | |
f008db91 | 143 | |
e82b531d CH |
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") | |
f008db91 JG |
147 | |
148 | ||
149 | def setup_module(mod): | |
150 | "Sets up the pytest environment" | |
151 | ||
e82b531d | 152 | tgen = Topogen(build_topo, mod.__name__) |
f008db91 JG |
153 | |
154 | frrdir = tgen.config.get(tgen.CONFIG_SECTION, "frrdir") | |
155 | if not os.path.isfile(os.path.join(frrdir, "pathd")): | |
a53c08bc | 156 | pytest.skip("pathd daemon wasn't built in:" + frrdir) |
f008db91 JG |
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_OSPF, os.path.join(CWD, "{}/ospfd.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=60, 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 add_candidate_path(rname, endpoint, pref, name, segment_list="default"): | |
236 | get_topogen().net[rname].cmd( | |
237 | """ \ | |
238 | vtysh -c "conf t" \ | |
239 | -c "segment-routing" \ | |
240 | -c "traffic-eng" \ | |
241 | -c "policy color 1 endpoint """ | |
242 | + endpoint | |
243 | + """" \ | |
244 | -c "candidate-path preference """ | |
245 | + str(pref) | |
246 | + """ name """ | |
247 | + name | |
248 | + """ explicit segment-list """ | |
249 | + segment_list | |
250 | + '''"''' | |
251 | ) | |
252 | ||
253 | ||
254 | def delete_candidate_path(rname, endpoint, pref): | |
255 | get_topogen().net[rname].cmd( | |
256 | """ \ | |
257 | vtysh -c "conf t" \ | |
258 | -c "segment-routing" \ | |
259 | -c "traffic-eng" \ | |
260 | -c "policy color 1 endpoint """ | |
261 | + endpoint | |
262 | + """" \ | |
263 | -c "no candidate-path preference """ | |
264 | + str(pref) | |
265 | + '''"''' | |
266 | ) | |
267 | ||
268 | ||
269 | def add_segment(rname, name, index, label): | |
270 | get_topogen().net[rname].cmd( | |
271 | """ \ | |
272 | vtysh -c "conf t" \ | |
273 | -c "segment-routing" \ | |
274 | -c "traffic-eng" \ | |
275 | -c "segment-list """ | |
276 | + name | |
277 | + """" \ | |
278 | -c "index """ | |
279 | + str(index) | |
280 | + """ mpls label """ | |
281 | + str(label) | |
282 | + '''"''' | |
283 | ) | |
284 | ||
285 | ||
286 | def delete_segment(rname, name, index): | |
287 | get_topogen().net[rname].cmd( | |
288 | """ \ | |
289 | vtysh -c "conf t" \ | |
290 | -c "segment-routing" \ | |
291 | -c "traffic-eng" \ | |
292 | -c "segment-list """ | |
293 | + name | |
294 | + """" \ | |
295 | -c "no index """ | |
296 | + str(index) | |
297 | + '''"''' | |
298 | ) | |
299 | ||
300 | ||
301 | def add_segment_adj(rname, name, index, src, dst): | |
302 | get_topogen().net[rname].cmd( | |
303 | """ \ | |
304 | vtysh -c "conf t" \ | |
305 | -c "segment-routing" \ | |
306 | -c "traffic-eng" \ | |
307 | -c "segment-list """ | |
308 | + name | |
309 | + """" \ | |
310 | -c "index """ | |
311 | + str(index) | |
312 | + """ nai adjacency """ | |
313 | + str(src) | |
314 | + """ """ | |
315 | + str(dst) | |
316 | + '''"''' | |
317 | ) | |
318 | ||
319 | ||
320 | def create_sr_policy(rname, endpoint, bsid): | |
321 | get_topogen().net[rname].cmd( | |
322 | """ \ | |
323 | vtysh -c "conf t" \ | |
324 | -c "segment-routing" \ | |
325 | -c "traffic-eng" \ | |
326 | -c "policy color 1 endpoint """ | |
327 | + endpoint | |
328 | + """" \ | |
329 | -c "name default" \ | |
330 | -c "binding-sid """ | |
331 | + str(bsid) | |
332 | + '''"''' | |
333 | ) | |
334 | ||
335 | ||
336 | def delete_sr_policy(rname, endpoint): | |
337 | get_topogen().net[rname].cmd( | |
338 | """ \ | |
339 | vtysh -c "conf t" \ | |
340 | -c "segment-routing" \ | |
341 | -c "traffic-eng" \ | |
342 | -c "no policy color 1 endpoint """ | |
343 | + endpoint | |
344 | + '''"''' | |
345 | ) | |
346 | ||
347 | ||
348 | def create_prefix_sid(rname, prefix, sid): | |
349 | get_topogen().net[rname].cmd( | |
350 | """ \ | |
351 | vtysh -c "conf t" \ | |
352 | -c "router ospf " \ | |
353 | -c "segment-routing prefix """ | |
354 | + prefix | |
355 | + " index " | |
356 | + str(sid) | |
357 | + '''"''' | |
358 | ) | |
359 | ||
360 | ||
361 | def delete_prefix_sid(rname, prefix): | |
362 | get_topogen().net[rname].cmd( | |
363 | ''' \ | |
364 | vtysh -c "conf t" \ | |
365 | -c "router ospf " \ | |
366 | -c "no segment-routing prefix "''' | |
367 | + prefix | |
368 | ) | |
369 | ||
370 | ||
371 | def check_bsid(rt, bsid, fn_name, positive): | |
372 | """ | |
373 | Search for a bsid in rt1 and rt6 | |
374 | Positive means that check is true is bsid is found | |
375 | Positive="False" means that check is true is bsid is NOT found | |
376 | """ | |
377 | ||
378 | logger.info('Checking "%s" bsid "%s" for router "%s" ', positive, bsid, rt) | |
379 | ||
380 | count = 0 | |
381 | candidate_key = bsid | |
382 | candidate_output = "" | |
383 | # First wait for convergence | |
384 | tgen = get_topogen() | |
385 | while count < 30: | |
386 | matched = False | |
387 | matched_key = False | |
388 | sleep(1) | |
389 | count += 1 | |
390 | router = tgen.gears[rt] | |
391 | candidate_output = router.vtysh_cmd("show mpls table json") | |
392 | candidate_output_json = json.loads(candidate_output) | |
393 | for item in candidate_output_json.items(): | |
a53c08bc CH |
394 | # logger.info('item "%s"', item) |
395 | if item[0] == candidate_key: | |
396 | matched_key = True | |
397 | if positive: | |
398 | break | |
f008db91 JG |
399 | if positive: |
400 | if matched_key: | |
401 | matched = True | |
402 | assertmsg = "{} don't has entry {} but is was expected".format( | |
a53c08bc CH |
403 | router.name, candidate_key |
404 | ) | |
f008db91 JG |
405 | else: |
406 | if not matched_key: | |
407 | matched = True | |
408 | assertmsg = "{} has entry {} but is wans't expected".format( | |
a53c08bc CH |
409 | router.name, candidate_key |
410 | ) | |
f008db91 JG |
411 | if matched: |
412 | logger.info('Success "%s" in "%s"', router.name, fn_name) | |
413 | return | |
414 | assert matched, assertmsg | |
415 | ||
416 | ||
417 | # | |
418 | # Step 1 | |
419 | # | |
420 | # Checking the MPLS table using a single SR Policy and a single Candidate Path | |
421 | # Segment list are base in adjacency that query TED | |
422 | # | |
423 | def test_srte_init_step1(): | |
424 | setup_testcase("Test (step 1): wait OSPF convergence / label distribution") | |
425 | ||
426 | check_bsid("rt1", "1111", test_srte_init_step1.__name__, False) | |
427 | check_bsid("rt6", "6666", test_srte_init_step1.__name__, False) | |
428 | ||
429 | ||
430 | def test_srte_add_candidate_check_mpls_table_step1(): | |
431 | setup_testcase("Test (step 1): check MPLS table regarding the added Candidate Path") | |
432 | ||
433 | for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]: | |
434 | add_candidate_path(rname, endpoint, 100, "default") | |
a53c08bc CH |
435 | check_bsid( |
436 | rname, | |
437 | "1111" if rname == "rt1" else "6666", | |
438 | test_srte_init_step1.__name__, | |
439 | True, | |
440 | ) | |
f008db91 JG |
441 | delete_candidate_path(rname, endpoint, 100) |
442 | ||
443 | ||
444 | def test_srte_reinstall_sr_policy_check_mpls_table_step1(): | |
445 | setup_testcase( | |
446 | "Test (step 1): check MPLS table after the SR Policy was removed and reinstalled" | |
447 | ) | |
448 | ||
449 | for rname, endpoint, bsid in [("rt1", "6.6.6.6", 1111), ("rt6", "1.1.1.1", 6666)]: | |
450 | add_candidate_path(rname, endpoint, 100, "default") | |
451 | delete_sr_policy(rname, endpoint) | |
452 | check_bsid(rname, bsid, test_srte_init_step1.__name__, False) | |
453 | create_sr_policy(rname, endpoint, bsid) | |
454 | add_candidate_path(rname, endpoint, 100, "default") | |
a53c08bc CH |
455 | check_bsid( |
456 | rname, | |
457 | "1111" if rname == "rt1" else "6666", | |
458 | test_srte_init_step1.__name__, | |
459 | True, | |
460 | ) | |
f008db91 JG |
461 | delete_candidate_path(rname, endpoint, 100) |
462 | ||
463 | ||
464 | # | |
465 | # Step 2 | |
466 | # | |
467 | # Checking pathd operational data using a single SR Policy and a single Candidate Path | |
468 | # Segment list are base in adjacency that query TED | |
469 | # | |
470 | def test_srte_bare_policy_step2(): | |
471 | setup_testcase("Test (step 2): bare SR Policy should not be operational") | |
472 | ||
473 | for rname in ["rt1", "rt6"]: | |
474 | cmp_json_output_exact( | |
475 | rname, | |
476 | "show yang operational-data /frr-pathd:pathd pathd", | |
477 | "step2/show_operational_data.ref", | |
478 | ) | |
479 | ||
480 | ||
481 | def test_srte_add_candidate_check_operational_data_step2(): | |
482 | setup_testcase( | |
483 | "Test (step 2): add single Candidate Path, SR Policy should be operational" | |
484 | ) | |
485 | ||
486 | for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]: | |
487 | add_candidate_path(rname, endpoint, 100, "default") | |
488 | cmp_json_output( | |
489 | rname, | |
490 | "show yang operational-data /frr-pathd:pathd pathd", | |
491 | "step2/show_operational_data_with_candidate.ref", | |
492 | ) | |
493 | ||
494 | ||
495 | def test_srte_config_remove_candidate_check_operational_data_step2(): | |
496 | setup_testcase( | |
497 | "Test (step 2): remove single Candidate Path, SR Policy should not be operational anymore" | |
498 | ) | |
499 | ||
500 | for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]: | |
501 | delete_candidate_path(rname, endpoint, 100) | |
502 | cmp_json_output_exact( | |
503 | rname, | |
504 | "show yang operational-data /frr-pathd:pathd pathd", | |
505 | "step2/show_operational_data.ref", | |
506 | ) | |
507 | ||
508 | ||
509 | # | |
510 | # Step 3 | |
511 | # | |
512 | # Testing the Candidate Path selection | |
513 | # Segment list are based in adjacencies resolved by query TED | |
514 | # | |
515 | def test_srte_add_two_candidates_step3(): | |
516 | setup_testcase("Test (step 3): second Candidate Path has higher Priority") | |
517 | ||
518 | for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]: | |
519 | for pref, cand_name in [("100", "first"), ("200", "second")]: | |
520 | add_candidate_path(rname, endpoint, pref, cand_name) | |
521 | cmp_json_output( | |
522 | rname, | |
523 | "show yang operational-data /frr-pathd:pathd pathd", | |
524 | "step3/show_operational_data_with_two_candidates.ref", | |
525 | ) | |
526 | ||
527 | # cleanup | |
528 | for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]: | |
529 | for pref in ["100", "200"]: | |
530 | delete_candidate_path(rname, endpoint, pref) | |
531 | ||
532 | ||
533 | def test_srte_add_two_candidates_with_reverse_priority_step3(): | |
534 | setup_testcase("Test (step 3): second Candidate Path has lower Priority") | |
535 | ||
536 | # Use reversed priorities here | |
537 | for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]: | |
538 | for pref, cand_name in [("200", "first"), ("100", "second")]: | |
539 | add_candidate_path(rname, endpoint, pref, cand_name) | |
540 | cmp_json_output( | |
541 | rname, | |
542 | "show yang operational-data /frr-pathd:pathd pathd", | |
543 | "step3/show_operational_data_with_two_candidates.ref", | |
544 | ) | |
545 | ||
546 | # cleanup | |
547 | for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]: | |
548 | for pref in ["100", "200"]: | |
549 | delete_candidate_path(rname, endpoint, pref) | |
550 | ||
551 | ||
552 | def test_srte_remove_best_candidate_step3(): | |
553 | setup_testcase("Test (step 3): delete the Candidate Path with higher priority") | |
554 | ||
555 | for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]: | |
556 | for pref, cand_name in [("100", "first"), ("200", "second")]: | |
557 | add_candidate_path(rname, endpoint, pref, cand_name) | |
558 | ||
559 | # Delete candidate with higher priority | |
560 | for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]: | |
561 | delete_candidate_path(rname, endpoint, 200) | |
562 | ||
563 | # Candidate with lower priority should get active now | |
564 | for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]: | |
565 | cmp_json_output( | |
566 | rname, | |
567 | "show yang operational-data /frr-pathd:pathd pathd", | |
568 | "step3/show_operational_data_with_single_candidate.ref", | |
569 | ) | |
570 | # cleanup | |
571 | delete_candidate_path(rname, endpoint, 100) | |
572 | ||
573 | ||
574 | # | |
575 | # Step 4 | |
576 | # | |
577 | # Checking MPLS table with a single SR Policy and a Candidate Path with different Segment Lists and other modifications | |
578 | # Segment list are base in adjacency that query TED | |
579 | # | |
580 | def test_srte_change_segment_list_check_mpls_table_step4(): | |
581 | setup_testcase("Test (step 4): check MPLS table for changed Segment List") | |
582 | ||
583 | for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]: | |
584 | add_candidate_path(rname, endpoint, 100, "default") | |
585 | # now change the segment list name | |
586 | add_candidate_path(rname, endpoint, 100, "default", "test") | |
a53c08bc CH |
587 | check_bsid( |
588 | rname, | |
589 | "1111" if rname == "rt1" else "6666", | |
590 | test_srte_init_step1.__name__, | |
591 | True, | |
592 | ) | |
f008db91 JG |
593 | delete_segment(rname, "test", 10) |
594 | delete_segment(rname, "test", 20) | |
595 | delete_segment(rname, "test", 30) | |
596 | delete_segment(rname, "test", 40) | |
597 | if rname == "rt1": | |
598 | add_segment_adj(rname, "test", 10, "10.0.1.1", "10.0.1.2") | |
599 | add_segment_adj(rname, "test", 20, "10.0.2.2", "10.0.2.4") | |
600 | add_segment_adj(rname, "test", 30, "10.0.6.4", "10.0.6.5") | |
601 | add_segment_adj(rname, "test", 40, "10.0.8.5", "10.0.8.6") | |
602 | else: | |
603 | add_segment_adj(rname, "test", 10, "10.0.8.6", "10.0.8.5") | |
604 | add_segment_adj(rname, "test", 20, "10.0.6.5", "10.0.6.4") | |
605 | add_segment_adj(rname, "test", 30, "10.0.2.4", "10.0.2.2") | |
606 | add_segment_adj(rname, "test", 40, "10.0.1.2", "10.0.1.1") | |
a53c08bc CH |
607 | check_bsid( |
608 | rname, | |
609 | "1111" if rname == "rt1" else "6666", | |
610 | test_srte_init_step1.__name__, | |
611 | True, | |
612 | ) | |
f008db91 JG |
613 | delete_candidate_path(rname, endpoint, 100) |
614 | ||
615 | ||
616 | def test_srte_change_sl_priority_error_ted_check_mpls_table_step4(): | |
617 | setup_testcase("Test (step 4): check MPLS table keeps low prio sl") | |
618 | ||
619 | for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]: | |
620 | add_candidate_path(rname, endpoint, 100, "default") | |
621 | # now change the segment list name | |
622 | add_candidate_path(rname, endpoint, 200, "test", "test") | |
a53c08bc CH |
623 | check_bsid( |
624 | rname, | |
625 | "1111" if rname == "rt1" else "6666", | |
626 | test_srte_init_step1.__name__, | |
627 | True, | |
628 | ) | |
f008db91 JG |
629 | delete_segment(rname, "test", 10) |
630 | delete_segment(rname, "test", 20) | |
631 | delete_segment(rname, "test", 30) | |
632 | delete_segment(rname, "test", 40) | |
633 | # These won't resolv | |
634 | if rname == "rt1": | |
635 | add_segment_adj(rname, "test", 10, "10.0.1.99", "10.0.1.99") | |
636 | add_segment_adj(rname, "test", 20, "10.0.2.99", "10.0.2.99") | |
637 | add_segment_adj(rname, "test", 30, "10.0.6.99", "10.0.6.99") | |
638 | add_segment_adj(rname, "test", 40, "10.0.8.99", "10.0.8.99") | |
639 | else: | |
640 | add_segment_adj(rname, "test", 10, "10.0.8.99", "10.0.8.99") | |
641 | add_segment_adj(rname, "test", 20, "10.0.6.99", "10.0.6.99") | |
642 | add_segment_adj(rname, "test", 30, "10.0.2.99", "10.0.2.99") | |
643 | add_segment_adj(rname, "test", 40, "10.0.1.99", "10.0.1.99") | |
644 | # So policy sticks with default sl even higher prio | |
a53c08bc CH |
645 | check_bsid( |
646 | rname, | |
647 | "1111" if rname == "rt1" else "6666", | |
648 | test_srte_init_step1.__name__, | |
649 | True, | |
650 | ) | |
f008db91 JG |
651 | delete_candidate_path(rname, endpoint, 100) |
652 | ||
653 | ||
654 | # Memory leak test template | |
655 | def test_memory_leak(): | |
656 | "Run the memory leak test and report results." | |
657 | tgen = get_topogen() | |
658 | if not tgen.is_memleak_enabled(): | |
659 | pytest.skip("Memory leak test/report is disabled") | |
660 | ||
661 | tgen.report_memory_leaks() | |
662 | ||
663 | ||
664 | if __name__ == "__main__": | |
665 | args = ["-s"] + sys.argv[1:] | |
666 | sys.exit(pytest.main(args)) |