]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_gr_helper.c
*: Convert thread_timer_remain_XXX to event_timer_remain_XXX
[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{
200 struct ospf6_neighbor *nbr = THREAD_ARG(thread);
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)) {
c905f04c 385 THREAD_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)
473 THREAD_OFF(nbr->gr_helper_info.t_grace_timer);
474
475 if (ospf6->ospf6_helper_cfg.active_restarter_cnt <= 0) {
476 zlog_err(
477 "OSPF6 GR-Helper: Number of active Restarters should be greater than zero.");
478 return;
479 }
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");
940 json_object_string_add(
941 json, "restartSupoort",
942 (ospf6->ospf6_helper_cfg.only_planned_restart)
943 ? "Planned Restart only"
944 : "Planned and Unplanned Restarts");
945
946 json_object_int_add(
947 json, "supportedGracePeriod",
948 ospf6->ospf6_helper_cfg.supported_grace_time);
949
77a2f8e5 950 if (ospf6->ospf6_helper_cfg.last_exit_reason !=
1ce23106 951 OSPF6_GR_HELPER_EXIT_NONE)
77a2f8e5
DA
952 json_object_string_add(
953 json, "lastExitReason",
954 ospf6_exit_reason_desc
955 [ospf6->ospf6_helper_cfg
956 .last_exit_reason]);
0fc3e113 957
239ccb07 958 if (ospf6->ospf6_helper_cfg.active_restarter_cnt)
959 json_object_int_add(
960 json, "activeRestarterCnt",
961 ospf6->ospf6_helper_cfg.active_restarter_cnt);
962
0fc3e113 963 if (OSPF6_HELPER_ENABLE_RTR_COUNT(ospf6)) {
964 struct json_object *json_rid_array =
965 json_object_new_array();
966
967 json_object_object_add(json, "enabledRouterIds",
968 json_rid_array);
969
970 hash_walk(ospf6->ospf6_helper_cfg.enable_rtr_list,
971 ospf6_print_json_helper_dis_rtr_walkcb,
972 json_rid_array);
973 }
974 }
975
976 if (detail) {
977 int cnt = 1;
978 struct listnode *i, *j, *k;
979 struct ospf6_area *oa;
980 json_object *json_neighbors = NULL;
981
982 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa))
983 for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) {
984 struct ospf6_neighbor *nbr;
985
986 if (uj) {
77a2f8e5
DA
987 json_object_object_get_ex(
988 json, "neighbors",
989 &json_neighbors);
0fc3e113 990 if (!json_neighbors) {
991 json_neighbors =
992 json_object_new_object();
77a2f8e5
DA
993 json_object_object_add(
994 json, "neighbors",
995 json_neighbors);
0fc3e113 996 }
997 }
998
999 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, k,
1000 nbr)) {
1001
1002 if (!OSPF6_GR_IS_ACTIVE_HELPER(nbr))
1003 continue;
1004
1005 if (!uj)
1006 vty_out(vty,
1007 " Neighbour %d :\n",
1008 cnt++);
1009
1010 show_ospfv6_gr_helper_per_nbr(
1011 vty, json_neighbors, uj, nbr);
1012
1013 }
1014 }
1015 }
0fc3e113 1016}
1017
1018/* Graceful Restart HELPER config Commands */
1019DEFPY(ospf6_gr_helper_enable,
1020 ospf6_gr_helper_enable_cmd,
6b513b4c 1021 "graceful-restart helper enable [A.B.C.D$rtr_id]",
0fc3e113 1022 "ospf6 graceful restart\n"
6b513b4c 1023 "ospf6 GR Helper\n"
0fc3e113 1024 "Enable Helper support\n"
6b513b4c 1025 "Advertisement Router-ID\n")
0fc3e113 1026{
1027 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1028
1029 if (rtr_id_str != NULL) {
1030
1031 ospf6_gr_helper_support_set_per_routerid(ospf6, rtr_id,
1032 OSPF6_TRUE);
1033
1034 return CMD_SUCCESS;
1035 }
1036
1037 ospf6_gr_helper_support_set(ospf6, OSPF6_TRUE);
1038
1039 return CMD_SUCCESS;
1040}
1041
1042DEFPY(ospf6_gr_helper_disable,
1043 ospf6_gr_helper_disable_cmd,
6b513b4c 1044 "no graceful-restart helper enable [A.B.C.D$rtr_id]",
0fc3e113 1045 NO_STR
1046 "ospf6 graceful restart\n"
6b513b4c
RW
1047 "ospf6 GR Helper\n"
1048 "Enable Helper support\n"
1049 "Advertisement Router-ID\n")
0fc3e113 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_FALSE);
1057
1058 return CMD_SUCCESS;
1059 }
1060
1061 ospf6_gr_helper_support_set(ospf6, OSPF6_FALSE);
1062
1063 return CMD_SUCCESS;
1064}
1065
1066DEFPY(ospf6_gr_helper_disable_lsacheck,
1067 ospf6_gr_helper_disable_lsacheck_cmd,
1068 "graceful-restart helper lsa-check-disable",
1069 "ospf6 graceful restart\n"
1070 "ospf6 GR Helper\n"
1071 "disable strict LSA check\n")
1072{
1073 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1074
1075 ospf6_gr_helper_lsacheck_set(ospf6, OSPF6_FALSE);
1076 return CMD_SUCCESS;
1077}
1078
1079DEFPY(no_ospf6_gr_helper_disable_lsacheck,
1080 no_ospf6_gr_helper_disable_lsacheck_cmd,
1081 "no graceful-restart helper lsa-check-disable",
1082 NO_STR
1083 "ospf6 graceful restart\n"
1084 "ospf6 GR Helper\n"
1085 "diasble strict LSA check\n")
1086{
1087 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1088
1089 ospf6_gr_helper_lsacheck_set(ospf6, OSPF6_TRUE);
1090 return CMD_SUCCESS;
1091}
1092
1093DEFPY(ospf6_gr_helper_planned_only,
1094 ospf6_gr_helper_planned_only_cmd,
1095 "graceful-restart helper planned-only",
1096 "ospf6 graceful restart\n"
1097 "ospf6 GR Helper\n"
1098 "supported only planned restart\n")
1099{
1100 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1101
1102 ospf6_gr_helper_set_supported_onlyPlanned_restart(ospf6, OSPF6_TRUE);
1103
1104 return CMD_SUCCESS;
1105}
1106
1107DEFPY(no_ospf6_gr_helper_planned_only, no_ospf6_gr_helper_planned_only_cmd,
1108 "no graceful-restart helper planned-only",
1109 NO_STR
1110 "ospf6 graceful restart\n"
1111 "ospf6 GR Helper\n"
1112 "supported only for planned restart\n")
1113{
1114 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1115
1116 ospf6_gr_helper_set_supported_onlyPlanned_restart(ospf6, OSPF6_FALSE);
1117
1118 return CMD_SUCCESS;
1119}
1120
1121DEFPY(ospf6_gr_helper_supported_grace_time,
1122 ospf6_gr_helper_supported_grace_time_cmd,
1123 "graceful-restart helper supported-grace-time (10-1800)$interval",
1124 "ospf6 graceful restart\n"
1125 "ospf6 GR Helper\n"
1126 "supported grace timer\n"
1127 "grace interval(in seconds)\n")
1128{
1129 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1130
1131 ospf6_gr_helper_supported_gracetime_set(ospf6, interval);
1132 return CMD_SUCCESS;
1133}
1134
1135DEFPY(no_ospf6_gr_helper_supported_grace_time,
1136 no_ospf6_gr_helper_supported_grace_time_cmd,
1137 "no graceful-restart helper supported-grace-time (10-1800)$interval",
1138 NO_STR
1139 "ospf6 graceful restart\n"
1140 "ospf6 GR Helper\n"
1141 "supported grace timer\n"
1142 "grace interval(in seconds)\n")
1143{
1144 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1145
1146 ospf6_gr_helper_supported_gracetime_set(ospf6,
1147 OSPF6_MAX_GRACE_INTERVAL);
1148 return CMD_SUCCESS;
1149}
1150
1151/* Show commands */
1152DEFPY(show_ipv6_ospf6_gr_helper,
1153 show_ipv6_ospf6_gr_helper_cmd,
1154 "show ipv6 ospf6 graceful-restart helper [detail] [json]",
1155 SHOW_STR
1156 "Ipv6 Information\n"
1157 "OSPF6 information\n"
1158 "ospf6 graceful restart\n"
1159 "helper details in the router\n"
1160 "detailed information\n" JSON_STR)
1161{
1162 int idx = 0;
1163 bool uj = use_json(argc, argv);
1164 struct ospf6 *ospf6 = NULL;
1165 json_object *json = NULL;
1166 bool detail = false;
1167
1168 ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
390dce12
IR
1169 if (ospf6 == NULL) {
1170 vty_out(vty, "OSPFv3 is not configured\n");
1171 return CMD_SUCCESS;
1172 }
0fc3e113 1173
1174 if (argv_find(argv, argc, "detail", &idx))
1175 detail = true;
1176
1177 if (uj)
1178 json = json_object_new_object();
1179
1180 show_ospf6_gr_helper_details(vty, ospf6, json, uj, detail);
1181
c48349e3 1182 if (uj)
5a6c232b 1183 vty_json(vty, json);
0fc3e113 1184
1185 return CMD_SUCCESS;
1186}
1187
06943666 1188/* Debug commands */
0fc3e113 1189DEFPY(debug_ospf6_gr, debug_ospf6_gr_cmd,
06943666 1190 "[no$no] debug ospf6 graceful-restart",
0fc3e113 1191 NO_STR DEBUG_STR OSPF6_STR "Graceful restart\n")
06943666 1192{
1193 if (!no)
0fc3e113 1194 OSPF6_DEBUG_GR_ON();
06943666 1195 else
0fc3e113 1196 OSPF6_DEBUG_GR_OFF();
06943666 1197
1198 return CMD_SUCCESS;
1199}
1200
0fc3e113 1201/*
1202 * Api to display the grace LSA information.
1203 *
1204 * vty
1205 * vty pointer.
1206 * lsa
1207 * Grace LSA.
1208 * json
1209 * json object
1210 *
1211 * Returns:
1212 * Nothing.
1213 */
1214static int ospf6_grace_lsa_show_info(struct vty *vty, struct ospf6_lsa *lsa,
1215 json_object *json, bool use_json)
1216{
1217 struct ospf6_lsa_header *lsah = NULL;
1218 struct tlv_header *tlvh = NULL;
1219 struct grace_tlv_graceperiod *gracePeriod;
1220 struct grace_tlv_restart_reason *grReason;
1221 uint16_t length = 0;
1222 int sum = 0;
1223
1224 lsah = (struct ospf6_lsa_header *)lsa->header;
905b12b2 1225 if (ntohs(lsah->length) <= OSPF6_LSA_HEADER_SIZE) {
1226 if (IS_DEBUG_OSPF6_GR)
1227 zlog_debug("%s: undersized (%u B) lsa", __func__,
1228 ntohs(lsah->length));
1229 return OSPF6_FAILURE;
1230 }
0fc3e113 1231
1232 length = ntohs(lsah->length) - OSPF6_LSA_HEADER_SIZE;
1233
1234 if (vty) {
1235 if (!use_json)
1236 vty_out(vty, "TLV info:\n");
1237 } else {
1238 zlog_debug(" TLV info:");
1239 }
1240
6d1a5a1c 1241 for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh;
0fc3e113 1242 tlvh = TLV_HDR_NEXT(tlvh)) {
6d1a5a1c 1243
1244 /* Check TLV len */
1245 if (sum + TLV_SIZE(tlvh) > length) {
1246 if (vty)
1247 vty_out(vty, "%% Invalid TLV length: %d\n",
1248 TLV_SIZE(tlvh));
1249 else if (IS_DEBUG_OSPF6_GR)
1250 zlog_debug("%% Invalid TLV length: %d",
1251 TLV_SIZE(tlvh));
1252 return OSPF6_FAILURE;
1253 }
1254
0fc3e113 1255 switch (ntohs(tlvh->type)) {
1256 case GRACE_PERIOD_TYPE:
1257 gracePeriod = (struct grace_tlv_graceperiod *)tlvh;
1258 sum += TLV_SIZE(tlvh);
1259
1260 if (vty) {
1261 if (use_json)
1262 json_object_int_add(
1263 json, "gracePeriod",
1264 ntohl(gracePeriod->interval));
1265 else
1266 vty_out(vty, " Grace period:%d\n",
1267 ntohl(gracePeriod->interval));
1268 } else {
1269 zlog_debug(" Grace period:%d",
1270 ntohl(gracePeriod->interval));
1271 }
1272 break;
1273 case RESTART_REASON_TYPE:
1274 grReason = (struct grace_tlv_restart_reason *)tlvh;
1275 sum += TLV_SIZE(tlvh);
1276 if (vty) {
1277 if (use_json)
1278 json_object_string_add(
1279 json, "restartReason",
1280 ospf6_restart_reason_desc
1281 [grReason->reason]);
1282 else
1283 vty_out(vty, " Restart reason:%s\n",
1284 ospf6_restart_reason_desc
1285 [grReason->reason]);
1286 } else {
1287 zlog_debug(" Restart reason:%s",
1288 ospf6_restart_reason_desc
1289 [grReason->reason]);
1290 }
1291 break;
1292 default:
1293 break;
1294 }
1295 }
1296
1297 return 0;
1298}
1299
1300void ospf6_gr_helper_config_init(void)
1301{
1302
1303 ospf6_install_lsa_handler(&grace_lsa_handler);
1304
1305 install_element(OSPF6_NODE, &ospf6_gr_helper_enable_cmd);
1306 install_element(OSPF6_NODE, &ospf6_gr_helper_disable_cmd);
1307 install_element(OSPF6_NODE, &ospf6_gr_helper_disable_lsacheck_cmd);
1308 install_element(OSPF6_NODE, &no_ospf6_gr_helper_disable_lsacheck_cmd);
1309 install_element(OSPF6_NODE, &ospf6_gr_helper_planned_only_cmd);
1310 install_element(OSPF6_NODE, &no_ospf6_gr_helper_planned_only_cmd);
1311 install_element(OSPF6_NODE, &ospf6_gr_helper_supported_grace_time_cmd);
1312 install_element(OSPF6_NODE,
1313 &no_ospf6_gr_helper_supported_grace_time_cmd);
1314
1315 install_element(VIEW_NODE, &show_ipv6_ospf6_gr_helper_cmd);
1316
1317 install_element(CONFIG_NODE, &debug_ospf6_gr_cmd);
1318 install_element(ENABLE_NODE, &debug_ospf6_gr_cmd);
1319}
1320
1321
59790f52 1322/*
0d1753a7 1323 * Initialize GR helper config data structure.
59790f52 1324 *
1325 * ospf6
1326 * ospf6 pointer
1327 *
1328 * Returns:
1329 * Nothing
1330 */
1331void ospf6_gr_helper_init(struct ospf6 *ospf6)
1332{
0fc3e113 1333 if (IS_DEBUG_OSPF6_GR)
0d1753a7 1334 zlog_debug("%s, GR Helper init.", __func__);
06943666 1335
59790f52 1336 ospf6->ospf6_helper_cfg.is_helper_supported = OSPF6_FALSE;
1337 ospf6->ospf6_helper_cfg.strict_lsa_check = OSPF6_TRUE;
1338 ospf6->ospf6_helper_cfg.only_planned_restart = OSPF6_FALSE;
1339 ospf6->ospf6_helper_cfg.supported_grace_time = OSPF6_MAX_GRACE_INTERVAL;
1340 ospf6->ospf6_helper_cfg.last_exit_reason = OSPF6_GR_HELPER_EXIT_NONE;
1341 ospf6->ospf6_helper_cfg.active_restarter_cnt = 0;
1342
1343 ospf6->ospf6_helper_cfg.enable_rtr_list = hash_create(
1344 ospf6_enable_rtr_hash_key, ospf6_enable_rtr_hash_cmp,
1345 "Ospf6 enable router hash");
1346}
1347
1348/*
0fc3e113 1349 * De-initialize GR helper config data structure.
59790f52 1350 *
1351 * ospf6
1352 * ospf6 pointer
1353 *
1354 * Returns:
1355 * Nothing
1356 */
1357void ospf6_gr_helper_deinit(struct ospf6 *ospf6)
1358{
06943666 1359
0fc3e113 1360 if (IS_DEBUG_OSPF6_GR)
0d1753a7 1361 zlog_debug("%s, GR helper deinit.", __func__);
06943666 1362
59790f52 1363 ospf6_enable_rtr_hash_destroy(ospf6);
1364}
0fc3e113 1365
1366static int ospf6_cfg_write_helper_enable_rtr_walkcb(struct hash_bucket *backet,
1367 void *arg)
1368{
1369 struct advRtr *rtr = backet->data;
1370 struct vty *vty = (struct vty *)arg;
1371
6b513b4c 1372 vty_out(vty, " graceful-restart helper enable %pI4\n", &rtr->advRtrAddr);
0fc3e113 1373 return HASHWALK_CONTINUE;
1374}
1375
1376int config_write_ospf6_gr_helper(struct vty *vty, struct ospf6 *ospf6)
1377{
1378 if (ospf6->ospf6_helper_cfg.is_helper_supported)
6b513b4c 1379 vty_out(vty, " graceful-restart helper enable\n");
0fc3e113 1380
1381 if (!ospf6->ospf6_helper_cfg.strict_lsa_check)
1382 vty_out(vty, " graceful-restart helper lsa-check-disable\n");
1383
1384 if (ospf6->ospf6_helper_cfg.only_planned_restart)
1385 vty_out(vty, " graceful-restart helper planned-only\n");
1386
1387 if (ospf6->ospf6_helper_cfg.supported_grace_time
1388 != OSPF6_MAX_GRACE_INTERVAL)
1389 vty_out(vty,
1390 " graceful-restart helper supported-grace-time %d\n",
1391 ospf6->ospf6_helper_cfg.supported_grace_time);
1392
1393 if (OSPF6_HELPER_ENABLE_RTR_COUNT(ospf6)) {
1394 hash_walk(ospf6->ospf6_helper_cfg.enable_rtr_list,
1395 ospf6_cfg_write_helper_enable_rtr_walkcb, vty);
1396 }
1397
1398 return 0;
1399}
1400
1401int config_write_ospf6_debug_gr_helper(struct vty *vty)
1402{
1403 if (IS_DEBUG_OSPF6_GR)
3ebc5e4b 1404 vty_out(vty, "debug ospf6 graceful-restart\n");
0fc3e113 1405 return 0;
1406}