From b131b1ed9c6ed94a9faacfe62f3329e04e3bfd45 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 17 Mar 2023 22:48:59 -0300 Subject: [PATCH 1/3] ospfd: Refactor the "show ip ospf database" command Combine all variations of this command into a single DEFPY to improve maintainability. No behavioral changes intended. Signed-off-by: Renato Westphal --- doc/user/ospfd.rst | 22 +- ospfd/ospf_vty.c | 518 ++++++++++----------------------------------- 2 files changed, 121 insertions(+), 419 deletions(-) diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst index ce3648bf6d..da2968055e 100644 --- a/doc/user/ospfd.rst +++ b/doc/user/ospfd.rst @@ -806,25 +806,19 @@ Showing Information Json o/p of this command covers base route information i.e all LSAs except opaque lsa info. -.. clicmd:: show ip ospf [vrf ] database [json] +.. clicmd:: show ip ospf [vrf ] database [self-originate] [json] -.. clicmd:: show ip ospf [vrf ] database (asbr-summary|external|network|router|summary) [json] - -.. clicmd:: show ip ospf [vrf ] database (asbr-summary|external|network|router|summary) LINK-STATE-ID [json] - -.. clicmd:: show ip ospf [vrf ] database (asbr-summary|external|network|router|summary) LINK-STATE-ID adv-router ADV-ROUTER [json] - -.. clicmd:: show ip ospf [vrf ] database (asbr-summary|external|network|router|summary) adv-router ADV-ROUTER [json] - -.. clicmd:: show ip ospf [vrf ] database (asbr-summary|external|network|router|summary) LINK-STATE-ID self-originate [json] - -.. clicmd:: show ip ospf [vrf ] database (asbr-summary|external|network|router|summary) self-originate [json] + Show the OSPF database summary. .. clicmd:: show ip ospf [vrf ] database max-age [json] -.. clicmd:: show ip ospf [vrf ] database self-originate [json] + Show all MaxAge LSAs present in the OSPF link-state database. - Show the OSPF database summary. +.. clicmd:: show ip ospf [vrf ] database (asbr-summary|external|network|router|summary|nssa-external|opaque-link|opaque-area|opaque-as) [LINK-STATE-ID] [adv-router A.B.C.D] [json] + +.. clicmd:: show ip ospf [vrf ] database (asbr-summary|external|network|router|summary|nssa-external|opaque-link|opaque-area|opaque-as) [LINK-STATE-ID] [self-originate] [json] + + Show detailed information about the OSPF link-state database. .. clicmd:: show ip ospf route [json] diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index eb03a9c3a7..505cd40d9e 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -7084,15 +7084,13 @@ static void show_ip_ospf_database_maxage(struct vty *vty, struct ospf *ospf, OSPF_LSA_TYPE_OPAQUE_LINK_DESC OSPF_LSA_TYPE_OPAQUE_AREA_DESC \ OSPF_LSA_TYPE_OPAQUE_AS_DESC -static int show_ip_ospf_database_common(struct vty *vty, struct ospf *ospf, - int arg_base, int argc, - struct cmd_token **argv, - uint8_t use_vrf, json_object *json, - bool uj) +static int +show_ip_ospf_database_common(struct vty *vty, struct ospf *ospf, bool maxage, + bool self, const char *type_name, + struct in_addr *lsid, struct in_addr *adv_router, + bool use_vrf, json_object *json, bool uj) { - int idx_type = 4; - int type, ret; - struct in_addr id, adv_router; + int type; json_object *json_vrf = NULL; if (uj) { @@ -7121,298 +7119,56 @@ static int show_ip_ospf_database_common(struct vty *vty, struct ospf *ospf, &ospf->router_id); } - /* Show all LSA. */ - if ((argc == arg_base + 4) || (uj && (argc == arg_base + 5))) { - show_ip_ospf_database_summary(vty, ospf, 0, json_vrf); - if (json) { - if (use_vrf) - json_object_object_add( - json, ospf_get_name(ospf), json_vrf); - } - return CMD_SUCCESS; - } - - /* Set database type to show. */ - if (strncmp(argv[arg_base + idx_type]->text, "r", 1) == 0) - type = OSPF_ROUTER_LSA; - else if (strncmp(argv[arg_base + idx_type]->text, "ne", 2) == 0) - type = OSPF_NETWORK_LSA; - else if (strncmp(argv[arg_base + idx_type]->text, "ns", 2) == 0) - type = OSPF_AS_NSSA_LSA; - else if (strncmp(argv[arg_base + idx_type]->text, "su", 2) == 0) - type = OSPF_SUMMARY_LSA; - else if (strncmp(argv[arg_base + idx_type]->text, "a", 1) == 0) - type = OSPF_ASBR_SUMMARY_LSA; - else if (strncmp(argv[arg_base + idx_type]->text, "e", 1) == 0) - type = OSPF_AS_EXTERNAL_LSA; - else if (strncmp(argv[arg_base + idx_type]->text, "se", 2) == 0) { - show_ip_ospf_database_summary(vty, ospf, 1, json_vrf); - if (json) { - if (use_vrf) - json_object_object_add( - json, ospf_get_name(ospf), json_vrf); - } - return CMD_SUCCESS; - } else if (strncmp(argv[arg_base + idx_type]->text, "m", 1) == 0) { + /* Show MaxAge LSAs */ + if (maxage) { show_ip_ospf_database_maxage(vty, ospf, json_vrf); if (json) { - if (use_vrf) - json_object_object_add( - json, ospf_get_name(ospf), json_vrf); + if (use_vrf) { + if (ospf->vrf_id == VRF_DEFAULT) + json_object_object_add(json, "default", + json_vrf); + else + json_object_object_add(json, ospf->name, + json_vrf); + } } return CMD_SUCCESS; - } else if (strncmp(argv[arg_base + idx_type]->text, "opaque-l", 8) == 0) - type = OSPF_OPAQUE_LINK_LSA; - else if (strncmp(argv[arg_base + idx_type]->text, "opaque-ar", 9) == 0) - type = OSPF_OPAQUE_AREA_LSA; - else if (strncmp(argv[arg_base + idx_type]->text, "opaque-as", 9) == 0) - type = OSPF_OPAQUE_AS_LSA; - else - return CMD_WARNING; - - /* `show ip ospf database LSA'. */ - if ((argc == arg_base + 5) || (uj && (argc == arg_base + 6))) - show_lsa_detail(vty, ospf, type, NULL, NULL, json_vrf); - else if (argc >= arg_base + 6) { - ret = inet_aton(argv[arg_base + 5]->arg, &id); - if (!ret) - return CMD_WARNING; - - /* `show ip ospf database LSA ID'. */ - if ((argc == arg_base + 6) || (uj && (argc == arg_base + 7))) - show_lsa_detail(vty, ospf, type, &id, NULL, json_vrf); - /* `show ip ospf database LSA ID adv-router ADV_ROUTER'. */ - else if ((argc == arg_base + 7) - || (uj && (argc == arg_base + 8))) { - if (strncmp(argv[arg_base + 6]->text, "s", 1) == 0) - adv_router = ospf->router_id; - else { - ret = inet_aton(argv[arg_base + 7]->arg, - &adv_router); - if (!ret) - return CMD_WARNING; - } - show_lsa_detail(vty, ospf, type, &id, &adv_router, - json_vrf); - } } - if (json) { - if (use_vrf) - json_object_object_add(json, ospf_get_name(ospf), - json_vrf); - } - - return CMD_SUCCESS; -} - -DEFUN (show_ip_ospf_database_max, - show_ip_ospf_database_max_cmd, - "show ip ospf [vrf ] database [json]", - SHOW_STR - IP_STR - "OSPF information\n" - VRF_CMD_HELP_STR - "All VRFs\n" - "Database summary\n" - "LSAs in MaxAge list\n" - "Self-originated link states\n" - JSON_STR) -{ - struct ospf *ospf = NULL; - struct listnode *node = NULL; - char *vrf_name = NULL; - bool all_vrf = false; - int ret = CMD_SUCCESS; - int inst = 0; - int idx_vrf = 0; - uint8_t use_vrf = 0; - bool uj = use_json(argc, argv); - json_object *json = NULL; - - if (uj) - json = json_object_new_object(); - - OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); - - if (vrf_name) { - bool ospf_output = false; - - use_vrf = 1; - - if (all_vrf) { - for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { - if (!ospf->oi_running) - continue; - ospf_output = true; - ret = show_ip_ospf_database_common( - vty, ospf, idx_vrf ? 2 : 0, argc, argv, - use_vrf, json, uj); + /* Show all LSAs. */ + if (!type_name) { + show_ip_ospf_database_summary(vty, ospf, self, json_vrf); + if (json) { + if (use_vrf) { + if (ospf->vrf_id == VRF_DEFAULT) + json_object_object_add(json, "default", + json_vrf); + else + json_object_object_add(json, ospf->name, + json_vrf); } - - if (!ospf_output) - vty_out(vty, "%% OSPF is not enabled\n"); - } else { - ospf = ospf_lookup_by_inst_name(inst, vrf_name); - if (ospf == NULL || !ospf->oi_running) { - vty_out(vty, - "%% OSPF is not enabled in vrf %s\n", - vrf_name); - if (uj) - json_object_free(json); - - return CMD_SUCCESS; - } - ret = (show_ip_ospf_database_common( - vty, ospf, idx_vrf ? 2 : 0, argc, argv, use_vrf, - json, uj)); } - } else { - /* Display default ospf (instance 0) info */ - ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); - if (ospf == NULL || !ospf->oi_running) { - vty_out(vty, "%% OSPF is not enabled in vrf default\n"); - if (uj) - json_object_free(json); - - return CMD_SUCCESS; - } - - ret = show_ip_ospf_database_common(vty, ospf, 0, argc, argv, - use_vrf, json, uj); - } - - if (uj) - vty_json(vty, json); - - return ret; -} - -ALIAS (show_ip_ospf_database_max, - show_ip_ospf_database_cmd, - "show ip ospf [vrf ] database [ [A.B.C.D []]] [json]", - SHOW_STR - IP_STR - "OSPF information\n" - VRF_CMD_HELP_STR - "All VRFs\n" - "Database summary\n" - OSPF_LSA_TYPES_DESC - "Link State ID (as an IP address)\n" - "Self-originated link states\n" - "Advertising Router link states\n" - "Advertising Router (as an IP address)\n" - JSON_STR) - -DEFUN (show_ip_ospf_instance_database_max, - show_ip_ospf_instance_database_max_cmd, - "show ip ospf (1-65535) database [json]", - SHOW_STR - IP_STR - "OSPF information\n" - "Instance ID\n" - "Database summary\n" - "LSAs in MaxAge list\n" - "Self-originated link states\n" - JSON_STR) -{ - int idx_number = 3; - struct ospf *ospf; - unsigned short instance = 0; - bool uj = use_json(argc, argv); - json_object *json = NULL; - - if (uj) - json = json_object_new_object(); - - instance = strtoul(argv[idx_number]->arg, NULL, 10); - if (instance != ospf_instance) - return CMD_NOT_MY_INSTANCE; - - ospf = ospf_lookup_instance(instance); - if (!ospf || !ospf->oi_running) return CMD_SUCCESS; - - show_ip_ospf_database_common(vty, ospf, 1, argc, argv, 0, json, uj); - - if (uj) - vty_json(vty, json); - - return CMD_SUCCESS; -} - -ALIAS (show_ip_ospf_instance_database_max, - show_ip_ospf_instance_database_cmd, - "show ip ospf (1-65535) database [ [A.B.C.D []]] [json]", - SHOW_STR - IP_STR - "OSPF information\n" - "Instance ID\n" - "Database summary\n" - OSPF_LSA_TYPES_DESC - "Link State ID (as an IP address)\n" - "Self-originated link states\n" - "Advertising Router link states\n" - "Advertising Router (as an IP address)\n" - JSON_STR) - -static int show_ip_ospf_database_type_adv_router_common(struct vty *vty, - struct ospf *ospf, - int arg_base, int argc, - struct cmd_token **argv, - uint8_t use_vrf, - json_object *json, - bool uj) -{ - int idx_type = 4; - int type, ret; - struct in_addr adv_router; - json_object *json_vrf = NULL; - - if (uj) { - if (use_vrf) - json_vrf = json_object_new_object(); - else - json_vrf = json; - } - - if (ospf->instance) { - if (uj) - json_object_int_add(json, "ospfInstance", - ospf->instance); - else - vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); - } - - ospf_show_vrf_name(ospf, vty, json_vrf, use_vrf); - - /* Show Router ID. */ - if (uj) { - json_object_string_addf(json_vrf, "routerId", "%pI4", - &ospf->router_id); - } else { - vty_out(vty, "\n OSPF Router with ID (%pI4)\n\n", - &ospf->router_id); } /* Set database type to show. */ - if (strncmp(argv[arg_base + idx_type]->text, "r", 1) == 0) + if (strncmp(type_name, "r", 1) == 0) type = OSPF_ROUTER_LSA; - else if (strncmp(argv[arg_base + idx_type]->text, "ne", 2) == 0) + else if (strncmp(type_name, "ne", 2) == 0) type = OSPF_NETWORK_LSA; - else if (strncmp(argv[arg_base + idx_type]->text, "ns", 2) == 0) + else if (strncmp(type_name, "ns", 2) == 0) type = OSPF_AS_NSSA_LSA; - else if (strncmp(argv[arg_base + idx_type]->text, "s", 1) == 0) + else if (strncmp(type_name, "su", 2) == 0) type = OSPF_SUMMARY_LSA; - else if (strncmp(argv[arg_base + idx_type]->text, "a", 1) == 0) + else if (strncmp(type_name, "a", 1) == 0) type = OSPF_ASBR_SUMMARY_LSA; - else if (strncmp(argv[arg_base + idx_type]->text, "e", 1) == 0) + else if (strncmp(type_name, "e", 1) == 0) type = OSPF_AS_EXTERNAL_LSA; - else if (strncmp(argv[arg_base + idx_type]->text, "opaque-l", 8) == 0) + else if (strncmp(type_name, "opaque-l", 8) == 0) type = OSPF_OPAQUE_LINK_LSA; - else if (strncmp(argv[arg_base + idx_type]->text, "opaque-ar", 9) == 0) + else if (strncmp(type_name, "opaque-ar", 9) == 0) type = OSPF_OPAQUE_AREA_LSA; - else if (strncmp(argv[arg_base + idx_type]->text, "opaque-as", 9) == 0) + else if (strncmp(type_name, "opaque-as", 9) == 0) type = OSPF_OPAQUE_AS_LSA; else { if (uj) { @@ -7422,155 +7178,114 @@ static int show_ip_ospf_database_type_adv_router_common(struct vty *vty, return CMD_WARNING; } - /* `show ip ospf database LSA adv-router ADV_ROUTER'. */ - if (strncmp(argv[arg_base + 5]->text, "s", 1) == 0) - adv_router = ospf->router_id; - else { - ret = inet_aton(argv[arg_base + 6]->arg, &adv_router); - if (!ret) { - if (uj) { - if (use_vrf) - json_object_free(json_vrf); - } - return CMD_WARNING; - } - } - - show_lsa_detail_adv_router(vty, ospf, type, &adv_router, json_vrf); + if (adv_router && !lsid) + show_lsa_detail_adv_router(vty, ospf, type, adv_router, + json_vrf); + else + show_lsa_detail(vty, ospf, type, lsid, adv_router, json_vrf); if (json) { - if (use_vrf) - json_object_object_add(json, ospf_get_name(ospf), - json_vrf); + if (use_vrf) { + if (ospf->vrf_id == VRF_DEFAULT) + json_object_object_add(json, "default", + json_vrf); + else + json_object_object_add(json, ospf->name, + json_vrf); + } } return CMD_SUCCESS; } -DEFUN (show_ip_ospf_database_type_adv_router, - show_ip_ospf_database_type_adv_router_cmd, - "show ip ospf [vrf ] database [json]", - SHOW_STR - IP_STR - "OSPF information\n" - VRF_CMD_HELP_STR - "All VRFs\n" - "Database summary\n" - OSPF_LSA_TYPES_DESC - "Advertising Router link states\n" - "Advertising Router (as an IP address)\n" - "Self-originated link states\n" - JSON_STR) -{ - struct ospf *ospf = NULL; - struct listnode *node = NULL; - char *vrf_name = NULL; - bool all_vrf = false; - int ret = CMD_SUCCESS; - int inst = 0; - int idx_vrf = 0; - uint8_t use_vrf = 0; - bool uj = use_json(argc, argv); - json_object *json = NULL; - - if (uj) - json = json_object_new_object(); - - OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); - - if (vrf_name) { - bool ospf_output = false; - - use_vrf = 1; - - if (all_vrf) { - for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { - if (!ospf->oi_running) - continue; - ospf_output = true; - ret = show_ip_ospf_database_type_adv_router_common( - vty, ospf, 2, argc, argv, use_vrf, json, - uj); - } - if (!ospf_output) - vty_out(vty, "%% OSPF is not enabled\n"); - } else { - ospf = ospf_lookup_by_inst_name(inst, vrf_name); - if ((ospf == NULL) || !ospf->oi_running) { - if (uj) - vty_json(vty, json); - else - vty_out(vty, - "%% OSPF is not enabled in vrf %s\n", - vrf_name); - return CMD_SUCCESS; - } - - ret = show_ip_ospf_database_type_adv_router_common( - vty, ospf, 2, argc, argv, use_vrf, json, uj); - } - } else { - /* Display default ospf (instance 0) info */ - ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); - if (ospf == NULL || !ospf->oi_running) { - if (uj) - vty_json(vty, json); - else - vty_out(vty, - "%% OSPF is not enabled on vrf default\n"); - return CMD_SUCCESS; - } - - ret = show_ip_ospf_database_type_adv_router_common( - vty, ospf, 0, argc, argv, use_vrf, json, uj); - } - - if (uj) { - vty_out(vty, "%s\n", json_object_to_json_string(json)); - json_object_free(json); - } - - return ret; -} - -DEFUN (show_ip_ospf_instance_database_type_adv_router, - show_ip_ospf_instance_database_type_adv_router_cmd, - "show ip ospf (1-65535) database [json]", +DEFPY (show_ip_ospf_database, + show_ip_ospf_database_cmd, + "show ip ospf [(1-65535)$instance_id] [vrf $vrf_name] database\ + [<\ + max-age$maxage\ + |self-originate$selforig\ + |$type_name\ + [{\ + A.B.C.D$lsid\ + |\ + }]\ + >]\ + [json]", SHOW_STR IP_STR "OSPF information\n" "Instance ID\n" + VRF_CMD_HELP_STR + "All VRFs\n" "Database summary\n" + "LSAs in MaxAge list\n" + "Self-originated link states\n" OSPF_LSA_TYPES_DESC + "Link State ID (as an IP address)\n" "Advertising Router link states\n" "Advertising Router (as an IP address)\n" "Self-originated link states\n" JSON_STR) { - int idx_number = 3; struct ospf *ospf; - unsigned short instance = 0; + int ret = CMD_SUCCESS; + bool use_vrf = !!vrf_name; bool uj = use_json(argc, argv); + struct in_addr *lsid_p = NULL; + struct in_addr *adv_router_p = NULL; json_object *json = NULL; if (uj) json = json_object_new_object(); + if (lsid_str) + lsid_p = &lsid; + if (adv_router_str) + adv_router_p = &adv_router; - instance = strtoul(argv[idx_number]->arg, NULL, 10); - if (instance != ospf_instance) - return CMD_NOT_MY_INSTANCE; + if (vrf_name && strmatch(vrf_name, "all")) { + struct listnode *node; + bool ospf_output = false; - ospf = ospf_lookup_instance(instance); - if (!ospf || !ospf->oi_running) - return CMD_SUCCESS; + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + if (ospf->instance != instance_id) + continue; - show_ip_ospf_database_type_adv_router_common(vty, ospf, 1, argc, argv, - 0, json, uj); + if (adv_router_self) + adv_router_p = &ospf->router_id; + + ospf_output = true; + ret = show_ip_ospf_database_common( + vty, ospf, !!maxage, !!selforig, type_name, + lsid_p, adv_router_p, use_vrf, json, uj); + } + + if (!ospf_output && !uj) + vty_out(vty, "%% OSPF is not enabled\n"); + } else { + if (!vrf_name) + vrf_name = VRF_DEFAULT_NAME; + ospf = ospf_lookup_by_inst_name(instance_id, vrf_name); + if (ospf == NULL || !ospf->oi_running) { + if (uj) + vty_json(vty, json); + else + vty_out(vty, "%% OSPF instance not found\n"); + return CMD_SUCCESS; + } + if (adv_router_self) + adv_router_p = &ospf->router_id; + + ret = (show_ip_ospf_database_common( + vty, ospf, !!maxage, !!selforig, type_name, lsid_p, + adv_router_p, use_vrf, json, uj)); + } if (uj) vty_json(vty, json); - return CMD_SUCCESS; + return ret; } DEFUN (ip_ospf_authentication_args, @@ -12781,13 +12496,6 @@ void ospf_vty_show_init(void) /* "show ip ospf database" commands. */ install_element(VIEW_NODE, &show_ip_ospf_database_cmd); - install_element(VIEW_NODE, &show_ip_ospf_database_max_cmd); - install_element(VIEW_NODE, - &show_ip_ospf_database_type_adv_router_cmd); - install_element(VIEW_NODE, - &show_ip_ospf_instance_database_type_adv_router_cmd); - install_element(VIEW_NODE, &show_ip_ospf_instance_database_cmd); - install_element(VIEW_NODE, &show_ip_ospf_instance_database_max_cmd); /* "show ip ospf interface" commands. */ install_element(VIEW_NODE, &show_ip_ospf_interface_cmd); From a08f41b95b7af2a5803d1cd18c80e361fa24c66d Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 17 Mar 2023 22:48:59 -0300 Subject: [PATCH 2/3] ospfd: Add "detail" option to "show ip ospf database" This option is useful to dump detailed information about the LSDB using a single command (instead of one command per LSA type). Signed-off-by: Renato Westphal --- doc/user/ospfd.rst | 4 ++++ ospfd/ospf_vty.c | 42 +++++++++++++++++++++++++++++++++++------- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst index da2968055e..30d55f34a7 100644 --- a/doc/user/ospfd.rst +++ b/doc/user/ospfd.rst @@ -814,6 +814,10 @@ Showing Information Show all MaxAge LSAs present in the OSPF link-state database. +.. clicmd:: show ip ospf [vrf ] database detail [LINK-STATE-ID] [adv-router A.B.C.D] [json] + +.. clicmd:: show ip ospf [vrf ] database detail [LINK-STATE-ID] [self-originate] [json] + .. clicmd:: show ip ospf [vrf ] database (asbr-summary|external|network|router|summary|nssa-external|opaque-link|opaque-area|opaque-as) [LINK-STATE-ID] [adv-router A.B.C.D] [json] .. clicmd:: show ip ospf [vrf ] database (asbr-summary|external|network|router|summary|nssa-external|opaque-link|opaque-area|opaque-as) [LINK-STATE-ID] [self-originate] [json] diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 505cd40d9e..11641c888d 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -7086,7 +7086,7 @@ static void show_ip_ospf_database_maxage(struct vty *vty, struct ospf *ospf, static int show_ip_ospf_database_common(struct vty *vty, struct ospf *ospf, bool maxage, - bool self, const char *type_name, + bool self, bool detail, const char *type_name, struct in_addr *lsid, struct in_addr *adv_router, bool use_vrf, json_object *json, bool uj) { @@ -7137,7 +7137,30 @@ show_ip_ospf_database_common(struct vty *vty, struct ospf *ospf, bool maxage, /* Show all LSAs. */ if (!type_name) { - show_ip_ospf_database_summary(vty, ospf, self, json_vrf); + if (detail) { + for (int i = OSPF_ROUTER_LSA; i <= OSPF_OPAQUE_AS_LSA; + i++) { + switch (i) { + case OSPF_GROUP_MEMBER_LSA: + case OSPF_EXTERNAL_ATTRIBUTES_LSA: + /* ignore deprecated LSA types */ + continue; + default: + break; + } + + if (adv_router && !lsid) + show_lsa_detail_adv_router(vty, ospf, i, + adv_router, + json_vrf); + else + show_lsa_detail(vty, ospf, i, lsid, + adv_router, json_vrf); + } + } else + show_ip_ospf_database_summary(vty, ospf, self, + json_vrf); + if (json) { if (use_vrf) { if (ospf->vrf_id == VRF_DEFAULT) @@ -7204,7 +7227,10 @@ DEFPY (show_ip_ospf_database, [<\ max-age$maxage\ |self-originate$selforig\ - |$type_name\ + |<\ + detail$detail\ + |$type_name\ + >\ [{\ A.B.C.D$lsid\ |\ @@ -7220,6 +7246,7 @@ DEFPY (show_ip_ospf_database, "Database summary\n" "LSAs in MaxAge list\n" "Self-originated link states\n" + "Show detailed information\n" OSPF_LSA_TYPES_DESC "Link State ID (as an IP address)\n" "Advertising Router link states\n" @@ -7257,8 +7284,9 @@ DEFPY (show_ip_ospf_database, ospf_output = true; ret = show_ip_ospf_database_common( - vty, ospf, !!maxage, !!selforig, type_name, - lsid_p, adv_router_p, use_vrf, json, uj); + vty, ospf, !!maxage, !!selforig, !!detail, + type_name, lsid_p, adv_router_p, use_vrf, json, + uj); } if (!ospf_output && !uj) @@ -7278,8 +7306,8 @@ DEFPY (show_ip_ospf_database, adv_router_p = &ospf->router_id; ret = (show_ip_ospf_database_common( - vty, ospf, !!maxage, !!selforig, type_name, lsid_p, - adv_router_p, use_vrf, json, uj)); + vty, ospf, !!maxage, !!selforig, !!detail, type_name, + lsid_p, adv_router_p, use_vrf, json, uj)); } if (uj) From f54232d0b2f5a54d4ec53ce2efff4877c15cc8d1 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 17 Mar 2023 22:48:59 -0300 Subject: [PATCH 3/3] ospfd: Fix inconsistency in LSDB JSON output As it can be seen below, the LSDB JSON output varies depending whether a filter option is specified or not (e.g. "adv-router", "self-originate"): > show ip ospf database router json { "routerId":"3.3.3.3", "routerLinkStates":{ "areas":{ "0.0.0.0":[ { "lsaAge":175, "options":"*|-|-|-|-|-|E|-", [snip] > show ip ospf database router adv-router 2.2.2.2 json { "routerId":"3.3.3.3", "Router Link States":{ "0.0.0.0":{ "2.2.2.2":{ "lsaAge":193, "options":"*|-|-|-|-|-|E|-", [snip] This inconsistency is undesirable since it makes this data harder to consume programmatically. Also, in the second output, "Router Link States" is used as a JSON key, which doesn't conform to our JSON guidelines (JSON keys need to be camelCased). Make the required changes to ensure the first output structure is used, regardless if any output filter is used or not. Signed-off-by: Renato Westphal --- ospfd/ospf_vty.c | 69 ++++++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 11641c888d..262f805468 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -6800,31 +6800,24 @@ static void show_lsa_detail_adv_router_proc(struct vty *vty, struct in_addr *adv_router, json_object *json) { - char buf[PREFIX_STRLEN]; struct route_node *rn; struct ospf_lsa *lsa; + json_object *json_lsa = NULL; for (rn = route_top(rt); rn; rn = route_next(rn)) if ((lsa = rn->info)) { - json_object *json_lsa = NULL; - if (IPV4_ADDR_SAME(adv_router, &lsa->data->adv_router)) { if (CHECK_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT)) continue; - if (json) + if (json) { json_lsa = json_object_new_object(); + json_object_array_add(json, json_lsa); + } if (show_function[lsa->data->type] != NULL) show_function[lsa->data->type]( vty, lsa, json_lsa); - if (json) - json_object_object_add( - json, - inet_ntop(AF_INET, - &lsa->data->id, - buf, sizeof(buf)), - json_lsa); } } } @@ -6837,11 +6830,12 @@ static void show_lsa_detail_adv_router(struct vty *vty, struct ospf *ospf, struct listnode *node; struct ospf_area *area; char buf[PREFIX_STRLEN]; - json_object *json_lstype = NULL; - json_object *json_area = NULL; + json_object *json_lsa_type = NULL; + json_object *json_areas = NULL; + json_object *json_lsa_array = NULL; if (json) - json_lstype = json_object_new_object(); + json_lsa_type = json_object_new_object(); switch (type) { case OSPF_AS_EXTERNAL_LSA: @@ -6849,38 +6843,49 @@ static void show_lsa_detail_adv_router(struct vty *vty, struct ospf *ospf, if (!json) vty_out(vty, " %s \n\n", show_database_desc[type]); + else + json_lsa_array = json_object_new_array(); show_lsa_detail_adv_router_proc(vty, AS_LSDB(ospf, type), - adv_router, json_lstype); + adv_router, json_lsa_array); + if (json) + json_object_object_add(json, + show_database_desc_json[type], + json_lsa_array); break; default: + if (json) + json_areas = json_object_new_object(); for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { - if (json) - json_area = json_object_new_object(); - else + if (!json) { vty_out(vty, "\n %s (Area %s)\n\n", show_database_desc[type], ospf_area_desc_string(area)); - show_lsa_detail_adv_router_proc(vty, - AREA_LSDB(area, type), - adv_router, json_area); + } else { + json_lsa_array = json_object_new_array(); + json_object_object_add( + json_areas, + inet_ntop(AF_INET, &area->area_id, buf, + sizeof(buf)), + json_lsa_array); + } - if (json) - json_object_object_add(json_lstype, - inet_ntop(AF_INET, - &area->area_id, - buf, - sizeof(buf)), - json_area); + show_lsa_detail_adv_router_proc( + vty, AREA_LSDB(area, type), adv_router, + json_lsa_array); + } + + if (json) { + json_object_object_add(json_lsa_type, "areas", + json_areas); + json_object_object_add(json, + show_database_desc_json[type], + json_lsa_type); } break; } - - if (json) - json_object_object_add(json, show_database_desc[type], - json_lstype); } void show_ip_ospf_database_summary(struct vty *vty, struct ospf *ospf, int self,