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