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