]> git.proxmox.com Git - mirror_frr.git/blob - ospfd/ospf_gr_helper.c
Merge pull request #12818 from imzyxwvu/fix/other-table-inactive
[mirror_frr.git] / ospfd / ospf_gr_helper.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * OSPF Graceful Restart helper functions.
4 *
5 * Copyright (C) 2020-21 Vmware, Inc.
6 * Rajesh Kumar Girada
7 */
8
9 #include <zebra.h>
10
11 #include "thread.h"
12 #include "memory.h"
13 #include "linklist.h"
14 #include "prefix.h"
15 #include "if.h"
16 #include "table.h"
17 #include "vty.h"
18 #include "filter.h"
19 #include "log.h"
20 #include "jhash.h"
21
22 #include "ospfd/ospfd.h"
23 #include "ospfd/ospf_interface.h"
24 #include "ospfd/ospf_asbr.h"
25 #include "ospfd/ospf_lsa.h"
26 #include "ospfd/ospf_lsdb.h"
27 #include "ospfd/ospf_neighbor.h"
28 #include "ospfd/ospf_spf.h"
29 #include "ospfd/ospf_flood.h"
30 #include "ospfd/ospf_route.h"
31 #include "ospfd/ospf_zebra.h"
32 #include "ospfd/ospf_dump.h"
33 #include "ospfd/ospf_errors.h"
34 #include "ospfd/ospf_nsm.h"
35 #include "ospfd/ospf_ism.h"
36 #include "ospfd/ospf_gr.h"
37
38 static const char * const ospf_exit_reason_desc[] = {
39 "Unknown reason",
40 "Helper in progress",
41 "Topology Change",
42 "Grace timer expiry",
43 "Successful graceful restart",
44 };
45
46 static const char * const ospf_restart_reason_desc[] = {
47 "Unknown restart",
48 "Software restart",
49 "Software reload/upgrade",
50 "Switch to redundant control processor",
51 };
52
53 static const char * const ospf_rejected_reason_desc[] = {
54 "Unknown reason",
55 "Helper support disabled",
56 "Neighbour is not in FULL state",
57 "Supports only planned restart but received unplanned",
58 "Topo change due to change in lsa rxmt list",
59 "LSA age is more than Grace interval",
60 "Router is in the process of graceful restart",
61 };
62
63 static void show_ospf_grace_lsa_info(struct vty *vty, struct json_object *json,
64 struct ospf_lsa *lsa);
65 static bool ospf_check_change_in_rxmt_list(struct ospf_neighbor *nbr);
66
67 static unsigned int ospf_enable_rtr_hash_key(const void *data)
68 {
69 const struct advRtr *rtr = data;
70
71 return jhash_1word(rtr->advRtrAddr.s_addr, 0);
72 }
73
74 static bool ospf_enable_rtr_hash_cmp(const void *d1, const void *d2)
75 {
76 const struct advRtr *rtr1 = (struct advRtr *)d1;
77 const struct advRtr *rtr2 = (struct advRtr *)d2;
78
79 return (rtr1->advRtrAddr.s_addr == rtr2->advRtrAddr.s_addr);
80 }
81
82 static void *ospf_enable_rtr_hash_alloc(void *p)
83 {
84 struct advRtr *rid;
85
86 rid = XCALLOC(MTYPE_OSPF_GR_HELPER, sizeof(struct advRtr));
87 rid->advRtrAddr.s_addr = ((struct in_addr *)p)->s_addr;
88
89 return rid;
90 }
91
92 static void ospf_disable_rtr_hash_free(void *rtr)
93 {
94 XFREE(MTYPE_OSPF_GR_HELPER, rtr);
95 }
96
97 static void ospf_enable_rtr_hash_destroy(struct ospf *ospf)
98 {
99 if (ospf->enable_rtr_list == NULL)
100 return;
101
102 hash_clean(ospf->enable_rtr_list, ospf_disable_rtr_hash_free);
103 hash_free(ospf->enable_rtr_list);
104 ospf->enable_rtr_list = NULL;
105 }
106
107 /*
108 * GR exit reason strings
109 */
110 const char *ospf_exit_reason2str(unsigned int reason)
111 {
112 if (reason < array_size(ospf_exit_reason_desc))
113 return(ospf_exit_reason_desc[reason]);
114 else
115 return "Invalid reason";
116 }
117
118 /*
119 * GR restart reason strings
120 */
121 const char *ospf_restart_reason2str(unsigned int reason)
122 {
123 if (reason < array_size(ospf_restart_reason_desc))
124 return(ospf_restart_reason_desc[reason]);
125 else
126 return "Invalid reason";
127 }
128
129 /*
130 * GR rejected reason strings
131 */
132 const char *ospf_rejected_reason2str(unsigned int reason)
133 {
134 if (reason < array_size(ospf_rejected_reason_desc))
135 return(ospf_rejected_reason_desc[reason]);
136 else
137 return "Invalid reason";
138 }
139
140 /*
141 * Initialize GR helper config data structures.
142 *
143 * OSPF
144 * OSPF pointer
145 *
146 * Returns:
147 * Nothing
148 */
149 void ospf_gr_helper_instance_init(struct ospf *ospf)
150 {
151 if (IS_DEBUG_OSPF_GR)
152 zlog_debug("%s, GR Helper init.", __func__);
153
154 ospf->is_helper_supported = OSPF_GR_FALSE;
155 ospf->strict_lsa_check = OSPF_GR_TRUE;
156 ospf->only_planned_restart = OSPF_GR_FALSE;
157 ospf->supported_grace_time = OSPF_MAX_GRACE_INTERVAL;
158 ospf->last_exit_reason = OSPF_GR_HELPER_EXIT_NONE;
159 ospf->active_restarter_cnt = 0;
160
161 ospf->enable_rtr_list =
162 hash_create(ospf_enable_rtr_hash_key, ospf_enable_rtr_hash_cmp,
163 "OSPF enable router hash");
164 }
165
166 /*
167 * De-Initialize GR helper config data structures.
168 *
169 * OSPF
170 * OSPF pointer
171 *
172 * Returns:
173 * Nothing
174 */
175 void ospf_gr_helper_instance_stop(struct ospf *ospf)
176 {
177 if (IS_DEBUG_OSPF_GR)
178 zlog_debug("%s, GR helper deinit.", __func__);
179
180 ospf_enable_rtr_hash_destroy(ospf);
181 }
182
183 /*
184 * Initialize GR helper config data structures.
185 *
186 * Returns:
187 * Nothing
188 */
189 void ospf_gr_helper_init(void)
190 {
191 int rc;
192
193 if (IS_DEBUG_OSPF_GR)
194 zlog_debug("%s, GR Helper init.", __func__);
195
196 rc = ospf_register_opaque_functab(
197 OSPF_OPAQUE_LINK_LSA, OPAQUE_TYPE_GRACE_LSA, NULL, NULL, NULL,
198 NULL, NULL, NULL, NULL, show_ospf_grace_lsa_info, NULL, NULL,
199 NULL, NULL);
200 if (rc != 0) {
201 flog_warn(EC_OSPF_OPAQUE_REGISTRATION,
202 "%s: Failed to register Grace LSA functions",
203 __func__);
204 }
205 }
206
207 /*
208 * De-Initialize GR helper config data structures.
209 *
210 * Returns:
211 * Nothing
212 */
213 void ospf_gr_helper_stop(void)
214 {
215 if (IS_DEBUG_OSPF_GR)
216 zlog_debug("%s, GR helper deinit.", __func__);
217
218 ospf_delete_opaque_functab(OSPF_OPAQUE_LINK_LSA, OPAQUE_TYPE_GRACE_LSA);
219 }
220
221 /*
222 * Extracting tlv info from GRACE LSA.
223 *
224 * lsa
225 * ospf grace lsa
226 *
227 * Returns:
228 * interval : grace interval.
229 * addr : RESTARTER address.
230 * reason : Restarting reason.
231 */
232 static int ospf_extract_grace_lsa_fields(struct ospf_lsa *lsa,
233 uint32_t *interval,
234 struct in_addr *addr, uint8_t *reason)
235 {
236 struct lsa_header *lsah = NULL;
237 struct tlv_header *tlvh = NULL;
238 struct grace_tlv_graceperiod *grace_period;
239 struct grace_tlv_restart_reason *gr_reason;
240 struct grace_tlv_restart_addr *restart_addr;
241 uint16_t length = 0;
242 int sum = 0;
243
244 lsah = (struct lsa_header *)lsa->data;
245
246 /* Check LSA len */
247 if (lsa->size <= OSPF_LSA_HEADER_SIZE) {
248 if (IS_DEBUG_OSPF_GR)
249 zlog_debug("%s: Malformed packet: Invalid LSA len:%d",
250 __func__, length);
251 return OSPF_GR_FAILURE;
252 }
253
254 length = lsa->size - OSPF_LSA_HEADER_SIZE;
255
256 for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh;
257 tlvh = TLV_HDR_NEXT(tlvh)) {
258
259 /* Check TLV len against overall LSA */
260 if (sum + TLV_SIZE(tlvh) > length) {
261 if (IS_DEBUG_OSPF_GR)
262 zlog_debug("%s: Malformed packet: Invalid TLV len:%u",
263 __func__, TLV_SIZE(tlvh));
264 return OSPF_GR_FAILURE;
265 }
266
267 switch (ntohs(tlvh->type)) {
268 case GRACE_PERIOD_TYPE:
269 if (TLV_SIZE(tlvh) <
270 sizeof(struct grace_tlv_graceperiod)) {
271 zlog_debug("%s: Malformed packet: Invalid grace TLV len:%u",
272 __func__, TLV_SIZE(tlvh));
273 return OSPF_GR_FAILURE;
274 }
275
276 grace_period = (struct grace_tlv_graceperiod *)tlvh;
277 *interval = ntohl(grace_period->interval);
278 sum += TLV_SIZE(tlvh);
279
280 /* Check if grace interval is valid */
281 if (*interval > OSPF_MAX_GRACE_INTERVAL
282 || *interval < OSPF_MIN_GRACE_INTERVAL)
283 return OSPF_GR_FAILURE;
284 break;
285 case RESTART_REASON_TYPE:
286 if (TLV_SIZE(tlvh) <
287 sizeof(struct grace_tlv_restart_reason)) {
288 zlog_debug("%s: Malformed packet: Invalid reason TLV len:%u",
289 __func__, TLV_SIZE(tlvh));
290 return OSPF_GR_FAILURE;
291 }
292
293 gr_reason = (struct grace_tlv_restart_reason *)tlvh;
294 *reason = gr_reason->reason;
295 sum += TLV_SIZE(tlvh);
296
297 if (*reason >= OSPF_GR_INVALID_REASON_CODE)
298 return OSPF_GR_FAILURE;
299 break;
300 case RESTARTER_IP_ADDR_TYPE:
301 if (TLV_SIZE(tlvh) <
302 sizeof(struct grace_tlv_restart_addr)) {
303 zlog_debug("%s: Malformed packet: Invalid addr TLV len:%u",
304 __func__, TLV_SIZE(tlvh));
305 return OSPF_GR_FAILURE;
306 }
307
308 restart_addr = (struct grace_tlv_restart_addr *)tlvh;
309 addr->s_addr = restart_addr->addr.s_addr;
310 sum += TLV_SIZE(tlvh);
311 break;
312 default:
313 if (IS_DEBUG_OSPF_GR)
314 zlog_debug(
315 "%s, Malformed packet.Invalid TLV type:%d",
316 __func__, ntohs(tlvh->type));
317 return OSPF_GR_FAILURE;
318 }
319 }
320
321 return OSPF_GR_SUCCESS;
322 }
323
324 /*
325 * Grace timer expiry handler.
326 * HELPER aborts its role at grace timer expiry.
327 *
328 * thread
329 * thread pointer
330 *
331 * Returns:
332 * Nothing
333 */
334 static void ospf_handle_grace_timer_expiry(struct thread *thread)
335 {
336 struct ospf_neighbor *nbr = THREAD_ARG(thread);
337
338 nbr->gr_helper_info.t_grace_timer = NULL;
339
340 ospf_gr_helper_exit(nbr, OSPF_GR_HELPER_GRACE_TIMEOUT);
341 }
342
343 /*
344 * Process Grace LSA.If it is eligible move to HELPER role.
345 * Ref rfc3623 section 3.1
346 *
347 * ospf
348 * OSPF pointer.
349 *
350 * lsa
351 * Grace LSA received from RESTARTER.
352 *
353 * nbr
354 * OSPF neighbour which requests the router to act as
355 * HELPER.
356 *
357 * Returns:
358 * status.
359 * If supported as HELPER : OSPF_GR_HELPER_INPROGRESS
360 * If Not supported as HELPER : OSPF_GR_HELPER_NONE
361 */
362 int ospf_process_grace_lsa(struct ospf *ospf, struct ospf_lsa *lsa,
363 struct ospf_neighbor *nbr)
364 {
365 struct in_addr restart_addr = {0};
366 uint8_t restart_reason = 0;
367 uint32_t grace_interval = 0;
368 uint32_t actual_grace_interval = 0;
369 struct advRtr lookup;
370 struct ospf_neighbor *restarter = NULL;
371 struct ospf_interface *oi = nbr->oi;
372 int ret;
373
374
375 /* Extract the grace lsa packet fields */
376 ret = ospf_extract_grace_lsa_fields(lsa, &grace_interval, &restart_addr,
377 &restart_reason);
378 if (ret != OSPF_GR_SUCCESS) {
379 if (IS_DEBUG_OSPF_GR)
380 zlog_debug("%s, Wrong Grace LSA packet.", __func__);
381 return OSPF_GR_NOT_HELPER;
382 }
383
384 if (IS_DEBUG_OSPF_GR)
385 zlog_debug(
386 "%s, Grace LSA received from %pI4, grace interval:%u, restart reason:%s",
387 __func__, &restart_addr, grace_interval,
388 ospf_restart_reason2str(restart_reason));
389
390 /* In case of broadcast links, if RESTARTER is DR_OTHER,
391 * grace LSA might be received from DR, so need to get
392 * actual neighbour info , here RESTARTER.
393 */
394 if (oi->type != OSPF_IFTYPE_POINTOPOINT) {
395 restarter = ospf_nbr_lookup_by_addr(oi->nbrs, &restart_addr);
396
397 if (!restarter) {
398 if (IS_DEBUG_OSPF_GR)
399 zlog_debug(
400 "%s, Restarter is not a nbr(%pI4) for this router.",
401 __func__, &restart_addr);
402 return OSPF_GR_NOT_HELPER;
403 }
404 } else
405 restarter = nbr;
406
407 /* Verify Helper enabled globally */
408 if (!ospf->is_helper_supported) {
409 /* Verify that Helper support is enabled for the
410 * current neighbour router-id.
411 */
412 lookup.advRtrAddr.s_addr = restarter->router_id.s_addr;
413
414 if (!hash_lookup(ospf->enable_rtr_list, &lookup)) {
415 if (IS_DEBUG_OSPF_GR)
416 zlog_debug(
417 "%s, HELPER support is disabled, So not a HELPER",
418 __func__);
419 restarter->gr_helper_info.rejected_reason =
420 OSPF_HELPER_SUPPORT_DISABLED;
421 return OSPF_GR_NOT_HELPER;
422 }
423 }
424
425
426 /* Check neighbour is in FULL state and
427 * became a adjacency.
428 */
429 if (!IS_NBR_STATE_FULL(restarter)) {
430 if (IS_DEBUG_OSPF_GR)
431 zlog_debug(
432 "%s, This Neighbour %pI4 is not in FULL state.",
433 __func__, &restarter->src);
434 restarter->gr_helper_info.rejected_reason =
435 OSPF_HELPER_NOT_A_VALID_NEIGHBOUR;
436 return OSPF_GR_NOT_HELPER;
437 }
438
439 /* Based on the restart reason from grace lsa
440 * check the current router is supporting or not
441 */
442 if (ospf->only_planned_restart
443 && !OSPF_GR_IS_PLANNED_RESTART(restart_reason)) {
444 if (IS_DEBUG_OSPF_GR)
445 zlog_debug(
446 "%s, Router supports only planned restarts but received the GRACE LSA for an unplanned restart.",
447 __func__);
448 restarter->gr_helper_info.rejected_reason =
449 OSPF_HELPER_PLANNED_ONLY_RESTART;
450 return OSPF_GR_NOT_HELPER;
451 }
452
453 /* Check the retransmission list of this
454 * neighbour, check any change in lsas.
455 */
456 if (ospf->strict_lsa_check && !ospf_ls_retransmit_isempty(restarter)
457 && ospf_check_change_in_rxmt_list(restarter)) {
458 if (IS_DEBUG_OSPF_GR)
459 zlog_debug(
460 "%s, Changed LSA in Rxmt list. So not Helper.",
461 __func__);
462 restarter->gr_helper_info.rejected_reason =
463 OSPF_HELPER_TOPO_CHANGE_RTXMT_LIST;
464 return OSPF_GR_NOT_HELPER;
465 }
466
467 /*LSA age must be less than the grace period */
468 if (ntohs(lsa->data->ls_age) >= grace_interval) {
469 if (IS_DEBUG_OSPF_GR)
470 zlog_debug(
471 "%s, Grace LSA age(%d) is more than the grace interval(%d)",
472 __func__, lsa->data->ls_age, grace_interval);
473 restarter->gr_helper_info.rejected_reason =
474 OSPF_HELPER_LSA_AGE_MORE;
475 return OSPF_GR_NOT_HELPER;
476 }
477
478 if (ospf->gr_info.restart_in_progress) {
479 if (IS_DEBUG_OSPF_GR)
480 zlog_debug(
481 "%s: router is in the process of graceful restart",
482 __func__);
483 restarter->gr_helper_info.rejected_reason =
484 OSPF_HELPER_RESTARTING;
485 return OSPF_GR_NOT_HELPER;
486 }
487
488 /* check supported grace period configured
489 * if configured, use this to start the grace
490 * timer otherwise use the interval received
491 * in grace LSA packet.
492 */
493 actual_grace_interval = grace_interval;
494 if (grace_interval > ospf->supported_grace_time) {
495 if (IS_DEBUG_OSPF_GR)
496 zlog_debug(
497 "%s, Received grace period %d is larger than supported grace %d",
498 __func__, grace_interval,
499 ospf->supported_grace_time);
500 actual_grace_interval = ospf->supported_grace_time;
501 }
502
503 if (OSPF_GR_IS_ACTIVE_HELPER(restarter)) {
504 if (restarter->gr_helper_info.t_grace_timer)
505 THREAD_OFF(restarter->gr_helper_info.t_grace_timer);
506
507 if (ospf->active_restarter_cnt > 0)
508 ospf->active_restarter_cnt--;
509
510 if (IS_DEBUG_OSPF_GR)
511 zlog_debug(
512 "%s, Router is already acting as a HELPER for this nbr,so restart the grace timer",
513 __func__);
514 } else {
515 if (IS_DEBUG_OSPF_GR)
516 zlog_debug(
517 "%s, This Router becomes a HELPER for the neighbour %pI4",
518 __func__, &restarter->src);
519 }
520
521 /* Became a Helper to the RESTART neighbour.
522 * Change the helper status.
523 */
524 restarter->gr_helper_info.gr_helper_status = OSPF_GR_ACTIVE_HELPER;
525 restarter->gr_helper_info.recvd_grace_period = grace_interval;
526 restarter->gr_helper_info.actual_grace_period = actual_grace_interval;
527 restarter->gr_helper_info.gr_restart_reason = restart_reason;
528 restarter->gr_helper_info.rejected_reason = OSPF_HELPER_REJECTED_NONE;
529
530 /* Increment the active restarter count */
531 ospf->active_restarter_cnt++;
532
533 if (IS_DEBUG_OSPF_GR)
534 zlog_debug("%s, Grace timer started.interval:%d", __func__,
535 actual_grace_interval);
536
537 /* Start the grace timer */
538 thread_add_timer(master, ospf_handle_grace_timer_expiry, restarter,
539 actual_grace_interval,
540 &restarter->gr_helper_info.t_grace_timer);
541
542 return OSPF_GR_ACTIVE_HELPER;
543 }
544
545 /*
546 * API to check any change in the neighbor's
547 * retransmission list.
548 *
549 * nbr
550 * OSPF neighbor
551 *
552 * Returns:
553 * TRUE - if any change in the lsa.
554 * FALSE - no change in the lsas.
555 */
556 static bool ospf_check_change_in_rxmt_list(struct ospf_neighbor *nbr)
557 {
558 struct route_node *rn;
559 struct ospf_lsa *lsa;
560 struct route_table *tbl;
561
562 tbl = nbr->ls_rxmt.type[OSPF_ROUTER_LSA].db;
563 LSDB_LOOP (tbl, rn, lsa)
564 if (lsa->to_be_acknowledged)
565 return OSPF_GR_TRUE;
566 tbl = nbr->ls_rxmt.type[OSPF_NETWORK_LSA].db;
567 LSDB_LOOP (tbl, rn, lsa)
568 if (lsa->to_be_acknowledged)
569 return OSPF_GR_TRUE;
570
571 tbl = nbr->ls_rxmt.type[OSPF_SUMMARY_LSA].db;
572 LSDB_LOOP (tbl, rn, lsa)
573 if (lsa->to_be_acknowledged)
574 return OSPF_GR_TRUE;
575
576 tbl = nbr->ls_rxmt.type[OSPF_ASBR_SUMMARY_LSA].db;
577 LSDB_LOOP (tbl, rn, lsa)
578 if (lsa->to_be_acknowledged)
579 return OSPF_GR_TRUE;
580
581 tbl = nbr->ls_rxmt.type[OSPF_AS_EXTERNAL_LSA].db;
582 LSDB_LOOP (tbl, rn, lsa)
583 if (lsa->to_be_acknowledged)
584 return OSPF_GR_TRUE;
585
586 tbl = nbr->ls_rxmt.type[OSPF_AS_NSSA_LSA].db;
587 LSDB_LOOP (tbl, rn, lsa)
588 if (lsa->to_be_acknowledged)
589 return OSPF_GR_TRUE;
590
591 return OSPF_GR_FALSE;
592 }
593
594 /*
595 * Actions to be taken when topo change detected
596 * HELPER will exit upon topo change.
597 *
598 * ospf
599 * ospf pointer
600 * lsa
601 * topo change occurred due to this lsa type (1 to 5 and 7)
602 *
603 * Returns:
604 * Nothing
605 */
606 void ospf_helper_handle_topo_chg(struct ospf *ospf, struct ospf_lsa *lsa)
607 {
608 struct listnode *node;
609 struct ospf_interface *oi;
610
611 /* Topo change not required to be handled if strict
612 * LSA check is disabled for this router.
613 */
614 if (!ospf->strict_lsa_check)
615 return;
616
617 if (IS_DEBUG_OSPF_GR)
618 zlog_debug("%s: Topo change detected due to LSA[%s]", __func__,
619 dump_lsa_key(lsa));
620
621 lsa->to_be_acknowledged = OSPF_GR_TRUE;
622
623 for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
624 struct route_node *rn = NULL;
625
626 if (ospf_interface_neighbor_count(oi) == 0)
627 continue;
628
629 /* Ref rfc3623 section 3.2.3.b
630 * If change due to external LSA and if the area is
631 * stub, then it is not a topo change. Since Type-5
632 * lsas will not be flooded in stub area.
633 */
634 if ((oi->area->external_routing == OSPF_AREA_STUB)
635 && (lsa->data->type == OSPF_AS_EXTERNAL_LSA)) {
636 continue;
637 }
638
639 for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
640 struct ospf_neighbor *nbr = NULL;
641
642 if (!rn->info)
643 continue;
644
645 nbr = rn->info;
646
647 if (OSPF_GR_IS_ACTIVE_HELPER(nbr))
648 ospf_gr_helper_exit(nbr,
649 OSPF_GR_HELPER_TOPO_CHG);
650 }
651 }
652 }
653
654 /*
655 * Api to exit from HELPER role to take all actions
656 * required at exit.
657 * Ref rfc3623 section 3.2
658 *
659 * ospf
660 * OSPF pointer.
661 *
662 * nbr
663 * OSPF neighbour for which it is acting as HELPER.
664 *
665 * reason
666 * The reason for exiting from HELPER.
667 *
668 * Returns:
669 * Nothing.
670 */
671 void ospf_gr_helper_exit(struct ospf_neighbor *nbr,
672 enum ospf_helper_exit_reason reason)
673 {
674 struct ospf_interface *oi = nbr->oi;
675 struct ospf *ospf = oi->ospf;
676
677 if (!OSPF_GR_IS_ACTIVE_HELPER(nbr))
678 return;
679
680 if (IS_DEBUG_OSPF_GR)
681 zlog_debug("%s, Exiting from HELPER support to %pI4, due to %s",
682 __func__, &nbr->src, ospf_exit_reason2str(reason));
683
684 /* Reset helper status*/
685 nbr->gr_helper_info.gr_helper_status = OSPF_GR_NOT_HELPER;
686 nbr->gr_helper_info.helper_exit_reason = reason;
687 nbr->gr_helper_info.actual_grace_period = 0;
688 nbr->gr_helper_info.recvd_grace_period = 0;
689 nbr->gr_helper_info.gr_restart_reason = 0;
690 ospf->last_exit_reason = reason;
691
692 if (ospf->active_restarter_cnt <= 0) {
693 zlog_err(
694 "OSPF GR-Helper: active_restarter_cnt should be greater than zero here.");
695 return;
696 }
697 /* Decrement active Restarter count */
698 ospf->active_restarter_cnt--;
699
700 /* If the exit not triggered due to grace timer
701 * expiry, stop the grace timer.
702 */
703 if (reason != OSPF_GR_HELPER_GRACE_TIMEOUT)
704 THREAD_OFF(nbr->gr_helper_info.t_grace_timer);
705
706 /* check exit triggered due to successful completion
707 * of graceful restart.
708 */
709 if (reason != OSPF_GR_HELPER_COMPLETED) {
710 if (IS_DEBUG_OSPF_GR)
711 zlog_debug("%s, Unsuccessful GR exit", __func__);
712 }
713
714 /*Recalculate the DR for the network segment */
715 if (oi->type == OSPF_IFTYPE_BROADCAST || oi->type == OSPF_IFTYPE_NBMA)
716 ospf_dr_election(oi);
717
718 /* Originate a router LSA */
719 ospf_router_lsa_update_area(oi->area);
720
721 /* Originate network lsa if it is an DR in the LAN */
722 if (oi->state == ISM_DR)
723 ospf_network_lsa_update(oi);
724 }
725
726 /*
727 * Process MaxAge Grace LSA.
728 * It is a indication for successful completion of GR.
729 * If router acting as HELPER, It exits from helper role.
730 *
731 * ospf
732 * OSPF pointer.
733 *
734 * lsa
735 * Grace LSA received from RESTARTER.
736 *
737 * nbr
738 * OSPF neighbour which requests the router to act as
739 * HELPER.
740 *
741 * Returns:
742 * Nothing.
743 */
744 void ospf_process_maxage_grace_lsa(struct ospf *ospf, struct ospf_lsa *lsa,
745 struct ospf_neighbor *nbr)
746 {
747 struct in_addr restartAddr = {0};
748 uint8_t restartReason = 0;
749 uint32_t graceInterval = 0;
750 struct ospf_neighbor *restarter = NULL;
751 struct ospf_interface *oi = nbr->oi;
752 int ret;
753
754 /* Extract the grace lsa packet fields */
755 ret = ospf_extract_grace_lsa_fields(lsa, &graceInterval, &restartAddr,
756 &restartReason);
757 if (ret != OSPF_GR_SUCCESS) {
758 if (IS_DEBUG_OSPF_GR)
759 zlog_debug("%s, Wrong Grace LSA packet.", __func__);
760 return;
761 }
762
763 if (IS_DEBUG_OSPF_GR)
764 zlog_debug("%s, GraceLSA received for neighbour %pI4", __func__,
765 &restartAddr);
766
767 /* In case of broadcast links, if RESTARTER is DR_OTHER,
768 * grace LSA might be received from DR, so fetching the
769 * actual neighbour information using restarter address.
770 */
771 if (oi->type != OSPF_IFTYPE_POINTOPOINT) {
772 restarter = ospf_nbr_lookup_by_addr(oi->nbrs, &restartAddr);
773
774 if (!restarter) {
775 if (IS_DEBUG_OSPF_GR)
776 zlog_debug(
777 "%s, Restarter is not a neighbour for this router.",
778 __func__);
779 return;
780 }
781 } else {
782 restarter = nbr;
783 }
784
785 ospf_gr_helper_exit(restarter, OSPF_GR_HELPER_COMPLETED);
786 }
787
788 /* Configuration handlers */
789 /*
790 * Disable/Enable HELPER support on router level.
791 *
792 * ospf
793 * OSPF pointer.
794 *
795 * status
796 * TRUE/FALSE
797 *
798 * Returns:
799 * Nothing.
800 */
801 void ospf_gr_helper_support_set(struct ospf *ospf, bool support)
802 {
803 struct ospf_interface *oi;
804 struct listnode *node;
805 struct advRtr lookup;
806
807 if (ospf->is_helper_supported == support)
808 return;
809
810 ospf->is_helper_supported = support;
811
812 /* If helper support disabled, cease HELPER role for all
813 * supporting neighbors.
814 */
815 if (support == OSPF_GR_FALSE) {
816 for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
817 struct route_node *rn = NULL;
818
819 if (ospf_interface_neighbor_count(oi) == 0)
820 continue;
821
822 for (rn = route_top(oi->nbrs); rn;
823 rn = route_next(rn)) {
824 struct ospf_neighbor *nbr = NULL;
825
826 if (!rn->info)
827 continue;
828
829 nbr = rn->info;
830
831 lookup.advRtrAddr.s_addr =
832 nbr->router_id.s_addr;
833 /* check if helper support enabled for the
834 * corresponding routerid.If enabled, don't
835 * exit from helper role.
836 */
837 if (hash_lookup(ospf->enable_rtr_list, &lookup))
838 continue;
839
840 if (OSPF_GR_IS_ACTIVE_HELPER(nbr))
841 ospf_gr_helper_exit(
842 nbr, OSPF_GR_HELPER_TOPO_CHG);
843 }
844 }
845 }
846 }
847
848 /*
849 * Enable/Disable HELPER support on a specified advertagement
850 * router.
851 *
852 * ospf
853 * OSPF pointer.
854 *
855 * advRtr
856 * HELPER support for given Advertisement Router.
857 *
858 * support
859 * True - Enable Helper Support.
860 * False - Disable Helper Support.
861 *
862 * Returns:
863 * Nothing.
864 */
865
866 void ospf_gr_helper_support_set_per_routerid(struct ospf *ospf,
867 struct in_addr *advrtr,
868 bool support)
869 {
870 struct advRtr temp;
871 struct advRtr *rtr;
872 struct ospf_interface *oi;
873 struct listnode *node;
874
875 temp.advRtrAddr.s_addr = advrtr->s_addr;
876
877 if (support == OSPF_GR_FALSE) {
878 /*Delete the routerid from the enable router hash table */
879 rtr = hash_lookup(ospf->enable_rtr_list, &temp);
880
881 if (rtr) {
882 hash_release(ospf->enable_rtr_list, rtr);
883 ospf_disable_rtr_hash_free(rtr);
884 }
885
886 /* If helper support is enabled globally
887 * no action is required.
888 */
889 if (ospf->is_helper_supported)
890 return;
891
892 /* Cease the HELPER role fore neighbours from the
893 * specified advertisement router.
894 */
895 for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
896 struct route_node *rn = NULL;
897
898 if (ospf_interface_neighbor_count(oi) == 0)
899 continue;
900
901 for (rn = route_top(oi->nbrs); rn;
902 rn = route_next(rn)) {
903 struct ospf_neighbor *nbr = NULL;
904
905 if (!rn->info)
906 continue;
907
908 nbr = rn->info;
909
910 if (nbr->router_id.s_addr != advrtr->s_addr)
911 continue;
912
913 if (OSPF_GR_IS_ACTIVE_HELPER(nbr))
914 ospf_gr_helper_exit(
915 nbr, OSPF_GR_HELPER_TOPO_CHG);
916 }
917 }
918
919 } else {
920 /* Add the routerid to the enable router hash table */
921 (void)hash_get(ospf->enable_rtr_list, &temp,
922 ospf_enable_rtr_hash_alloc);
923 }
924 }
925
926 /*
927 * Api to enable/disable strict lsa check on the HELPER.
928 *
929 * ospf
930 * OSPF pointer.
931 *
932 * enabled
933 * True - disable the lsa check.
934 * False - enable the strict lsa check.
935 *
936 * Returns:
937 * Nothing.
938 */
939 void ospf_gr_helper_lsa_check_set(struct ospf *ospf, bool enabled)
940 {
941 if (ospf->strict_lsa_check == enabled)
942 return;
943
944 ospf->strict_lsa_check = enabled;
945 }
946
947 /*
948 * Api to set the supported grace interval in this router.
949 *
950 * ospf
951 * OSPF pointer.
952 *
953 * interval
954 * The supported grace interval..
955 *
956 * Returns:
957 * Nothing.
958 */
959 void ospf_gr_helper_supported_gracetime_set(struct ospf *ospf,
960 uint32_t interval)
961 {
962 ospf->supported_grace_time = interval;
963 }
964
965 /*
966 * Api to set the supported restart reason.
967 *
968 * ospf
969 * OSPF pointer.
970 *
971 * planned_only
972 * True: support only planned restart.
973 * False: support for planned/unplanned restarts.
974 *
975 * Returns:
976 * Nothing.
977 */
978 void ospf_gr_helper_set_supported_planned_only_restart(struct ospf *ospf,
979 bool planned_only)
980 {
981 ospf->only_planned_restart = planned_only;
982 }
983
984 /*
985 * Api to display the grace LSA information.
986 *
987 * vty
988 * vty pointer.
989 * lsa
990 * Grace LSA.
991 * json
992 * json object
993 *
994 * Returns:
995 * Nothing.
996 */
997 static void show_ospf_grace_lsa_info(struct vty *vty, struct json_object *json,
998 struct ospf_lsa *lsa)
999 {
1000 struct lsa_header *lsah = NULL;
1001 struct tlv_header *tlvh = NULL;
1002 struct grace_tlv_graceperiod *gracePeriod;
1003 struct grace_tlv_restart_reason *grReason;
1004 struct grace_tlv_restart_addr *restartAddr;
1005 uint16_t length = 0;
1006 int sum = 0;
1007
1008 if (json)
1009 return;
1010
1011 lsah = (struct lsa_header *)lsa->data;
1012
1013 if (lsa->size <= OSPF_LSA_HEADER_SIZE) {
1014 if (vty)
1015 vty_out(vty, "%% Invalid LSA length: %d\n", length);
1016 else
1017 zlog_debug("%% Invalid LSA length: %d", length);
1018 return;
1019 }
1020
1021 length = lsa->size - OSPF_LSA_HEADER_SIZE;
1022
1023 if (vty)
1024 vty_out(vty, " TLV info:\n");
1025 else
1026 zlog_debug(" TLV info:");
1027
1028 for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh;
1029 tlvh = TLV_HDR_NEXT(tlvh)) {
1030 /* Check TLV len */
1031 if (sum + TLV_SIZE(tlvh) > length) {
1032 if (vty)
1033 vty_out(vty, "%% Invalid TLV length: %u\n",
1034 TLV_SIZE(tlvh));
1035 else
1036 zlog_debug("%% Invalid TLV length: %u",
1037 TLV_SIZE(tlvh));
1038 return;
1039 }
1040
1041 switch (ntohs(tlvh->type)) {
1042 case GRACE_PERIOD_TYPE:
1043 if (TLV_SIZE(tlvh)
1044 < sizeof(struct grace_tlv_graceperiod)) {
1045 if (vty)
1046 vty_out(vty,
1047 "%% Invalid grace TLV length %u\n",
1048 TLV_SIZE(tlvh));
1049 else
1050 zlog_debug(
1051 "%% Invalid grace TLV length %u",
1052 TLV_SIZE(tlvh));
1053 return;
1054 }
1055
1056 gracePeriod = (struct grace_tlv_graceperiod *)tlvh;
1057 sum += TLV_SIZE(tlvh);
1058
1059 if (vty)
1060 vty_out(vty, " Grace period:%d\n",
1061 ntohl(gracePeriod->interval));
1062 else
1063 zlog_debug(" Grace period:%d",
1064 ntohl(gracePeriod->interval));
1065 break;
1066 case RESTART_REASON_TYPE:
1067 if (TLV_SIZE(tlvh)
1068 < sizeof(struct grace_tlv_restart_reason)) {
1069 if (vty)
1070 vty_out(vty,
1071 "%% Invalid reason TLV length %u\n",
1072 TLV_SIZE(tlvh));
1073 else
1074 zlog_debug(
1075 "%% Invalid reason TLV length %u",
1076 TLV_SIZE(tlvh));
1077 return;
1078 }
1079
1080 grReason = (struct grace_tlv_restart_reason *)tlvh;
1081 sum += TLV_SIZE(tlvh);
1082
1083 if (vty)
1084 vty_out(vty, " Restart reason:%s\n",
1085 ospf_restart_reason2str(
1086 grReason->reason));
1087 else
1088 zlog_debug(" Restart reason:%s",
1089 ospf_restart_reason2str(
1090 grReason->reason));
1091 break;
1092 case RESTARTER_IP_ADDR_TYPE:
1093 if (TLV_SIZE(tlvh)
1094 < sizeof(struct grace_tlv_restart_addr)) {
1095 if (vty)
1096 vty_out(vty,
1097 "%% Invalid addr TLV length %u\n",
1098 TLV_SIZE(tlvh));
1099 else
1100 zlog_debug(
1101 "%% Invalid addr TLV length %u",
1102 TLV_SIZE(tlvh));
1103 return;
1104 }
1105
1106 restartAddr = (struct grace_tlv_restart_addr *)tlvh;
1107 sum += TLV_SIZE(tlvh);
1108
1109 if (vty)
1110 vty_out(vty, " Restarter address:%pI4\n",
1111 &restartAddr->addr);
1112 else
1113 zlog_debug(" Restarter address:%pI4",
1114 &restartAddr->addr);
1115 break;
1116 default:
1117 if (vty)
1118 vty_out(vty, " Unknown TLV type %d\n",
1119 ntohs(tlvh->type));
1120 else
1121 zlog_debug(" Unknown TLV type %d",
1122 ntohs(tlvh->type));
1123
1124 break;
1125 }
1126 }
1127 }