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