From: rgirada Date: Thu, 1 Jul 2021 14:09:38 +0000 (-0700) Subject: ospf6d: GR helper configurations X-Git-Tag: base_8.1~177^2 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=refs%2Fpull%2F8935%2Fhead;p=mirror%2Ffrr.git ospf6d: GR helper configurations Description: Adding the following cli commands to enable/disable GR helper functionality. 1. [no] graceful-restart helper-only [A.B.C.D] 2. [no] graceful-restart helper lsa-check-disable 3. [no] graceful-restart helper planned-only 4. [no] graceful-restart helper supported-grace-time (10-1800) show commands: show ipv6 ospf6 graceful-restart helper [detail] [json] Signed-off-by: Rajesh Girada --- diff --git a/ospf6d/ospf6_flood.c b/ospf6d/ospf6_flood.c index 458b81f2ea..87c43c4657 100644 --- a/ospf6d/ospf6_flood.c +++ b/ospf6d/ospf6_flood.c @@ -1026,7 +1026,7 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from, if (OSPF6_LSA_IS_MAXAGE(new)) { - if (IS_DEBUG_OSPF6_GR_HELPER) + if (IS_DEBUG_OSPF6_GR) zlog_debug( "%s, Received a maxage GraceLSA from router %pI4", __func__, @@ -1035,7 +1035,7 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from, ospf6_process_maxage_grace_lsa( ospf6, new, from); } else { - if (IS_DEBUG_OSPF6_GR_HELPER) + if (IS_DEBUG_OSPF6_GR) zlog_debug( "%s, GraceLSA doesn't exist in lsdb, so discarding GraceLSA", __func__); @@ -1043,7 +1043,7 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from, } } else { - if (IS_DEBUG_OSPF6_GR_HELPER) + if (IS_DEBUG_OSPF6_GR) zlog_debug( "%s, Received a GraceLSA from router %pI4", __func__, @@ -1051,7 +1051,7 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from, if (ospf6_process_grace_lsa(ospf6, new, from) == OSPF6_GR_NOT_HELPER) { - if (IS_DEBUG_OSPF6_GR_HELPER) + if (IS_DEBUG_OSPF6_GR) zlog_debug( "%s, Not moving to HELPER role, So dicarding GraceLSA", __func__); diff --git a/ospf6d/ospf6_gr.h b/ospf6d/ospf6_gr.h index 49fc86a4e2..378b7193cd 100644 --- a/ospf6d/ospf6_gr.h +++ b/ospf6d/ospf6_gr.h @@ -36,15 +36,13 @@ /* Debug option */ extern unsigned char conf_debug_ospf6_gr; -#define OSPF6_DEBUG_GR_HELPER 0x01 +#define OSPF6_DEBUG_GR 0x01 -#define OSPF6_DEBUG_GR_HELPER_ON() \ - (conf_debug_ospf6_gr |= OSPF6_DEBUG_GR_HELPER) +#define OSPF6_DEBUG_GR_ON() (conf_debug_ospf6_gr |= OSPF6_DEBUG_GR) -#define OSPF6_DEBUG_GR_HELPER_OFF() \ - (conf_debug_ospf6_gr &= ~OSPF6_DEBUG_GR_HELPER) +#define OSPF6_DEBUG_GR_OFF() (conf_debug_ospf6_gr &= ~OSPF6_DEBUG_GR) -#define IS_DEBUG_OSPF6_GR_HELPER conf_debug_ospf6_gr +#define IS_DEBUG_OSPF6_GR conf_debug_ospf6_gr enum ospf6_helper_exit_reason { @@ -98,7 +96,7 @@ struct tlv_header { #define TLV_HDR_NEXT(tlvh) \ (struct tlv_header *)((char *)(tlvh) + TLV_SIZE(tlvh)) -/* Ref RFC5187 appendex-A */ +/* Ref RFC5187 appendix-A */ /* Grace period TLV */ #define GRACE_PERIOD_TYPE 1 #define GRACE_PERIOD_LENGTH 4 @@ -126,7 +124,7 @@ struct advRtr { }; #define OSPF6_HELPER_ENABLE_RTR_COUNT(ospf) \ - (ospf6->ospf6_helper_cfg.enableRtrList->count) + (ospf6->ospf6_helper_cfg.enable_rtr_list->count) /* Check , it is a planned restart */ #define OSPF6_GR_IS_PLANNED_RESTART(reason) \ @@ -146,6 +144,7 @@ extern const char *ospf6_exit_reason_desc[]; extern const char *ospf6_restart_reason_desc[]; extern const char *ospf6_rejected_reason_desc[]; +extern void ospf6_gr_helper_config_init(void); extern void ospf6_gr_helper_init(struct ospf6 *ospf6); extern void ospf6_gr_helper_deinit(struct ospf6 *ospf6); extern void ospf6_gr_helper_exit(struct ospf6_neighbor *nbr, @@ -157,4 +156,6 @@ extern void ospf6_process_maxage_grace_lsa(struct ospf6 *ospf, struct ospf6_neighbor *nbr); extern void ospf6_helper_handle_topo_chg(struct ospf6 *ospf6, struct ospf6_lsa *lsa); +extern int config_write_ospf6_gr_helper(struct vty *vty, struct ospf6 *ospf6); +extern int config_write_ospf6_debug_gr_helper(struct vty *vty); #endif /* OSPF6_GR_H */ diff --git a/ospf6d/ospf6_gr_helper.c b/ospf6d/ospf6_gr_helper.c index 60c62a9341..07e479efcb 100644 --- a/ospf6d/ospf6_gr_helper.c +++ b/ospf6d/ospf6_gr_helper.c @@ -57,9 +57,23 @@ DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_GR_HELPER, "OSPF6 Graceful restart helper"); unsigned char conf_debug_ospf6_gr; +static int ospf6_grace_lsa_show_info(struct vty *vty, struct ospf6_lsa *lsa, + json_object *json, bool use_json); + +struct ospf6_lsa_handler grace_lsa_handler = {.lh_type = OSPF6_LSTYPE_GRACE_LSA, + .lh_name = "Grace", + .lh_short_name = "GR", + .lh_show = + ospf6_grace_lsa_show_info, + .lh_get_prefix_str = NULL, + .lh_debug = 0}; + const char *ospf6_exit_reason_desc[] = { - "Unknown reason", "Helper inprogress", "Topology Change", - "Grace timer expiry", "Successful graceful restart", + "Unknown reason", + "Helper in progress", + "Topology Change", + "Grace timer expiry", + "Successful graceful restart", }; const char *ospf6_restart_reason_desc[] = { @@ -165,10 +179,9 @@ static int ospf6_extract_grace_lsa_fields(struct ospf6_lsa *lsa, return OSPF6_FAILURE; break; default: - if (IS_DEBUG_OSPF6_GR_HELPER) - zlog_debug( - "%s, Ignoring unknown TLV type:%d", - __func__, ntohs(tlvh->type)); + if (IS_DEBUG_OSPF6_GR) + zlog_debug("%s, Ignoring unknown TLV type:%d", + __func__, ntohs(tlvh->type)); } } @@ -259,17 +272,15 @@ int ospf6_process_grace_lsa(struct ospf6 *ospf6, struct ospf6_lsa *lsa, ret = ospf6_extract_grace_lsa_fields(lsa, &grace_interval, &restart_reason); if (ret != OSPF6_SUCCESS) { - if (IS_DEBUG_OSPF6_GR_HELPER) - zlog_debug("%s, Wrong Grace LSA packet.", - __func__); + if (IS_DEBUG_OSPF6_GR) + zlog_debug("%s, Wrong Grace LSA packet.", __func__); return OSPF6_GR_NOT_HELPER; } - if (IS_DEBUG_OSPF6_GR_HELPER) + if (IS_DEBUG_OSPF6_GR) zlog_debug( "%s, Grace LSA received from %pI4, grace interval:%u, restart reason :%s", - __func__, &restarter->router_id, - grace_interval, + __func__, &restarter->router_id, grace_interval, ospf6_restart_reason_desc[restart_reason]); /* Verify Helper enabled globally */ @@ -281,7 +292,7 @@ int ospf6_process_grace_lsa(struct ospf6 *ospf6, struct ospf6_lsa *lsa, if (!hash_lookup(ospf6->ospf6_helper_cfg.enable_rtr_list, &lookup)) { - if (IS_DEBUG_OSPF6_GR_HELPER) + if (IS_DEBUG_OSPF6_GR) zlog_debug( "%s, HELPER support is disabled, So not a HELPER", __func__); @@ -295,7 +306,7 @@ int ospf6_process_grace_lsa(struct ospf6 *ospf6, struct ospf6_lsa *lsa, * became a adjacency. */ if (!IS_NBR_STATE_FULL(restarter)) { - if (IS_DEBUG_OSPF6_GR_HELPER) + if (IS_DEBUG_OSPF6_GR) zlog_debug( "%s, This Neighbour %pI6 is not in FULL state.", __func__, &restarter->linklocal_addr); @@ -309,7 +320,7 @@ int ospf6_process_grace_lsa(struct ospf6 *ospf6, struct ospf6_lsa *lsa, */ if (ospf6->ospf6_helper_cfg.only_planned_restart && !OSPF6_GR_IS_PLANNED_RESTART(restart_reason)) { - if (IS_DEBUG_OSPF6_GR_HELPER) + if (IS_DEBUG_OSPF6_GR) zlog_debug( "%s, Router supports only planned restarts but received the GRACE LSA due a unplanned restart", __func__); @@ -324,7 +335,7 @@ int ospf6_process_grace_lsa(struct ospf6 *ospf6, struct ospf6_lsa *lsa, if (ospf6->ospf6_helper_cfg.strict_lsa_check && restarter->retrans_list->count && ospf6_check_chg_in_rxmt_list(restarter)) { - if (IS_DEBUG_OSPF6_GR_HELPER) + if (IS_DEBUG_OSPF6_GR) zlog_debug( "%s, Changed LSA in Rxmt list.So not Helper.", __func__); @@ -333,13 +344,12 @@ int ospf6_process_grace_lsa(struct ospf6 *ospf6, struct ospf6_lsa *lsa, return OSPF6_GR_NOT_HELPER; } - /*LSA age must be less than the grace period */ + /* LSA age must be less than the grace period */ if (ntohs(lsa->header->age) >= grace_interval) { - if (IS_DEBUG_OSPF6_GR_HELPER) + if (IS_DEBUG_OSPF6_GR) zlog_debug( "%s, Grace LSA age(%d) is more than the grace interval(%d)", - __func__, lsa->header->age, - grace_interval); + __func__, lsa->header->age, grace_interval); restarter->gr_helper_info.rejected_reason = OSPF6_HELPER_LSA_AGE_MORE; return OSPF6_GR_NOT_HELPER; @@ -352,7 +362,7 @@ int ospf6_process_grace_lsa(struct ospf6 *ospf6, struct ospf6_lsa *lsa, */ actual_grace_interval = grace_interval; if (grace_interval > ospf6->ospf6_helper_cfg.supported_grace_time) { - if (IS_DEBUG_OSPF6_GR_HELPER) + if (IS_DEBUG_OSPF6_GR) zlog_debug( "%s, Received grace period %d is larger than supported grace %d", __func__, grace_interval, @@ -368,12 +378,12 @@ int ospf6_process_grace_lsa(struct ospf6 *ospf6, struct ospf6_lsa *lsa, if (ospf6->ospf6_helper_cfg.active_restarter_cnt > 0) ospf6->ospf6_helper_cfg.active_restarter_cnt--; - if (IS_DEBUG_OSPF6_GR_HELPER) + if (IS_DEBUG_OSPF6_GR) zlog_debug( "%s, Router is already acting as a HELPER for this nbr,so restart the grace timer", __func__); } else { - if (IS_DEBUG_OSPF6_GR_HELPER) + if (IS_DEBUG_OSPF6_GR) zlog_debug( "%s, This Router becomes a HELPER for the neighbour %pI6", __func__, &restarter->linklocal_addr); @@ -391,9 +401,9 @@ int ospf6_process_grace_lsa(struct ospf6 *ospf6, struct ospf6_lsa *lsa, /* Increment the active restart nbr count */ ospf6->ospf6_helper_cfg.active_restarter_cnt++; - if (IS_DEBUG_OSPF6_GR_HELPER) - zlog_debug("%s, Grace timer started.interval:%u", - __func__, actual_grace_interval); + if (IS_DEBUG_OSPF6_GR) + zlog_debug("%s, Grace timer started.interval:%u", __func__, + actual_grace_interval); /* Start the grace timer */ thread_add_timer(master, ospf6_handle_grace_timer_expiry, restarter, @@ -434,7 +444,7 @@ void ospf6_gr_helper_exit(struct ospf6_neighbor *nbr, if (!OSPF6_GR_IS_ACTIVE_HELPER(nbr)) return; - if (IS_DEBUG_OSPF6_GR_HELPER) + if (IS_DEBUG_OSPF6_GR) zlog_debug("%s, Exiting from HELPER support to %pI6, due to %s", __func__, &nbr->linklocal_addr, ospf6_exit_reason_desc[reason]); @@ -448,7 +458,7 @@ void ospf6_gr_helper_exit(struct ospf6_neighbor *nbr, ospf6->ospf6_helper_cfg.last_exit_reason = reason; /* If the exit not triggered due to grace timer - * expairy , stop the grace timer. + * expiry, stop the grace timer. */ if (reason != OSPF6_GR_HELPER_GRACE_TIMEOUT) THREAD_OFF(nbr->gr_helper_info.t_grace_timer); @@ -458,14 +468,14 @@ void ospf6_gr_helper_exit(struct ospf6_neighbor *nbr, "OSPF6 GR-Helper: Number of active Restarters should be greater than zero."); return; } - /* Decrement active Restarter count */ + /* Decrement active restarter count */ ospf6->ospf6_helper_cfg.active_restarter_cnt--; /* check exit triggered due to successful completion * of graceful restart. */ if (reason != OSPF6_GR_HELPER_COMPLETED) { - if (IS_DEBUG_OSPF6_GR_HELPER) + if (IS_DEBUG_OSPF6_GR) zlog_debug("%s, Unsuccessful GR exit. RESTARTER : %pI6", __func__, &nbr->linklocal_addr); } @@ -482,8 +492,8 @@ void ospf6_gr_helper_exit(struct ospf6_neighbor *nbr, } /* - * Process Maxage Grace LSA. - * It is a indication for successfull completion of GR. + * Process max age Grace LSA. + * It is a indication for successful completion of GR. * If router acting as HELPER, It exits from helper role. * * ospf6 @@ -493,7 +503,7 @@ void ospf6_gr_helper_exit(struct ospf6_neighbor *nbr, * Grace LSA received from RESTARTER. * * nbr - * ospf6 neighbour which requets the router to act as + * ospf6 neighbour which request the router to act as * HELPER. * * Returns: @@ -510,13 +520,12 @@ void ospf6_process_maxage_grace_lsa(struct ospf6 *ospf6, struct ospf6_lsa *lsa, ret = ospf6_extract_grace_lsa_fields(lsa, &grace_interval, &restart_reason); if (ret != OSPF6_SUCCESS) { - if (IS_DEBUG_OSPF6_GR_HELPER) - zlog_debug("%s, Wrong Grace LSA packet.", - __func__); + if (IS_DEBUG_OSPF6_GR) + zlog_debug("%s, Wrong Grace LSA packet.", __func__); return; } - if (IS_DEBUG_OSPF6_GR_HELPER) + if (IS_DEBUG_OSPF6_GR) zlog_debug("%s, GraceLSA received for neighbour %pI4.", __func__, &restarter->router_id); @@ -530,7 +539,7 @@ void ospf6_process_maxage_grace_lsa(struct ospf6 *ospf6, struct ospf6_lsa *lsa, * ospf6 * ospf6 pointer * lsa - * topo change occured due to this lsa(type (1-5 and 7) + * topo change occurred due to this lsa(type (1-5 and 7) * * Returns: * Nothing @@ -545,16 +554,15 @@ void ospf6_helper_handle_topo_chg(struct ospf6 *ospf6, struct ospf6_lsa *lsa) if (!ospf6->ospf6_helper_cfg.active_restarter_cnt) return; - /* Topo change not required to be hanlded if strict - * LSA check is disbaled for this router. + /* Topo change not required to be handled if strict + * LSA check is disabled for this router. */ if (!ospf6->ospf6_helper_cfg.strict_lsa_check) return; - if (IS_DEBUG_OSPF6_GR_HELPER) - zlog_debug( - "%s, Topo change detected due to lsa details : %s", - __func__, lsa->name); + if (IS_DEBUG_OSPF6_GR) + zlog_debug("%s, Topo change detected due to lsa details : %s", + __func__, lsa->name); lsa->tobe_acknowledged = OSPF6_TRUE; @@ -582,22 +590,704 @@ void ospf6_helper_handle_topo_chg(struct ospf6 *ospf6, struct ospf6_lsa *lsa) } } +/* Configuration handlers */ +/* + * Disable/Enable HELPER support on router level. + * + * ospf6 + * Ospf6 pointer. + * + * status + * TRUE/FALSE + * + * Returns: + * Nothing. + */ +static void ospf6_gr_helper_support_set(struct ospf6 *ospf6, bool support) +{ + struct ospf6_interface *oi; + struct advRtr lookup; + struct listnode *i, *j, *k; + struct ospf6_neighbor *nbr = NULL; + struct ospf6_area *oa = NULL; + + if (ospf6->ospf6_helper_cfg.is_helper_supported == support) + return; + + ospf6->ospf6_helper_cfg.is_helper_supported = support; + + /* If helper support disabled, cease HELPER role for all + * supporting neighbors. + */ + if (support == OSPF6_FALSE) { + for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) + for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { + + for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, k, + nbr)) { + + lookup.advRtrAddr = nbr->router_id; + /* check if helper support enabled for + * the corresponding routerid. + * If enabled, + * dont exit from helper role. + */ + if (hash_lookup( + ospf6->ospf6_helper_cfg + .enable_rtr_list, + &lookup)) + continue; + + ospf6_gr_helper_exit( + nbr, OSPF6_GR_HELPER_TOPO_CHG); + } + } + } +} + +/* + * Api to enable/disable strict lsa check on the HELPER. + * + * ospf6 + * Ospf6 pointer. + * + * enabled + * True - disable the lsa check. + * False - enable the strict lsa check. + * + * Returns: + * Nothing. + */ +static void ospf6_gr_helper_lsacheck_set(struct ospf6 *ospf6, bool enabled) +{ + if (ospf6->ospf6_helper_cfg.strict_lsa_check == enabled) + return; + + ospf6->ospf6_helper_cfg.strict_lsa_check = enabled; +} + +/* + * Api to set the supported restart reason. + * + * ospf6 + * Ospf6 pointer. + * + * only_planned + * True: support only planned restart. + * False: support for planned/unplanned restarts. + * + * Returns: + * Nothing. + */ + +static void +ospf6_gr_helper_set_supported_onlyPlanned_restart(struct ospf6 *ospf6, + bool only_planned) +{ + ospf6->ospf6_helper_cfg.only_planned_restart = only_planned; +} + +/* + * Api to set the supported grace interval in this router. + * + * ospf6 + * Ospf6 pointer. + * + * interval + * The supported grace interval.. + * + * Returns: + * Nothing. + */ +static void ospf6_gr_helper_supported_gracetime_set(struct ospf6 *ospf6, + uint32_t interval) +{ + ospf6->ospf6_helper_cfg.supported_grace_time = interval; +} + +/* API to walk and print all the Helper supported router ids */ +static int ospf6_print_vty_helper_dis_rtr_walkcb(struct hash_bucket *bucket, + void *arg) +{ + struct advRtr *rtr = bucket->data; + struct vty *vty = (struct vty *)arg; + static unsigned int count; + + vty_out(vty, "%-6pI4,", &rtr->advRtrAddr); + count++; + + if (count % 5 == 0) + vty_out(vty, "\n"); + + return HASHWALK_CONTINUE; +} + +/* API to walk and print all the Helper supported router ids.*/ +static int ospf6_print_json_helper_dis_rtr_walkcb(struct hash_bucket *bucket, + void *arg) +{ + struct advRtr *rtr = bucket->data; + struct json_object *json_rid_array = (struct json_object *)arg; + struct json_object *json_rid; + char router_id[16]; + + inet_ntop(AF_INET, &rtr->advRtrAddr, router_id, sizeof(router_id)); + + json_rid = json_object_new_object(); + + json_object_string_add(json_rid, "routerId", router_id); + json_object_array_add(json_rid_array, json_rid); + + return HASHWALK_CONTINUE; +} + +/* + * Enable/Disable HELPER support on a specified advertisement + * router. + * + * ospf6 + * Ospf6 pointer. + * + * advRtr + * HELPER support for given Advertisement Router. + * + * support + * True - Enable Helper Support. + * False - Disable Helper Support. + * + * Returns: + * Nothing. + */ +static void ospf6_gr_helper_support_set_per_routerid(struct ospf6 *ospf6, + struct in_addr router_id, + bool support) +{ + struct advRtr temp; + struct advRtr *rtr; + struct listnode *i, *j, *k; + struct ospf6_interface *oi; + struct ospf6_neighbor *nbr; + struct ospf6_area *oa; + + temp.advRtrAddr = router_id.s_addr; + + if (support == OSPF6_FALSE) { + /*Delete the routerid from the enable router hash table */ + rtr = hash_lookup(ospf6->ospf6_helper_cfg.enable_rtr_list, + &temp); + + if (rtr) { + hash_release(ospf6->ospf6_helper_cfg.enable_rtr_list, + rtr); + ospf6_disable_rtr_hash_free(rtr); + } + + /* If helper support is enabled globally + * no action is required. + */ + if (ospf6->ospf6_helper_cfg.is_helper_supported) + return; + + /* Cease the HELPER role fore neighbours from the + * specified advertisement router. + */ + for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) + for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { + + for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, k, + nbr)) { + + if (nbr->router_id != router_id.s_addr) + continue; + + if (OSPF6_GR_IS_ACTIVE_HELPER(nbr)) + ospf6_gr_helper_exit( + nbr, + OSPF6_GR_HELPER_TOPO_CHG); + } + } + + } else { + /* Add the routerid to the enable router hash table */ + hash_get(ospf6->ospf6_helper_cfg.enable_rtr_list, &temp, + ospf6_enable_rtr_hash_alloc); + } +} + +static void show_ospfv6_gr_helper_per_nbr(struct vty *vty, json_object *json, + bool uj, struct ospf6_neighbor *nbr) +{ + if (!uj) { + vty_out(vty, " Routerid : %pI4\n", &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", + ospf6_restart_reason_desc[nbr->gr_helper_info + .gr_restart_reason]); + } else { + char nbrid[16]; + json_object *json_neigh = NULL; + + inet_ntop(AF_INET, &nbr->router_id, nbrid, sizeof(nbrid)); + json_neigh = json_object_new_object(); + json_object_string_add(json_neigh, "routerid", nbrid); + 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", + ospf6_restart_reason_desc[ + nbr->gr_helper_info.gr_restart_reason]); + json_object_object_add(json, nbr->name, json_neigh); + } +} + +static int show_ospf6_gr_helper_details(struct vty *vty, struct ospf6 *ospf6, + json_object *json, bool uj, bool detail) +{ + struct ospf6_interface *oi; + + /* Show Router ID. */ + if (uj) { + char router_id[16]; + + inet_ntop(AF_INET, &ospf6->router_id, router_id, + sizeof(router_id)); + json_object_string_add(json, "routerId", router_id); + } else + vty_out(vty, + " OSPFv3 Routing Process (0) with Router-ID %pI4\n", + &ospf6->router_id); + + if (!uj) { + + if (ospf6->ospf6_helper_cfg.is_helper_supported) + vty_out(vty, + " Graceful restart helper support enabled.\n"); + else + vty_out(vty, + " Graceful restart helper support disabled.\n"); + + if (ospf6->ospf6_helper_cfg.strict_lsa_check) + vty_out(vty, " Strict LSA check is enabled.\n"); + else + vty_out(vty, " Strict LSA check is disabled.\n"); + + if (ospf6->ospf6_helper_cfg.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", + ospf6->ospf6_helper_cfg.supported_grace_time); + + if (OSPF6_HELPER_ENABLE_RTR_COUNT(ospf)) { + vty_out(vty, " Enable Router list:\n"); + vty_out(vty, " "); + hash_walk(ospf6->ospf6_helper_cfg.enable_rtr_list, + ospf6_print_vty_helper_dis_rtr_walkcb, vty); + vty_out(vty, "\n\n"); + } + + if (ospf6->ospf6_helper_cfg.last_exit_reason + != OSPF6_GR_HELPER_EXIT_NONE) { + vty_out(vty, " Last Helper exit Reason :%s\n", + ospf6_exit_reason_desc + [ospf6->ospf6_helper_cfg + .last_exit_reason]); + + if (ospf6->ospf6_helper_cfg.active_restarter_cnt) + vty_out(vty, + " Number of Active neighbours in graceful restart: %d\n", + ospf6->ospf6_helper_cfg + .active_restarter_cnt); + else + vty_out(vty, "\n"); + } + + + } else { + json_object_string_add( + json, "helperSupport", + (ospf6->ospf6_helper_cfg.is_helper_supported) + ? "Enabled" + : "Disabled"); + json_object_string_add( + json, "strictLsaCheck", + (ospf6->ospf6_helper_cfg.strict_lsa_check) + ? "Enabled" + : "Disabled"); + json_object_string_add( + json, "restartSupoort", + (ospf6->ospf6_helper_cfg.only_planned_restart) + ? "Planned Restart only" + : "Planned and Unplanned Restarts"); + + json_object_int_add( + json, "supportedGracePeriod", + ospf6->ospf6_helper_cfg.supported_grace_time); + + if (ospf6->ospf6_helper_cfg.last_exit_reason + != OSPF6_GR_HELPER_EXIT_NONE) + json_object_string_add( + json, "LastExitReason", + ospf6_exit_reason_desc + [ospf6->ospf6_helper_cfg + .last_exit_reason]); + + if (OSPF6_HELPER_ENABLE_RTR_COUNT(ospf6)) { + struct json_object *json_rid_array = + json_object_new_array(); + + json_object_object_add(json, "enabledRouterIds", + json_rid_array); + + hash_walk(ospf6->ospf6_helper_cfg.enable_rtr_list, + ospf6_print_json_helper_dis_rtr_walkcb, + json_rid_array); + } + } + + if (detail) { + int cnt = 1; + struct listnode *i, *j, *k; + struct ospf6_area *oa; + json_object *json_neighbors = NULL; + + for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) + for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { + struct ospf6_neighbor *nbr; + + if (uj) { + json_object_object_get_ex( + json, "Neighbors", + &json_neighbors); + if (!json_neighbors) { + json_neighbors = + json_object_new_object(); + json_object_object_add( + json, "Neighbors", + json_neighbors); + } + } + + for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, k, + nbr)) { + + if (!OSPF6_GR_IS_ACTIVE_HELPER(nbr)) + continue; + + if (!uj) + vty_out(vty, + " Neighbour %d :\n", + cnt++); + + show_ospfv6_gr_helper_per_nbr( + vty, json_neighbors, uj, nbr); + + } + } + } + + return CMD_SUCCESS; +} + +/* Graceful Restart HELPER config Commands */ +DEFPY(ospf6_gr_helper_enable, + ospf6_gr_helper_enable_cmd, + "graceful-restart helper-only [A.B.C.D$rtr_id]", + "ospf6 graceful restart\n" + "Enable Helper support\n" + "Advertisement RouterId\n") +{ + VTY_DECLVAR_CONTEXT(ospf6, ospf6); + + if (rtr_id_str != NULL) { + + ospf6_gr_helper_support_set_per_routerid(ospf6, rtr_id, + OSPF6_TRUE); + + return CMD_SUCCESS; + } + + ospf6_gr_helper_support_set(ospf6, OSPF6_TRUE); + + return CMD_SUCCESS; +} + +DEFPY(ospf6_gr_helper_disable, + ospf6_gr_helper_disable_cmd, + "no graceful-restart helper-only [A.B.C.D$rtr_id]", + NO_STR + "ospf6 graceful restart\n" + "Disable Helper support\n" + "Advertisement RouterId\n") +{ + VTY_DECLVAR_CONTEXT(ospf6, ospf6); + + if (rtr_id_str != NULL) { + + ospf6_gr_helper_support_set_per_routerid(ospf6, rtr_id, + OSPF6_FALSE); + + return CMD_SUCCESS; + } + + ospf6_gr_helper_support_set(ospf6, OSPF6_FALSE); + + return CMD_SUCCESS; +} + +DEFPY(ospf6_gr_helper_disable_lsacheck, + ospf6_gr_helper_disable_lsacheck_cmd, + "graceful-restart helper lsa-check-disable", + "ospf6 graceful restart\n" + "ospf6 GR Helper\n" + "disable strict LSA check\n") +{ + VTY_DECLVAR_CONTEXT(ospf6, ospf6); + + ospf6_gr_helper_lsacheck_set(ospf6, OSPF6_FALSE); + return CMD_SUCCESS; +} + +DEFPY(no_ospf6_gr_helper_disable_lsacheck, + no_ospf6_gr_helper_disable_lsacheck_cmd, + "no graceful-restart helper lsa-check-disable", + NO_STR + "ospf6 graceful restart\n" + "ospf6 GR Helper\n" + "diasble strict LSA check\n") +{ + VTY_DECLVAR_CONTEXT(ospf6, ospf6); + + ospf6_gr_helper_lsacheck_set(ospf6, OSPF6_TRUE); + return CMD_SUCCESS; +} + +DEFPY(ospf6_gr_helper_planned_only, + ospf6_gr_helper_planned_only_cmd, + "graceful-restart helper planned-only", + "ospf6 graceful restart\n" + "ospf6 GR Helper\n" + "supported only planned restart\n") +{ + VTY_DECLVAR_CONTEXT(ospf6, ospf6); + + ospf6_gr_helper_set_supported_onlyPlanned_restart(ospf6, OSPF6_TRUE); + + return CMD_SUCCESS; +} + +DEFPY(no_ospf6_gr_helper_planned_only, no_ospf6_gr_helper_planned_only_cmd, + "no graceful-restart helper planned-only", + NO_STR + "ospf6 graceful restart\n" + "ospf6 GR Helper\n" + "supported only for planned restart\n") +{ + VTY_DECLVAR_CONTEXT(ospf6, ospf6); + + ospf6_gr_helper_set_supported_onlyPlanned_restart(ospf6, OSPF6_FALSE); + + return CMD_SUCCESS; +} + +DEFPY(ospf6_gr_helper_supported_grace_time, + ospf6_gr_helper_supported_grace_time_cmd, + "graceful-restart helper supported-grace-time (10-1800)$interval", + "ospf6 graceful restart\n" + "ospf6 GR Helper\n" + "supported grace timer\n" + "grace interval(in seconds)\n") +{ + VTY_DECLVAR_CONTEXT(ospf6, ospf6); + + ospf6_gr_helper_supported_gracetime_set(ospf6, interval); + return CMD_SUCCESS; +} + +DEFPY(no_ospf6_gr_helper_supported_grace_time, + no_ospf6_gr_helper_supported_grace_time_cmd, + "no graceful-restart helper supported-grace-time (10-1800)$interval", + NO_STR + "ospf6 graceful restart\n" + "ospf6 GR Helper\n" + "supported grace timer\n" + "grace interval(in seconds)\n") +{ + VTY_DECLVAR_CONTEXT(ospf6, ospf6); + + ospf6_gr_helper_supported_gracetime_set(ospf6, + OSPF6_MAX_GRACE_INTERVAL); + return CMD_SUCCESS; +} + +/* Show commands */ +DEFPY(show_ipv6_ospf6_gr_helper, + show_ipv6_ospf6_gr_helper_cmd, + "show ipv6 ospf6 graceful-restart helper [detail] [json]", + SHOW_STR + "Ipv6 Information\n" + "OSPF6 information\n" + "ospf6 graceful restart\n" + "helper details in the router\n" + "detailed information\n" JSON_STR) +{ + int idx = 0; + bool uj = use_json(argc, argv); + struct ospf6 *ospf6 = NULL; + json_object *json = NULL; + bool detail = false; + + ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME); + OSPF6_CMD_CHECK_RUNNING(); + + if (argv_find(argv, argc, "detail", &idx)) + detail = true; + + if (uj) + json = json_object_new_object(); + + show_ospf6_gr_helper_details(vty, ospf6, 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; +} + /* Debug commands */ -DEFPY(debug_ospf6_gr, - debug_ospf6_gr_cmd, +DEFPY(debug_ospf6_gr, debug_ospf6_gr_cmd, "[no$no] debug ospf6 graceful-restart", - NO_STR - DEBUG_STR OSPF6_STR - "Graceful restart\n") + NO_STR DEBUG_STR OSPF6_STR "Graceful restart\n") { if (!no) - OSPF6_DEBUG_GR_HELPER_ON(); + OSPF6_DEBUG_GR_ON(); else - OSPF6_DEBUG_GR_HELPER_OFF(); + OSPF6_DEBUG_GR_OFF(); return CMD_SUCCESS; } +/* + * Api to display the grace LSA information. + * + * vty + * vty pointer. + * lsa + * Grace LSA. + * json + * json object + * + * Returns: + * Nothing. + */ +static int ospf6_grace_lsa_show_info(struct vty *vty, struct ospf6_lsa *lsa, + json_object *json, bool use_json) +{ + struct ospf6_lsa_header *lsah = NULL; + struct tlv_header *tlvh = NULL; + struct grace_tlv_graceperiod *gracePeriod; + struct grace_tlv_restart_reason *grReason; + uint16_t length = 0; + int sum = 0; + + lsah = (struct ospf6_lsa_header *)lsa->header; + + length = ntohs(lsah->length) - OSPF6_LSA_HEADER_SIZE; + + if (vty) { + if (!use_json) + vty_out(vty, "TLV info:\n"); + } else { + zlog_debug(" TLV info:"); + } + + 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); + + if (vty) { + if (use_json) + json_object_int_add( + json, "gracePeriod", + ntohl(gracePeriod->interval)); + else + vty_out(vty, " Grace period:%d\n", + ntohl(gracePeriod->interval)); + } else { + zlog_debug(" Grace period:%d", + ntohl(gracePeriod->interval)); + } + break; + case RESTART_REASON_TYPE: + grReason = (struct grace_tlv_restart_reason *)tlvh; + sum += TLV_SIZE(tlvh); + if (vty) { + if (use_json) + json_object_string_add( + json, "restartReason", + ospf6_restart_reason_desc + [grReason->reason]); + else + vty_out(vty, " Restart reason:%s\n", + ospf6_restart_reason_desc + [grReason->reason]); + } else { + zlog_debug(" Restart reason:%s", + ospf6_restart_reason_desc + [grReason->reason]); + } + break; + default: + break; + } + } + + return 0; +} + +void ospf6_gr_helper_config_init(void) +{ + + ospf6_install_lsa_handler(&grace_lsa_handler); + + install_element(OSPF6_NODE, &ospf6_gr_helper_enable_cmd); + install_element(OSPF6_NODE, &ospf6_gr_helper_disable_cmd); + install_element(OSPF6_NODE, &ospf6_gr_helper_disable_lsacheck_cmd); + install_element(OSPF6_NODE, &no_ospf6_gr_helper_disable_lsacheck_cmd); + install_element(OSPF6_NODE, &ospf6_gr_helper_planned_only_cmd); + install_element(OSPF6_NODE, &no_ospf6_gr_helper_planned_only_cmd); + install_element(OSPF6_NODE, &ospf6_gr_helper_supported_grace_time_cmd); + install_element(OSPF6_NODE, + &no_ospf6_gr_helper_supported_grace_time_cmd); + + install_element(VIEW_NODE, &show_ipv6_ospf6_gr_helper_cmd); + + install_element(CONFIG_NODE, &debug_ospf6_gr_cmd); + install_element(ENABLE_NODE, &debug_ospf6_gr_cmd); +} + + /* * Initialize GR helper config data structure. * @@ -609,7 +1299,7 @@ DEFPY(debug_ospf6_gr, */ void ospf6_gr_helper_init(struct ospf6 *ospf6) { - if (IS_DEBUG_OSPF6_GR_HELPER) + if (IS_DEBUG_OSPF6_GR) zlog_debug("%s, GR Helper init.", __func__); ospf6->ospf6_helper_cfg.is_helper_supported = OSPF6_FALSE; @@ -625,7 +1315,7 @@ void ospf6_gr_helper_init(struct ospf6 *ospf6) } /* - * De-Initilise GR helper config datastructer. + * De-initialize GR helper config data structure. * * ospf6 * ospf6 pointer @@ -636,8 +1326,50 @@ void ospf6_gr_helper_init(struct ospf6 *ospf6) void ospf6_gr_helper_deinit(struct ospf6 *ospf6) { - if (IS_DEBUG_OSPF6_GR_HELPER) + if (IS_DEBUG_OSPF6_GR) zlog_debug("%s, GR helper deinit.", __func__); ospf6_enable_rtr_hash_destroy(ospf6); } + +static int ospf6_cfg_write_helper_enable_rtr_walkcb(struct hash_bucket *backet, + void *arg) +{ + struct advRtr *rtr = backet->data; + struct vty *vty = (struct vty *)arg; + + vty_out(vty, " graceful-restart helper-only %pI4\n", &rtr->advRtrAddr); + return HASHWALK_CONTINUE; +} + +int config_write_ospf6_gr_helper(struct vty *vty, struct ospf6 *ospf6) +{ + if (ospf6->ospf6_helper_cfg.is_helper_supported) + vty_out(vty, " graceful-restart helper-only\n"); + + if (!ospf6->ospf6_helper_cfg.strict_lsa_check) + vty_out(vty, " graceful-restart helper lsa-check-disable\n"); + + if (ospf6->ospf6_helper_cfg.only_planned_restart) + vty_out(vty, " graceful-restart helper planned-only\n"); + + if (ospf6->ospf6_helper_cfg.supported_grace_time + != OSPF6_MAX_GRACE_INTERVAL) + vty_out(vty, + " graceful-restart helper supported-grace-time %d\n", + ospf6->ospf6_helper_cfg.supported_grace_time); + + if (OSPF6_HELPER_ENABLE_RTR_COUNT(ospf6)) { + hash_walk(ospf6->ospf6_helper_cfg.enable_rtr_list, + ospf6_cfg_write_helper_enable_rtr_walkcb, vty); + } + + return 0; +} + +int config_write_ospf6_debug_gr_helper(struct vty *vty) +{ + if (IS_DEBUG_OSPF6_GR) + vty_out(vty, "debug ospf6 gr helper\n"); + return 0; +} diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c index a80ec4430f..cd73e3d406 100644 --- a/ospf6d/ospf6_message.c +++ b/ospf6d/ospf6_message.c @@ -515,7 +515,7 @@ static void ospf6_hello_recv(struct in6_addr *src, struct in6_addr *dst, if (twoway) thread_execute(master, twoway_received, on, 0); else { - if (IS_DEBUG_OSPF6_GR_HELPER) + if (IS_DEBUG_OSPF6_GR) zlog_debug( "%s, Received oneway hello from RESTARTER so ignore here.", __PRETTY_FUNCTION__); @@ -545,7 +545,7 @@ static void ospf6_hello_recv(struct in6_addr *src, struct in6_addr *dst, * period, it can handle if there is any change before GR and * after GR. */ - if (IS_DEBUG_OSPF6_GR_HELPER) + if (IS_DEBUG_OSPF6_GR) zlog_debug( "%s, Neighbor is under GR Restart, hence ignoring the ISM Events", __PRETTY_FUNCTION__); @@ -1302,7 +1302,7 @@ static unsigned ospf6_lsa_examin(struct ospf6_lsa_header *lsah, case OSPF6_LSTYPE_GRACE_LSA: if (lsalen < OSPF6_LSA_HEADER_SIZE + GRACE_PERIOD_TLV_SIZE + GRACE_RESTART_REASON_TLV_SIZE) { - if (IS_DEBUG_OSPF6_GR_HELPER) + if (IS_DEBUG_OSPF6_GR) zlog_debug("%s: Undersized GraceLSA.", __func__); return MSG_NG; diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c index 331b75f803..4ea615f32b 100644 --- a/ospf6d/ospf6_neighbor.c +++ b/ospf6d/ospf6_neighbor.c @@ -622,7 +622,7 @@ int inactivity_timer(struct thread *thread) ospf6_neighbor_delete(on); } else { - if (IS_DEBUG_OSPF6_GR_HELPER) + if (IS_DEBUG_OSPF6_GR) zlog_debug( "%s, Acting as HELPER for this neighbour, So restart the dead timer.", __PRETTY_FUNCTION__); diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 37361de689..fc181a6d18 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -2236,6 +2236,7 @@ static int config_write_ospf6(struct vty *vty) ospf6_distance_config_write(vty, ospf6); ospf6_distribute_config_write(vty, ospf6); ospf6_asbr_summary_config_write(vty, ospf6); + config_write_ospf6_gr_helper(vty, ospf6); vty_out(vty, "!\n"); } return 0; diff --git a/ospf6d/ospf6d.c b/ospf6d/ospf6d.c index fb6ac4402a..5dfd986e2a 100644 --- a/ospf6d/ospf6d.c +++ b/ospf6d/ospf6d.c @@ -45,6 +45,7 @@ #include "ospf6_flood.h" #include "ospf6d.h" #include "ospf6_bfd.h" +#include "ospf6_gr.h" #include "lib/json.h" #include "ospf6_nssa.h" @@ -96,6 +97,7 @@ static int config_write_ospf6_debug(struct vty *vty) config_write_ospf6_debug_abr(vty); config_write_ospf6_debug_flood(vty); config_write_ospf6_debug_nssa(vty); + config_write_ospf6_debug_gr_helper(vty); return 0; } @@ -1402,6 +1404,7 @@ void ospf6_init(struct thread_master *master) ospf6_intra_init(); ospf6_asbr_init(); ospf6_abr_init(); + ospf6_gr_helper_config_init(); /* initialize hooks for modifying filter rules */ prefix_list_add_hook(ospf6_plist_add);