4 # Copyright (c) 2021 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."""
30 from copy
import deepcopy
31 from ipaddress
import IPv4Address
32 from lib
.topotest
import frr_unicode
35 # Save the Current Working Directory to find configuration files.
36 CWD
= os
.path
.dirname(os
.path
.realpath(__file__
))
37 sys
.path
.append(os
.path
.join(CWD
, "../"))
38 sys
.path
.append(os
.path
.join(CWD
, "../lib/"))
40 # pylint: disable=C0413
41 # Import topogen and topotest helpers
42 from lib
.topogen
import Topogen
, get_topogen
44 # Import topoJson from lib, to create topology and initial configuration
45 from lib
.common_config
import (
49 reset_config_on_routers
,
54 shutdown_bringup_interface
,
55 create_interfaces_cfg
,
56 get_frr_ipv6_linklocal
,
58 from lib
.topolog
import logger
59 from lib
.topojson
import build_config_from_json
61 from lib
.ospf
import (
62 verify_ospf6_neighbor
,
63 config_ospf_interface
,
67 verify_ospf6_interface
,
68 verify_ospf6_database
,
69 config_ospf6_interface
,
72 from ipaddress
import IPv6Address
74 pytestmark
= [pytest
.mark
.ospfd
, pytest
.mark
.staticd
]
88 "ipv6": ["2::1/128", "2::2/128", "2::3/128", "2::4/128", "2::5/128"],
90 MASK
= {"ipv6": "32", "ipv6": "128"}
94 Please view in a fixed-width font such as Courier.
95 Topo : Broadcast Networks
96 +---+ +---+ +---+ +---+
97 |R0 + +R1 + +R2 + +R3 |
98 +-+-+ +-+-+ +-+-+ +-+-+
101 --+-----------+--------------+---------------+-----
105 1. Verify OSPF ECMP with max path configured as 8
106 (Edge having 1 uplink port as broadcast network,
107 connect to 8 TORs - LAN case)
112 def setup_module(mod
):
114 Sets up the pytest environment
118 global topo
, switch_name
119 testsuite_run_time
= time
.asctime(time
.localtime(time
.time()))
120 logger
.info("Testsuite start time: {}".format(testsuite_run_time
))
121 logger
.info("=" * 40)
123 logger
.info("Running setup_module to create topology")
125 # This function initiates the topology build with Topogen...
126 json_file
= "{}/ospfv3_ecmp_lan.json".format(CWD
)
127 tgen
= Topogen(json_file
, mod
.__name
__)
129 topo
= tgen
.json_topo
130 # ... and here it calls Mininet initialization functions.
132 # Starting topology, create tmp files which are loaded to routers
133 # to start daemons and then start routers
136 # Creating configuration from JSON
137 build_config_from_json(tgen
, topo
)
139 # Don't run this test if we have any failure.
140 if tgen
.routers_have_failure():
141 pytest
.skip(tgen
.errors
)
142 # Api call verify whether OSPF is converged
143 ospf_covergence
= verify_ospf6_neighbor(tgen
, topo
, lan
=True)
144 assert ospf_covergence
is True, "setup_module :Failed \n Error: {}".format(
148 switch_name
= [k
for k
in topo
["switches"].keys()][0]
150 logger
.info("Running setup_module() done")
153 def teardown_module(mod
):
155 Teardown the pytest environment.
160 logger
.info("Running teardown_module to delete topology")
164 # Stop toplogy and Remove tmp files
167 # Stop toplogy and Remove tmp files
171 # OSError exception is raised when mininet tries to stop switch
172 # though switch is stopped once but mininet tries to stop same
173 # switch again, where it ended up with exception
176 "Testsuite end time: {}".format(time
.asctime(time
.localtime(time
.time())))
178 logger
.info("=" * 40)
181 def red_static(dut
, config
=True):
182 """Local def for Redstribute static routes inside ospf."""
186 ospf_red
= {dut
: {"ospf6": {"redistribute": [{"redist_type": "static"}]}}}
190 "ospf6": {"redistribute": [{"redist_type": "static", "delete": True}]}
193 result
= create_router_ospf(tgen
, topo
, ospf_red
)
194 assert result
is True, "Testcase : Failed \n Error: {}".format(result
)
197 def red_connected(dut
, config
=True):
198 """Local def for Redstribute connected routes inside ospf."""
202 ospf_red
= {dut
: {"ospf6": {"redistribute": [{"redist_type": "connected"}]}}}
207 "redistribute": [{"redist_type": "connected", "del_action": True}]
211 result
= create_router_ospf(tgen
, topo
, ospf_red
)
212 assert result
is True, "Testcase: Failed \n Error: {}".format(result
)
215 def get_llip(onrouter
, intf
):
217 API to get the link local ipv6 address of a particular interface
221 * `fromnode`: Source node
222 * `tonode` : interface for which link local ip needs to be returned.
226 result = get_llip('r1', 'r2-link0')
230 1) link local ipv6 address from the interface.
231 2) errormsg - when link local ip not found.
234 intf
= topo
["routers"][onrouter
]["links"][intf
]["interface"]
235 llip
= get_frr_ipv6_linklocal(tgen
, onrouter
, intf
)
237 logger
.info("llip ipv6 address to be set as NH is %s", llip
)
242 def get_glipv6(onrouter
, intf
):
244 API to get the global ipv6 address of a particular interface
248 * `onrouter`: Source node
249 * `intf` : interface for which link local ip needs to be returned.
253 result = get_glipv6('r1', 'r2-link0')
257 1) global ipv6 address from the interface.
258 2) errormsg - when link local ip not found.
260 glipv6
= (topo
["routers"][onrouter
]["links"][intf
]["ipv6"]).split("/")[0]
262 logger
.info("Global ipv6 address to be set as NH is %s", glipv6
)
267 # ##################################
268 # Test cases start here.
269 # ##################################
272 def test_ospfv3_lan_ecmp_tc18_p0(request
):
276 Verify OSPF ECMP with max path configured as 8
277 (Edge having 1 uplink port as broadcast network,
278 connect to 8 TORs - LAN case)
281 tc_name
= request
.node
.name
282 write_test_header(tc_name
)
285 # Don't run this test if we have any failure.
286 if tgen
.routers_have_failure():
287 pytest
.skip(tgen
.errors
)
290 step("Bring up the base config as per the topology")
291 step(". Configure ospf in all the routers on LAN interface.")
293 reset_config_on_routers(tgen
)
295 step("Verify that OSPF is up with 8 neighborship sessions.")
297 ospf_covergence
= verify_ospf6_neighbor(tgen
, topo
, lan
=True)
298 assert ospf_covergence
is True, "Testcase Failed \n Error: {}".format(
303 "Configure a static route in all the routes and "
304 "redistribute static/connected in OSPF."
307 for rtr
in topo
["routers"]:
311 {"network": NETWORK
["ipv6"][0], "no_of_ip": 5, "next_hop": "Null0"}
315 result
= create_static_routes(tgen
, input_dict
)
316 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
324 "Verify that route in R0 in stalled with 8 hops. "
325 "Verify ospf route table and ip route table."
329 for rtr
in topo
["routers"]:
330 llip
= get_llip(rtr
, switch_name
)
331 assert llip
is not None, "Testcase {} : Failed \n Error: {}".format(
336 llip
= get_llip("r1", switch_name
)
337 assert llip
is not None, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
341 result
= verify_ospf6_rib(tgen
, dut
, input_dict
)
342 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
345 result
= verify_rib(tgen
, "ipv6", dut
, input_dict
, protocol
=protocol
)
346 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
348 step(" clear ip ospf interface on DUT(r0)")
349 clear_ospf(tgen
, "r0", ospf
="ospf6")
352 "Verify that after clearing the ospf interface all the "
353 "neighbours are up and routes are installed with 8 next hop "
354 "in ospf and ip route tables on R0"
358 ospf_covergence
= verify_ospf6_neighbor(tgen
, topo
, dut
=dut
, lan
=True)
359 assert ospf_covergence
is True, "Testcase Failed \n Error: {}".format(
363 step(" clear ip ospf interface on R2")
364 clear_ospf(tgen
, "r2")
367 ospf_covergence
= verify_ospf6_neighbor(tgen
, topo
, dut
=dut
, lan
=True)
368 assert ospf_covergence
is True, "Testcase Failed \n Error: {}".format(
372 step("Delete static/connected cmd in ospf in all the routes one by one.")
373 for rtr
in topo
["routers"]:
378 "network": NETWORK
["ipv6"][0],
386 result
= create_static_routes(tgen
, input_dict
)
387 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
391 write_test_footer(tc_name
)
394 if __name__
== "__main__":
395 args
= ["-s"] + sys
.argv
[1:]
396 sys
.exit(pytest
.main(args
))