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