mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-05 02:42:42 +00:00
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 <rgirada@vmware.com>
This commit is contained in:
parent
07b33add1d
commit
abd5b8c72c
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
406
ospfd/ospf_vty.c
406
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 <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);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user