back to topotato report
topotato coverage report
Current view: top level - ospfd - ospf_gr_helper.c (source / functions) Hit Total Coverage
Test: aggregated run ( view descriptions ) Lines: 26 414 6.3 %
Date: 2023-02-24 19:38:44 Functions: 4 25 16.0 %

          Line data    Source code
       1             : /*
       2             :  * OSPF Graceful Restart helper functions.
       3             :  *
       4             :  * Copyright (C) 2020-21 Vmware, Inc.
       5             :  * Rajesh Kumar Girada
       6             :  *
       7             :  * This file is part of GNU Zebra.
       8             :  *
       9             :  * GNU Zebra is free software; you can redistribute it and/or modify it
      10             :  * under the terms of the GNU General Public License as published by the
      11             :  * Free Software Foundation; either version 2, or (at your option) any
      12             :  * later version.
      13             :  *
      14             :  * GNU Zebra is distributed in the hope that it will be useful, but
      15             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      17             :  * General Public License for more details.
      18             :  *
      19             :  * You should have received a copy of the GNU General Public License along
      20             :  * with this program; see the file COPYING; if not, write to the Free Software
      21             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      22             :  */
      23             : 
      24             : #include <zebra.h>
      25             : 
      26             : #include "thread.h"
      27             : #include "memory.h"
      28             : #include "linklist.h"
      29             : #include "prefix.h"
      30             : #include "if.h"
      31             : #include "table.h"
      32             : #include "vty.h"
      33             : #include "filter.h"
      34             : #include "log.h"
      35             : #include "jhash.h"
      36             : 
      37             : #include "ospfd/ospfd.h"
      38             : #include "ospfd/ospf_interface.h"
      39             : #include "ospfd/ospf_asbr.h"
      40             : #include "ospfd/ospf_lsa.h"
      41             : #include "ospfd/ospf_lsdb.h"
      42             : #include "ospfd/ospf_neighbor.h"
      43             : #include "ospfd/ospf_spf.h"
      44             : #include "ospfd/ospf_flood.h"
      45             : #include "ospfd/ospf_route.h"
      46             : #include "ospfd/ospf_zebra.h"
      47             : #include "ospfd/ospf_dump.h"
      48             : #include "ospfd/ospf_errors.h"
      49             : #include "ospfd/ospf_nsm.h"
      50             : #include "ospfd/ospf_ism.h"
      51             : #include "ospfd/ospf_gr.h"
      52             : 
      53             : static const char * const ospf_exit_reason_desc[] = {
      54             :         "Unknown reason",
      55             :         "Helper in progress",
      56             :         "Topology Change",
      57             :         "Grace timer expiry",
      58             :         "Successful graceful restart",
      59             : };
      60             : 
      61             : static const char * const ospf_restart_reason_desc[] = {
      62             :         "Unknown restart",
      63             :         "Software restart",
      64             :         "Software reload/upgrade",
      65             :         "Switch to redundant control processor",
      66             : };
      67             : 
      68             : static const char * const ospf_rejected_reason_desc[] = {
      69             :         "Unknown reason",
      70             :         "Helper support disabled",
      71             :         "Neighbour is not in FULL state",
      72             :         "Supports only planned restart but received unplanned",
      73             :         "Topo change due to change in lsa rxmt list",
      74             :         "LSA age is more than Grace interval",
      75             :         "Router is in the process of graceful restart",
      76             : };
      77             : 
      78             : static void show_ospf_grace_lsa_info(struct vty *vty, struct json_object *json,
      79             :                                      struct ospf_lsa *lsa);
      80             : static bool ospf_check_change_in_rxmt_list(struct ospf_neighbor *nbr);
      81             : 
      82           0 : static unsigned int ospf_enable_rtr_hash_key(const void *data)
      83             : {
      84           0 :         const struct advRtr *rtr = data;
      85             : 
      86           0 :         return jhash_1word(rtr->advRtrAddr.s_addr, 0);
      87             : }
      88             : 
      89           0 : static bool ospf_enable_rtr_hash_cmp(const void *d1, const void *d2)
      90             : {
      91           0 :         const struct advRtr *rtr1 = (struct advRtr *)d1;
      92           0 :         const struct advRtr *rtr2 = (struct advRtr *)d2;
      93             : 
      94           0 :         return (rtr1->advRtrAddr.s_addr == rtr2->advRtrAddr.s_addr);
      95             : }
      96             : 
      97           0 : static void *ospf_enable_rtr_hash_alloc(void *p)
      98             : {
      99           0 :         struct advRtr *rid;
     100             : 
     101           0 :         rid = XCALLOC(MTYPE_OSPF_GR_HELPER, sizeof(struct advRtr));
     102           0 :         rid->advRtrAddr.s_addr = ((struct in_addr *)p)->s_addr;
     103             : 
     104           0 :         return rid;
     105             : }
     106             : 
     107           0 : static void ospf_disable_rtr_hash_free(void *rtr)
     108             : {
     109           0 :         XFREE(MTYPE_OSPF_GR_HELPER, rtr);
     110           0 : }
     111             : 
     112           4 : static void ospf_enable_rtr_hash_destroy(struct ospf *ospf)
     113             : {
     114           4 :         if (ospf->enable_rtr_list == NULL)
     115             :                 return;
     116             : 
     117           4 :         hash_clean(ospf->enable_rtr_list, ospf_disable_rtr_hash_free);
     118           4 :         hash_free(ospf->enable_rtr_list);
     119           4 :         ospf->enable_rtr_list = NULL;
     120             : }
     121             : 
     122             : /*
     123             :  * GR exit reason strings
     124             :  */
     125           0 : const char *ospf_exit_reason2str(unsigned int reason)
     126             : {
     127           0 :         if (reason < array_size(ospf_exit_reason_desc))
     128           0 :                 return(ospf_exit_reason_desc[reason]);
     129             :         else
     130             :                 return "Invalid reason";
     131             : }
     132             : 
     133             : /*
     134             :  * GR restart reason strings
     135             :  */
     136           0 : const char *ospf_restart_reason2str(unsigned int reason)
     137             : {
     138           0 :         if (reason < array_size(ospf_restart_reason_desc))
     139           0 :                 return(ospf_restart_reason_desc[reason]);
     140             :         else
     141             :                 return "Invalid reason";
     142             : }
     143             : 
     144             : /*
     145             :  * GR rejected reason strings
     146             :  */
     147           0 : const char *ospf_rejected_reason2str(unsigned int reason)
     148             : {
     149           0 :         if (reason < array_size(ospf_rejected_reason_desc))
     150           0 :                 return(ospf_rejected_reason_desc[reason]);
     151             :         else
     152             :                 return "Invalid reason";
     153             : }
     154             : 
     155             : /*
     156             :  * Initialize GR helper config data structures.
     157             :  *
     158             :  * OSPF
     159             :  *    OSPF pointer
     160             :  *
     161             :  * Returns:
     162             :  *    Nothing
     163             :  */
     164           4 : void ospf_gr_helper_instance_init(struct ospf *ospf)
     165             : {
     166           4 :         if (IS_DEBUG_OSPF_GR)
     167           0 :                 zlog_debug("%s, GR Helper init.", __func__);
     168             : 
     169           4 :         ospf->is_helper_supported = OSPF_GR_FALSE;
     170           4 :         ospf->strict_lsa_check = OSPF_GR_TRUE;
     171           4 :         ospf->only_planned_restart = OSPF_GR_FALSE;
     172           4 :         ospf->supported_grace_time = OSPF_MAX_GRACE_INTERVAL;
     173           4 :         ospf->last_exit_reason = OSPF_GR_HELPER_EXIT_NONE;
     174           4 :         ospf->active_restarter_cnt = 0;
     175             : 
     176           8 :         ospf->enable_rtr_list =
     177           4 :                 hash_create(ospf_enable_rtr_hash_key, ospf_enable_rtr_hash_cmp,
     178             :                             "OSPF enable router hash");
     179           4 : }
     180             : 
     181             : /*
     182             :  * De-Initialize GR helper config data structures.
     183             :  *
     184             :  * OSPF
     185             :  *    OSPF pointer
     186             :  *
     187             :  * Returns:
     188             :  *    Nothing
     189             :  */
     190           4 : void ospf_gr_helper_instance_stop(struct ospf *ospf)
     191             : {
     192           4 :         if (IS_DEBUG_OSPF_GR)
     193           0 :                 zlog_debug("%s, GR helper deinit.", __func__);
     194             : 
     195           4 :         ospf_enable_rtr_hash_destroy(ospf);
     196           4 : }
     197             : 
     198             : /*
     199             :  * Initialize GR helper config data structures.
     200             :  *
     201             :  * Returns:
     202             :  *    Nothing
     203             :  */
     204           4 : void ospf_gr_helper_init(void)
     205             : {
     206           4 :         int rc;
     207             : 
     208           4 :         if (IS_DEBUG_OSPF_GR)
     209           0 :                 zlog_debug("%s, GR Helper init.", __func__);
     210             : 
     211           4 :         rc = ospf_register_opaque_functab(
     212             :                 OSPF_OPAQUE_LINK_LSA, OPAQUE_TYPE_GRACE_LSA, NULL, NULL, NULL,
     213             :                 NULL, NULL, NULL, NULL, show_ospf_grace_lsa_info, NULL, NULL,
     214             :                 NULL, NULL);
     215           4 :         if (rc != 0) {
     216           0 :                 flog_warn(EC_OSPF_OPAQUE_REGISTRATION,
     217             :                           "%s: Failed to register Grace LSA functions",
     218             :                                 __func__);
     219             :         }
     220           4 : }
     221             : 
     222             : /*
     223             :  * De-Initialize GR helper config data structures.
     224             :  *
     225             :  * Returns:
     226             :  *    Nothing
     227             :  */
     228           0 : void ospf_gr_helper_stop(void)
     229             : {
     230           0 :         if (IS_DEBUG_OSPF_GR)
     231           0 :                 zlog_debug("%s, GR helper deinit.", __func__);
     232             : 
     233           0 :         ospf_delete_opaque_functab(OSPF_OPAQUE_LINK_LSA, OPAQUE_TYPE_GRACE_LSA);
     234           0 : }
     235             : 
     236             : /*
     237             :  * Extracting tlv info from GRACE LSA.
     238             :  *
     239             :  * lsa
     240             :  *   ospf grace lsa
     241             :  *
     242             :  * Returns:
     243             :  * interval : grace interval.
     244             :  * addr     : RESTARTER address.
     245             :  * reason   : Restarting reason.
     246             :  */
     247           0 : static int ospf_extract_grace_lsa_fields(struct ospf_lsa *lsa,
     248             :                                          uint32_t *interval,
     249             :                                          struct in_addr *addr, uint8_t *reason)
     250             : {
     251           0 :         struct lsa_header *lsah = NULL;
     252           0 :         struct tlv_header *tlvh = NULL;
     253           0 :         struct grace_tlv_graceperiod *grace_period;
     254           0 :         struct grace_tlv_restart_reason *gr_reason;
     255           0 :         struct grace_tlv_restart_addr *restart_addr;
     256           0 :         uint16_t length = 0;
     257           0 :         int sum = 0;
     258             : 
     259           0 :         lsah = (struct lsa_header *)lsa->data;
     260             : 
     261             :         /* Check LSA len */
     262           0 :         if (lsa->size <= OSPF_LSA_HEADER_SIZE) {
     263           0 :                 if (IS_DEBUG_OSPF_GR)
     264           0 :                         zlog_debug("%s: Malformed packet: Invalid LSA len:%d",
     265             :                                    __func__, length);
     266           0 :                 return OSPF_GR_FAILURE;
     267             :         }
     268             : 
     269           0 :         length = lsa->size - OSPF_LSA_HEADER_SIZE;
     270             : 
     271           0 :         for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh;
     272           0 :              tlvh = TLV_HDR_NEXT(tlvh)) {
     273             : 
     274             :                 /* Check TLV len against overall LSA */
     275           0 :                 if (sum + TLV_SIZE(tlvh) > length) {
     276           0 :                         if (IS_DEBUG_OSPF_GR)
     277           0 :                                 zlog_debug("%s: Malformed packet: Invalid TLV len:%u",
     278             :                                            __func__, TLV_SIZE(tlvh));
     279           0 :                         return OSPF_GR_FAILURE;
     280             :                 }
     281             : 
     282           0 :                 switch (ntohs(tlvh->type)) {
     283           0 :                 case GRACE_PERIOD_TYPE:
     284           0 :                         if (TLV_SIZE(tlvh) <
     285             :                             sizeof(struct grace_tlv_graceperiod)) {
     286           0 :                                 zlog_debug("%s: Malformed packet: Invalid grace TLV len:%u",
     287             :                                            __func__, TLV_SIZE(tlvh));
     288           0 :                                 return OSPF_GR_FAILURE;
     289             :                         }
     290             : 
     291           0 :                         grace_period = (struct grace_tlv_graceperiod *)tlvh;
     292           0 :                         *interval = ntohl(grace_period->interval);
     293           0 :                         sum += TLV_SIZE(tlvh);
     294             : 
     295             :                         /* Check if grace interval is valid */
     296           0 :                         if (*interval > OSPF_MAX_GRACE_INTERVAL
     297           0 :                             || *interval < OSPF_MIN_GRACE_INTERVAL)
     298             :                                 return OSPF_GR_FAILURE;
     299             :                         break;
     300           0 :                 case RESTART_REASON_TYPE:
     301           0 :                         if (TLV_SIZE(tlvh) <
     302             :                             sizeof(struct grace_tlv_restart_reason)) {
     303           0 :                                 zlog_debug("%s: Malformed packet: Invalid reason TLV len:%u",
     304             :                                            __func__, TLV_SIZE(tlvh));
     305           0 :                                 return OSPF_GR_FAILURE;
     306             :                         }
     307             : 
     308           0 :                         gr_reason = (struct grace_tlv_restart_reason *)tlvh;
     309           0 :                         *reason = gr_reason->reason;
     310           0 :                         sum += TLV_SIZE(tlvh);
     311             : 
     312           0 :                         if (*reason >= OSPF_GR_INVALID_REASON_CODE)
     313             :                                 return OSPF_GR_FAILURE;
     314             :                         break;
     315           0 :                 case RESTARTER_IP_ADDR_TYPE:
     316           0 :                         if (TLV_SIZE(tlvh) <
     317             :                             sizeof(struct grace_tlv_restart_addr)) {
     318           0 :                                 zlog_debug("%s: Malformed packet: Invalid addr TLV len:%u",
     319             :                                            __func__, TLV_SIZE(tlvh));
     320           0 :                                 return OSPF_GR_FAILURE;
     321             :                         }
     322             : 
     323           0 :                         restart_addr = (struct grace_tlv_restart_addr *)tlvh;
     324           0 :                         addr->s_addr = restart_addr->addr.s_addr;
     325           0 :                         sum += TLV_SIZE(tlvh);
     326           0 :                         break;
     327           0 :                 default:
     328           0 :                         if (IS_DEBUG_OSPF_GR)
     329           0 :                                 zlog_debug(
     330             :                                         "%s, Malformed packet.Invalid TLV type:%d",
     331             :                                         __func__, ntohs(tlvh->type));
     332             :                         return OSPF_GR_FAILURE;
     333             :                 }
     334             :         }
     335             : 
     336             :         return OSPF_GR_SUCCESS;
     337             : }
     338             : 
     339             : /*
     340             :  * Grace timer expiry handler.
     341             :  * HELPER aborts its role at grace timer expiry.
     342             :  *
     343             :  * thread
     344             :  *    thread pointer
     345             :  *
     346             :  * Returns:
     347             :  *    Nothing
     348             :  */
     349           0 : static void ospf_handle_grace_timer_expiry(struct thread *thread)
     350             : {
     351           0 :         struct ospf_neighbor *nbr = THREAD_ARG(thread);
     352             : 
     353           0 :         nbr->gr_helper_info.t_grace_timer = NULL;
     354             : 
     355           0 :         ospf_gr_helper_exit(nbr, OSPF_GR_HELPER_GRACE_TIMEOUT);
     356           0 : }
     357             : 
     358             : /*
     359             :  * Process Grace LSA.If it is eligible move to HELPER role.
     360             :  * Ref rfc3623 section 3.1
     361             :  *
     362             :  * ospf
     363             :  *    OSPF pointer.
     364             :  *
     365             :  * lsa
     366             :  *    Grace LSA received from RESTARTER.
     367             :  *
     368             :  * nbr
     369             :  *    OSPF neighbour which requests the router to act as
     370             :  *    HELPER.
     371             :  *
     372             :  * Returns:
     373             :  *    status.
     374             :  *    If supported as HELPER : OSPF_GR_HELPER_INPROGRESS
     375             :  *    If Not supported as HELPER : OSPF_GR_HELPER_NONE
     376             :  */
     377           0 : int ospf_process_grace_lsa(struct ospf *ospf, struct ospf_lsa *lsa,
     378             :                            struct ospf_neighbor *nbr)
     379             : {
     380           0 :         struct in_addr restart_addr = {0};
     381           0 :         uint8_t restart_reason = 0;
     382           0 :         uint32_t grace_interval = 0;
     383           0 :         uint32_t actual_grace_interval = 0;
     384           0 :         struct advRtr lookup;
     385           0 :         struct ospf_neighbor *restarter = NULL;
     386           0 :         struct ospf_interface *oi = nbr->oi;
     387           0 :         int ret;
     388             : 
     389             : 
     390             :         /* Extract the grace lsa packet fields */
     391           0 :         ret = ospf_extract_grace_lsa_fields(lsa, &grace_interval, &restart_addr,
     392             :                                             &restart_reason);
     393           0 :         if (ret != OSPF_GR_SUCCESS) {
     394           0 :                 if (IS_DEBUG_OSPF_GR)
     395           0 :                         zlog_debug("%s, Wrong Grace LSA packet.", __func__);
     396           0 :                 return OSPF_GR_NOT_HELPER;
     397             :         }
     398             : 
     399           0 :         if (IS_DEBUG_OSPF_GR)
     400           0 :                 zlog_debug(
     401             :                         "%s, Grace LSA received from %pI4, grace interval:%u, restart reason:%s",
     402             :                         __func__, &restart_addr, grace_interval,
     403             :                         ospf_restart_reason2str(restart_reason));
     404             : 
     405             :         /* In case of broadcast links, if RESTARTER is DR_OTHER,
     406             :          * grace LSA might be received from DR, so need to get
     407             :          * actual neighbour info , here RESTARTER.
     408             :          */
     409           0 :         if (oi->type != OSPF_IFTYPE_POINTOPOINT) {
     410           0 :                 restarter = ospf_nbr_lookup_by_addr(oi->nbrs, &restart_addr);
     411             : 
     412           0 :                 if (!restarter) {
     413           0 :                         if (IS_DEBUG_OSPF_GR)
     414           0 :                                 zlog_debug(
     415             :                                         "%s, Restarter is not a nbr(%pI4) for this router.",
     416             :                                         __func__, &restart_addr);
     417           0 :                         return OSPF_GR_NOT_HELPER;
     418             :                 }
     419             :         } else
     420             :                 restarter = nbr;
     421             : 
     422             :         /* Verify Helper enabled globally */
     423           0 :         if (!ospf->is_helper_supported) {
     424             :                 /* Verify that Helper support is enabled for the
     425             :                  * current neighbour router-id.
     426             :                  */
     427           0 :                 lookup.advRtrAddr.s_addr = restarter->router_id.s_addr;
     428             : 
     429           0 :                 if (!hash_lookup(ospf->enable_rtr_list, &lookup)) {
     430           0 :                         if (IS_DEBUG_OSPF_GR)
     431           0 :                                 zlog_debug(
     432             :                                         "%s, HELPER support is disabled, So not a HELPER",
     433             :                                         __func__);
     434           0 :                         restarter->gr_helper_info.rejected_reason =
     435             :                                 OSPF_HELPER_SUPPORT_DISABLED;
     436           0 :                         return OSPF_GR_NOT_HELPER;
     437             :                 }
     438             :         }
     439             : 
     440             : 
     441             :         /* Check neighbour is in FULL state and
     442             :          * became a adjacency.
     443             :          */
     444           0 :         if (!IS_NBR_STATE_FULL(restarter)) {
     445           0 :                 if (IS_DEBUG_OSPF_GR)
     446           0 :                         zlog_debug(
     447             :                                 "%s, This Neighbour %pI4 is not in FULL state.",
     448             :                                 __func__, &restarter->src);
     449           0 :                 restarter->gr_helper_info.rejected_reason =
     450             :                         OSPF_HELPER_NOT_A_VALID_NEIGHBOUR;
     451           0 :                 return OSPF_GR_NOT_HELPER;
     452             :         }
     453             : 
     454             :         /* Based on the restart reason from grace lsa
     455             :          * check the current router is supporting or not
     456             :          */
     457           0 :         if (ospf->only_planned_restart
     458           0 :             && !OSPF_GR_IS_PLANNED_RESTART(restart_reason)) {
     459           0 :                 if (IS_DEBUG_OSPF_GR)
     460           0 :                         zlog_debug(
     461             :                                 "%s, Router supports only planned restarts but received the GRACE LSA for an unplanned restart.",
     462             :                                 __func__);
     463           0 :                 restarter->gr_helper_info.rejected_reason =
     464             :                         OSPF_HELPER_PLANNED_ONLY_RESTART;
     465           0 :                 return OSPF_GR_NOT_HELPER;
     466             :         }
     467             : 
     468             :         /* Check the retransmission list of this
     469             :          * neighbour, check any change in lsas.
     470             :          */
     471           0 :         if (ospf->strict_lsa_check && !ospf_ls_retransmit_isempty(restarter)
     472           0 :             && ospf_check_change_in_rxmt_list(restarter)) {
     473           0 :                 if (IS_DEBUG_OSPF_GR)
     474           0 :                         zlog_debug(
     475             :                                 "%s, Changed LSA in Rxmt list. So not Helper.",
     476             :                                 __func__);
     477           0 :                 restarter->gr_helper_info.rejected_reason =
     478             :                         OSPF_HELPER_TOPO_CHANGE_RTXMT_LIST;
     479           0 :                 return OSPF_GR_NOT_HELPER;
     480             :         }
     481             : 
     482             :         /*LSA age must be less than the grace period */
     483           0 :         if (ntohs(lsa->data->ls_age) >= grace_interval) {
     484           0 :                 if (IS_DEBUG_OSPF_GR)
     485           0 :                         zlog_debug(
     486             :                                 "%s, Grace LSA age(%d) is more than the grace interval(%d)",
     487             :                                 __func__, lsa->data->ls_age, grace_interval);
     488           0 :                 restarter->gr_helper_info.rejected_reason =
     489             :                         OSPF_HELPER_LSA_AGE_MORE;
     490           0 :                 return OSPF_GR_NOT_HELPER;
     491             :         }
     492             : 
     493           0 :         if (ospf->gr_info.restart_in_progress) {
     494           0 :                 if (IS_DEBUG_OSPF_GR)
     495           0 :                         zlog_debug(
     496             :                                 "%s: router is in the process of graceful restart",
     497             :                                 __func__);
     498           0 :                 restarter->gr_helper_info.rejected_reason =
     499             :                         OSPF_HELPER_RESTARTING;
     500           0 :                 return OSPF_GR_NOT_HELPER;
     501             :         }
     502             : 
     503             :         /* check supported grace period configured
     504             :          * if configured, use this to start the grace
     505             :          * timer otherwise use the interval received
     506             :          * in grace LSA packet.
     507             :          */
     508           0 :         actual_grace_interval = grace_interval;
     509           0 :         if (grace_interval > ospf->supported_grace_time) {
     510           0 :                 if (IS_DEBUG_OSPF_GR)
     511           0 :                         zlog_debug(
     512             :                                 "%s, Received grace period %d is larger than supported grace %d",
     513             :                                 __func__, grace_interval,
     514             :                                 ospf->supported_grace_time);
     515           0 :                 actual_grace_interval = ospf->supported_grace_time;
     516             :         }
     517             : 
     518           0 :         if (OSPF_GR_IS_ACTIVE_HELPER(restarter)) {
     519           0 :                 if (restarter->gr_helper_info.t_grace_timer)
     520           0 :                         THREAD_OFF(restarter->gr_helper_info.t_grace_timer);
     521             : 
     522           0 :                 if (ospf->active_restarter_cnt > 0)
     523           0 :                         ospf->active_restarter_cnt--;
     524             : 
     525           0 :                 if (IS_DEBUG_OSPF_GR)
     526           0 :                         zlog_debug(
     527             :                                 "%s, Router is already acting as a HELPER for this nbr,so restart the grace timer",
     528             :                                 __func__);
     529             :         } else {
     530           0 :                 if (IS_DEBUG_OSPF_GR)
     531           0 :                         zlog_debug(
     532             :                                 "%s, This Router becomes a HELPER for the neighbour %pI4",
     533             :                                 __func__, &restarter->src);
     534             :         }
     535             : 
     536             :         /* Became a Helper to the RESTART neighbour.
     537             :          * Change the helper status.
     538             :          */
     539           0 :         restarter->gr_helper_info.gr_helper_status = OSPF_GR_ACTIVE_HELPER;
     540           0 :         restarter->gr_helper_info.recvd_grace_period = grace_interval;
     541           0 :         restarter->gr_helper_info.actual_grace_period = actual_grace_interval;
     542           0 :         restarter->gr_helper_info.gr_restart_reason = restart_reason;
     543           0 :         restarter->gr_helper_info.rejected_reason = OSPF_HELPER_REJECTED_NONE;
     544             : 
     545             :         /* Increment the active restarter count */
     546           0 :         ospf->active_restarter_cnt++;
     547             : 
     548           0 :         if (IS_DEBUG_OSPF_GR)
     549           0 :                 zlog_debug("%s, Grace timer started.interval:%d", __func__,
     550             :                            actual_grace_interval);
     551             : 
     552             :         /* Start the grace timer */
     553           0 :         thread_add_timer(master, ospf_handle_grace_timer_expiry, restarter,
     554             :                          actual_grace_interval,
     555             :                          &restarter->gr_helper_info.t_grace_timer);
     556             : 
     557           0 :         return OSPF_GR_ACTIVE_HELPER;
     558             : }
     559             : 
     560             : /*
     561             :  * API to check any change in the neighbor's
     562             :  * retransmission list.
     563             :  *
     564             :  * nbr
     565             :  *    OSPF neighbor
     566             :  *
     567             :  * Returns:
     568             :  *    TRUE  - if any change in the lsa.
     569             :  *    FALSE - no change in the lsas.
     570             :  */
     571           0 : static bool ospf_check_change_in_rxmt_list(struct ospf_neighbor *nbr)
     572             : {
     573           0 :         struct route_node *rn;
     574           0 :         struct ospf_lsa *lsa;
     575           0 :         struct route_table *tbl;
     576             : 
     577           0 :         tbl = nbr->ls_rxmt.type[OSPF_ROUTER_LSA].db;
     578           0 :         LSDB_LOOP (tbl, rn, lsa)
     579           0 :                 if (lsa->to_be_acknowledged)
     580             :                         return OSPF_GR_TRUE;
     581           0 :         tbl = nbr->ls_rxmt.type[OSPF_NETWORK_LSA].db;
     582           0 :         LSDB_LOOP (tbl, rn, lsa)
     583           0 :                 if (lsa->to_be_acknowledged)
     584             :                         return OSPF_GR_TRUE;
     585             : 
     586           0 :         tbl = nbr->ls_rxmt.type[OSPF_SUMMARY_LSA].db;
     587           0 :         LSDB_LOOP (tbl, rn, lsa)
     588           0 :                 if (lsa->to_be_acknowledged)
     589             :                         return OSPF_GR_TRUE;
     590             : 
     591           0 :         tbl = nbr->ls_rxmt.type[OSPF_ASBR_SUMMARY_LSA].db;
     592           0 :         LSDB_LOOP (tbl, rn, lsa)
     593           0 :                 if (lsa->to_be_acknowledged)
     594             :                         return OSPF_GR_TRUE;
     595             : 
     596           0 :         tbl = nbr->ls_rxmt.type[OSPF_AS_EXTERNAL_LSA].db;
     597           0 :         LSDB_LOOP (tbl, rn, lsa)
     598           0 :                 if (lsa->to_be_acknowledged)
     599             :                         return OSPF_GR_TRUE;
     600             : 
     601           0 :         tbl = nbr->ls_rxmt.type[OSPF_AS_NSSA_LSA].db;
     602           0 :         LSDB_LOOP (tbl, rn, lsa)
     603           0 :                 if (lsa->to_be_acknowledged)
     604             :                         return OSPF_GR_TRUE;
     605             : 
     606             :         return OSPF_GR_FALSE;
     607             : }
     608             : 
     609             : /*
     610             :  * Actions to be taken  when topo change detected
     611             :  * HELPER will exit upon topo change.
     612             :  *
     613             :  * ospf
     614             :  *    ospf pointer
     615             :  * lsa
     616             :  *    topo change occurred due to this lsa type (1 to 5 and 7)
     617             :  *
     618             :  * Returns:
     619             :  *    Nothing
     620             :  */
     621           0 : void ospf_helper_handle_topo_chg(struct ospf *ospf, struct ospf_lsa *lsa)
     622             : {
     623           0 :         struct listnode *node;
     624           0 :         struct ospf_interface *oi;
     625             : 
     626             :         /* Topo change not required to be handled if strict
     627             :          * LSA check is disabled for this router.
     628             :          */
     629           0 :         if (!ospf->strict_lsa_check)
     630             :                 return;
     631             : 
     632           0 :         if (IS_DEBUG_OSPF_GR)
     633           0 :                 zlog_debug("%s: Topo change detected due to LSA[%s]", __func__,
     634             :                            dump_lsa_key(lsa));
     635             : 
     636           0 :         lsa->to_be_acknowledged = OSPF_GR_TRUE;
     637             : 
     638           0 :         for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
     639           0 :                 struct route_node *rn = NULL;
     640             : 
     641           0 :                 if (ospf_interface_neighbor_count(oi) == 0)
     642           0 :                         continue;
     643             : 
     644             :                 /* Ref rfc3623 section 3.2.3.b
     645             :                  * If change due to external LSA and if the area is
     646             :                  * stub, then it is not a topo change. Since Type-5
     647             :                  * lsas will not be flooded in stub area.
     648             :                  */
     649           0 :                 if ((oi->area->external_routing == OSPF_AREA_STUB)
     650           0 :                     && (lsa->data->type == OSPF_AS_EXTERNAL_LSA)) {
     651           0 :                         continue;
     652             :                 }
     653             : 
     654           0 :                 for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
     655           0 :                         struct ospf_neighbor *nbr = NULL;
     656             : 
     657           0 :                         if (!rn->info)
     658           0 :                                 continue;
     659             : 
     660           0 :                         nbr = rn->info;
     661             : 
     662           0 :                         if (OSPF_GR_IS_ACTIVE_HELPER(nbr))
     663           0 :                                 ospf_gr_helper_exit(nbr,
     664             :                                                     OSPF_GR_HELPER_TOPO_CHG);
     665             :                 }
     666             :         }
     667             : }
     668             : 
     669             : /*
     670             :  * Api to exit from HELPER role to take all actions
     671             :  * required at exit.
     672             :  * Ref rfc3623 section 3.2
     673             :  *
     674             :  * ospf
     675             :  *    OSPF pointer.
     676             :  *
     677             :  * nbr
     678             :  *    OSPF neighbour for which it is acting as HELPER.
     679             :  *
     680             :  * reason
     681             :  *    The reason for exiting from HELPER.
     682             :  *
     683             :  * Returns:
     684             :  *    Nothing.
     685             :  */
     686           0 : void ospf_gr_helper_exit(struct ospf_neighbor *nbr,
     687             :                          enum ospf_helper_exit_reason reason)
     688             : {
     689           0 :         struct ospf_interface *oi = nbr->oi;
     690           0 :         struct ospf *ospf = oi->ospf;
     691             : 
     692           0 :         if (!OSPF_GR_IS_ACTIVE_HELPER(nbr))
     693             :                 return;
     694             : 
     695           0 :         if (IS_DEBUG_OSPF_GR)
     696           0 :                 zlog_debug("%s, Exiting from HELPER support to %pI4, due to %s",
     697             :                            __func__, &nbr->src, ospf_exit_reason2str(reason));
     698             : 
     699             :         /* Reset helper status*/
     700           0 :         nbr->gr_helper_info.gr_helper_status = OSPF_GR_NOT_HELPER;
     701           0 :         nbr->gr_helper_info.helper_exit_reason = reason;
     702           0 :         nbr->gr_helper_info.actual_grace_period = 0;
     703           0 :         nbr->gr_helper_info.recvd_grace_period = 0;
     704           0 :         nbr->gr_helper_info.gr_restart_reason = 0;
     705           0 :         ospf->last_exit_reason = reason;
     706             : 
     707           0 :         if (ospf->active_restarter_cnt <= 0) {
     708           0 :                 zlog_err(
     709             :                         "OSPF GR-Helper: active_restarter_cnt should be greater than zero here.");
     710           0 :                 return;
     711             :         }
     712             :         /* Decrement active Restarter count */
     713           0 :         ospf->active_restarter_cnt--;
     714             : 
     715             :         /* If the exit not triggered due to grace timer
     716             :          * expiry, stop the grace timer.
     717             :          */
     718           0 :         if (reason != OSPF_GR_HELPER_GRACE_TIMEOUT)
     719           0 :                 THREAD_OFF(nbr->gr_helper_info.t_grace_timer);
     720             : 
     721             :         /* check exit triggered due to successful completion
     722             :          * of graceful restart.
     723             :          */
     724           0 :         if (reason != OSPF_GR_HELPER_COMPLETED) {
     725           0 :                 if (IS_DEBUG_OSPF_GR)
     726           0 :                         zlog_debug("%s, Unsuccessful GR exit", __func__);
     727             :         }
     728             : 
     729             :         /*Recalculate the DR for the network segment */
     730           0 :         if (oi->type == OSPF_IFTYPE_BROADCAST || oi->type == OSPF_IFTYPE_NBMA)
     731           0 :                 ospf_dr_election(oi);
     732             : 
     733             :         /* Originate a router LSA */
     734           0 :         ospf_router_lsa_update_area(oi->area);
     735             : 
     736             :         /* Originate network lsa if it is an DR in the LAN */
     737           0 :         if (oi->state == ISM_DR)
     738           0 :                 ospf_network_lsa_update(oi);
     739             : }
     740             : 
     741             : /*
     742             :  * Process MaxAge Grace LSA.
     743             :  * It is a indication for successful completion of GR.
     744             :  * If router acting as HELPER, It exits from helper role.
     745             :  *
     746             :  * ospf
     747             :  *    OSPF pointer.
     748             :  *
     749             :  * lsa
     750             :  *    Grace LSA received from RESTARTER.
     751             :  *
     752             :  * nbr
     753             :  *    OSPF neighbour which requests the router to act as
     754             :  *    HELPER.
     755             :  *
     756             :  * Returns:
     757             :  *    Nothing.
     758             :  */
     759           0 : void ospf_process_maxage_grace_lsa(struct ospf *ospf, struct ospf_lsa *lsa,
     760             :                                    struct ospf_neighbor *nbr)
     761             : {
     762           0 :         struct in_addr restartAddr = {0};
     763           0 :         uint8_t restartReason = 0;
     764           0 :         uint32_t graceInterval = 0;
     765           0 :         struct ospf_neighbor *restarter = NULL;
     766           0 :         struct ospf_interface *oi = nbr->oi;
     767           0 :         int ret;
     768             : 
     769             :         /* Extract the grace lsa packet fields */
     770           0 :         ret = ospf_extract_grace_lsa_fields(lsa, &graceInterval, &restartAddr,
     771             :                                             &restartReason);
     772           0 :         if (ret != OSPF_GR_SUCCESS) {
     773           0 :                 if (IS_DEBUG_OSPF_GR)
     774           0 :                         zlog_debug("%s, Wrong Grace LSA packet.", __func__);
     775           0 :                 return;
     776             :         }
     777             : 
     778           0 :         if (IS_DEBUG_OSPF_GR)
     779           0 :                 zlog_debug("%s, GraceLSA received for neighbour %pI4", __func__,
     780             :                            &restartAddr);
     781             : 
     782             :         /* In case of broadcast links, if RESTARTER is DR_OTHER,
     783             :          * grace LSA might be received from DR, so fetching the
     784             :          * actual neighbour information using restarter address.
     785             :          */
     786           0 :         if (oi->type != OSPF_IFTYPE_POINTOPOINT) {
     787           0 :                 restarter = ospf_nbr_lookup_by_addr(oi->nbrs, &restartAddr);
     788             : 
     789           0 :                 if (!restarter) {
     790           0 :                         if (IS_DEBUG_OSPF_GR)
     791           0 :                                 zlog_debug(
     792             :                                         "%s, Restarter is not a neighbour for this router.",
     793             :                                         __func__);
     794           0 :                         return;
     795             :                 }
     796             :         } else {
     797             :                 restarter = nbr;
     798             :         }
     799             : 
     800           0 :         ospf_gr_helper_exit(restarter, OSPF_GR_HELPER_COMPLETED);
     801             : }
     802             : 
     803             : /* Configuration handlers */
     804             : /*
     805             :  * Disable/Enable HELPER support on router level.
     806             :  *
     807             :  * ospf
     808             :  *    OSPF pointer.
     809             :  *
     810             :  * status
     811             :  *    TRUE/FALSE
     812             :  *
     813             :  * Returns:
     814             :  *    Nothing.
     815             :  */
     816           0 : void ospf_gr_helper_support_set(struct ospf *ospf, bool support)
     817             : {
     818           0 :         struct ospf_interface *oi;
     819           0 :         struct listnode *node;
     820           0 :         struct advRtr lookup;
     821             : 
     822           0 :         if (ospf->is_helper_supported == support)
     823           0 :                 return;
     824             : 
     825           0 :         ospf->is_helper_supported = support;
     826             : 
     827             :         /* If helper support disabled, cease HELPER role for all
     828             :          * supporting neighbors.
     829             :          */
     830           0 :         if (support == OSPF_GR_FALSE) {
     831           0 :                 for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
     832           0 :                         struct route_node *rn = NULL;
     833             : 
     834           0 :                         if (ospf_interface_neighbor_count(oi) == 0)
     835           0 :                                 continue;
     836             : 
     837           0 :                         for (rn = route_top(oi->nbrs); rn;
     838           0 :                              rn = route_next(rn)) {
     839           0 :                                 struct ospf_neighbor *nbr = NULL;
     840             : 
     841           0 :                                 if (!rn->info)
     842           0 :                                         continue;
     843             : 
     844           0 :                                 nbr = rn->info;
     845             : 
     846           0 :                                 lookup.advRtrAddr.s_addr =
     847           0 :                                         nbr->router_id.s_addr;
     848             :                                 /* check if helper support enabled for the
     849             :                                  * corresponding routerid.If enabled, don't
     850             :                                  * exit from helper role.
     851             :                                  */
     852           0 :                                 if (hash_lookup(ospf->enable_rtr_list, &lookup))
     853           0 :                                         continue;
     854             : 
     855           0 :                                 if (OSPF_GR_IS_ACTIVE_HELPER(nbr))
     856           0 :                                         ospf_gr_helper_exit(
     857             :                                                 nbr, OSPF_GR_HELPER_TOPO_CHG);
     858             :                         }
     859             :                 }
     860             :         }
     861             : }
     862             : 
     863             : /*
     864             :  * Enable/Disable HELPER support on a specified advertagement
     865             :  * router.
     866             :  *
     867             :  * ospf
     868             :  *    OSPF pointer.
     869             :  *
     870             :  * advRtr
     871             :  *    HELPER support for given Advertisement Router.
     872             :  *
     873             :  * support
     874             :  *    True - Enable Helper Support.
     875             :  *    False - Disable Helper Support.
     876             :  *
     877             :  * Returns:
     878             :  *    Nothing.
     879             :  */
     880             : 
     881           0 : void ospf_gr_helper_support_set_per_routerid(struct ospf *ospf,
     882             :                                              struct in_addr *advrtr,
     883             :                                              bool support)
     884             : {
     885           0 :         struct advRtr temp;
     886           0 :         struct advRtr *rtr;
     887           0 :         struct ospf_interface *oi;
     888           0 :         struct listnode *node;
     889             : 
     890           0 :         temp.advRtrAddr.s_addr = advrtr->s_addr;
     891             : 
     892           0 :         if (support == OSPF_GR_FALSE) {
     893             :                 /*Delete the routerid from the enable router hash table */
     894           0 :                 rtr = hash_lookup(ospf->enable_rtr_list, &temp);
     895             : 
     896           0 :                 if (rtr) {
     897           0 :                         hash_release(ospf->enable_rtr_list, rtr);
     898           0 :                         ospf_disable_rtr_hash_free(rtr);
     899             :                 }
     900             : 
     901             :                 /* If helper support is enabled globally
     902             :                  * no action is required.
     903             :                  */
     904           0 :                 if (ospf->is_helper_supported)
     905           0 :                         return;
     906             : 
     907             :                 /* Cease the HELPER role fore neighbours from the
     908             :                  * specified advertisement router.
     909             :                  */
     910           0 :                 for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
     911           0 :                         struct route_node *rn = NULL;
     912             : 
     913           0 :                         if (ospf_interface_neighbor_count(oi) == 0)
     914           0 :                                 continue;
     915             : 
     916           0 :                         for (rn = route_top(oi->nbrs); rn;
     917           0 :                              rn = route_next(rn)) {
     918           0 :                                 struct ospf_neighbor *nbr = NULL;
     919             : 
     920           0 :                                 if (!rn->info)
     921           0 :                                         continue;
     922             : 
     923           0 :                                 nbr = rn->info;
     924             : 
     925           0 :                                 if (nbr->router_id.s_addr != advrtr->s_addr)
     926           0 :                                         continue;
     927             : 
     928           0 :                                 if (OSPF_GR_IS_ACTIVE_HELPER(nbr))
     929           0 :                                         ospf_gr_helper_exit(
     930             :                                                 nbr, OSPF_GR_HELPER_TOPO_CHG);
     931             :                         }
     932             :                 }
     933             : 
     934             :         } else {
     935             :                 /* Add the routerid to the enable router hash table */
     936           0 :                 (void)hash_get(ospf->enable_rtr_list, &temp,
     937             :                                ospf_enable_rtr_hash_alloc);
     938             :         }
     939             : }
     940             : 
     941             : /*
     942             :  * Api to enable/disable strict lsa check on the HELPER.
     943             :  *
     944             :  * ospf
     945             :  *    OSPF pointer.
     946             :  *
     947             :  * enabled
     948             :  *    True - disable the lsa check.
     949             :  *    False - enable the strict lsa check.
     950             :  *
     951             :  * Returns:
     952             :  *    Nothing.
     953             :  */
     954           0 : void ospf_gr_helper_lsa_check_set(struct ospf *ospf, bool enabled)
     955             : {
     956           0 :         if (ospf->strict_lsa_check == enabled)
     957             :                 return;
     958             : 
     959           0 :         ospf->strict_lsa_check = enabled;
     960             : }
     961             : 
     962             : /*
     963             :  * Api to set the supported grace interval in this router.
     964             :  *
     965             :  * ospf
     966             :  *    OSPF pointer.
     967             :  *
     968             :  * interval
     969             :  *    The supported grace interval..
     970             :  *
     971             :  * Returns:
     972             :  *    Nothing.
     973             :  */
     974           0 : void ospf_gr_helper_supported_gracetime_set(struct ospf *ospf,
     975             :                                             uint32_t interval)
     976             : {
     977           0 :         ospf->supported_grace_time = interval;
     978           0 : }
     979             : 
     980             : /*
     981             :  * Api to set the supported restart reason.
     982             :  *
     983             :  * ospf
     984             :  *    OSPF pointer.
     985             :  *
     986             :  * planned_only
     987             :  *    True: support only planned restart.
     988             :  *    False: support for planned/unplanned restarts.
     989             :  *
     990             :  * Returns:
     991             :  *    Nothing.
     992             :  */
     993           0 : void ospf_gr_helper_set_supported_planned_only_restart(struct ospf *ospf,
     994             :                                                       bool planned_only)
     995             : {
     996           0 :         ospf->only_planned_restart = planned_only;
     997           0 : }
     998             : 
     999             : /*
    1000             :  * Api to display the grace LSA information.
    1001             :  *
    1002             :  * vty
    1003             :  *    vty pointer.
    1004             :  * lsa
    1005             :  *    Grace LSA.
    1006             :  * json
    1007             :  *    json object
    1008             :  *
    1009             :  * Returns:
    1010             :  *    Nothing.
    1011             :  */
    1012           0 : static void show_ospf_grace_lsa_info(struct vty *vty, struct json_object *json,
    1013             :                                      struct ospf_lsa *lsa)
    1014             : {
    1015           0 :         struct lsa_header *lsah = NULL;
    1016           0 :         struct tlv_header *tlvh = NULL;
    1017           0 :         struct grace_tlv_graceperiod *gracePeriod;
    1018           0 :         struct grace_tlv_restart_reason *grReason;
    1019           0 :         struct grace_tlv_restart_addr *restartAddr;
    1020           0 :         uint16_t length = 0;
    1021           0 :         int sum = 0;
    1022             : 
    1023           0 :         if (json)
    1024             :                 return;
    1025             : 
    1026           0 :         lsah = (struct lsa_header *)lsa->data;
    1027             : 
    1028           0 :         if (lsa->size <= OSPF_LSA_HEADER_SIZE) {
    1029           0 :                 if (vty)
    1030           0 :                         vty_out(vty, "%% Invalid LSA length: %d\n", length);
    1031             :                 else
    1032           0 :                         zlog_debug("%% Invalid LSA length: %d", length);
    1033           0 :                 return;
    1034             :         }
    1035             : 
    1036           0 :         length = lsa->size - OSPF_LSA_HEADER_SIZE;
    1037             : 
    1038           0 :         if (vty)
    1039           0 :                 vty_out(vty, "  TLV info:\n");
    1040             :         else
    1041           0 :                 zlog_debug("  TLV info:");
    1042             : 
    1043           0 :         for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh;
    1044           0 :              tlvh = TLV_HDR_NEXT(tlvh)) {
    1045             :                 /* Check TLV len */
    1046           0 :                 if (sum + TLV_SIZE(tlvh) > length) {
    1047           0 :                         if (vty)
    1048           0 :                                 vty_out(vty, "%% Invalid TLV length: %u\n",
    1049           0 :                                         TLV_SIZE(tlvh));
    1050             :                         else
    1051           0 :                                 zlog_debug("%% Invalid TLV length: %u",
    1052             :                                            TLV_SIZE(tlvh));
    1053           0 :                         return;
    1054             :                 }
    1055             : 
    1056           0 :                 switch (ntohs(tlvh->type)) {
    1057           0 :                 case GRACE_PERIOD_TYPE:
    1058           0 :                         if (TLV_SIZE(tlvh)
    1059             :                             < sizeof(struct grace_tlv_graceperiod)) {
    1060           0 :                                 if (vty)
    1061           0 :                                         vty_out(vty,
    1062             :                                                 "%% Invalid grace TLV length %u\n",
    1063           0 :                                                 TLV_SIZE(tlvh));
    1064             :                                 else
    1065           0 :                                         zlog_debug(
    1066             :                                                 "%% Invalid grace TLV length %u",
    1067             :                                                 TLV_SIZE(tlvh));
    1068           0 :                                 return;
    1069             :                         }
    1070             : 
    1071           0 :                         gracePeriod = (struct grace_tlv_graceperiod *)tlvh;
    1072           0 :                         sum += TLV_SIZE(tlvh);
    1073             : 
    1074           0 :                         if (vty)
    1075           0 :                                 vty_out(vty, "   Grace period:%d\n",
    1076             :                                         ntohl(gracePeriod->interval));
    1077             :                         else
    1078           0 :                                 zlog_debug("   Grace period:%d",
    1079             :                                            ntohl(gracePeriod->interval));
    1080             :                         break;
    1081           0 :                 case RESTART_REASON_TYPE:
    1082           0 :                         if (TLV_SIZE(tlvh)
    1083             :                             < sizeof(struct grace_tlv_restart_reason)) {
    1084           0 :                                 if (vty)
    1085           0 :                                         vty_out(vty,
    1086             :                                                 "%% Invalid reason TLV length %u\n",
    1087           0 :                                                 TLV_SIZE(tlvh));
    1088             :                                 else
    1089           0 :                                         zlog_debug(
    1090             :                                                 "%% Invalid reason TLV length %u",
    1091             :                                                 TLV_SIZE(tlvh));
    1092           0 :                                 return;
    1093             :                         }
    1094             : 
    1095           0 :                         grReason = (struct grace_tlv_restart_reason *)tlvh;
    1096           0 :                         sum += TLV_SIZE(tlvh);
    1097             : 
    1098           0 :                         if (vty)
    1099           0 :                                 vty_out(vty, "   Restart reason:%s\n",
    1100             :                                         ospf_restart_reason2str(
    1101           0 :                                                 grReason->reason));
    1102             :                         else
    1103           0 :                                 zlog_debug("   Restart reason:%s",
    1104             :                                            ospf_restart_reason2str(
    1105             :                                                    grReason->reason));
    1106             :                         break;
    1107           0 :                 case RESTARTER_IP_ADDR_TYPE:
    1108           0 :                         if (TLV_SIZE(tlvh)
    1109             :                             < sizeof(struct grace_tlv_restart_addr)) {
    1110           0 :                                 if (vty)
    1111           0 :                                         vty_out(vty,
    1112             :                                                 "%% Invalid addr TLV length %u\n",
    1113           0 :                                                 TLV_SIZE(tlvh));
    1114             :                                 else
    1115           0 :                                         zlog_debug(
    1116             :                                                 "%% Invalid addr TLV length %u",
    1117             :                                                 TLV_SIZE(tlvh));
    1118           0 :                                 return;
    1119             :                         }
    1120             : 
    1121           0 :                         restartAddr = (struct grace_tlv_restart_addr *)tlvh;
    1122           0 :                         sum += TLV_SIZE(tlvh);
    1123             : 
    1124           0 :                         if (vty)
    1125           0 :                                 vty_out(vty, "   Restarter address:%pI4\n",
    1126             :                                         &restartAddr->addr);
    1127             :                         else
    1128           0 :                                 zlog_debug("   Restarter address:%pI4",
    1129             :                                            &restartAddr->addr);
    1130             :                         break;
    1131           0 :                 default:
    1132           0 :                         if (vty)
    1133           0 :                                 vty_out(vty, "   Unknown TLV type %d\n",
    1134           0 :                                         ntohs(tlvh->type));
    1135             :                         else
    1136           0 :                                 zlog_debug("   Unknown TLV type %d",
    1137             :                                            ntohs(tlvh->type));
    1138             : 
    1139             :                         break;
    1140             :                 }
    1141             :         }
    1142             : }

Generated by: LCOV version v1.16-topotato