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 bool ospf_check_change_in_rxmt_list(struct ospf_neighbor
*nbr
);
79 static unsigned int ospf_enable_rtr_hash_key(const void *data
)
81 const struct advRtr
*rtr
= data
;
83 return jhash_1word(rtr
->advRtrAddr
.s_addr
, 0);
86 static bool ospf_enable_rtr_hash_cmp(const void *d1
, const void *d2
)
88 const struct advRtr
*rtr1
= (struct advRtr
*)d1
;
89 const struct advRtr
*rtr2
= (struct advRtr
*)d2
;
91 return (rtr1
->advRtrAddr
.s_addr
== rtr2
->advRtrAddr
.s_addr
);
94 static void *ospf_enable_rtr_hash_alloc(void *p
)
98 rid
= XCALLOC(MTYPE_OSPF_GR_HELPER
, sizeof(struct advRtr
));
99 rid
->advRtrAddr
.s_addr
= ((struct in_addr
*)p
)->s_addr
;
104 static void ospf_disable_rtr_hash_free(void *rtr
)
106 XFREE(MTYPE_OSPF_GR_HELPER
, rtr
);
109 static void ospf_enable_rtr_hash_destroy(struct ospf
*ospf
)
111 if (ospf
->enable_rtr_list
== NULL
)
114 hash_clean(ospf
->enable_rtr_list
, ospf_disable_rtr_hash_free
);
115 hash_free(ospf
->enable_rtr_list
);
116 ospf
->enable_rtr_list
= NULL
;
120 * Initialize GR helper config data structures.
128 void ospf_gr_helper_init(struct ospf
*ospf
)
130 if (IS_DEBUG_OSPF_GR_HELPER
)
131 zlog_debug("%s, GR Helper init.", __PRETTY_FUNCTION__
);
133 ospf
->is_helper_supported
= OSPF_GR_FALSE
;
134 ospf
->strict_lsa_check
= OSPF_GR_TRUE
;
135 ospf
->only_planned_restart
= OSPF_GR_FALSE
;
136 ospf
->supported_grace_time
= OSPF_MAX_GRACE_INTERVAL
;
137 ospf
->last_exit_reason
= OSPF_GR_HELPER_EXIT_NONE
;
138 ospf
->active_restarter_cnt
= 0;
140 ospf
->enable_rtr_list
=
141 hash_create(ospf_enable_rtr_hash_key
, ospf_enable_rtr_hash_cmp
,
142 "OSPF enable router hash");
146 * De-Initialize GR helper config data structures.
154 void ospf_gr_helper_stop(struct ospf
*ospf
)
157 if (IS_DEBUG_OSPF_GR_HELPER
)
158 zlog_debug("%s, GR helper deinit.", __PRETTY_FUNCTION__
);
160 ospf_enable_rtr_hash_destroy(ospf
);
164 * Extracting tlv info from GRACE LSA.
170 * interval : grace interval.
171 * addr : RESTARTER address.
172 * reason : Restarting reason.
174 static int ospf_extract_grace_lsa_fields(struct ospf_lsa
*lsa
,
176 struct in_addr
*addr
, uint8_t *reason
)
178 struct lsa_header
*lsah
= NULL
;
179 struct tlv_header
*tlvh
= NULL
;
180 struct grace_tlv_graceperiod
*grace_period
;
181 struct grace_tlv_restart_reason
*gr_reason
;
182 struct grace_tlv_restart_addr
*restart_addr
;
186 lsah
= (struct lsa_header
*)lsa
->data
;
188 length
= ntohs(lsah
->length
) - OSPF_LSA_HEADER_SIZE
;
190 for (tlvh
= TLV_HDR_TOP(lsah
); sum
< length
;
191 tlvh
= TLV_HDR_NEXT(tlvh
)) {
192 switch (ntohs(tlvh
->type
)) {
193 case GRACE_PERIOD_TYPE
:
194 grace_period
= (struct grace_tlv_graceperiod
*)tlvh
;
195 *interval
= ntohl(grace_period
->interval
);
196 sum
+= TLV_SIZE(tlvh
);
198 /* Check if grace interval is valid */
199 if (*interval
> OSPF_MAX_GRACE_INTERVAL
200 || *interval
< OSPF_MIN_GRACE_INTERVAL
)
201 return OSPF_GR_FAILURE
;
203 case RESTART_REASON_TYPE
:
204 gr_reason
= (struct grace_tlv_restart_reason
*)tlvh
;
205 *reason
= gr_reason
->reason
;
206 sum
+= TLV_SIZE(tlvh
);
208 if (*reason
>= OSPF_GR_INVALID_REASON_CODE
)
209 return OSPF_GR_FAILURE
;
211 case RESTARTER_IP_ADDR_TYPE
:
212 restart_addr
= (struct grace_tlv_restart_addr
*)tlvh
;
213 addr
->s_addr
= restart_addr
->addr
.s_addr
;
214 sum
+= TLV_SIZE(tlvh
);
217 if (IS_DEBUG_OSPF_GR_HELPER
)
219 "%s, Malformed packet.Invalid TLV type:%d",
220 __PRETTY_FUNCTION__
, ntohs(tlvh
->type
));
221 return OSPF_GR_FAILURE
;
225 return OSPF_GR_SUCCESS
;
229 * Grace timer expiry handler.
230 * HELPER aborts its role at grace timer expiry.
238 static int ospf_handle_grace_timer_expiry(struct thread
*thread
)
240 struct ospf_neighbor
*nbr
= THREAD_ARG(thread
);
242 nbr
->gr_helper_info
.t_grace_timer
= NULL
;
244 ospf_gr_helper_exit(nbr
, OSPF_GR_HELPER_GRACE_TIMEOUT
);
245 return OSPF_GR_SUCCESS
;
249 * Process Grace LSA.If it is eligible move to HELPER role.
250 * Ref rfc3623 section 3.1
256 * Grace LSA received from RESTARTER.
259 * ospf neighbour which requets the router to act as
264 * If supported as HELPER : OSPF_GR_HELPER_INPROGRESS
265 * If Not supported as HELPER : OSPF_GR_HELPER_NONE
267 int ospf_process_grace_lsa(struct ospf
*ospf
, struct ospf_lsa
*lsa
,
268 struct ospf_neighbor
*nbr
)
270 struct in_addr restart_addr
= {0};
271 uint8_t restart_reason
= 0;
272 uint32_t grace_interval
= 0;
273 uint32_t actual_grace_interval
= 0;
274 struct advRtr lookup
;
275 struct ospf_neighbor
*restarter
= NULL
;
276 struct ospf_interface
*oi
= nbr
->oi
;
280 /* Extract the grace lsa packet fields */
281 ret
= ospf_extract_grace_lsa_fields(lsa
, &grace_interval
, &restart_addr
,
283 if (ret
!= OSPF_GR_SUCCESS
) {
284 if (IS_DEBUG_OSPF_GR_HELPER
)
285 zlog_debug("%s, Wrong Grace LSA packet.",
286 __PRETTY_FUNCTION__
);
287 return OSPF_GR_NOT_HELPER
;
290 if (IS_DEBUG_OSPF_GR_HELPER
)
292 "%s, Grace LSA received from %s, grace interval:%u, restartreason :%s",
293 __PRETTY_FUNCTION__
, inet_ntoa(restart_addr
),
294 grace_interval
, ospf_restart_reason_desc
[restart_reason
]);
296 /* Incase of broadcast links, if RESTARTER is DR_OTHER,
297 * grace LSA might be received from DR, so need to get
298 * actual neighbour info , here RESTARTER.
300 if (oi
->type
!= OSPF_IFTYPE_POINTOPOINT
) {
301 restarter
= ospf_nbr_lookup_by_addr(oi
->nbrs
, &restart_addr
);
304 if (IS_DEBUG_OSPF_GR_HELPER
)
306 "%s, Restarter is not a nbr(%s) for this router.",
308 inet_ntoa(restart_addr
));
309 return OSPF_GR_NOT_HELPER
;
314 /* Verify Helper enabled globally */
315 if (!ospf
->is_helper_supported
) {
316 /* Verify that Helper support is enabled for the
317 * current neighbour router-id.
319 lookup
.advRtrAddr
.s_addr
= restarter
->router_id
.s_addr
;
321 if (!hash_lookup(ospf
->enable_rtr_list
, &lookup
)) {
322 if (IS_DEBUG_OSPF_GR_HELPER
)
324 "%s, HELPER support is disabled, So not a HELPER",
325 __PRETTY_FUNCTION__
);
326 restarter
->gr_helper_info
.rejected_reason
=
327 OSPF_HELPER_SUPPORT_DISABLED
;
328 return OSPF_GR_NOT_HELPER
;
333 /* Check neighbour is in FULL state and
334 * became a adjacency.
336 if (!IS_NBR_STATE_FULL(restarter
)) {
337 if (IS_DEBUG_OSPF_GR_HELPER
)
339 "%s, This Neighbour %s is not in FULL state.",
340 __PRETTY_FUNCTION__
, inet_ntoa(restarter
->src
));
341 restarter
->gr_helper_info
.rejected_reason
=
342 OSPF_HELPER_NOT_A_VALID_NEIGHBOUR
;
343 return OSPF_GR_NOT_HELPER
;
346 /* Based on the restart reason from grace lsa
347 * check the current router is supporting or not
349 if (ospf
->only_planned_restart
350 && !OSPF_GR_IS_PLANNED_RESTART(restart_reason
)) {
351 if (IS_DEBUG_OSPF_GR_HELPER
)
353 "%s, Router supports only planned restarts but received the GRACE LSA for an unplanned restart.",
354 __PRETTY_FUNCTION__
);
355 restarter
->gr_helper_info
.rejected_reason
=
356 OSPF_HELPER_PLANNED_ONLY_RESTART
;
357 return OSPF_GR_NOT_HELPER
;
360 /* Check the retranmission list of this
361 * neighbour, check any change in lsas.
363 if (ospf
->strict_lsa_check
&& !ospf_ls_retransmit_isempty(restarter
)
364 && ospf_check_change_in_rxmt_list(restarter
)) {
365 if (IS_DEBUG_OSPF_GR_HELPER
)
367 "%s, Changed LSA in Rxmt list. So not Helper.",
368 __PRETTY_FUNCTION__
);
369 restarter
->gr_helper_info
.rejected_reason
=
370 OSPF_HELPER_TOPO_CHANGE_RTXMT_LIST
;
371 return OSPF_GR_NOT_HELPER
;
374 /*LSA age must be less than the grace period */
375 if (ntohs(lsa
->data
->ls_age
) >= grace_interval
) {
376 if (IS_DEBUG_OSPF_GR_HELPER
)
378 "%s, Grace LSA age(%d) is more than the graceinterval(%d)",
379 __PRETTY_FUNCTION__
, lsa
->data
->ls_age
,
381 restarter
->gr_helper_info
.rejected_reason
=
382 OSPF_HELPER_LSA_AGE_MORE
;
383 return OSPF_GR_NOT_HELPER
;
386 /* check supported grace period configured
387 * if configured, use this to start the grace
388 * timer otherwise use the interval received
389 * in grace LSA packet.
391 actual_grace_interval
= grace_interval
;
392 if (grace_interval
> ospf
->supported_grace_time
) {
393 if (IS_DEBUG_OSPF_GR_HELPER
)
395 "%s, Received grace period %d is larger than supported grace %d",
396 __PRETTY_FUNCTION__
, grace_interval
,
397 ospf
->supported_grace_time
);
398 actual_grace_interval
= ospf
->supported_grace_time
;
401 if (OSPF_GR_IS_ACTIVE_HELPER(restarter
)) {
402 if (restarter
->gr_helper_info
.t_grace_timer
)
403 THREAD_OFF(restarter
->gr_helper_info
.t_grace_timer
);
405 if (ospf
->active_restarter_cnt
> 0)
406 ospf
->active_restarter_cnt
--;
408 if (IS_DEBUG_OSPF_GR_HELPER
)
410 "%s, Router is already acting as a HELPER for this nbr,so restart the grace timer",
411 __PRETTY_FUNCTION__
);
413 if (IS_DEBUG_OSPF_GR_HELPER
)
415 "%s, This Router becomes a HELPER for the neighbour %s",
416 __PRETTY_FUNCTION__
, inet_ntoa(restarter
->src
));
419 /* Became a Helper to the RESTART neighbour.
420 * Change the helper status.
422 restarter
->gr_helper_info
.gr_helper_status
= OSPF_GR_ACTIVE_HELPER
;
423 restarter
->gr_helper_info
.recvd_grace_period
= grace_interval
;
424 restarter
->gr_helper_info
.actual_grace_period
= actual_grace_interval
;
425 restarter
->gr_helper_info
.gr_restart_reason
= restart_reason
;
426 restarter
->gr_helper_info
.rejected_reason
= OSPF_HELPER_REJECTED_NONE
;
428 /* Incremnet the active restarer count */
429 ospf
->active_restarter_cnt
++;
431 if (IS_DEBUG_OSPF_GR_HELPER
)
432 zlog_debug("%s, Grace timer started.interval:%d",
433 __PRETTY_FUNCTION__
, actual_grace_interval
);
435 /* Start the grace timer */
436 thread_add_timer(master
, ospf_handle_grace_timer_expiry
, restarter
,
437 actual_grace_interval
,
438 &restarter
->gr_helper_info
.t_grace_timer
);
440 return OSPF_GR_ACTIVE_HELPER
;
444 * API to check any change in the neighbor's
445 * retransmission list.
451 * TRUE - if any change in the lsa.
452 * FALSE - no change in the lsas.
454 static bool ospf_check_change_in_rxmt_list(struct ospf_neighbor
*nbr
)
456 struct route_node
*rn
;
457 struct ospf_lsa
*lsa
;
458 struct route_table
*tbl
;
460 tbl
= nbr
->ls_rxmt
.type
[OSPF_ROUTER_LSA
].db
;
461 LSDB_LOOP (tbl
, rn
, lsa
)
462 if (lsa
->to_be_acknowledged
)
464 tbl
= nbr
->ls_rxmt
.type
[OSPF_NETWORK_LSA
].db
;
465 LSDB_LOOP (tbl
, rn
, lsa
)
466 if (lsa
->to_be_acknowledged
)
469 tbl
= nbr
->ls_rxmt
.type
[OSPF_SUMMARY_LSA
].db
;
470 LSDB_LOOP (tbl
, rn
, lsa
)
471 if (lsa
->to_be_acknowledged
)
474 tbl
= nbr
->ls_rxmt
.type
[OSPF_ASBR_SUMMARY_LSA
].db
;
475 LSDB_LOOP (tbl
, rn
, lsa
)
476 if (lsa
->to_be_acknowledged
)
479 tbl
= nbr
->ls_rxmt
.type
[OSPF_AS_EXTERNAL_LSA
].db
;
480 LSDB_LOOP (tbl
, rn
, lsa
)
481 if (lsa
->to_be_acknowledged
)
484 tbl
= nbr
->ls_rxmt
.type
[OSPF_AS_NSSA_LSA
].db
;
485 LSDB_LOOP (tbl
, rn
, lsa
)
486 if (lsa
->to_be_acknowledged
)
489 return OSPF_GR_FALSE
;
493 * Actions to be taken when topo change detected
494 * HELPER will exit upon topo change.
499 * topo change occured due to this lsa type (1 to 5 and 7)
504 void ospf_helper_handle_topo_chg(struct ospf
*ospf
, struct ospf_lsa
*lsa
)
506 struct listnode
*node
;
507 struct ospf_interface
*oi
;
509 if (!ospf
->active_restarter_cnt
)
512 /* Topo change not required to be hanlded if strict
513 * LSA check is disbaled for this router.
515 if (!ospf
->strict_lsa_check
)
518 if (IS_DEBUG_OSPF_GR_HELPER
)
520 "%s, Topo change detected due to lsa LSID:%s type:%d",
521 __PRETTY_FUNCTION__
, inet_ntoa(lsa
->data
->id
),
524 lsa
->to_be_acknowledged
= OSPF_GR_TRUE
;
526 for (ALL_LIST_ELEMENTS_RO(ospf
->oiflist
, node
, oi
)) {
527 struct route_node
*rn
= NULL
;
529 if (ospf_interface_neighbor_count(oi
) == 0)
532 /* Ref rfc3623 section 3.2.3.b
533 * If change due to external LSA and if the area is
534 * stub, then it is not a topo change. Since Type-5
535 * lsas will not be flooded in stub area.
537 if ((oi
->area
->external_routing
== OSPF_AREA_STUB
)
538 && (lsa
->data
->type
== OSPF_AS_EXTERNAL_LSA
)) {
542 for (rn
= route_top(oi
->nbrs
); rn
; rn
= route_next(rn
)) {
543 struct ospf_neighbor
*nbr
= NULL
;
550 if (OSPF_GR_IS_ACTIVE_HELPER(nbr
))
551 ospf_gr_helper_exit(nbr
,
552 OSPF_GR_HELPER_TOPO_CHG
);
558 * Api to exit from HELPER role to take all actions
560 * Ref rfc3623 section 3.2
566 * OSPF neighbour for which it is acting as HELPER.
569 * The reason for exiting from HELPER.
574 void ospf_gr_helper_exit(struct ospf_neighbor
*nbr
,
575 enum ospf_helper_exit_reason reason
)
577 struct ospf_interface
*oi
= nbr
->oi
;
578 struct ospf
*ospf
= oi
->ospf
;
580 if (!OSPF_GR_IS_ACTIVE_HELPER(nbr
))
583 if (IS_DEBUG_OSPF_GR_HELPER
)
584 zlog_debug("%s, Exiting from HELPER support to %s, due to %s",
585 __PRETTY_FUNCTION__
, inet_ntoa(nbr
->src
),
586 ospf_exit_reason_desc
[reason
]);
588 /* Reset helper status*/
589 nbr
->gr_helper_info
.gr_helper_status
= OSPF_GR_NOT_HELPER
;
590 nbr
->gr_helper_info
.helper_exit_reason
= reason
;
591 nbr
->gr_helper_info
.actual_grace_period
= 0;
592 nbr
->gr_helper_info
.recvd_grace_period
= 0;
593 nbr
->gr_helper_info
.gr_restart_reason
= 0;
594 ospf
->last_exit_reason
= reason
;
596 if (ospf
->active_restarter_cnt
<= 0) {
598 "OSPF GR-Helper: active_restarter_cnt should be greater than zero here.");
601 /* Decrement active Restarter count */
602 ospf
->active_restarter_cnt
--;
604 /* If the exit not triggered due to grace timer
605 * expairy , stop the grace timer.
607 if (reason
!= OSPF_GR_HELPER_GRACE_TIMEOUT
)
608 THREAD_OFF(nbr
->gr_helper_info
.t_grace_timer
);
610 /* check exit triggered due to successful completion
611 * of graceful restart.
612 * If no, bringdown the neighbour.
614 if (reason
!= OSPF_GR_HELPER_COMPLETED
) {
615 if (IS_DEBUG_OSPF_GR_HELPER
)
617 "%s, Failed GR exit, so bringing down the neighbour",
618 __PRETTY_FUNCTION__
);
619 OSPF_NSM_EVENT_EXECUTE(nbr
, NSM_KillNbr
);
622 /*Recalculate the DR for the network segment */
623 ospf_dr_election(oi
);
625 /* Originate a router LSA */
626 ospf_router_lsa_update_area(oi
->area
);
628 /* Originate network lsa if it is an DR in the LAN */
629 if (oi
->state
== ISM_DR
)
630 ospf_network_lsa_update(oi
);
634 * Process Maxage Grace LSA.
635 * It is a indication for successful completion of GR.
636 * If router acting as HELPER, It exits from helper role.
642 * Grace LSA received from RESTARTER.
645 * ospf neighbour which requets the router to act as
651 void ospf_process_maxage_grace_lsa(struct ospf
*ospf
, struct ospf_lsa
*lsa
,
652 struct ospf_neighbor
*nbr
)
654 struct in_addr restartAddr
= {0};
655 uint8_t restartReason
= 0;
656 uint32_t graceInterval
= 0;
657 struct ospf_neighbor
*restarter
= NULL
;
658 struct ospf_interface
*oi
= nbr
->oi
;
661 /* Extract the grace lsa packet fields */
662 ret
= ospf_extract_grace_lsa_fields(lsa
, &graceInterval
, &restartAddr
,
664 if (ret
!= OSPF_GR_SUCCESS
) {
665 if (IS_DEBUG_OSPF_GR_HELPER
)
666 zlog_debug("%s, Wrong Grace LSA packet.",
667 __PRETTY_FUNCTION__
);
671 if (IS_DEBUG_OSPF_GR_HELPER
)
672 zlog_debug("%s, GraceLSA received for neighbour %s.",
673 __PRETTY_FUNCTION__
, inet_ntoa(restartAddr
));
675 /* In case of broadcast links, if RESTARTER is DR_OTHER,
676 * grace LSA might be received from DR, so fetching the
677 * actual neighbour information using restarter address.
679 if (oi
->type
!= OSPF_IFTYPE_POINTOPOINT
) {
680 restarter
= ospf_nbr_lookup_by_addr(oi
->nbrs
, &restartAddr
);
683 if (IS_DEBUG_OSPF_GR_HELPER
)
685 "%s, Restarter is not a neighbour for this router.",
686 __PRETTY_FUNCTION__
);
693 ospf_gr_helper_exit(restarter
, OSPF_GR_HELPER_COMPLETED
);
696 /* Configuration handlers */
698 * Disable/Enable HELPER support on router level.
709 void ospf_gr_helper_support_set(struct ospf
*ospf
, bool support
)
711 struct ospf_interface
*oi
;
712 struct listnode
*node
;
713 struct advRtr lookup
;
715 if (ospf
->is_helper_supported
== support
)
718 ospf
->is_helper_supported
= support
;
720 /* If helper support disabled, cease HELPER role for all
721 * supporting neighbors.
723 if (support
== OSPF_GR_FALSE
) {
724 for (ALL_LIST_ELEMENTS_RO(ospf
->oiflist
, node
, oi
)) {
725 struct route_node
*rn
= NULL
;
727 if (ospf_interface_neighbor_count(oi
) == 0)
730 for (rn
= route_top(oi
->nbrs
); rn
;
731 rn
= route_next(rn
)) {
732 struct ospf_neighbor
*nbr
= NULL
;
739 lookup
.advRtrAddr
.s_addr
=
740 nbr
->router_id
.s_addr
;
741 /* check if helper support enabled for the
742 * correspodning routerid.If enabled, dont
743 * dont exit from helper role.
745 if (hash_lookup(ospf
->enable_rtr_list
, &lookup
))
748 if (OSPF_GR_IS_ACTIVE_HELPER(nbr
))
750 nbr
, OSPF_GR_HELPER_TOPO_CHG
);
757 * Enable/Disable HELPER support on a specified advertagement
764 * HELPER support for given Advertisement Router.
767 * True - Enable Helper Support.
768 * False - Disable Helper Support.
774 void ospf_gr_helper_support_set_per_routerid(struct ospf
*ospf
,
775 struct in_addr
*advrtr
,
780 struct ospf_interface
*oi
;
781 struct listnode
*node
;
783 temp
.advRtrAddr
.s_addr
= advrtr
->s_addr
;
785 if (support
== OSPF_GR_FALSE
) {
786 /*Delete the routerid from the enable router hash table */
787 rtr
= hash_lookup(ospf
->enable_rtr_list
, &temp
);
790 hash_release(ospf
->enable_rtr_list
, rtr
);
791 ospf_disable_rtr_hash_free(rtr
);
794 /* If helper support is enabled globally
795 * no action is required.
797 if (ospf
->is_helper_supported
)
800 /* Cease the HELPER role fore neighbours from the
801 * specified advertisement router.
803 for (ALL_LIST_ELEMENTS_RO(ospf
->oiflist
, node
, oi
)) {
804 struct route_node
*rn
= NULL
;
806 if (ospf_interface_neighbor_count(oi
) == 0)
809 for (rn
= route_top(oi
->nbrs
); rn
;
810 rn
= route_next(rn
)) {
811 struct ospf_neighbor
*nbr
= NULL
;
818 if (nbr
->router_id
.s_addr
!= advrtr
->s_addr
)
821 if (OSPF_GR_IS_ACTIVE_HELPER(nbr
))
823 nbr
, OSPF_GR_HELPER_TOPO_CHG
);
828 /* Add the routerid to the enable router hash table */
829 hash_get(ospf
->enable_rtr_list
, &temp
,
830 ospf_enable_rtr_hash_alloc
);
835 * Api to enable/disable strict lsa check on the HELPER.
841 * True - disable the lsa check.
842 * False - enable the strict lsa check.
847 void ospf_gr_helper_lsa_check_set(struct ospf
*ospf
, bool enabled
)
849 if (ospf
->strict_lsa_check
== enabled
)
852 ospf
->strict_lsa_check
= enabled
;
856 * Api to set the supported grace interval in this router.
862 * The supported grace interval..
867 void ospf_gr_helper_supported_gracetime_set(struct ospf
*ospf
,
870 ospf
->supported_grace_time
= interval
;
874 * Api to set the supported restart reason.
880 * True: support only planned restart.
881 * False: support for planned/unplanned restarts.
886 void ospf_gr_helper_set_supported_planned_only_restart(struct ospf
*ospf
,
889 ospf
->only_planned_restart
= planned_only
;