]>
Commit | Line | Data |
---|---|---|
4d7b695d SM |
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 | import re | |
83 | from time import sleep | |
84 | from functools import partial | |
85 | ||
86 | # Save the Current Working Directory to find configuration files. | |
87 | CWD = os.path.dirname(os.path.realpath(__file__)) | |
5980ad0a | 88 | sys.path.append(os.path.join(CWD, "../")) |
4d7b695d SM |
89 | |
90 | # pylint: disable=C0413 | |
91 | # Import topogen and topotest helpers | |
92 | from lib import topotest | |
93 | from lib.topogen import Topogen, TopoRouter, get_topogen | |
94 | from lib.topolog import logger | |
95 | ||
96 | # Required to instantiate the topology builder class. | |
8db751b8 | 97 | from lib.micronet_compat import Topo |
4d7b695d | 98 | |
785eb4f7 DS |
99 | pytestmark = [pytest.mark.bgpd, pytest.mark.isisd, pytest.mark.pathd] |
100 | ||
6907ac7e | 101 | |
4d7b695d SM |
102 | class TemplateTopo(Topo): |
103 | "Test topology builder" | |
5980ad0a | 104 | |
4d7b695d SM |
105 | def build(self, *_args, **_opts): |
106 | "Build function" | |
107 | tgen = get_topogen(self) | |
108 | ||
109 | # | |
110 | # Define FRR Routers | |
111 | # | |
5980ad0a | 112 | for router in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6", "dst"]: |
4d7b695d SM |
113 | tgen.add_router(router) |
114 | ||
115 | # | |
116 | # Define connections | |
117 | # | |
5980ad0a DS |
118 | switch = tgen.add_switch("s1") |
119 | switch.add_link(tgen.gears["rt1"], nodeif="eth-sw1") | |
120 | switch.add_link(tgen.gears["rt2"], nodeif="eth-sw1") | |
121 | switch.add_link(tgen.gears["rt3"], nodeif="eth-sw1") | |
122 | ||
123 | switch = tgen.add_switch("s2") | |
124 | switch.add_link(tgen.gears["rt2"], nodeif="eth-rt4-1") | |
125 | switch.add_link(tgen.gears["rt4"], nodeif="eth-rt2-1") | |
4d7b695d | 126 | |
5980ad0a DS |
127 | switch = tgen.add_switch("s3") |
128 | switch.add_link(tgen.gears["rt2"], nodeif="eth-rt4-2") | |
129 | switch.add_link(tgen.gears["rt4"], nodeif="eth-rt2-2") | |
4d7b695d | 130 | |
5980ad0a DS |
131 | switch = tgen.add_switch("s4") |
132 | switch.add_link(tgen.gears["rt3"], nodeif="eth-rt5-1") | |
133 | switch.add_link(tgen.gears["rt5"], nodeif="eth-rt3-1") | |
4d7b695d | 134 | |
5980ad0a DS |
135 | switch = tgen.add_switch("s5") |
136 | switch.add_link(tgen.gears["rt3"], nodeif="eth-rt5-2") | |
137 | switch.add_link(tgen.gears["rt5"], nodeif="eth-rt3-2") | |
4d7b695d | 138 | |
5980ad0a DS |
139 | switch = tgen.add_switch("s6") |
140 | switch.add_link(tgen.gears["rt4"], nodeif="eth-rt5") | |
141 | switch.add_link(tgen.gears["rt5"], nodeif="eth-rt4") | |
4d7b695d | 142 | |
5980ad0a DS |
143 | switch = tgen.add_switch("s7") |
144 | switch.add_link(tgen.gears["rt4"], nodeif="eth-rt6") | |
145 | switch.add_link(tgen.gears["rt6"], nodeif="eth-rt4") | |
4d7b695d | 146 | |
5980ad0a DS |
147 | switch = tgen.add_switch("s8") |
148 | switch.add_link(tgen.gears["rt5"], nodeif="eth-rt6") | |
149 | switch.add_link(tgen.gears["rt6"], nodeif="eth-rt5") | |
4d7b695d | 150 | |
5980ad0a DS |
151 | switch = tgen.add_switch("s9") |
152 | switch.add_link(tgen.gears["rt6"], nodeif="eth-dst") | |
153 | switch.add_link(tgen.gears["dst"], nodeif="eth-rt6") | |
4d7b695d | 154 | |
4d7b695d SM |
155 | |
156 | def setup_module(mod): | |
157 | "Sets up the pytest environment" | |
f7f6a796 | 158 | |
4d7b695d | 159 | tgen = Topogen(TemplateTopo, mod.__name__) |
f7f6a796 SM |
160 | |
161 | frrdir = tgen.config.get(tgen.CONFIG_SECTION, "frrdir") | |
162 | if not os.path.isfile(os.path.join(frrdir, "pathd")): | |
163 | pytest.skip("pathd daemon wasn't built") | |
164 | ||
4d7b695d SM |
165 | tgen.start_topology() |
166 | ||
167 | router_list = tgen.routers() | |
168 | ||
169 | # For all registered routers, load the zebra configuration file | |
d7d21c3a | 170 | for rname, router in router_list.items(): |
4d7b695d | 171 | router.load_config( |
5980ad0a | 172 | TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) |
4d7b695d SM |
173 | ) |
174 | router.load_config( | |
5980ad0a | 175 | TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname)) |
4d7b695d SM |
176 | ) |
177 | router.load_config( | |
5980ad0a | 178 | TopoRouter.RD_PATH, os.path.join(CWD, "{}/pathd.conf".format(rname)) |
4d7b695d SM |
179 | ) |
180 | router.load_config( | |
5980ad0a | 181 | TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname)) |
4d7b695d SM |
182 | ) |
183 | ||
184 | tgen.start_router() | |
185 | ||
5980ad0a | 186 | |
4d7b695d SM |
187 | def teardown_module(mod): |
188 | "Teardown the pytest environment" | |
189 | tgen = get_topogen() | |
190 | ||
191 | # This function tears down the whole topology. | |
192 | tgen.stop_topology() | |
193 | ||
5980ad0a | 194 | |
4d7b695d SM |
195 | def setup_testcase(msg): |
196 | logger.info(msg) | |
197 | tgen = get_topogen() | |
198 | ||
199 | # Skip if previous fatal error condition is raised | |
200 | if tgen.routers_have_failure(): | |
201 | pytest.skip(tgen.errors) | |
202 | ||
203 | return tgen | |
204 | ||
5980ad0a | 205 | |
4d7b695d SM |
206 | def print_cmd_result(rname, command): |
207 | print(get_topogen().gears[rname].vtysh_cmd(command, isjson=False)) | |
208 | ||
5980ad0a | 209 | |
4d7b695d SM |
210 | def compare_json_test(router, command, reference, exact): |
211 | output = router.vtysh_cmd(command, isjson=True) | |
212 | result = topotest.json_cmp(output, reference) | |
213 | ||
214 | # Note: topotest.json_cmp() just checks on inclusion of keys. | |
215 | # For exact matching also compare the other way around. | |
216 | if not result and exact: | |
5980ad0a | 217 | return topotest.json_cmp(reference, output) |
4d7b695d | 218 | else: |
5980ad0a DS |
219 | return result |
220 | ||
4d7b695d SM |
221 | |
222 | def cmp_json_output(rname, command, reference, exact=False): | |
223 | "Compare router JSON output" | |
224 | ||
225 | logger.info('Comparing router "%s" "%s" output', rname, command) | |
226 | ||
227 | tgen = get_topogen() | |
5980ad0a | 228 | filename = "{}/{}/{}".format(CWD, rname, reference) |
4d7b695d SM |
229 | expected = json.loads(open(filename).read()) |
230 | ||
231 | # Run test function until we get an result. Wait at most 60 seconds. | |
5980ad0a | 232 | test_func = partial(compare_json_test, tgen.gears[rname], command, expected, exact) |
4d7b695d SM |
233 | _, diff = topotest.run_and_expect(test_func, None, count=120, wait=0.5) |
234 | assertmsg = '"{}" JSON output mismatches the expected result'.format(rname) | |
235 | assert diff is None, assertmsg | |
236 | ||
5980ad0a | 237 | |
4d7b695d SM |
238 | def cmp_json_output_exact(rname, command, reference): |
239 | return cmp_json_output(rname, command, reference, True) | |
240 | ||
5980ad0a DS |
241 | |
242 | def add_candidate_path(rname, endpoint, pref, name, segment_list="default"): | |
243 | get_topogen().net[rname].cmd( | |
244 | """ \ | |
4d7b695d SM |
245 | vtysh -c "conf t" \ |
246 | -c "segment-routing" \ | |
247 | -c "traffic-eng" \ | |
5980ad0a DS |
248 | -c "policy color 1 endpoint """ |
249 | + endpoint | |
250 | + """" \ | |
251 | -c "candidate-path preference """ | |
252 | + str(pref) | |
253 | + """ name """ | |
254 | + name | |
255 | + """ explicit segment-list """ | |
256 | + segment_list | |
257 | + '''"''' | |
258 | ) | |
259 | ||
4d7b695d SM |
260 | |
261 | def delete_candidate_path(rname, endpoint, pref): | |
5980ad0a DS |
262 | get_topogen().net[rname].cmd( |
263 | """ \ | |
4d7b695d SM |
264 | vtysh -c "conf t" \ |
265 | -c "segment-routing" \ | |
266 | -c "traffic-eng" \ | |
5980ad0a DS |
267 | -c "policy color 1 endpoint """ |
268 | + endpoint | |
269 | + """" \ | |
270 | -c "no candidate-path preference """ | |
271 | + str(pref) | |
272 | + '''"''' | |
273 | ) | |
274 | ||
4d7b695d SM |
275 | |
276 | def add_segment(rname, name, index, label): | |
5980ad0a DS |
277 | get_topogen().net[rname].cmd( |
278 | """ \ | |
4d7b695d SM |
279 | vtysh -c "conf t" \ |
280 | -c "segment-routing" \ | |
281 | -c "traffic-eng" \ | |
5980ad0a DS |
282 | -c "segment-list """ |
283 | + name | |
284 | + """" \ | |
285 | -c "index """ | |
286 | + str(index) | |
287 | + """ mpls label """ | |
288 | + str(label) | |
289 | + '''"''' | |
290 | ) | |
291 | ||
4d7b695d SM |
292 | |
293 | def delete_segment(rname, name, index): | |
5980ad0a DS |
294 | get_topogen().net[rname].cmd( |
295 | """ \ | |
4d7b695d SM |
296 | vtysh -c "conf t" \ |
297 | -c "segment-routing" \ | |
298 | -c "traffic-eng" \ | |
5980ad0a DS |
299 | -c "segment-list """ |
300 | + name | |
301 | + """" \ | |
302 | -c "no index """ | |
303 | + str(index) | |
304 | + '''"''' | |
305 | ) | |
306 | ||
4d7b695d SM |
307 | |
308 | def create_sr_policy(rname, endpoint, bsid): | |
5980ad0a DS |
309 | get_topogen().net[rname].cmd( |
310 | """ \ | |
4d7b695d SM |
311 | vtysh -c "conf t" \ |
312 | -c "segment-routing" \ | |
313 | -c "traffic-eng" \ | |
5980ad0a DS |
314 | -c "policy color 1 endpoint """ |
315 | + endpoint | |
316 | + """" \ | |
4d7b695d | 317 | -c "name default" \ |
5980ad0a DS |
318 | -c "binding-sid """ |
319 | + str(bsid) | |
320 | + '''"''' | |
321 | ) | |
322 | ||
4d7b695d SM |
323 | |
324 | def delete_sr_policy(rname, endpoint): | |
5980ad0a DS |
325 | get_topogen().net[rname].cmd( |
326 | """ \ | |
4d7b695d SM |
327 | vtysh -c "conf t" \ |
328 | -c "segment-routing" \ | |
329 | -c "traffic-eng" \ | |
5980ad0a DS |
330 | -c "no policy color 1 endpoint """ |
331 | + endpoint | |
332 | + '''"''' | |
333 | ) | |
334 | ||
4d7b695d SM |
335 | |
336 | def create_prefix_sid(rname, prefix, sid): | |
5980ad0a DS |
337 | get_topogen().net[rname].cmd( |
338 | """ \ | |
4d7b695d SM |
339 | vtysh -c "conf t" \ |
340 | -c "router isis 1" \ | |
5980ad0a DS |
341 | -c "segment-routing prefix """ |
342 | + prefix | |
343 | + " index " | |
344 | + str(sid) | |
345 | + '''"''' | |
346 | ) | |
347 | ||
4d7b695d SM |
348 | |
349 | def delete_prefix_sid(rname, prefix): | |
5980ad0a DS |
350 | get_topogen().net[rname].cmd( |
351 | ''' \ | |
4d7b695d SM |
352 | vtysh -c "conf t" \ |
353 | -c "router isis 1" \ | |
5980ad0a DS |
354 | -c "no segment-routing prefix "''' |
355 | + prefix | |
356 | ) | |
357 | ||
4d7b695d SM |
358 | |
359 | # | |
360 | # Step 1 | |
361 | # | |
362 | # Checking the MPLS table using a single SR Policy and a single Candidate Path | |
363 | # | |
364 | def test_srte_init_step1(): | |
365 | setup_testcase("Test (step 1): wait for IS-IS convergence / label distribution") | |
366 | ||
5980ad0a DS |
367 | for rname in ["rt1", "rt6"]: |
368 | cmp_json_output( | |
369 | rname, "show mpls table json", "step1/show_mpls_table_without_candidate.ref" | |
370 | ) | |
371 | ||
4d7b695d SM |
372 | |
373 | def test_srte_add_candidate_check_mpls_table_step1(): | |
374 | setup_testcase("Test (step 1): check MPLS table regarding the added Candidate Path") | |
375 | ||
5980ad0a DS |
376 | for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]: |
377 | add_candidate_path(rname, endpoint, 100, "default") | |
378 | cmp_json_output( | |
379 | rname, "show mpls table json", "step1/show_mpls_table_with_candidate.ref" | |
380 | ) | |
4d7b695d SM |
381 | delete_candidate_path(rname, endpoint, 100) |
382 | ||
5980ad0a | 383 | |
4d7b695d | 384 | def test_srte_reinstall_sr_policy_check_mpls_table_step1(): |
5980ad0a DS |
385 | setup_testcase( |
386 | "Test (step 1): check MPLS table after the SR Policy was removed and reinstalled" | |
387 | ) | |
4d7b695d | 388 | |
5980ad0a DS |
389 | for rname, endpoint, bsid in [("rt1", "6.6.6.6", 1111), ("rt6", "1.1.1.1", 6666)]: |
390 | add_candidate_path(rname, endpoint, 100, "default") | |
4d7b695d | 391 | delete_sr_policy(rname, endpoint) |
5980ad0a DS |
392 | cmp_json_output( |
393 | rname, "show mpls table json", "step1/show_mpls_table_without_candidate.ref" | |
394 | ) | |
4d7b695d | 395 | create_sr_policy(rname, endpoint, bsid) |
5980ad0a DS |
396 | add_candidate_path(rname, endpoint, 100, "default") |
397 | cmp_json_output( | |
398 | rname, "show mpls table json", "step1/show_mpls_table_with_candidate.ref" | |
399 | ) | |
4d7b695d SM |
400 | delete_candidate_path(rname, endpoint, 100) |
401 | ||
5980ad0a | 402 | |
4d7b695d SM |
403 | # |
404 | # Step 2 | |
405 | # | |
406 | # Checking pathd operational data using a single SR Policy and a single Candidate Path | |
407 | # | |
408 | def test_srte_bare_policy_step2(): | |
409 | setup_testcase("Test (step 2): bare SR Policy should not be operational") | |
410 | ||
5980ad0a DS |
411 | for rname in ["rt1", "rt6"]: |
412 | cmp_json_output_exact( | |
413 | rname, | |
414 | "show yang operational-data /frr-pathd:pathd pathd", | |
415 | "step2/show_operational_data.ref", | |
416 | ) | |
417 | ||
4d7b695d SM |
418 | |
419 | def test_srte_add_candidate_check_operational_data_step2(): | |
5980ad0a DS |
420 | setup_testcase( |
421 | "Test (step 2): add single Candidate Path, SR Policy should be operational" | |
422 | ) | |
423 | ||
424 | for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]: | |
425 | add_candidate_path(rname, endpoint, 100, "default") | |
426 | cmp_json_output( | |
427 | rname, | |
428 | "show yang operational-data /frr-pathd:pathd pathd", | |
429 | "step2/show_operational_data_with_candidate.ref", | |
430 | ) | |
4d7b695d | 431 | |
4d7b695d SM |
432 | |
433 | def test_srte_config_remove_candidate_check_operational_data_step2(): | |
5980ad0a DS |
434 | setup_testcase( |
435 | "Test (step 2): remove single Candidate Path, SR Policy should not be operational anymore" | |
436 | ) | |
4d7b695d | 437 | |
5980ad0a | 438 | for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]: |
4d7b695d | 439 | delete_candidate_path(rname, endpoint, 100) |
5980ad0a DS |
440 | cmp_json_output_exact( |
441 | rname, | |
442 | "show yang operational-data /frr-pathd:pathd pathd", | |
443 | "step2/show_operational_data.ref", | |
444 | ) | |
445 | ||
4d7b695d SM |
446 | |
447 | # | |
448 | # Step 3 | |
449 | # | |
450 | # Testing the Candidate Path selection | |
451 | # | |
452 | def test_srte_add_two_candidates_step3(): | |
453 | setup_testcase("Test (step 3): second Candidate Path has higher Priority") | |
454 | ||
5980ad0a DS |
455 | for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]: |
456 | for pref, cand_name in [("100", "first"), ("200", "second")]: | |
4d7b695d | 457 | add_candidate_path(rname, endpoint, pref, cand_name) |
5980ad0a DS |
458 | cmp_json_output( |
459 | rname, | |
460 | "show yang operational-data /frr-pathd:pathd pathd", | |
461 | "step3/show_operational_data_with_two_candidates.ref", | |
462 | ) | |
4d7b695d SM |
463 | |
464 | # cleanup | |
5980ad0a DS |
465 | for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]: |
466 | for pref in ["100", "200"]: | |
4d7b695d SM |
467 | delete_candidate_path(rname, endpoint, pref) |
468 | ||
5980ad0a | 469 | |
4d7b695d SM |
470 | def test_srte_add_two_candidates_with_reverse_priority_step3(): |
471 | setup_testcase("Test (step 3): second Candidate Path has lower Priority") | |
472 | ||
473 | # Use reversed priorities here | |
5980ad0a DS |
474 | for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]: |
475 | for pref, cand_name in [("200", "first"), ("100", "second")]: | |
4d7b695d | 476 | add_candidate_path(rname, endpoint, pref, cand_name) |
5980ad0a DS |
477 | cmp_json_output( |
478 | rname, | |
479 | "show yang operational-data /frr-pathd:pathd pathd", | |
480 | "step3/show_operational_data_with_two_candidates.ref", | |
481 | ) | |
4d7b695d SM |
482 | |
483 | # cleanup | |
5980ad0a DS |
484 | for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]: |
485 | for pref in ["100", "200"]: | |
4d7b695d SM |
486 | delete_candidate_path(rname, endpoint, pref) |
487 | ||
5980ad0a | 488 | |
4d7b695d SM |
489 | def test_srte_remove_best_candidate_step3(): |
490 | setup_testcase("Test (step 3): delete the Candidate Path with higher priority") | |
491 | ||
5980ad0a DS |
492 | for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]: |
493 | for pref, cand_name in [("100", "first"), ("200", "second")]: | |
4d7b695d SM |
494 | add_candidate_path(rname, endpoint, pref, cand_name) |
495 | ||
496 | # Delete candidate with higher priority | |
5980ad0a | 497 | for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]: |
4d7b695d SM |
498 | delete_candidate_path(rname, endpoint, 200) |
499 | ||
500 | # Candidate with lower priority should get active now | |
5980ad0a DS |
501 | for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]: |
502 | cmp_json_output( | |
503 | rname, | |
504 | "show yang operational-data /frr-pathd:pathd pathd", | |
505 | "step3/show_operational_data_with_single_candidate.ref", | |
506 | ) | |
4d7b695d SM |
507 | # cleanup |
508 | delete_candidate_path(rname, endpoint, 100) | |
509 | ||
5980ad0a | 510 | |
4d7b695d SM |
511 | # |
512 | # Step 4 | |
513 | # | |
514 | # Checking MPLS table with a single SR Policy and a Candidate Path with different Segment Lists and other modifications | |
515 | # | |
516 | def test_srte_change_segment_list_check_mpls_table_step4(): | |
517 | setup_testcase("Test (step 4): check MPLS table for changed Segment List") | |
518 | ||
5980ad0a DS |
519 | for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]: |
520 | add_candidate_path(rname, endpoint, 100, "default") | |
521 | # now change the segment list name | |
522 | add_candidate_path(rname, endpoint, 100, "default", "test") | |
523 | cmp_json_output(rname, "show mpls table json", "step4/show_mpls_table.ref") | |
4d7b695d SM |
524 | delete_candidate_path(rname, endpoint, 100) |
525 | ||
5980ad0a | 526 | |
4d7b695d | 527 | def test_srte_segment_list_add_segment_check_mpls_table_step4(): |
5980ad0a DS |
528 | setup_testcase( |
529 | "Test (step 4): check MPLS table for added (then changed and finally deleted) segment" | |
530 | ) | |
4d7b695d | 531 | |
5980ad0a | 532 | add_candidate_path("rt1", "6.6.6.6", 100, "default", "test") |
4d7b695d SM |
533 | |
534 | # first add a new segment | |
5980ad0a DS |
535 | add_segment("rt1", "test", 25, 16050) |
536 | cmp_json_output( | |
537 | "rt1", "show mpls table json", "step4/show_mpls_table_add_segment.ref" | |
538 | ) | |
4d7b695d SM |
539 | |
540 | # ... then change it ... | |
5980ad0a DS |
541 | add_segment("rt1", "test", 25, 16030) |
542 | cmp_json_output( | |
543 | "rt1", "show mpls table json", "step4/show_mpls_table_change_segment.ref" | |
544 | ) | |
4d7b695d SM |
545 | |
546 | # ... and finally delete it | |
5980ad0a DS |
547 | delete_segment("rt1", "test", 25) |
548 | cmp_json_output("rt1", "show mpls table json", "step4/show_mpls_table.ref") | |
549 | delete_candidate_path("rt1", "6.6.6.6", 100) | |
550 | ||
4d7b695d SM |
551 | |
552 | # | |
553 | # Step 5 | |
554 | # | |
555 | # Checking the nexthop using a single SR Policy and a Candidate Path with configured route-map | |
556 | # | |
557 | def test_srte_route_map_with_sr_policy_check_nextop_step5(): | |
5980ad0a DS |
558 | setup_testcase( |
559 | "Test (step 5): recursive nexthop learned through BGP neighbour should be aligned with SR Policy from route-map" | |
560 | ) | |
4d7b695d SM |
561 | |
562 | # (re-)build the SR Policy two times to ensure that reinstalling still works | |
5980ad0a DS |
563 | for i in [1, 2]: |
564 | cmp_json_output( | |
565 | "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_inactive_srte.ref" | |
566 | ) | |
4d7b695d | 567 | |
5980ad0a DS |
568 | delete_sr_policy("rt1", "6.6.6.6") |
569 | cmp_json_output( | |
570 | "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_inactive_srte.ref" | |
571 | ) | |
4d7b695d | 572 | |
5980ad0a DS |
573 | create_sr_policy("rt1", "6.6.6.6", 1111) |
574 | cmp_json_output( | |
575 | "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_inactive_srte.ref" | |
576 | ) | |
577 | ||
578 | add_candidate_path("rt1", "6.6.6.6", 100, "default") | |
579 | cmp_json_output( | |
580 | "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_active_srte.ref" | |
581 | ) | |
4d7b695d | 582 | |
5980ad0a | 583 | delete_candidate_path("rt1", "6.6.6.6", 100) |
4d7b695d | 584 | |
4d7b695d SM |
585 | |
586 | def test_srte_route_map_with_sr_policy_reinstall_prefix_sid_check_nextop_step5(): | |
5980ad0a DS |
587 | setup_testcase( |
588 | "Test (step 5): remove and re-install prefix SID on fist path element and check SR Policy activity" | |
589 | ) | |
4d7b695d SM |
590 | |
591 | # first add a candidate path so the SR Policy is active | |
5980ad0a DS |
592 | add_candidate_path("rt1", "6.6.6.6", 100, "default") |
593 | cmp_json_output( | |
594 | "rt1", | |
595 | "show yang operational-data /frr-pathd:pathd pathd", | |
596 | "step5/show_operational_data_active.ref", | |
597 | ) | |
4d7b695d SM |
598 | |
599 | # delete prefix SID from first element of the configured path and check | |
600 | # if the SR Policy is inactive since the label can't be resolved anymore | |
5980ad0a DS |
601 | delete_prefix_sid("rt5", "5.5.5.5/32") |
602 | cmp_json_output( | |
603 | "rt1", | |
604 | "show yang operational-data /frr-pathd:pathd pathd", | |
605 | "step5/show_operational_data_inactive.ref", | |
606 | ) | |
607 | cmp_json_output( | |
608 | "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_inactive_srte.ref" | |
609 | ) | |
4d7b695d SM |
610 | |
611 | # re-create the prefix SID and check if the SR Policy is active | |
5980ad0a DS |
612 | create_prefix_sid("rt5", "5.5.5.5/32", 50) |
613 | cmp_json_output( | |
614 | "rt1", | |
615 | "show yang operational-data /frr-pathd:pathd pathd", | |
616 | "step5/show_operational_data_active.ref", | |
617 | ) | |
618 | cmp_json_output( | |
619 | "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_active_srte.ref" | |
620 | ) | |
621 | ||
4d7b695d SM |
622 | |
623 | # Memory leak test template | |
624 | def test_memory_leak(): | |
625 | "Run the memory leak test and report results." | |
626 | tgen = get_topogen() | |
627 | if not tgen.is_memleak_enabled(): | |
5980ad0a | 628 | pytest.skip("Memory leak test/report is disabled") |
4d7b695d SM |
629 | |
630 | tgen.report_memory_leaks() | |
631 | ||
5980ad0a DS |
632 | |
633 | if __name__ == "__main__": | |
4d7b695d SM |
634 | args = ["-s"] + sys.argv[1:] |
635 | sys.exit(pytest.main(args)) |