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 copy
import deepcopy
30 from lib
.topotest
import frr_unicode
32 # Save the Current Working Directory to find configuration files.
33 CWD
= os
.path
.dirname(os
.path
.realpath(__file__
))
34 sys
.path
.append(os
.path
.join(CWD
, "../"))
35 sys
.path
.append(os
.path
.join(CWD
, "../lib/"))
37 # pylint: disable=C0413
38 # Import topogen and topotest helpers
39 from lib
.topogen
import Topogen
, get_topogen
41 # Import topoJson from lib, to create topology and initial configuration
42 from lib
.common_config
import (
45 create_interfaces_cfg
,
47 reset_config_on_routers
,
49 shutdown_bringup_interface
,
54 from lib
.topolog
import logger
55 from lib
.topojson
import build_config_from_json
56 from lib
.ospf
import (
60 verify_ospf_interface
,
62 from ipaddress
import IPv4Address
64 pytestmark
= [pytest
.mark
.ospfd
, pytest
.mark
.staticd
]
83 Please view in a fixed-width font such as Courier.
84 Topo : Broadcast Networks
85 +---+ +---+ +---+ +---+
86 |R0 + +R1 + +R2 + +R3 |
87 +-+-+ +-+-+ +-+-+ +-+-+
90 --+-----------+--------------+---------------+-----
94 1. OSPF Hello protocol - Verify DR BDR Elections
95 2. OSPF IFSM -Verify state change events on DR / BDR / DR Other
100 def setup_module(mod
):
102 Sets up the pytest environment
106 testsuite_run_time
= time
.asctime(time
.localtime(time
.time()))
107 logger
.info("Testsuite start time: {}".format(testsuite_run_time
))
108 logger
.info("=" * 40)
110 logger
.info("Running setup_module to create topology")
112 # This function initiates the topology build with Topogen...
113 json_file
= "{}/ospf_lan.json".format(CWD
)
114 tgen
= Topogen(json_file
, mod
.__name
__)
116 topo
= tgen
.json_topo
117 # ... and here it calls Mininet initialization functions.
119 # get list of daemons needs to be started for this suite.
120 daemons
= topo_daemons(tgen
, topo
)
122 # Starting topology, create tmp files which are loaded to routers
123 # to start deamons and then start routers
124 start_topology(tgen
, daemons
)
126 # Creating configuration from JSON
127 build_config_from_json(tgen
, topo
)
129 # Don't run this test if we have any failure.
130 if tgen
.routers_have_failure():
131 pytest
.skip(tgen
.errors
)
132 # Api call verify whether OSPF is converged
133 ospf_covergence
= verify_ospf_neighbor(tgen
, topo
, lan
=True)
134 assert ospf_covergence
is True, "setup_module :Failed \n Error:" " {}".format(
138 logger
.info("Running setup_module() done")
141 def teardown_module():
142 """Teardown the pytest environment"""
144 logger
.info("Running teardown_module to delete topology")
149 # Stop toplogy and Remove tmp files
153 # OSError exception is raised when mininet tries to stop switch
154 # though switch is stopped once but mininet tries to stop same
155 # switch again, where it ended up with exception
159 # ##################################
160 # Test cases start here.
161 # ##################################
164 def test_ospf_lan_tc1_p0(request
):
166 OSPF Hello protocol - Verify DR BDR Elections
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 reset_config_on_routers(tgen
)
180 step("Verify that DR BDR DRother are elected in the LAN.")
185 "r1": {"state": "Full", "role": "DR"},
186 "r2": {"state": "Full", "role": "DROther"},
187 "r3": {"state": "Full", "role": "DROther"},
193 result
= verify_ospf_neighbor(tgen
, topo
, dut
, input_dict
, lan
=True)
194 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
197 "Verify that all the routers are in FULL state with DR and BDR "
205 "r0": {"state": "Full", "role": "Backup"},
206 "r2": {"state": "Full", "role": "DROther"},
207 "r3": {"state": "Full", "role": "DROther"},
213 result
= verify_ospf_neighbor(tgen
, topo
, dut
, input_dict
, lan
=True)
214 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
217 "Configure DR pririty 100 on R0 and clear ospf neighbors " "on all the routers."
224 "interface": topo
["routers"]["r0"]["links"]["s1"]["interface"],
225 "ospf": {"priority": 100},
231 result
= create_interfaces_cfg(tgen
, input_dict
)
232 assert result
is True, "Testcase {} :Failed \n Error: {}".format(tc_name
, result
)
234 step("Clear ospf neighbours in all routers")
235 for rtr
in ["r0", "r1", "r2", "r3"]:
236 clear_ospf(tgen
, rtr
)
238 step("Verify that DR election is triggered and R0 is elected as DR")
243 "r1": {"state": "Full", "role": "Backup"},
244 "r2": {"state": "Full", "role": "DROther"},
245 "r3": {"state": "Full", "role": "DROther"},
251 result
= verify_ospf_neighbor(tgen
, topo
, dut
, input_dict
, lan
=True)
252 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
255 "Configure DR pririty 150 on R0 and clear ospf neighbors " "on all the routers."
262 "interface": topo
["routers"]["r0"]["links"]["s1"]["interface"],
263 "ospf": {"priority": 150},
269 result
= create_interfaces_cfg(tgen
, input_dict
)
270 assert result
is True, "Testcase {} :Failed \n Error: {}".format(tc_name
, result
)
272 step("Clear ospf neighbours in all routers")
273 for rtr
in ["r0", "r1"]:
274 clear_ospf(tgen
, rtr
)
276 step("Verify that DR election is triggered and R0 is elected as DR")
281 "r1": {"state": "Full", "role": "Backup"},
282 "r2": {"state": "Full", "role": "DROther"},
283 "r3": {"state": "Full", "role": "DROther"},
289 result
= verify_ospf_neighbor(tgen
, topo
, dut
, input_dict
, lan
=True)
290 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
292 step("Configure DR priority 0 on R0 & Clear ospf nbrs on all the routers")
298 "interface": topo
["routers"]["r0"]["links"]["s1"]["interface"],
299 "ospf": {"priority": 0},
305 result
= create_interfaces_cfg(tgen
, input_dict
)
306 assert result
is True, "Testcase {} :Failed \n Error: {}".format(tc_name
, result
)
308 step("Clear ospf neighbours in all routers")
310 clear_ospf(tgen
, rtr
)
312 step("Verify that DR election is triggered and R0 is elected as DRother")
317 "r1": {"state": "Full", "role": "DR"},
318 "r2": {"state": "2-Way", "role": "DROther"},
319 "r3": {"state": "2-Way", "role": "DROther"},
325 result
= verify_ospf_neighbor(tgen
, topo
, dut
, input_dict
, lan
=True)
326 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
329 "Configure DR priority to default on R0 and Clear ospf neighbors"
330 " on all the routers"
337 "interface": topo
["routers"]["r0"]["links"]["s1"]["interface"],
338 "ospf": {"priority": 100},
344 result
= create_interfaces_cfg(tgen
, input_dict
)
345 assert result
is True, "Testcase {} :Failed \n Error: {}".format(tc_name
, result
)
347 step("Clear ospf neighbours in all routers")
348 for rtr
in ["r0", "r1"]:
349 clear_ospf(tgen
, rtr
)
351 step("Verify that DR election is triggered and R0 is elected as DR")
356 "r1": {"state": "Full", "role": "Backup"},
357 "r2": {"state": "Full", "role": "DROther"},
358 "r3": {"state": "Full", "role": "DROther"},
364 result
= verify_ospf_neighbor(tgen
, topo
, dut
, input_dict
, lan
=True)
365 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
367 step("Shut interface on R0")
369 intf
= topo
["routers"]["r0"]["links"]["s1"]["interface"]
370 shutdown_bringup_interface(tgen
, dut
, intf
, False)
372 result
= verify_ospf_neighbor(tgen
, topo
, dut
, lan
=True, expected
=False)
375 ), "Testcase {} : Failed \n " "r0: OSPF neighbors-hip is up \n Error: {}".format(
379 step("No Shut interface on R0")
381 intf
= topo
["routers"]["r0"]["links"]["s1"]["interface"]
382 shutdown_bringup_interface(tgen
, dut
, intf
, True)
388 "r1": {"state": "Full", "role": "DR"},
389 "r2": {"state": "Full", "role": "DROther"},
390 "r3": {"state": "Full", "role": "DROther"},
395 step("Verify that after no shut ospf neighbours are full on R0.")
396 result
= verify_ospf_neighbor(tgen
, topo
, dut
, input_dict
, lan
=True)
397 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
399 step("Clear ospf on DR router in the topology.")
400 clear_ospf(tgen
, "r0")
402 step("Verify that BDR is getting promoted to DR after clear.")
403 step("Verify that all the nbrs are in FULL state with the elected DR.")
404 result
= verify_ospf_neighbor(tgen
, topo
, dut
, input_dict
, lan
=True)
405 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
407 step("Change the ip on LAN intf on R0 to other ip from the same subnet.")
408 topo_modify_change_ip
= deepcopy(topo
)
409 intf_ip
= topo_modify_change_ip
["routers"]["r0"]["links"]["s1"]["ipv4"]
410 topo_modify_change_ip
["routers"]["r0"]["links"]["s1"]["ipv4"] = str(
411 IPv4Address(frr_unicode(intf_ip
.split("/")[0])) + 4
412 ) + "/{}".format(intf_ip
.split("/")[1])
414 build_config_from_json(tgen
, topo_modify_change_ip
, save_bkup
=False)
417 "Verify that OSPF is in FULL state with other routers with "
418 "newly configured IP."
420 result
= verify_ospf_neighbor(tgen
, topo
, dut
, input_dict
, lan
=True)
421 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
423 step("Change the ospf router id on the R0 and clear ip ospf interface.")
424 change_rid
= {"r0": {"ospf": {"router_id": "100.1.1.100"}}}
426 result
= create_router_ospf(tgen
, topo
, change_rid
)
427 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
428 topo
["routers"]["r0"]["ospf"]["router_id"] = "100.1.1.100"
429 step("Reload the FRR router")
431 stop_router(tgen
, "r0")
432 start_router(tgen
, "r0")
435 "Verify that OSPF is in FULL state with other routers with"
436 " newly configured router id."
442 "r0": {"state": "Full", "role": "Backup"},
443 "r2": {"state": "Full", "role": "DROther"},
444 "r3": {"state": "Full", "role": "DROther"},
450 result
= verify_ospf_neighbor(tgen
, topo
, dut
, input_dict
, lan
=True)
451 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
453 step("Reconfigure the original router id and clear ip ospf interface.")
454 change_rid
= {"r0": {"ospf": {"router_id": "100.1.1.0"}}}
455 result
= create_router_ospf(tgen
, topo
, change_rid
)
456 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
457 topo
["routers"]["r0"]["ospf"]["router_id"] = "100.1.1.0"
458 step("Reload the FRR router")
459 # stop/start -> restart FRR router and verify
460 stop_router(tgen
, "r0")
461 start_router(tgen
, "r0")
463 step("Verify that OSPF is enabled with router id previously configured.")
468 "r0": {"state": "Full", "role": "Backup"},
469 "r2": {"state": "Full", "role": "DROther"},
470 "r3": {"state": "Full", "role": "DROther"},
476 result
= verify_ospf_neighbor(tgen
, topo
, dut
, input_dict
, lan
=True)
477 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
479 write_test_footer(tc_name
)
482 def test_ospf_lan_tc2_p0(request
):
484 OSPF IFSM -Verify state change events on DR / BDR / DR Other
487 tc_name
= request
.node
.name
488 write_test_header(tc_name
)
491 # Don't run this test if we have any failure.
492 if tgen
.routers_have_failure():
493 pytest
.skip(tgen
.errors
)
496 step("Bring up the base config as per the topology")
497 reset_config_on_routers(tgen
)
499 "Verify that OSPF is subscribed to multi cast services "
500 "(All SPF, all DR Routers)."
502 step("Verify that interface is enabled in ospf.")
512 "mcastMemberOspfDesignatedRouters": True,
513 "mcastMemberOspfAllRouters": True,
520 result
= verify_ospf_interface(tgen
, topo
, dut
=dut
, input_dict
=input_dict
)
521 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
523 step("Delete the ip address")
528 "ipv4": topo
["routers"]["r0"]["links"]["s1"]["ipv4"],
529 "interface": topo
["routers"]["r0"]["links"]["s1"]["interface"],
536 result
= create_interfaces_cfg(tgen
, topo1
)
537 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
539 step("Change the ip on the R0 interface")
541 topo_modify_change_ip
= deepcopy(topo
)
542 intf_ip
= topo_modify_change_ip
["routers"]["r0"]["links"]["s1"]["ipv4"]
543 topo_modify_change_ip
["routers"]["r0"]["links"]["s1"]["ipv4"] = str(
544 IPv4Address(frr_unicode(intf_ip
.split("/")[0])) + 3
545 ) + "/{}".format(intf_ip
.split("/")[1])
547 build_config_from_json(tgen
, topo_modify_change_ip
, save_bkup
=False)
548 step("Verify that interface is enabled in ospf.")
555 "ipAddress": topo_modify_change_ip
["routers"]["r0"]["links"][
557 ]["ipv4"].split("/")[0],
558 "ipAddressPrefixlen": int(
559 topo_modify_change_ip
["routers"]["r0"]["links"]["s1"][
568 result
= verify_ospf_interface(tgen
, topo
, dut
=dut
, input_dict
=input_dict
)
569 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
571 step("Modify the mask on the R0 interface")
572 ip_addr
= topo_modify_change_ip
["routers"]["r0"]["links"]["s1"]["ipv4"]
573 mask
= topo_modify_change_ip
["routers"]["r0"]["links"]["s1"]["ipv4"]
574 step("Delete the ip address")
580 "interface": topo
["routers"]["r0"]["links"]["s1"]["interface"],
587 result
= create_interfaces_cfg(tgen
, topo1
)
588 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
590 step("Change the ip on the R0 interface")
592 topo_modify_change_ip
= deepcopy(topo
)
593 intf_ip
= topo_modify_change_ip
["routers"]["r0"]["links"]["s1"]["ipv4"]
594 topo_modify_change_ip
["routers"]["r0"]["links"]["s1"]["ipv4"] = str(
595 IPv4Address(frr_unicode(intf_ip
.split("/")[0])) + 3
596 ) + "/{}".format(int(intf_ip
.split("/")[1]) + 1)
598 build_config_from_json(tgen
, topo_modify_change_ip
, save_bkup
=False)
599 step("Verify that interface is enabled in ospf.")
606 "ipAddress": topo_modify_change_ip
["routers"]["r0"]["links"][
608 ]["ipv4"].split("/")[0],
609 "ipAddressPrefixlen": int(
610 topo_modify_change_ip
["routers"]["r0"]["links"]["s1"][
619 result
= verify_ospf_interface(tgen
, topo
, dut
=dut
, input_dict
=input_dict
)
620 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
622 step("Change the area id on the interface")
627 "interface": topo
["routers"]["r0"]["links"]["s1"]["interface"],
628 "ospf": {"area": "0.0.0.3"},
635 result
= create_interfaces_cfg(tgen
, input_dict
)
636 assert result
is True, "Testcase {} :Failed \n Error: {}".format(tc_name
, result
)
642 "interface": topo
["routers"]["r0"]["links"]["s1"]["interface"],
643 "ospf": {"area": "0.0.0.2"},
649 result
= create_interfaces_cfg(tgen
, input_dict
)
650 assert result
is True, "Testcase {} :Failed \n Error: {}".format(tc_name
, result
)
651 step("Verify that interface is enabled in ospf.")
654 "r0": {"links": {"s1": {"ospf": {"area": "0.0.0.2", "ospfEnabled": True}}}}
656 result
= verify_ospf_interface(tgen
, topo
, dut
=dut
, input_dict
=input_dict
)
657 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
659 write_test_footer(tc_name
)
662 if __name__
== "__main__":
663 args
= ["-s"] + sys
.argv
[1:]
664 sys
.exit(pytest
.main(args
))