2 * OSPF Graceful Restart helper functions.
4 * Copyright (C) 2020-21 Vmware, Inc.
7 * This file is part of GNU Zebra.
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
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.
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
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_helper.h"
53 const char *ospf_exit_reason_desc
[] = {
57 "Grace timer expairy",
58 "Successful graceful restart",
61 const char *ospf_restart_reason_desc
[] = {
64 "Software reload/upgrade",
65 "Switch to redundant control processor",
68 const char *ospf_rejected_reason_desc
[] = {
70 "Helper support disabled",
71 "Neighbour is not in FULL state",
72 "Supports only planned restart but received for unplanned",
73 "Topo change due to change in lsa rxmt list",
74 "LSA age is more than Grace interval",
77 static void show_ospf_grace_lsa_info(struct vty
*vty
, struct ospf_lsa
*lsa
);
78 static bool ospf_check_change_in_rxmt_list(struct ospf_neighbor
*nbr
);
80 static unsigned int ospf_enable_rtr_hash_key(const void *data
)
82 const struct advRtr
*rtr
= data
;
84 return jhash_1word(rtr
->advRtrAddr
.s_addr
, 0);
87 static bool ospf_enable_rtr_hash_cmp(const void *d1
, const void *d2
)
89 const struct advRtr
*rtr1
= (struct advRtr
*)d1
;
90 const struct advRtr
*rtr2
= (struct advRtr
*)d2
;
92 return (rtr1
->advRtrAddr
.s_addr
== rtr2
->advRtrAddr
.s_addr
);
95 static void *ospf_enable_rtr_hash_alloc(void *p
)
99 rid
= XCALLOC(MTYPE_OSPF_GR_HELPER
, sizeof(struct advRtr
));
100 rid
->advRtrAddr
.s_addr
= ((struct in_addr
*)p
)->s_addr
;
105 static void ospf_disable_rtr_hash_free(void *rtr
)
107 XFREE(MTYPE_OSPF_GR_HELPER
, rtr
);
110 static void ospf_enable_rtr_hash_destroy(struct ospf
*ospf
)
112 if (ospf
->enable_rtr_list
== NULL
)
115 hash_clean(ospf
->enable_rtr_list
, ospf_disable_rtr_hash_free
);
116 hash_free(ospf
->enable_rtr_list
);
117 ospf
->enable_rtr_list
= NULL
;
121 * Initialize GR helper config data structures.
129 void ospf_gr_helper_init(struct ospf
*ospf
)
133 if (IS_DEBUG_OSPF_GR_HELPER
)
134 zlog_debug("%s, GR Helper init.", __PRETTY_FUNCTION__
);
136 ospf
->is_helper_supported
= OSPF_GR_FALSE
;
137 ospf
->strict_lsa_check
= OSPF_GR_TRUE
;
138 ospf
->only_planned_restart
= OSPF_GR_FALSE
;
139 ospf
->supported_grace_time
= OSPF_MAX_GRACE_INTERVAL
;
140 ospf
->last_exit_reason
= OSPF_GR_HELPER_EXIT_NONE
;
141 ospf
->active_restarter_cnt
= 0;
143 ospf
->enable_rtr_list
=
144 hash_create(ospf_enable_rtr_hash_key
, ospf_enable_rtr_hash_cmp
,
145 "OSPF enable router hash");
147 rc
= ospf_register_opaque_functab(
148 OSPF_OPAQUE_LINK_LSA
, OPAQUE_TYPE_GRACE_LSA
, NULL
, NULL
, NULL
,
149 NULL
, NULL
, NULL
, NULL
, show_ospf_grace_lsa_info
, NULL
, NULL
,
152 flog_warn(EC_OSPF_OPAQUE_REGISTRATION
,
153 "%s: Failed to register Grace LSA functions",
159 * De-Initialize GR helper config data structures.
167 void ospf_gr_helper_stop(struct ospf
*ospf
)
170 if (IS_DEBUG_OSPF_GR_HELPER
)
171 zlog_debug("%s, GR helper deinit.", __PRETTY_FUNCTION__
);
173 ospf_enable_rtr_hash_destroy(ospf
);
175 ospf_delete_opaque_functab(OSPF_OPAQUE_LINK_LSA
, OPAQUE_TYPE_GRACE_LSA
);
179 * Extracting tlv info from GRACE LSA.
185 * interval : grace interval.
186 * addr : RESTARTER address.
187 * reason : Restarting reason.
189 static int ospf_extract_grace_lsa_fields(struct ospf_lsa
*lsa
,
191 struct in_addr
*addr
, uint8_t *reason
)
193 struct lsa_header
*lsah
= NULL
;
194 struct tlv_header
*tlvh
= NULL
;
195 struct grace_tlv_graceperiod
*grace_period
;
196 struct grace_tlv_restart_reason
*gr_reason
;
197 struct grace_tlv_restart_addr
*restart_addr
;
201 lsah
= (struct lsa_header
*)lsa
->data
;
203 length
= ntohs(lsah
->length
) - OSPF_LSA_HEADER_SIZE
;
205 for (tlvh
= TLV_HDR_TOP(lsah
); sum
< length
;
206 tlvh
= TLV_HDR_NEXT(tlvh
)) {
207 switch (ntohs(tlvh
->type
)) {
208 case GRACE_PERIOD_TYPE
:
209 grace_period
= (struct grace_tlv_graceperiod
*)tlvh
;
210 *interval
= ntohl(grace_period
->interval
);
211 sum
+= TLV_SIZE(tlvh
);
213 /* Check if grace interval is valid */
214 if (*interval
> OSPF_MAX_GRACE_INTERVAL
215 || *interval
< OSPF_MIN_GRACE_INTERVAL
)
216 return OSPF_GR_FAILURE
;
218 case RESTART_REASON_TYPE
:
219 gr_reason
= (struct grace_tlv_restart_reason
*)tlvh
;
220 *reason
= gr_reason
->reason
;
221 sum
+= TLV_SIZE(tlvh
);
223 if (*reason
>= OSPF_GR_INVALID_REASON_CODE
)
224 return OSPF_GR_FAILURE
;
226 case RESTARTER_IP_ADDR_TYPE
:
227 restart_addr
= (struct grace_tlv_restart_addr
*)tlvh
;
228 addr
->s_addr
= restart_addr
->addr
.s_addr
;
229 sum
+= TLV_SIZE(tlvh
);
232 if (IS_DEBUG_OSPF_GR_HELPER
)
234 "%s, Malformed packet.Invalid TLV type:%d",
235 __PRETTY_FUNCTION__
, ntohs(tlvh
->type
));
236 return OSPF_GR_FAILURE
;
240 return OSPF_GR_SUCCESS
;
244 * Grace timer expiry handler.
245 * HELPER aborts its role at grace timer expiry.
253 static int ospf_handle_grace_timer_expiry(struct thread
*thread
)
255 struct ospf_neighbor
*nbr
= THREAD_ARG(thread
);
257 nbr
->gr_helper_info
.t_grace_timer
= NULL
;
259 ospf_gr_helper_exit(nbr
, OSPF_GR_HELPER_GRACE_TIMEOUT
);
260 return OSPF_GR_SUCCESS
;
264 * Process Grace LSA.If it is eligible move to HELPER role.
265 * Ref rfc3623 section 3.1
271 * Grace LSA received from RESTARTER.
274 * ospf neighbour which requets the router to act as
279 * If supported as HELPER : OSPF_GR_HELPER_INPROGRESS
280 * If Not supported as HELPER : OSPF_GR_HELPER_NONE
282 int ospf_process_grace_lsa(struct ospf
*ospf
, struct ospf_lsa
*lsa
,
283 struct ospf_neighbor
*nbr
)
285 struct in_addr restart_addr
= {0};
286 uint8_t restart_reason
= 0;
287 uint32_t grace_interval
= 0;
288 uint32_t actual_grace_interval
= 0;
289 struct advRtr lookup
;
290 struct ospf_neighbor
*restarter
= NULL
;
291 struct ospf_interface
*oi
= nbr
->oi
;
295 /* Extract the grace lsa packet fields */
296 ret
= ospf_extract_grace_lsa_fields(lsa
, &grace_interval
, &restart_addr
,
298 if (ret
!= OSPF_GR_SUCCESS
) {
299 if (IS_DEBUG_OSPF_GR_HELPER
)
300 zlog_debug("%s, Wrong Grace LSA packet.",
301 __PRETTY_FUNCTION__
);
302 return OSPF_GR_NOT_HELPER
;
305 if (IS_DEBUG_OSPF_GR_HELPER
)
307 "%s, Grace LSA received from %s, grace interval:%u, restartreason :%s",
308 __PRETTY_FUNCTION__
, inet_ntoa(restart_addr
),
309 grace_interval
, ospf_restart_reason_desc
[restart_reason
]);
311 /* Incase of broadcast links, if RESTARTER is DR_OTHER,
312 * grace LSA might be received from DR, so need to get
313 * actual neighbour info , here RESTARTER.
315 if (oi
->type
!= OSPF_IFTYPE_POINTOPOINT
) {
316 restarter
= ospf_nbr_lookup_by_addr(oi
->nbrs
, &restart_addr
);
319 if (IS_DEBUG_OSPF_GR_HELPER
)
321 "%s, Restarter is not a nbr(%s) for this router.",
323 inet_ntoa(restart_addr
));
324 return OSPF_GR_NOT_HELPER
;
329 /* Verify Helper enabled globally */
330 if (!ospf
->is_helper_supported
) {
331 /* Verify that Helper support is enabled for the
332 * current neighbour router-id.
334 lookup
.advRtrAddr
.s_addr
= restarter
->router_id
.s_addr
;
336 if (!hash_lookup(ospf
->enable_rtr_list
, &lookup
)) {
337 if (IS_DEBUG_OSPF_GR_HELPER
)
339 "%s, HELPER support is disabled, So not a HELPER",
340 __PRETTY_FUNCTION__
);
341 restarter
->gr_helper_info
.rejected_reason
=
342 OSPF_HELPER_SUPPORT_DISABLED
;
343 return OSPF_GR_NOT_HELPER
;
348 /* Check neighbour is in FULL state and
349 * became a adjacency.
351 if (!IS_NBR_STATE_FULL(restarter
)) {
352 if (IS_DEBUG_OSPF_GR_HELPER
)
354 "%s, This Neighbour %s is not in FULL state.",
355 __PRETTY_FUNCTION__
, inet_ntoa(restarter
->src
));
356 restarter
->gr_helper_info
.rejected_reason
=
357 OSPF_HELPER_NOT_A_VALID_NEIGHBOUR
;
358 return OSPF_GR_NOT_HELPER
;
361 /* Based on the restart reason from grace lsa
362 * check the current router is supporting or not
364 if (ospf
->only_planned_restart
365 && !OSPF_GR_IS_PLANNED_RESTART(restart_reason
)) {
366 if (IS_DEBUG_OSPF_GR_HELPER
)
368 "%s, Router supports only planned restarts but received the GRACE LSA for an unplanned restart.",
369 __PRETTY_FUNCTION__
);
370 restarter
->gr_helper_info
.rejected_reason
=
371 OSPF_HELPER_PLANNED_ONLY_RESTART
;
372 return OSPF_GR_NOT_HELPER
;
375 /* Check the retranmission list of this
376 * neighbour, check any change in lsas.
378 if (ospf
->strict_lsa_check
&& !ospf_ls_retransmit_isempty(restarter
)
379 && ospf_check_change_in_rxmt_list(restarter
)) {
380 if (IS_DEBUG_OSPF_GR_HELPER
)
382 "%s, Changed LSA in Rxmt list. So not Helper.",
383 __PRETTY_FUNCTION__
);
384 restarter
->gr_helper_info
.rejected_reason
=
385 OSPF_HELPER_TOPO_CHANGE_RTXMT_LIST
;
386 return OSPF_GR_NOT_HELPER
;
389 /*LSA age must be less than the grace period */
390 if (ntohs(lsa
->data
->ls_age
) >= grace_interval
) {
391 if (IS_DEBUG_OSPF_GR_HELPER
)
393 "%s, Grace LSA age(%d) is more than the graceinterval(%d)",
394 __PRETTY_FUNCTION__
, lsa
->data
->ls_age
,
396 restarter
->gr_helper_info
.rejected_reason
=
397 OSPF_HELPER_LSA_AGE_MORE
;
398 return OSPF_GR_NOT_HELPER
;
401 /* check supported grace period configured
402 * if configured, use this to start the grace
403 * timer otherwise use the interval received
404 * in grace LSA packet.
406 actual_grace_interval
= grace_interval
;
407 if (grace_interval
> ospf
->supported_grace_time
) {
408 if (IS_DEBUG_OSPF_GR_HELPER
)
410 "%s, Received grace period %d is larger than supported grace %d",
411 __PRETTY_FUNCTION__
, grace_interval
,
412 ospf
->supported_grace_time
);
413 actual_grace_interval
= ospf
->supported_grace_time
;
416 if (OSPF_GR_IS_ACTIVE_HELPER(restarter
)) {
417 if (restarter
->gr_helper_info
.t_grace_timer
)
418 THREAD_OFF(restarter
->gr_helper_info
.t_grace_timer
);
420 if (ospf
->active_restarter_cnt
> 0)
421 ospf
->active_restarter_cnt
--;
423 if (IS_DEBUG_OSPF_GR_HELPER
)
425 "%s, Router is already acting as a HELPER for this nbr,so restart the grace timer",
426 __PRETTY_FUNCTION__
);
428 if (IS_DEBUG_OSPF_GR_HELPER
)
430 "%s, This Router becomes a HELPER for the neighbour %s",
431 __PRETTY_FUNCTION__
, inet_ntoa(restarter
->src
));
434 /* Became a Helper to the RESTART neighbour.
435 * Change the helper status.
437 restarter
->gr_helper_info
.gr_helper_status
= OSPF_GR_ACTIVE_HELPER
;
438 restarter
->gr_helper_info
.recvd_grace_period
= grace_interval
;
439 restarter
->gr_helper_info
.actual_grace_period
= actual_grace_interval
;
440 restarter
->gr_helper_info
.gr_restart_reason
= restart_reason
;
441 restarter
->gr_helper_info
.rejected_reason
= OSPF_HELPER_REJECTED_NONE
;
443 /* Incremnet the active restarer count */
444 ospf
->active_restarter_cnt
++;
446 if (IS_DEBUG_OSPF_GR_HELPER
)
447 zlog_debug("%s, Grace timer started.interval:%d",
448 __PRETTY_FUNCTION__
, actual_grace_interval
);
450 /* Start the grace timer */
451 thread_add_timer(master
, ospf_handle_grace_timer_expiry
, restarter
,
452 actual_grace_interval
,
453 &restarter
->gr_helper_info
.t_grace_timer
);
455 return OSPF_GR_ACTIVE_HELPER
;
459 * API to check any change in the neighbor's
460 * retransmission list.
466 * TRUE - if any change in the lsa.
467 * FALSE - no change in the lsas.
469 static bool ospf_check_change_in_rxmt_list(struct ospf_neighbor
*nbr
)
471 struct route_node
*rn
;
472 struct ospf_lsa
*lsa
;
473 struct route_table
*tbl
;
475 tbl
= nbr
->ls_rxmt
.type
[OSPF_ROUTER_LSA
].db
;
476 LSDB_LOOP (tbl
, rn
, lsa
)
477 if (lsa
->to_be_acknowledged
)
479 tbl
= nbr
->ls_rxmt
.type
[OSPF_NETWORK_LSA
].db
;
480 LSDB_LOOP (tbl
, rn
, lsa
)
481 if (lsa
->to_be_acknowledged
)
484 tbl
= nbr
->ls_rxmt
.type
[OSPF_SUMMARY_LSA
].db
;
485 LSDB_LOOP (tbl
, rn
, lsa
)
486 if (lsa
->to_be_acknowledged
)
489 tbl
= nbr
->ls_rxmt
.type
[OSPF_ASBR_SUMMARY_LSA
].db
;
490 LSDB_LOOP (tbl
, rn
, lsa
)
491 if (lsa
->to_be_acknowledged
)
494 tbl
= nbr
->ls_rxmt
.type
[OSPF_AS_EXTERNAL_LSA
].db
;
495 LSDB_LOOP (tbl
, rn
, lsa
)
496 if (lsa
->to_be_acknowledged
)
499 tbl
= nbr
->ls_rxmt
.type
[OSPF_AS_NSSA_LSA
].db
;
500 LSDB_LOOP (tbl
, rn
, lsa
)
501 if (lsa
->to_be_acknowledged
)
504 return OSPF_GR_FALSE
;
508 * Actions to be taken when topo change detected
509 * HELPER will exit upon topo change.
514 * topo change occured due to this lsa type (1 to 5 and 7)
519 void ospf_helper_handle_topo_chg(struct ospf
*ospf
, struct ospf_lsa
*lsa
)
521 struct listnode
*node
;
522 struct ospf_interface
*oi
;
524 if (!ospf
->active_restarter_cnt
)
527 /* Topo change not required to be hanlded if strict
528 * LSA check is disbaled for this router.
530 if (!ospf
->strict_lsa_check
)
533 if (IS_DEBUG_OSPF_GR_HELPER
)
535 "%s, Topo change detected due to lsa LSID:%s type:%d",
536 __PRETTY_FUNCTION__
, inet_ntoa(lsa
->data
->id
),
539 lsa
->to_be_acknowledged
= OSPF_GR_TRUE
;
541 for (ALL_LIST_ELEMENTS_RO(ospf
->oiflist
, node
, oi
)) {
542 struct route_node
*rn
= NULL
;
544 if (ospf_interface_neighbor_count(oi
) == 0)
547 /* Ref rfc3623 section 3.2.3.b
548 * If change due to external LSA and if the area is
549 * stub, then it is not a topo change. Since Type-5
550 * lsas will not be flooded in stub area.
552 if ((oi
->area
->external_routing
== OSPF_AREA_STUB
)
553 && (lsa
->data
->type
== OSPF_AS_EXTERNAL_LSA
)) {
557 for (rn
= route_top(oi
->nbrs
); rn
; rn
= route_next(rn
)) {
558 struct ospf_neighbor
*nbr
= NULL
;
565 if (OSPF_GR_IS_ACTIVE_HELPER(nbr
))
566 ospf_gr_helper_exit(nbr
,
567 OSPF_GR_HELPER_TOPO_CHG
);
573 * Api to exit from HELPER role to take all actions
575 * Ref rfc3623 section 3.2
581 * OSPF neighbour for which it is acting as HELPER.
584 * The reason for exiting from HELPER.
589 void ospf_gr_helper_exit(struct ospf_neighbor
*nbr
,
590 enum ospf_helper_exit_reason reason
)
592 struct ospf_interface
*oi
= nbr
->oi
;
593 struct ospf
*ospf
= oi
->ospf
;
595 if (!OSPF_GR_IS_ACTIVE_HELPER(nbr
))
598 if (IS_DEBUG_OSPF_GR_HELPER
)
599 zlog_debug("%s, Exiting from HELPER support to %s, due to %s",
600 __PRETTY_FUNCTION__
, inet_ntoa(nbr
->src
),
601 ospf_exit_reason_desc
[reason
]);
603 /* Reset helper status*/
604 nbr
->gr_helper_info
.gr_helper_status
= OSPF_GR_NOT_HELPER
;
605 nbr
->gr_helper_info
.helper_exit_reason
= reason
;
606 nbr
->gr_helper_info
.actual_grace_period
= 0;
607 nbr
->gr_helper_info
.recvd_grace_period
= 0;
608 nbr
->gr_helper_info
.gr_restart_reason
= 0;
609 ospf
->last_exit_reason
= reason
;
611 if (ospf
->active_restarter_cnt
<= 0) {
613 "OSPF GR-Helper: active_restarter_cnt should be greater than zero here.");
616 /* Decrement active Restarter count */
617 ospf
->active_restarter_cnt
--;
619 /* If the exit not triggered due to grace timer
620 * expairy , stop the grace timer.
622 if (reason
!= OSPF_GR_HELPER_GRACE_TIMEOUT
)
623 THREAD_OFF(nbr
->gr_helper_info
.t_grace_timer
);
625 /* check exit triggered due to successful completion
626 * of graceful restart.
627 * If no, bringdown the neighbour.
629 if (reason
!= OSPF_GR_HELPER_COMPLETED
) {
630 if (IS_DEBUG_OSPF_GR_HELPER
)
632 "%s, Failed GR exit, so bringing down the neighbour",
633 __PRETTY_FUNCTION__
);
634 OSPF_NSM_EVENT_EXECUTE(nbr
, NSM_KillNbr
);
637 /*Recalculate the DR for the network segment */
638 ospf_dr_election(oi
);
640 /* Originate a router LSA */
641 ospf_router_lsa_update_area(oi
->area
);
643 /* Originate network lsa if it is an DR in the LAN */
644 if (oi
->state
== ISM_DR
)
645 ospf_network_lsa_update(oi
);
649 * Process Maxage Grace LSA.
650 * It is a indication for successful completion of GR.
651 * If router acting as HELPER, It exits from helper role.
657 * Grace LSA received from RESTARTER.
660 * ospf neighbour which requets the router to act as
666 void ospf_process_maxage_grace_lsa(struct ospf
*ospf
, struct ospf_lsa
*lsa
,
667 struct ospf_neighbor
*nbr
)
669 struct in_addr restartAddr
= {0};
670 uint8_t restartReason
= 0;
671 uint32_t graceInterval
= 0;
672 struct ospf_neighbor
*restarter
= NULL
;
673 struct ospf_interface
*oi
= nbr
->oi
;
676 /* Extract the grace lsa packet fields */
677 ret
= ospf_extract_grace_lsa_fields(lsa
, &graceInterval
, &restartAddr
,
679 if (ret
!= OSPF_GR_SUCCESS
) {
680 if (IS_DEBUG_OSPF_GR_HELPER
)
681 zlog_debug("%s, Wrong Grace LSA packet.",
682 __PRETTY_FUNCTION__
);
686 if (IS_DEBUG_OSPF_GR_HELPER
)
687 zlog_debug("%s, GraceLSA received for neighbour %s.",
688 __PRETTY_FUNCTION__
, inet_ntoa(restartAddr
));
690 /* In case of broadcast links, if RESTARTER is DR_OTHER,
691 * grace LSA might be received from DR, so fetching the
692 * actual neighbour information using restarter address.
694 if (oi
->type
!= OSPF_IFTYPE_POINTOPOINT
) {
695 restarter
= ospf_nbr_lookup_by_addr(oi
->nbrs
, &restartAddr
);
698 if (IS_DEBUG_OSPF_GR_HELPER
)
700 "%s, Restarter is not a neighbour for this router.",
701 __PRETTY_FUNCTION__
);
708 ospf_gr_helper_exit(restarter
, OSPF_GR_HELPER_COMPLETED
);
711 /* Configuration handlers */
713 * Disable/Enable HELPER support on router level.
724 void ospf_gr_helper_support_set(struct ospf
*ospf
, bool support
)
726 struct ospf_interface
*oi
;
727 struct listnode
*node
;
728 struct advRtr lookup
;
730 if (ospf
->is_helper_supported
== support
)
733 ospf
->is_helper_supported
= support
;
735 /* If helper support disabled, cease HELPER role for all
736 * supporting neighbors.
738 if (support
== OSPF_GR_FALSE
) {
739 for (ALL_LIST_ELEMENTS_RO(ospf
->oiflist
, node
, oi
)) {
740 struct route_node
*rn
= NULL
;
742 if (ospf_interface_neighbor_count(oi
) == 0)
745 for (rn
= route_top(oi
->nbrs
); rn
;
746 rn
= route_next(rn
)) {
747 struct ospf_neighbor
*nbr
= NULL
;
754 lookup
.advRtrAddr
.s_addr
=
755 nbr
->router_id
.s_addr
;
756 /* check if helper support enabled for the
757 * correspodning routerid.If enabled, dont
758 * dont exit from helper role.
760 if (hash_lookup(ospf
->enable_rtr_list
, &lookup
))
763 if (OSPF_GR_IS_ACTIVE_HELPER(nbr
))
765 nbr
, OSPF_GR_HELPER_TOPO_CHG
);
772 * Enable/Disable HELPER support on a specified advertagement
779 * HELPER support for given Advertisement Router.
782 * True - Enable Helper Support.
783 * False - Disable Helper Support.
789 void ospf_gr_helper_support_set_per_routerid(struct ospf
*ospf
,
790 struct in_addr
*advrtr
,
795 struct ospf_interface
*oi
;
796 struct listnode
*node
;
798 temp
.advRtrAddr
.s_addr
= advrtr
->s_addr
;
800 if (support
== OSPF_GR_FALSE
) {
801 /*Delete the routerid from the enable router hash table */
802 rtr
= hash_lookup(ospf
->enable_rtr_list
, &temp
);
805 hash_release(ospf
->enable_rtr_list
, rtr
);
806 ospf_disable_rtr_hash_free(rtr
);
809 /* If helper support is enabled globally
810 * no action is required.
812 if (ospf
->is_helper_supported
)
815 /* Cease the HELPER role fore neighbours from the
816 * specified advertisement router.
818 for (ALL_LIST_ELEMENTS_RO(ospf
->oiflist
, node
, oi
)) {
819 struct route_node
*rn
= NULL
;
821 if (ospf_interface_neighbor_count(oi
) == 0)
824 for (rn
= route_top(oi
->nbrs
); rn
;
825 rn
= route_next(rn
)) {
826 struct ospf_neighbor
*nbr
= NULL
;
833 if (nbr
->router_id
.s_addr
!= advrtr
->s_addr
)
836 if (OSPF_GR_IS_ACTIVE_HELPER(nbr
))
838 nbr
, OSPF_GR_HELPER_TOPO_CHG
);
843 /* Add the routerid to the enable router hash table */
844 hash_get(ospf
->enable_rtr_list
, &temp
,
845 ospf_enable_rtr_hash_alloc
);
850 * Api to enable/disable strict lsa check on the HELPER.
856 * True - disable the lsa check.
857 * False - enable the strict lsa check.
862 void ospf_gr_helper_lsa_check_set(struct ospf
*ospf
, bool enabled
)
864 if (ospf
->strict_lsa_check
== enabled
)
867 ospf
->strict_lsa_check
= enabled
;
871 * Api to set the supported grace interval in this router.
877 * The supported grace interval..
882 void ospf_gr_helper_supported_gracetime_set(struct ospf
*ospf
,
885 ospf
->supported_grace_time
= interval
;
889 * Api to set the supported restart reason.
895 * True: support only planned restart.
896 * False: support for planned/unplanned restarts.
901 void ospf_gr_helper_set_supported_planned_only_restart(struct ospf
*ospf
,
904 ospf
->only_planned_restart
= planned_only
;
908 * Api to display the grace LSA information.
920 static void show_ospf_grace_lsa_info(struct vty
*vty
, struct ospf_lsa
*lsa
)
922 struct lsa_header
*lsah
= NULL
;
923 struct tlv_header
*tlvh
= NULL
;
924 struct grace_tlv_graceperiod
*gracePeriod
;
925 struct grace_tlv_restart_reason
*grReason
;
926 struct grace_tlv_restart_addr
*restartAddr
;
930 lsah
= (struct lsa_header
*)lsa
->data
;
932 length
= ntohs(lsah
->length
) - OSPF_LSA_HEADER_SIZE
;
934 vty_out(vty
, " TLV info:\n");
936 for (tlvh
= TLV_HDR_TOP(lsah
); sum
< length
;
937 tlvh
= TLV_HDR_NEXT(tlvh
)) {
938 switch (ntohs(tlvh
->type
)) {
939 case GRACE_PERIOD_TYPE
:
940 gracePeriod
= (struct grace_tlv_graceperiod
*)tlvh
;
941 sum
+= TLV_SIZE(tlvh
);
943 vty_out(vty
, " Grace period:%d\n",
944 ntohl(gracePeriod
->interval
));
946 case RESTART_REASON_TYPE
:
947 grReason
= (struct grace_tlv_restart_reason
*)tlvh
;
948 sum
+= TLV_SIZE(tlvh
);
950 vty_out(vty
, " Restart reason:%s\n",
951 ospf_restart_reason_desc
[grReason
->reason
]);
953 case RESTARTER_IP_ADDR_TYPE
:
954 restartAddr
= (struct grace_tlv_restart_addr
*)tlvh
;
955 sum
+= TLV_SIZE(tlvh
);
957 vty_out(vty
, " Restarter address:%s\n",
958 inet_ntoa(restartAddr
->addr
));