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