]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_gr_helper.c
Merge pull request #13345 from donaldsharp/pim_after_dark
[mirror_frr.git] / ospf6d / ospf6_gr_helper.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
59790f52 2/*
0d1753a7 3 * OSPF6 Graceful Restart helper functions.
59790f52 4 *
5 * Copyright (C) 2021-22 Vmware, Inc.
6 * Rajesh Kumar Girada
59790f52 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"
0d1753a7 35#include "ospf6_gr.h"
59790f52 36#include "lib/json.h"
59790f52 37#include "ospf6d/ospf6_gr_helper_clippy.c"
59790f52 38
39DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_GR_HELPER, "OSPF6 Graceful restart helper");
40
0d1753a7 41unsigned char conf_debug_ospf6_gr;
06943666 42
0fc3e113 43static int ospf6_grace_lsa_show_info(struct vty *vty, struct ospf6_lsa *lsa,
44 json_object *json, bool use_json);
45
46struct 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
59790f52 54const char *ospf6_exit_reason_desc[] = {
0fc3e113 55 "Unknown reason",
56 "Helper in progress",
57 "Topology Change",
58 "Grace timer expiry",
59 "Successful graceful restart",
59790f52 60};
61
62const char *ospf6_restart_reason_desc[] = {
63 "Unknown restart",
64 "Software restart",
65 "Software reload/upgrade",
66 "Switch to redundant control processor",
67};
68
69const 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
78static 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
85static 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
93static 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
103static void ospf6_disable_rtr_hash_free(void *rtr)
104{
105 XFREE(MTYPE_OSPF6_GR_HELPER, rtr);
106}
107
108static void ospf6_enable_rtr_hash_destroy(struct ospf6 *ospf6)
109{
110 if (ospf6->ospf6_helper_cfg.enable_rtr_list == NULL)
111 return;
112
d8bc11a5
DS
113 hash_clean_and_free(&ospf6->ospf6_helper_cfg.enable_rtr_list,
114 ospf6_disable_rtr_hash_free);
59790f52 115}
116
0d1753a7 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 */
127static 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;
905b12b2 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 }
0d1753a7 144
145 length = ntohs(lsah->length) - OSPF6_LSA_HEADER_SIZE;
146
6d1a5a1c 147 for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh;
0d1753a7 148 tlvh = TLV_HDR_NEXT(tlvh)) {
6d1a5a1c 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
0d1753a7 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:
0fc3e113 179 if (IS_DEBUG_OSPF6_GR)
180 zlog_debug("%s, Ignoring unknown TLV type:%d",
181 __func__, ntohs(tlvh->type));
0d1753a7 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 */
e6685141 198static void ospf6_handle_grace_timer_expiry(struct event *thread)
0d1753a7 199{
e16d030c 200 struct ospf6_neighbor *nbr = EVENT_ARG(thread);
0d1753a7 201
9a06f23d 202 ospf6_gr_helper_exit(nbr, OSPF6_GR_HELPER_GRACE_TIMEOUT);
0d1753a7 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 */
216static 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
37692712 230 if (lsa_in_db && lsa_in_db->tobe_acknowledged) {
231 ospf6_lsa_unlock(lsa);
232 if (lsanext)
233 ospf6_lsa_unlock(lsanext);
234
0d1753a7 235 return OSPF6_TRUE;
37692712 236 }
0d1753a7 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 */
261int 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) {
0fc3e113 274 if (IS_DEBUG_OSPF6_GR)
275 zlog_debug("%s, Wrong Grace LSA packet.", __func__);
0d1753a7 276 return OSPF6_GR_NOT_HELPER;
277 }
278
0fc3e113 279 if (IS_DEBUG_OSPF6_GR)
0d1753a7 280 zlog_debug(
ba427e63
DA
281 "%s, Grace LSA received from %s(%pI4), grace interval:%u, restart reason:%s",
282 __func__, restarter->name, &restarter->router_id,
283 grace_interval,
0d1753a7 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)) {
0fc3e113 295 if (IS_DEBUG_OSPF6_GR)
0d1753a7 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)) {
0fc3e113 309 if (IS_DEBUG_OSPF6_GR)
0d1753a7 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)) {
0fc3e113 323 if (IS_DEBUG_OSPF6_GR)
0d1753a7 324 zlog_debug(
abc14fa0 325 "%s, Router supports only planned restarts but received the GRACE LSA due to an unplanned restart",
0d1753a7 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)) {
0fc3e113 338 if (IS_DEBUG_OSPF6_GR)
0d1753a7 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
0fc3e113 347 /* LSA age must be less than the grace period */
0d1753a7 348 if (ntohs(lsa->header->age) >= grace_interval) {
0fc3e113 349 if (IS_DEBUG_OSPF6_GR)
0d1753a7 350 zlog_debug(
351 "%s, Grace LSA age(%d) is more than the grace interval(%d)",
0fc3e113 352 __func__, lsa->header->age, grace_interval);
0d1753a7 353 restarter->gr_helper_info.rejected_reason =
354 OSPF6_HELPER_LSA_AGE_MORE;
355 return OSPF6_GR_NOT_HELPER;
356 }
357
71165098
RW
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
0d1753a7 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) {
0fc3e113 375 if (IS_DEBUG_OSPF6_GR)
0d1753a7 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)) {
e16d030c 385 EVENT_OFF(restarter->gr_helper_info.t_grace_timer);
0d1753a7 386
387 if (ospf6->ospf6_helper_cfg.active_restarter_cnt > 0)
388 ospf6->ospf6_helper_cfg.active_restarter_cnt--;
389
0fc3e113 390 if (IS_DEBUG_OSPF6_GR)
0d1753a7 391 zlog_debug(
392 "%s, Router is already acting as a HELPER for this nbr,so restart the grace timer",
393 __func__);
394 } else {
0fc3e113 395 if (IS_DEBUG_OSPF6_GR)
0d1753a7 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
0fc3e113 413 if (IS_DEBUG_OSPF6_GR)
414 zlog_debug("%s, Grace timer started.interval:%u", __func__,
415 actual_grace_interval);
0d1753a7 416
417 /* Start the grace timer */
907a2395
DS
418 event_add_timer(master, ospf6_handle_grace_timer_expiry, restarter,
419 actual_grace_interval,
420 &restarter->gr_helper_info.t_grace_timer);
0d1753a7 421
422 return OSPF6_GR_ACTIVE_HELPER;
423}
424
9a06f23d 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 */
442void 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
0fc3e113 456 if (IS_DEBUG_OSPF6_GR)
9a06f23d 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
0fc3e113 470 * expiry, stop the grace timer.
9a06f23d 471 */
472 if (reason != OSPF6_GR_HELPER_GRACE_TIMEOUT)
e16d030c 473 EVENT_OFF(nbr->gr_helper_info.t_grace_timer);
9a06f23d 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 }
0fc3e113 480 /* Decrement active restarter count */
9a06f23d 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) {
0fc3e113 487 if (IS_DEBUG_OSPF6_GR)
9a06f23d 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/*
0fc3e113 504 * Process max age Grace LSA.
505 * It is a indication for successful completion of GR.
9a06f23d 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
0fc3e113 515 * ospf6 neighbour which request the router to act as
9a06f23d 516 * HELPER.
517 *
518 * Returns:
519 * Nothing.
520 */
521void 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) {
0fc3e113 532 if (IS_DEBUG_OSPF6_GR)
533 zlog_debug("%s, Wrong Grace LSA packet.", __func__);
9a06f23d 534 return;
535 }
536
0fc3e113 537 if (IS_DEBUG_OSPF6_GR)
9a06f23d 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
0fc3e113 551 * topo change occurred due to this lsa(type (1-5 and 7)
9a06f23d 552 *
553 * Returns:
554 * Nothing
555 */
556void 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
0fc3e113 566 /* Topo change not required to be handled if strict
567 * LSA check is disabled for this router.
9a06f23d 568 */
569 if (!ospf6->ospf6_helper_cfg.strict_lsa_check)
570 return;
571
0fc3e113 572 if (IS_DEBUG_OSPF6_GR)
573 zlog_debug("%s, Topo change detected due to lsa details : %s",
574 __func__, lsa->name);
9a06f23d 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
0fc3e113 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 */
615static 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 */
670static 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
692static void
693ospf6_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 */
711static 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 */
718static 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.*/
735static 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 */
770static 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 */
8e3aae66 821 (void)hash_get(ospf6->ospf6_helper_cfg.enable_rtr_list, &temp,
822 ospf6_enable_rtr_hash_alloc);
0fc3e113 823 }
824}
825
826static 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",
4f830a07 836 event_timer_remain_second(
0fc3e113 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",
4f830a07
DS
853 event_timer_remain_second(
854 nbr->gr_helper_info.t_grace_timer));
0fc3e113 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
4d97dde2 862static void show_ospf6_gr_helper_details(struct vty *vty, struct ospf6 *ospf6,
0fc3e113 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");
a63fecfb
MS
940
941#if CONFDATE > 20240401
942 CPP_NOTICE("Remove deprecated json key: restartSupoort")
943#endif
0fc3e113 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
a63fecfb
MS
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
0fc3e113 956 json_object_int_add(
957 json, "supportedGracePeriod",
958 ospf6->ospf6_helper_cfg.supported_grace_time);
959
77a2f8e5 960 if (ospf6->ospf6_helper_cfg.last_exit_reason !=
1ce23106 961 OSPF6_GR_HELPER_EXIT_NONE)
77a2f8e5
DA
962 json_object_string_add(
963 json, "lastExitReason",
964 ospf6_exit_reason_desc
965 [ospf6->ospf6_helper_cfg
966 .last_exit_reason]);
0fc3e113 967
239ccb07 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
0fc3e113 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) {
77a2f8e5
DA
997 json_object_object_get_ex(
998 json, "neighbors",
999 &json_neighbors);
0fc3e113 1000 if (!json_neighbors) {
1001 json_neighbors =
1002 json_object_new_object();
77a2f8e5
DA
1003 json_object_object_add(
1004 json, "neighbors",
1005 json_neighbors);
0fc3e113 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 }
0fc3e113 1026}
1027
1028/* Graceful Restart HELPER config Commands */
1029DEFPY(ospf6_gr_helper_enable,
1030 ospf6_gr_helper_enable_cmd,
6b513b4c 1031 "graceful-restart helper enable [A.B.C.D$rtr_id]",
0fc3e113 1032 "ospf6 graceful restart\n"
6b513b4c 1033 "ospf6 GR Helper\n"
0fc3e113 1034 "Enable Helper support\n"
6b513b4c 1035 "Advertisement Router-ID\n")
0fc3e113 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
1052DEFPY(ospf6_gr_helper_disable,
1053 ospf6_gr_helper_disable_cmd,
6b513b4c 1054 "no graceful-restart helper enable [A.B.C.D$rtr_id]",
0fc3e113 1055 NO_STR
1056 "ospf6 graceful restart\n"
6b513b4c
RW
1057 "ospf6 GR Helper\n"
1058 "Enable Helper support\n"
1059 "Advertisement Router-ID\n")
0fc3e113 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
1076DEFPY(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
1089DEFPY(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
1103DEFPY(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
1117DEFPY(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
1131DEFPY(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
1145DEFPY(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 */
1162DEFPY(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);
390dce12
IR
1179 if (ospf6 == NULL) {
1180 vty_out(vty, "OSPFv3 is not configured\n");
1181 return CMD_SUCCESS;
1182 }
0fc3e113 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
c48349e3 1192 if (uj)
5a6c232b 1193 vty_json(vty, json);
0fc3e113 1194
1195 return CMD_SUCCESS;
1196}
1197
06943666 1198/* Debug commands */
0fc3e113 1199DEFPY(debug_ospf6_gr, debug_ospf6_gr_cmd,
06943666 1200 "[no$no] debug ospf6 graceful-restart",
0fc3e113 1201 NO_STR DEBUG_STR OSPF6_STR "Graceful restart\n")
06943666 1202{
1203 if (!no)
0fc3e113 1204 OSPF6_DEBUG_GR_ON();
06943666 1205 else
0fc3e113 1206 OSPF6_DEBUG_GR_OFF();
06943666 1207
1208 return CMD_SUCCESS;
1209}
1210
0fc3e113 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 */
1224static 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;
905b12b2 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 }
0fc3e113 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
6d1a5a1c 1251 for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh;
0fc3e113 1252 tlvh = TLV_HDR_NEXT(tlvh)) {
6d1a5a1c 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
0fc3e113 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
1310void 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
59790f52 1332/*
0d1753a7 1333 * Initialize GR helper config data structure.
59790f52 1334 *
1335 * ospf6
1336 * ospf6 pointer
1337 *
1338 * Returns:
1339 * Nothing
1340 */
1341void ospf6_gr_helper_init(struct ospf6 *ospf6)
1342{
0fc3e113 1343 if (IS_DEBUG_OSPF6_GR)
0d1753a7 1344 zlog_debug("%s, GR Helper init.", __func__);
06943666 1345
59790f52 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/*
0fc3e113 1359 * De-initialize GR helper config data structure.
59790f52 1360 *
1361 * ospf6
1362 * ospf6 pointer
1363 *
1364 * Returns:
1365 * Nothing
1366 */
1367void ospf6_gr_helper_deinit(struct ospf6 *ospf6)
1368{
06943666 1369
0fc3e113 1370 if (IS_DEBUG_OSPF6_GR)
0d1753a7 1371 zlog_debug("%s, GR helper deinit.", __func__);
06943666 1372
59790f52 1373 ospf6_enable_rtr_hash_destroy(ospf6);
1374}
0fc3e113 1375
1376static 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
6b513b4c 1382 vty_out(vty, " graceful-restart helper enable %pI4\n", &rtr->advRtrAddr);
0fc3e113 1383 return HASHWALK_CONTINUE;
1384}
1385
1386int config_write_ospf6_gr_helper(struct vty *vty, struct ospf6 *ospf6)
1387{
1388 if (ospf6->ospf6_helper_cfg.is_helper_supported)
6b513b4c 1389 vty_out(vty, " graceful-restart helper enable\n");
0fc3e113 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
1411int config_write_ospf6_debug_gr_helper(struct vty *vty)
1412{
1413 if (IS_DEBUG_OSPF6_GR)
3ebc5e4b 1414 vty_out(vty, "debug ospf6 graceful-restart\n");
0fc3e113 1415 return 0;
1416}