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