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