]> git.proxmox.com Git - mirror_frr.git/blame - tests/topotests/lib/ospf.py
Merge pull request #9464 from idryzhov/ospfv3-debug-doc
[mirror_frr.git] / tests / topotests / lib / ospf.py
CommitLineData
4256a209 1#
2# Copyright (c) 2020 by VMware, Inc. ("VMware")
3# Used Copyright (c) 2018 by Network Device Education Foundation, Inc.
4# ("NetDEF") in this file.
5#
6# Permission to use, copy, modify, and/or distribute this software
7# for any purpose with or without fee is hereby granted, provided
8# that the above copyright notice and this permission notice appear
9# in all copies.
10#
11# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
12# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
14# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
15# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
16# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
17# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
18# OF THIS SOFTWARE.
19#
20
4256a209 21import traceback
2448d002 22import ipaddr
23import ipaddress
24import sys
25
26from copy import deepcopy
4256a209 27from time import sleep
28from lib.topolog import logger
61196140 29from lib.topotest import frr_unicode
2448d002 30from ipaddress import IPv6Address
db56171c 31
4256a209 32# Import common_config to use commomnly used APIs
701a0192 33from lib.common_config import (
34 create_common_configuration,
35 InvalidCLIError,
36 retry,
37 generate_ips,
38 check_address_types,
39 validate_ip_address,
40 run_frr_cmd,
41)
4256a209 42
43LOGDIR = "/tmp/topotests/"
44TMPDIR = None
45
46################################
47# Configure procs
48################################
49
701a0192 50
51def create_router_ospf(tgen, topo, input_dict=None, build=False, load_config=True):
4256a209 52 """
53 API to configure ospf on router.
54
55 Parameters
56 ----------
57 * `tgen` : Topogen object
58 * `topo` : json file data
59 * `input_dict` : Input dict data, required when configuring from testcase
60 * `build` : Only for initial setup phase this is set as True.
61 * `load_config` : Loading the config to router this is set as True.
62
63 Usage
64 -----
65 input_dict = {
66 "r1": {
67 "ospf": {
68 "router_id": "22.22.22.22",
9458be1a 69 "area": [{ "id": "0.0.0.0", "type": "nssa"}]
4256a209 70 }
71 }
72
73 result = create_router_ospf(tgen, topo, input_dict)
74
75 Returns
76 -------
77 True or False
78 """
79 logger.debug("Entering lib API: create_router_ospf()")
80 result = False
81
82 if not input_dict:
83 input_dict = deepcopy(topo)
84 else:
85 topo = topo["routers"]
86 input_dict = deepcopy(input_dict)
87
88 for router in input_dict.keys():
89 if "ospf" not in input_dict[router]:
90 logger.debug("Router %s: 'ospf' not present in input_dict", router)
91 continue
92
db56171c 93 result = __create_ospf_global(tgen, input_dict, router, build, load_config)
4256a209 94 if result is True:
95 ospf_data = input_dict[router]["ospf"]
96
2448d002 97 for router in input_dict.keys():
98 if "ospf6" not in input_dict[router]:
99 logger.debug("Router %s: 'ospf6' not present in input_dict", router)
100 continue
101
102 result = __create_ospf_global(
db56171c 103 tgen, input_dict, router, build, load_config, ospf="ospf6"
104 )
2448d002 105 if result is True:
106 ospf_data = input_dict[router]["ospf6"]
107
4256a209 108 logger.debug("Exiting lib API: create_router_ospf()")
109 return result
110
111
5980ad0a
DS
112def __create_ospf_global(
113 tgen, input_dict, router, build=False, load_config=True, ospf="ospf"
114):
4256a209 115 """
116 Helper API to create ospf global configuration.
117
118 Parameters
119 ----------
120 * `tgen` : Topogen object
121 * `input_dict` : Input dict data, required when configuring from testcase
122 * `router` : router to be configured.
123 * `build` : Only for initial setup phase this is set as True.
124 * `load_config` : Loading the config to router this is set as True.
889da676 125 * `ospf` : either 'ospf' or 'ospf6'
4256a209 126
2718dd02 127 Usage
128 -----
129 input_dict = {
130 "routers": {
131 "r1": {
132 "links": {
133 "r3": {
134 "ipv6": "2013:13::1/64",
135 "ospf6": {
136 "hello_interval": 1,
137 "dead_interval": 4,
138 "network": "point-to-point"
139 }
140 }
141 },
142 "ospf6": {
143 "router_id": "1.1.1.1",
144 "neighbors": {
145 "r3": {
146 "area": "1.1.1.1"
147 }
148 }
149 }
150 }
151 }
152
4256a209 153 Returns
154 -------
155 True or False
156 """
157
158 result = False
159 logger.debug("Entering lib API: __create_ospf_global()")
160 try:
161
889da676 162 ospf_data = input_dict[router][ospf]
4256a209 163 del_ospf_action = ospf_data.setdefault("delete", False)
164 if del_ospf_action:
889da676 165 config_data = ["no router {}".format(ospf)]
701a0192 166 result = create_common_configuration(
889da676 167 tgen, router, config_data, ospf, build, load_config
701a0192 168 )
4256a209 169 return result
170
171 config_data = []
889da676 172 cmd = "router {}".format(ospf)
4256a209 173
174 config_data.append(cmd)
175
176 # router id
177 router_id = ospf_data.setdefault("router_id", None)
178 del_router_id = ospf_data.setdefault("del_router_id", False)
179 if del_router_id:
889da676 180 config_data.append("no {} router-id".format(ospf))
4256a209 181 if router_id:
889da676 182 config_data.append("{} router-id {}".format(ospf, router_id))
4256a209 183
2448d002 184 # log-adjacency-changes
185 log_adj_changes = ospf_data.setdefault("log_adj_changes", None)
186 del_log_adj_changes = ospf_data.setdefault("del_log_adj_changes", False)
187 if del_log_adj_changes:
188 config_data.append("no log-adjacency-changes detail")
189 if log_adj_changes:
db56171c 190 config_data.append("log-adjacency-changes {}".format(log_adj_changes))
2448d002 191
192 # aggregation timer
193 aggr_timer = ospf_data.setdefault("aggr_timer", None)
194 del_aggr_timer = ospf_data.setdefault("del_aggr_timer", False)
195 if del_aggr_timer:
196 config_data.append("no aggregation timer")
197 if aggr_timer:
db56171c 198 config_data.append("aggregation timer {}".format(aggr_timer))
2448d002 199
200 # maximum path information
201 ecmp_data = ospf_data.setdefault("maximum-paths", {})
202 if ecmp_data:
203 cmd = "maximum-paths {}".format(ecmp_data)
204 del_action = ospf_data.setdefault("del_max_path", False)
205 if del_action:
206 cmd = "no maximum-paths"
207 config_data.append(cmd)
208
4256a209 209 # redistribute command
210 redistribute_data = ospf_data.setdefault("redistribute", {})
211 if redistribute_data:
212 for redistribute in redistribute_data:
213 if "redist_type" not in redistribute:
701a0192 214 logger.debug(
215 "Router %s: 'redist_type' not present in " "input_dict", router
216 )
4256a209 217 else:
701a0192 218 cmd = "redistribute {}".format(redistribute["redist_type"])
4256a209 219 for red_type in redistribute_data:
220 if "route_map" in red_type:
701a0192 221 cmd = cmd + " route-map {}".format(red_type["route_map"])
4256a209 222 del_action = redistribute.setdefault("delete", False)
223 if del_action:
224 cmd = "no {}".format(cmd)
225 config_data.append(cmd)
889da676 226
701a0192 227 # area information
4256a209 228 area_data = ospf_data.setdefault("area", {})
229 if area_data:
230 for area in area_data:
231 if "id" not in area:
701a0192 232 logger.debug(
233 "Router %s: 'area id' not present in " "input_dict", router
234 )
4256a209 235 else:
236 cmd = "area {}".format(area["id"])
237
238 if "type" in area:
239 cmd = cmd + " {}".format(area["type"])
240
241 del_action = area.setdefault("delete", False)
242 if del_action:
243 cmd = "no {}".format(cmd)
244 config_data.append(cmd)
4256a209 245
db56171c 246 # def route information
2448d002 247 def_rte_data = ospf_data.setdefault("default-information", {})
248 if def_rte_data:
249 if "originate" not in def_rte_data:
db56171c 250 logger.debug(
251 "Router %s: 'originate key' not present in " "input_dict", router
252 )
2448d002 253 else:
254 cmd = "default-information originate"
255
256 if "always" in def_rte_data:
257 cmd = cmd + " always"
258
259 if "metric" in def_rte_data:
260 cmd = cmd + " metric {}".format(def_rte_data["metric"])
261
262 if "metric-type" in def_rte_data:
db56171c 263 cmd = cmd + " metric-type {}".format(def_rte_data["metric-type"])
2448d002 264
265 if "route-map" in def_rte_data:
db56171c 266 cmd = cmd + " route-map {}".format(def_rte_data["route-map"])
2448d002 267
268 del_action = def_rte_data.setdefault("delete", False)
269 if del_action:
270 cmd = "no {}".format(cmd)
271 config_data.append(cmd)
272
2718dd02 273 # area interface information for ospf6d only
274 if ospf == "ospf6":
275 area_iface = ospf_data.setdefault("neighbors", {})
276 if area_iface:
277 for neighbor in area_iface:
278 if "area" in area_iface[neighbor]:
279 iface = input_dict[router]["links"][neighbor]["interface"]
280 cmd = "interface {} area {}".format(
281 iface, area_iface[neighbor]["area"]
282 )
283 if area_iface[neighbor].setdefault("delete", False):
284 cmd = "no {}".format(cmd)
285 config_data.append(cmd)
286
2448d002 287 try:
db56171c 288 if "area" in input_dict[router]["links"][neighbor]["ospf6"]:
2448d002 289 iface = input_dict[router]["links"][neighbor]["interface"]
290 cmd = "interface {} area {}".format(
db56171c 291 iface,
292 input_dict[router]["links"][neighbor]["ospf6"]["area"],
293 )
294 if input_dict[router]["links"][neighbor].setdefault(
295 "delete", False
296 ):
2448d002 297 cmd = "no {}".format(cmd)
298 config_data.append(cmd)
299 except KeyError:
db56171c 300 pass
2448d002 301
4256a209 302 # summary information
303 summary_data = ospf_data.setdefault("summary-address", {})
304 if summary_data:
305 for summary in summary_data:
306 if "prefix" not in summary:
701a0192 307 logger.debug(
308 "Router %s: 'summary-address' not present in " "input_dict",
309 router,
310 )
4256a209 311 else:
701a0192 312 cmd = "summary {}/{}".format(summary["prefix"], summary["mask"])
4256a209 313
314 _tag = summary.setdefault("tag", None)
315 if _tag:
316 cmd = "{} tag {}".format(cmd, _tag)
317
318 _advertise = summary.setdefault("advertise", True)
319 if not _advertise:
320 cmd = "{} no-advertise".format(cmd)
321
322 del_action = summary.setdefault("delete", False)
323 if del_action:
324 cmd = "no {}".format(cmd)
325 config_data.append(cmd)
889da676 326
701a0192 327 result = create_common_configuration(
889da676 328 tgen, router, config_data, ospf, build, load_config
701a0192 329 )
4256a209 330
331 except InvalidCLIError:
332 # Traceback
333 errormsg = traceback.format_exc()
334 logger.error(errormsg)
335 return errormsg
336
337 logger.debug("Exiting lib API: create_ospf_global()")
338 return result
339
340
701a0192 341def create_router_ospf6(tgen, topo, input_dict=None, build=False, load_config=True):
4256a209 342 """
343 API to configure ospf on router
344
345 Parameters
346 ----------
347 * `tgen` : Topogen object
348 * `topo` : json file data
349 * `input_dict` : Input dict data, required when configuring from testcase
350 * `build` : Only for initial setup phase this is set as True.
351
352 Usage
353 -----
354 input_dict = {
355 "r1": {
356 "ospf6": {
357 "router_id": "22.22.22.22",
358 }
359 }
360
361 Returns
362 -------
363 True or False
364 """
12011c40 365 logger.debug("Entering lib API: create_router_ospf6()")
4256a209 366 result = False
367
368 if not input_dict:
369 input_dict = deepcopy(topo)
370 else:
371 topo = topo["routers"]
372 input_dict = deepcopy(input_dict)
373 for router in input_dict.keys():
12011c40 374 if "ospf6" not in input_dict[router]:
375 logger.debug("Router %s: 'ospf6' not present in input_dict", router)
4256a209 376 continue
377
12011c40 378 result = __create_ospf_global(
379 tgen, input_dict, router, build, load_config, "ospf6"
380 )
4256a209 381
12011c40 382 logger.debug("Exiting lib API: create_router_ospf6()")
4256a209 383 return result
384
385
701a0192 386def config_ospf_interface(tgen, topo, input_dict=None, build=False, load_config=True):
4256a209 387 """
388 API to configure ospf on router.
389
390 Parameters
391 ----------
392 * `tgen` : Topogen object
393 * `topo` : json file data
394 * `input_dict` : Input dict data, required when configuring from testcase
395 * `build` : Only for initial setup phase this is set as True.
396 * `load_config` : Loading the config to router this is set as True.
397
398 Usage
399 -----
400 r1_ospf_auth = {
401 "r1": {
402 "links": {
403 "r2": {
404 "ospf": {
9458be1a 405 "authentication": "message-digest",
4256a209 406 "authentication-key": "ospf",
407 "message-digest-key": "10"
408 }
409 }
410 }
411 }
412 }
413 result = config_ospf_interface(tgen, topo, r1_ospf_auth)
414
415 Returns
416 -------
417 True or False
418 """
419 logger.debug("Enter lib config_ospf_interface")
db56171c 420 result = False
4256a209 421 if not input_dict:
422 input_dict = deepcopy(topo)
423 else:
424 input_dict = deepcopy(input_dict)
425 for router in input_dict.keys():
426 config_data = []
701a0192 427 for lnk in input_dict[router]["links"].keys():
428 if "ospf" not in input_dict[router]["links"][lnk]:
429 logger.debug(
0b25370e 430 "Router %s: ospf config is not present in" "input_dict", router
701a0192 431 )
4256a209 432 continue
701a0192 433 ospf_data = input_dict[router]["links"][lnk]["ospf"]
4256a209 434 data_ospf_area = ospf_data.setdefault("area", None)
435 data_ospf_auth = ospf_data.setdefault("authentication", None)
436 data_ospf_dr_priority = ospf_data.setdefault("priority", None)
437 data_ospf_cost = ospf_data.setdefault("cost", None)
8694dd78 438 data_ospf_mtu = ospf_data.setdefault("mtu_ignore", None)
4256a209 439
440 try:
701a0192 441 intf = topo["routers"][router]["links"][lnk]["interface"]
4256a209 442 except KeyError:
701a0192 443 intf = topo["switches"][router]["links"][lnk]["interface"]
4256a209 444
445 # interface
446 cmd = "interface {}".format(intf)
447
448 config_data.append(cmd)
449 # interface area config
450 if data_ospf_area:
451 cmd = "ip ospf area {}".format(data_ospf_area)
452 config_data.append(cmd)
9458be1a 453
4256a209 454 # interface ospf auth
455 if data_ospf_auth:
701a0192 456 if data_ospf_auth == "null":
4256a209 457 cmd = "ip ospf authentication null"
701a0192 458 elif data_ospf_auth == "message-digest":
4256a209 459 cmd = "ip ospf authentication message-digest"
460 else:
461 cmd = "ip ospf authentication"
462
701a0192 463 if "del_action" in ospf_data:
4256a209 464 cmd = "no {}".format(cmd)
465 config_data.append(cmd)
466
467 if "message-digest-key" in ospf_data:
468 cmd = "ip ospf message-digest-key {} md5 {}".format(
701a0192 469 ospf_data["message-digest-key"], ospf_data["authentication-key"]
470 )
471 if "del_action" in ospf_data:
4256a209 472 cmd = "no {}".format(cmd)
473 config_data.append(cmd)
474
701a0192 475 if (
476 "authentication-key" in ospf_data
477 and "message-digest-key" not in ospf_data
478 ):
479 cmd = "ip ospf authentication-key {}".format(
480 ospf_data["authentication-key"]
481 )
482 if "del_action" in ospf_data:
4256a209 483 cmd = "no {}".format(cmd)
484 config_data.append(cmd)
485
486 # interface ospf dr priority
8694dd78 487 if data_ospf_dr_priority:
701a0192 488 cmd = "ip ospf priority {}".format(ospf_data["priority"])
489 if "del_action" in ospf_data:
4256a209 490 cmd = "no {}".format(cmd)
491 config_data.append(cmd)
492
493 # interface ospf cost
8694dd78 494 if data_ospf_cost:
701a0192 495 cmd = "ip ospf cost {}".format(ospf_data["cost"])
496 if "del_action" in ospf_data:
4256a209 497 cmd = "no {}".format(cmd)
498 config_data.append(cmd)
499
8694dd78 500 # interface ospf mtu
501 if data_ospf_mtu:
502 cmd = "ip ospf mtu-ignore"
db56171c 503 if "del_action" in ospf_data:
8694dd78 504 cmd = "no {}".format(cmd)
505 config_data.append(cmd)
506
4256a209 507 if build:
508 return config_data
509 else:
701a0192 510 result = create_common_configuration(
511 tgen, router, config_data, "interface_config", build=build
512 )
2448d002 513 logger.debug("Exiting lib API: config_ospf_interface()")
4256a209 514 return result
515
701a0192 516
2448d002 517def clear_ospf(tgen, router, ospf=None):
4256a209 518 """
519 This API is to clear ospf neighborship by running
520 clear ip ospf interface * command,
521
522 Parameters
523 ----------
524 * `tgen`: topogen object
525 * `router`: device under test
526
527 Usage
528 -----
529 clear_ospf(tgen, "r1")
530 """
531
532 logger.debug("Entering lib API: clear_ospf()")
533 if router not in tgen.routers():
534 return False
535
536 rnode = tgen.routers()[router]
4256a209 537 # Clearing OSPF
2448d002 538 if ospf:
539 version = "ipv6"
540 else:
541 version = "ip"
4256a209 542
2448d002 543 cmd = "clear {} ospf interface".format(version)
db56171c 544 logger.info("Clearing ospf process on router %s.. using command '%s'", router, cmd)
2448d002 545 run_frr_cmd(rnode, cmd)
4256a209 546
547 logger.debug("Exiting lib API: clear_ospf()")
548
549
88b7d3e7 550def redistribute_ospf(tgen, topo, dut, route_type, **kwargs):
551 """
552 Redstribution of routes inside ospf.
553
554 Parameters
555 ----------
556 * `tgen`: Topogen object
557 * `topo` : json file data
558 * `dut`: device under test
559 * `route_type`: "static" or "connected" or ....
560 * `kwargs`: pass extra information (see below)
561
562 Usage
563 -----
564 redistribute_ospf(tgen, topo, "r0", "static", delete=True)
565 redistribute_ospf(tgen, topo, "r0", "static", route_map="rmap_ipv4")
566 """
567
568 ospf_red = {dut: {"ospf": {"redistribute": [{"redist_type": route_type}]}}}
569 for k, v in kwargs.items():
570 ospf_red[dut]["ospf"]["redistribute"][0][k] = v
571
572 result = create_router_ospf(tgen, topo, ospf_red)
573 assert result is True, "Testcase : Failed \n Error: {}".format(result)
574
575
4256a209 576################################
577# Verification procs
578################################
ed776e38 579@retry(retry_timeout=80)
3c41ebf8 580def verify_ospf_neighbor(tgen, topo, dut=None, input_dict=None, lan=False, expected=True):
4256a209 581 """
582 This API is to verify ospf neighborship by running
583 show ip ospf neighbour command,
584
585 Parameters
586 ----------
587 * `tgen` : Topogen object
588 * `topo` : json file data
589 * `dut`: device under test
590 * `input_dict` : Input dict data, required when configuring from testcase
591 * `lan` : verify neighbors in lan topology
3c41ebf8 592 * `expected` : expected results from API, by-default True
4256a209 593
594 Usage
595 -----
596 1. To check FULL neighbors.
597 verify_ospf_neighbor(tgen, topo, dut=dut)
598
599 2. To check neighbors with their roles.
600 input_dict = {
601 "r0": {
602 "ospf": {
603 "neighbors": {
604 "r1": {
605 "state": "Full",
606 "role": "DR"
607 },
608 "r2": {
609 "state": "Full",
610 "role": "DROther"
611 },
612 "r3": {
613 "state": "Full",
614 "role": "DROther"
615 }
616 }
617 }
618 }
619 }
620 result = verify_ospf_neighbor(tgen, topo, dut, input_dict, lan=True)
621
622 Returns
623 -------
624 True or False (Error Message)
625 """
626 logger.debug("Entering lib API: verify_ospf_neighbor()")
627 result = False
628 if input_dict:
11761ab0 629 for router, rnode in tgen.routers().items():
701a0192 630 if "ospf" not in topo["routers"][router]:
4256a209 631 continue
632
633 if dut is not None and dut != router:
634 continue
635
636 logger.info("Verifying OSPF neighborship on router %s:", router)
701a0192 637 show_ospf_json = run_frr_cmd(
9458be1a 638 rnode, "show ip ospf neighbor all json", isjson=True
701a0192 639 )
4256a209 640
641 # Verifying output dictionary show_ospf_json is empty or not
642 if not bool(show_ospf_json):
643 errormsg = "OSPF is not running"
644 return errormsg
645
646 ospf_data_list = input_dict[router]["ospf"]
701a0192 647 ospf_nbr_list = ospf_data_list["neighbors"]
4256a209 648
649 for ospf_nbr, nbr_data in ospf_nbr_list.items():
701a0192 650 data_ip = topo["routers"][ospf_nbr]["links"]
651 data_rid = topo["routers"][ospf_nbr]["ospf"]["router_id"]
4256a209 652 if ospf_nbr in data_ip:
653 nbr_details = nbr_data[ospf_nbr]
654 elif lan:
701a0192 655 for switch in topo["switches"]:
656 if "ospf" in topo["switches"][switch]["links"][router]:
657 neighbor_ip = data_ip[switch]["ipv4"].split("/")[0]
4256a209 658 else:
659 continue
660 else:
701a0192 661 neighbor_ip = data_ip[router]["ipv4"].split("/")[0]
4256a209 662
663 nh_state = None
664 neighbor_ip = neighbor_ip.lower()
665 nbr_rid = data_rid
666 try:
701a0192 667 nh_state = show_ospf_json[nbr_rid][0]["state"].split("/")[0]
668 intf_state = show_ospf_json[nbr_rid][0]["state"].split("/")[1]
4256a209 669 except KeyError:
701a0192 670 errormsg = "[DUT: {}] OSPF peer {} missing".format(router, nbr_rid)
4256a209 671 return errormsg
672
701a0192 673 nbr_state = nbr_data.setdefault("state", None)
674 nbr_role = nbr_data.setdefault("role", None)
4256a209 675
676 if nbr_state:
677 if nbr_state == nh_state:
701a0192 678 logger.info(
679 "[DUT: {}] OSPF Nbr is {}:{} State {}".format(
680 router, ospf_nbr, nbr_rid, nh_state
681 )
682 )
4256a209 683 result = True
684 else:
701a0192 685 errormsg = (
686 "[DUT: {}] OSPF is not Converged, neighbor"
687 " state is {}".format(router, nh_state)
688 )
4256a209 689 return errormsg
690 if nbr_role:
691 if nbr_role == intf_state:
701a0192 692 logger.info(
693 "[DUT: {}] OSPF Nbr is {}: {} Role {}".format(
694 router, ospf_nbr, nbr_rid, nbr_role
695 )
696 )
4256a209 697 else:
701a0192 698 errormsg = (
699 "[DUT: {}] OSPF is not Converged with rid"
700 "{}, role is {}".format(router, nbr_rid, intf_state)
701 )
4256a209 702 return errormsg
703 continue
704 else:
11761ab0 705 for router, rnode in tgen.routers().items():
701a0192 706 if "ospf" not in topo["routers"][router]:
4256a209 707 continue
708
709 if dut is not None and dut != router:
710 continue
711
712 logger.info("Verifying OSPF neighborship on router %s:", router)
701a0192 713 show_ospf_json = run_frr_cmd(
714 rnode, "show ip ospf neighbor all json", isjson=True
715 )
4256a209 716 # Verifying output dictionary show_ospf_json is empty or not
717 if not bool(show_ospf_json):
718 errormsg = "OSPF is not running"
719 return errormsg
720
721 ospf_data_list = topo["routers"][router]["ospf"]
701a0192 722 ospf_neighbors = ospf_data_list["neighbors"]
4256a209 723 total_peer = 0
724 total_peer = len(ospf_neighbors.keys())
725 no_of_ospf_nbr = 0
701a0192 726 ospf_nbr_list = ospf_data_list["neighbors"]
4256a209 727 no_of_peer = 0
728 for ospf_nbr, nbr_data in ospf_nbr_list.items():
729 if nbr_data:
701a0192 730 data_ip = topo["routers"][nbr_data["nbr"]]["links"]
731 data_rid = topo["routers"][nbr_data["nbr"]]["ospf"]["router_id"]
4256a209 732 else:
701a0192 733 data_ip = topo["routers"][ospf_nbr]["links"]
734 data_rid = topo["routers"][ospf_nbr]["ospf"]["router_id"]
4256a209 735 if ospf_nbr in data_ip:
736 nbr_details = nbr_data[ospf_nbr]
737 elif lan:
701a0192 738 for switch in topo["switches"]:
739 if "ospf" in topo["switches"][switch]["links"][router]:
740 neighbor_ip = data_ip[switch]["ipv4"].split("/")[0]
4256a209 741 else:
742 continue
743 else:
701a0192 744 neighbor_ip = data_ip[router]["ipv4"].split("/")[0]
4256a209 745
746 nh_state = None
747 neighbor_ip = neighbor_ip.lower()
748 nbr_rid = data_rid
749 try:
701a0192 750 nh_state = show_ospf_json[nbr_rid][0]["state"].split("/")[0]
4256a209 751 except KeyError:
701a0192 752 errormsg = "[DUT: {}] OSPF peer {} missing,from " "{} ".format(
753 router, nbr_rid, ospf_nbr
754 )
4256a209 755 return errormsg
756
701a0192 757 if nh_state == "Full":
4256a209 758 no_of_peer += 1
759
760 if no_of_peer == total_peer:
761 logger.info("[DUT: {}] OSPF is Converged".format(router))
762 result = True
763 else:
701a0192 764 errormsg = "[DUT: {}] OSPF is not Converged".format(router)
4256a209 765 return errormsg
766
767 logger.debug("Exiting API: verify_ospf_neighbor()")
768 return result
769
701a0192 770
1feb577c 771################################
772# Verification procs
773################################
db56171c 774@retry(retry_timeout=50)
2448d002 775def verify_ospf6_neighbor(tgen, topo, dut=None, input_dict=None, lan=False):
1feb577c 776 """
777 This API is to verify ospf neighborship by running
2448d002 778 show ipv6 ospf neighbour command,
1feb577c 779
780 Parameters
781 ----------
782 * `tgen` : Topogen object
783 * `topo` : json file data
2448d002 784 * `dut`: device under test
785 * `input_dict` : Input dict data, required when configuring from testcase
786 * `lan` : verify neighbors in lan topology
1feb577c 787
788 Usage
789 -----
2448d002 790 1. To check FULL neighbors.
791 verify_ospf_neighbor(tgen, topo, dut=dut)
1feb577c 792
2448d002 793 2. To check neighbors with their roles.
794 input_dict = {
795 "r0": {
796 "ospf6": {
797 "neighbors": {
798 "r1": {
799 "state": "Full",
800 "role": "DR"
801 },
802 "r2": {
803 "state": "Full",
804 "role": "DROther"
805 },
806 "r3": {
807 "state": "Full",
808 "role": "DROther"
809 }
810 }
811 }
812 }
813 }
814 result = verify_ospf6_neighbor(tgen, topo, dut, input_dict, lan=True)
1feb577c 815
816 Returns
817 -------
818 True or False (Error Message)
819 """
2448d002 820 logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
1feb577c 821 result = False
1feb577c 822
2448d002 823 if input_dict:
824 for router, rnode in tgen.routers().items():
db56171c 825 if "ospf6" not in topo["routers"][router]:
2448d002 826 continue
1feb577c 827
2448d002 828 if dut is not None and dut != router:
829 continue
830
831 logger.info("Verifying OSPF neighborship on router %s:", router)
db56171c 832 show_ospf_json = run_frr_cmd(
833 rnode, "show ipv6 ospf neighbor json", isjson=True
834 )
2448d002 835 # Verifying output dictionary show_ospf_json is empty or not
836 if not bool(show_ospf_json):
837 errormsg = "OSPF6 is not running"
838 return errormsg
839
840 ospf_data_list = input_dict[router]["ospf6"]
db56171c 841 ospf_nbr_list = ospf_data_list["neighbors"]
2448d002 842
843 for ospf_nbr, nbr_data in ospf_nbr_list.items():
db56171c 844
845 try:
846 data_ip = data_rid = topo["routers"][ospf_nbr]["ospf6"]["router_id"]
847 except KeyError:
848 data_ip = data_rid = topo["routers"][nbr_data["nbr"]]["ospf6"][
849 "router_id"
850 ]
851
2448d002 852 if ospf_nbr in data_ip:
853 nbr_details = nbr_data[ospf_nbr]
854 elif lan:
db56171c 855 for switch in topo["switches"]:
856 if "ospf6" in topo["switches"][switch]["links"][router]:
2448d002 857 neighbor_ip = data_ip
858 else:
859 continue
860 else:
db56171c 861 neighbor_ip = data_ip[router]["ipv6"].split("/")[0]
2448d002 862
863 nh_state = None
864 neighbor_ip = neighbor_ip.lower()
865 nbr_rid = data_rid
db56171c 866 get_index_val = dict(
867 (d["neighborId"], dict(d, index=index))
868 for (index, d) in enumerate(show_ospf_json["neighbors"])
869 )
2448d002 870 try:
db56171c 871 nh_state = get_index_val.get(neighbor_ip)["state"]
872 intf_state = get_index_val.get(neighbor_ip)["ifState"]
2448d002 873 except TypeError:
db56171c 874 errormsg = "[DUT: {}] OSPF peer {} missing,from " "{} ".format(
875 router, nbr_rid, ospf_nbr
876 )
2448d002 877 return errormsg
878
db56171c 879 nbr_state = nbr_data.setdefault("state", None)
880 nbr_role = nbr_data.setdefault("role", None)
2448d002 881
882 if nbr_state:
883 if nbr_state == nh_state:
db56171c 884 logger.info(
885 "[DUT: {}] OSPF6 Nbr is {}:{} State {}".format(
886 router, ospf_nbr, nbr_rid, nh_state
887 )
888 )
2448d002 889 result = True
890 else:
db56171c 891 errormsg = (
892 "[DUT: {}] OSPF6 is not Converged, neighbor"
893 " state is {} , Expected state is {}".format(
894 router, nh_state, nbr_state
895 )
896 )
2448d002 897 return errormsg
898 if nbr_role:
899 if nbr_role == intf_state:
db56171c 900 logger.info(
901 "[DUT: {}] OSPF6 Nbr is {}: {} Role {}".format(
902 router, ospf_nbr, nbr_rid, nbr_role
903 )
904 )
2448d002 905 else:
db56171c 906 errormsg = (
907 "[DUT: {}] OSPF6 is not Converged with rid"
908 "{}, role is {}, Expected role is {}".format(
909 router, nbr_rid, intf_state, nbr_role
910 )
911 )
2448d002 912 return errormsg
913 continue
914 else:
915
916 for router, rnode in tgen.routers().items():
db56171c 917 if "ospf6" not in topo["routers"][router]:
2448d002 918 continue
919
920 if dut is not None and dut != router:
921 continue
922
923 logger.info("Verifying OSPF6 neighborship on router %s:", router)
db56171c 924 show_ospf_json = run_frr_cmd(
925 rnode, "show ipv6 ospf neighbor json", isjson=True
926 )
2448d002 927 # Verifying output dictionary show_ospf_json is empty or not
928 if not bool(show_ospf_json):
929 errormsg = "OSPF6 is not running"
930 return errormsg
931
932 ospf_data_list = topo["routers"][router]["ospf6"]
db56171c 933 ospf_neighbors = ospf_data_list["neighbors"]
2448d002 934 total_peer = 0
935 total_peer = len(ospf_neighbors.keys())
936 no_of_ospf_nbr = 0
db56171c 937 ospf_nbr_list = ospf_data_list["neighbors"]
2448d002 938 no_of_peer = 0
939 for ospf_nbr, nbr_data in ospf_nbr_list.items():
db56171c 940 try:
941 data_ip = data_rid = topo["routers"][ospf_nbr]["ospf6"]["router_id"]
942 except KeyError:
943 data_ip = data_rid = topo["routers"][nbr_data["nbr"]]["ospf6"][
944 "router_id"
945 ]
946
2448d002 947 if ospf_nbr in data_ip:
948 nbr_details = nbr_data[ospf_nbr]
949 elif lan:
db56171c 950 for switch in topo["switches"]:
951 if "ospf6" in topo["switches"][switch]["links"][router]:
2448d002 952 neighbor_ip = data_ip
953 else:
954 continue
955 else:
956 neighbor_ip = data_ip
957
958 nh_state = None
959 neighbor_ip = neighbor_ip.lower()
960 nbr_rid = data_rid
db56171c 961 get_index_val = dict(
962 (d["neighborId"], dict(d, index=index))
963 for (index, d) in enumerate(show_ospf_json["neighbors"])
964 )
2448d002 965 try:
db56171c 966 nh_state = get_index_val.get(neighbor_ip)["state"]
967 intf_state = get_index_val.get(neighbor_ip)["ifState"]
2448d002 968 except TypeError:
db56171c 969 errormsg = "[DUT: {}] OSPF peer {} missing,from " "{} ".format(
970 router, nbr_rid, ospf_nbr
971 )
2448d002 972 return errormsg
1feb577c 973
db56171c 974 if nh_state == "Full":
2448d002 975 no_of_peer += 1
1feb577c 976
2448d002 977 if no_of_peer == total_peer:
978 logger.info("[DUT: {}] OSPF6 is Converged".format(router))
979 result = True
980 else:
db56171c 981 errormsg = "[DUT: {}] OSPF6 is not Converged".format(router)
2448d002 982 return errormsg
1feb577c 983
2448d002 984 logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
1feb577c 985 return result
986
987
ed776e38 988@retry(retry_timeout=40)
701a0192 989def verify_ospf_rib(
3c41ebf8 990 tgen, dut, input_dict, next_hop=None, tag=None, metric=None, fib=None, expected=True
701a0192 991):
4256a209 992 """
993 This API is to verify ospf routes by running
994 show ip ospf route command.
995
996 Parameters
997 ----------
998 * `tgen` : Topogen object
999 * `dut`: device under test
1000 * `input_dict` : Input dict data, required when configuring from testcase
1001 * `next_hop` : next to be verified
1002 * `tag` : tag to be verified
1003 * `metric` : metric to be verified
1004 * `fib` : True if the route is installed in FIB.
3c41ebf8 1005 * `expected` : expected results from API, by-default True
4256a209 1006
1007 Usage
1008 -----
1009 input_dict = {
1010 "r1": {
1011 "static_routes": [
1012 {
1013 "network": ip_net,
1014 "no_of_ip": 1,
1015 "routeType": "N"
1016 }
1017 ]
1018 }
1019 }
1020
1021 result = verify_ospf_rib(tgen, dut, input_dict,next_hop=nh)
1022
1023 Returns
1024 -------
1025 True or False (Error Message)
1026 """
1027
1028 logger.info("Entering lib API: verify_ospf_rib()")
1029 result = False
1030 router_list = tgen.routers()
1031 additional_nexthops_in_required_nhs = []
1032 found_hops = []
1033 for routerInput in input_dict.keys():
11761ab0 1034 for router, rnode in router_list.items():
4256a209 1035 if router != dut:
1036 continue
1037
1038 logger.info("Checking router %s RIB:", router)
1039
1040 # Verifying RIB routes
1041 command = "show ip ospf route"
1042
1043 found_routes = []
1044 missing_routes = []
1045
701a0192 1046 if (
1047 "static_routes" in input_dict[routerInput]
1048 or "prefix" in input_dict[routerInput]
1049 ):
4256a209 1050 if "prefix" in input_dict[routerInput]:
1051 static_routes = input_dict[routerInput]["prefix"]
1052 else:
1053 static_routes = input_dict[routerInput]["static_routes"]
1054
4256a209 1055 for static_route in static_routes:
1056 cmd = "{}".format(command)
1057
1058 cmd = "{} json".format(cmd)
1059
701a0192 1060 ospf_rib_json = run_frr_cmd(rnode, cmd, isjson=True)
4256a209 1061
1062 # Verifying output dictionary ospf_rib_json is not empty
1063 if bool(ospf_rib_json) is False:
701a0192 1064 errormsg = (
1065 "[DUT: {}] No routes found in OSPF route "
4256a209 1066 "table".format(router)
701a0192 1067 )
4256a209 1068 return errormsg
1069
1070 network = static_route["network"]
1071 no_of_ip = static_route.setdefault("no_of_ip", 1)
1072 _tag = static_route.setdefault("tag", None)
1073 _rtype = static_route.setdefault("routeType", None)
1074
4256a209 1075 # Generating IPs for verification
1076 ip_list = generate_ips(network, no_of_ip)
1077 st_found = False
1078 nh_found = False
1079
1080 for st_rt in ip_list:
61196140 1081 st_rt = str(ipaddr.IPNetwork(frr_unicode(st_rt)))
4256a209 1082
1083 _addr_type = validate_ip_address(st_rt)
701a0192 1084 if _addr_type != "ipv4":
4256a209 1085 continue
1086
1087 if st_rt in ospf_rib_json:
1088 st_found = True
1089 found_routes.append(st_rt)
1090
1091 if fib and next_hop:
1092 if type(next_hop) is not list:
1093 next_hop = [next_hop]
1094
1095 for mnh in range(0, len(ospf_rib_json[st_rt])):
701a0192 1096 if (
1097 "fib"
1098 in ospf_rib_json[st_rt][mnh]["nexthops"][0]
1099 ):
1100 found_hops.append(
1101 [
1102 rib_r["ip"]
1103 for rib_r in ospf_rib_json[st_rt][mnh][
1104 "nexthops"
1105 ]
1106 ]
1107 )
4256a209 1108
1109 if found_hops[0]:
701a0192 1110 missing_list_of_nexthops = set(
1111 found_hops[0]
1112 ).difference(next_hop)
1113 additional_nexthops_in_required_nhs = set(
1114 next_hop
1115 ).difference(found_hops[0])
4256a209 1116
1117 if additional_nexthops_in_required_nhs:
1118 logger.info(
1119 "Nexthop "
1120 "%s is not active for route %s in "
1121 "RIB of router %s\n",
1122 additional_nexthops_in_required_nhs,
701a0192 1123 st_rt,
1124 dut,
1125 )
4256a209 1126 errormsg = (
1127 "Nexthop {} is not active"
1128 " for route {} in RIB of router"
1129 " {}\n".format(
701a0192 1130 additional_nexthops_in_required_nhs,
1131 st_rt,
1132 dut,
1133 )
1134 )
4256a209 1135 return errormsg
1136 else:
1137 nh_found = True
1138
1139 elif next_hop and fib is None:
1140 if type(next_hop) is not list:
1141 next_hop = [next_hop]
701a0192 1142 found_hops = [
1143 rib_r["ip"]
1144 for rib_r in ospf_rib_json[st_rt]["nexthops"]
1145 ]
4256a209 1146
1147 if found_hops:
701a0192 1148 missing_list_of_nexthops = set(
1149 found_hops
1150 ).difference(next_hop)
1151 additional_nexthops_in_required_nhs = set(
1152 next_hop
1153 ).difference(found_hops)
4256a209 1154
1155 if additional_nexthops_in_required_nhs:
1156 logger.info(
701a0192 1157 "Missing nexthop %s for route"
1158 " %s in RIB of router %s\n",
4256a209 1159 additional_nexthops_in_required_nhs,
701a0192 1160 st_rt,
1161 dut,
1162 )
1163 errormsg = (
1164 "Nexthop {} is Missing for "
1165 "route {} in RIB of router {}\n".format(
1166 additional_nexthops_in_required_nhs,
1167 st_rt,
1168 dut,
1169 )
1170 )
4256a209 1171 return errormsg
1172 else:
1173 nh_found = True
1174 if _rtype:
701a0192 1175 if "routeType" not in ospf_rib_json[st_rt]:
1176 errormsg = (
1177 "[DUT: {}]: routeType missing"
9458be1a 1178 " for route {} in OSPF RIB \n".format(
1179 dut, st_rt
1180 )
701a0192 1181 )
4256a209 1182 return errormsg
701a0192 1183 elif _rtype != ospf_rib_json[st_rt]["routeType"]:
1184 errormsg = (
1185 "[DUT: {}]: routeType mismatch"
9458be1a 1186 " for route {} in OSPF RIB \n".format(
1187 dut, st_rt
1188 )
701a0192 1189 )
4256a209 1190 return errormsg
1191 else:
701a0192 1192 logger.info(
9458be1a 1193 "[DUT: {}]: Found routeType {}"
1194 " for route {}".format(dut, _rtype, st_rt)
701a0192 1195 )
4256a209 1196 if tag:
701a0192 1197 if "tag" not in ospf_rib_json[st_rt]:
1198 errormsg = (
1199 "[DUT: {}]: tag is not"
1200 " present for"
1201 " route {} in RIB \n".format(dut, st_rt)
1202 )
4256a209 1203 return errormsg
1204
701a0192 1205 if _tag != ospf_rib_json[st_rt]["tag"]:
1206 errormsg = (
1207 "[DUT: {}]: tag value {}"
1208 " is not matched for"
9fa6ec14 1209 " route {} in RIB \n".format(
1210 dut,
1211 _tag,
1212 st_rt,
1213 )
701a0192 1214 )
4256a209 1215 return errormsg
1216
1217 if metric is not None:
701a0192 1218 if "type2cost" not in ospf_rib_json[st_rt]:
1219 errormsg = (
1220 "[DUT: {}]: metric is"
1221 " not present for"
1222 " route {} in RIB \n".format(dut, st_rt)
1223 )
4256a209 1224 return errormsg
1225
701a0192 1226 if metric != ospf_rib_json[st_rt]["type2cost"]:
1227 errormsg = (
1228 "[DUT: {}]: metric value "
1229 "{} is not matched for "
9fa6ec14 1230 "route {} in RIB \n".format(
1231 dut,
1232 metric,
1233 st_rt,
1234 )
701a0192 1235 )
4256a209 1236 return errormsg
1237
1238 else:
1239 missing_routes.append(st_rt)
1240
1241 if nh_found:
701a0192 1242 logger.info(
1243 "[DUT: {}]: Found next_hop {} for all OSPF"
1244 " routes in RIB".format(router, next_hop)
1245 )
4256a209 1246
1247 if len(missing_routes) > 0:
701a0192 1248 errormsg = "[DUT: {}]: Missing route in RIB, " "routes: {}".format(
1249 dut, missing_routes
1250 )
4256a209 1251 return errormsg
1252
1253 if found_routes:
701a0192 1254 logger.info(
1255 "[DUT: %s]: Verified routes in RIB, found" " routes are: %s\n",
1256 dut,
1257 found_routes,
1258 )
4256a209 1259 result = True
1260
1261 logger.info("Exiting lib API: verify_ospf_rib()")
1262 return result
1263
1264
ed776e38 1265@retry(retry_timeout=20)
3c41ebf8 1266def verify_ospf_interface(tgen, topo, dut=None, lan=False, input_dict=None, expected=True):
4256a209 1267 """
1268 This API is to verify ospf routes by running
1269 show ip ospf interface command.
1270
1271 Parameters
1272 ----------
1273 * `tgen` : Topogen object
1274 * `topo` : topology descriptions
1275 * `dut`: device under test
1276 * `lan`: if set to true this interface belongs to LAN.
1277 * `input_dict` : Input dict data, required when configuring from testcase
3c41ebf8 1278 * `expected` : expected results from API, by-default True
4256a209 1279
1280 Usage
1281 -----
1282 input_dict= {
1283 'r0': {
1284 'links':{
1285 's1': {
1286 'ospf':{
1287 'priority':98,
1288 'timerDeadSecs': 4,
1289 'area': '0.0.0.3',
1290 'mcastMemberOspfDesignatedRouters': True,
1291 'mcastMemberOspfAllRouters': True,
1292 'ospfEnabled': True,
1293
1294 }
1295 }
1296 }
1297 }
1298 }
1299 result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
1300
1301 Returns
1302 -------
1303 True or False (Error Message)
1304 """
1305
1306 logger.debug("Entering lib API: verify_ospf_interface()")
1307 result = False
11761ab0 1308 for router, rnode in tgen.routers().items():
701a0192 1309 if "ospf" not in topo["routers"][router]:
4256a209 1310 continue
1311
1312 if dut is not None and dut != router:
1313 continue
1314
1315 logger.info("Verifying OSPF interface on router %s:", router)
701a0192 1316 show_ospf_json = run_frr_cmd(rnode, "show ip ospf interface json", isjson=True)
4256a209 1317
1318 # Verifying output dictionary show_ospf_json is empty or not
1319 if not bool(show_ospf_json):
1320 errormsg = "OSPF is not running"
1321 return errormsg
1322
1323 # To find neighbor ip type
1324 ospf_intf_data = input_dict[router]["links"]
1325 for ospf_intf, intf_data in ospf_intf_data.items():
701a0192 1326 intf = topo["routers"][router]["links"][ospf_intf]["interface"]
1327 if intf in show_ospf_json["interfaces"]:
1328 for intf_attribute in intf_data["ospf"]:
1329 if (
1330 intf_data["ospf"][intf_attribute]
1331 == show_ospf_json["interfaces"][intf][intf_attribute]
1332 ):
1333 logger.info(
1334 "[DUT: %s] OSPF interface %s: %s is %s",
1335 router,
1336 intf,
1337 intf_attribute,
1338 intf_data["ospf"][intf_attribute],
1339 )
4256a209 1340 else:
701a0192 1341 errormsg = "[DUT: {}] OSPF interface {}: {} is {}, \
1342 Expected is {}".format(
1343 router,
1344 intf,
1345 intf_attribute,
1346 intf_data["ospf"][intf_attribute],
1347 show_ospf_json["interfaces"][intf][intf_attribute],
1348 )
4256a209 1349 return errormsg
1350 result = True
1351 logger.debug("Exiting API: verify_ospf_interface()")
1352 return result
1353
1354
ed776e38 1355@retry(retry_timeout=20)
3c41ebf8 1356def verify_ospf_database(tgen, topo, dut, input_dict, expected=True):
4256a209 1357 """
1358 This API is to verify ospf lsa's by running
1359 show ip ospf database command.
1360
1361 Parameters
1362 ----------
1363 * `tgen` : Topogen object
1364 * `dut`: device under test
1365 * `input_dict` : Input dict data, required when configuring from testcase
1366 * `topo` : next to be verified
3c41ebf8 1367 * `expected` : expected results from API, by-default True
4256a209 1368
1369 Usage
1370 -----
1371 input_dict = {
1372 "areas": {
1373 "0.0.0.0": {
1374 "Router Link States": {
1375 "100.1.1.0-100.1.1.0": {
1376 "LSID": "100.1.1.0",
1377 "Advertised router": "100.1.1.0",
1378 "LSA Age": 130,
1379 "Sequence Number": "80000006",
1380 "Checksum": "a703",
1381 "Router links": 3
1382 }
1383 },
1384 "Net Link States": {
1385 "10.0.0.2-100.1.1.1": {
1386 "LSID": "10.0.0.2",
1387 "Advertised router": "100.1.1.1",
1388 "LSA Age": 137,
1389 "Sequence Number": "80000001",
1390 "Checksum": "9583"
1391 }
1392 },
1393 },
1394 }
1395 }
1396 result = verify_ospf_database(tgen, topo, dut, input_dict)
1397
1398 Returns
1399 -------
1400 True or False (Error Message)
1401 """
1402
1403 result = False
1404 router = dut
1405 logger.debug("Entering lib API: verify_ospf_database()")
1406
701a0192 1407 if "ospf" not in topo["routers"][dut]:
1408 errormsg = "[DUT: {}] OSPF is not configured on the router.".format(dut)
4256a209 1409 return errormsg
1410
1411 rnode = tgen.routers()[dut]
1412
1413 logger.info("Verifying OSPF interface on router %s:", dut)
701a0192 1414 show_ospf_json = run_frr_cmd(rnode, "show ip ospf database json", isjson=True)
4256a209 1415 # Verifying output dictionary show_ospf_json is empty or not
1416 if not bool(show_ospf_json):
1417 errormsg = "OSPF is not running"
1418 return errormsg
1419
1420 # for inter and inter lsa's
1421 ospf_db_data = input_dict.setdefault("areas", None)
701a0192 1422 ospf_external_lsa = input_dict.setdefault("AS External Link States", None)
4256a209 1423 if ospf_db_data:
701a0192 1424 for ospf_area, area_lsa in ospf_db_data.items():
1425 if ospf_area in show_ospf_json["areas"]:
1426 if "Router Link States" in area_lsa:
1427 for lsa in area_lsa["Router Link States"]:
1428 if (
1429 lsa
1430 in show_ospf_json["areas"][ospf_area]["Router Link States"]
1431 ):
1432 logger.info(
1433 "[DUT: %s] OSPF LSDB area %s:Router " "LSA %s",
1434 router,
1435 ospf_area,
1436 lsa,
1437 )
1438 result = True
1439 else:
1440 errormsg = (
1441 "[DUT: {}] OSPF LSDB area {}: expected"
4256a209 1442 " Router LSA is {}".format(router, ospf_area, lsa)
701a0192 1443 )
1444 return errormsg
1445 if "Net Link States" in area_lsa:
1446 for lsa in area_lsa["Net Link States"]:
1447 if lsa in show_ospf_json["areas"][ospf_area]["Net Link States"]:
1448 logger.info(
1449 "[DUT: %s] OSPF LSDB area %s:Network " "LSA %s",
1450 router,
1451 ospf_area,
1452 lsa,
1453 )
1454 result = True
1455 else:
1456 errormsg = (
1457 "[DUT: {}] OSPF LSDB area {}: expected"
4256a209 1458 " Network LSA is {}".format(router, ospf_area, lsa)
701a0192 1459 )
1460 return errormsg
1461 if "Summary Link States" in area_lsa:
1462 for lsa in area_lsa["Summary Link States"]:
1463 if (
1464 lsa
1465 in show_ospf_json["areas"][ospf_area]["Summary Link States"]
1466 ):
1467 logger.info(
1468 "[DUT: %s] OSPF LSDB area %s:Summary " "LSA %s",
1469 router,
1470 ospf_area,
1471 lsa,
1472 )
1473 result = True
1474 else:
1475 errormsg = (
1476 "[DUT: {}] OSPF LSDB area {}: expected"
4256a209 1477 " Summary LSA is {}".format(router, ospf_area, lsa)
701a0192 1478 )
1479 return errormsg
1480 if "ASBR-Summary Link States" in area_lsa:
1481 for lsa in area_lsa["ASBR-Summary Link States"]:
1482 if (
1483 lsa
1484 in show_ospf_json["areas"][ospf_area][
1485 "ASBR-Summary Link States"
1486 ]
1487 ):
1488 logger.info(
1489 "[DUT: %s] OSPF LSDB area %s:ASBR Summary " "LSA %s",
1490 router,
1491 ospf_area,
1492 lsa,
1493 )
1494 result = True
1495 else:
1496 errormsg = (
1497 "[DUT: {}] OSPF LSDB area {}: expected"
1498 " ASBR Summary LSA is {}".format(router, ospf_area, lsa)
1499 )
1500 return errormsg
4256a209 1501 if ospf_external_lsa:
701a0192 1502 for ospf_ext_lsa, ext_lsa_data in ospf_external_lsa.items():
1503 if ospf_ext_lsa in show_ospf_json["AS External Link States"]:
1504 logger.info(
1505 "[DUT: %s] OSPF LSDB:External LSA %s", router, ospf_ext_lsa
1506 )
1507 result = True
1508 else:
1509 errormsg = (
1510 "[DUT: {}] OSPF LSDB : expected"
1511 " External LSA is {}".format(router, ospf_ext_lsa)
1512 )
1513 return errormsg
4256a209 1514
1515 logger.debug("Exiting API: verify_ospf_database()")
1516 return result
1517
1518
ed776e38 1519@retry(retry_timeout=20)
8a86be27 1520def verify_ospf_summary(tgen, topo, dut, input_dict, ospf=None, expected=True):
4256a209 1521 """
1522 This API is to verify ospf routes by running
1523 show ip ospf interface command.
1524
1525 Parameters
1526 ----------
1527 * `tgen` : Topogen object
1528 * `topo` : topology descriptions
1529 * `dut`: device under test
1530 * `input_dict` : Input dict data, required when configuring from testcase
1531
1532 Usage
1533 -----
1534 input_dict = {
1535 "11.0.0.0/8": {
1536 "Summary address": "11.0.0.0/8",
1537 "Metric-type": "E2",
1538 "Metric": 20,
1539 "Tag": 0,
1540 "External route count": 5
1541 }
1542 }
1543 result = verify_ospf_summary(tgen, topo, dut, input_dict)
1544
1545 Returns
1546 -------
1547 True or False (Error Message)
1548 """
1549
8a86be27 1550 logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
4256a209 1551 result = False
1552 router = dut
1553
1554 logger.info("Verifying OSPF summary on router %s:", router)
1555
4256a209 1556 rnode = tgen.routers()[dut]
8a86be27
MR
1557
1558 if ospf:
1559 if 'ospf6' not in topo['routers'][dut]:
1560 errormsg = "[DUT: {}] OSPF6 is not configured on the router.".format(
1561 router)
1562 return errormsg
1563
1564 show_ospf_json = run_frr_cmd(rnode, "show ipv6 ospf summary detail json",
1565 isjson=True)
1566 else:
1567 if 'ospf' not in topo['routers'][dut]:
1568 errormsg = "[DUT: {}] OSPF is not configured on the router.".format(
1569 router)
1570 return errormsg
1571
1572 show_ospf_json = run_frr_cmd(rnode, "show ip ospf summary detail json",
1573 isjson=True)
4256a209 1574
1575 # Verifying output dictionary show_ospf_json is empty or not
1576 if not bool(show_ospf_json):
1577 errormsg = "OSPF is not running"
1578 return errormsg
1579
1580 # To find neighbor ip type
1581 ospf_summary_data = input_dict
8a86be27
MR
1582
1583 if ospf:
1584 show_ospf_json = show_ospf_json['default']
1585
4256a209 1586 for ospf_summ, summ_data in ospf_summary_data.items():
1587 if ospf_summ not in show_ospf_json:
1588 continue
8a86be27
MR
1589 summary = ospf_summary_data[ospf_summ]['Summary address']
1590
4256a209 1591 if summary in show_ospf_json:
1592 for summ in summ_data:
1593 if summ_data[summ] == show_ospf_json[summary][summ]:
8a86be27
MR
1594 logger.info("[DUT: %s] OSPF summary %s:%s is %s",
1595 router, summary, summ, summ_data[summ])
4256a209 1596 result = True
1597 else:
8a86be27
MR
1598 errormsg = ("[DUT: {}] OSPF summary {} : {} is {}, "
1599 "Expected is {}".format(router, summary, summ,show_ospf_json[
1600 summary][summ], summ_data[summ] ))
4256a209 1601 return errormsg
1602
8a86be27 1603 logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
4256a209 1604 return result
2448d002 1605
1606
ed776e38 1607@retry(retry_timeout=30)
2448d002 1608def verify_ospf6_rib(tgen, dut, input_dict, next_hop=None,
1609 tag=None, metric=None, fib=None):
1610 """
1611 This API is to verify ospf routes by running
1612 show ip ospf route command.
1613
1614 Parameters
1615 ----------
1616 * `tgen` : Topogen object
1617 * `dut`: device under test
1618 * `input_dict` : Input dict data, required when configuring from testcase
1619 * `next_hop` : next to be verified
1620 * `tag` : tag to be verified
1621 * `metric` : metric to be verified
1622 * `fib` : True if the route is installed in FIB.
1623
1624 Usage
1625 -----
1626 input_dict = {
1627 "r1": {
1628 "static_routes": [
1629 {
1630 "network": ip_net,
1631 "no_of_ip": 1,
1632 "routeType": "N"
1633 }
1634 ]
1635 }
1636 }
1637
1638 result = verify_ospf6_rib(tgen, dut, input_dict,next_hop=nh)
1639
1640 Returns
1641 -------
1642 True or False (Error Message)
1643 """
1644
1645 logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
1646 result = False
1647 router_list = tgen.routers()
1648 additional_nexthops_in_required_nhs = []
1649 found_hops = []
1650 for routerInput in input_dict.keys():
1651 for router, rnode in router_list.iteritems():
1652 if router != dut:
1653 continue
1654
1655 logger.info("Checking router %s RIB:", router)
1656
1657 # Verifying RIB routes
1658 command = "show ipv6 ospf route"
1659
1660 found_routes = []
1661 missing_routes = []
1662
db56171c 1663 if (
1664 "static_routes" in input_dict[routerInput]
1665 or "prefix" in input_dict[routerInput]
1666 ):
2448d002 1667 if "prefix" in input_dict[routerInput]:
1668 static_routes = input_dict[routerInput]["prefix"]
1669 else:
1670 static_routes = input_dict[routerInput]["static_routes"]
1671
2448d002 1672 for static_route in static_routes:
1673 cmd = "{}".format(command)
1674
1675 cmd = "{} json".format(cmd)
1676
db56171c 1677 ospf_rib_json = run_frr_cmd(rnode, cmd, isjson=True)
2448d002 1678
1679 # Fix for PR 2644182
1680 try:
db56171c 1681 ospf_rib_json = ospf_rib_json["routes"]
2448d002 1682 except KeyError:
1683 pass
1684
1685 # Verifying output dictionary ospf_rib_json is not empty
1686 if bool(ospf_rib_json) is False:
db56171c 1687 errormsg = (
1688 "[DUT: {}] No routes found in OSPF6 route "
2448d002 1689 "table".format(router)
db56171c 1690 )
2448d002 1691 return errormsg
1692
1693 network = static_route["network"]
1694 no_of_ip = static_route.setdefault("no_of_ip", 1)
1695 _tag = static_route.setdefault("tag", None)
1696 _rtype = static_route.setdefault("routeType", None)
1697
2448d002 1698 # Generating IPs for verification
1699 ip_list = generate_ips(network, no_of_ip)
1700 st_found = False
1701 nh_found = False
1702 for st_rt in ip_list:
1703 st_rt = str(ipaddress.ip_network(frr_unicode(st_rt)))
1704
1705 _addr_type = validate_ip_address(st_rt)
db56171c 1706 if _addr_type != "ipv6":
2448d002 1707 continue
1708
1709 if st_rt in ospf_rib_json:
1710
1711 st_found = True
1712 found_routes.append(st_rt)
1713
1714 if fib and next_hop:
1715 if type(next_hop) is not list:
1716 next_hop = [next_hop]
1717
1718 for mnh in range(0, len(ospf_rib_json[st_rt])):
db56171c 1719 if (
1720 "fib"
1721 in ospf_rib_json[st_rt][mnh]["nextHops"][0]
1722 ):
1723 found_hops.append(
1724 [
1725 rib_r["ip"]
1726 for rib_r in ospf_rib_json[st_rt][mnh][
1727 "nextHops"
1728 ]
1729 ]
1730 )
2448d002 1731
1732 if found_hops[0]:
db56171c 1733 missing_list_of_nexthops = set(
1734 found_hops[0]
1735 ).difference(next_hop)
1736 additional_nexthops_in_required_nhs = set(
1737 next_hop
1738 ).difference(found_hops[0])
2448d002 1739
1740 if additional_nexthops_in_required_nhs:
1741 logger.info(
1742 "Nexthop "
1743 "%s is not active for route %s in "
1744 "RIB of router %s\n",
1745 additional_nexthops_in_required_nhs,
db56171c 1746 st_rt,
1747 dut,
1748 )
2448d002 1749 errormsg = (
1750 "Nexthop {} is not active"
1751 " for route {} in RIB of router"
1752 " {}\n".format(
db56171c 1753 additional_nexthops_in_required_nhs,
1754 st_rt,
1755 dut,
1756 )
1757 )
2448d002 1758 return errormsg
1759 else:
1760 nh_found = True
1761
1762 elif next_hop and fib is None:
1763 if type(next_hop) is not list:
1764 next_hop = [next_hop]
db56171c 1765 found_hops = [
1766 rib_r["nextHop"]
1767 for rib_r in ospf_rib_json[st_rt]["nextHops"]
1768 ]
2448d002 1769
1770 if found_hops:
db56171c 1771 missing_list_of_nexthops = set(
1772 found_hops
1773 ).difference(next_hop)
1774 additional_nexthops_in_required_nhs = set(
1775 next_hop
1776 ).difference(found_hops)
2448d002 1777 if additional_nexthops_in_required_nhs:
1778 logger.info(
db56171c 1779 "Missing nexthop %s for route"
1780 " %s in RIB of router %s\n",
2448d002 1781 additional_nexthops_in_required_nhs,
db56171c 1782 st_rt,
1783 dut,
1784 )
1785 errormsg = (
1786 "Nexthop {} is Missing for "
1787 "route {} in RIB of router {}\n".format(
1788 additional_nexthops_in_required_nhs,
1789 st_rt,
1790 dut,
1791 )
1792 )
2448d002 1793 return errormsg
1794 else:
1795 nh_found = True
1796 if _rtype:
db56171c 1797 if "destinationType" not in ospf_rib_json[st_rt]:
1798 errormsg = (
1799 "[DUT: {}]: destinationType missing"
1800 "for route {} in OSPF RIB \n".format(dut, st_rt)
1801 )
2448d002 1802 return errormsg
db56171c 1803 elif _rtype != ospf_rib_json[st_rt]["destinationType"]:
1804 errormsg = (
1805 "[DUT: {}]: destinationType mismatch"
1806 "for route {} in OSPF RIB \n".format(dut, st_rt)
1807 )
2448d002 1808 return errormsg
1809 else:
db56171c 1810 logger.info(
1811 "DUT: {}]: Found destinationType {}"
1812 "for route {}".format(dut, _rtype, st_rt)
1813 )
2448d002 1814 if tag:
db56171c 1815 if "tag" not in ospf_rib_json[st_rt]:
1816 errormsg = (
1817 "[DUT: {}]: tag is not"
1818 " present for"
1819 " route {} in RIB \n".format(dut, st_rt)
1820 )
2448d002 1821 return errormsg
1822
db56171c 1823 if _tag != ospf_rib_json[st_rt]["tag"]:
1824 errormsg = (
1825 "[DUT: {}]: tag value {}"
1826 " is not matched for"
1827 " route {} in RIB \n".format(
1828 dut,
1829 _tag,
1830 st_rt,
1831 )
1832 )
2448d002 1833 return errormsg
1834
1835 if metric is not None:
db56171c 1836 if "type2cost" not in ospf_rib_json[st_rt]:
1837 errormsg = (
1838 "[DUT: {}]: metric is"
1839 " not present for"
1840 " route {} in RIB \n".format(dut, st_rt)
1841 )
2448d002 1842 return errormsg
1843
db56171c 1844 if metric != ospf_rib_json[st_rt]["type2cost"]:
1845 errormsg = (
1846 "[DUT: {}]: metric value "
1847 "{} is not matched for "
1848 "route {} in RIB \n".format(
1849 dut,
1850 metric,
1851 st_rt,
1852 )
1853 )
2448d002 1854 return errormsg
1855
1856 else:
1857 missing_routes.append(st_rt)
1858
1859 if nh_found:
db56171c 1860 logger.info(
1861 "[DUT: {}]: Found next_hop {} for all OSPF"
1862 " routes in RIB".format(router, next_hop)
1863 )
2448d002 1864
1865 if len(missing_routes) > 0:
db56171c 1866 errormsg = "[DUT: {}]: Missing route in RIB, " "routes: {}".format(
1867 dut, missing_routes
1868 )
2448d002 1869 return errormsg
1870
1871 if found_routes:
db56171c 1872 logger.info(
1873 "[DUT: %s]: Verified routes in RIB, found" " routes are: %s\n",
1874 dut,
1875 found_routes,
1876 )
2448d002 1877 result = True
1878
1879 logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
1880 return result
1881
1882
ed776e38 1883@retry(retry_timeout=6)
2448d002 1884def verify_ospf6_interface(tgen, topo, dut=None,lan=False, input_dict=None):
1885 """
1886 This API is to verify ospf routes by running
1887 show ip ospf interface command.
1888
1889 Parameters
1890 ----------
1891 * `tgen` : Topogen object
1892 * `topo` : topology descriptions
1893 * `dut`: device under test
1894 * `lan`: if set to true this interface belongs to LAN.
1895 * `input_dict` : Input dict data, required when configuring from testcase
1896
1897 Usage
1898 -----
1899 input_dict= {
1900 'r0': {
1901 'links':{
1902 's1': {
1903 'ospf6':{
1904 'priority':98,
1905 'timerDeadSecs': 4,
1906 'area': '0.0.0.3',
1907 'mcastMemberOspfDesignatedRouters': True,
1908 'mcastMemberOspfAllRouters': True,
1909 'ospfEnabled': True,
1910
1911 }
1912 }
1913 }
1914 }
1915 }
1916 result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
1917
1918 Returns
1919 -------
1920 True or False (Error Message)
1921 """
1922
1923 logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
1924 result = False
1925
1926 for router, rnode in tgen.routers().iteritems():
db56171c 1927 if "ospf6" not in topo["routers"][router]:
2448d002 1928 continue
1929
1930 if dut is not None and dut != router:
1931 continue
1932
1933 logger.info("Verifying OSPF interface on router %s:", router)
db56171c 1934 show_ospf_json = run_frr_cmd(
1935 rnode, "show ipv6 ospf interface json", isjson=True
1936 )
2448d002 1937
1938 # Verifying output dictionary show_ospf_json is empty or not
1939 if not bool(show_ospf_json):
1940 errormsg = "OSPF6 is not running"
1941 return errormsg
1942
1943 # To find neighbor ip type
1944 ospf_intf_data = input_dict[router]["links"]
1945 for ospf_intf, intf_data in ospf_intf_data.items():
db56171c 1946 intf = topo["routers"][router]["links"][ospf_intf]["interface"]
1947 if intf in show_ospf_json:
1948 for intf_attribute in intf_data["ospf6"]:
1949 if intf_data["ospf6"][intf_attribute] is not list:
1950 if (
1951 intf_data["ospf6"][intf_attribute]
1952 == show_ospf_json[intf][intf_attribute]
1953 ):
1954 logger.info(
1955 "[DUT: %s] OSPF6 interface %s: %s is %s",
1956 router,
1957 intf,
1958 intf_attribute,
1959 intf_data["ospf6"][intf_attribute],
1960 )
1961 elif intf_data["ospf6"][intf_attribute] is list:
2448d002 1962 for addr_list in len(show_ospf_json[intf][intf_attribute]):
db56171c 1963 if (
1964 show_ospf_json[intf][intf_attribute][addr_list][
1965 "address"
1966 ].split("/")[0]
1967 == intf_data["ospf6"]["internetAddress"][0]["address"]
1968 ):
1969 break
2448d002 1970 else:
db56171c 1971 errormsg = "[DUT: {}] OSPF6 interface {}: {} is {}, \
1972 Expected is {}".format(
1973 router,
1974 intf,
1975 intf_attribute,
1976 intf_data["ospf6"][intf_attribute],
1977 intf_data["ospf6"][intf_attribute],
1978 )
2448d002 1979 return errormsg
1980 else:
db56171c 1981 errormsg = "[DUT: {}] OSPF6 interface {}: {} is {}, \
1982 Expected is {}".format(
1983 router,
1984 intf,
1985 intf_attribute,
1986 intf_data["ospf6"][intf_attribute],
1987 intf_data["ospf6"][intf_attribute],
1988 )
2448d002 1989 return errormsg
1990 result = True
1991 logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
1992 return result
1993
1994
ed776e38 1995@retry(retry_timeout=20)
2448d002 1996def verify_ospf6_database(tgen, topo, dut, input_dict):
1997 """
1998 This API is to verify ospf lsa's by running
1999 show ip ospf database command.
2000
2001 Parameters
2002 ----------
2003 * `tgen` : Topogen object
2004 * `dut`: device under test
2005 * `input_dict` : Input dict data, required when configuring from testcase
2006 * `topo` : next to be verified
2007
2008 Usage
2009 -----
2010 input_dict = {
2011 "areas": {
2012 "0.0.0.0": {
2013 "routerLinkStates": {
2014 "100.1.1.0-100.1.1.0": {
2015 "LSID": "100.1.1.0",
2016 "Advertised router": "100.1.1.0",
2017 "LSA Age": 130,
2018 "Sequence Number": "80000006",
2019 "Checksum": "a703",
2020 "Router links": 3
2021 }
2022 },
2023 "networkLinkStates": {
2024 "10.0.0.2-100.1.1.1": {
2025 "LSID": "10.0.0.2",
2026 "Advertised router": "100.1.1.1",
2027 "LSA Age": 137,
2028 "Sequence Number": "80000001",
2029 "Checksum": "9583"
2030 }
2031 },
2032 },
2033 }
2034 }
2035 result = verify_ospf_database(tgen, topo, dut, input_dict)
2036
2037 Returns
2038 -------
2039 True or False (Error Message)
2040 """
2041
2042 result = False
2043 router = dut
2044 logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
2045
db56171c 2046 if "ospf" not in topo["routers"][dut]:
2047 errormsg = "[DUT: {}] OSPF is not configured on the router.".format(dut)
2448d002 2048 return errormsg
2049
2050 rnode = tgen.routers()[dut]
2051
2052 logger.info("Verifying OSPF interface on router %s:", dut)
db56171c 2053 show_ospf_json = run_frr_cmd(rnode, "show ip ospf database json", isjson=True)
2448d002 2054 # Verifying output dictionary show_ospf_json is empty or not
2055 if not bool(show_ospf_json):
2056 errormsg = "OSPF is not running"
2057 return errormsg
2058
2059 # for inter and inter lsa's
2060 ospf_db_data = input_dict.setdefault("areas", None)
db56171c 2061 ospf_external_lsa = input_dict.setdefault("asExternalLinkStates", None)
2448d002 2062
2063 if ospf_db_data:
db56171c 2064 for ospf_area, area_lsa in ospf_db_data.items():
2065 if ospf_area in show_ospf_json["areas"]:
2066 if "routerLinkStates" in area_lsa:
2067 for lsa in area_lsa["routerLinkStates"]:
2068 for rtrlsa in show_ospf_json["areas"][ospf_area][
2069 "routerLinkStates"
2070 ]:
2071 if (
2072 lsa["lsaId"] == rtrlsa["lsaId"]
2073 and lsa["advertisedRouter"]
2074 == rtrlsa["advertisedRouter"]
2075 ):
2076 result = True
2448d002 2077 break
db56171c 2078 if result:
2079 logger.info(
2080 "[DUT: %s] OSPF LSDB area %s:Router " "LSA %s",
2081 router,
2082 ospf_area,
2083 lsa,
2084 )
2085 break
2086 else:
2087 errormsg = (
2088 "[DUT: {}] OSPF LSDB area {}: expected"
2448d002 2089 " Router LSA is {}".format(router, ospf_area, lsa)
db56171c 2090 )
2091 return errormsg
2448d002 2092
db56171c 2093 if "networkLinkStates" in area_lsa:
2094 for lsa in area_lsa["networkLinkStates"]:
2095 for netlsa in show_ospf_json["areas"][ospf_area][
2096 "networkLinkStates"
2097 ]:
2098 if (
2099 lsa
2100 in show_ospf_json["areas"][ospf_area][
2101 "networkLinkStates"
2102 ]
2103 ):
2104 if (
2105 lsa["lsaId"] == netlsa["lsaId"]
2106 and lsa["advertisedRouter"]
2107 == netlsa["advertisedRouter"]
2108 ):
2109 result = True
2110 break
2111 if result:
2112 logger.info(
2113 "[DUT: %s] OSPF LSDB area %s:Network " "LSA %s",
2114 router,
2115 ospf_area,
2116 lsa,
2117 )
2118 break
2119 else:
2120 errormsg = (
2121 "[DUT: {}] OSPF LSDB area {}: expected"
2448d002 2122 " Network LSA is {}".format(router, ospf_area, lsa)
db56171c 2123 )
2124 return errormsg
2448d002 2125
db56171c 2126 if "summaryLinkStates" in area_lsa:
2127 for lsa in area_lsa["summaryLinkStates"]:
2128 for t3lsa in show_ospf_json["areas"][ospf_area][
2129 "summaryLinkStates"
2130 ]:
2131 if (
2132 lsa["lsaId"] == t3lsa["lsaId"]
2133 and lsa["advertisedRouter"] == t3lsa["advertisedRouter"]
2134 ):
2135 result = True
2448d002 2136 break
db56171c 2137 if result:
2138 logger.info(
2139 "[DUT: %s] OSPF LSDB area %s:Summary " "LSA %s",
2140 router,
2141 ospf_area,
2142 lsa,
2143 )
2144 break
2145 else:
2146 errormsg = (
2147 "[DUT: {}] OSPF LSDB area {}: expected"
2448d002 2148 " Summary LSA is {}".format(router, ospf_area, lsa)
db56171c 2149 )
2150 return errormsg
2448d002 2151
db56171c 2152 if "nssaExternalLinkStates" in area_lsa:
2153 for lsa in area_lsa["nssaExternalLinkStates"]:
2154 for t7lsa in show_ospf_json["areas"][ospf_area][
2155 "nssaExternalLinkStates"
2156 ]:
2157 if (
2158 lsa["lsaId"] == t7lsa["lsaId"]
2159 and lsa["advertisedRouter"] == t7lsa["advertisedRouter"]
2160 ):
2161 result = True
2448d002 2162 break
db56171c 2163 if result:
2164 logger.info(
2165 "[DUT: %s] OSPF LSDB area %s:Type7 " "LSA %s",
2166 router,
2167 ospf_area,
2168 lsa,
2169 )
2170 break
2171 else:
2172 errormsg = (
2173 "[DUT: {}] OSPF LSDB area {}: expected"
2448d002 2174 " Type7 LSA is {}".format(router, ospf_area, lsa)
db56171c 2175 )
2176 return errormsg
2448d002 2177
db56171c 2178 if "asbrSummaryLinkStates" in area_lsa:
2179 for lsa in area_lsa["asbrSummaryLinkStates"]:
2180 for t4lsa in show_ospf_json["areas"][ospf_area][
2181 "asbrSummaryLinkStates"
2182 ]:
2183 if (
2184 lsa["lsaId"] == t4lsa["lsaId"]
2185 and lsa["advertisedRouter"] == t4lsa["advertisedRouter"]
2186 ):
2448d002 2187 result = True
db56171c 2188 break
2189 if result:
2190 logger.info(
2191 "[DUT: %s] OSPF LSDB area %s:ASBR Summary " "LSA %s",
2192 router,
2193 ospf_area,
2194 lsa,
2195 )
2196 result = True
2197 else:
2198 errormsg = (
2199 "[DUT: {}] OSPF LSDB area {}: expected"
2200 " ASBR Summary LSA is {}".format(router, ospf_area, lsa)
2201 )
2202 return errormsg
2448d002 2203
db56171c 2204 if "linkLocalOpaqueLsa" in area_lsa:
2205 for lsa in area_lsa["linkLocalOpaqueLsa"]:
2206 try:
2207 for lnklsa in show_ospf_json["areas"][ospf_area][
2208 "linkLocalOpaqueLsa"
2209 ]:
2210 if (
2211 lsa["lsaId"] in lnklsa["lsaId"]
2212 and "linkLocalOpaqueLsa"
2213 in show_ospf_json["areas"][ospf_area]
2214 ):
2215 logger.info(
2216 (
2217 "[DUT: FRR] OSPF LSDB area %s:Opaque-LSA"
2218 "%s",
2219 ospf_area,
2220 lsa,
2221 )
2222 )
2223 result = True
2224 else:
2225 errormsg = (
2226 "[DUT: FRR] OSPF LSDB area: {} "
2227 "expected Opaque-LSA is {}, Found is {}".format(
2228 ospf_area, lsa, show_ospf_json
2229 )
2230 )
2231 raise ValueError(errormsg)
2232 return errormsg
2233 except KeyError:
2234 errormsg = "[DUT: FRR] linkLocalOpaqueLsa Not " "present"
2235 return errormsg
2448d002 2236
2237 if ospf_external_lsa:
db56171c 2238 for lsa in ospf_external_lsa:
2239 try:
2240 for t5lsa in show_ospf_json["asExternalLinkStates"]:
2241 if (
2242 lsa["lsaId"] == t5lsa["lsaId"]
2243 and lsa["advertisedRouter"] == t5lsa["advertisedRouter"]
2244 ):
2245 result = True
2246 break
2247 except KeyError:
2248 result = False
2249 if result:
2250 logger.info("[DUT: %s] OSPF LSDB:External LSA %s", router, lsa)
2251 result = True
2252 else:
2253 errormsg = (
2254 "[DUT: {}] OSPF LSDB : expected"
2255 " External LSA is {}".format(router, lsa)
2256 )
2257 return errormsg
2448d002 2258
2259 logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
2260 return result
2261
2262
db56171c 2263def config_ospf6_interface(tgen, topo, input_dict=None, build=False, load_config=True):
2448d002 2264 """
2265 API to configure ospf on router.
2266
2267 Parameters
2268 ----------
2269 * `tgen` : Topogen object
2270 * `topo` : json file data
2271 * `input_dict` : Input dict data, required when configuring from testcase
2272 * `build` : Only for initial setup phase this is set as True.
2273 * `load_config` : Loading the config to router this is set as True.
2274
2275 Usage
2276 -----
2277 r1_ospf_auth = {
2278 "r1": {
2279 "links": {
2280 "r2": {
2281 "ospf": {
2282 "authentication": 'message-digest',
2283 "authentication-key": "ospf",
2284 "message-digest-key": "10"
2285 }
2286 }
2287 }
2288 }
2289 }
2290 result = config_ospf6_interface(tgen, topo, r1_ospf_auth)
2291
2292 Returns
2293 -------
2294 True or False
2295 """
2296 logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
2297 result = False
2298 if not input_dict:
2299 input_dict = deepcopy(topo)
2300 else:
2301 input_dict = deepcopy(input_dict)
2302 for router in input_dict.keys():
2303 config_data = []
2304 for lnk in input_dict[router]['links'].keys():
2305 if "ospf6" not in input_dict[router]['links'][lnk]:
ed776e38
CH
2306 logger.debug("Router %s: ospf6 config is not present in"
2307 "input_dict, passed input_dict %s", router,
2308 str(input_dict))
2448d002 2309 continue
db56171c 2310 ospf_data = input_dict[router]["links"][lnk]["ospf6"]
2448d002 2311 data_ospf_area = ospf_data.setdefault("area", None)
db56171c 2312 data_ospf_auth = ospf_data.setdefault("hash-algo", None)
2448d002 2313 data_ospf_dr_priority = ospf_data.setdefault("priority", None)
2314 data_ospf_cost = ospf_data.setdefault("cost", None)
2315 data_ospf_mtu = ospf_data.setdefault("mtu_ignore", None)
2316
2317 try:
db56171c 2318 intf = topo["routers"][router]["links"][lnk]["interface"]
2448d002 2319 except KeyError:
db56171c 2320 intf = topo["switches"][router]["links"][lnk]["interface"]
2448d002 2321
2322 # interface
2323 cmd = "interface {}".format(intf)
2324
2325 config_data.append(cmd)
2326 # interface area config
2327 if data_ospf_area:
2328 cmd = "ipv6 ospf area {}".format(data_ospf_area)
2329 config_data.append(cmd)
2330
db56171c 2331 # interface ospf auth
2332 if data_ospf_auth:
2333 cmd = "ipv6 ospf6 authentication"
2334
2335 if "del_action" in ospf_data:
2336 cmd = "no {}".format(cmd)
2337
2338 if "hash-algo" in ospf_data:
2339 cmd = "{} key-id {} hash-algo {} key {}".format(
2340 cmd,
2341 ospf_data["key-id"],
2342 ospf_data["hash-algo"],
2343 ospf_data["key"],
2344 )
2345 if "del_action" in ospf_data:
2346 cmd = "no {}".format(cmd)
2347 config_data.append(cmd)
2348
2448d002 2349 # interface ospf dr priority
2350 if data_ospf_dr_priority:
db56171c 2351 cmd = "ipv6 ospf priority {}".format(ospf_data["priority"])
2352 if "del_action" in ospf_data:
2448d002 2353 cmd = "no {}".format(cmd)
2354 config_data.append(cmd)
2355
2356 # interface ospf cost
2357 if data_ospf_cost:
db56171c 2358 cmd = "ipv6 ospf cost {}".format(ospf_data["cost"])
2359 if "del_action" in ospf_data:
2448d002 2360 cmd = "no {}".format(cmd)
2361 config_data.append(cmd)
2362
2363 # interface ospf mtu
2364 if data_ospf_mtu:
2365 cmd = "ipv6 ospf mtu-ignore"
db56171c 2366 if "del_action" in ospf_data:
2448d002 2367 cmd = "no {}".format(cmd)
2368 config_data.append(cmd)
2369
2370 if build:
2371 return config_data
2372 else:
db56171c 2373 result = create_common_configuration(
2374 tgen, router, config_data, "interface_config", build=build
2375 )
2448d002 2376 logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
2377 return result