From abd5b8c72c2e58a0e726f5307a7484bd2b77d037 Mon Sep 17 00:00:00 2001 From: rgirada Date: Sun, 23 Aug 2020 05:34:50 -0700 Subject: [PATCH] ospfd: GR helper specific show commands Description: The following show commands are added to display helper specific information. 1.show ip ospf graceful-restart helper [detail] [json] --> displays user configurations and list of all helpers details. 2.show ip ospf neighbour detail --> diplays helper details Signed-off-by: Rajesh Girada --- ospfd/ospf_gr_helper.c | 74 ++++++++ ospfd/ospf_gr_helper.h | 6 +- ospfd/ospf_vty.c | 406 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 485 insertions(+), 1 deletion(-) diff --git a/ospfd/ospf_gr_helper.c b/ospfd/ospf_gr_helper.c index 6d630f942a..a7b20d1f07 100644 --- a/ospfd/ospf_gr_helper.c +++ b/ospfd/ospf_gr_helper.c @@ -74,6 +74,7 @@ const char *ospf_rejected_reason_desc[] = { "LSA age is more than Grace interval", }; +static void show_ospf_grace_lsa_info(struct vty *vty, struct ospf_lsa *lsa); static bool ospf_check_change_in_rxmt_list(struct ospf_neighbor *nbr); static unsigned int ospf_enable_rtr_hash_key(const void *data) @@ -127,6 +128,8 @@ static void ospf_enable_rtr_hash_destroy(struct ospf *ospf) */ void ospf_gr_helper_init(struct ospf *ospf) { + int rc; + if (IS_DEBUG_OSPF_GR_HELPER) zlog_debug("%s, GR Helper init.", __PRETTY_FUNCTION__); @@ -140,6 +143,16 @@ void ospf_gr_helper_init(struct ospf *ospf) ospf->enable_rtr_list = hash_create(ospf_enable_rtr_hash_key, ospf_enable_rtr_hash_cmp, "OSPF enable router hash"); + + rc = ospf_register_opaque_functab( + OSPF_OPAQUE_LINK_LSA, OPAQUE_TYPE_GRACE_LSA, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, show_ospf_grace_lsa_info, NULL, NULL, + NULL, NULL); + if (rc != 0) { + flog_warn(EC_OSPF_OPAQUE_REGISTRATION, + "%s: Failed to register Grace LSA functions", + __func__); + } } /* @@ -158,6 +171,8 @@ void ospf_gr_helper_stop(struct ospf *ospf) zlog_debug("%s, GR helper deinit.", __PRETTY_FUNCTION__); ospf_enable_rtr_hash_destroy(ospf); + + ospf_delete_opaque_functab(OSPF_OPAQUE_LINK_LSA, OPAQUE_TYPE_GRACE_LSA); } /* @@ -888,3 +903,62 @@ void ospf_gr_helper_set_supported_planned_only_restart(struct ospf *ospf, { ospf->only_planned_restart = planned_only; } + +/* + * Api to display the grace LSA information. + * + * vty + * vty pointer. + * lsa + * Grace LSA. + * json + * json object + * + * Returns: + * Nothing. + */ +static void show_ospf_grace_lsa_info(struct vty *vty, struct ospf_lsa *lsa) +{ + struct lsa_header *lsah = NULL; + struct tlv_header *tlvh = NULL; + struct grace_tlv_graceperiod *gracePeriod; + struct grace_tlv_restart_reason *grReason; + struct grace_tlv_restart_addr *restartAddr; + uint16_t length = 0; + int sum = 0; + + lsah = (struct lsa_header *)lsa->data; + + length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE; + + vty_out(vty, " TLV info:\n"); + + for (tlvh = TLV_HDR_TOP(lsah); sum < length; + tlvh = TLV_HDR_NEXT(tlvh)) { + switch (ntohs(tlvh->type)) { + case GRACE_PERIOD_TYPE: + gracePeriod = (struct grace_tlv_graceperiod *)tlvh; + sum += TLV_SIZE(tlvh); + + vty_out(vty, " Grace period:%d\n", + ntohl(gracePeriod->interval)); + break; + case RESTART_REASON_TYPE: + grReason = (struct grace_tlv_restart_reason *)tlvh; + sum += TLV_SIZE(tlvh); + + vty_out(vty, " Restart reason:%s\n", + ospf_restart_reason_desc[grReason->reason]); + break; + case RESTARTER_IP_ADDR_TYPE: + restartAddr = (struct grace_tlv_restart_addr *)tlvh; + sum += TLV_SIZE(tlvh); + + vty_out(vty, " Restarter address:%s\n", + inet_ntoa(restartAddr->addr)); + break; + default: + break; + } + } +} diff --git a/ospfd/ospf_gr_helper.h b/ospfd/ospf_gr_helper.h index 2432610a9c..4e83028fe6 100644 --- a/ospfd/ospf_gr_helper.h +++ b/ospfd/ospf_gr_helper.h @@ -152,7 +152,11 @@ struct advRtr { #define OSPF_GR_FAILURE 0 #define OSPF_GR_INVALID -1 -extern void ospf_gr_helper_init(struct ospf *); +extern const char *ospf_exit_reason_desc[]; +extern const char *ospf_restart_reason_desc[]; +extern const char *ospf_rejected_reason_desc[]; + +extern void ospf_gr_helper_init(struct ospf *ospf); extern void ospf_gr_helper_stop(struct ospf *ospf); extern int ospf_process_grace_lsa(struct ospf *ospf, struct ospf_lsa *lsa, struct ospf_neighbor *nbr); diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 3bed817f61..1a9ad69ed3 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -5121,6 +5121,71 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty, " Thread Link State Update Retransmission %s\n\n", nbr->t_ls_upd != NULL ? "on" : "off"); + if (!use_json) { + vty_out(vty, " Graceful restart Helper info:\n"); + + if (OSPF_GR_IS_ACTIVE_HELPER(nbr)) { + vty_out(vty, + " Graceful Restart HELPER Status : Inprogress.\n"); + + vty_out(vty, + " Graceful Restart grace period time: %d (seconds).\n", + nbr->gr_helper_info.recvd_grace_period); + vty_out(vty, " Graceful Restart reason: %s.\n", + ospf_restart_reason_desc + [nbr->gr_helper_info + .gr_restart_reason]); + } else { + vty_out(vty, + " Graceful Restart HELPER Status : None\n"); + } + + if (nbr->gr_helper_info.rejected_reason + != OSPF_HELPER_REJECTED_NONE) + vty_out(vty, " Helper rejected reason: %s.\n", + ospf_rejected_reason_desc + [nbr->gr_helper_info.rejected_reason]); + + if (nbr->gr_helper_info.helper_exit_reason + != OSPF_GR_HELPER_EXIT_NONE) + vty_out(vty, " Last helper exit reason: %s.\n\n", + ospf_exit_reason_desc + [nbr->gr_helper_info + .helper_exit_reason]); + else + vty_out(vty, "\n"); + } else { + json_object_string_add(json_neigh, "grHelperStatus", + OSPF_GR_IS_ACTIVE_HELPER(nbr) ? + "Inprogress" + : "None"); + if (OSPF_GR_IS_ACTIVE_HELPER(nbr)) { + json_object_int_add( + json_neigh, "graceInterval", + nbr->gr_helper_info.recvd_grace_period); + json_object_string_add( + json_neigh, "grRestartReason", + ospf_restart_reason_desc + [nbr->gr_helper_info + .gr_restart_reason]); + } + + if (nbr->gr_helper_info.rejected_reason + != OSPF_HELPER_REJECTED_NONE) + json_object_string_add( + json_neigh, "helperRejectReason", + ospf_rejected_reason_desc + [nbr->gr_helper_info.rejected_reason]); + + if (nbr->gr_helper_info.helper_exit_reason + != OSPF_GR_HELPER_EXIT_NONE) + json_object_string_add( + json_neigh, "helperExitReason", + ospf_exit_reason_desc + [nbr->gr_helper_info + .helper_exit_reason]); + } + ospf_bfd_show_info(vty, nbr->bfd_info, json_neigh, use_json, 0); if (use_json) @@ -9129,6 +9194,344 @@ DEFPY(no_ospf_gr_helper_planned_only, return CMD_SUCCESS; } + +static int ospf_print_vty_helper_dis_rtr_walkcb(struct hash_bucket *backet, + void *arg) +{ + struct advRtr *rtr = backet->data; + struct vty *vty = (struct vty *)arg; + static unsigned int count; + + vty_out(vty, "%-6s,", inet_ntoa(rtr->advRtrAddr)); + count++; + + if (count % 5 == 0) + vty_out(vty, "\n"); + + return HASHWALK_CONTINUE; +} + +static int ospf_show_gr_helper_details(struct vty *vty, struct ospf *ospf, + uint8_t use_vrf, json_object *json, + bool uj, bool detail) +{ + struct listnode *node; + struct ospf_interface *oi; + 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); + + if (uj) { + 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); + } + } else + vty_out(vty, "\n"); + + /* Show Router ID. */ + if (uj) { + json_object_string_add(json_vrf, "routerId", + inet_ntoa(ospf->router_id)); + } else { + vty_out(vty, "\n OSPF Router with ID (%s)\n\n", + inet_ntoa(ospf->router_id)); + } + + if (!uj) { + + if (ospf->is_helper_supported) + vty_out(vty, + " Graceful restart helper support enabled.\n"); + else + vty_out(vty, + " Graceful restart helper support disabled.\n"); + + if (ospf->strict_lsa_check) + vty_out(vty, " Strict LSA check is enabled.\n"); + else + vty_out(vty, " Strict LSA check is disabled.\n"); + + if (ospf->only_planned_restart) + vty_out(vty, + " Helper supported for planned restarts only.\n"); + else + vty_out(vty, + " Helper supported for Planned and Unplanned Restarts.\n"); + + vty_out(vty, + " Supported Graceful restart interval: %d(in seconds).\n", + ospf->supported_grace_time); + + if (OSPF_HELPER_ENABLE_RTR_COUNT(ospf)) { + vty_out(vty, " Enable Router list:\n"); + vty_out(vty, " "); + hash_walk(ospf->enable_rtr_list, + ospf_print_vty_helper_dis_rtr_walkcb, vty); + vty_out(vty, "\n\n"); + } + + if (ospf->last_exit_reason != OSPF_GR_HELPER_EXIT_NONE) { + vty_out(vty, " Last Helper exit Reason :%s\n", + ospf_exit_reason_desc[ospf->last_exit_reason]); + } + + if (ospf->active_restarter_cnt) + vty_out(vty, + " Number of Active neighbours in graceful restart: %d\n", + ospf->active_restarter_cnt); + else + vty_out(vty, "\n"); + + } else { + json_object_string_add( + json_vrf, "helperSupport", + (ospf->is_helper_supported) ? "Enabled" : "Disabled"); + json_object_string_add(json_vrf, "strictLsaCheck", + (ospf->strict_lsa_check) ? "Enabled" + : "Disabled"); + json_object_string_add( + json_vrf, "restartSupoort", + (ospf->only_planned_restart) + ? "Planned Restart only" + : "Planned and Unplanned Restarts"); + + json_object_int_add(json_vrf, "supportedGracePeriod", + ospf->supported_grace_time); + + if (ospf->last_exit_reason != OSPF_GR_HELPER_EXIT_NONE) + json_object_string_add( + json_vrf, "LastExitReason", + ospf_exit_reason_desc[ospf->last_exit_reason]); + + if (ospf->active_restarter_cnt) + json_object_int_add(json_vrf, "activeRestarterCnt", + ospf->active_restarter_cnt); + } + + + if (detail) { + int cnt = 1; + json_object *json_neighbors = NULL; + + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) { + struct route_node *rn; + struct ospf_neighbor *nbr; + json_object *json_neigh; + + if (ospf_interface_neighbor_count(oi) == 0) + continue; + + if (uj) { + json_object_object_get_ex(json_vrf, "Neighbors", + &json_neighbors); + if (!json_neighbors) { + json_neighbors = + json_object_new_object(); + json_object_object_add(json_vrf, + "Neighbors", + json_neighbors); + } + } + + for (rn = route_top(oi->nbrs); rn; + rn = route_next(rn)) { + + if (!rn->info) + continue; + + nbr = rn->info; + + if (!OSPF_GR_IS_ACTIVE_HELPER(nbr)) + continue; + + if (!uj) { + vty_out(vty, " Neighbour %d :\n", cnt); + vty_out(vty, " Address : %s\n", + inet_ntoa(nbr->address.u + .prefix4)); + vty_out(vty, " Routerid : %s\n", + inet_ntoa(nbr->router_id)); + vty_out(vty, + " Received Grace period : %d(in seconds).\n", + nbr->gr_helper_info + .recvd_grace_period); + vty_out(vty, + " Actual Grace period : %d(in seconds)\n", + nbr->gr_helper_info + .actual_grace_period); + vty_out(vty, + " Remaining GraceTime:%ld(in seconds).\n", + thread_timer_remain_second( + nbr->gr_helper_info + .t_grace_timer)); + vty_out(vty, + " Graceful Restart reason: %s.\n\n", + ospf_restart_reason_desc + [nbr->gr_helper_info + .gr_restart_reason]); + cnt++; + } else { + json_neigh = json_object_new_object(); + json_object_string_add( + json_neigh, "srcAddr", + inet_ntoa(nbr->src)); + + json_object_string_add( + json_neigh, "routerid", + inet_ntoa(nbr->router_id)); + json_object_int_add( + json_neigh, + "recvdGraceInterval", + nbr->gr_helper_info + .recvd_grace_period); + json_object_int_add( + json_neigh, + "actualGraceInterval", + nbr->gr_helper_info + .actual_grace_period); + json_object_int_add( + json_neigh, "remainGracetime", + thread_timer_remain_second( + nbr->gr_helper_info + .t_grace_timer)); + json_object_string_add( + json_neigh, "restartReason", + ospf_restart_reason_desc + [nbr->gr_helper_info + .gr_restart_reason]); + json_object_object_add( + json_neighbors, + inet_ntoa(nbr->src), + json_neigh); + } + } + } + } + + return CMD_SUCCESS; +} + +DEFPY (show_ip_ospf_gr_helper, + show_ip_ospf_gr_helper_cmd, + "show ip ospf [vrf ] graceful-restart helper [detail] [json]", + SHOW_STR + IP_STR + "OSPF information\n" + VRF_CMD_HELP_STR + "All VRFs\n" + "OSPF Graceful Restart\n" + "Helper details in the router\n" + "Detailed informtion\n" + JSON_STR) +{ + char *vrf_name = NULL; + bool all_vrf = false; + int ret = CMD_SUCCESS; + int idx_vrf = 0; + int idx = 0; + uint8_t use_vrf = 0; + bool uj = use_json(argc, argv); + struct ospf *ospf = NULL; + json_object *json = NULL; + struct listnode *node = NULL; + int inst = 0; + bool detail = false; + + OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + + if (argv_find(argv, argc, "detail", &idx)) + detail = true; + + if (uj) + json = json_object_new_object(); + + /* vrf input is provided */ + if (vrf_name) { + use_vrf = 1; + + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + + ret = ospf_show_gr_helper_details( + vty, ospf, use_vrf, json, uj, detail); + } + + if (uj) { + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } + + return ret; + } + + ospf = ospf_lookup_by_inst_name(inst, vrf_name); + + if (ospf == NULL || !ospf->oi_running) { + + if (uj) { + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else + vty_out(vty, "%% OSPF instance not found\n"); + + return CMD_SUCCESS; + } + + } else { + /* Default Vrf */ + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + + if (ospf == NULL || !ospf->oi_running) { + + if (uj) { + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else + vty_out(vty, "%% OSPF instance not found\n"); + + return CMD_SUCCESS; + } + + ospf_show_gr_helper_details(vty, ospf, use_vrf, json, uj, + detail); + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } + + return CMD_SUCCESS; +} /* Graceful Restart HELPER commands end */ static void config_write_stub_router(struct vty *vty, struct ospf *ospf) @@ -10801,6 +11204,9 @@ void ospf_vty_show_init(void) /* "show ip ospf vrfs" commands. */ install_element(VIEW_NODE, &show_ip_ospf_vrfs_cmd); + + /* "show ip ospf gr-helper details" command */ + install_element(VIEW_NODE, &show_ip_ospf_gr_helper_cmd); } -- 2.39.5