2 # SPDX-License-Identifier: ISC
5 # Copyright (c) 2021 by VMware, Inc. ("VMware")
6 # Used Copyright (c) 2018 by Network Device Education Foundation, Inc.
7 # ("NetDEF") in this file.
11 """OSPF Basic Functionality Automation."""
17 # Save the Current Working Directory to find configuration files.
18 CWD
= os
.path
.dirname(os
.path
.realpath(__file__
))
19 sys
.path
.append(os
.path
.join(CWD
, "../"))
20 sys
.path
.append(os
.path
.join(CWD
, "../lib/"))
22 # pylint: disable=C0413
23 # Import topogen and topotest helpers
24 from lib
.topogen
import Topogen
, get_topogen
26 # Import topoJson from lib, to create topology and initial configuration
27 from lib
.common_config
import (
31 reset_config_on_routers
,
35 shutdown_bringup_interface
,
36 get_frr_ipv6_linklocal
,
38 from lib
.topolog
import logger
39 from lib
.topojson
import build_config_from_json
41 from lib
.ospf
import (
42 verify_ospf6_neighbor
,
45 config_ospf6_interface
,
49 pytestmark
= [pytest
.mark
.ospfd
, pytest
.mark
.staticd
]
63 "ipv6": ["2::1/128", "2::2/128", "2::3/128", "2::4/128", "2::5/128"],
67 Please view in a fixed-width font such as Courier.
69 +R1 +------------+R2 |
78 +R0 +-------------+R3 |
82 1. Verify OSPF ECMP with max path configured as 8 (ECMPconfigured at FRR level)
83 2. Verify OSPF ECMP with max path configured as 2 (Edge having 2 uplink ports)
87 def setup_module(mod
):
89 Sets up the pytest environment
93 testsuite_run_time
= time
.asctime(time
.localtime(time
.time()))
94 logger
.info("Testsuite start time: {}".format(testsuite_run_time
))
97 logger
.info("Running setup_module to create topology")
99 # This function initiates the topology build with Topogen...
100 json_file
= "{}/ospfv3_ecmp.json".format(CWD
)
101 tgen
= Topogen(json_file
, mod
.__name
__)
103 topo
= tgen
.json_topo
104 # ... and here it calls Mininet initialization functions.
106 # Starting topology, create tmp files which are loaded to routers
107 # to start daemons and then start routers
110 # Creating configuration from JSON
111 build_config_from_json(tgen
, topo
)
113 # Don't run this test if we have any failure.
114 if tgen
.routers_have_failure():
115 pytest
.skip(tgen
.errors
)
117 ospf_covergence
= verify_ospf6_neighbor(tgen
, topo
)
118 assert ospf_covergence
is True, "setup_module :Failed \n Error:" " {}".format(
122 logger
.info("Running setup_module() done")
125 def teardown_module(mod
):
127 Teardown the pytest environment.
132 logger
.info("Running teardown_module to delete topology")
136 # Stop toplogy and Remove tmp files
140 "Testsuite end time: {}".format(time
.asctime(time
.localtime(time
.time())))
142 logger
.info("=" * 40)
145 def red_static(dut
, config
=True):
146 """Local def for Redstribute static routes inside ospf."""
150 ospf_red
= {dut
: {"ospf6": {"redistribute": [{"redist_type": "static"}]}}}
154 "ospf6": {"redistribute": [{"redist_type": "static", "delete": True}]}
157 result
= create_router_ospf(tgen
, topo
, ospf_red
)
158 assert result
is True, "Testcase : Failed \n Error: {}".format(result
)
161 def red_connected(dut
, config
=True):
162 """Local def for Redstribute connected routes inside ospf."""
166 ospf_red
= {dut
: {"ospf6": {"redistribute": [{"redist_type": "connected"}]}}}
171 "redistribute": [{"redist_type": "connected", "del_action": True}]
175 result
= create_router_ospf(tgen
, topo
, ospf_red
)
176 assert result
is True, "Testcase: Failed \n Error: {}".format(result
)
179 def get_llip(onrouter
, intf
):
181 API to get the link local ipv6 address of a particular interface
185 * `fromnode`: Source node
186 * `tonode` : interface for which link local ip needs to be returned.
190 result = get_llip('r1', 'r2-link0')
194 1) link local ipv6 address from the interface.
195 2) errormsg - when link local ip not found.
198 intf
= topo
["routers"][onrouter
]["links"][intf
]["interface"]
199 llip
= get_frr_ipv6_linklocal(tgen
, onrouter
, intf
)
201 logger
.info("llip ipv6 address to be set as NH is %s", llip
)
206 def get_glipv6(onrouter
, intf
):
208 API to get the global ipv6 address of a particular interface
212 * `onrouter`: Source node
213 * `intf` : interface for which link local ip needs to be returned.
217 result = get_glipv6('r1', 'r2-link0')
221 1) global ipv6 address from the interface.
222 2) errormsg - when link local ip not found.
224 glipv6
= (topo
["routers"][onrouter
]["links"][intf
]["ipv6"]).split("/")[0]
226 logger
.info("Global ipv6 address to be set as NH is %s", glipv6
)
231 # ##################################
232 # Test cases start here.
233 # ##################################
236 def test_ospfv3_ecmp_tc16_p0(request
):
240 Verify OSPF ECMP with max path configured as 8 (ECMP
241 configured at FRR level)
243 tc_name
= request
.node
.name
244 write_test_header(tc_name
)
247 # Don't run this test if we have any failure.
248 if tgen
.routers_have_failure():
249 pytest
.skip(tgen
.errors
)
252 step("Bring up the base config as per the topology")
253 step("Configure 8 interfaces between R1 and R2 and enable ospf in area 0.")
255 reset_config_on_routers(tgen
)
257 step("Verify that OSPF is up with 8 neighborship sessions.")
259 ospf_covergence
= verify_ospf6_neighbor(tgen
, topo
, dut
=dut
)
260 assert ospf_covergence
is True, "setup_module :Failed \n Error:" " {}".format(
264 step("Configure a static route in R0 and redistribute in OSPF.")
270 "network": NETWORK
["ipv6"][0],
277 result
= create_static_routes(tgen
, input_dict
)
278 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
283 llip
= get_llip("r0", "r1-link1")
284 assert llip
is not None, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
286 step("Verify that route in R2 in stalled with 8 next hops.")
288 for item
in range(1, 7):
291 llip
= get_llip("r0", "r1")
292 assert llip
is not None, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
299 result
= verify_ospf6_rib(tgen
, dut
, input_dict
, next_hop
=nh
)
300 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
303 result
= verify_rib(tgen
, "ipv6", dut
, input_dict
, protocol
=protocol
, next_hop
=nh
)
304 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
306 step("shut no shut all the interfaces on the remote router - R2")
308 for intfr
in range(1, 7):
309 intf
= topo
["routers"]["r1"]["links"]["r0-link{}".format(intfr
)]["interface"]
310 shutdown_bringup_interface(tgen
, dut
, intf
, False)
312 result
= verify_ospf6_rib(tgen
, dut
, input_dict
, next_hop
=nh
, expected
=False)
315 ), "Testcase {} : Failed \n Route present in OSPF RIB. Error: {}".format(
321 tgen
, "ipv6", dut
, input_dict
, protocol
=protocol
, next_hop
=nh
, expected
=False
325 ), "Testcase {} : Failed \n Route present in RIB. Error: {}".format(tc_name
, result
)
327 for intfr
in range(1, 7):
328 intf
= topo
["routers"]["r1"]["links"]["r0-link{}".format(intfr
)]["interface"]
329 shutdown_bringup_interface(tgen
, dut
, intf
, True)
331 result
= verify_ospf6_rib(tgen
, dut
, input_dict
, next_hop
=nh
)
332 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
335 result
= verify_rib(tgen
, "ipv6", dut
, input_dict
, protocol
=protocol
, next_hop
=nh
)
336 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
338 step("shut no shut on all the interfaces on DUT (r1)")
339 for intfr
in range(1, 7):
340 intf
= topo
["routers"]["r1"]["links"]["r0-link{}".format(intfr
)]["interface"]
341 shutdown_bringup_interface(tgen
, dut
, intf
, False)
343 for intfr
in range(1, 7):
344 intf
= topo
["routers"]["r1"]["links"]["r0-link{}".format(intfr
)]["interface"]
345 shutdown_bringup_interface(tgen
, dut
, intf
, True)
348 "Verify that all the neighbours are up and routes are installed"
349 " with 8 next hop in ospf and ip route tables on R1."
352 step("Verify that OSPF is up with 8 neighborship sessions.")
354 ospf_covergence
= verify_ospf6_neighbor(tgen
, topo
, dut
=dut
)
355 assert ospf_covergence
is True, "setup_module :Failed \n Error:" " {}".format(
360 result
= verify_ospf6_rib(tgen
, dut
, input_dict
, next_hop
=nh
)
361 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
364 result
= verify_rib(tgen
, "ipv6", dut
, input_dict
, protocol
=protocol
, next_hop
=nh
)
365 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
367 write_test_footer(tc_name
)
370 def test_ospfv3_ecmp_tc17_p0(request
):
374 Verify OSPF ECMP with max path configured as 2 (Edge having 2 uplink ports)
376 tc_name
= request
.node
.name
377 write_test_header(tc_name
)
380 # Don't run this test if we have any failure.
381 if tgen
.routers_have_failure():
382 pytest
.skip(tgen
.errors
)
385 step("Bring up the base config as per the topology")
386 step("Configure 2 interfaces between R1 and R2 & enable ospf in area 0.")
388 reset_config_on_routers(tgen
)
390 step("Verify that OSPF is up with 2 neighborship sessions.")
392 ospf_covergence
= verify_ospf6_neighbor(tgen
, topo
, dut
=dut
)
393 assert ospf_covergence
is True, "setup_module :Failed \n Error:" " {}".format(
397 step("Configure a static route in R0 and redistribute in OSPF.")
403 "network": NETWORK
["ipv6"][0],
410 result
= create_static_routes(tgen
, input_dict
)
411 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
416 step("Verify that route in R2 in stalled with 2 next hops.")
418 llip
= get_llip("r0", "r1-link1")
419 assert llip
is not None, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
423 llip
= get_llip("r0", "r1")
424 assert llip
is not None, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
431 result
= verify_ospf6_rib(tgen
, dut
, input_dict
, next_hop
=nh
)
432 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
435 result
= verify_rib(tgen
, "ipv6", dut
, input_dict
, protocol
=protocol
, next_hop
=nh
)
436 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
438 step("Configure ECMP value as 1.")
439 max_path
= {"r1": {"ospf6": {"maximum-paths": 1}}}
440 result
= create_router_ospf(tgen
, topo
, max_path
)
441 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
443 result
= verify_rib(tgen
, "ipv6", dut
, input_dict
, protocol
=protocol
, next_hop
=nh2
)
444 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
447 max_path
= {"r1": {"ospf6": {"maximum-paths": 2}}}
448 result
= create_router_ospf(tgen
, topo
, max_path
)
449 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
451 result
= verify_rib(tgen
, "ipv6", dut
, input_dict
, protocol
=protocol
, next_hop
=nh
)
452 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
454 step("Configure cost on R0 as 100")
455 r0_ospf_cost
= {"r0": {"links": {"r1": {"ospf6": {"cost": 100}}}}}
456 result
= config_ospf6_interface(tgen
, topo
, r0_ospf_cost
)
457 assert result
is True, "Testcase {} :Failed \n Error: {}".format(tc_name
, result
)
460 result
= verify_ospf6_rib(tgen
, dut
, input_dict
, next_hop
=nh
)
461 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
464 result
= verify_rib(tgen
, "ipv6", dut
, input_dict
, protocol
=protocol
, next_hop
=nh
)
465 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
467 write_test_footer(tc_name
)
470 if __name__
== "__main__":
471 args
= ["-s"] + sys
.argv
[1:]
472 sys
.exit(pytest
.main(args
))