]> git.puffer.fish Git - mirror/frr.git/commitdiff
ospfd: GR helper specific show commands
authorrgirada <rgirada@vmware.com>
Sun, 23 Aug 2020 12:34:50 +0000 (05:34 -0700)
committerrgirada <rgirada@vmware.com>
Tue, 22 Sep 2020 07:02:37 +0000 (00:02 -0700)
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 <rgirada@vmware.com>
ospfd/ospf_gr_helper.c
ospfd/ospf_gr_helper.h
ospfd/ospf_vty.c

index 6d630f942a821fc79192368ffb86dc1334ab52ea..a7b20d1f073ef6be20ec7ec1606f298644f83c0c 100644 (file)
@@ -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;
+               }
+       }
+}
index 2432610a9c0a972cfbc629f79a3406e21bd26409..4e83028fe6091497c2592ba5736e9f15729c89d1 100644 (file)
@@ -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);
index 3bed817f614d68027ef12868ad842229a9e3a3b9..1a9ad69ed3bc961a37d73ca3212487c772310653 100644 (file)
@@ -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 <NAME|all>] 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);
 }