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