]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_gr_helper.c
Merge pull request #13177 from mjstapp/fix_ospf_supoort_typo
[mirror_frr.git] / ospf6d / ospf6_gr_helper.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * OSPF6 Graceful Restart helper functions.
4 *
5 * Copyright (C) 2021-22 Vmware, Inc.
6 * Rajesh Kumar Girada
7 */
8
9 #include <zebra.h>
10
11 #include "log.h"
12 #include "vty.h"
13 #include "command.h"
14 #include "prefix.h"
15 #include "stream.h"
16 #include "zclient.h"
17 #include "memory.h"
18 #include "table.h"
19 #include "lib/bfd.h"
20 #include "lib_errors.h"
21 #include "jhash.h"
22
23 #include "ospf6_proto.h"
24 #include "ospf6_lsa.h"
25 #include "ospf6_lsdb.h"
26 #include "ospf6_route.h"
27 #include "ospf6_message.h"
28
29 #include "ospf6_top.h"
30 #include "ospf6_area.h"
31 #include "ospf6_interface.h"
32 #include "ospf6_neighbor.h"
33 #include "ospf6_intra.h"
34 #include "ospf6d.h"
35 #include "ospf6_gr.h"
36 #include "lib/json.h"
37 #include "ospf6d/ospf6_gr_helper_clippy.c"
38
39 DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_GR_HELPER, "OSPF6 Graceful restart helper");
40
41 unsigned char conf_debug_ospf6_gr;
42
43 static int ospf6_grace_lsa_show_info(struct vty *vty, struct ospf6_lsa *lsa,
44 json_object *json, bool use_json);
45
46 struct ospf6_lsa_handler grace_lsa_handler = {.lh_type = OSPF6_LSTYPE_GRACE_LSA,
47 .lh_name = "Grace",
48 .lh_short_name = "GR",
49 .lh_show =
50 ospf6_grace_lsa_show_info,
51 .lh_get_prefix_str = NULL,
52 .lh_debug = 0};
53
54 const char *ospf6_exit_reason_desc[] = {
55 "Unknown reason",
56 "Helper in progress",
57 "Topology Change",
58 "Grace timer expiry",
59 "Successful graceful restart",
60 };
61
62 const char *ospf6_restart_reason_desc[] = {
63 "Unknown restart",
64 "Software restart",
65 "Software reload/upgrade",
66 "Switch to redundant control processor",
67 };
68
69 const char *ospf6_rejected_reason_desc[] = {
70 "Unknown reason",
71 "Helper support disabled",
72 "Neighbour is not in FULL state",
73 "Supports only planned restart but received for unplanned",
74 "Topo change due to change in lsa rxmt list",
75 "LSA age is more than Grace interval",
76 };
77
78 static unsigned int ospf6_enable_rtr_hash_key(const void *data)
79 {
80 const struct advRtr *rtr = data;
81
82 return jhash_1word(rtr->advRtrAddr, 0);
83 }
84
85 static bool ospf6_enable_rtr_hash_cmp(const void *d1, const void *d2)
86 {
87 const struct advRtr *rtr1 = d1;
88 const struct advRtr *rtr2 = d2;
89
90 return (rtr1->advRtrAddr == rtr2->advRtrAddr);
91 }
92
93 static void *ospf6_enable_rtr_hash_alloc(void *p)
94 {
95 struct advRtr *rid;
96
97 rid = XCALLOC(MTYPE_OSPF6_GR_HELPER, sizeof(struct advRtr));
98 rid->advRtrAddr = ((struct advRtr *)p)->advRtrAddr;
99
100 return rid;
101 }
102
103 static void ospf6_disable_rtr_hash_free(void *rtr)
104 {
105 XFREE(MTYPE_OSPF6_GR_HELPER, rtr);
106 }
107
108 static void ospf6_enable_rtr_hash_destroy(struct ospf6 *ospf6)
109 {
110 if (ospf6->ospf6_helper_cfg.enable_rtr_list == NULL)
111 return;
112
113 hash_clean_and_free(&ospf6->ospf6_helper_cfg.enable_rtr_list,
114 ospf6_disable_rtr_hash_free);
115 }
116
117 /*
118 * Extracting tlv info from GRACE LSA.
119 *
120 * lsa
121 * ospf6 grace lsa
122 *
123 * Returns:
124 * interval : grace interval.
125 * reason : Restarting reason.
126 */
127 static int ospf6_extract_grace_lsa_fields(struct ospf6_lsa *lsa,
128 uint32_t *interval, uint8_t *reason)
129 {
130 struct ospf6_lsa_header *lsah = NULL;
131 struct tlv_header *tlvh = NULL;
132 struct grace_tlv_graceperiod *gracePeriod;
133 struct grace_tlv_restart_reason *grReason;
134 uint16_t length = 0;
135 int sum = 0;
136
137 lsah = (struct ospf6_lsa_header *)lsa->header;
138 if (ntohs(lsah->length) <= OSPF6_LSA_HEADER_SIZE) {
139 if (IS_DEBUG_OSPF6_GR)
140 zlog_debug("%s: undersized (%u B) lsa", __func__,
141 ntohs(lsah->length));
142 return OSPF6_FAILURE;
143 }
144
145 length = ntohs(lsah->length) - OSPF6_LSA_HEADER_SIZE;
146
147 for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh;
148 tlvh = TLV_HDR_NEXT(tlvh)) {
149
150 /* Check TLV len against overall LSA */
151 if (sum + TLV_SIZE(tlvh) > length) {
152 if (IS_DEBUG_OSPF6_GR)
153 zlog_debug(
154 "%s: Malformed packet: Invalid TLV len:%d",
155 __func__, TLV_SIZE(tlvh));
156 return OSPF6_FAILURE;
157 }
158
159 switch (ntohs(tlvh->type)) {
160 case GRACE_PERIOD_TYPE:
161 gracePeriod = (struct grace_tlv_graceperiod *)tlvh;
162 *interval = ntohl(gracePeriod->interval);
163 sum += TLV_SIZE(tlvh);
164
165 /* Check if grace interval is valid */
166 if (*interval > OSPF6_MAX_GRACE_INTERVAL
167 || *interval < OSPF6_MIN_GRACE_INTERVAL)
168 return OSPF6_FAILURE;
169 break;
170 case RESTART_REASON_TYPE:
171 grReason = (struct grace_tlv_restart_reason *)tlvh;
172 *reason = grReason->reason;
173 sum += TLV_SIZE(tlvh);
174
175 if (*reason >= OSPF6_GR_INVALID_REASON_CODE)
176 return OSPF6_FAILURE;
177 break;
178 default:
179 if (IS_DEBUG_OSPF6_GR)
180 zlog_debug("%s, Ignoring unknown TLV type:%d",
181 __func__, ntohs(tlvh->type));
182 }
183 }
184
185 return OSPF6_SUCCESS;
186 }
187
188 /*
189 * Grace timer expiry handler.
190 * HELPER aborts its role at grace timer expiry.
191 *
192 * thread
193 * thread pointer
194 *
195 * Returns:
196 * Nothing
197 */
198 static void ospf6_handle_grace_timer_expiry(struct event *thread)
199 {
200 struct ospf6_neighbor *nbr = EVENT_ARG(thread);
201
202 ospf6_gr_helper_exit(nbr, OSPF6_GR_HELPER_GRACE_TIMEOUT);
203 }
204
205 /*
206 * API to check any change in the neighbor's
207 * retransmission list.
208 *
209 * nbr
210 * ospf6 neighbor
211 *
212 * Returns:
213 * TRUE - if any change in the lsa.
214 * FALSE - no change in the lsas.
215 */
216 static bool ospf6_check_chg_in_rxmt_list(struct ospf6_neighbor *nbr)
217 {
218 struct ospf6_lsa *lsa, *lsanext;
219
220 for (ALL_LSDB(nbr->retrans_list, lsa, lsanext)) {
221 struct ospf6_lsa *lsa_in_db = NULL;
222
223 /* Fetching the same copy of LSA form LSDB to validate the
224 * topochange.
225 */
226 lsa_in_db =
227 ospf6_lsdb_lookup(lsa->header->type, lsa->header->id,
228 lsa->header->adv_router, lsa->lsdb);
229
230 if (lsa_in_db && lsa_in_db->tobe_acknowledged) {
231 ospf6_lsa_unlock(lsa);
232 if (lsanext)
233 ospf6_lsa_unlock(lsanext);
234
235 return OSPF6_TRUE;
236 }
237 }
238
239 return OSPF6_FALSE;
240 }
241
242 /*
243 * Process Grace LSA.If it is eligible move to HELPER role.
244 * Ref rfc3623 section 3.1 and rfc5187
245 *
246 * ospf
247 * Ospf6 pointer.
248 *
249 * lsa
250 * Grace LSA received from RESTARTER.
251 *
252 * restarter
253 * ospf6 neighbour which requests the router to act as
254 * HELPER.
255 *
256 * Returns:
257 * status.
258 * If supported as HELPER : OSPF_GR_HELPER_INPROGRESS
259 * If Not supported as HELPER : OSPF_GR_HELPER_NONE
260 */
261 int ospf6_process_grace_lsa(struct ospf6 *ospf6, struct ospf6_lsa *lsa,
262 struct ospf6_neighbor *restarter)
263 {
264 uint8_t restart_reason = 0;
265 uint32_t grace_interval = 0;
266 uint32_t actual_grace_interval = 0;
267 struct advRtr lookup;
268 int ret;
269
270 /* Extract the grace lsa packet fields */
271 ret = ospf6_extract_grace_lsa_fields(lsa, &grace_interval,
272 &restart_reason);
273 if (ret != OSPF6_SUCCESS) {
274 if (IS_DEBUG_OSPF6_GR)
275 zlog_debug("%s, Wrong Grace LSA packet.", __func__);
276 return OSPF6_GR_NOT_HELPER;
277 }
278
279 if (IS_DEBUG_OSPF6_GR)
280 zlog_debug(
281 "%s, Grace LSA received from %s(%pI4), grace interval:%u, restart reason:%s",
282 __func__, restarter->name, &restarter->router_id,
283 grace_interval,
284 ospf6_restart_reason_desc[restart_reason]);
285
286 /* Verify Helper enabled globally */
287 if (!ospf6->ospf6_helper_cfg.is_helper_supported) {
288 /* Verify Helper support is enabled for the
289 * current neighbour router-id.
290 */
291 lookup.advRtrAddr = restarter->router_id;
292
293 if (!hash_lookup(ospf6->ospf6_helper_cfg.enable_rtr_list,
294 &lookup)) {
295 if (IS_DEBUG_OSPF6_GR)
296 zlog_debug(
297 "%s, HELPER support is disabled, So not a HELPER",
298 __func__);
299 restarter->gr_helper_info.rejected_reason =
300 OSPF6_HELPER_SUPPORT_DISABLED;
301 return OSPF6_GR_NOT_HELPER;
302 }
303 }
304
305 /* Check neighbour is in FULL state and
306 * became a adjacency.
307 */
308 if (!IS_NBR_STATE_FULL(restarter)) {
309 if (IS_DEBUG_OSPF6_GR)
310 zlog_debug(
311 "%s, This Neighbour %pI6 is not in FULL state.",
312 __func__, &restarter->linklocal_addr);
313 restarter->gr_helper_info.rejected_reason =
314 OSPF6_HELPER_NOT_A_VALID_NEIGHBOUR;
315 return OSPF6_GR_NOT_HELPER;
316 }
317
318 /* Based on the restart reason from grace lsa
319 * check the current router is supporting or not
320 */
321 if (ospf6->ospf6_helper_cfg.only_planned_restart
322 && !OSPF6_GR_IS_PLANNED_RESTART(restart_reason)) {
323 if (IS_DEBUG_OSPF6_GR)
324 zlog_debug(
325 "%s, Router supports only planned restarts but received the GRACE LSA due to an unplanned restart",
326 __func__);
327 restarter->gr_helper_info.rejected_reason =
328 OSPF6_HELPER_PLANNED_ONLY_RESTART;
329 return OSPF6_GR_NOT_HELPER;
330 }
331
332 /* Check the retransmission list of this
333 * neighbour, check any change in lsas.
334 */
335 if (ospf6->ospf6_helper_cfg.strict_lsa_check
336 && restarter->retrans_list->count
337 && ospf6_check_chg_in_rxmt_list(restarter)) {
338 if (IS_DEBUG_OSPF6_GR)
339 zlog_debug(
340 "%s, Changed LSA in Rxmt list.So not Helper.",
341 __func__);
342 restarter->gr_helper_info.rejected_reason =
343 OSPF6_HELPER_TOPO_CHANGE_RTXMT_LIST;
344 return OSPF6_GR_NOT_HELPER;
345 }
346
347 /* LSA age must be less than the grace period */
348 if (ntohs(lsa->header->age) >= grace_interval) {
349 if (IS_DEBUG_OSPF6_GR)
350 zlog_debug(
351 "%s, Grace LSA age(%d) is more than the grace interval(%d)",
352 __func__, lsa->header->age, grace_interval);
353 restarter->gr_helper_info.rejected_reason =
354 OSPF6_HELPER_LSA_AGE_MORE;
355 return OSPF6_GR_NOT_HELPER;
356 }
357
358 if (ospf6->gr_info.restart_in_progress) {
359 if (IS_DEBUG_OSPF6_GR)
360 zlog_debug(
361 "%s: router is in the process of graceful restart",
362 __func__);
363 restarter->gr_helper_info.rejected_reason =
364 OSPF6_HELPER_RESTARTING;
365 return OSPF6_GR_NOT_HELPER;
366 }
367
368 /* check supported grace period configured
369 * if configured, use this to start the grace
370 * timer otherwise use the interval received
371 * in grace LSA packet.
372 */
373 actual_grace_interval = grace_interval;
374 if (grace_interval > ospf6->ospf6_helper_cfg.supported_grace_time) {
375 if (IS_DEBUG_OSPF6_GR)
376 zlog_debug(
377 "%s, Received grace period %d is larger than supported grace %d",
378 __func__, grace_interval,
379 ospf6->ospf6_helper_cfg.supported_grace_time);
380 actual_grace_interval =
381 ospf6->ospf6_helper_cfg.supported_grace_time;
382 }
383
384 if (OSPF6_GR_IS_ACTIVE_HELPER(restarter)) {
385 EVENT_OFF(restarter->gr_helper_info.t_grace_timer);
386
387 if (ospf6->ospf6_helper_cfg.active_restarter_cnt > 0)
388 ospf6->ospf6_helper_cfg.active_restarter_cnt--;
389
390 if (IS_DEBUG_OSPF6_GR)
391 zlog_debug(
392 "%s, Router is already acting as a HELPER for this nbr,so restart the grace timer",
393 __func__);
394 } else {
395 if (IS_DEBUG_OSPF6_GR)
396 zlog_debug(
397 "%s, This Router becomes a HELPER for the neighbour %pI6",
398 __func__, &restarter->linklocal_addr);
399 }
400
401 /* Became a Helper to the RESTART neighbour.
402 * change the helper status.
403 */
404 restarter->gr_helper_info.gr_helper_status = OSPF6_GR_ACTIVE_HELPER;
405 restarter->gr_helper_info.recvd_grace_period = grace_interval;
406 restarter->gr_helper_info.actual_grace_period = actual_grace_interval;
407 restarter->gr_helper_info.gr_restart_reason = restart_reason;
408 restarter->gr_helper_info.rejected_reason = OSPF6_HELPER_REJECTED_NONE;
409
410 /* Increment the active restart nbr count */
411 ospf6->ospf6_helper_cfg.active_restarter_cnt++;
412
413 if (IS_DEBUG_OSPF6_GR)
414 zlog_debug("%s, Grace timer started.interval:%u", __func__,
415 actual_grace_interval);
416
417 /* Start the grace timer */
418 event_add_timer(master, ospf6_handle_grace_timer_expiry, restarter,
419 actual_grace_interval,
420 &restarter->gr_helper_info.t_grace_timer);
421
422 return OSPF6_GR_ACTIVE_HELPER;
423 }
424
425 /*
426 * Api to exit from HELPER role to take all actions
427 * required at exit.
428 * Ref rfc3623 section 3. and rfc51872
429 *
430 * ospf6
431 * Ospf6 pointer.
432 *
433 * nbr
434 * Ospf6 neighbour for which it is acting as HELPER.
435 *
436 * reason
437 * The reason for exiting from HELPER.
438 *
439 * Returns:
440 * Nothing.
441 */
442 void ospf6_gr_helper_exit(struct ospf6_neighbor *nbr,
443 enum ospf6_helper_exit_reason reason)
444 {
445 struct ospf6_interface *oi = nbr->ospf6_if;
446 struct ospf6 *ospf6;
447
448 if (!oi)
449 return;
450
451 ospf6 = oi->area->ospf6;
452
453 if (!OSPF6_GR_IS_ACTIVE_HELPER(nbr))
454 return;
455
456 if (IS_DEBUG_OSPF6_GR)
457 zlog_debug("%s, Exiting from HELPER support to %pI6, due to %s",
458 __func__, &nbr->linklocal_addr,
459 ospf6_exit_reason_desc[reason]);
460
461 /* Reset helper status*/
462 nbr->gr_helper_info.gr_helper_status = OSPF6_GR_NOT_HELPER;
463 nbr->gr_helper_info.helper_exit_reason = reason;
464 nbr->gr_helper_info.actual_grace_period = 0;
465 nbr->gr_helper_info.recvd_grace_period = 0;
466 nbr->gr_helper_info.gr_restart_reason = 0;
467 ospf6->ospf6_helper_cfg.last_exit_reason = reason;
468
469 /* If the exit not triggered due to grace timer
470 * expiry, stop the grace timer.
471 */
472 if (reason != OSPF6_GR_HELPER_GRACE_TIMEOUT)
473 EVENT_OFF(nbr->gr_helper_info.t_grace_timer);
474
475 if (ospf6->ospf6_helper_cfg.active_restarter_cnt <= 0) {
476 zlog_err(
477 "OSPF6 GR-Helper: Number of active Restarters should be greater than zero.");
478 return;
479 }
480 /* Decrement active restarter count */
481 ospf6->ospf6_helper_cfg.active_restarter_cnt--;
482
483 /* check exit triggered due to successful completion
484 * of graceful restart.
485 */
486 if (reason != OSPF6_GR_HELPER_COMPLETED) {
487 if (IS_DEBUG_OSPF6_GR)
488 zlog_debug("%s, Unsuccessful GR exit. RESTARTER : %pI6",
489 __func__, &nbr->linklocal_addr);
490 }
491
492 /*Recalculate the DR for the network segment */
493 dr_election(oi);
494
495 /* Originate a router LSA */
496 OSPF6_ROUTER_LSA_SCHEDULE(nbr->ospf6_if->area);
497
498 /* Originate network lsa if it is an DR in the LAN */
499 if (nbr->ospf6_if->state == OSPF6_INTERFACE_DR)
500 OSPF6_NETWORK_LSA_SCHEDULE(nbr->ospf6_if);
501 }
502
503 /*
504 * Process max age Grace LSA.
505 * It is a indication for successful completion of GR.
506 * If router acting as HELPER, It exits from helper role.
507 *
508 * ospf6
509 * Ospf6 pointer.
510 *
511 * lsa
512 * Grace LSA received from RESTARTER.
513 *
514 * nbr
515 * ospf6 neighbour which request the router to act as
516 * HELPER.
517 *
518 * Returns:
519 * Nothing.
520 */
521 void ospf6_process_maxage_grace_lsa(struct ospf6 *ospf6, struct ospf6_lsa *lsa,
522 struct ospf6_neighbor *restarter)
523 {
524 uint8_t restart_reason = 0;
525 uint32_t grace_interval = 0;
526 int ret;
527
528 /* Extract the grace lsa packet fields */
529 ret = ospf6_extract_grace_lsa_fields(lsa, &grace_interval,
530 &restart_reason);
531 if (ret != OSPF6_SUCCESS) {
532 if (IS_DEBUG_OSPF6_GR)
533 zlog_debug("%s, Wrong Grace LSA packet.", __func__);
534 return;
535 }
536
537 if (IS_DEBUG_OSPF6_GR)
538 zlog_debug("%s, GraceLSA received for neighbour %pI4.",
539 __func__, &restarter->router_id);
540
541 ospf6_gr_helper_exit(restarter, OSPF6_GR_HELPER_COMPLETED);
542 }
543
544 /*
545 * Actions to be taken when topo change detected
546 * HELPER will be exited upon a topo change.
547 *
548 * ospf6
549 * ospf6 pointer
550 * lsa
551 * topo change occurred due to this lsa(type (1-5 and 7)
552 *
553 * Returns:
554 * Nothing
555 */
556 void ospf6_helper_handle_topo_chg(struct ospf6 *ospf6, struct ospf6_lsa *lsa)
557 {
558 struct listnode *i, *j, *k;
559 struct ospf6_neighbor *nbr = NULL;
560 struct ospf6_area *oa = NULL;
561 struct ospf6_interface *oi = NULL;
562
563 if (!ospf6->ospf6_helper_cfg.active_restarter_cnt)
564 return;
565
566 /* Topo change not required to be handled if strict
567 * LSA check is disabled for this router.
568 */
569 if (!ospf6->ospf6_helper_cfg.strict_lsa_check)
570 return;
571
572 if (IS_DEBUG_OSPF6_GR)
573 zlog_debug("%s, Topo change detected due to lsa details : %s",
574 __func__, lsa->name);
575
576 lsa->tobe_acknowledged = OSPF6_TRUE;
577
578 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa))
579 for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) {
580
581 /* Ref rfc3623 section 3.2.3.b and rfc5187
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.
585 */
586 if (IS_AREA_STUB(oi->area)
587 && ((lsa->header->type == OSPF6_LSTYPE_AS_EXTERNAL)
588 || (lsa->header->type == OSPF6_LSTYPE_TYPE_7)
589 || (lsa->header->type
590 == OSPF6_LSTYPE_INTER_ROUTER))) {
591 continue;
592 }
593
594 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, k, nbr)) {
595
596 ospf6_gr_helper_exit(nbr,
597 OSPF6_GR_HELPER_TOPO_CHG);
598 }
599 }
600 }
601
602 /* Configuration handlers */
603 /*
604 * Disable/Enable HELPER support on router level.
605 *
606 * ospf6
607 * Ospf6 pointer.
608 *
609 * status
610 * TRUE/FALSE
611 *
612 * Returns:
613 * Nothing.
614 */
615 static void ospf6_gr_helper_support_set(struct ospf6 *ospf6, bool support)
616 {
617 struct ospf6_interface *oi;
618 struct advRtr lookup;
619 struct listnode *i, *j, *k;
620 struct ospf6_neighbor *nbr = NULL;
621 struct ospf6_area *oa = NULL;
622
623 if (ospf6->ospf6_helper_cfg.is_helper_supported == support)
624 return;
625
626 ospf6->ospf6_helper_cfg.is_helper_supported = support;
627
628 /* If helper support disabled, cease HELPER role for all
629 * supporting neighbors.
630 */
631 if (support == OSPF6_FALSE) {
632 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa))
633 for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) {
634
635 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, k,
636 nbr)) {
637
638 lookup.advRtrAddr = nbr->router_id;
639 /* check if helper support enabled for
640 * the corresponding routerid.
641 * If enabled,
642 * dont exit from helper role.
643 */
644 if (hash_lookup(
645 ospf6->ospf6_helper_cfg
646 .enable_rtr_list,
647 &lookup))
648 continue;
649
650 ospf6_gr_helper_exit(
651 nbr, OSPF6_GR_HELPER_TOPO_CHG);
652 }
653 }
654 }
655 }
656
657 /*
658 * Api to enable/disable strict lsa check on the HELPER.
659 *
660 * ospf6
661 * Ospf6 pointer.
662 *
663 * enabled
664 * True - disable the lsa check.
665 * False - enable the strict lsa check.
666 *
667 * Returns:
668 * Nothing.
669 */
670 static void ospf6_gr_helper_lsacheck_set(struct ospf6 *ospf6, bool enabled)
671 {
672 if (ospf6->ospf6_helper_cfg.strict_lsa_check == enabled)
673 return;
674
675 ospf6->ospf6_helper_cfg.strict_lsa_check = enabled;
676 }
677
678 /*
679 * Api to set the supported restart reason.
680 *
681 * ospf6
682 * Ospf6 pointer.
683 *
684 * only_planned
685 * True: support only planned restart.
686 * False: support for planned/unplanned restarts.
687 *
688 * Returns:
689 * Nothing.
690 */
691
692 static void
693 ospf6_gr_helper_set_supported_onlyPlanned_restart(struct ospf6 *ospf6,
694 bool only_planned)
695 {
696 ospf6->ospf6_helper_cfg.only_planned_restart = only_planned;
697 }
698
699 /*
700 * Api to set the supported grace interval in this router.
701 *
702 * ospf6
703 * Ospf6 pointer.
704 *
705 * interval
706 * The supported grace interval..
707 *
708 * Returns:
709 * Nothing.
710 */
711 static void ospf6_gr_helper_supported_gracetime_set(struct ospf6 *ospf6,
712 uint32_t interval)
713 {
714 ospf6->ospf6_helper_cfg.supported_grace_time = interval;
715 }
716
717 /* API to walk and print all the Helper supported router ids */
718 static int ospf6_print_vty_helper_dis_rtr_walkcb(struct hash_bucket *bucket,
719 void *arg)
720 {
721 struct advRtr *rtr = bucket->data;
722 struct vty *vty = (struct vty *)arg;
723 static unsigned int count;
724
725 vty_out(vty, "%-6pI4,", &rtr->advRtrAddr);
726 count++;
727
728 if (count % 5 == 0)
729 vty_out(vty, "\n");
730
731 return HASHWALK_CONTINUE;
732 }
733
734 /* API to walk and print all the Helper supported router ids.*/
735 static int ospf6_print_json_helper_dis_rtr_walkcb(struct hash_bucket *bucket,
736 void *arg)
737 {
738 struct advRtr *rtr = bucket->data;
739 struct json_object *json_rid_array = (struct json_object *)arg;
740 struct json_object *json_rid;
741 char router_id[16];
742
743 inet_ntop(AF_INET, &rtr->advRtrAddr, router_id, sizeof(router_id));
744
745 json_rid = json_object_new_object();
746
747 json_object_string_add(json_rid, "routerId", router_id);
748 json_object_array_add(json_rid_array, json_rid);
749
750 return HASHWALK_CONTINUE;
751 }
752
753 /*
754 * Enable/Disable HELPER support on a specified advertisement
755 * router.
756 *
757 * ospf6
758 * Ospf6 pointer.
759 *
760 * advRtr
761 * HELPER support for given Advertisement Router.
762 *
763 * support
764 * True - Enable Helper Support.
765 * False - Disable Helper Support.
766 *
767 * Returns:
768 * Nothing.
769 */
770 static void ospf6_gr_helper_support_set_per_routerid(struct ospf6 *ospf6,
771 struct in_addr router_id,
772 bool support)
773 {
774 struct advRtr temp;
775 struct advRtr *rtr;
776 struct listnode *i, *j, *k;
777 struct ospf6_interface *oi;
778 struct ospf6_neighbor *nbr;
779 struct ospf6_area *oa;
780
781 temp.advRtrAddr = router_id.s_addr;
782
783 if (support == OSPF6_FALSE) {
784 /*Delete the routerid from the enable router hash table */
785 rtr = hash_lookup(ospf6->ospf6_helper_cfg.enable_rtr_list,
786 &temp);
787
788 if (rtr) {
789 hash_release(ospf6->ospf6_helper_cfg.enable_rtr_list,
790 rtr);
791 ospf6_disable_rtr_hash_free(rtr);
792 }
793
794 /* If helper support is enabled globally
795 * no action is required.
796 */
797 if (ospf6->ospf6_helper_cfg.is_helper_supported)
798 return;
799
800 /* Cease the HELPER role fore neighbours from the
801 * specified advertisement router.
802 */
803 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa))
804 for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) {
805
806 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, k,
807 nbr)) {
808
809 if (nbr->router_id != router_id.s_addr)
810 continue;
811
812 if (OSPF6_GR_IS_ACTIVE_HELPER(nbr))
813 ospf6_gr_helper_exit(
814 nbr,
815 OSPF6_GR_HELPER_TOPO_CHG);
816 }
817 }
818
819 } else {
820 /* Add the routerid to the enable router hash table */
821 (void)hash_get(ospf6->ospf6_helper_cfg.enable_rtr_list, &temp,
822 ospf6_enable_rtr_hash_alloc);
823 }
824 }
825
826 static void show_ospfv6_gr_helper_per_nbr(struct vty *vty, json_object *json,
827 bool uj, struct ospf6_neighbor *nbr)
828 {
829 if (!uj) {
830 vty_out(vty, " Routerid : %pI4\n", &nbr->router_id);
831 vty_out(vty, " Received Grace period : %d(in seconds).\n",
832 nbr->gr_helper_info.recvd_grace_period);
833 vty_out(vty, " Actual Grace period : %d(in seconds)\n",
834 nbr->gr_helper_info.actual_grace_period);
835 vty_out(vty, " Remaining GraceTime:%ld(in seconds).\n",
836 event_timer_remain_second(
837 nbr->gr_helper_info.t_grace_timer));
838 vty_out(vty, " Graceful Restart reason: %s.\n\n",
839 ospf6_restart_reason_desc[nbr->gr_helper_info
840 .gr_restart_reason]);
841 } else {
842 char nbrid[16];
843 json_object *json_neigh = NULL;
844
845 inet_ntop(AF_INET, &nbr->router_id, nbrid, sizeof(nbrid));
846 json_neigh = json_object_new_object();
847 json_object_string_add(json_neigh, "routerid", nbrid);
848 json_object_int_add(json_neigh, "recvdGraceInterval",
849 nbr->gr_helper_info.recvd_grace_period);
850 json_object_int_add(json_neigh, "actualGraceInterval",
851 nbr->gr_helper_info.actual_grace_period);
852 json_object_int_add(json_neigh, "remainGracetime",
853 event_timer_remain_second(
854 nbr->gr_helper_info.t_grace_timer));
855 json_object_string_add(json_neigh, "restartReason",
856 ospf6_restart_reason_desc[
857 nbr->gr_helper_info.gr_restart_reason]);
858 json_object_object_add(json, nbr->name, json_neigh);
859 }
860 }
861
862 static void show_ospf6_gr_helper_details(struct vty *vty, struct ospf6 *ospf6,
863 json_object *json, bool uj, bool detail)
864 {
865 struct ospf6_interface *oi;
866
867 /* Show Router ID. */
868 if (uj) {
869 char router_id[16];
870
871 inet_ntop(AF_INET, &ospf6->router_id, router_id,
872 sizeof(router_id));
873 json_object_string_add(json, "routerId", router_id);
874 } else
875 vty_out(vty,
876 " OSPFv3 Routing Process (0) with Router-ID %pI4\n",
877 &ospf6->router_id);
878
879 if (!uj) {
880
881 if (ospf6->ospf6_helper_cfg.is_helper_supported)
882 vty_out(vty,
883 " Graceful restart helper support enabled.\n");
884 else
885 vty_out(vty,
886 " Graceful restart helper support disabled.\n");
887
888 if (ospf6->ospf6_helper_cfg.strict_lsa_check)
889 vty_out(vty, " Strict LSA check is enabled.\n");
890 else
891 vty_out(vty, " Strict LSA check is disabled.\n");
892
893 if (ospf6->ospf6_helper_cfg.only_planned_restart)
894 vty_out(vty,
895 " Helper supported for planned restarts only.\n");
896 else
897 vty_out(vty,
898 " Helper supported for Planned and Unplanned Restarts.\n");
899
900 vty_out(vty,
901 " Supported Graceful restart interval: %d(in seconds).\n",
902 ospf6->ospf6_helper_cfg.supported_grace_time);
903
904 if (OSPF6_HELPER_ENABLE_RTR_COUNT(ospf)) {
905 vty_out(vty, " Enable Router list:\n");
906 vty_out(vty, " ");
907 hash_walk(ospf6->ospf6_helper_cfg.enable_rtr_list,
908 ospf6_print_vty_helper_dis_rtr_walkcb, vty);
909 vty_out(vty, "\n\n");
910 }
911
912 if (ospf6->ospf6_helper_cfg.last_exit_reason
913 != OSPF6_GR_HELPER_EXIT_NONE) {
914 vty_out(vty, " Last Helper exit Reason :%s\n",
915 ospf6_exit_reason_desc
916 [ospf6->ospf6_helper_cfg
917 .last_exit_reason]);
918
919 if (ospf6->ospf6_helper_cfg.active_restarter_cnt)
920 vty_out(vty,
921 " Number of Active neighbours in graceful restart: %d\n",
922 ospf6->ospf6_helper_cfg
923 .active_restarter_cnt);
924 else
925 vty_out(vty, "\n");
926 }
927
928
929 } else {
930 json_object_string_add(
931 json, "helperSupport",
932 (ospf6->ospf6_helper_cfg.is_helper_supported)
933 ? "Enabled"
934 : "Disabled");
935 json_object_string_add(
936 json, "strictLsaCheck",
937 (ospf6->ospf6_helper_cfg.strict_lsa_check)
938 ? "Enabled"
939 : "Disabled");
940
941 #if CONFDATE > 20240401
942 CPP_NOTICE("Remove deprecated json key: restartSupoort")
943 #endif
944 json_object_string_add(
945 json, "restartSupoort",
946 (ospf6->ospf6_helper_cfg.only_planned_restart)
947 ? "Planned Restart only"
948 : "Planned and Unplanned Restarts");
949
950 json_object_string_add(
951 json, "restartSupport",
952 (ospf6->ospf6_helper_cfg.only_planned_restart)
953 ? "Planned Restart only"
954 : "Planned and Unplanned Restarts");
955
956 json_object_int_add(
957 json, "supportedGracePeriod",
958 ospf6->ospf6_helper_cfg.supported_grace_time);
959
960 if (ospf6->ospf6_helper_cfg.last_exit_reason !=
961 OSPF6_GR_HELPER_EXIT_NONE)
962 json_object_string_add(
963 json, "lastExitReason",
964 ospf6_exit_reason_desc
965 [ospf6->ospf6_helper_cfg
966 .last_exit_reason]);
967
968 if (ospf6->ospf6_helper_cfg.active_restarter_cnt)
969 json_object_int_add(
970 json, "activeRestarterCnt",
971 ospf6->ospf6_helper_cfg.active_restarter_cnt);
972
973 if (OSPF6_HELPER_ENABLE_RTR_COUNT(ospf6)) {
974 struct json_object *json_rid_array =
975 json_object_new_array();
976
977 json_object_object_add(json, "enabledRouterIds",
978 json_rid_array);
979
980 hash_walk(ospf6->ospf6_helper_cfg.enable_rtr_list,
981 ospf6_print_json_helper_dis_rtr_walkcb,
982 json_rid_array);
983 }
984 }
985
986 if (detail) {
987 int cnt = 1;
988 struct listnode *i, *j, *k;
989 struct ospf6_area *oa;
990 json_object *json_neighbors = NULL;
991
992 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa))
993 for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) {
994 struct ospf6_neighbor *nbr;
995
996 if (uj) {
997 json_object_object_get_ex(
998 json, "neighbors",
999 &json_neighbors);
1000 if (!json_neighbors) {
1001 json_neighbors =
1002 json_object_new_object();
1003 json_object_object_add(
1004 json, "neighbors",
1005 json_neighbors);
1006 }
1007 }
1008
1009 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, k,
1010 nbr)) {
1011
1012 if (!OSPF6_GR_IS_ACTIVE_HELPER(nbr))
1013 continue;
1014
1015 if (!uj)
1016 vty_out(vty,
1017 " Neighbour %d :\n",
1018 cnt++);
1019
1020 show_ospfv6_gr_helper_per_nbr(
1021 vty, json_neighbors, uj, nbr);
1022
1023 }
1024 }
1025 }
1026 }
1027
1028 /* Graceful Restart HELPER config Commands */
1029 DEFPY(ospf6_gr_helper_enable,
1030 ospf6_gr_helper_enable_cmd,
1031 "graceful-restart helper enable [A.B.C.D$rtr_id]",
1032 "ospf6 graceful restart\n"
1033 "ospf6 GR Helper\n"
1034 "Enable Helper support\n"
1035 "Advertisement Router-ID\n")
1036 {
1037 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1038
1039 if (rtr_id_str != NULL) {
1040
1041 ospf6_gr_helper_support_set_per_routerid(ospf6, rtr_id,
1042 OSPF6_TRUE);
1043
1044 return CMD_SUCCESS;
1045 }
1046
1047 ospf6_gr_helper_support_set(ospf6, OSPF6_TRUE);
1048
1049 return CMD_SUCCESS;
1050 }
1051
1052 DEFPY(ospf6_gr_helper_disable,
1053 ospf6_gr_helper_disable_cmd,
1054 "no graceful-restart helper enable [A.B.C.D$rtr_id]",
1055 NO_STR
1056 "ospf6 graceful restart\n"
1057 "ospf6 GR Helper\n"
1058 "Enable Helper support\n"
1059 "Advertisement Router-ID\n")
1060 {
1061 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1062
1063 if (rtr_id_str != NULL) {
1064
1065 ospf6_gr_helper_support_set_per_routerid(ospf6, rtr_id,
1066 OSPF6_FALSE);
1067
1068 return CMD_SUCCESS;
1069 }
1070
1071 ospf6_gr_helper_support_set(ospf6, OSPF6_FALSE);
1072
1073 return CMD_SUCCESS;
1074 }
1075
1076 DEFPY(ospf6_gr_helper_disable_lsacheck,
1077 ospf6_gr_helper_disable_lsacheck_cmd,
1078 "graceful-restart helper lsa-check-disable",
1079 "ospf6 graceful restart\n"
1080 "ospf6 GR Helper\n"
1081 "disable strict LSA check\n")
1082 {
1083 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1084
1085 ospf6_gr_helper_lsacheck_set(ospf6, OSPF6_FALSE);
1086 return CMD_SUCCESS;
1087 }
1088
1089 DEFPY(no_ospf6_gr_helper_disable_lsacheck,
1090 no_ospf6_gr_helper_disable_lsacheck_cmd,
1091 "no graceful-restart helper lsa-check-disable",
1092 NO_STR
1093 "ospf6 graceful restart\n"
1094 "ospf6 GR Helper\n"
1095 "diasble strict LSA check\n")
1096 {
1097 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1098
1099 ospf6_gr_helper_lsacheck_set(ospf6, OSPF6_TRUE);
1100 return CMD_SUCCESS;
1101 }
1102
1103 DEFPY(ospf6_gr_helper_planned_only,
1104 ospf6_gr_helper_planned_only_cmd,
1105 "graceful-restart helper planned-only",
1106 "ospf6 graceful restart\n"
1107 "ospf6 GR Helper\n"
1108 "supported only planned restart\n")
1109 {
1110 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1111
1112 ospf6_gr_helper_set_supported_onlyPlanned_restart(ospf6, OSPF6_TRUE);
1113
1114 return CMD_SUCCESS;
1115 }
1116
1117 DEFPY(no_ospf6_gr_helper_planned_only, no_ospf6_gr_helper_planned_only_cmd,
1118 "no graceful-restart helper planned-only",
1119 NO_STR
1120 "ospf6 graceful restart\n"
1121 "ospf6 GR Helper\n"
1122 "supported only for planned restart\n")
1123 {
1124 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1125
1126 ospf6_gr_helper_set_supported_onlyPlanned_restart(ospf6, OSPF6_FALSE);
1127
1128 return CMD_SUCCESS;
1129 }
1130
1131 DEFPY(ospf6_gr_helper_supported_grace_time,
1132 ospf6_gr_helper_supported_grace_time_cmd,
1133 "graceful-restart helper supported-grace-time (10-1800)$interval",
1134 "ospf6 graceful restart\n"
1135 "ospf6 GR Helper\n"
1136 "supported grace timer\n"
1137 "grace interval(in seconds)\n")
1138 {
1139 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1140
1141 ospf6_gr_helper_supported_gracetime_set(ospf6, interval);
1142 return CMD_SUCCESS;
1143 }
1144
1145 DEFPY(no_ospf6_gr_helper_supported_grace_time,
1146 no_ospf6_gr_helper_supported_grace_time_cmd,
1147 "no graceful-restart helper supported-grace-time (10-1800)$interval",
1148 NO_STR
1149 "ospf6 graceful restart\n"
1150 "ospf6 GR Helper\n"
1151 "supported grace timer\n"
1152 "grace interval(in seconds)\n")
1153 {
1154 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1155
1156 ospf6_gr_helper_supported_gracetime_set(ospf6,
1157 OSPF6_MAX_GRACE_INTERVAL);
1158 return CMD_SUCCESS;
1159 }
1160
1161 /* Show commands */
1162 DEFPY(show_ipv6_ospf6_gr_helper,
1163 show_ipv6_ospf6_gr_helper_cmd,
1164 "show ipv6 ospf6 graceful-restart helper [detail] [json]",
1165 SHOW_STR
1166 "Ipv6 Information\n"
1167 "OSPF6 information\n"
1168 "ospf6 graceful restart\n"
1169 "helper details in the router\n"
1170 "detailed information\n" JSON_STR)
1171 {
1172 int idx = 0;
1173 bool uj = use_json(argc, argv);
1174 struct ospf6 *ospf6 = NULL;
1175 json_object *json = NULL;
1176 bool detail = false;
1177
1178 ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
1179 if (ospf6 == NULL) {
1180 vty_out(vty, "OSPFv3 is not configured\n");
1181 return CMD_SUCCESS;
1182 }
1183
1184 if (argv_find(argv, argc, "detail", &idx))
1185 detail = true;
1186
1187 if (uj)
1188 json = json_object_new_object();
1189
1190 show_ospf6_gr_helper_details(vty, ospf6, json, uj, detail);
1191
1192 if (uj)
1193 vty_json(vty, json);
1194
1195 return CMD_SUCCESS;
1196 }
1197
1198 /* Debug commands */
1199 DEFPY(debug_ospf6_gr, debug_ospf6_gr_cmd,
1200 "[no$no] debug ospf6 graceful-restart",
1201 NO_STR DEBUG_STR OSPF6_STR "Graceful restart\n")
1202 {
1203 if (!no)
1204 OSPF6_DEBUG_GR_ON();
1205 else
1206 OSPF6_DEBUG_GR_OFF();
1207
1208 return CMD_SUCCESS;
1209 }
1210
1211 /*
1212 * Api to display the grace LSA information.
1213 *
1214 * vty
1215 * vty pointer.
1216 * lsa
1217 * Grace LSA.
1218 * json
1219 * json object
1220 *
1221 * Returns:
1222 * Nothing.
1223 */
1224 static int ospf6_grace_lsa_show_info(struct vty *vty, struct ospf6_lsa *lsa,
1225 json_object *json, bool use_json)
1226 {
1227 struct ospf6_lsa_header *lsah = NULL;
1228 struct tlv_header *tlvh = NULL;
1229 struct grace_tlv_graceperiod *gracePeriod;
1230 struct grace_tlv_restart_reason *grReason;
1231 uint16_t length = 0;
1232 int sum = 0;
1233
1234 lsah = (struct ospf6_lsa_header *)lsa->header;
1235 if (ntohs(lsah->length) <= OSPF6_LSA_HEADER_SIZE) {
1236 if (IS_DEBUG_OSPF6_GR)
1237 zlog_debug("%s: undersized (%u B) lsa", __func__,
1238 ntohs(lsah->length));
1239 return OSPF6_FAILURE;
1240 }
1241
1242 length = ntohs(lsah->length) - OSPF6_LSA_HEADER_SIZE;
1243
1244 if (vty) {
1245 if (!use_json)
1246 vty_out(vty, "TLV info:\n");
1247 } else {
1248 zlog_debug(" TLV info:");
1249 }
1250
1251 for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh;
1252 tlvh = TLV_HDR_NEXT(tlvh)) {
1253
1254 /* Check TLV len */
1255 if (sum + TLV_SIZE(tlvh) > length) {
1256 if (vty)
1257 vty_out(vty, "%% Invalid TLV length: %d\n",
1258 TLV_SIZE(tlvh));
1259 else if (IS_DEBUG_OSPF6_GR)
1260 zlog_debug("%% Invalid TLV length: %d",
1261 TLV_SIZE(tlvh));
1262 return OSPF6_FAILURE;
1263 }
1264
1265 switch (ntohs(tlvh->type)) {
1266 case GRACE_PERIOD_TYPE:
1267 gracePeriod = (struct grace_tlv_graceperiod *)tlvh;
1268 sum += TLV_SIZE(tlvh);
1269
1270 if (vty) {
1271 if (use_json)
1272 json_object_int_add(
1273 json, "gracePeriod",
1274 ntohl(gracePeriod->interval));
1275 else
1276 vty_out(vty, " Grace period:%d\n",
1277 ntohl(gracePeriod->interval));
1278 } else {
1279 zlog_debug(" Grace period:%d",
1280 ntohl(gracePeriod->interval));
1281 }
1282 break;
1283 case RESTART_REASON_TYPE:
1284 grReason = (struct grace_tlv_restart_reason *)tlvh;
1285 sum += TLV_SIZE(tlvh);
1286 if (vty) {
1287 if (use_json)
1288 json_object_string_add(
1289 json, "restartReason",
1290 ospf6_restart_reason_desc
1291 [grReason->reason]);
1292 else
1293 vty_out(vty, " Restart reason:%s\n",
1294 ospf6_restart_reason_desc
1295 [grReason->reason]);
1296 } else {
1297 zlog_debug(" Restart reason:%s",
1298 ospf6_restart_reason_desc
1299 [grReason->reason]);
1300 }
1301 break;
1302 default:
1303 break;
1304 }
1305 }
1306
1307 return 0;
1308 }
1309
1310 void ospf6_gr_helper_config_init(void)
1311 {
1312
1313 ospf6_install_lsa_handler(&grace_lsa_handler);
1314
1315 install_element(OSPF6_NODE, &ospf6_gr_helper_enable_cmd);
1316 install_element(OSPF6_NODE, &ospf6_gr_helper_disable_cmd);
1317 install_element(OSPF6_NODE, &ospf6_gr_helper_disable_lsacheck_cmd);
1318 install_element(OSPF6_NODE, &no_ospf6_gr_helper_disable_lsacheck_cmd);
1319 install_element(OSPF6_NODE, &ospf6_gr_helper_planned_only_cmd);
1320 install_element(OSPF6_NODE, &no_ospf6_gr_helper_planned_only_cmd);
1321 install_element(OSPF6_NODE, &ospf6_gr_helper_supported_grace_time_cmd);
1322 install_element(OSPF6_NODE,
1323 &no_ospf6_gr_helper_supported_grace_time_cmd);
1324
1325 install_element(VIEW_NODE, &show_ipv6_ospf6_gr_helper_cmd);
1326
1327 install_element(CONFIG_NODE, &debug_ospf6_gr_cmd);
1328 install_element(ENABLE_NODE, &debug_ospf6_gr_cmd);
1329 }
1330
1331
1332 /*
1333 * Initialize GR helper config data structure.
1334 *
1335 * ospf6
1336 * ospf6 pointer
1337 *
1338 * Returns:
1339 * Nothing
1340 */
1341 void ospf6_gr_helper_init(struct ospf6 *ospf6)
1342 {
1343 if (IS_DEBUG_OSPF6_GR)
1344 zlog_debug("%s, GR Helper init.", __func__);
1345
1346 ospf6->ospf6_helper_cfg.is_helper_supported = OSPF6_FALSE;
1347 ospf6->ospf6_helper_cfg.strict_lsa_check = OSPF6_TRUE;
1348 ospf6->ospf6_helper_cfg.only_planned_restart = OSPF6_FALSE;
1349 ospf6->ospf6_helper_cfg.supported_grace_time = OSPF6_MAX_GRACE_INTERVAL;
1350 ospf6->ospf6_helper_cfg.last_exit_reason = OSPF6_GR_HELPER_EXIT_NONE;
1351 ospf6->ospf6_helper_cfg.active_restarter_cnt = 0;
1352
1353 ospf6->ospf6_helper_cfg.enable_rtr_list = hash_create(
1354 ospf6_enable_rtr_hash_key, ospf6_enable_rtr_hash_cmp,
1355 "Ospf6 enable router hash");
1356 }
1357
1358 /*
1359 * De-initialize GR helper config data structure.
1360 *
1361 * ospf6
1362 * ospf6 pointer
1363 *
1364 * Returns:
1365 * Nothing
1366 */
1367 void ospf6_gr_helper_deinit(struct ospf6 *ospf6)
1368 {
1369
1370 if (IS_DEBUG_OSPF6_GR)
1371 zlog_debug("%s, GR helper deinit.", __func__);
1372
1373 ospf6_enable_rtr_hash_destroy(ospf6);
1374 }
1375
1376 static int ospf6_cfg_write_helper_enable_rtr_walkcb(struct hash_bucket *backet,
1377 void *arg)
1378 {
1379 struct advRtr *rtr = backet->data;
1380 struct vty *vty = (struct vty *)arg;
1381
1382 vty_out(vty, " graceful-restart helper enable %pI4\n", &rtr->advRtrAddr);
1383 return HASHWALK_CONTINUE;
1384 }
1385
1386 int config_write_ospf6_gr_helper(struct vty *vty, struct ospf6 *ospf6)
1387 {
1388 if (ospf6->ospf6_helper_cfg.is_helper_supported)
1389 vty_out(vty, " graceful-restart helper enable\n");
1390
1391 if (!ospf6->ospf6_helper_cfg.strict_lsa_check)
1392 vty_out(vty, " graceful-restart helper lsa-check-disable\n");
1393
1394 if (ospf6->ospf6_helper_cfg.only_planned_restart)
1395 vty_out(vty, " graceful-restart helper planned-only\n");
1396
1397 if (ospf6->ospf6_helper_cfg.supported_grace_time
1398 != OSPF6_MAX_GRACE_INTERVAL)
1399 vty_out(vty,
1400 " graceful-restart helper supported-grace-time %d\n",
1401 ospf6->ospf6_helper_cfg.supported_grace_time);
1402
1403 if (OSPF6_HELPER_ENABLE_RTR_COUNT(ospf6)) {
1404 hash_walk(ospf6->ospf6_helper_cfg.enable_rtr_list,
1405 ospf6_cfg_write_helper_enable_rtr_walkcb, vty);
1406 }
1407
1408 return 0;
1409 }
1410
1411 int config_write_ospf6_debug_gr_helper(struct vty *vty)
1412 {
1413 if (IS_DEBUG_OSPF6_GR)
1414 vty_out(vty, "debug ospf6 graceful-restart\n");
1415 return 0;
1416 }