]> git.proxmox.com Git - mirror_frr.git/blame - tests/topotests/lib/ospf.py
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / tests / topotests / lib / ospf.py
CommitLineData
acddc0ed 1# SPDX-License-Identifier: ISC
4256a209 2#
3# Copyright (c) 2020 by VMware, Inc. ("VMware")
4# Used Copyright (c) 2018 by Network Device Education Foundation, Inc.
5# ("NetDEF") in this file.
6#
4256a209 7
2448d002 8import ipaddress
9import sys
2448d002 10from copy import deepcopy
044561b1 11from time import sleep
49581587 12
4256a209 13# Import common_config to use commomnly used APIs
701a0192 14from lib.common_config import (
4f99894d 15 create_common_configurations,
701a0192 16 InvalidCLIError,
49581587
CH
17 generate_ips,
18 retry,
701a0192 19 run_frr_cmd,
49581587 20 validate_ip_address,
701a0192 21)
49581587
CH
22from lib.topolog import logger
23from lib.topotest import frr_unicode
4256a209 24
25################################
26# Configure procs
27################################
28
701a0192 29
49581587 30def create_router_ospf(tgen, topo=None, input_dict=None, build=False, load_config=True):
4256a209 31 """
32 API to configure ospf on router.
33
34 Parameters
35 ----------
36 * `tgen` : Topogen object
37 * `topo` : json file data
38 * `input_dict` : Input dict data, required when configuring from testcase
39 * `build` : Only for initial setup phase this is set as True.
40 * `load_config` : Loading the config to router this is set as True.
41
42 Usage
43 -----
44 input_dict = {
45 "r1": {
46 "ospf": {
47 "router_id": "22.22.22.22",
9458be1a 48 "area": [{ "id": "0.0.0.0", "type": "nssa"}]
4256a209 49 }
50 }
51
52 result = create_router_ospf(tgen, topo, input_dict)
53
54 Returns
55 -------
56 True or False
57 """
58 logger.debug("Entering lib API: create_router_ospf()")
59 result = False
60
49581587
CH
61 if topo is None:
62 topo = tgen.json_topo
63
4256a209 64 if not input_dict:
65 input_dict = deepcopy(topo)
66 else:
67 topo = topo["routers"]
68 input_dict = deepcopy(input_dict)
69
4f99894d
CH
70 for ospf in ["ospf", "ospf6"]:
71 config_data_dict = {}
4256a209 72
4f99894d
CH
73 for router in input_dict.keys():
74 if ospf not in input_dict[router]:
75 logger.debug("Router %s: %s not present in input_dict", router, ospf)
76 continue
2448d002 77
4f99894d
CH
78 config_data = __create_ospf_global(
79 tgen, input_dict, router, build, load_config, ospf
80 )
81 if config_data:
82 if router not in config_data_dict:
83 config_data_dict[router] = config_data
84 else:
85 config_data_dict[router].extend(config_data)
86 try:
87 result = create_common_configurations(
88 tgen, config_data_dict, ospf, build, load_config
89 )
90 except InvalidCLIError:
91 logger.error("create_router_ospf (ipv4)", exc_info=True)
92 result = False
2448d002 93
4256a209 94 logger.debug("Exiting lib API: create_router_ospf()")
95 return result
96
97
a53c08bc 98def __create_ospf_global(tgen, input_dict, router, build, load_config, ospf):
4256a209 99 """
100 Helper API to create ospf global configuration.
101
102 Parameters
103 ----------
104 * `tgen` : Topogen object
105 * `input_dict` : Input dict data, required when configuring from testcase
106 * `router` : router to be configured.
107 * `build` : Only for initial setup phase this is set as True.
108 * `load_config` : Loading the config to router this is set as True.
889da676 109 * `ospf` : either 'ospf' or 'ospf6'
4256a209 110
2718dd02 111 Usage
112 -----
113 input_dict = {
114 "routers": {
115 "r1": {
116 "links": {
117 "r3": {
118 "ipv6": "2013:13::1/64",
4f99894d 119 "ospf6": {
2718dd02 120 "hello_interval": 1,
121 "dead_interval": 4,
122 "network": "point-to-point"
123 }
4f99894d 124 }
2718dd02 125 },
126 "ospf6": {
127 "router_id": "1.1.1.1",
128 "neighbors": {
129 "r3": {
130 "area": "1.1.1.1"
131 }
132 }
133 }
134 }
135 }
136
4256a209 137 Returns
138 -------
4f99894d 139 list of configuration commands
4256a209 140 """
141
4f99894d 142 config_data = []
4256a209 143
4f99894d
CH
144 if ospf not in input_dict[router]:
145 return config_data
4256a209 146
4f99894d 147 logger.debug("Entering lib API: __create_ospf_global()")
4256a209 148
4f99894d
CH
149 ospf_data = input_dict[router][ospf]
150 del_ospf_action = ospf_data.setdefault("delete", False)
151 if del_ospf_action:
152 config_data = ["no router {}".format(ospf)]
153 return config_data
154
155 cmd = "router {}".format(ospf)
156
157 config_data.append(cmd)
158
159 # router id
160 router_id = ospf_data.setdefault("router_id", None)
161 del_router_id = ospf_data.setdefault("del_router_id", False)
162 if del_router_id:
163 config_data.append("no {} router-id".format(ospf))
164 if router_id:
165 config_data.append("{} router-id {}".format(ospf, router_id))
166
167 # log-adjacency-changes
168 log_adj_changes = ospf_data.setdefault("log_adj_changes", None)
169 del_log_adj_changes = ospf_data.setdefault("del_log_adj_changes", False)
170 if del_log_adj_changes:
171 config_data.append("no log-adjacency-changes detail")
172 if log_adj_changes:
a53c08bc 173 config_data.append("log-adjacency-changes {}".format(log_adj_changes))
4f99894d
CH
174
175 # aggregation timer
176 aggr_timer = ospf_data.setdefault("aggr_timer", None)
177 del_aggr_timer = ospf_data.setdefault("del_aggr_timer", False)
178 if del_aggr_timer:
179 config_data.append("no aggregation timer")
180 if aggr_timer:
a53c08bc 181 config_data.append("aggregation timer {}".format(aggr_timer))
4f99894d
CH
182
183 # maximum path information
184 ecmp_data = ospf_data.setdefault("maximum-paths", {})
185 if ecmp_data:
186 cmd = "maximum-paths {}".format(ecmp_data)
187 del_action = ospf_data.setdefault("del_max_path", False)
188 if del_action:
189 cmd = "no maximum-paths"
4256a209 190 config_data.append(cmd)
191
044561b1
MN
192 # Flood reduction.
193 flood_data = ospf_data.setdefault("flood-reduction", {})
194 if flood_data:
195 cmd = "flood-reduction"
196 del_action = ospf_data.setdefault("del_flood_reduction", False)
197 if del_action:
198 cmd = "no flood-reduction"
199 config_data.append(cmd)
200
201 # LSA refresh timer - A hidden command.
202 refresh_data = ospf_data.setdefault("lsa-refresh", {})
203 if refresh_data:
204 cmd = "ospf lsa-refresh {}".format(refresh_data)
205 del_action = ospf_data.setdefault("del_lsa_refresh", False)
206 if del_action:
207 cmd = "no ospf lsa-refresh"
208 config_data.append(cmd)
209
4f99894d
CH
210 # redistribute command
211 redistribute_data = ospf_data.setdefault("redistribute", {})
212 if redistribute_data:
213 for redistribute in redistribute_data:
214 if "redist_type" not in redistribute:
215 logger.debug(
216 "Router %s: 'redist_type' not present in " "input_dict", router
217 )
218 else:
219 cmd = "redistribute {}".format(redistribute["redist_type"])
220 for red_type in redistribute_data:
221 if "route_map" in red_type:
222 cmd = cmd + " route-map {}".format(red_type["route_map"])
223 del_action = redistribute.setdefault("delete", False)
224 if del_action:
225 cmd = "no {}".format(cmd)
226 config_data.append(cmd)
2448d002 227
4f99894d
CH
228 # area information
229 area_data = ospf_data.setdefault("area", {})
230 if area_data:
231 for area in area_data:
232 if "id" not in area:
233 logger.debug(
234 "Router %s: 'area id' not present in " "input_dict", router
235 )
236 else:
237 cmd = "area {}".format(area["id"])
889da676 238
4f99894d
CH
239 if "type" in area:
240 cmd = cmd + " {}".format(area["type"])
4256a209 241
044561b1
MN
242 if "flood-reduction" in area:
243 cmd = cmd + " flood-reduction"
244
4f99894d
CH
245 del_action = area.setdefault("delete", False)
246 if del_action:
247 cmd = "no {}".format(cmd)
248 config_data.append(cmd)
4256a209 249
a53c08bc 250 # def route information
4f99894d
CH
251 def_rte_data = ospf_data.setdefault("default-information", {})
252 if def_rte_data:
253 if "originate" not in def_rte_data:
a53c08bc
CH
254 logger.debug(
255 "Router %s: 'originate key' not present in " "input_dict", router
256 )
4f99894d
CH
257 else:
258 cmd = "default-information originate"
4256a209 259
4f99894d
CH
260 if "always" in def_rte_data:
261 cmd = cmd + " always"
2448d002 262
4f99894d
CH
263 if "metric" in def_rte_data:
264 cmd = cmd + " metric {}".format(def_rte_data["metric"])
2448d002 265
4f99894d 266 if "metric-type" in def_rte_data:
a53c08bc 267 cmd = cmd + " metric-type {}".format(def_rte_data["metric-type"])
2448d002 268
4f99894d
CH
269 if "route-map" in def_rte_data:
270 cmd = cmd + " route-map {}".format(def_rte_data["route-map"])
2448d002 271
4f99894d
CH
272 del_action = def_rte_data.setdefault("delete", False)
273 if del_action:
274 cmd = "no {}".format(cmd)
275 config_data.append(cmd)
2448d002 276
4f99894d
CH
277 # summary information
278 summary_data = ospf_data.setdefault("summary-address", {})
279 if summary_data:
280 for summary in summary_data:
281 if "prefix" not in summary:
282 logger.debug(
283 "Router %s: 'summary-address' not present in " "input_dict",
284 router,
285 )
286 else:
287 cmd = "summary {}/{}".format(summary["prefix"], summary["mask"])
4256a209 288
4f99894d
CH
289 _tag = summary.setdefault("tag", None)
290 if _tag:
291 cmd = "{} tag {}".format(cmd, _tag)
889da676 292
4f99894d
CH
293 _advertise = summary.setdefault("advertise", True)
294 if not _advertise:
295 cmd = "{} no-advertise".format(cmd)
cc90defc 296
4f99894d
CH
297 del_action = summary.setdefault("delete", False)
298 if del_action:
cc90defc 299 cmd = "no {}".format(cmd)
300 config_data.append(cmd)
301
4f99894d
CH
302 # ospf gr information
303 gr_data = ospf_data.setdefault("graceful-restart", {})
304 if gr_data:
305
306 if "opaque" in gr_data and gr_data["opaque"]:
307 cmd = "capability opaque"
308 if gr_data.setdefault("delete", False):
309 cmd = "no {}".format(cmd)
310 config_data.append(cmd)
311
859bce81
RW
312 if "helper enable" in gr_data and not gr_data["helper enable"]:
313 cmd = "graceful-restart helper enable"
4f99894d
CH
314 if gr_data.setdefault("delete", False):
315 cmd = "no {}".format(cmd)
316 config_data.append(cmd)
859bce81
RW
317 elif "helper enable" in gr_data and type(gr_data["helper enable"]) is list:
318 for rtrs in gr_data["helper enable"]:
319 cmd = "graceful-restart helper enable {}".format(rtrs)
cc90defc 320 if gr_data.setdefault("delete", False):
321 cmd = "no {}".format(cmd)
322 config_data.append(cmd)
cc90defc 323
4f99894d
CH
324 if "helper" in gr_data:
325 if type(gr_data["helper"]) is not list:
326 gr_data["helper"] = list(gr_data["helper"])
327 for helper_role in gr_data["helper"]:
328 cmd = "graceful-restart helper {}".format(helper_role)
cc90defc 329 if gr_data.setdefault("delete", False):
330 cmd = "no {}".format(cmd)
331 config_data.append(cmd)
332
4f99894d
CH
333 if "supported-grace-time" in gr_data:
334 cmd = "graceful-restart helper supported-grace-time {}".format(
335 gr_data["supported-grace-time"]
336 )
337 if gr_data.setdefault("delete", False):
338 cmd = "no {}".format(cmd)
339 config_data.append(cmd)
4256a209 340
341 logger.debug("Exiting lib API: create_ospf_global()")
4f99894d
CH
342
343 return config_data
4256a209 344
345
a53c08bc
CH
346def config_ospf_interface(
347 tgen, topo=None, input_dict=None, build=False, load_config=True
348):
4256a209 349 """
350 API to configure ospf on router.
351
352 Parameters
353 ----------
354 * `tgen` : Topogen object
355 * `topo` : json file data
356 * `input_dict` : Input dict data, required when configuring from testcase
357 * `build` : Only for initial setup phase this is set as True.
358 * `load_config` : Loading the config to router this is set as True.
359
360 Usage
361 -----
362 r1_ospf_auth = {
363 "r1": {
364 "links": {
365 "r2": {
366 "ospf": {
9458be1a 367 "authentication": "message-digest",
4256a209 368 "authentication-key": "ospf",
369 "message-digest-key": "10"
370 }
371 }
372 }
373 }
374 }
375 result = config_ospf_interface(tgen, topo, r1_ospf_auth)
376
377 Returns
378 -------
379 True or False
380 """
381 logger.debug("Enter lib config_ospf_interface")
db56171c 382 result = False
49581587
CH
383
384 if topo is None:
385 topo = tgen.json_topo
386
4256a209 387 if not input_dict:
388 input_dict = deepcopy(topo)
389 else:
390 input_dict = deepcopy(input_dict)
4f99894d
CH
391
392 config_data_dict = {}
393
4256a209 394 for router in input_dict.keys():
395 config_data = []
701a0192 396 for lnk in input_dict[router]["links"].keys():
397 if "ospf" not in input_dict[router]["links"][lnk]:
398 logger.debug(
0b25370e 399 "Router %s: ospf config is not present in" "input_dict", router
701a0192 400 )
4256a209 401 continue
701a0192 402 ospf_data = input_dict[router]["links"][lnk]["ospf"]
4256a209 403 data_ospf_area = ospf_data.setdefault("area", None)
404 data_ospf_auth = ospf_data.setdefault("authentication", None)
405 data_ospf_dr_priority = ospf_data.setdefault("priority", None)
406 data_ospf_cost = ospf_data.setdefault("cost", None)
8694dd78 407 data_ospf_mtu = ospf_data.setdefault("mtu_ignore", None)
4256a209 408
409 try:
701a0192 410 intf = topo["routers"][router]["links"][lnk]["interface"]
4256a209 411 except KeyError:
701a0192 412 intf = topo["switches"][router]["links"][lnk]["interface"]
4256a209 413
414 # interface
415 cmd = "interface {}".format(intf)
416
417 config_data.append(cmd)
418 # interface area config
419 if data_ospf_area:
420 cmd = "ip ospf area {}".format(data_ospf_area)
421 config_data.append(cmd)
9458be1a 422
4256a209 423 # interface ospf auth
424 if data_ospf_auth:
701a0192 425 if data_ospf_auth == "null":
4256a209 426 cmd = "ip ospf authentication null"
701a0192 427 elif data_ospf_auth == "message-digest":
4256a209 428 cmd = "ip ospf authentication message-digest"
429 else:
430 cmd = "ip ospf authentication"
431
701a0192 432 if "del_action" in ospf_data:
4256a209 433 cmd = "no {}".format(cmd)
434 config_data.append(cmd)
435
436 if "message-digest-key" in ospf_data:
437 cmd = "ip ospf message-digest-key {} md5 {}".format(
701a0192 438 ospf_data["message-digest-key"], ospf_data["authentication-key"]
439 )
440 if "del_action" in ospf_data:
4256a209 441 cmd = "no {}".format(cmd)
442 config_data.append(cmd)
443
701a0192 444 if (
445 "authentication-key" in ospf_data
446 and "message-digest-key" not in ospf_data
447 ):
448 cmd = "ip ospf authentication-key {}".format(
449 ospf_data["authentication-key"]
450 )
451 if "del_action" in ospf_data:
4256a209 452 cmd = "no {}".format(cmd)
453 config_data.append(cmd)
454
455 # interface ospf dr priority
8694dd78 456 if data_ospf_dr_priority:
701a0192 457 cmd = "ip ospf priority {}".format(ospf_data["priority"])
458 if "del_action" in ospf_data:
4256a209 459 cmd = "no {}".format(cmd)
460 config_data.append(cmd)
461
462 # interface ospf cost
8694dd78 463 if data_ospf_cost:
701a0192 464 cmd = "ip ospf cost {}".format(ospf_data["cost"])
465 if "del_action" in ospf_data:
4256a209 466 cmd = "no {}".format(cmd)
467 config_data.append(cmd)
468
8694dd78 469 # interface ospf mtu
470 if data_ospf_mtu:
471 cmd = "ip ospf mtu-ignore"
db56171c 472 if "del_action" in ospf_data:
8694dd78 473 cmd = "no {}".format(cmd)
474 config_data.append(cmd)
475
4256a209 476 if build:
477 return config_data
4f99894d
CH
478
479 if config_data:
480 config_data_dict[router] = config_data
481
482 result = create_common_configurations(
483 tgen, config_data_dict, "interface_config", build=build
484 )
485
2448d002 486 logger.debug("Exiting lib API: config_ospf_interface()")
4256a209 487 return result
488
701a0192 489
2448d002 490def clear_ospf(tgen, router, ospf=None):
4256a209 491 """
492 This API is to clear ospf neighborship by running
493 clear ip ospf interface * command,
494
495 Parameters
496 ----------
497 * `tgen`: topogen object
498 * `router`: device under test
499
500 Usage
501 -----
502 clear_ospf(tgen, "r1")
503 """
504
505 logger.debug("Entering lib API: clear_ospf()")
506 if router not in tgen.routers():
507 return False
508
509 rnode = tgen.routers()[router]
4256a209 510 # Clearing OSPF
2448d002 511 if ospf:
512 version = "ipv6"
513 else:
514 version = "ip"
4256a209 515
2448d002 516 cmd = "clear {} ospf interface".format(version)
db56171c 517 logger.info("Clearing ospf process on router %s.. using command '%s'", router, cmd)
2448d002 518 run_frr_cmd(rnode, cmd)
4256a209 519
520 logger.debug("Exiting lib API: clear_ospf()")
521
522
88b7d3e7 523def redistribute_ospf(tgen, topo, dut, route_type, **kwargs):
524 """
525 Redstribution of routes inside ospf.
526
527 Parameters
528 ----------
529 * `tgen`: Topogen object
530 * `topo` : json file data
531 * `dut`: device under test
532 * `route_type`: "static" or "connected" or ....
533 * `kwargs`: pass extra information (see below)
534
535 Usage
536 -----
537 redistribute_ospf(tgen, topo, "r0", "static", delete=True)
538 redistribute_ospf(tgen, topo, "r0", "static", route_map="rmap_ipv4")
539 """
540
541 ospf_red = {dut: {"ospf": {"redistribute": [{"redist_type": route_type}]}}}
542 for k, v in kwargs.items():
543 ospf_red[dut]["ospf"]["redistribute"][0][k] = v
544
545 result = create_router_ospf(tgen, topo, ospf_red)
546 assert result is True, "Testcase : Failed \n Error: {}".format(result)
547
548
4256a209 549################################
550# Verification procs
551################################
ed776e38 552@retry(retry_timeout=80)
a53c08bc
CH
553def verify_ospf_neighbor(
554 tgen, topo=None, dut=None, input_dict=None, lan=False, expected=True
555):
4256a209 556 """
557 This API is to verify ospf neighborship by running
558 show ip ospf neighbour command,
559
560 Parameters
561 ----------
562 * `tgen` : Topogen object
563 * `topo` : json file data
564 * `dut`: device under test
565 * `input_dict` : Input dict data, required when configuring from testcase
566 * `lan` : verify neighbors in lan topology
3c41ebf8 567 * `expected` : expected results from API, by-default True
4256a209 568
569 Usage
570 -----
571 1. To check FULL neighbors.
572 verify_ospf_neighbor(tgen, topo, dut=dut)
573
574 2. To check neighbors with their roles.
575 input_dict = {
576 "r0": {
577 "ospf": {
578 "neighbors": {
579 "r1": {
580 "state": "Full",
581 "role": "DR"
582 },
583 "r2": {
584 "state": "Full",
585 "role": "DROther"
586 },
587 "r3": {
588 "state": "Full",
589 "role": "DROther"
590 }
591 }
592 }
593 }
594 }
595 result = verify_ospf_neighbor(tgen, topo, dut, input_dict, lan=True)
596
597 Returns
598 -------
599 True or False (Error Message)
600 """
601 logger.debug("Entering lib API: verify_ospf_neighbor()")
602 result = False
49581587
CH
603 if topo is None:
604 topo = tgen.json_topo
605
4256a209 606 if input_dict:
11761ab0 607 for router, rnode in tgen.routers().items():
701a0192 608 if "ospf" not in topo["routers"][router]:
4256a209 609 continue
610
611 if dut is not None and dut != router:
612 continue
613
614 logger.info("Verifying OSPF neighborship on router %s:", router)
701a0192 615 show_ospf_json = run_frr_cmd(
9458be1a 616 rnode, "show ip ospf neighbor all json", isjson=True
701a0192 617 )
4256a209 618
619 # Verifying output dictionary show_ospf_json is empty or not
620 if not bool(show_ospf_json):
621 errormsg = "OSPF is not running"
622 return errormsg
623
624 ospf_data_list = input_dict[router]["ospf"]
701a0192 625 ospf_nbr_list = ospf_data_list["neighbors"]
4256a209 626
627 for ospf_nbr, nbr_data in ospf_nbr_list.items():
701a0192 628 data_ip = topo["routers"][ospf_nbr]["links"]
629 data_rid = topo["routers"][ospf_nbr]["ospf"]["router_id"]
4256a209 630 if ospf_nbr in data_ip:
631 nbr_details = nbr_data[ospf_nbr]
632 elif lan:
701a0192 633 for switch in topo["switches"]:
634 if "ospf" in topo["switches"][switch]["links"][router]:
635 neighbor_ip = data_ip[switch]["ipv4"].split("/")[0]
4256a209 636 else:
637 continue
638 else:
701a0192 639 neighbor_ip = data_ip[router]["ipv4"].split("/")[0]
4256a209 640
641 nh_state = None
642 neighbor_ip = neighbor_ip.lower()
643 nbr_rid = data_rid
644 try:
701a0192 645 nh_state = show_ospf_json[nbr_rid][0]["state"].split("/")[0]
646 intf_state = show_ospf_json[nbr_rid][0]["state"].split("/")[1]
4256a209 647 except KeyError:
701a0192 648 errormsg = "[DUT: {}] OSPF peer {} missing".format(router, nbr_rid)
4256a209 649 return errormsg
650
701a0192 651 nbr_state = nbr_data.setdefault("state", None)
652 nbr_role = nbr_data.setdefault("role", None)
4256a209 653
654 if nbr_state:
655 if nbr_state == nh_state:
701a0192 656 logger.info(
657 "[DUT: {}] OSPF Nbr is {}:{} State {}".format(
658 router, ospf_nbr, nbr_rid, nh_state
659 )
660 )
4256a209 661 result = True
662 else:
701a0192 663 errormsg = (
664 "[DUT: {}] OSPF is not Converged, neighbor"
665 " state is {}".format(router, nh_state)
666 )
4256a209 667 return errormsg
668 if nbr_role:
669 if nbr_role == intf_state:
701a0192 670 logger.info(
671 "[DUT: {}] OSPF Nbr is {}: {} Role {}".format(
672 router, ospf_nbr, nbr_rid, nbr_role
673 )
674 )
4256a209 675 else:
701a0192 676 errormsg = (
677 "[DUT: {}] OSPF is not Converged with rid"
678 "{}, role is {}".format(router, nbr_rid, intf_state)
679 )
4256a209 680 return errormsg
681 continue
682 else:
11761ab0 683 for router, rnode in tgen.routers().items():
701a0192 684 if "ospf" not in topo["routers"][router]:
4256a209 685 continue
686
687 if dut is not None and dut != router:
688 continue
689
690 logger.info("Verifying OSPF neighborship on router %s:", router)
701a0192 691 show_ospf_json = run_frr_cmd(
692 rnode, "show ip ospf neighbor all json", isjson=True
693 )
4256a209 694 # Verifying output dictionary show_ospf_json is empty or not
695 if not bool(show_ospf_json):
696 errormsg = "OSPF is not running"
697 return errormsg
698
699 ospf_data_list = topo["routers"][router]["ospf"]
701a0192 700 ospf_neighbors = ospf_data_list["neighbors"]
4256a209 701 total_peer = 0
702 total_peer = len(ospf_neighbors.keys())
703 no_of_ospf_nbr = 0
701a0192 704 ospf_nbr_list = ospf_data_list["neighbors"]
4256a209 705 no_of_peer = 0
706 for ospf_nbr, nbr_data in ospf_nbr_list.items():
707 if nbr_data:
701a0192 708 data_ip = topo["routers"][nbr_data["nbr"]]["links"]
709 data_rid = topo["routers"][nbr_data["nbr"]]["ospf"]["router_id"]
4256a209 710 else:
701a0192 711 data_ip = topo["routers"][ospf_nbr]["links"]
712 data_rid = topo["routers"][ospf_nbr]["ospf"]["router_id"]
4256a209 713 if ospf_nbr in data_ip:
714 nbr_details = nbr_data[ospf_nbr]
715 elif lan:
701a0192 716 for switch in topo["switches"]:
717 if "ospf" in topo["switches"][switch]["links"][router]:
718 neighbor_ip = data_ip[switch]["ipv4"].split("/")[0]
4256a209 719 else:
720 continue
721 else:
701a0192 722 neighbor_ip = data_ip[router]["ipv4"].split("/")[0]
4256a209 723
724 nh_state = None
725 neighbor_ip = neighbor_ip.lower()
726 nbr_rid = data_rid
727 try:
701a0192 728 nh_state = show_ospf_json[nbr_rid][0]["state"].split("/")[0]
4256a209 729 except KeyError:
701a0192 730 errormsg = "[DUT: {}] OSPF peer {} missing,from " "{} ".format(
731 router, nbr_rid, ospf_nbr
732 )
4256a209 733 return errormsg
734
701a0192 735 if nh_state == "Full":
4256a209 736 no_of_peer += 1
737
738 if no_of_peer == total_peer:
739 logger.info("[DUT: {}] OSPF is Converged".format(router))
740 result = True
741 else:
701a0192 742 errormsg = "[DUT: {}] OSPF is not Converged".format(router)
4256a209 743 return errormsg
744
745 logger.debug("Exiting API: verify_ospf_neighbor()")
746 return result
747
701a0192 748
db56171c 749@retry(retry_timeout=50)
49581587 750def verify_ospf6_neighbor(tgen, topo=None, dut=None, input_dict=None, lan=False):
1feb577c 751 """
752 This API is to verify ospf neighborship by running
2448d002 753 show ipv6 ospf neighbour command,
1feb577c 754
755 Parameters
756 ----------
757 * `tgen` : Topogen object
758 * `topo` : json file data
2448d002 759 * `dut`: device under test
760 * `input_dict` : Input dict data, required when configuring from testcase
761 * `lan` : verify neighbors in lan topology
1feb577c 762
763 Usage
764 -----
2448d002 765 1. To check FULL neighbors.
766 verify_ospf_neighbor(tgen, topo, dut=dut)
1feb577c 767
2448d002 768 2. To check neighbors with their roles.
769 input_dict = {
770 "r0": {
771 "ospf6": {
772 "neighbors": {
773 "r1": {
774 "state": "Full",
775 "role": "DR"
776 },
777 "r2": {
778 "state": "Full",
779 "role": "DROther"
780 },
781 "r3": {
782 "state": "Full",
783 "role": "DROther"
784 }
785 }
786 }
787 }
788 }
789 result = verify_ospf6_neighbor(tgen, topo, dut, input_dict, lan=True)
1feb577c 790
96c715f3 791 3. To check there are no neighbors.
792 input_dict = {
793 "r0": {
794 "ospf6": {
795 "neighbors": []
796 }
797 }
798 }
799 result = verify_ospf6_neighbor(tgen, topo, dut, input_dict)
800
1feb577c 801 Returns
802 -------
803 True or False (Error Message)
804 """
2448d002 805 logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
1feb577c 806 result = False
1feb577c 807
49581587
CH
808 if topo is None:
809 topo = tgen.json_topo
810
2448d002 811 if input_dict:
812 for router, rnode in tgen.routers().items():
db56171c 813 if "ospf6" not in topo["routers"][router]:
2448d002 814 continue
1feb577c 815
2448d002 816 if dut is not None and dut != router:
817 continue
818
819 logger.info("Verifying OSPF neighborship on router %s:", router)
db56171c 820 show_ospf_json = run_frr_cmd(
821 rnode, "show ipv6 ospf neighbor json", isjson=True
822 )
2448d002 823 # Verifying output dictionary show_ospf_json is empty or not
824 if not bool(show_ospf_json):
825 errormsg = "OSPF6 is not running"
826 return errormsg
827
828 ospf_data_list = input_dict[router]["ospf6"]
db56171c 829 ospf_nbr_list = ospf_data_list["neighbors"]
2448d002 830
96c715f3 831 # Check if looking for no neighbors
832 if ospf_nbr_list == []:
833 if show_ospf_json["neighbors"] == []:
834 logger.info("[DUT: {}] OSPF6 no neighbors found".format(router))
835 return True
836 else:
837 errormsg = (
838 "[DUT: {}] OSPF6 active neighbors found, expected None".format(
839 router
840 )
841 )
842 return errormsg
843
2448d002 844 for ospf_nbr, nbr_data in ospf_nbr_list.items():
db56171c 845
846 try:
847 data_ip = data_rid = topo["routers"][ospf_nbr]["ospf6"]["router_id"]
848 except KeyError:
849 data_ip = data_rid = topo["routers"][nbr_data["nbr"]]["ospf6"][
850 "router_id"
851 ]
852
2448d002 853 if ospf_nbr in data_ip:
854 nbr_details = nbr_data[ospf_nbr]
855 elif lan:
db56171c 856 for switch in topo["switches"]:
857 if "ospf6" in topo["switches"][switch]["links"][router]:
2448d002 858 neighbor_ip = data_ip
859 else:
860 continue
861 else:
db56171c 862 neighbor_ip = data_ip[router]["ipv6"].split("/")[0]
2448d002 863
864 nh_state = None
865 neighbor_ip = neighbor_ip.lower()
866 nbr_rid = data_rid
db56171c 867 get_index_val = dict(
868 (d["neighborId"], dict(d, index=index))
869 for (index, d) in enumerate(show_ospf_json["neighbors"])
870 )
2448d002 871 try:
db56171c 872 nh_state = get_index_val.get(neighbor_ip)["state"]
873 intf_state = get_index_val.get(neighbor_ip)["ifState"]
2448d002 874 except TypeError:
db56171c 875 errormsg = "[DUT: {}] OSPF peer {} missing,from " "{} ".format(
876 router, nbr_rid, ospf_nbr
877 )
2448d002 878 return errormsg
879
db56171c 880 nbr_state = nbr_data.setdefault("state", None)
881 nbr_role = nbr_data.setdefault("role", None)
2448d002 882
883 if nbr_state:
884 if nbr_state == nh_state:
db56171c 885 logger.info(
886 "[DUT: {}] OSPF6 Nbr is {}:{} State {}".format(
887 router, ospf_nbr, nbr_rid, nh_state
888 )
889 )
2448d002 890 result = True
891 else:
db56171c 892 errormsg = (
893 "[DUT: {}] OSPF6 is not Converged, neighbor"
894 " state is {} , Expected state is {}".format(
895 router, nh_state, nbr_state
896 )
897 )
2448d002 898 return errormsg
899 if nbr_role:
900 if nbr_role == intf_state:
db56171c 901 logger.info(
902 "[DUT: {}] OSPF6 Nbr is {}: {} Role {}".format(
903 router, ospf_nbr, nbr_rid, nbr_role
904 )
905 )
2448d002 906 else:
db56171c 907 errormsg = (
908 "[DUT: {}] OSPF6 is not Converged with rid"
909 "{}, role is {}, Expected role is {}".format(
910 router, nbr_rid, intf_state, nbr_role
911 )
912 )
2448d002 913 return errormsg
914 continue
915 else:
916
917 for router, rnode in tgen.routers().items():
db56171c 918 if "ospf6" not in topo["routers"][router]:
2448d002 919 continue
920
921 if dut is not None and dut != router:
922 continue
923
924 logger.info("Verifying OSPF6 neighborship on router %s:", router)
db56171c 925 show_ospf_json = run_frr_cmd(
926 rnode, "show ipv6 ospf neighbor json", isjson=True
927 )
2448d002 928 # Verifying output dictionary show_ospf_json is empty or not
929 if not bool(show_ospf_json):
930 errormsg = "OSPF6 is not running"
931 return errormsg
932
933 ospf_data_list = topo["routers"][router]["ospf6"]
db56171c 934 ospf_neighbors = ospf_data_list["neighbors"]
2448d002 935 total_peer = 0
936 total_peer = len(ospf_neighbors.keys())
937 no_of_ospf_nbr = 0
db56171c 938 ospf_nbr_list = ospf_data_list["neighbors"]
2448d002 939 no_of_peer = 0
940 for ospf_nbr, nbr_data in ospf_nbr_list.items():
db56171c 941 try:
942 data_ip = data_rid = topo["routers"][ospf_nbr]["ospf6"]["router_id"]
943 except KeyError:
944 data_ip = data_rid = topo["routers"][nbr_data["nbr"]]["ospf6"][
945 "router_id"
946 ]
947
2448d002 948 if ospf_nbr in data_ip:
949 nbr_details = nbr_data[ospf_nbr]
950 elif lan:
db56171c 951 for switch in topo["switches"]:
952 if "ospf6" in topo["switches"][switch]["links"][router]:
2448d002 953 neighbor_ip = data_ip
954 else:
955 continue
956 else:
957 neighbor_ip = data_ip
958
959 nh_state = None
960 neighbor_ip = neighbor_ip.lower()
961 nbr_rid = data_rid
db56171c 962 get_index_val = dict(
963 (d["neighborId"], dict(d, index=index))
964 for (index, d) in enumerate(show_ospf_json["neighbors"])
965 )
2448d002 966 try:
db56171c 967 nh_state = get_index_val.get(neighbor_ip)["state"]
968 intf_state = get_index_val.get(neighbor_ip)["ifState"]
2448d002 969 except TypeError:
db56171c 970 errormsg = "[DUT: {}] OSPF peer {} missing,from " "{} ".format(
971 router, nbr_rid, ospf_nbr
972 )
2448d002 973 return errormsg
1feb577c 974
db56171c 975 if nh_state == "Full":
2448d002 976 no_of_peer += 1
1feb577c 977
2448d002 978 if no_of_peer == total_peer:
979 logger.info("[DUT: {}] OSPF6 is Converged".format(router))
980 result = True
981 else:
db56171c 982 errormsg = "[DUT: {}] OSPF6 is not Converged".format(router)
2448d002 983 return errormsg
1feb577c 984
2448d002 985 logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
1feb577c 986 return result
987
988
ed776e38 989@retry(retry_timeout=40)
701a0192 990def verify_ospf_rib(
3c41ebf8 991 tgen, dut, input_dict, next_hop=None, tag=None, metric=None, fib=None, expected=True
701a0192 992):
4256a209 993 """
994 This API is to verify ospf routes by running
995 show ip ospf route command.
996
997 Parameters
998 ----------
999 * `tgen` : Topogen object
1000 * `dut`: device under test
1001 * `input_dict` : Input dict data, required when configuring from testcase
1002 * `next_hop` : next to be verified
1003 * `tag` : tag to be verified
1004 * `metric` : metric to be verified
1005 * `fib` : True if the route is installed in FIB.
3c41ebf8 1006 * `expected` : expected results from API, by-default True
4256a209 1007
1008 Usage
1009 -----
1010 input_dict = {
1011 "r1": {
1012 "static_routes": [
1013 {
1014 "network": ip_net,
1015 "no_of_ip": 1,
1016 "routeType": "N"
1017 }
1018 ]
1019 }
1020 }
1021
1022 result = verify_ospf_rib(tgen, dut, input_dict,next_hop=nh)
1023
1024 Returns
1025 -------
1026 True or False (Error Message)
1027 """
1028
1029 logger.info("Entering lib API: verify_ospf_rib()")
1030 result = False
1031 router_list = tgen.routers()
1032 additional_nexthops_in_required_nhs = []
1033 found_hops = []
1034 for routerInput in input_dict.keys():
11761ab0 1035 for router, rnode in router_list.items():
4256a209 1036 if router != dut:
1037 continue
1038
1039 logger.info("Checking router %s RIB:", router)
1040
1041 # Verifying RIB routes
1042 command = "show ip ospf route"
1043
1044 found_routes = []
1045 missing_routes = []
1046
701a0192 1047 if (
1048 "static_routes" in input_dict[routerInput]
1049 or "prefix" in input_dict[routerInput]
1050 ):
4256a209 1051 if "prefix" in input_dict[routerInput]:
1052 static_routes = input_dict[routerInput]["prefix"]
1053 else:
1054 static_routes = input_dict[routerInput]["static_routes"]
1055
4256a209 1056 for static_route in static_routes:
1057 cmd = "{}".format(command)
1058
1059 cmd = "{} json".format(cmd)
1060
701a0192 1061 ospf_rib_json = run_frr_cmd(rnode, cmd, isjson=True)
4256a209 1062
1063 # Verifying output dictionary ospf_rib_json is not empty
1064 if bool(ospf_rib_json) is False:
701a0192 1065 errormsg = (
1066 "[DUT: {}] No routes found in OSPF route "
4256a209 1067 "table".format(router)
701a0192 1068 )
4256a209 1069 return errormsg
1070
1071 network = static_route["network"]
1072 no_of_ip = static_route.setdefault("no_of_ip", 1)
1073 _tag = static_route.setdefault("tag", None)
1074 _rtype = static_route.setdefault("routeType", None)
1075
4256a209 1076 # Generating IPs for verification
1077 ip_list = generate_ips(network, no_of_ip)
1078 st_found = False
1079 nh_found = False
1080
1081 for st_rt in ip_list:
c8e5983d 1082 st_rt = str(ipaddress.ip_network(frr_unicode(st_rt)))
4256a209 1083
1084 _addr_type = validate_ip_address(st_rt)
701a0192 1085 if _addr_type != "ipv4":
4256a209 1086 continue
1087
1088 if st_rt in ospf_rib_json:
1089 st_found = True
1090 found_routes.append(st_rt)
1091
1092 if fib and next_hop:
1093 if type(next_hop) is not list:
1094 next_hop = [next_hop]
1095
1096 for mnh in range(0, len(ospf_rib_json[st_rt])):
701a0192 1097 if (
1098 "fib"
1099 in ospf_rib_json[st_rt][mnh]["nexthops"][0]
1100 ):
1101 found_hops.append(
1102 [
1103 rib_r["ip"]
1104 for rib_r in ospf_rib_json[st_rt][mnh][
1105 "nexthops"
1106 ]
1107 ]
1108 )
4256a209 1109
1110 if found_hops[0]:
701a0192 1111 missing_list_of_nexthops = set(
1112 found_hops[0]
1113 ).difference(next_hop)
1114 additional_nexthops_in_required_nhs = set(
1115 next_hop
1116 ).difference(found_hops[0])
4256a209 1117
1118 if additional_nexthops_in_required_nhs:
1119 logger.info(
1120 "Nexthop "
1121 "%s is not active for route %s in "
1122 "RIB of router %s\n",
1123 additional_nexthops_in_required_nhs,
701a0192 1124 st_rt,
1125 dut,
1126 )
4256a209 1127 errormsg = (
1128 "Nexthop {} is not active"
1129 " for route {} in RIB of router"
1130 " {}\n".format(
701a0192 1131 additional_nexthops_in_required_nhs,
1132 st_rt,
1133 dut,
1134 )
1135 )
4256a209 1136 return errormsg
1137 else:
1138 nh_found = True
1139
1140 elif next_hop and fib is None:
1141 if type(next_hop) is not list:
1142 next_hop = [next_hop]
701a0192 1143 found_hops = [
1144 rib_r["ip"]
1145 for rib_r in ospf_rib_json[st_rt]["nexthops"]
1146 ]
4256a209 1147
1148 if found_hops:
701a0192 1149 missing_list_of_nexthops = set(
1150 found_hops
1151 ).difference(next_hop)
1152 additional_nexthops_in_required_nhs = set(
1153 next_hop
1154 ).difference(found_hops)
4256a209 1155
1156 if additional_nexthops_in_required_nhs:
1157 logger.info(
701a0192 1158 "Missing nexthop %s for route"
1159 " %s in RIB of router %s\n",
4256a209 1160 additional_nexthops_in_required_nhs,
701a0192 1161 st_rt,
1162 dut,
1163 )
1164 errormsg = (
1165 "Nexthop {} is Missing for "
1166 "route {} in RIB of router {}\n".format(
1167 additional_nexthops_in_required_nhs,
1168 st_rt,
1169 dut,
1170 )
1171 )
4256a209 1172 return errormsg
1173 else:
1174 nh_found = True
1175 if _rtype:
701a0192 1176 if "routeType" not in ospf_rib_json[st_rt]:
1177 errormsg = (
1178 "[DUT: {}]: routeType missing"
9458be1a 1179 " for route {} in OSPF RIB \n".format(
1180 dut, st_rt
1181 )
701a0192 1182 )
4256a209 1183 return errormsg
701a0192 1184 elif _rtype != ospf_rib_json[st_rt]["routeType"]:
1185 errormsg = (
1186 "[DUT: {}]: routeType mismatch"
9458be1a 1187 " for route {} in OSPF RIB \n".format(
1188 dut, st_rt
1189 )
701a0192 1190 )
4256a209 1191 return errormsg
1192 else:
701a0192 1193 logger.info(
9458be1a 1194 "[DUT: {}]: Found routeType {}"
1195 " for route {}".format(dut, _rtype, st_rt)
701a0192 1196 )
4256a209 1197 if tag:
701a0192 1198 if "tag" not in ospf_rib_json[st_rt]:
1199 errormsg = (
1200 "[DUT: {}]: tag is not"
1201 " present for"
1202 " route {} in RIB \n".format(dut, st_rt)
1203 )
4256a209 1204 return errormsg
1205
701a0192 1206 if _tag != ospf_rib_json[st_rt]["tag"]:
1207 errormsg = (
1208 "[DUT: {}]: tag value {}"
1209 " is not matched for"
9fa6ec14 1210 " route {} in RIB \n".format(
1211 dut,
1212 _tag,
1213 st_rt,
1214 )
701a0192 1215 )
4256a209 1216 return errormsg
1217
1218 if metric is not None:
701a0192 1219 if "type2cost" not in ospf_rib_json[st_rt]:
1220 errormsg = (
1221 "[DUT: {}]: metric is"
1222 " not present for"
1223 " route {} in RIB \n".format(dut, st_rt)
1224 )
4256a209 1225 return errormsg
1226
701a0192 1227 if metric != ospf_rib_json[st_rt]["type2cost"]:
1228 errormsg = (
1229 "[DUT: {}]: metric value "
1230 "{} is not matched for "
9fa6ec14 1231 "route {} in RIB \n".format(
1232 dut,
1233 metric,
1234 st_rt,
1235 )
701a0192 1236 )
4256a209 1237 return errormsg
1238
1239 else:
1240 missing_routes.append(st_rt)
1241
1242 if nh_found:
701a0192 1243 logger.info(
1244 "[DUT: {}]: Found next_hop {} for all OSPF"
1245 " routes in RIB".format(router, next_hop)
1246 )
4256a209 1247
1248 if len(missing_routes) > 0:
701a0192 1249 errormsg = "[DUT: {}]: Missing route in RIB, " "routes: {}".format(
1250 dut, missing_routes
1251 )
4256a209 1252 return errormsg
1253
1254 if found_routes:
701a0192 1255 logger.info(
1256 "[DUT: %s]: Verified routes in RIB, found" " routes are: %s\n",
1257 dut,
1258 found_routes,
1259 )
4256a209 1260 result = True
1261
1262 logger.info("Exiting lib API: verify_ospf_rib()")
1263 return result
1264
1265
ed776e38 1266@retry(retry_timeout=20)
a53c08bc
CH
1267def verify_ospf_interface(
1268 tgen, topo=None, dut=None, lan=False, input_dict=None, expected=True
1269):
4256a209 1270 """
1271 This API is to verify ospf routes by running
1272 show ip ospf interface command.
1273
1274 Parameters
1275 ----------
1276 * `tgen` : Topogen object
1277 * `topo` : topology descriptions
1278 * `dut`: device under test
1279 * `lan`: if set to true this interface belongs to LAN.
1280 * `input_dict` : Input dict data, required when configuring from testcase
3c41ebf8 1281 * `expected` : expected results from API, by-default True
4256a209 1282
1283 Usage
1284 -----
1285 input_dict= {
1286 'r0': {
1287 'links':{
1288 's1': {
1289 'ospf':{
1290 'priority':98,
1291 'timerDeadSecs': 4,
1292 'area': '0.0.0.3',
1293 'mcastMemberOspfDesignatedRouters': True,
1294 'mcastMemberOspfAllRouters': True,
1295 'ospfEnabled': True,
1296
1297 }
1298 }
1299 }
1300 }
1301 }
1302 result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
1303
1304 Returns
1305 -------
1306 True or False (Error Message)
1307 """
1308
1309 logger.debug("Entering lib API: verify_ospf_interface()")
1310 result = False
49581587
CH
1311 if topo is None:
1312 topo = tgen.json_topo
1313
11761ab0 1314 for router, rnode in tgen.routers().items():
701a0192 1315 if "ospf" not in topo["routers"][router]:
4256a209 1316 continue
1317
1318 if dut is not None and dut != router:
1319 continue
1320
1321 logger.info("Verifying OSPF interface on router %s:", router)
701a0192 1322 show_ospf_json = run_frr_cmd(rnode, "show ip ospf interface json", isjson=True)
4256a209 1323
1324 # Verifying output dictionary show_ospf_json is empty or not
1325 if not bool(show_ospf_json):
1326 errormsg = "OSPF is not running"
1327 return errormsg
1328
1329 # To find neighbor ip type
1330 ospf_intf_data = input_dict[router]["links"]
1331 for ospf_intf, intf_data in ospf_intf_data.items():
701a0192 1332 intf = topo["routers"][router]["links"][ospf_intf]["interface"]
1333 if intf in show_ospf_json["interfaces"]:
1334 for intf_attribute in intf_data["ospf"]:
1335 if (
1336 intf_data["ospf"][intf_attribute]
1337 == show_ospf_json["interfaces"][intf][intf_attribute]
1338 ):
1339 logger.info(
1340 "[DUT: %s] OSPF interface %s: %s is %s",
1341 router,
1342 intf,
1343 intf_attribute,
1344 intf_data["ospf"][intf_attribute],
1345 )
4256a209 1346 else:
701a0192 1347 errormsg = "[DUT: {}] OSPF interface {}: {} is {}, \
1348 Expected is {}".format(
1349 router,
1350 intf,
1351 intf_attribute,
1352 intf_data["ospf"][intf_attribute],
1353 show_ospf_json["interfaces"][intf][intf_attribute],
1354 )
4256a209 1355 return errormsg
1356 result = True
1357 logger.debug("Exiting API: verify_ospf_interface()")
1358 return result
1359
1360
044561b1
MN
1361@retry(retry_timeout=40)
1362def verify_ospf_database(
1363 tgen, topo, dut, input_dict, vrf=None, lsatype=None, rid=None, expected=True
1364):
4256a209 1365 """
1366 This API is to verify ospf lsa's by running
1367 show ip ospf database command.
1368
1369 Parameters
1370 ----------
1371 * `tgen` : Topogen object
1372 * `dut`: device under test
1373 * `input_dict` : Input dict data, required when configuring from testcase
1374 * `topo` : next to be verified
3c41ebf8 1375 * `expected` : expected results from API, by-default True
4256a209 1376
1377 Usage
1378 -----
1379 input_dict = {
1380 "areas": {
1381 "0.0.0.0": {
1382 "Router Link States": {
1383 "100.1.1.0-100.1.1.0": {
1384 "LSID": "100.1.1.0",
1385 "Advertised router": "100.1.1.0",
1386 "LSA Age": 130,
1387 "Sequence Number": "80000006",
1388 "Checksum": "a703",
1389 "Router links": 3
1390 }
1391 },
1392 "Net Link States": {
1393 "10.0.0.2-100.1.1.1": {
1394 "LSID": "10.0.0.2",
1395 "Advertised router": "100.1.1.1",
1396 "LSA Age": 137,
1397 "Sequence Number": "80000001",
1398 "Checksum": "9583"
1399 }
1400 },
1401 },
1402 }
1403 }
1404 result = verify_ospf_database(tgen, topo, dut, input_dict)
1405
1406 Returns
1407 -------
1408 True or False (Error Message)
1409 """
1410
1411 result = False
1412 router = dut
1413 logger.debug("Entering lib API: verify_ospf_database()")
1414
701a0192 1415 if "ospf" not in topo["routers"][dut]:
1416 errormsg = "[DUT: {}] OSPF is not configured on the router.".format(dut)
4256a209 1417 return errormsg
1418
1419 rnode = tgen.routers()[dut]
1420
1421 logger.info("Verifying OSPF interface on router %s:", dut)
044561b1
MN
1422
1423 if not rid:
1424 rid = "self-originate"
1425 if lsatype:
1426 if vrf is None:
1427 command = "show ip ospf database {} {} json".format(lsatype, rid)
1428 else:
1429 command = "show ip ospf database {} {} vrf {} json".format(
1430 lsatype, rid, vrf
1431 )
1432 else:
1433 if vrf is None:
1434 command = "show ip ospf database json"
1435 else:
1436 command = "show ip ospf database vrf {} json".format(vrf)
1437
1438 show_ospf_json = run_frr_cmd(rnode, command, isjson=True)
4256a209 1439 # Verifying output dictionary show_ospf_json is empty or not
1440 if not bool(show_ospf_json):
1441 errormsg = "OSPF is not running"
1442 return errormsg
1443
1444 # for inter and inter lsa's
1445 ospf_db_data = input_dict.setdefault("areas", None)
701a0192 1446 ospf_external_lsa = input_dict.setdefault("AS External Link States", None)
044561b1 1447 # import pdb; pdb.set_trace()
4256a209 1448 if ospf_db_data:
701a0192 1449 for ospf_area, area_lsa in ospf_db_data.items():
044561b1
MN
1450 if ospf_area in show_ospf_json["routerLinkStates"]["areas"]:
1451 if "routerLinkStates" in area_lsa:
1452 for lsa in area_lsa["routerLinkStates"]:
1453 _advrtr = lsa.setdefault("advertisedRouter", None)
1454 _options = lsa.setdefault("options", None)
1455
701a0192 1456 if (
044561b1
MN
1457 _options
1458 and lsa["lsaId"]
1459 == show_ospf_json["routerLinkStates"]["areas"][ospf_area][
1460 0
1461 ]["linkStateId"]
1462 and lsa["options"]
1463 == show_ospf_json["routerLinkStates"]["areas"][ospf_area][
1464 0
1465 ]["options"]
701a0192 1466 ):
701a0192 1467 result = True
044561b1 1468 break
701a0192 1469 else:
044561b1
MN
1470 errormsg = '[DUT: {}] OSPF LSA options: expected {}, Received Options are {} lsa["options"] {} OSPF LSAID: expected lsaid {}, Received lsaid {}'.format(
1471 dut,
1472 show_ospf_json["routerLinkStates"]["areas"][ospf_area][
1473 0
1474 ]["options"],
1475 _options,
1476 lsa["options"],
1477 show_ospf_json["routerLinkStates"]["areas"][ospf_area][
1478 0
1479 ]["linkStateId"],
1480 lsa["lsaId"],
701a0192 1481 )
1482 return errormsg
1483 if "Net Link States" in area_lsa:
1484 for lsa in area_lsa["Net Link States"]:
1485 if lsa in show_ospf_json["areas"][ospf_area]["Net Link States"]:
1486 logger.info(
1487 "[DUT: %s] OSPF LSDB area %s:Network " "LSA %s",
1488 router,
1489 ospf_area,
1490 lsa,
1491 )
1492 result = True
1493 else:
1494 errormsg = (
1495 "[DUT: {}] OSPF LSDB area {}: expected"
4256a209 1496 " Network LSA is {}".format(router, ospf_area, lsa)
701a0192 1497 )
1498 return errormsg
1499 if "Summary Link States" in area_lsa:
1500 for lsa in area_lsa["Summary Link States"]:
1501 if (
1502 lsa
1503 in show_ospf_json["areas"][ospf_area]["Summary Link States"]
1504 ):
1505 logger.info(
1506 "[DUT: %s] OSPF LSDB area %s:Summary " "LSA %s",
1507 router,
1508 ospf_area,
1509 lsa,
1510 )
1511 result = True
1512 else:
1513 errormsg = (
1514 "[DUT: {}] OSPF LSDB area {}: expected"
4256a209 1515 " Summary LSA is {}".format(router, ospf_area, lsa)
701a0192 1516 )
1517 return errormsg
1518 if "ASBR-Summary Link States" in area_lsa:
1519 for lsa in area_lsa["ASBR-Summary Link States"]:
1520 if (
1521 lsa
1522 in show_ospf_json["areas"][ospf_area][
1523 "ASBR-Summary Link States"
1524 ]
1525 ):
1526 logger.info(
1527 "[DUT: %s] OSPF LSDB area %s:ASBR Summary " "LSA %s",
1528 router,
1529 ospf_area,
1530 lsa,
1531 )
1532 result = True
1533 else:
1534 errormsg = (
1535 "[DUT: {}] OSPF LSDB area {}: expected"
1536 " ASBR Summary LSA is {}".format(router, ospf_area, lsa)
1537 )
1538 return errormsg
4256a209 1539 if ospf_external_lsa:
701a0192 1540 for ospf_ext_lsa, ext_lsa_data in ospf_external_lsa.items():
1541 if ospf_ext_lsa in show_ospf_json["AS External Link States"]:
1542 logger.info(
1543 "[DUT: %s] OSPF LSDB:External LSA %s", router, ospf_ext_lsa
1544 )
1545 result = True
1546 else:
1547 errormsg = (
1548 "[DUT: {}] OSPF LSDB : expected"
1549 " External LSA is {}".format(router, ospf_ext_lsa)
1550 )
1551 return errormsg
4256a209 1552
1553 logger.debug("Exiting API: verify_ospf_database()")
1554 return result
1555
1556
ed776e38 1557@retry(retry_timeout=20)
8a86be27 1558def verify_ospf_summary(tgen, topo, dut, input_dict, ospf=None, expected=True):
4256a209 1559 """
1560 This API is to verify ospf routes by running
1561 show ip ospf interface command.
1562
1563 Parameters
1564 ----------
1565 * `tgen` : Topogen object
1566 * `topo` : topology descriptions
1567 * `dut`: device under test
1568 * `input_dict` : Input dict data, required when configuring from testcase
1569
1570 Usage
1571 -----
1572 input_dict = {
1573 "11.0.0.0/8": {
f932966b
DA
1574 "summaryAddress": "11.0.0.0/8",
1575 "metricType": "E2",
1576 "metric": 20,
1577 "tag": 0,
1578 "externalRouteCount": 5
4256a209 1579 }
1580 }
1581 result = verify_ospf_summary(tgen, topo, dut, input_dict)
1582
1583 Returns
1584 -------
1585 True or False (Error Message)
1586 """
1587
8a86be27 1588 logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
4256a209 1589 result = False
1590 router = dut
1591
1592 logger.info("Verifying OSPF summary on router %s:", router)
1593
4256a209 1594 rnode = tgen.routers()[dut]
8a86be27
MR
1595
1596 if ospf:
a53c08bc
CH
1597 if "ospf6" not in topo["routers"][dut]:
1598 errormsg = "[DUT: {}] OSPF6 is not configured on the router.".format(router)
8a86be27
MR
1599 return errormsg
1600
a53c08bc
CH
1601 show_ospf_json = run_frr_cmd(
1602 rnode, "show ipv6 ospf summary detail json", isjson=True
1603 )
8a86be27 1604 else:
a53c08bc
CH
1605 if "ospf" not in topo["routers"][dut]:
1606 errormsg = "[DUT: {}] OSPF is not configured on the router.".format(router)
8a86be27
MR
1607 return errormsg
1608
a53c08bc
CH
1609 show_ospf_json = run_frr_cmd(
1610 rnode, "show ip ospf summary detail json", isjson=True
1611 )
4256a209 1612
1613 # Verifying output dictionary show_ospf_json is empty or not
1614 if not bool(show_ospf_json):
1615 errormsg = "OSPF is not running"
1616 return errormsg
1617
1618 # To find neighbor ip type
1619 ospf_summary_data = input_dict
8a86be27
MR
1620
1621 if ospf:
a53c08bc 1622 show_ospf_json = show_ospf_json["default"]
8a86be27 1623
4256a209 1624 for ospf_summ, summ_data in ospf_summary_data.items():
1625 if ospf_summ not in show_ospf_json:
1626 continue
f932966b 1627 summary = ospf_summary_data[ospf_summ]["summaryAddress"]
8a86be27 1628
4256a209 1629 if summary in show_ospf_json:
1630 for summ in summ_data:
1631 if summ_data[summ] == show_ospf_json[summary][summ]:
a53c08bc
CH
1632 logger.info(
1633 "[DUT: %s] OSPF summary %s:%s is %s",
1634 router,
1635 summary,
1636 summ,
1637 summ_data[summ],
1638 )
4256a209 1639 result = True
1640 else:
a53c08bc
CH
1641 errormsg = (
1642 "[DUT: {}] OSPF summary {} : {} is {}, "
1643 "Expected is {}".format(
1644 router,
1645 summary,
1646 summ,
1647 show_ospf_json[summary][summ],
1648 summ_data[summ],
1649 )
1650 )
4256a209 1651 return errormsg
1652
8a86be27 1653 logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
4256a209 1654 return result
2448d002 1655
1656
ed776e38 1657@retry(retry_timeout=30)
a53c08bc
CH
1658def verify_ospf6_rib(
1659 tgen, dut, input_dict, next_hop=None, tag=None, metric=None, fib=None
1660):
2448d002 1661 """
1662 This API is to verify ospf routes by running
1663 show ip ospf route command.
1664
1665 Parameters
1666 ----------
1667 * `tgen` : Topogen object
1668 * `dut`: device under test
1669 * `input_dict` : Input dict data, required when configuring from testcase
1670 * `next_hop` : next to be verified
1671 * `tag` : tag to be verified
1672 * `metric` : metric to be verified
1673 * `fib` : True if the route is installed in FIB.
1674
1675 Usage
1676 -----
1677 input_dict = {
1678 "r1": {
1679 "static_routes": [
1680 {
1681 "network": ip_net,
1682 "no_of_ip": 1,
1683 "routeType": "N"
1684 }
1685 ]
1686 }
1687 }
1688
1689 result = verify_ospf6_rib(tgen, dut, input_dict,next_hop=nh)
1690
1691 Returns
1692 -------
1693 True or False (Error Message)
1694 """
1695
1696 logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
1697 result = False
1698 router_list = tgen.routers()
1699 additional_nexthops_in_required_nhs = []
1700 found_hops = []
1701 for routerInput in input_dict.keys():
c8e5983d 1702 for router, rnode in router_list.items():
2448d002 1703 if router != dut:
1704 continue
1705
1706 logger.info("Checking router %s RIB:", router)
1707
1708 # Verifying RIB routes
d1b5fa5b 1709 command = "show ipv6 ospf route detail"
2448d002 1710
1711 found_routes = []
1712 missing_routes = []
1713
db56171c 1714 if (
1715 "static_routes" in input_dict[routerInput]
1716 or "prefix" in input_dict[routerInput]
1717 ):
2448d002 1718 if "prefix" in input_dict[routerInput]:
1719 static_routes = input_dict[routerInput]["prefix"]
1720 else:
1721 static_routes = input_dict[routerInput]["static_routes"]
1722
2448d002 1723 for static_route in static_routes:
1724 cmd = "{}".format(command)
1725
1726 cmd = "{} json".format(cmd)
1727
db56171c 1728 ospf_rib_json = run_frr_cmd(rnode, cmd, isjson=True)
2448d002 1729
1730 # Fix for PR 2644182
1731 try:
db56171c 1732 ospf_rib_json = ospf_rib_json["routes"]
2448d002 1733 except KeyError:
1734 pass
1735
1736 # Verifying output dictionary ospf_rib_json is not empty
1737 if bool(ospf_rib_json) is False:
db56171c 1738 errormsg = (
1739 "[DUT: {}] No routes found in OSPF6 route "
2448d002 1740 "table".format(router)
db56171c 1741 )
2448d002 1742 return errormsg
1743
1744 network = static_route["network"]
1745 no_of_ip = static_route.setdefault("no_of_ip", 1)
1746 _tag = static_route.setdefault("tag", None)
1747 _rtype = static_route.setdefault("routeType", None)
1748
2448d002 1749 # Generating IPs for verification
1750 ip_list = generate_ips(network, no_of_ip)
d1b5fa5b 1751 if len(ip_list) == 1:
1752 ip_list = [network]
2448d002 1753 st_found = False
1754 nh_found = False
1755 for st_rt in ip_list:
1756 st_rt = str(ipaddress.ip_network(frr_unicode(st_rt)))
1757
1758 _addr_type = validate_ip_address(st_rt)
db56171c 1759 if _addr_type != "ipv6":
2448d002 1760 continue
1761
1762 if st_rt in ospf_rib_json:
1763
1764 st_found = True
1765 found_routes.append(st_rt)
1766
1767 if fib and next_hop:
1768 if type(next_hop) is not list:
1769 next_hop = [next_hop]
1770
1771 for mnh in range(0, len(ospf_rib_json[st_rt])):
db56171c 1772 if (
1773 "fib"
1774 in ospf_rib_json[st_rt][mnh]["nextHops"][0]
1775 ):
1776 found_hops.append(
1777 [
1778 rib_r["ip"]
1779 for rib_r in ospf_rib_json[st_rt][mnh][
1780 "nextHops"
1781 ]
1782 ]
1783 )
2448d002 1784
1785 if found_hops[0]:
db56171c 1786 missing_list_of_nexthops = set(
1787 found_hops[0]
1788 ).difference(next_hop)
1789 additional_nexthops_in_required_nhs = set(
1790 next_hop
1791 ).difference(found_hops[0])
2448d002 1792
1793 if additional_nexthops_in_required_nhs:
1794 logger.info(
1795 "Nexthop "
1796 "%s is not active for route %s in "
1797 "RIB of router %s\n",
1798 additional_nexthops_in_required_nhs,
db56171c 1799 st_rt,
1800 dut,
1801 )
2448d002 1802 errormsg = (
1803 "Nexthop {} is not active"
1804 " for route {} in RIB of router"
1805 " {}\n".format(
db56171c 1806 additional_nexthops_in_required_nhs,
1807 st_rt,
1808 dut,
1809 )
1810 )
2448d002 1811 return errormsg
1812 else:
1813 nh_found = True
1814
1815 elif next_hop and fib is None:
1816 if type(next_hop) is not list:
1817 next_hop = [next_hop]
db56171c 1818 found_hops = [
1819 rib_r["nextHop"]
1820 for rib_r in ospf_rib_json[st_rt]["nextHops"]
1821 ]
2448d002 1822
1823 if found_hops:
db56171c 1824 missing_list_of_nexthops = set(
1825 found_hops
1826 ).difference(next_hop)
1827 additional_nexthops_in_required_nhs = set(
1828 next_hop
1829 ).difference(found_hops)
2448d002 1830 if additional_nexthops_in_required_nhs:
1831 logger.info(
db56171c 1832 "Missing nexthop %s for route"
1833 " %s in RIB of router %s\n",
2448d002 1834 additional_nexthops_in_required_nhs,
db56171c 1835 st_rt,
1836 dut,
1837 )
1838 errormsg = (
1839 "Nexthop {} is Missing for "
1840 "route {} in RIB of router {}\n".format(
1841 additional_nexthops_in_required_nhs,
1842 st_rt,
1843 dut,
1844 )
1845 )
2448d002 1846 return errormsg
1847 else:
1848 nh_found = True
1849 if _rtype:
db56171c 1850 if "destinationType" not in ospf_rib_json[st_rt]:
1851 errormsg = (
1852 "[DUT: {}]: destinationType missing"
1853 "for route {} in OSPF RIB \n".format(dut, st_rt)
1854 )
2448d002 1855 return errormsg
db56171c 1856 elif _rtype != ospf_rib_json[st_rt]["destinationType"]:
1857 errormsg = (
1858 "[DUT: {}]: destinationType mismatch"
1859 "for route {} in OSPF RIB \n".format(dut, st_rt)
1860 )
2448d002 1861 return errormsg
1862 else:
db56171c 1863 logger.info(
1864 "DUT: {}]: Found destinationType {}"
1865 "for route {}".format(dut, _rtype, st_rt)
1866 )
2448d002 1867 if tag:
db56171c 1868 if "tag" not in ospf_rib_json[st_rt]:
1869 errormsg = (
1870 "[DUT: {}]: tag is not"
1871 " present for"
1872 " route {} in RIB \n".format(dut, st_rt)
1873 )
2448d002 1874 return errormsg
1875
db56171c 1876 if _tag != ospf_rib_json[st_rt]["tag"]:
1877 errormsg = (
1878 "[DUT: {}]: tag value {}"
1879 " is not matched for"
1880 " route {} in RIB \n".format(
1881 dut,
1882 _tag,
1883 st_rt,
1884 )
1885 )
2448d002 1886 return errormsg
1887
1888 if metric is not None:
d1b5fa5b 1889 if "metricCostE2" not in ospf_rib_json[st_rt]:
db56171c 1890 errormsg = (
1891 "[DUT: {}]: metric is"
1892 " not present for"
1893 " route {} in RIB \n".format(dut, st_rt)
1894 )
2448d002 1895 return errormsg
1896
d1b5fa5b 1897 if metric != ospf_rib_json[st_rt]["metricCostE2"]:
db56171c 1898 errormsg = (
1899 "[DUT: {}]: metric value "
1900 "{} is not matched for "
1901 "route {} in RIB \n".format(
1902 dut,
1903 metric,
1904 st_rt,
1905 )
1906 )
2448d002 1907 return errormsg
1908
1909 else:
1910 missing_routes.append(st_rt)
1911
1912 if nh_found:
db56171c 1913 logger.info(
1914 "[DUT: {}]: Found next_hop {} for all OSPF"
1915 " routes in RIB".format(router, next_hop)
1916 )
2448d002 1917
1918 if len(missing_routes) > 0:
db56171c 1919 errormsg = "[DUT: {}]: Missing route in RIB, " "routes: {}".format(
1920 dut, missing_routes
1921 )
2448d002 1922 return errormsg
1923
1924 if found_routes:
db56171c 1925 logger.info(
1926 "[DUT: %s]: Verified routes in RIB, found" " routes are: %s\n",
1927 dut,
1928 found_routes,
1929 )
2448d002 1930 result = True
1931
1932 logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
1933 return result
1934
1935
ed776e38 1936@retry(retry_timeout=6)
a53c08bc 1937def verify_ospf6_interface(tgen, topo=None, dut=None, lan=False, input_dict=None):
2448d002 1938 """
1939 This API is to verify ospf routes by running
1940 show ip ospf interface command.
1941
1942 Parameters
1943 ----------
1944 * `tgen` : Topogen object
1945 * `topo` : topology descriptions
1946 * `dut`: device under test
1947 * `lan`: if set to true this interface belongs to LAN.
1948 * `input_dict` : Input dict data, required when configuring from testcase
1949
1950 Usage
1951 -----
1952 input_dict= {
1953 'r0': {
1954 'links':{
1955 's1': {
1956 'ospf6':{
1957 'priority':98,
1958 'timerDeadSecs': 4,
1959 'area': '0.0.0.3',
1960 'mcastMemberOspfDesignatedRouters': True,
1961 'mcastMemberOspfAllRouters': True,
1962 'ospfEnabled': True,
1963
1964 }
1965 }
1966 }
1967 }
1968 }
1969 result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
1970
1971 Returns
1972 -------
1973 True or False (Error Message)
1974 """
1975
0afa6453 1976 logger.debug("Entering lib API: verify_ospf6_interface")
2448d002 1977 result = False
1978
49581587
CH
1979 if topo is None:
1980 topo = tgen.json_topo
1981
1982 for router, rnode in tgen.routers().items():
a53c08bc 1983 if "ospf6" not in topo["routers"][router]:
2448d002 1984 continue
1985
1986 if dut is not None and dut != router:
1987 continue
1988
1989 logger.info("Verifying OSPF interface on router %s:", router)
db56171c 1990 show_ospf_json = run_frr_cmd(
1991 rnode, "show ipv6 ospf interface json", isjson=True
1992 )
2448d002 1993
1994 # Verifying output dictionary show_ospf_json is empty or not
1995 if not bool(show_ospf_json):
1996 errormsg = "OSPF6 is not running"
1997 return errormsg
1998
1999 # To find neighbor ip type
2000 ospf_intf_data = input_dict[router]["links"]
2001 for ospf_intf, intf_data in ospf_intf_data.items():
db56171c 2002 intf = topo["routers"][router]["links"][ospf_intf]["interface"]
2003 if intf in show_ospf_json:
2004 for intf_attribute in intf_data["ospf6"]:
2005 if intf_data["ospf6"][intf_attribute] is not list:
2006 if (
2007 intf_data["ospf6"][intf_attribute]
2008 == show_ospf_json[intf][intf_attribute]
2009 ):
2010 logger.info(
2011 "[DUT: %s] OSPF6 interface %s: %s is %s",
2012 router,
2013 intf,
2014 intf_attribute,
2015 intf_data["ospf6"][intf_attribute],
2016 )
2017 elif intf_data["ospf6"][intf_attribute] is list:
2448d002 2018 for addr_list in len(show_ospf_json[intf][intf_attribute]):
db56171c 2019 if (
2020 show_ospf_json[intf][intf_attribute][addr_list][
2021 "address"
2022 ].split("/")[0]
2023 == intf_data["ospf6"]["internetAddress"][0]["address"]
2024 ):
2025 break
2448d002 2026 else:
db56171c 2027 errormsg = "[DUT: {}] OSPF6 interface {}: {} is {}, \
2028 Expected is {}".format(
2029 router,
2030 intf,
2031 intf_attribute,
2032 intf_data["ospf6"][intf_attribute],
2033 intf_data["ospf6"][intf_attribute],
2034 )
2448d002 2035 return errormsg
2036 else:
db56171c 2037 errormsg = "[DUT: {}] OSPF6 interface {}: {} is {}, \
2038 Expected is {}".format(
2039 router,
2040 intf,
2041 intf_attribute,
2042 intf_data["ospf6"][intf_attribute],
2043 intf_data["ospf6"][intf_attribute],
2044 )
2448d002 2045 return errormsg
2046 result = True
2047 logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
2048 return result
2049
2050
ed776e38 2051@retry(retry_timeout=20)
2448d002 2052def verify_ospf6_database(tgen, topo, dut, input_dict):
2053 """
2054 This API is to verify ospf lsa's by running
2055 show ip ospf database command.
2056
2057 Parameters
2058 ----------
2059 * `tgen` : Topogen object
2060 * `dut`: device under test
2061 * `input_dict` : Input dict data, required when configuring from testcase
2062 * `topo` : next to be verified
2063
2064 Usage
2065 -----
2066 input_dict = {
2067 "areas": {
2068 "0.0.0.0": {
2069 "routerLinkStates": {
2070 "100.1.1.0-100.1.1.0": {
2071 "LSID": "100.1.1.0",
2072 "Advertised router": "100.1.1.0",
2073 "LSA Age": 130,
2074 "Sequence Number": "80000006",
2075 "Checksum": "a703",
2076 "Router links": 3
2077 }
2078 },
2079 "networkLinkStates": {
2080 "10.0.0.2-100.1.1.1": {
2081 "LSID": "10.0.0.2",
2082 "Advertised router": "100.1.1.1",
2083 "LSA Age": 137,
2084 "Sequence Number": "80000001",
2085 "Checksum": "9583"
2086 }
2087 },
2088 },
2089 }
2090 }
2091 result = verify_ospf_database(tgen, topo, dut, input_dict)
2092
2093 Returns
2094 -------
2095 True or False (Error Message)
2096 """
2097
2098 result = False
2099 router = dut
2100 logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
2101
db56171c 2102 if "ospf" not in topo["routers"][dut]:
2103 errormsg = "[DUT: {}] OSPF is not configured on the router.".format(dut)
2448d002 2104 return errormsg
2105
2106 rnode = tgen.routers()[dut]
2107
2108 logger.info("Verifying OSPF interface on router %s:", dut)
db56171c 2109 show_ospf_json = run_frr_cmd(rnode, "show ip ospf database json", isjson=True)
2448d002 2110 # Verifying output dictionary show_ospf_json is empty or not
2111 if not bool(show_ospf_json):
2112 errormsg = "OSPF is not running"
2113 return errormsg
2114
2115 # for inter and inter lsa's
2116 ospf_db_data = input_dict.setdefault("areas", None)
db56171c 2117 ospf_external_lsa = input_dict.setdefault("asExternalLinkStates", None)
2448d002 2118
2119 if ospf_db_data:
db56171c 2120 for ospf_area, area_lsa in ospf_db_data.items():
2121 if ospf_area in show_ospf_json["areas"]:
2122 if "routerLinkStates" in area_lsa:
2123 for lsa in area_lsa["routerLinkStates"]:
2124 for rtrlsa in show_ospf_json["areas"][ospf_area][
2125 "routerLinkStates"
2126 ]:
2127 if (
2128 lsa["lsaId"] == rtrlsa["lsaId"]
2129 and lsa["advertisedRouter"]
2130 == rtrlsa["advertisedRouter"]
2131 ):
2132 result = True
2448d002 2133 break
db56171c 2134 if result:
2135 logger.info(
2136 "[DUT: %s] OSPF LSDB area %s:Router " "LSA %s",
2137 router,
2138 ospf_area,
2139 lsa,
2140 )
2141 break
2142 else:
2143 errormsg = (
2144 "[DUT: {}] OSPF LSDB area {}: expected"
2448d002 2145 " Router LSA is {}".format(router, ospf_area, lsa)
db56171c 2146 )
2147 return errormsg
2448d002 2148
db56171c 2149 if "networkLinkStates" in area_lsa:
2150 for lsa in area_lsa["networkLinkStates"]:
2151 for netlsa in show_ospf_json["areas"][ospf_area][
2152 "networkLinkStates"
2153 ]:
2154 if (
2155 lsa
2156 in show_ospf_json["areas"][ospf_area][
2157 "networkLinkStates"
2158 ]
2159 ):
2160 if (
2161 lsa["lsaId"] == netlsa["lsaId"]
2162 and lsa["advertisedRouter"]
2163 == netlsa["advertisedRouter"]
2164 ):
2165 result = True
2166 break
2167 if result:
2168 logger.info(
2169 "[DUT: %s] OSPF LSDB area %s:Network " "LSA %s",
2170 router,
2171 ospf_area,
2172 lsa,
2173 )
2174 break
2175 else:
2176 errormsg = (
2177 "[DUT: {}] OSPF LSDB area {}: expected"
2448d002 2178 " Network LSA is {}".format(router, ospf_area, lsa)
db56171c 2179 )
2180 return errormsg
2448d002 2181
db56171c 2182 if "summaryLinkStates" in area_lsa:
2183 for lsa in area_lsa["summaryLinkStates"]:
2184 for t3lsa in show_ospf_json["areas"][ospf_area][
2185 "summaryLinkStates"
2186 ]:
2187 if (
2188 lsa["lsaId"] == t3lsa["lsaId"]
2189 and lsa["advertisedRouter"] == t3lsa["advertisedRouter"]
2190 ):
2191 result = True
2448d002 2192 break
db56171c 2193 if result:
2194 logger.info(
2195 "[DUT: %s] OSPF LSDB area %s:Summary " "LSA %s",
2196 router,
2197 ospf_area,
2198 lsa,
2199 )
2200 break
2201 else:
2202 errormsg = (
2203 "[DUT: {}] OSPF LSDB area {}: expected"
2448d002 2204 " Summary LSA is {}".format(router, ospf_area, lsa)
db56171c 2205 )
2206 return errormsg
2448d002 2207
db56171c 2208 if "nssaExternalLinkStates" in area_lsa:
2209 for lsa in area_lsa["nssaExternalLinkStates"]:
2210 for t7lsa in show_ospf_json["areas"][ospf_area][
2211 "nssaExternalLinkStates"
2212 ]:
2213 if (
2214 lsa["lsaId"] == t7lsa["lsaId"]
2215 and lsa["advertisedRouter"] == t7lsa["advertisedRouter"]
2216 ):
2217 result = True
2448d002 2218 break
db56171c 2219 if result:
2220 logger.info(
2221 "[DUT: %s] OSPF LSDB area %s:Type7 " "LSA %s",
2222 router,
2223 ospf_area,
2224 lsa,
2225 )
2226 break
2227 else:
2228 errormsg = (
2229 "[DUT: {}] OSPF LSDB area {}: expected"
2448d002 2230 " Type7 LSA is {}".format(router, ospf_area, lsa)
db56171c 2231 )
2232 return errormsg
2448d002 2233
db56171c 2234 if "asbrSummaryLinkStates" in area_lsa:
2235 for lsa in area_lsa["asbrSummaryLinkStates"]:
2236 for t4lsa in show_ospf_json["areas"][ospf_area][
2237 "asbrSummaryLinkStates"
2238 ]:
2239 if (
2240 lsa["lsaId"] == t4lsa["lsaId"]
2241 and lsa["advertisedRouter"] == t4lsa["advertisedRouter"]
2242 ):
2448d002 2243 result = True
db56171c 2244 break
2245 if result:
2246 logger.info(
2247 "[DUT: %s] OSPF LSDB area %s:ASBR Summary " "LSA %s",
2248 router,
2249 ospf_area,
2250 lsa,
2251 )
2252 result = True
2253 else:
2254 errormsg = (
2255 "[DUT: {}] OSPF LSDB area {}: expected"
2256 " ASBR Summary LSA is {}".format(router, ospf_area, lsa)
2257 )
2258 return errormsg
2448d002 2259
db56171c 2260 if "linkLocalOpaqueLsa" in area_lsa:
2261 for lsa in area_lsa["linkLocalOpaqueLsa"]:
2262 try:
2263 for lnklsa in show_ospf_json["areas"][ospf_area][
2264 "linkLocalOpaqueLsa"
2265 ]:
2266 if (
2267 lsa["lsaId"] in lnklsa["lsaId"]
2268 and "linkLocalOpaqueLsa"
2269 in show_ospf_json["areas"][ospf_area]
2270 ):
2271 logger.info(
2272 (
2273 "[DUT: FRR] OSPF LSDB area %s:Opaque-LSA"
2274 "%s",
2275 ospf_area,
2276 lsa,
2277 )
2278 )
2279 result = True
2280 else:
2281 errormsg = (
2282 "[DUT: FRR] OSPF LSDB area: {} "
2283 "expected Opaque-LSA is {}, Found is {}".format(
2284 ospf_area, lsa, show_ospf_json
2285 )
2286 )
2287 raise ValueError(errormsg)
2288 return errormsg
2289 except KeyError:
2290 errormsg = "[DUT: FRR] linkLocalOpaqueLsa Not " "present"
2291 return errormsg
2448d002 2292
2293 if ospf_external_lsa:
db56171c 2294 for lsa in ospf_external_lsa:
2295 try:
2296 for t5lsa in show_ospf_json["asExternalLinkStates"]:
2297 if (
2298 lsa["lsaId"] == t5lsa["lsaId"]
2299 and lsa["advertisedRouter"] == t5lsa["advertisedRouter"]
2300 ):
2301 result = True
2302 break
2303 except KeyError:
2304 result = False
2305 if result:
2306 logger.info("[DUT: %s] OSPF LSDB:External LSA %s", router, lsa)
2307 result = True
2308 else:
2309 errormsg = (
2310 "[DUT: {}] OSPF LSDB : expected"
2311 " External LSA is {}".format(router, lsa)
2312 )
2313 return errormsg
2448d002 2314
2315 logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
2316 return result
2317
2318
a53c08bc
CH
2319def config_ospf6_interface(
2320 tgen, topo=None, input_dict=None, build=False, load_config=True
2321):
2448d002 2322 """
2323 API to configure ospf on router.
2324
2325 Parameters
2326 ----------
2327 * `tgen` : Topogen object
2328 * `topo` : json file data
2329 * `input_dict` : Input dict data, required when configuring from testcase
2330 * `build` : Only for initial setup phase this is set as True.
2331 * `load_config` : Loading the config to router this is set as True.
2332
2333 Usage
2334 -----
2335 r1_ospf_auth = {
2336 "r1": {
2337 "links": {
2338 "r2": {
2339 "ospf": {
2340 "authentication": 'message-digest',
2341 "authentication-key": "ospf",
2342 "message-digest-key": "10"
2343 }
2344 }
2345 }
2346 }
2347 }
2348 result = config_ospf6_interface(tgen, topo, r1_ospf_auth)
2349
2350 Returns
2351 -------
2352 True or False
2353 """
0afa6453 2354
2448d002 2355 logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
2356 result = False
49581587
CH
2357 if topo is None:
2358 topo = tgen.json_topo
2359
2448d002 2360 if not input_dict:
2361 input_dict = deepcopy(topo)
2362 else:
2363 input_dict = deepcopy(input_dict)
4f99894d
CH
2364
2365 config_data_dict = {}
2366
2448d002 2367 for router in input_dict.keys():
2368 config_data = []
a53c08bc
CH
2369 for lnk in input_dict[router]["links"].keys():
2370 if "ospf6" not in input_dict[router]["links"][lnk]:
2371 logger.debug(
2372 "Router %s: ospf6 config is not present in"
2373 "input_dict, passed input_dict %s",
2374 router,
2375 str(input_dict),
2376 )
2448d002 2377 continue
db56171c 2378 ospf_data = input_dict[router]["links"][lnk]["ospf6"]
2448d002 2379 data_ospf_area = ospf_data.setdefault("area", None)
db56171c 2380 data_ospf_auth = ospf_data.setdefault("hash-algo", None)
0afa6453 2381 data_ospf_keychain = ospf_data.setdefault("keychain", None)
2448d002 2382 data_ospf_dr_priority = ospf_data.setdefault("priority", None)
2383 data_ospf_cost = ospf_data.setdefault("cost", None)
2384 data_ospf_mtu = ospf_data.setdefault("mtu_ignore", None)
2385
2386 try:
db56171c 2387 intf = topo["routers"][router]["links"][lnk]["interface"]
2448d002 2388 except KeyError:
db56171c 2389 intf = topo["switches"][router]["links"][lnk]["interface"]
2448d002 2390
2391 # interface
2392 cmd = "interface {}".format(intf)
2393
2394 config_data.append(cmd)
2395 # interface area config
2396 if data_ospf_area:
2397 cmd = "ipv6 ospf area {}".format(data_ospf_area)
2398 config_data.append(cmd)
2399
db56171c 2400 # interface ospf auth
2401 if data_ospf_auth:
2402 cmd = "ipv6 ospf6 authentication"
2403
2404 if "del_action" in ospf_data:
2405 cmd = "no {}".format(cmd)
2406
2407 if "hash-algo" in ospf_data:
2408 cmd = "{} key-id {} hash-algo {} key {}".format(
2409 cmd,
2410 ospf_data["key-id"],
2411 ospf_data["hash-algo"],
2412 ospf_data["key"],
2413 )
0afa6453
AR
2414 config_data.append(cmd)
2415
2416 # interface ospf auth with keychain
2417 if data_ospf_keychain:
2418 cmd = "ipv6 ospf6 authentication"
2419
2420 if "del_action" in ospf_data:
2421 cmd = "no {}".format(cmd)
2422
2423 if "keychain" in ospf_data:
2424 cmd = "{} keychain {}".format(cmd, ospf_data["keychain"])
2425 config_data.append(cmd)
db56171c 2426
2448d002 2427 # interface ospf dr priority
2428 if data_ospf_dr_priority:
db56171c 2429 cmd = "ipv6 ospf priority {}".format(ospf_data["priority"])
2430 if "del_action" in ospf_data:
2448d002 2431 cmd = "no {}".format(cmd)
2432 config_data.append(cmd)
2433
2434 # interface ospf cost
2435 if data_ospf_cost:
db56171c 2436 cmd = "ipv6 ospf cost {}".format(ospf_data["cost"])
2437 if "del_action" in ospf_data:
2448d002 2438 cmd = "no {}".format(cmd)
2439 config_data.append(cmd)
2440
2441 # interface ospf mtu
2442 if data_ospf_mtu:
2443 cmd = "ipv6 ospf mtu-ignore"
db56171c 2444 if "del_action" in ospf_data:
2448d002 2445 cmd = "no {}".format(cmd)
2446 config_data.append(cmd)
2447
2448 if build:
2449 return config_data
4f99894d
CH
2450
2451 if config_data:
2452 config_data_dict[router] = config_data
2453
2454 result = create_common_configurations(
2455 tgen, config_data_dict, "interface_config", build=build
2456 )
2457
2448d002 2458 logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
2459 return result
cc90defc 2460
a53c08bc 2461
cc90defc 2462@retry(retry_timeout=20)
2463def verify_ospf_gr_helper(tgen, topo, dut, input_dict=None):
2464 """
2465 This API is used to vreify gr helper using command
2466 show ip ospf graceful-restart helper
2467
2468 Parameters
2469 ----------
2470 * `tgen` : Topogen object
2471 * `topo` : topology descriptions
2472 * 'dut' : router
2473 * 'input_dict' - values to be verified
2474
2475 Usage:
2476 -------
2477 input_dict = {
2478 "helperSupport":"Disabled",
2479 "strictLsaCheck":"Enabled",
2480 "restartSupoort":"Planned and Unplanned Restarts",
2481 "supportedGracePeriod":1800
2482 }
2483 result = verify_ospf_gr_helper(tgen, topo, dut, input_dict)
2484
2485 """
2486 logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
2487 result = False
2488
a53c08bc
CH
2489 if "ospf" not in topo["routers"][dut]:
2490 errormsg = "[DUT: {}] OSPF is not configured on the router.".format(dut)
cc90defc 2491 return errormsg
2492
2493 rnode = tgen.routers()[dut]
2494 logger.info("Verifying OSPF GR details on router %s:", dut)
a53c08bc
CH
2495 show_ospf_json = run_frr_cmd(
2496 rnode, "show ip ospf graceful-restart helper json", isjson=True
2497 )
cc90defc 2498
2499 # Verifying output dictionary show_ospf_json is empty or not
2500 if not bool(show_ospf_json):
2501 errormsg = "OSPF is not running"
a53c08bc 2502 raise ValueError(errormsg)
cc90defc 2503 return errormsg
2504
a53c08bc 2505 for ospf_gr, gr_data in input_dict.items():
cc90defc 2506 try:
2507 if input_dict[ospf_gr] == show_ospf_json[ospf_gr]:
a53c08bc
CH
2508 logger.info(
2509 "[DUT: FRR] OSPF GR Helper: %s is %s",
2510 ospf_gr,
2511 show_ospf_json[ospf_gr],
2512 )
cc90defc 2513 result = True
2514 else:
a53c08bc
CH
2515 errormsg = (
2516 "[DUT: FRR] OSPF GR Helper: {} expected is {}, Found "
2517 "is {}".format(
2518 ospf_gr, input_dict[ospf_gr], show_ospf_json[ospf_gr]
2519 )
2520 )
2521 raise ValueError(errormsg)
cc90defc 2522 return errormsg
2523
2524 except KeyError:
a53c08bc 2525 errormsg = "[DUT: FRR] OSPF GR Helper: {}".format(ospf_gr)
cc90defc 2526 return errormsg
2527
2528 logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
2529 return result
044561b1
MN
2530
2531
2532def get_ospf_database(tgen, topo, dut, input_dict, vrf=None, lsatype=None, rid=None):
2533 """
2534 This API is to return ospf lsa's by running
2535 show ip ospf database command.
2536
2537 Parameters
2538 ----------
2539 * `tgen` : Topogen object
2540 * `dut`: device under test
2541 * `input_dict` : Input dict data, required when configuring from testcase
2542 * `topo` : next to be verified
2543 * `vrf` : vrf to be checked
2544 * `lsatype` : type of lsa to be checked
2545 * `rid` : router id for lsa to be checked
2546 Usage
2547 -----
2548 input_dict = {
2549 "areas": {
2550 "0.0.0.0": {
2551 "routerLinkStates": {
2552 "100.1.1.0-100.1.1.0": {
2553 "LSID": "100.1.1.0",
2554 "Advertised router": "100.1.1.0",
2555 "LSA Age": 130,
2556 "Sequence Number": "80000006",
2557 "Checksum": "a703",
2558 "Router links": 3
2559 }
2560 },
2561 "networkLinkStates": {
2562 "10.0.0.2-100.1.1.1": {
2563 "LSID": "10.0.0.2",
2564 "Advertised router": "100.1.1.1",
2565 "LSA Age": 137,
2566 "Sequence Number": "80000001",
2567 "Checksum": "9583"
2568 }
2569 },
2570 },
2571 }
2572 }
2573 result = get_ospf_database(tgen, topo, dut, input_dict)
2574
2575 Returns
2576 -------
2577 True or False (Error Message)
2578 """
2579
2580 result = False
2581 router = dut
2582 logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
2583 sleep(10)
2584 if "ospf" not in topo["routers"][dut]:
2585 errormsg = "[DUT: {}] OSPF is not configured on the router.".format(dut)
2586 return errormsg
2587
2588 rnode = tgen.routers()[dut]
2589
2590 logger.info("Verifying OSPF interface on router %s:", dut)
2591 if not rid:
2592 rid = "self-originate"
2593 if lsatype:
2594 if vrf is None:
2595 command = "show ip ospf database {} {} json".format(lsatype, rid)
2596 else:
2597 command = "show ip ospf database {} {} vrf {} json".format(
2598 lsatype, rid, vrf
2599 )
2600 else:
2601 if vrf is None:
2602 command = "show ip ospf database json"
2603 else:
2604 command = "show ip ospf database vrf {} json".format(vrf)
2605
2606 show_ospf_json = run_frr_cmd(rnode, command, isjson=True)
2607 # Verifying output dictionary show_ospf_json is empty or not
2608 if not bool(show_ospf_json):
2609 errormsg = "OSPF is not running"
2610 return errormsg
2611
2612 # for inter and inter lsa's
2613 ospf_db_data = input_dict.setdefault("areas", None)
2614 ospf_external_lsa = input_dict.setdefault("asExternalLinkStates", None)
2615
2616 if ospf_db_data:
2617 for ospf_area, area_lsa in ospf_db_data.items():
2618 if "areas" in show_ospf_json and ospf_area in show_ospf_json["areas"]:
2619 if "routerLinkStates" in area_lsa:
2620 for lsa in area_lsa["routerLinkStates"]:
2621 for rtrlsa in show_ospf_json["areas"][ospf_area][
2622 "routerLinkStates"
2623 ]:
2624 _advrtr = lsa.setdefault("advertisedRouter", None)
2625 _options = lsa.setdefault("options", None)
2626 if (
2627 _advrtr
2628 and lsa["lsaId"] == rtrlsa["lsaId"]
2629 and lsa["advertisedRouter"]
2630 == rtrlsa["advertisedRouter"]
2631 ):
2632 result = True
2633 break
2634 if (
2635 _options
2636 and lsa["lsaId"] == rtrlsa["lsaId"]
2637 and lsa["options"] == rtrlsa["options"]
2638 ):
2639 result = True
2640 break
2641
2642 if result:
2643 logger.info(
2644 "[DUT: %s] OSPF LSDB area %s:Router " "LSA %s",
2645 router,
2646 ospf_area,
2647 lsa,
2648 )
2649 break
2650 else:
2651 errormsg = (
2652 "[DUT: {}] OSPF LSDB area {}: expected"
2653 " Router LSA is {}\n found Router LSA: {}".format(
2654 router, ospf_area, lsa, rtrlsa
2655 )
2656 )
2657 return errormsg
2658
2659 if "networkLinkStates" in area_lsa:
2660 for lsa in area_lsa["networkLinkStates"]:
2661 for netlsa in show_ospf_json["areas"][ospf_area][
2662 "networkLinkStates"
2663 ]:
2664 if (
2665 lsa
2666 in show_ospf_json["areas"][ospf_area][
2667 "networkLinkStates"
2668 ]
2669 ):
2670 if (
2671 lsa["lsaId"] == netlsa["lsaId"]
2672 and lsa["advertisedRouter"]
2673 == netlsa["advertisedRouter"]
2674 ):
2675 result = True
2676 break
2677 if result:
2678 logger.info(
2679 "[DUT: %s] OSPF LSDB area %s:Network " "LSA %s",
2680 router,
2681 ospf_area,
2682 lsa,
2683 )
2684 break
2685 else:
2686 errormsg = (
2687 "[DUT: {}] OSPF LSDB area {}: expected"
2688 " Network LSA is {}".format(router, ospf_area, lsa)
2689 )
2690 return errormsg
2691
2692 if "summaryLinkStates" in area_lsa:
2693 for lsa in area_lsa["summaryLinkStates"]:
2694 for t3lsa in show_ospf_json["areas"][ospf_area][
2695 "summaryLinkStates"
2696 ]:
2697 if (
2698 lsa["lsaId"] == t3lsa["lsaId"]
2699 and lsa["advertisedRouter"] == t3lsa["advertisedRouter"]
2700 ):
2701 result = True
2702 break
2703 if result:
2704 logger.info(
2705 "[DUT: %s] OSPF LSDB area %s:Summary " "LSA %s",
2706 router,
2707 ospf_area,
2708 lsa,
2709 )
2710 break
2711 else:
2712 errormsg = (
2713 "[DUT: {}] OSPF LSDB area {}: expected"
2714 " Summary LSA is {}".format(router, ospf_area, lsa)
2715 )
2716 return errormsg
2717
2718 if "nssaExternalLinkStates" in area_lsa:
2719 for lsa in area_lsa["nssaExternalLinkStates"]:
2720 for t7lsa in show_ospf_json["areas"][ospf_area][
2721 "nssaExternalLinkStates"
2722 ]:
2723 if (
2724 lsa["lsaId"] == t7lsa["lsaId"]
2725 and lsa["advertisedRouter"] == t7lsa["advertisedRouter"]
2726 ):
2727 result = True
2728 break
2729 if result:
2730 logger.info(
2731 "[DUT: %s] OSPF LSDB area %s:Type7 " "LSA %s",
2732 router,
2733 ospf_area,
2734 lsa,
2735 )
2736 break
2737 else:
2738 errormsg = (
2739 "[DUT: {}] OSPF LSDB area {}: expected"
2740 " Type7 LSA is {}".format(router, ospf_area, lsa)
2741 )
2742 return errormsg
2743
2744 if "asbrSummaryLinkStates" in area_lsa:
2745 for lsa in area_lsa["asbrSummaryLinkStates"]:
2746 for t4lsa in show_ospf_json["areas"][ospf_area][
2747 "asbrSummaryLinkStates"
2748 ]:
2749 if (
2750 lsa["lsaId"] == t4lsa["lsaId"]
2751 and lsa["advertisedRouter"] == t4lsa["advertisedRouter"]
2752 ):
2753 result = True
2754 break
2755 if result:
2756 logger.info(
2757 "[DUT: %s] OSPF LSDB area %s:ASBR Summary " "LSA %s",
2758 router,
2759 ospf_area,
2760 lsa,
2761 )
2762 result = True
2763 else:
2764 errormsg = (
2765 "[DUT: {}] OSPF LSDB area {}: expected"
2766 " ASBR Summary LSA is {}".format(router, ospf_area, lsa)
2767 )
2768 return errormsg
2769
2770 if "linkLocalOpaqueLsa" in area_lsa:
2771 for lsa in area_lsa["linkLocalOpaqueLsa"]:
2772 try:
2773 for lnklsa in show_ospf_json["areas"][ospf_area][
2774 "linkLocalOpaqueLsa"
2775 ]:
2776 if (
2777 lsa["lsaId"] in lnklsa["lsaId"]
2778 and "linkLocalOpaqueLsa"
2779 in show_ospf_json["areas"][ospf_area]
2780 ):
2781 logger.info(
2782 (
2783 "[DUT: FRR] OSPF LSDB area %s:Opaque-LSA"
2784 "%s",
2785 ospf_area,
2786 lsa,
2787 )
2788 )
2789 result = True
2790 else:
2791 errormsg = (
2792 "[DUT: FRR] OSPF LSDB area: {} "
2793 "expected Opaque-LSA is {}, Found is {}".format(
2794 ospf_area, lsa, show_ospf_json
2795 )
2796 )
2797 raise ValueError(errormsg)
2798 return errormsg
2799 except KeyError:
2800 errormsg = "[DUT: FRR] linkLocalOpaqueLsa Not " "present"
2801 return errormsg
2802 else:
2803 if "routerLinkStates" in area_lsa:
2804 for lsa in area_lsa["routerLinkStates"]:
2805 for rtrlsa in show_ospf_json["routerLinkStates"]:
2806 _advrtr = lsa.setdefault("advertisedRouter", None)
2807 _options = lsa.setdefault("options", None)
2808 _age = lsa.setdefault("lsaAge", None)
2809 if (
2810 _options
2811 and lsa["options"]
2812 == show_ospf_json["routerLinkStates"][rtrlsa][
2813 ospf_area
2814 ][0]["options"]
2815 ):
2816 result = True
2817 break
2818 if (
2819 _age is not "get"
2820 and lsa["lsaAge"]
2821 == show_ospf_json["routerLinkStates"][rtrlsa][
2822 ospf_area
2823 ][0]["lsaAge"]
2824 ):
2825 result = True
2826 break
2827
2828 if _age == "get":
2829 return "{}".format(
2830 show_ospf_json["routerLinkStates"][rtrlsa][
2831 ospf_area
2832 ][0]["lsaAge"]
2833 )
2834 if result:
2835 logger.info(
2836 "[DUT: %s] OSPF LSDB area %s:Router " "LSA %s",
2837 router,
2838 ospf_area,
2839 lsa,
2840 )
2841 break
2842 else:
2843 errormsg = (
2844 "[DUT: {}] OSPF LSDB area {}: expected"
2845 " Router LSA is {}\n found Router LSA: {}".format(
2846 router,
2847 ospf_area,
2848 lsa,
2849 show_ospf_json["routerLinkStates"],
2850 )
2851 )
2852 return errormsg
2853
2854 if "networkLinkStates" in area_lsa:
2855 for lsa in area_lsa["networkLinkStates"]:
2856 for netlsa in show_ospf_json["areas"][ospf_area][
2857 "networkLinkStates"
2858 ]:
2859 if (
2860 lsa
2861 in show_ospf_json["areas"][ospf_area][
2862 "networkLinkStates"
2863 ]
2864 ):
2865 if (
2866 lsa["lsaId"] == netlsa["lsaId"]
2867 and lsa["advertisedRouter"]
2868 == netlsa["advertisedRouter"]
2869 ):
2870 result = True
2871 break
2872 if result:
2873 logger.info(
2874 "[DUT: %s] OSPF LSDB area %s:Network " "LSA %s",
2875 router,
2876 ospf_area,
2877 lsa,
2878 )
2879 break
2880 else:
2881 errormsg = (
2882 "[DUT: {}] OSPF LSDB area {}: expected"
2883 " Network LSA is {}".format(router, ospf_area, lsa)
2884 )
2885 return errormsg
2886
2887 if "summaryLinkStates" in area_lsa:
2888 for lsa in area_lsa["summaryLinkStates"]:
2889 for t3lsa in show_ospf_json["areas"][ospf_area][
2890 "summaryLinkStates"
2891 ]:
2892 if (
2893 lsa["lsaId"] == t3lsa["lsaId"]
2894 and lsa["advertisedRouter"] == t3lsa["advertisedRouter"]
2895 ):
2896 result = True
2897 break
2898 if result:
2899 logger.info(
2900 "[DUT: %s] OSPF LSDB area %s:Summary " "LSA %s",
2901 router,
2902 ospf_area,
2903 lsa,
2904 )
2905 break
2906 else:
2907 errormsg = (
2908 "[DUT: {}] OSPF LSDB area {}: expected"
2909 " Summary LSA is {}".format(router, ospf_area, lsa)
2910 )
2911 return errormsg
2912
2913 if "nssaExternalLinkStates" in area_lsa:
2914 for lsa in area_lsa["nssaExternalLinkStates"]:
2915 for t7lsa in show_ospf_json["areas"][ospf_area][
2916 "nssaExternalLinkStates"
2917 ]:
2918 if (
2919 lsa["lsaId"] == t7lsa["lsaId"]
2920 and lsa["advertisedRouter"] == t7lsa["advertisedRouter"]
2921 ):
2922 result = True
2923 break
2924 if result:
2925 logger.info(
2926 "[DUT: %s] OSPF LSDB area %s:Type7 " "LSA %s",
2927 router,
2928 ospf_area,
2929 lsa,
2930 )
2931 break
2932 else:
2933 errormsg = (
2934 "[DUT: {}] OSPF LSDB area {}: expected"
2935 " Type7 LSA is {}".format(router, ospf_area, lsa)
2936 )
2937 return errormsg
2938
2939 if "asbrSummaryLinkStates" in area_lsa:
2940 for lsa in area_lsa["asbrSummaryLinkStates"]:
2941 for t4lsa in show_ospf_json["areas"][ospf_area][
2942 "asbrSummaryLinkStates"
2943 ]:
2944 if (
2945 lsa["lsaId"] == t4lsa["lsaId"]
2946 and lsa["advertisedRouter"] == t4lsa["advertisedRouter"]
2947 ):
2948 result = True
2949 break
2950 if result:
2951 logger.info(
2952 "[DUT: %s] OSPF LSDB area %s:ASBR Summary " "LSA %s",
2953 router,
2954 ospf_area,
2955 lsa,
2956 )
2957 result = True
2958 else:
2959 errormsg = (
2960 "[DUT: {}] OSPF LSDB area {}: expected"
2961 " ASBR Summary LSA is {}".format(router, ospf_area, lsa)
2962 )
2963 return errormsg
2964
2965 if "linkLocalOpaqueLsa" in area_lsa:
2966 for lsa in area_lsa["linkLocalOpaqueLsa"]:
2967 try:
2968 for lnklsa in show_ospf_json["areas"][ospf_area][
2969 "linkLocalOpaqueLsa"
2970 ]:
2971 if (
2972 lsa["lsaId"] in lnklsa["lsaId"]
2973 and "linkLocalOpaqueLsa"
2974 in show_ospf_json["areas"][ospf_area]
2975 ):
2976 logger.info(
2977 (
2978 "[DUT: FRR] OSPF LSDB area %s:Opaque-LSA"
2979 "%s",
2980 ospf_area,
2981 lsa,
2982 )
2983 )
2984 result = True
2985 else:
2986 errormsg = (
2987 "[DUT: FRR] OSPF LSDB area: {} "
2988 "expected Opaque-LSA is {}, Found is {}".format(
2989 ospf_area, lsa, show_ospf_json
2990 )
2991 )
2992 raise ValueError(errormsg)
2993 return errormsg
2994 except KeyError:
2995 errormsg = "[DUT: FRR] linkLocalOpaqueLsa Not " "present"
2996 return errormsg
2997
2998 if ospf_external_lsa:
2999 for lsa in ospf_external_lsa:
3000 try:
3001 for t5lsa in show_ospf_json["asExternalLinkStates"]:
3002 if (
3003 lsa["lsaId"] == t5lsa["lsaId"]
3004 and lsa["advertisedRouter"] == t5lsa["advertisedRouter"]
3005 ):
3006 result = True
3007 break
3008 except KeyError:
3009 result = False
3010 if result:
3011 logger.info("[DUT: %s] OSPF LSDB:External LSA %s", router, lsa)
3012 result = True
3013 else:
3014 errormsg = (
3015 "[DUT: {}] OSPF LSDB : expected"
3016 " External LSA is {}".format(router, lsa)
3017 )
3018 return errormsg
3019
3020 logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
3021 return result