]> git.proxmox.com Git - mirror_frr.git/blame - tests/topotests/ospf_basic_functionality/test_ospf_p2mp.py
tests: Topotests daemon start as per feature test
[mirror_frr.git] / tests / topotests / ospf_basic_functionality / test_ospf_p2mp.py
CommitLineData
dc5298d7 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
dc5298d7 29from copy import deepcopy
30from ipaddress import IPv4Address
31
32# Save the Current Working Directory to find configuration files.
33CWD = os.path.dirname(os.path.realpath(__file__))
34sys.path.append(os.path.join(CWD, "../"))
35sys.path.append(os.path.join(CWD, "../lib/"))
36
37# pylint: disable=C0413
38# Import topogen and topotest helpers
dc5298d7 39from lib.topogen import Topogen, get_topogen
dc5298d7 40
41# Import topoJson from lib, to create topology and initial configuration
42from lib.common_config import (
43 start_topology,
44 write_test_header,
45 write_test_footer,
46 reset_config_on_routers,
dc5298d7 47 step,
dc5298d7 48 create_interfaces_cfg,
49 topo_daemons,
675ba67d
LB
50 retry,
51 run_frr_cmd,
dc5298d7 52)
53from lib.topolog import logger
4953ca97 54from lib.topojson import build_config_from_json
675ba67d 55from lib.topotest import frr_unicode, json_cmp
dc5298d7 56
57from lib.ospf import (
dc5298d7 58 verify_ospf_interface,
dc5298d7 59)
60
6ff492b1 61
e82b531d 62pytestmark = [pytest.mark.ospfd, pytest.mark.staticd]
6ff492b1 63
dc5298d7 64# Global variables
65topo = None
66
dc5298d7 67
68"""
69TOPOOLOGY =
70 Please view in a fixed-width font such as Courier.
71 +---+ A1 +---+
72 +R1 +------------+R2 |
73 +-+-+- +--++
74 | -- -- |
75 | -- A0 -- |
76 A0| ---- |
77 | ---- | A2
78 | -- -- |
79 | -- -- |
80 +-+-+- +-+-+
81 +R0 +-------------+R3 |
82 +---+ A3 +---+
83
84TESTCASES =
851. OSPF P2MP -Verify state change events on p2mp network.
86 """
87
88
dc5298d7 89def setup_module(mod):
90 """
91 Sets up the pytest environment
92
93 * `mod`: module name
94 """
dc5298d7 95 testsuite_run_time = time.asctime(time.localtime(time.time()))
96 logger.info("Testsuite start time: {}".format(testsuite_run_time))
97 logger.info("=" * 40)
98
99 logger.info("Running setup_module to create topology")
100
101 # This function initiates the topology build with Topogen...
e82b531d
CH
102 json_file = "{}/ospf_p2mp.json".format(CWD)
103 tgen = Topogen(json_file, mod.__name__)
104 global topo
105 topo = tgen.json_topo
dc5298d7 106 # ... and here it calls Mininet initialization functions.
107
108 # get list of daemons needs to be started for this suite.
109 daemons = topo_daemons(tgen, topo)
110
111 # Starting topology, create tmp files which are loaded to routers
d60a3f0e 112 # to start daemons and then start routers
dc5298d7 113 start_topology(tgen, daemons)
114
115 # Creating configuration from JSON
116 build_config_from_json(tgen, topo)
117
118 # Don't run this test if we have any failure.
119 if tgen.routers_have_failure():
120 pytest.skip(tgen.errors)
121
dc5298d7 122 logger.info("Running setup_module() done")
123
124
125def teardown_module(mod):
126 """
127 Teardown the pytest environment.
128
129 * `mod`: module name
130 """
131
132 logger.info("Running teardown_module to delete topology")
133
134 tgen = get_topogen()
135
136 # Stop toplogy and Remove tmp files
137 tgen.stop_topology()
138
139 logger.info(
140 "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
141 )
142 logger.info("=" * 40)
143
144
145# ##################################
146# Test cases start here.
147# ##################################
148
149
150def test_ospf_p2mp_tc1_p0(request):
151 """OSPF IFSM -Verify state change events on p2mp network."""
152 tc_name = request.node.name
153 write_test_header(tc_name)
154 tgen = get_topogen()
155
156 # Don't run this test if we have any failure.
157 if tgen.routers_have_failure():
158 pytest.skip(tgen.errors)
159
160 global topo
161 step("Bring up the base config as per the topology")
162 reset_config_on_routers(tgen)
163 step(
164 "Verify that OSPF is subscribed to multi cast services "
165 "(All SPF, all DR Routers)."
166 )
167 step("Verify that interface is enabled in ospf.")
168 step("Verify that config is successful.")
169 dut = "r0"
170 input_dict = {
171 "r0": {
172 "links": {
173 "r3": {"ospf": {"mcastMemberOspfAllRouters": True, "ospfEnabled": True}}
174 }
175 }
176 }
177 result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
178 assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
179
180 step("Delete the ip address")
181 topo1 = {
182 "r0": {
183 "links": {
184 "r3": {
185 "ipv4": topo["routers"]["r0"]["links"]["r3"]["ipv4"],
186 "interface": topo["routers"]["r0"]["links"]["r3"]["interface"],
187 "delete": True,
188 }
189 }
190 }
191 }
192
193 result = create_interfaces_cfg(tgen, topo1)
194 assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
195
196 step("Change the ip on the R0 interface")
197
198 topo_modify_change_ip = deepcopy(topo)
199 intf_ip = topo_modify_change_ip["routers"]["r0"]["links"]["r3"]["ipv4"]
200 topo_modify_change_ip["routers"]["r0"]["links"]["r3"]["ipv4"] = str(
d7d21c3a 201 IPv4Address(frr_unicode(intf_ip.split("/")[0])) + 3
dc5298d7 202 ) + "/{}".format(intf_ip.split("/")[1])
203
204 build_config_from_json(tgen, topo_modify_change_ip, save_bkup=False)
205 step("Verify that interface is enabled in ospf.")
206 dut = "r0"
207 input_dict = {
208 "r0": {
209 "links": {
210 "r3": {
211 "ospf": {
212 "ipAddress": topo_modify_change_ip["routers"]["r0"]["links"][
213 "r3"
214 ]["ipv4"].split("/")[0],
215 "ipAddressPrefixlen": int(
216 topo_modify_change_ip["routers"]["r0"]["links"]["r3"][
217 "ipv4"
218 ].split("/")[1]
219 ),
220 }
221 }
222 }
223 }
224 }
225 result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
226 assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
227
228 step("Modify the mask on the R0 interface")
229 ip_addr = topo_modify_change_ip["routers"]["r0"]["links"]["r3"]["ipv4"]
230 mask = topo_modify_change_ip["routers"]["r0"]["links"]["r3"]["ipv4"]
231 step("Delete the ip address")
232 topo1 = {
233 "r0": {
234 "links": {
235 "r3": {
236 "ipv4": ip_addr,
237 "interface": topo["routers"]["r0"]["links"]["r3"]["interface"],
238 "delete": True,
239 }
240 }
241 }
242 }
243
244 result = create_interfaces_cfg(tgen, topo1)
245 assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
246
247 step("Change the ip on the R0 interface")
248
249 topo_modify_change_ip = deepcopy(topo)
250 intf_ip = topo_modify_change_ip["routers"]["r0"]["links"]["r3"]["ipv4"]
251 topo_modify_change_ip["routers"]["r0"]["links"]["r3"]["ipv4"] = str(
d7d21c3a 252 IPv4Address(frr_unicode(intf_ip.split("/")[0])) + 3
dc5298d7 253 ) + "/{}".format(int(intf_ip.split("/")[1]) + 1)
254
255 build_config_from_json(tgen, topo_modify_change_ip, save_bkup=False)
256 step("Verify that interface is enabled in ospf.")
257 dut = "r0"
258 input_dict = {
259 "r0": {
260 "links": {
261 "r3": {
262 "ospf": {
263 "ipAddress": topo_modify_change_ip["routers"]["r0"]["links"][
264 "r3"
265 ]["ipv4"].split("/")[0],
266 "ipAddressPrefixlen": int(
267 topo_modify_change_ip["routers"]["r0"]["links"]["r3"][
268 "ipv4"
269 ].split("/")[1]
270 ),
271 }
272 }
273 }
274 }
275 }
276 result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
277 assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
278
279 topo1 = {
280 "r0": {
281 "links": {
282 "r3": {
283 "ipv4": topo_modify_change_ip["routers"]["r0"]["links"]["r3"][
284 "ipv4"
285 ],
286 "interface": topo_modify_change_ip["routers"]["r0"]["links"]["r3"][
287 "interface"
288 ],
289 "delete": True,
290 }
291 }
292 }
293 }
294
295 result = create_interfaces_cfg(tgen, topo1)
296 assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
297
298 build_config_from_json(tgen, topo, save_bkup=False)
299
300 step("Change the area id on the interface")
301 input_dict = {
302 "r0": {
303 "links": {
304 "r3": {
305 "interface": topo["routers"]["r0"]["links"]["r3"]["interface"],
306 "ospf": {"area": "0.0.0.0"},
307 "delete": True,
308 }
309 }
310 }
311 }
312
313 result = create_interfaces_cfg(tgen, input_dict)
314 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
315
316 input_dict = {
317 "r0": {
318 "links": {
319 "r3": {
320 "interface": topo["routers"]["r0"]["links"]["r3"]["interface"],
321 "ospf": {"area": "0.0.0.1"},
322 }
323 }
324 }
325 }
326
327 result = create_interfaces_cfg(tgen, input_dict)
328 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
329 step("Verify that interface is enabled in ospf.")
330 dut = "r0"
331 input_dict = {
332 "r0": {"links": {"r3": {"ospf": {"area": "0.0.0.1", "ospfEnabled": True}}}}
333 }
334 result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
335 assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
336
337 input_dict = {
338 "r0": {
339 "links": {
340 "r3": {
341 "interface": topo["routers"]["r0"]["links"]["r3"]["interface"],
342 "ospf": {"area": "0.0.0.1"},
343 "delete": True,
344 }
345 }
346 }
347 }
348
349 result = create_interfaces_cfg(tgen, input_dict)
350 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
351
352 input_dict = {
353 "r0": {
354 "links": {
355 "r3": {
356 "interface": topo["routers"]["r0"]["links"]["r3"]["interface"],
357 "ospf": {"area": "0.0.0.0"},
358 }
359 }
360 }
361 }
362
363 result = create_interfaces_cfg(tgen, input_dict)
364 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
365
366 step("Verify if interface is enabled with network type P2MP")
367 input_dict = {
368 "r0": {
369 "links": {
370 "r3": {
371 "interface": topo["routers"]["r0"]["links"]["r3"]["interface"],
5980ad0a 372 "ospf": {"area": "0.0.0.0", "networkType": "POINTOMULTIPOINT"},
dc5298d7 373 }
374 }
375 }
376 }
377 result = create_interfaces_cfg(tgen, input_dict)
378 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
379
380 write_test_footer(tc_name)
381
382
675ba67d
LB
383@retry(retry_timeout=30)
384def verify_ospf_json(tgen, dut, input_dict, cmd="show ip ospf database json"):
385 del tgen
386 show_ospf_json = run_frr_cmd(dut, cmd, isjson=True)
387 if not bool(show_ospf_json):
388 return "ospf is not running"
389 result = json_cmp(show_ospf_json, input_dict)
390 return str(result) if result else None
391
392
393@pytest.mark.parametrize("tgen", [2], indirect=True)
394def test_ospf_nbrs(tgen):
395 db_full = {
396 "areas": {
397 "0.0.0.0": {
398 "routerLinkStates": [
399 {
400 "lsId": "100.1.1.0",
401 "advertisedRouter": "100.1.1.0",
402 "numOfRouterLinks": 6,
403 },
404 {
405 "lsId": "100.1.1.1",
406 "advertisedRouter": "100.1.1.1",
407 "numOfRouterLinks": 6,
408 },
409 {
410 "lsId": "100.1.1.2",
411 "advertisedRouter": "100.1.1.2",
412 "numOfRouterLinks": 6,
413 },
414 {
415 "lsId": "100.1.1.3",
416 "advertisedRouter": "100.1.1.3",
417 "numOfRouterLinks": 7,
418 },
419 ]
420 }
421 }
422 }
423 input = [
424 [
425 "r0",
426 "show ip ospf n json",
427 {
428 "neighbors": {
429 "100.1.1.1": [
430 {
431 "state": "Full/DROther",
432 }
433 ],
434 "100.1.1.2": [
435 {
436 "state": "Full/DROther",
437 }
438 ],
439 "100.1.1.3": [
440 {
441 "state": "Full/DROther",
442 }
443 ],
444 }
445 },
446 ],
447 [
448 "r1",
449 "show ip ospf n json",
450 {
451 "neighbors": {
452 "100.1.1.0": [
453 {
454 "state": "Full/DROther",
455 }
456 ],
457 "100.1.1.2": [
458 {
459 "state": "Full/DROther",
460 }
461 ],
462 "100.1.1.3": [
463 {
464 "state": "Full/DROther",
465 }
466 ],
467 }
468 },
469 ],
470 [
471 "r2",
472 "show ip ospf n json",
473 {
474 "neighbors": {
475 "100.1.1.0": [
476 {
477 "state": "Full/DROther",
478 }
479 ],
480 "100.1.1.1": [
481 {
482 "state": "Full/DROther",
483 }
484 ],
485 "100.1.1.3": [
486 {
487 "state": "Full/DROther",
488 }
489 ],
490 }
491 },
492 ],
493 [
494 "r3",
495 "show ip ospf n json",
496 {
497 "neighbors": {
498 "100.1.1.0": [
499 {
500 "state": "Full/DROther",
501 }
502 ],
503 "100.1.1.1": [
504 {
505 "state": "Full/DROther",
506 }
507 ],
508 "100.1.1.2": [
509 {
510 "state": "Full/DROther",
511 }
512 ],
513 }
514 },
515 ],
516 ["r0", "show ip ospf database json", db_full],
517 ["r1", "show ip ospf database json", db_full],
518 ["r2", "show ip ospf database json", db_full],
519 ["r3", "show ip ospf database json", db_full],
520 ["r0", "show ip ospf database json", db_full],
521 ["r0", "show ip ospf database router json", {}],
522 ["r0", "show ip ospf interface traffic json", {}],
523 ["r1", "show ip ospf interface traffic json", {}],
524 ["r2", "show ip ospf interface traffic json", {}],
525 ["r3", "show ip ospf interface traffic json", {}],
526 ]
527 for cmd_set in input:
528 step("test_ospf: %s - %s" % (cmd_set[0], cmd_set[1]))
529 assert (
530 verify_ospf_json(tgen, tgen.gears[cmd_set[0]], cmd_set[2], cmd_set[1])
531 is None
532 )
533
534
dc5298d7 535if __name__ == "__main__":
536 args = ["-s"] + sys.argv[1:]
537 sys.exit(pytest.main(args))