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 static const char * const ospf_exit_reason_desc
[] = {
58 "Successful graceful restart",
61 static const char * const ospf_restart_reason_desc
[] = {
64 "Software reload/upgrade",
65 "Switch to redundant control processor",
68 static const char * const ospf_rejected_reason_desc
[] = {
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",
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 * GR exit reason strings
123 const char *ospf_exit_reason2str(unsigned int reason
)
125 if (reason
< array_size(ospf_exit_reason_desc
))
126 return(ospf_exit_reason_desc
[reason
]);
128 return "Invalid reason";
132 * GR restart reason strings
134 const char *ospf_restart_reason2str(unsigned int reason
)
136 if (reason
< array_size(ospf_restart_reason_desc
))
137 return(ospf_restart_reason_desc
[reason
]);
139 return "Invalid reason";
143 * GR rejected reason strings
145 const char *ospf_rejected_reason2str(unsigned int reason
)
147 if (reason
< array_size(ospf_rejected_reason_desc
))
148 return(ospf_rejected_reason_desc
[reason
]);
150 return "Invalid reason";
154 * Initialize GR helper config data structures.
162 void ospf_gr_helper_init(struct ospf
*ospf
)
166 if (IS_DEBUG_OSPF_GR_HELPER
)
167 zlog_debug("%s, GR Helper init.", __PRETTY_FUNCTION__
);
169 ospf
->is_helper_supported
= OSPF_GR_FALSE
;
170 ospf
->strict_lsa_check
= OSPF_GR_TRUE
;
171 ospf
->only_planned_restart
= OSPF_GR_FALSE
;
172 ospf
->supported_grace_time
= OSPF_MAX_GRACE_INTERVAL
;
173 ospf
->last_exit_reason
= OSPF_GR_HELPER_EXIT_NONE
;
174 ospf
->active_restarter_cnt
= 0;
176 ospf
->enable_rtr_list
=
177 hash_create(ospf_enable_rtr_hash_key
, ospf_enable_rtr_hash_cmp
,
178 "OSPF enable router hash");
180 rc
= ospf_register_opaque_functab(
181 OSPF_OPAQUE_LINK_LSA
, OPAQUE_TYPE_GRACE_LSA
, NULL
, NULL
, NULL
,
182 NULL
, NULL
, NULL
, NULL
, show_ospf_grace_lsa_info
, NULL
, NULL
,
185 flog_warn(EC_OSPF_OPAQUE_REGISTRATION
,
186 "%s: Failed to register Grace LSA functions",
192 * De-Initialize GR helper config data structures.
200 void ospf_gr_helper_stop(struct ospf
*ospf
)
203 if (IS_DEBUG_OSPF_GR_HELPER
)
204 zlog_debug("%s, GR helper deinit.", __PRETTY_FUNCTION__
);
206 ospf_enable_rtr_hash_destroy(ospf
);
208 ospf_delete_opaque_functab(OSPF_OPAQUE_LINK_LSA
, OPAQUE_TYPE_GRACE_LSA
);
212 * Extracting tlv info from GRACE LSA.
218 * interval : grace interval.
219 * addr : RESTARTER address.
220 * reason : Restarting reason.
222 static int ospf_extract_grace_lsa_fields(struct ospf_lsa
*lsa
,
224 struct in_addr
*addr
, uint8_t *reason
)
226 struct lsa_header
*lsah
= NULL
;
227 struct tlv_header
*tlvh
= NULL
;
228 struct grace_tlv_graceperiod
*grace_period
;
229 struct grace_tlv_restart_reason
*gr_reason
;
230 struct grace_tlv_restart_addr
*restart_addr
;
234 lsah
= (struct lsa_header
*)lsa
->data
;
236 length
= ntohs(lsah
->length
) - OSPF_LSA_HEADER_SIZE
;
238 for (tlvh
= TLV_HDR_TOP(lsah
); sum
< length
;
239 tlvh
= TLV_HDR_NEXT(tlvh
)) {
240 switch (ntohs(tlvh
->type
)) {
241 case GRACE_PERIOD_TYPE
:
242 grace_period
= (struct grace_tlv_graceperiod
*)tlvh
;
243 *interval
= ntohl(grace_period
->interval
);
244 sum
+= TLV_SIZE(tlvh
);
246 /* Check if grace interval is valid */
247 if (*interval
> OSPF_MAX_GRACE_INTERVAL
248 || *interval
< OSPF_MIN_GRACE_INTERVAL
)
249 return OSPF_GR_FAILURE
;
251 case RESTART_REASON_TYPE
:
252 gr_reason
= (struct grace_tlv_restart_reason
*)tlvh
;
253 *reason
= gr_reason
->reason
;
254 sum
+= TLV_SIZE(tlvh
);
256 if (*reason
>= OSPF_GR_INVALID_REASON_CODE
)
257 return OSPF_GR_FAILURE
;
259 case RESTARTER_IP_ADDR_TYPE
:
260 restart_addr
= (struct grace_tlv_restart_addr
*)tlvh
;
261 addr
->s_addr
= restart_addr
->addr
.s_addr
;
262 sum
+= TLV_SIZE(tlvh
);
265 if (IS_DEBUG_OSPF_GR_HELPER
)
267 "%s, Malformed packet.Invalid TLV type:%d",
268 __PRETTY_FUNCTION__
, ntohs(tlvh
->type
));
269 return OSPF_GR_FAILURE
;
273 return OSPF_GR_SUCCESS
;
277 * Grace timer expiry handler.
278 * HELPER aborts its role at grace timer expiry.
286 static int ospf_handle_grace_timer_expiry(struct thread
*thread
)
288 struct ospf_neighbor
*nbr
= THREAD_ARG(thread
);
290 nbr
->gr_helper_info
.t_grace_timer
= NULL
;
292 ospf_gr_helper_exit(nbr
, OSPF_GR_HELPER_GRACE_TIMEOUT
);
293 return OSPF_GR_SUCCESS
;
297 * Process Grace LSA.If it is eligible move to HELPER role.
298 * Ref rfc3623 section 3.1
304 * Grace LSA received from RESTARTER.
307 * ospf neighbour which requets the router to act as
312 * If supported as HELPER : OSPF_GR_HELPER_INPROGRESS
313 * If Not supported as HELPER : OSPF_GR_HELPER_NONE
315 int ospf_process_grace_lsa(struct ospf
*ospf
, struct ospf_lsa
*lsa
,
316 struct ospf_neighbor
*nbr
)
318 struct in_addr restart_addr
= {0};
319 uint8_t restart_reason
= 0;
320 uint32_t grace_interval
= 0;
321 uint32_t actual_grace_interval
= 0;
322 struct advRtr lookup
;
323 struct ospf_neighbor
*restarter
= NULL
;
324 struct ospf_interface
*oi
= nbr
->oi
;
328 /* Extract the grace lsa packet fields */
329 ret
= ospf_extract_grace_lsa_fields(lsa
, &grace_interval
, &restart_addr
,
331 if (ret
!= OSPF_GR_SUCCESS
) {
332 if (IS_DEBUG_OSPF_GR_HELPER
)
333 zlog_debug("%s, Wrong Grace LSA packet.",
334 __PRETTY_FUNCTION__
);
335 return OSPF_GR_NOT_HELPER
;
338 if (IS_DEBUG_OSPF_GR_HELPER
)
340 "%s, Grace LSA received from %s, grace interval:%u, restartreason :%s",
341 __PRETTY_FUNCTION__
, inet_ntoa(restart_addr
),
343 ospf_restart_reason2str(restart_reason
));
345 /* Incase of broadcast links, if RESTARTER is DR_OTHER,
346 * grace LSA might be received from DR, so need to get
347 * actual neighbour info , here RESTARTER.
349 if (oi
->type
!= OSPF_IFTYPE_POINTOPOINT
) {
350 restarter
= ospf_nbr_lookup_by_addr(oi
->nbrs
, &restart_addr
);
353 if (IS_DEBUG_OSPF_GR_HELPER
)
355 "%s, Restarter is not a nbr(%s) for this router.",
357 inet_ntoa(restart_addr
));
358 return OSPF_GR_NOT_HELPER
;
363 /* Verify Helper enabled globally */
364 if (!ospf
->is_helper_supported
) {
365 /* Verify that Helper support is enabled for the
366 * current neighbour router-id.
368 lookup
.advRtrAddr
.s_addr
= restarter
->router_id
.s_addr
;
370 if (!hash_lookup(ospf
->enable_rtr_list
, &lookup
)) {
371 if (IS_DEBUG_OSPF_GR_HELPER
)
373 "%s, HELPER support is disabled, So not a HELPER",
374 __PRETTY_FUNCTION__
);
375 restarter
->gr_helper_info
.rejected_reason
=
376 OSPF_HELPER_SUPPORT_DISABLED
;
377 return OSPF_GR_NOT_HELPER
;
382 /* Check neighbour is in FULL state and
383 * became a adjacency.
385 if (!IS_NBR_STATE_FULL(restarter
)) {
386 if (IS_DEBUG_OSPF_GR_HELPER
)
388 "%s, This Neighbour %s is not in FULL state.",
389 __PRETTY_FUNCTION__
, inet_ntoa(restarter
->src
));
390 restarter
->gr_helper_info
.rejected_reason
=
391 OSPF_HELPER_NOT_A_VALID_NEIGHBOUR
;
392 return OSPF_GR_NOT_HELPER
;
395 /* Based on the restart reason from grace lsa
396 * check the current router is supporting or not
398 if (ospf
->only_planned_restart
399 && !OSPF_GR_IS_PLANNED_RESTART(restart_reason
)) {
400 if (IS_DEBUG_OSPF_GR_HELPER
)
402 "%s, Router supports only planned restarts but received the GRACE LSA for an unplanned restart.",
403 __PRETTY_FUNCTION__
);
404 restarter
->gr_helper_info
.rejected_reason
=
405 OSPF_HELPER_PLANNED_ONLY_RESTART
;
406 return OSPF_GR_NOT_HELPER
;
409 /* Check the retranmission list of this
410 * neighbour, check any change in lsas.
412 if (ospf
->strict_lsa_check
&& !ospf_ls_retransmit_isempty(restarter
)
413 && ospf_check_change_in_rxmt_list(restarter
)) {
414 if (IS_DEBUG_OSPF_GR_HELPER
)
416 "%s, Changed LSA in Rxmt list. So not Helper.",
417 __PRETTY_FUNCTION__
);
418 restarter
->gr_helper_info
.rejected_reason
=
419 OSPF_HELPER_TOPO_CHANGE_RTXMT_LIST
;
420 return OSPF_GR_NOT_HELPER
;
423 /*LSA age must be less than the grace period */
424 if (ntohs(lsa
->data
->ls_age
) >= grace_interval
) {
425 if (IS_DEBUG_OSPF_GR_HELPER
)
427 "%s, Grace LSA age(%d) is more than the graceinterval(%d)",
428 __PRETTY_FUNCTION__
, lsa
->data
->ls_age
,
430 restarter
->gr_helper_info
.rejected_reason
=
431 OSPF_HELPER_LSA_AGE_MORE
;
432 return OSPF_GR_NOT_HELPER
;
435 /* check supported grace period configured
436 * if configured, use this to start the grace
437 * timer otherwise use the interval received
438 * in grace LSA packet.
440 actual_grace_interval
= grace_interval
;
441 if (grace_interval
> ospf
->supported_grace_time
) {
442 if (IS_DEBUG_OSPF_GR_HELPER
)
444 "%s, Received grace period %d is larger than supported grace %d",
445 __PRETTY_FUNCTION__
, grace_interval
,
446 ospf
->supported_grace_time
);
447 actual_grace_interval
= ospf
->supported_grace_time
;
450 if (OSPF_GR_IS_ACTIVE_HELPER(restarter
)) {
451 if (restarter
->gr_helper_info
.t_grace_timer
)
452 THREAD_OFF(restarter
->gr_helper_info
.t_grace_timer
);
454 if (ospf
->active_restarter_cnt
> 0)
455 ospf
->active_restarter_cnt
--;
457 if (IS_DEBUG_OSPF_GR_HELPER
)
459 "%s, Router is already acting as a HELPER for this nbr,so restart the grace timer",
460 __PRETTY_FUNCTION__
);
462 if (IS_DEBUG_OSPF_GR_HELPER
)
464 "%s, This Router becomes a HELPER for the neighbour %s",
465 __PRETTY_FUNCTION__
, inet_ntoa(restarter
->src
));
468 /* Became a Helper to the RESTART neighbour.
469 * Change the helper status.
471 restarter
->gr_helper_info
.gr_helper_status
= OSPF_GR_ACTIVE_HELPER
;
472 restarter
->gr_helper_info
.recvd_grace_period
= grace_interval
;
473 restarter
->gr_helper_info
.actual_grace_period
= actual_grace_interval
;
474 restarter
->gr_helper_info
.gr_restart_reason
= restart_reason
;
475 restarter
->gr_helper_info
.rejected_reason
= OSPF_HELPER_REJECTED_NONE
;
477 /* Incremnet the active restarer count */
478 ospf
->active_restarter_cnt
++;
480 if (IS_DEBUG_OSPF_GR_HELPER
)
481 zlog_debug("%s, Grace timer started.interval:%d",
482 __PRETTY_FUNCTION__
, actual_grace_interval
);
484 /* Start the grace timer */
485 thread_add_timer(master
, ospf_handle_grace_timer_expiry
, restarter
,
486 actual_grace_interval
,
487 &restarter
->gr_helper_info
.t_grace_timer
);
489 return OSPF_GR_ACTIVE_HELPER
;
493 * API to check any change in the neighbor's
494 * retransmission list.
500 * TRUE - if any change in the lsa.
501 * FALSE - no change in the lsas.
503 static bool ospf_check_change_in_rxmt_list(struct ospf_neighbor
*nbr
)
505 struct route_node
*rn
;
506 struct ospf_lsa
*lsa
;
507 struct route_table
*tbl
;
509 tbl
= nbr
->ls_rxmt
.type
[OSPF_ROUTER_LSA
].db
;
510 LSDB_LOOP (tbl
, rn
, lsa
)
511 if (lsa
->to_be_acknowledged
)
513 tbl
= nbr
->ls_rxmt
.type
[OSPF_NETWORK_LSA
].db
;
514 LSDB_LOOP (tbl
, rn
, lsa
)
515 if (lsa
->to_be_acknowledged
)
518 tbl
= nbr
->ls_rxmt
.type
[OSPF_SUMMARY_LSA
].db
;
519 LSDB_LOOP (tbl
, rn
, lsa
)
520 if (lsa
->to_be_acknowledged
)
523 tbl
= nbr
->ls_rxmt
.type
[OSPF_ASBR_SUMMARY_LSA
].db
;
524 LSDB_LOOP (tbl
, rn
, lsa
)
525 if (lsa
->to_be_acknowledged
)
528 tbl
= nbr
->ls_rxmt
.type
[OSPF_AS_EXTERNAL_LSA
].db
;
529 LSDB_LOOP (tbl
, rn
, lsa
)
530 if (lsa
->to_be_acknowledged
)
533 tbl
= nbr
->ls_rxmt
.type
[OSPF_AS_NSSA_LSA
].db
;
534 LSDB_LOOP (tbl
, rn
, lsa
)
535 if (lsa
->to_be_acknowledged
)
538 return OSPF_GR_FALSE
;
542 * Actions to be taken when topo change detected
543 * HELPER will exit upon topo change.
548 * topo change occured due to this lsa type (1 to 5 and 7)
553 void ospf_helper_handle_topo_chg(struct ospf
*ospf
, struct ospf_lsa
*lsa
)
555 struct listnode
*node
;
556 struct ospf_interface
*oi
;
558 if (!ospf
->active_restarter_cnt
)
561 /* Topo change not required to be hanlded if strict
562 * LSA check is disbaled for this router.
564 if (!ospf
->strict_lsa_check
)
567 if (IS_DEBUG_OSPF_GR_HELPER
)
569 "%s, Topo change detected due to lsa LSID:%s type:%d",
570 __PRETTY_FUNCTION__
, inet_ntoa(lsa
->data
->id
),
573 lsa
->to_be_acknowledged
= OSPF_GR_TRUE
;
575 for (ALL_LIST_ELEMENTS_RO(ospf
->oiflist
, node
, oi
)) {
576 struct route_node
*rn
= NULL
;
578 if (ospf_interface_neighbor_count(oi
) == 0)
581 /* Ref rfc3623 section 3.2.3.b
582 * If change due to external LSA and if the area is
583 * stub, then it is not a topo change. Since Type-5
584 * lsas will not be flooded in stub area.
586 if ((oi
->area
->external_routing
== OSPF_AREA_STUB
)
587 && (lsa
->data
->type
== OSPF_AS_EXTERNAL_LSA
)) {
591 for (rn
= route_top(oi
->nbrs
); rn
; rn
= route_next(rn
)) {
592 struct ospf_neighbor
*nbr
= NULL
;
599 if (OSPF_GR_IS_ACTIVE_HELPER(nbr
))
600 ospf_gr_helper_exit(nbr
,
601 OSPF_GR_HELPER_TOPO_CHG
);
607 * Api to exit from HELPER role to take all actions
609 * Ref rfc3623 section 3.2
615 * OSPF neighbour for which it is acting as HELPER.
618 * The reason for exiting from HELPER.
623 void ospf_gr_helper_exit(struct ospf_neighbor
*nbr
,
624 enum ospf_helper_exit_reason reason
)
626 struct ospf_interface
*oi
= nbr
->oi
;
627 struct ospf
*ospf
= oi
->ospf
;
629 if (!OSPF_GR_IS_ACTIVE_HELPER(nbr
))
632 if (IS_DEBUG_OSPF_GR_HELPER
)
633 zlog_debug("%s, Exiting from HELPER support to %s, due to %s",
634 __PRETTY_FUNCTION__
, inet_ntoa(nbr
->src
),
635 ospf_exit_reason2str(reason
));
637 /* Reset helper status*/
638 nbr
->gr_helper_info
.gr_helper_status
= OSPF_GR_NOT_HELPER
;
639 nbr
->gr_helper_info
.helper_exit_reason
= reason
;
640 nbr
->gr_helper_info
.actual_grace_period
= 0;
641 nbr
->gr_helper_info
.recvd_grace_period
= 0;
642 nbr
->gr_helper_info
.gr_restart_reason
= 0;
643 ospf
->last_exit_reason
= reason
;
645 if (ospf
->active_restarter_cnt
<= 0) {
647 "OSPF GR-Helper: active_restarter_cnt should be greater than zero here.");
650 /* Decrement active Restarter count */
651 ospf
->active_restarter_cnt
--;
653 /* If the exit not triggered due to grace timer
654 * expairy , stop the grace timer.
656 if (reason
!= OSPF_GR_HELPER_GRACE_TIMEOUT
)
657 THREAD_OFF(nbr
->gr_helper_info
.t_grace_timer
);
659 /* check exit triggered due to successful completion
660 * of graceful restart.
661 * If no, bringdown the neighbour.
663 if (reason
!= OSPF_GR_HELPER_COMPLETED
) {
664 if (IS_DEBUG_OSPF_GR_HELPER
)
666 "%s, Failed GR exit, so bringing down the neighbour",
667 __PRETTY_FUNCTION__
);
668 OSPF_NSM_EVENT_EXECUTE(nbr
, NSM_KillNbr
);
671 /*Recalculate the DR for the network segment */
672 ospf_dr_election(oi
);
674 /* Originate a router LSA */
675 ospf_router_lsa_update_area(oi
->area
);
677 /* Originate network lsa if it is an DR in the LAN */
678 if (oi
->state
== ISM_DR
)
679 ospf_network_lsa_update(oi
);
683 * Process Maxage Grace LSA.
684 * It is a indication for successful completion of GR.
685 * If router acting as HELPER, It exits from helper role.
691 * Grace LSA received from RESTARTER.
694 * ospf neighbour which requets the router to act as
700 void ospf_process_maxage_grace_lsa(struct ospf
*ospf
, struct ospf_lsa
*lsa
,
701 struct ospf_neighbor
*nbr
)
703 struct in_addr restartAddr
= {0};
704 uint8_t restartReason
= 0;
705 uint32_t graceInterval
= 0;
706 struct ospf_neighbor
*restarter
= NULL
;
707 struct ospf_interface
*oi
= nbr
->oi
;
710 /* Extract the grace lsa packet fields */
711 ret
= ospf_extract_grace_lsa_fields(lsa
, &graceInterval
, &restartAddr
,
713 if (ret
!= OSPF_GR_SUCCESS
) {
714 if (IS_DEBUG_OSPF_GR_HELPER
)
715 zlog_debug("%s, Wrong Grace LSA packet.",
716 __PRETTY_FUNCTION__
);
720 if (IS_DEBUG_OSPF_GR_HELPER
)
721 zlog_debug("%s, GraceLSA received for neighbour %s.",
722 __PRETTY_FUNCTION__
, inet_ntoa(restartAddr
));
724 /* In case of broadcast links, if RESTARTER is DR_OTHER,
725 * grace LSA might be received from DR, so fetching the
726 * actual neighbour information using restarter address.
728 if (oi
->type
!= OSPF_IFTYPE_POINTOPOINT
) {
729 restarter
= ospf_nbr_lookup_by_addr(oi
->nbrs
, &restartAddr
);
732 if (IS_DEBUG_OSPF_GR_HELPER
)
734 "%s, Restarter is not a neighbour for this router.",
735 __PRETTY_FUNCTION__
);
742 ospf_gr_helper_exit(restarter
, OSPF_GR_HELPER_COMPLETED
);
745 /* Configuration handlers */
747 * Disable/Enable HELPER support on router level.
758 void ospf_gr_helper_support_set(struct ospf
*ospf
, bool support
)
760 struct ospf_interface
*oi
;
761 struct listnode
*node
;
762 struct advRtr lookup
;
764 if (ospf
->is_helper_supported
== support
)
767 ospf
->is_helper_supported
= support
;
769 /* If helper support disabled, cease HELPER role for all
770 * supporting neighbors.
772 if (support
== OSPF_GR_FALSE
) {
773 for (ALL_LIST_ELEMENTS_RO(ospf
->oiflist
, node
, oi
)) {
774 struct route_node
*rn
= NULL
;
776 if (ospf_interface_neighbor_count(oi
) == 0)
779 for (rn
= route_top(oi
->nbrs
); rn
;
780 rn
= route_next(rn
)) {
781 struct ospf_neighbor
*nbr
= NULL
;
788 lookup
.advRtrAddr
.s_addr
=
789 nbr
->router_id
.s_addr
;
790 /* check if helper support enabled for the
791 * correspodning routerid.If enabled, dont
792 * dont exit from helper role.
794 if (hash_lookup(ospf
->enable_rtr_list
, &lookup
))
797 if (OSPF_GR_IS_ACTIVE_HELPER(nbr
))
799 nbr
, OSPF_GR_HELPER_TOPO_CHG
);
806 * Enable/Disable HELPER support on a specified advertagement
813 * HELPER support for given Advertisement Router.
816 * True - Enable Helper Support.
817 * False - Disable Helper Support.
823 void ospf_gr_helper_support_set_per_routerid(struct ospf
*ospf
,
824 struct in_addr
*advrtr
,
829 struct ospf_interface
*oi
;
830 struct listnode
*node
;
832 temp
.advRtrAddr
.s_addr
= advrtr
->s_addr
;
834 if (support
== OSPF_GR_FALSE
) {
835 /*Delete the routerid from the enable router hash table */
836 rtr
= hash_lookup(ospf
->enable_rtr_list
, &temp
);
839 hash_release(ospf
->enable_rtr_list
, rtr
);
840 ospf_disable_rtr_hash_free(rtr
);
843 /* If helper support is enabled globally
844 * no action is required.
846 if (ospf
->is_helper_supported
)
849 /* Cease the HELPER role fore neighbours from the
850 * specified advertisement router.
852 for (ALL_LIST_ELEMENTS_RO(ospf
->oiflist
, node
, oi
)) {
853 struct route_node
*rn
= NULL
;
855 if (ospf_interface_neighbor_count(oi
) == 0)
858 for (rn
= route_top(oi
->nbrs
); rn
;
859 rn
= route_next(rn
)) {
860 struct ospf_neighbor
*nbr
= NULL
;
867 if (nbr
->router_id
.s_addr
!= advrtr
->s_addr
)
870 if (OSPF_GR_IS_ACTIVE_HELPER(nbr
))
872 nbr
, OSPF_GR_HELPER_TOPO_CHG
);
877 /* Add the routerid to the enable router hash table */
878 hash_get(ospf
->enable_rtr_list
, &temp
,
879 ospf_enable_rtr_hash_alloc
);
884 * Api to enable/disable strict lsa check on the HELPER.
890 * True - disable the lsa check.
891 * False - enable the strict lsa check.
896 void ospf_gr_helper_lsa_check_set(struct ospf
*ospf
, bool enabled
)
898 if (ospf
->strict_lsa_check
== enabled
)
901 ospf
->strict_lsa_check
= enabled
;
905 * Api to set the supported grace interval in this router.
911 * The supported grace interval..
916 void ospf_gr_helper_supported_gracetime_set(struct ospf
*ospf
,
919 ospf
->supported_grace_time
= interval
;
923 * Api to set the supported restart reason.
929 * True: support only planned restart.
930 * False: support for planned/unplanned restarts.
935 void ospf_gr_helper_set_supported_planned_only_restart(struct ospf
*ospf
,
938 ospf
->only_planned_restart
= planned_only
;
942 * Api to display the grace LSA information.
954 static void show_ospf_grace_lsa_info(struct vty
*vty
, struct ospf_lsa
*lsa
)
956 struct lsa_header
*lsah
= NULL
;
957 struct tlv_header
*tlvh
= NULL
;
958 struct grace_tlv_graceperiod
*gracePeriod
;
959 struct grace_tlv_restart_reason
*grReason
;
960 struct grace_tlv_restart_addr
*restartAddr
;
964 lsah
= (struct lsa_header
*)lsa
->data
;
966 length
= ntohs(lsah
->length
) - OSPF_LSA_HEADER_SIZE
;
968 vty_out(vty
, " TLV info:\n");
970 for (tlvh
= TLV_HDR_TOP(lsah
); sum
< length
;
971 tlvh
= TLV_HDR_NEXT(tlvh
)) {
972 switch (ntohs(tlvh
->type
)) {
973 case GRACE_PERIOD_TYPE
:
974 gracePeriod
= (struct grace_tlv_graceperiod
*)tlvh
;
975 sum
+= TLV_SIZE(tlvh
);
977 vty_out(vty
, " Grace period:%d\n",
978 ntohl(gracePeriod
->interval
));
980 case RESTART_REASON_TYPE
:
981 grReason
= (struct grace_tlv_restart_reason
*)tlvh
;
982 sum
+= TLV_SIZE(tlvh
);
984 vty_out(vty
, " Restart reason:%s\n",
985 ospf_restart_reason2str(grReason
->reason
));
987 case RESTARTER_IP_ADDR_TYPE
:
988 restartAddr
= (struct grace_tlv_restart_addr
*)tlvh
;
989 sum
+= TLV_SIZE(tlvh
);
991 vty_out(vty
, " Restarter address:%s\n",
992 inet_ntoa(restartAddr
->addr
));