4 # Copyright (c) 2020 by VMware, Inc. ("VMware")
5 # Used Copyright (c) 2018 by Network Device Education Foundation, Inc.
6 # ("NetDEF") in this file.
8 # Permission to use, copy, modify, and/or distribute this software
9 # for any purpose with or without fee is hereby granted, provided
10 # that the above copyright notice and this permission notice appear
13 # THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
14 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
16 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
17 # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18 # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
19 # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
24 """OSPF Basic Functionality Automation."""
29 from time
import sleep
31 # Save the Current Working Directory to find configuration files.
32 CWD
= os
.path
.dirname(os
.path
.realpath(__file__
))
33 sys
.path
.append(os
.path
.join(CWD
, "../"))
34 sys
.path
.append(os
.path
.join(CWD
, "../lib/"))
36 # pylint: disable=C0413
37 # Import topogen and topotest helpers
38 from lib
.topogen
import Topogen
, get_topogen
40 # Import topoJson from lib, to create topology and initial configuration
41 from lib
.common_config
import (
45 reset_config_on_routers
,
49 shutdown_bringup_interface
,
51 from lib
.topolog
import logger
53 from lib
.topojson
import build_config_from_json
54 from lib
.ospf
import (
56 config_ospf_interface
,
61 pytestmark
= [pytest
.mark
.ospfd
, pytest
.mark
.staticd
]
79 Please view in a fixed-width font such as Courier.
81 +R1 +------------+R2 |
90 +R0 +-------------+R3 |
94 1. Verify OSPF ECMP with max path configured as 8 (ECMPconfigured at FRR level)
95 2. Verify OSPF ECMP with max path configured as 2 (Edge having 2 uplink ports)
99 def setup_module(mod
):
101 Sets up the pytest environment
105 testsuite_run_time
= time
.asctime(time
.localtime(time
.time()))
106 logger
.info("Testsuite start time: {}".format(testsuite_run_time
))
107 logger
.info("=" * 40)
109 logger
.info("Running setup_module to create topology")
111 # This function initiates the topology build with Topogen...
112 json_file
= "{}/ospf_ecmp.json".format(CWD
)
113 tgen
= Topogen(json_file
, mod
.__name
__)
115 topo
= tgen
.json_topo
116 # ... and here it calls Mininet initialization functions.
118 # Starting topology, create tmp files which are loaded to routers
119 # to start daemons and then start routers
122 # Creating configuration from JSON
123 build_config_from_json(tgen
, topo
)
125 # Don't run this test if we have any failure.
126 if tgen
.routers_have_failure():
127 pytest
.skip(tgen
.errors
)
128 # Api call verify whether OSPF is converged
129 ospf_covergence
= verify_ospf_neighbor(tgen
, topo
)
130 assert ospf_covergence
is True, "setup_module :Failed \n Error {}".format(
134 logger
.info("Running setup_module() done")
137 def teardown_module(mod
):
139 Teardown the pytest environment.
144 logger
.info("Running teardown_module to delete topology")
148 # Stop toplogy and Remove tmp files
152 "Testsuite end time: {}".format(time
.asctime(time
.localtime(time
.time())))
154 logger
.info("=" * 40)
157 # ##################################
158 # Test cases start here.
159 # ##################################
162 def test_ospf_ecmp_tc16_p0(request
):
166 Verify OSPF ECMP with max path configured as 8 (ECMP
167 configured at FRR level)
169 tc_name
= request
.node
.name
170 write_test_header(tc_name
)
173 # Don't run this test if we have any failure.
174 if tgen
.routers_have_failure():
175 pytest
.skip(tgen
.errors
)
178 step("Bring up the base config as per the topology")
179 step("Configure 8 interfaces between R1 and R2 and enable ospf in area 0.")
180 reset_config_on_routers(tgen
)
181 step("Verify that OSPF is up with 8 neighborship sessions.")
183 ospf_covergence
= verify_ospf_neighbor(tgen
, topo
, dut
=dut
)
184 assert ospf_covergence
is True, "Testcase Failed \n Error {}".format(
188 step("Configure a static route in R0 and redistribute in OSPF.")
194 "network": NETWORK
["ipv4"][0],
201 result
= create_static_routes(tgen
, input_dict
)
202 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
205 redistribute_ospf(tgen
, topo
, dut
, "static")
207 step("Verify that route in R2 in stalled with 8 next hops.")
209 for item
in range(1, 7):
210 nh
.append(topo
["routers"]["r0"]["links"]["r1-link1"]["ipv4"].split("/")[0])
212 nh2
= topo
["routers"]["r0"]["links"]["r1"]["ipv4"].split("/")[0]
217 result
= verify_ospf_rib(tgen
, dut
, input_dict
, next_hop
=nh
)
218 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
221 result
= verify_rib(tgen
, "ipv4", dut
, input_dict
, protocol
=protocol
, next_hop
=nh
)
222 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
224 step("shut no shut all the interfaces on the remote router - R2")
226 for intfr
in range(1, 7):
227 intf
= topo
["routers"]["r1"]["links"]["r0-link{}".format(intfr
)]["interface"]
228 shutdown_bringup_interface(tgen
, dut
, intf
, False)
230 result
= verify_ospf_rib(tgen
, dut
, input_dict
, next_hop
=nh
, expected
=False)
233 ), "Testcase {} : Failed \n r1: OSPF routes are present \n Error: {}".format(
239 tgen
, "ipv4", dut
, input_dict
, protocol
=protocol
, next_hop
=nh
, expected
=False
243 ), "Testcase {} : Failed \n r1: routes are still present \n Error: {}".format(
247 for intfr
in range(1, 7):
248 intf
= topo
["routers"]["r1"]["links"]["r0-link{}".format(intfr
)]["interface"]
249 shutdown_bringup_interface(tgen
, dut
, intf
, True)
251 result
= verify_ospf_rib(tgen
, dut
, input_dict
, next_hop
=nh
)
252 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
255 result
= verify_rib(tgen
, "ipv4", dut
, input_dict
, protocol
=protocol
, next_hop
=nh
)
256 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
258 step("shut no shut on all the interfaces on DUT (r1)")
259 for intfr
in range(1, 7):
260 intf
= topo
["routers"]["r1"]["links"]["r0-link{}".format(intfr
)]["interface"]
261 shutdown_bringup_interface(tgen
, dut
, intf
, False)
263 for intfr
in range(1, 7):
264 intf
= topo
["routers"]["r1"]["links"]["r0-link{}".format(intfr
)]["interface"]
265 shutdown_bringup_interface(tgen
, dut
, intf
, True)
268 "Verify that all the neighbours are up and routes are installed"
269 " with 8 next hop in ospf and ip route tables on R1."
272 step("Verify that OSPF is up with 8 neighborship sessions.")
274 ospf_covergence
= verify_ospf_neighbor(tgen
, topo
, dut
=dut
)
275 assert ospf_covergence
is True, "Testcase Failed \n Error {}".format(
280 result
= verify_ospf_rib(tgen
, dut
, input_dict
, next_hop
=nh
)
281 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
284 result
= verify_rib(tgen
, "ipv4", dut
, input_dict
, protocol
=protocol
, next_hop
=nh
)
285 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
287 step(" Un configure static route on R0")
290 redistribute_ospf(tgen
, topo
, dut
, "static", delete
=True)
292 # Wait for R0 to flush external LSAs.
295 step("Verify that route is withdrawn from R2.")
297 result
= verify_ospf_rib(
298 tgen
, dut
, input_dict
, next_hop
=nh
, retry_timeout
=10, expected
=False
302 ), "Testcase {} : Failed \n r1: OSPF routes are present \n Error: {}".format(
319 ), "Testcase {} : Failed \n r1: routes are still present \n Error: {}".format(
323 step("Re configure the static route in R0.")
325 redistribute_ospf(tgen
, topo
, dut
, "static")
328 result
= verify_ospf_rib(tgen
, dut
, input_dict
, next_hop
=nh
)
329 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
332 result
= verify_rib(tgen
, "ipv4", dut
, input_dict
, protocol
=protocol
, next_hop
=nh
)
333 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
335 write_test_footer(tc_name
)
338 def test_ospf_ecmp_tc17_p0(request
):
342 Verify OSPF ECMP with max path configured as 2 (Edge having 2 uplink ports)
344 tc_name
= request
.node
.name
345 write_test_header(tc_name
)
348 # Don't run this test if we have any failure.
349 if tgen
.routers_have_failure():
350 pytest
.skip(tgen
.errors
)
353 step("Bring up the base config as per the topology")
354 step("Configure 2 interfaces between R1 and R2 & enable ospf in area 0.")
355 reset_config_on_routers(tgen
)
356 step("Verify that OSPF is up with 2 neighborship sessions.")
358 ospf_covergence
= verify_ospf_neighbor(tgen
, topo
, dut
=dut
)
359 assert ospf_covergence
is True, "Testcase Failed \n Error {}".format(
363 step("Configure a static route in R0 and redistribute in OSPF.")
369 "network": NETWORK
["ipv4"][0],
376 result
= create_static_routes(tgen
, input_dict
)
377 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
380 redistribute_ospf(tgen
, topo
, dut
, "static")
382 step("Verify that route in R2 in stalled with 2 next hops.")
384 nh1
= topo
["routers"]["r0"]["links"]["r1-link1"]["ipv4"].split("/")[0]
385 nh2
= topo
["routers"]["r0"]["links"]["r1"]["ipv4"].split("/")[0]
389 result
= verify_ospf_rib(tgen
, dut
, input_dict
, next_hop
=nh
)
390 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
393 result
= verify_rib(tgen
, "ipv4", dut
, input_dict
, protocol
=protocol
, next_hop
=nh
)
394 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
396 step(" Un configure static route on R0")
399 redistribute_ospf(tgen
, topo
, dut
, "static", delete
=True)
400 # sleep till the route gets withdrawn
403 step("Verify that route is withdrawn from R2.")
405 result
= verify_ospf_rib(
406 tgen
, dut
, input_dict
, next_hop
=nh
, retry_timeout
=10, expected
=False
410 ), "Testcase {} : Failed \n r1: OSPF routes are present \n Error: {}".format(
427 ), "Testcase {} : Failed \n r1: routes are still present \n Error: {}".format(
431 step("Reconfigure the static route in R0.Change ECMP value to 2.")
433 redistribute_ospf(tgen
, topo
, dut
, "static")
435 step("Configure cost on R0 as 100")
436 r0_ospf_cost
= {"r0": {"links": {"r1": {"ospf": {"cost": 100}}}}}
437 result
= config_ospf_interface(tgen
, topo
, r0_ospf_cost
)
438 assert result
is True, "Testcase {} :Failed \n Error: {}".format(tc_name
, result
)
441 result
= verify_ospf_rib(tgen
, dut
, input_dict
, next_hop
=nh
)
442 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
445 result
= verify_rib(tgen
, "ipv4", dut
, input_dict
, protocol
=protocol
, next_hop
=nh
)
446 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
448 write_test_footer(tc_name
)
451 if __name__
== "__main__":
452 args
= ["-s"] + sys
.argv
[1:]
453 sys
.exit(pytest
.main(args
))