]> git.proxmox.com Git - mirror_frr.git/blame - tests/topotests/ospf_basic_functionality/test_ospf_ecmp.py
tests: Topotests daemon start as per feature test
[mirror_frr.git] / tests / topotests / ospf_basic_functionality / test_ospf_ecmp.py
CommitLineData
4256a209 1#!/usr/bin/python
2
3#
4# Copyright (c) 2020 by VMware, Inc. ("VMware")
5# Used Copyright (c) 2018 by Network Device Education Foundation, Inc.
6# ("NetDEF") in this file.
7#
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
11# in all copies.
12#
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
20# OF THIS SOFTWARE.
21#
22
23
24"""OSPF Basic Functionality Automation."""
25import os
26import sys
27import time
28import pytest
4256a209 29from time import sleep
4256a209 30
31# Save the Current Working Directory to find configuration files.
32CWD = os.path.dirname(os.path.realpath(__file__))
33sys.path.append(os.path.join(CWD, "../"))
34sys.path.append(os.path.join(CWD, "../lib/"))
35
36# pylint: disable=C0413
37# Import topogen and topotest helpers
4256a209 38from lib.topogen import Topogen, get_topogen
4256a209 39
40# Import topoJson from lib, to create topology and initial configuration
41from lib.common_config import (
42 start_topology,
43 write_test_header,
44 write_test_footer,
45 reset_config_on_routers,
46 verify_rib,
47 create_static_routes,
48 step,
4256a209 49 shutdown_bringup_interface,
701a0192 50 topo_daemons,
4256a209 51)
52from lib.topolog import logger
53
4953ca97 54from lib.topojson import build_config_from_json
4256a209 55from lib.ospf import (
56 verify_ospf_neighbor,
57 config_ospf_interface,
4256a209 58 verify_ospf_rib,
88b7d3e7 59 redistribute_ospf,
4256a209 60)
61
6ff492b1
DS
62pytestmark = [pytest.mark.ospfd, pytest.mark.staticd]
63
64
4256a209 65topo = None
66
4256a209 67
68# Global variables
69NETWORK = {
70 "ipv4": [
71 "11.0.20.1/32",
72 "11.0.20.2/32",
73 "11.0.20.3/32",
74 "11.0.20.4/32",
75 "11.0.20.5/32",
76 ]
77}
78"""
79TOPOLOGY :
80 Please view in a fixed-width font such as Courier.
81 +---+ A1 +---+
82 +R1 +------------+R2 |
83 +-+-+- +--++
84 | -- -- |
85 | -- A0 -- |
86 A0| ---- |
87 | ---- | A2
88 | -- -- |
89 | -- -- |
90 +-+-+- +-+-+
91 +R0 +-------------+R3 |
92 +---+ A3 +---+
93
94TESTCASES :
951. Verify OSPF ECMP with max path configured as 8 (ECMPconfigured at FRR level)
962. Verify OSPF ECMP with max path configured as 2 (Edge having 2 uplink ports)
97 """
98
99
4256a209 100def setup_module(mod):
101 """
102 Sets up the pytest environment
103
104 * `mod`: module name
105 """
4256a209 106 testsuite_run_time = time.asctime(time.localtime(time.time()))
107 logger.info("Testsuite start time: {}".format(testsuite_run_time))
108 logger.info("=" * 40)
109
110 logger.info("Running setup_module to create topology")
111
112 # This function initiates the topology build with Topogen...
e82b531d
CH
113 json_file = "{}/ospf_ecmp.json".format(CWD)
114 tgen = Topogen(json_file, mod.__name__)
115 global topo
116 topo = tgen.json_topo
4256a209 117 # ... and here it calls Mininet initialization functions.
118
035267a3 119 # get list of daemons needs to be started for this suite.
120 daemons = topo_daemons(tgen, topo)
121
4256a209 122 # Starting topology, create tmp files which are loaded to routers
d60a3f0e 123 # to start daemons and then start routers
035267a3 124 start_topology(tgen, daemons)
4256a209 125
126 # Creating configuration from JSON
127 build_config_from_json(tgen, topo)
128
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)
134 assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
135 ospf_covergence
136 )
137
138 logger.info("Running setup_module() done")
139
140
141def teardown_module(mod):
142 """
143 Teardown the pytest environment.
144
145 * `mod`: module name
146 """
147
148 logger.info("Running teardown_module to delete topology")
149
150 tgen = get_topogen()
151
152 # Stop toplogy and Remove tmp files
153 tgen.stop_topology()
154
155 logger.info(
156 "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
157 )
158 logger.info("=" * 40)
159
160
4256a209 161# ##################################
162# Test cases start here.
163# ##################################
164
165
166def test_ospf_ecmp_tc16_p0(request):
167 """
168 Verify OSPF ECMP.
169
170 Verify OSPF ECMP with max path configured as 8 (ECMP
171 configured at FRR level)
172 """
173 tc_name = request.node.name
174 write_test_header(tc_name)
175 tgen = get_topogen()
176
177 # Don't run this test if we have any failure.
178 if tgen.routers_have_failure():
179 pytest.skip(tgen.errors)
180
181 global topo
182 step("Bring up the base config as per the topology")
183 step("Configure 8 interfaces between R1 and R2 and enable ospf in area 0.")
184 reset_config_on_routers(tgen)
185 step("Verify that OSPF is up with 8 neighborship sessions.")
186 dut = "r1"
187 ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut)
188 assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
189 ospf_covergence
190 )
191
192 step("Configure a static route in R0 and redistribute in OSPF.")
193
194 input_dict = {
195 "r0": {
196 "static_routes": [
9fa6ec14 197 {
198 "network": NETWORK["ipv4"][0],
199 "no_of_ip": 5,
200 "next_hop": "Null0",
201 }
4256a209 202 ]
203 }
204 }
205 result = create_static_routes(tgen, input_dict)
206 assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
207
208 dut = "r0"
88b7d3e7 209 redistribute_ospf(tgen, topo, dut, "static")
4256a209 210
211 step("Verify that route in R2 in stalled with 8 next hops.")
212 nh = []
213 for item in range(1, 7):
214 nh.append(topo["routers"]["r0"]["links"]["r1-link1"]["ipv4"].split("/")[0])
215
216 nh2 = topo["routers"]["r0"]["links"]["r1"]["ipv4"].split("/")[0]
217
218 nh.append(nh2)
219
220 dut = "r1"
221 result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh)
222 assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
223
224 protocol = "ospf"
225 result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh)
226 assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
227
228 step("shut no shut all the interfaces on the remote router - R2")
229 dut = "r1"
230 for intfr in range(1, 7):
231 intf = topo["routers"]["r1"]["links"]["r0-link{}".format(intfr)]["interface"]
232 shutdown_bringup_interface(tgen, dut, intf, False)
233
234 result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh, expected=False)
0b25370e
DS
235 assert (
236 result is not True
237 ), "Testcase {} : Failed \n " "r1: OSPF routes are present \n Error: {}".format(
4256a209 238 tc_name, result
0b25370e 239 )
4256a209 240
241 protocol = "ospf"
242 result = verify_rib(
243 tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh, expected=False
244 )
0b25370e
DS
245 assert (
246 result is not True
247 ), "Testcase {} : Failed \n " "r1: routes are still present \n Error: {}".format(
4256a209 248 tc_name, result
0b25370e 249 )
4256a209 250
251 for intfr in range(1, 7):
252 intf = topo["routers"]["r1"]["links"]["r0-link{}".format(intfr)]["interface"]
253 shutdown_bringup_interface(tgen, dut, intf, True)
254
255 result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh)
256 assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
257
258 protocol = "ospf"
259 result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh)
260 assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
261
262 step("shut no shut on all the interfaces on DUT (r1)")
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, False)
266
267 for intfr in range(1, 7):
268 intf = topo["routers"]["r1"]["links"]["r0-link{}".format(intfr)]["interface"]
269 shutdown_bringup_interface(tgen, dut, intf, True)
270
271 step(
272 "Verify that all the neighbours are up and routes are installed"
273 " with 8 next hop in ospf and ip route tables on R1."
274 )
275
276 step("Verify that OSPF is up with 8 neighborship sessions.")
277 dut = "r1"
278 ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut)
279 assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
280 ospf_covergence
281 )
282
283 dut = "r1"
284 result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh)
285 assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
286
287 protocol = "ospf"
288 result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh)
289 assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
290
291 step(" Un configure static route on R0")
292
293 dut = "r0"
88b7d3e7 294 redistribute_ospf(tgen, topo, dut, "static", delete=True)
4256a209 295
296 # Wait for R0 to flush external LSAs.
297 sleep(10)
298
299 step("Verify that route is withdrawn from R2.")
300 dut = "r1"
301 result = verify_ospf_rib(
ed776e38 302 tgen, dut, input_dict, next_hop=nh, retry_timeout=10, expected=False
4256a209 303 )
0b25370e
DS
304 assert (
305 result is not True
306 ), "Testcase {} : Failed \n " "r1: OSPF routes are present \n Error: {}".format(
4256a209 307 tc_name, result
0b25370e 308 )
4256a209 309
310 protocol = "ospf"
a81774ec 311 result = verify_rib(
312 tgen,
313 "ipv4",
314 dut,
315 input_dict,
316 protocol=protocol,
317 next_hop=nh,
ed776e38 318 retry_timeout=10,
a81774ec 319 expected=False,
320 )
0b25370e
DS
321 assert (
322 result is not True
323 ), "Testcase {} : Failed \n " "r1: routes are still present \n Error: {}".format(
4256a209 324 tc_name, result
0b25370e 325 )
4256a209 326
327 step("Re configure the static route in R0.")
328 dut = "r0"
88b7d3e7 329 redistribute_ospf(tgen, topo, dut, "static")
4256a209 330
331 dut = "r1"
332 result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh)
333 assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
334
335 protocol = "ospf"
336 result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh)
337 assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
338
339 write_test_footer(tc_name)
340
341
342def test_ospf_ecmp_tc17_p0(request):
343 """
344 Verify OSPF ECMP.
345
346 Verify OSPF ECMP with max path configured as 2 (Edge having 2 uplink ports)
347 """
348 tc_name = request.node.name
349 write_test_header(tc_name)
350 tgen = get_topogen()
351
352 # Don't run this test if we have any failure.
353 if tgen.routers_have_failure():
354 pytest.skip(tgen.errors)
355
356 global topo
357 step("Bring up the base config as per the topology")
358 step("Configure 2 interfaces between R1 and R2 & enable ospf in area 0.")
359 reset_config_on_routers(tgen)
360 step("Verify that OSPF is up with 2 neighborship sessions.")
361 dut = "r1"
362 ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut)
363 assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
364 ospf_covergence
365 )
366
367 step("Configure a static route in R0 and redistribute in OSPF.")
368
369 input_dict = {
370 "r0": {
371 "static_routes": [
9fa6ec14 372 {
373 "network": NETWORK["ipv4"][0],
374 "no_of_ip": 5,
375 "next_hop": "Null0",
376 }
4256a209 377 ]
378 }
379 }
380 result = create_static_routes(tgen, input_dict)
381 assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
382
383 dut = "r0"
88b7d3e7 384 redistribute_ospf(tgen, topo, dut, "static")
4256a209 385
386 step("Verify that route in R2 in stalled with 2 next hops.")
387
388 nh1 = topo["routers"]["r0"]["links"]["r1-link1"]["ipv4"].split("/")[0]
389 nh2 = topo["routers"]["r0"]["links"]["r1"]["ipv4"].split("/")[0]
390 nh = [nh1, nh2]
391
392 dut = "r1"
393 result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh)
394 assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
395
396 protocol = "ospf"
397 result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh)
398 assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
399
400 step(" Un configure static route on R0")
401
402 dut = "r0"
88b7d3e7 403 redistribute_ospf(tgen, topo, dut, "static", delete=True)
4256a209 404 # sleep till the route gets withdrawn
405 sleep(10)
406
407 step("Verify that route is withdrawn from R2.")
408 dut = "r1"
a81774ec 409 result = verify_ospf_rib(
ed776e38 410 tgen, dut, input_dict, next_hop=nh, retry_timeout=10, expected=False
a81774ec 411 )
0b25370e
DS
412 assert (
413 result is not True
414 ), "Testcase {} : Failed \n " "r1: OSPF routes are present \n Error: {}".format(
4256a209 415 tc_name, result
0b25370e 416 )
4256a209 417
418 protocol = "ospf"
a81774ec 419 result = verify_rib(
420 tgen,
421 "ipv4",
422 dut,
423 input_dict,
424 protocol=protocol,
425 next_hop=nh,
ed776e38 426 retry_timeout=10,
a81774ec 427 expected=False,
428 )
0b25370e
DS
429 assert (
430 result is not True
431 ), "Testcase {} : Failed \n " "r1: routes are still present \n Error: {}".format(
4256a209 432 tc_name, result
0b25370e 433 )
4256a209 434
435 step("Reconfigure the static route in R0.Change ECMP value to 2.")
436 dut = "r0"
88b7d3e7 437 redistribute_ospf(tgen, topo, dut, "static")
4256a209 438
439 step("Configure cost on R0 as 100")
440 r0_ospf_cost = {"r0": {"links": {"r1": {"ospf": {"cost": 100}}}}}
441 result = config_ospf_interface(tgen, topo, r0_ospf_cost)
442 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
443
444 dut = "r1"
445 result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh)
446 assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
447
448 protocol = "ospf"
449 result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh)
450 assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
451
452 write_test_footer(tc_name)
453
454
455if __name__ == "__main__":
456 args = ["-s"] + sys.argv[1:]
457 sys.exit(pytest.main(args))