]>
Commit | Line | Data |
---|---|---|
2448d002 | 1 | #!/usr/bin/python |
acddc0ed | 2 | # SPDX-License-Identifier: ISC |
2448d002 | 3 | # |
4 | # Copyright (c) 2021 by VMware, Inc. ("VMware") | |
5 | # Used Copyright (c) 2018 by Network Device Education Foundation, Inc. | |
6 | # ("NetDEF") in this file. | |
7 | # | |
2448d002 | 8 | |
9 | ||
10 | """OSPF Basic Functionality Automation.""" | |
11 | import os | |
12 | import sys | |
13 | import time | |
14 | import pytest | |
2448d002 | 15 | |
16 | # Save the Current Working Directory to find configuration files. | |
17 | CWD = os.path.dirname(os.path.realpath(__file__)) | |
18 | sys.path.append(os.path.join(CWD, "../")) | |
19 | sys.path.append(os.path.join(CWD, "../lib/")) | |
20 | ||
21 | # pylint: disable=C0413 | |
22 | # Import topogen and topotest helpers | |
2448d002 | 23 | from lib.topogen import Topogen, get_topogen |
24 | import ipaddress | |
2448d002 | 25 | |
26 | # Import topoJson from lib, to create topology and initial configuration | |
27 | from lib.common_config import ( | |
28 | start_topology, | |
29 | write_test_header, | |
30 | write_test_footer, | |
31 | reset_config_on_routers, | |
32 | verify_rib, | |
2448d002 | 33 | step, |
2448d002 | 34 | shutdown_bringup_interface, |
35 | create_interfaces_cfg, | |
2448d002 | 36 | get_frr_ipv6_linklocal, |
d1b5fa5b | 37 | check_router_status, |
38 | create_static_routes, | |
2448d002 | 39 | ) |
40 | ||
41 | from lib.topolog import logger | |
4953ca97 | 42 | from lib.topojson import build_config_from_json |
d1b5fa5b | 43 | from lib.bgp import create_router_bgp, verify_bgp_convergence |
2448d002 | 44 | from lib.ospf import ( |
45 | verify_ospf6_neighbor, | |
d1b5fa5b | 46 | clear_ospf, |
2448d002 | 47 | verify_ospf6_rib, |
d1b5fa5b | 48 | verify_ospf_database, |
2448d002 | 49 | create_router_ospf, |
2448d002 | 50 | config_ospf6_interface, |
d1b5fa5b | 51 | verify_ospf6_interface, |
2448d002 | 52 | ) |
53 | ||
2448d002 | 54 | |
6ff492b1 DS |
55 | pytestmark = [pytest.mark.ospfd, pytest.mark.staticd] |
56 | ||
57 | ||
2448d002 | 58 | # Global variables |
59 | topo = None | |
60 | ||
2448d002 | 61 | NETWORK = { |
62 | "ipv6": [ | |
63 | "11.0.20.1/32", | |
64 | "11.0.20.2/32", | |
65 | "11.0.20.3/32", | |
66 | "11.0.20.4/32", | |
67 | "11.0.20.5/32", | |
68 | ], | |
69 | "ipv6": ["2::1/128", "2::2/128", "2::3/128", "2::4/128", "2::5/128"], | |
70 | } | |
71 | TOPOOLOGY = """ | |
72 | Please view in a fixed-width font such as Courier. | |
73 | +---+ A1 +---+ | |
74 | +R1 +------------+R2 | | |
75 | +-+-+- +--++ | |
76 | | -- -- | | |
77 | | -- A0 -- | | |
78 | A0| ---- | | |
79 | | ---- | A2 | |
80 | | -- -- | | |
81 | | -- -- | | |
82 | +-+-+- +-+-+ | |
83 | +R0 +-------------+R3 | | |
84 | +---+ A3 +---+ | |
85 | """ | |
86 | ||
87 | TESTCASES = """ | |
88 | 1. OSPF Cost - verifying ospf interface cost functionality | |
89 | """ | |
90 | ||
91 | ||
2448d002 | 92 | def setup_module(mod): |
93 | """ | |
94 | Sets up the pytest environment | |
95 | ||
96 | * `mod`: module name | |
97 | """ | |
2448d002 | 98 | testsuite_run_time = time.asctime(time.localtime(time.time())) |
99 | logger.info("Testsuite start time: {}".format(testsuite_run_time)) | |
100 | logger.info("=" * 40) | |
101 | ||
102 | logger.info("Running setup_module to create topology") | |
103 | ||
104 | # This function initiates the topology build with Topogen... | |
e82b531d CH |
105 | json_file = "{}/ospfv3_rte_calc.json".format(CWD) |
106 | tgen = Topogen(json_file, mod.__name__) | |
107 | global topo | |
108 | topo = tgen.json_topo | |
2448d002 | 109 | # ... and here it calls Mininet initialization functions. |
110 | ||
2448d002 | 111 | # Starting topology, create tmp files which are loaded to routers |
d60a3f0e | 112 | # to start daemons and then start routers |
991a971f | 113 | start_topology(tgen) |
2448d002 | 114 | |
115 | # Creating configuration from JSON | |
116 | build_config_from_json(tgen, topo) | |
117 | ||
118 | # Don't run this test if we have any failure. | |
119 | if tgen.routers_have_failure(): | |
120 | pytest.skip(tgen.errors) | |
121 | ||
122 | ospf_covergence = verify_ospf6_neighbor(tgen, topo) | |
74dd0c84 | 123 | assert ospf_covergence is True, "setup_module :Failed \n Error: {}".format( |
2448d002 | 124 | ospf_covergence |
125 | ) | |
126 | ||
127 | logger.info("Running setup_module() done") | |
128 | ||
129 | ||
130 | def teardown_module(mod): | |
131 | """ | |
132 | Teardown the pytest environment. | |
133 | ||
134 | * `mod`: module name | |
135 | """ | |
136 | ||
137 | logger.info("Running teardown_module to delete topology") | |
138 | ||
139 | tgen = get_topogen() | |
140 | ||
141 | # Stop toplogy and Remove tmp files | |
142 | tgen.stop_topology() | |
143 | ||
144 | logger.info( | |
145 | "Testsuite end time: {}".format(time.asctime(time.localtime(time.time()))) | |
146 | ) | |
147 | logger.info("=" * 40) | |
148 | ||
149 | ||
150 | def get_llip(onrouter, intf): | |
151 | """ | |
dea6dce3 | 152 | API to get the link local ipv6 address of a particular interface |
2448d002 | 153 | |
154 | Parameters | |
155 | ---------- | |
156 | * `fromnode`: Source node | |
157 | * `tonode` : interface for which link local ip needs to be returned. | |
158 | ||
159 | Usage | |
160 | ----- | |
161 | result = get_llip('r1', 'r2-link0') | |
162 | ||
163 | Returns | |
164 | ------- | |
165 | 1) link local ipv6 address from the interface. | |
166 | 2) errormsg - when link local ip not found. | |
167 | """ | |
168 | tgen = get_topogen() | |
169 | intf = topo["routers"][onrouter]["links"][intf]["interface"] | |
170 | llip = get_frr_ipv6_linklocal(tgen, onrouter, intf) | |
171 | if llip: | |
172 | logger.info("llip ipv6 address to be set as NH is %s", llip) | |
173 | return llip | |
174 | return None | |
175 | ||
176 | ||
177 | def get_glipv6(onrouter, intf): | |
178 | """ | |
dea6dce3 | 179 | API to get the global ipv6 address of a particular interface |
2448d002 | 180 | |
181 | Parameters | |
182 | ---------- | |
183 | * `onrouter`: Source node | |
184 | * `intf` : interface for which link local ip needs to be returned. | |
185 | ||
186 | Usage | |
187 | ----- | |
188 | result = get_glipv6('r1', 'r2-link0') | |
189 | ||
190 | Returns | |
191 | ------- | |
192 | 1) global ipv6 address from the interface. | |
193 | 2) errormsg - when link local ip not found. | |
194 | """ | |
195 | glipv6 = (topo["routers"][onrouter]["links"][intf]["ipv6"]).split("/")[0] | |
196 | if glipv6: | |
197 | logger.info("Global ipv6 address to be set as NH is %s", glipv6) | |
198 | return glipv6 | |
199 | return None | |
200 | ||
201 | ||
202 | def red_static(dut, config=True): | |
203 | """Local def for Redstribute static routes inside ospf.""" | |
204 | global topo | |
205 | tgen = get_topogen() | |
206 | if config: | |
207 | ospf_red = {dut: {"ospf6": {"redistribute": [{"redist_type": "static"}]}}} | |
208 | else: | |
209 | ospf_red = { | |
210 | dut: { | |
211 | "ospf6": { | |
212 | "redistribute": [{"redist_type": "static", "del_action": True}] | |
213 | } | |
214 | } | |
215 | } | |
216 | result = create_router_ospf(tgen, topo, ospf_red) | |
217 | assert result is True, "Testcase : Failed \n Error: {}".format(result) | |
218 | ||
219 | ||
220 | def red_connected(dut, config=True): | |
221 | """Local def for Redstribute connected routes inside ospf.""" | |
222 | global topo | |
223 | tgen = get_topogen() | |
224 | if config: | |
225 | ospf_red = {dut: {"ospf6": {"redistribute": [{"redist_type": "connected"}]}}} | |
226 | else: | |
227 | ospf_red = { | |
228 | dut: { | |
229 | "ospf6": { | |
230 | "redistribute": [{"redist_type": "connected", "del_action": True}] | |
231 | } | |
232 | } | |
233 | } | |
234 | result = create_router_ospf(tgen, topo, ospf_red) | |
235 | assert result is True, "Testcase: Failed \n Error: {}".format(result) | |
236 | ||
237 | ||
238 | # ################################## | |
239 | # Test cases start here. | |
240 | # ################################## | |
d1b5fa5b | 241 | |
242 | ||
db56171c | 243 | def test_ospfv3_redistribution_tc5_p0(request): |
244 | """Test OSPF intra area route calculations.""" | |
245 | tc_name = request.node.name | |
246 | write_test_header(tc_name) | |
247 | tgen = get_topogen() | |
248 | ||
249 | # Don't run this test if we have any failure. | |
250 | if tgen.routers_have_failure(): | |
d1b5fa5b | 251 | check_router_status(tgen) |
db56171c | 252 | |
253 | global topo | |
254 | step("Bring up the base config.") | |
255 | reset_config_on_routers(tgen) | |
256 | ||
257 | step("Verify that OSPF neighbors are FULL.") | |
258 | ospf_covergence = verify_ospf6_neighbor(tgen, topo) | |
74dd0c84 | 259 | assert ospf_covergence is True, "Testcase Failed \n Error: {}".format( |
db56171c | 260 | ospf_covergence |
261 | ) | |
262 | ||
263 | step("verify intra area route is calculated for r0-r3 interface ip in R1") | |
264 | ip = topo["routers"]["r0"]["links"]["r3"]["ipv6"] | |
265 | ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network) | |
266 | ||
267 | llip = get_llip("r0", "r1") | |
268 | assert llip is not None, "Testcase {} : Failed \n Error: {}".format(tc_name, llip) | |
269 | ||
270 | nh = llip | |
271 | input_dict = { | |
d1b5fa5b | 272 | "r1": { |
273 | "static_routes": [ | |
274 | {"network": ip_net, "no_of_ip": 1, "routeType": "Network"} | |
275 | ] | |
276 | } | |
db56171c | 277 | } |
278 | ||
279 | dut = "r1" | |
280 | result = verify_ospf6_rib(tgen, dut, input_dict, next_hop=nh) | |
281 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
282 | ||
283 | protocol = "ospf" | |
284 | result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol, next_hop=nh) | |
285 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
286 | ||
287 | step("Delete the ip address on newly configured loopback of R0") | |
288 | topo1 = { | |
289 | "r0": { | |
290 | "links": { | |
291 | "r3": { | |
292 | "ipv6": topo["routers"]["r0"]["links"]["r3"]["ipv6"], | |
293 | "interface": topo["routers"]["r0"]["links"]["r3"]["interface"], | |
294 | "delete": True, | |
295 | } | |
296 | } | |
297 | } | |
298 | } | |
299 | ||
300 | result = create_interfaces_cfg(tgen, topo1) | |
301 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
302 | ||
303 | dut = "r1" | |
304 | result = verify_ospf6_rib(tgen, dut, input_dict, next_hop=nh, expected=False) | |
305 | assert ( | |
306 | result is not True | |
307 | ), "Testcase {} : Failed \n Route present in RIB. Error: {}".format(tc_name, result) | |
308 | ||
309 | protocol = "ospf" | |
310 | result = verify_rib( | |
311 | tgen, "ipv6", dut, input_dict, protocol=protocol, next_hop=nh, expected=False | |
312 | ) | |
313 | assert ( | |
314 | result is not True | |
315 | ), "Testcase {} : Failed \n Route present in RIB. Error: {}".format(tc_name, result) | |
316 | ||
317 | step("Add back the deleted ip address on newly configured interface of R0") | |
318 | topo1 = { | |
319 | "r0": { | |
320 | "links": { | |
321 | "r3": { | |
322 | "ipv6": topo["routers"]["r0"]["links"]["r3"]["ipv6"], | |
323 | "interface": topo["routers"]["r0"]["links"]["r3"]["interface"], | |
324 | } | |
325 | } | |
326 | } | |
327 | } | |
328 | ||
329 | result = create_interfaces_cfg(tgen, topo1) | |
330 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
331 | ||
332 | dut = "r1" | |
333 | result = verify_ospf6_rib(tgen, dut, input_dict, next_hop=nh) | |
334 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
335 | ||
336 | protocol = "ospf" | |
337 | result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol, next_hop=nh) | |
338 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
339 | ||
340 | step("Shut no shut interface on R0") | |
341 | dut = "r0" | |
342 | intf = topo["routers"]["r0"]["links"]["r3"]["interface"] | |
343 | shutdown_bringup_interface(tgen, dut, intf, False) | |
344 | ||
345 | step("un shut the OSPF interface on R0") | |
346 | dut = "r0" | |
347 | shutdown_bringup_interface(tgen, dut, intf, True) | |
348 | ||
349 | dut = "r1" | |
350 | result = verify_ospf6_rib(tgen, dut, input_dict) | |
351 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
352 | ||
353 | protocol = "ospf" | |
354 | result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol, next_hop=nh) | |
355 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
356 | ||
357 | write_test_footer(tc_name) | |
358 | ||
359 | ||
360 | def test_ospfv3_redistribution_tc6_p0(request): | |
361 | """Test OSPF inter area route calculations.""" | |
362 | tc_name = request.node.name | |
363 | write_test_header(tc_name) | |
364 | tgen = get_topogen() | |
365 | ||
366 | # Don't run this test if we have any failure. | |
367 | if tgen.routers_have_failure(): | |
d1b5fa5b | 368 | check_router_status(tgen) |
db56171c | 369 | |
370 | global topo | |
371 | step("Bring up the base config.") | |
372 | reset_config_on_routers(tgen) | |
373 | ||
374 | step("Verify that OSPF neighbors are FULL.") | |
375 | ospf_covergence = verify_ospf6_neighbor(tgen, topo) | |
d1b5fa5b | 376 | assert ospf_covergence is True, "Testcase {} : Failed \n Error: {}".format( |
377 | tc_name, ospf_covergence | |
db56171c | 378 | ) |
379 | ||
380 | step("verify intra area route is calculated for r0-r3 interface ip in R1") | |
381 | ip = topo["routers"]["r0"]["links"]["r3"]["ipv6"] | |
382 | ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network) | |
383 | llip = get_llip("r0", "r1") | |
384 | assert llip is not None, "Testcase {} : Failed \n Error: {}".format(tc_name, llip) | |
385 | nh = llip | |
386 | input_dict = { | |
d1b5fa5b | 387 | "r1": { |
388 | "static_routes": [ | |
389 | {"network": ip_net, "no_of_ip": 1, "routeType": "Network"} | |
390 | ] | |
391 | } | |
db56171c | 392 | } |
393 | ||
394 | dut = "r1" | |
395 | result = verify_ospf6_rib(tgen, dut, input_dict, next_hop=nh) | |
396 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
397 | ||
398 | protocol = "ospf" | |
399 | result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol, next_hop=nh) | |
400 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
401 | ||
402 | step("Delete the ip address on newly configured loopback of R0") | |
403 | topo1 = { | |
404 | "r0": { | |
405 | "links": { | |
406 | "r3": { | |
407 | "ipv6": topo["routers"]["r0"]["links"]["r3"]["ipv6"], | |
408 | "interface": topo["routers"]["r0"]["links"]["r3"]["interface"], | |
409 | "delete": True, | |
410 | } | |
411 | } | |
412 | } | |
413 | } | |
414 | ||
415 | result = create_interfaces_cfg(tgen, topo1) | |
416 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
417 | ||
418 | dut = "r1" | |
419 | result = verify_ospf6_rib(tgen, dut, input_dict, next_hop=nh, expected=False) | |
420 | assert ( | |
421 | result is not True | |
422 | ), "Testcase {} : Failed \n Route present in RIB. Error: {}".format(tc_name, result) | |
423 | ||
424 | protocol = "ospf" | |
425 | result = verify_rib( | |
426 | tgen, "ipv6", dut, input_dict, protocol=protocol, next_hop=nh, expected=False | |
427 | ) | |
428 | assert ( | |
429 | result is not True | |
430 | ), "Testcase {} : Failed \n Route present in RIB. Error: {}".format(tc_name, result) | |
431 | ||
432 | step("Add back the deleted ip address on newly configured interface of R0") | |
433 | topo1 = { | |
434 | "r0": { | |
435 | "links": { | |
436 | "r3": { | |
437 | "ipv6": topo["routers"]["r0"]["links"]["r3"]["ipv6"], | |
438 | "interface": topo["routers"]["r0"]["links"]["r3"]["interface"], | |
439 | } | |
440 | } | |
441 | } | |
442 | } | |
443 | ||
444 | result = create_interfaces_cfg(tgen, topo1) | |
445 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
446 | ||
447 | dut = "r1" | |
448 | result = verify_ospf6_rib(tgen, dut, input_dict, next_hop=nh) | |
449 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
450 | ||
451 | protocol = "ospf" | |
452 | result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol, next_hop=nh) | |
453 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
454 | ||
455 | step("Shut no shut interface on R0") | |
456 | dut = "r0" | |
457 | intf = topo["routers"]["r0"]["links"]["r3"]["interface"] | |
458 | shutdown_bringup_interface(tgen, dut, intf, False) | |
459 | ||
db56171c | 460 | step("un shut the OSPF interface on R0") |
461 | dut = "r0" | |
462 | shutdown_bringup_interface(tgen, dut, intf, True) | |
463 | ||
464 | dut = "r1" | |
465 | result = verify_ospf6_rib(tgen, dut, input_dict) | |
466 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
467 | ||
468 | protocol = "ospf" | |
469 | result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol, next_hop=nh) | |
470 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
471 | ||
472 | write_test_footer(tc_name) | |
473 | ||
474 | ||
d1b5fa5b | 475 | def test_ospfv3_redistribution_tc8_p1(request): |
476 | """ | |
477 | Test OSPF redistribution of connected routes. | |
478 | ||
479 | Verify OSPF redistribution of connected routes when bgp multi hop | |
480 | neighbor is configured using ospf routes | |
481 | ||
482 | """ | |
483 | tc_name = request.node.name | |
484 | write_test_header(tc_name) | |
485 | tgen = get_topogen() | |
486 | global topo | |
487 | step("Bring up the base config.") | |
488 | step( | |
489 | "Configure loopback interface on all routers, and redistribut" | |
490 | "e connected routes into ospf" | |
491 | ) | |
492 | if tgen.routers_have_failure(): | |
493 | check_router_status(tgen) | |
494 | reset_config_on_routers(tgen) | |
495 | ||
496 | step( | |
497 | "verify that connected routes -loopback is found in all routers" | |
498 | "advertised/exchaged via ospf" | |
499 | ) | |
500 | for rtr in topo["routers"]: | |
501 | red_static(rtr) | |
502 | red_connected(rtr) | |
503 | ||
504 | for node in topo["routers"]: | |
505 | input_dict = { | |
506 | "r0": { | |
507 | "static_routes": [ | |
508 | { | |
509 | "network": topo["routers"][node]["links"]["lo"]["ipv6"], | |
510 | "no_of_ip": 1, | |
511 | } | |
512 | ] | |
513 | } | |
514 | } | |
515 | for rtr in topo["routers"]: | |
516 | result = verify_rib(tgen, "ipv6", rtr, input_dict) | |
517 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
518 | tc_name, result | |
519 | ) | |
520 | ||
521 | step("Configure E BGP multi hop using the loopback addresses.") | |
522 | as_num = 100 | |
523 | for node in topo["routers"]: | |
524 | as_num += 1 | |
525 | topo["routers"][node].update( | |
526 | { | |
527 | "bgp": { | |
528 | "local_as": as_num, | |
529 | "address_family": {"ipv6": {"unicast": {"neighbor": {}}}}, | |
530 | } | |
531 | } | |
532 | ) | |
533 | for node in topo["routers"]: | |
534 | for rtr in topo["routers"]: | |
535 | if node is not rtr: | |
536 | topo["routers"][node]["bgp"]["address_family"]["ipv6"]["unicast"][ | |
537 | "neighbor" | |
538 | ].update( | |
539 | { | |
540 | rtr: { | |
541 | "dest_link": { | |
542 | "lo": {"source_link": "lo", "ebgp_multihop": 2} | |
543 | } | |
544 | } | |
545 | } | |
546 | ) | |
547 | ||
548 | result = create_router_bgp(tgen, topo, topo["routers"]) | |
549 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
550 | ||
551 | # Modify router id | |
552 | input_dict = { | |
553 | "r0": {"bgp": {"router_id": "11.11.11.11"}}, | |
554 | "r1": {"bgp": {"router_id": "22.22.22.22"}}, | |
555 | "r2": {"bgp": {"router_id": "33.33.33.33"}}, | |
556 | "r3": {"bgp": {"router_id": "44.44.44.44"}}, | |
557 | } | |
558 | result = create_router_bgp(tgen, topo, input_dict) | |
559 | assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) | |
560 | ||
561 | step("Verify that BGP neighbor is ESTABLISHED") | |
562 | result = verify_bgp_convergence(tgen, topo) | |
563 | assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) | |
564 | step( | |
565 | "Configure couple of static routes in R0 and " | |
566 | "Redistribute static routes in R1 bgp." | |
567 | ) | |
568 | ||
569 | for rtr in topo["routers"]: | |
570 | ospf_red = { | |
571 | rtr: { | |
572 | "ospf6": {"redistribute": [{"redist_type": "static", "delete": True}]} | |
573 | } | |
574 | } | |
575 | result = create_router_ospf(tgen, topo, ospf_red) | |
576 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
577 | tc_name, result | |
578 | ) | |
579 | ||
580 | input_dict = { | |
581 | "r0": { | |
582 | "static_routes": [ | |
583 | { | |
584 | "network": NETWORK["ipv6"][0], | |
585 | "no_of_ip": 5, | |
586 | "next_hop": "Null0", | |
587 | } | |
588 | ] | |
589 | } | |
590 | } | |
591 | result = create_static_routes(tgen, input_dict) | |
592 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
593 | ||
594 | configure_bgp_on_r0 = { | |
595 | "r0": { | |
596 | "bgp": { | |
597 | "address_family": { | |
598 | "ipv6": {"unicast": {"redistribute": [{"redist_type": "static"}]}} | |
599 | } | |
600 | } | |
601 | } | |
602 | } | |
603 | result = create_router_bgp(tgen, topo, configure_bgp_on_r0) | |
604 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
605 | protocol = "bgp" | |
606 | for rtr in ["r1", "r2", "r3"]: | |
607 | result = verify_rib(tgen, "ipv6", rtr, input_dict, protocol=protocol) | |
608 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
609 | tc_name, result | |
610 | ) | |
611 | ||
612 | step("Clear ospf neighbours in R0") | |
613 | for rtr in topo["routers"]: | |
614 | clear_ospf(tgen, rtr) | |
615 | ||
616 | step("Verify that OSPF neighbours are reset and forms new adjacencies.") | |
617 | # Api call verify whether OSPF is converged | |
618 | ospf_covergence = verify_ospf6_neighbor(tgen, topo) | |
74dd0c84 | 619 | assert ospf_covergence is True, "Testcase Failed \n Error: {}".format( |
d1b5fa5b | 620 | ospf_covergence |
621 | ) | |
622 | ||
623 | step("Verify that BGP neighbours are reset and forms new adjacencies.") | |
624 | result = verify_bgp_convergence(tgen, topo) | |
625 | assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) | |
626 | ||
627 | protocol = "bgp" | |
628 | for rtr in ["r1", "r2", "r3"]: | |
629 | result = verify_rib(tgen, "ipv6", rtr, input_dict, protocol=protocol) | |
630 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
631 | tc_name, result | |
632 | ) | |
633 | ||
634 | write_test_footer(tc_name) | |
635 | ||
636 | ||
2448d002 | 637 | def test_ospfv3_cost_tc52_p0(request): |
638 | """OSPF Cost - verifying ospf interface cost functionality""" | |
639 | tc_name = request.node.name | |
640 | write_test_header(tc_name) | |
641 | tgen = get_topogen() | |
642 | global topo | |
643 | step("Bring up the base config.") | |
d1b5fa5b | 644 | if tgen.routers_have_failure(): |
645 | check_router_status(tgen) | |
2448d002 | 646 | reset_config_on_routers(tgen) |
647 | ||
648 | step( | |
649 | "Configure ospf cost as 20 on interface between R0 and R1. " | |
650 | "Configure ospf cost as 30 between interface between R0 and R2." | |
651 | ) | |
652 | ||
653 | r0_ospf_cost = { | |
654 | "r0": {"links": {"r1": {"ospf6": {"cost": 20}}, "r2": {"ospf6": {"cost": 30}}}} | |
655 | } | |
656 | result = config_ospf6_interface(tgen, topo, r0_ospf_cost) | |
657 | assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) | |
658 | ||
659 | step( | |
660 | "Verify that cost is updated in the ospf interface between" | |
661 | " r0 and r1 as 30 and r0 and r2 as 20" | |
662 | ) | |
663 | dut = "r0" | |
664 | result = verify_ospf6_interface(tgen, topo, dut=dut, input_dict=r0_ospf_cost) | |
665 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
666 | ||
667 | step( | |
668 | "Swap the costs between interfaces on r0, between r0 and r1 to 30" | |
669 | ", r0 and r2 to 20" | |
670 | ) | |
671 | ||
672 | r0_ospf_cost = { | |
673 | "r0": {"links": {"r1": {"ospf6": {"cost": 30}}, "r2": {"ospf6": {"cost": 20}}}} | |
674 | } | |
675 | result = config_ospf6_interface(tgen, topo, r0_ospf_cost) | |
676 | assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) | |
677 | ||
678 | step( | |
679 | "Verify that cost is updated in the ospf interface between r0 " | |
680 | "and r1 as 30 and r0 and r2 as 20." | |
681 | ) | |
682 | result = verify_ospf6_interface(tgen, topo, dut=dut, input_dict=r0_ospf_cost) | |
683 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
684 | ||
685 | step(" Un configure cost from the interface r0 - r1.") | |
686 | ||
687 | r0_ospf_cost = { | |
688 | "r0": {"links": {"r1": {"ospf6": {"cost": 30, "del_action": True}}}} | |
689 | } | |
690 | result = config_ospf6_interface(tgen, topo, r0_ospf_cost) | |
691 | assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) | |
692 | ||
693 | input_dict = { | |
694 | "r0": {"links": {"r1": {"ospf6": {"cost": 10}}, "r2": {"ospf6": {"cost": 20}}}} | |
695 | } | |
696 | step( | |
697 | "Verify that cost is updated in the ospf interface between r0" | |
698 | " and r1 as 10 and r0 and r2 as 20." | |
699 | ) | |
700 | ||
701 | result = verify_ospf6_interface(tgen, topo, dut=dut, input_dict=input_dict) | |
702 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
703 | ||
704 | step(" Un configure cost from the interface r0 - r2.") | |
705 | ||
706 | r0_ospf_cost = { | |
707 | "r0": {"links": {"r2": {"ospf6": {"cost": 20, "del_action": True}}}} | |
708 | } | |
709 | result = config_ospf6_interface(tgen, topo, r0_ospf_cost) | |
710 | assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) | |
711 | ||
712 | step( | |
713 | "Verify that cost is updated in the ospf interface between r0" | |
714 | "and r1 as 10 and r0 and r2 as 10" | |
715 | ) | |
716 | ||
717 | input_dict = { | |
718 | "r0": {"links": {"r1": {"ospf6": {"cost": 10}}, "r2": {"ospf6": {"cost": 10}}}} | |
719 | } | |
720 | result = verify_ospf6_interface(tgen, topo, dut=dut, input_dict=input_dict) | |
721 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
722 | ||
723 | write_test_footer(tc_name) | |
724 | ||
725 | ||
d1b5fa5b | 726 | def test_ospfv3_def_rte_tc9_p0(request): |
727 | """OSPF default route - Verify OSPF default route origination.""" | |
728 | tc_name = request.node.name | |
729 | write_test_header(tc_name) | |
730 | tgen = get_topogen() | |
731 | global topo | |
732 | step("Bring up the base config.") | |
733 | step("Configure OSPF on all the routers of the topology.") | |
734 | if tgen.routers_have_failure(): | |
735 | check_router_status(tgen) | |
736 | reset_config_on_routers(tgen) | |
737 | ||
738 | step(" Configure default-information originate always on R0.") | |
739 | input_dict = {"r0": {"ospf6": {"default-information": {"originate": True}}}} | |
740 | result = create_router_ospf(tgen, topo, input_dict) | |
741 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
742 | ||
743 | dut = "r0" | |
744 | step(" Configure default-information originate always on R0.") | |
745 | input_dict = { | |
746 | "r0": { | |
747 | "ospf6": { | |
748 | "default-information": { | |
749 | "originate": True, | |
750 | "always": True, | |
751 | } | |
752 | } | |
753 | } | |
754 | } | |
755 | result = create_router_ospf(tgen, topo, input_dict) | |
756 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
757 | ||
758 | step("Verify that default route is originated in area always.") | |
759 | dut = "r1" | |
760 | ||
761 | step(" Configure default-information originate metric type 1 on R0.") | |
762 | input_dict = { | |
763 | "r0": { | |
764 | "ospf6": { | |
765 | "default-information": { | |
766 | "originate": True, | |
767 | "always": True, | |
768 | "metric-type": 1, | |
769 | } | |
770 | } | |
771 | } | |
772 | } | |
773 | ||
774 | step( | |
775 | "Verify that default route is originated in area when external " | |
776 | "routes are present in R0 with metric type as 1." | |
777 | ) | |
778 | dut = "r0" | |
779 | step( | |
780 | "Verify that on R1 default route with type 1 is installed" | |
781 | " (R1 is DUT in this case)" | |
782 | ) | |
783 | dut = "r1" | |
784 | step("Configure default-information originate metric type 2 on R0.") | |
785 | input_dict = { | |
786 | "r0": { | |
787 | "ospf6": { | |
788 | "default-information": { | |
789 | "originate": True, | |
790 | "always": True, | |
791 | "metric-type": 2, | |
792 | } | |
793 | } | |
794 | } | |
795 | } | |
796 | result = create_router_ospf(tgen, topo, input_dict) | |
797 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
798 | ||
799 | step( | |
800 | "Verify that default route is originated in area when external" | |
801 | " routes are present in R0 with metric type as 2." | |
802 | ) | |
803 | ||
804 | dut = "r1" | |
805 | step(" Configure default-information originate metric 100 on R0") | |
806 | input_dict = { | |
807 | "r0": { | |
808 | "ospf6": { | |
809 | "default-information": { | |
810 | "originate": True, | |
811 | "always": True, | |
812 | "metric-type": 2, | |
813 | "metric": 100, | |
814 | } | |
815 | } | |
816 | } | |
817 | } | |
818 | result = create_router_ospf(tgen, topo, input_dict) | |
819 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
820 | ||
821 | step("Verify that default route is originated with cost as 100 on R0.") | |
822 | ||
823 | dut = "r1" | |
824 | ||
825 | step("Delete the default-information command") | |
826 | input_dict = { | |
827 | "r0": { | |
828 | "ospf6": { | |
829 | "default-information": { | |
830 | "originate": True, | |
831 | "always": True, | |
832 | "delete": True, | |
833 | } | |
834 | } | |
835 | } | |
836 | } | |
837 | result = create_router_ospf(tgen, topo, input_dict) | |
838 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
839 | ||
840 | dut = "r0" | |
841 | step("Configure default-information originate always on R0.") | |
842 | input_dict = { | |
843 | "r0": { | |
844 | "ospf6": { | |
845 | "default-information": { | |
846 | "originate": True, | |
847 | "always": True, | |
848 | } | |
849 | } | |
850 | } | |
851 | } | |
852 | result = create_router_ospf(tgen, topo, input_dict) | |
853 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
854 | ||
855 | step("Configure default route originate with active def route in zebra") | |
856 | input_dict = { | |
857 | "r0": { | |
858 | "static_routes": [ | |
859 | { | |
860 | "network": "0::0/0", | |
861 | "no_of_ip": 1, | |
862 | "next_hop": "Null0", | |
863 | } | |
864 | ] | |
865 | } | |
866 | } | |
867 | result = create_static_routes(tgen, input_dict) | |
868 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
869 | ||
870 | input_dict = { | |
871 | "r0": { | |
872 | "ospf6": { | |
873 | "default-information": { | |
874 | "originate": True, | |
875 | } | |
876 | } | |
877 | } | |
878 | } | |
879 | result = create_router_ospf(tgen, topo, input_dict) | |
880 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
881 | ||
882 | step("Verify that default route is originated by R0.") | |
883 | dut = "r1" | |
884 | ||
885 | step("Delete static route") | |
886 | input_dict = { | |
887 | "r0": { | |
888 | "static_routes": [ | |
889 | { | |
890 | "network": "0::0/0", | |
891 | "no_of_ip": 1, | |
892 | "next_hop": "Null0", | |
893 | "delete": True, | |
894 | } | |
895 | ] | |
896 | } | |
897 | } | |
898 | result = create_static_routes(tgen, input_dict) | |
899 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
900 | ||
901 | write_test_footer(tc_name) | |
902 | ||
903 | ||
2448d002 | 904 | if __name__ == "__main__": |
905 | args = ["-s"] + sys.argv[1:] | |
906 | sys.exit(pytest.main(args)) |