]> git.proxmox.com Git - mirror_frr.git/blob - ospfd/ospf_spf.c
Merge pull request #11242 from patrasar/pimv6_issue_11233
[mirror_frr.git] / ospfd / ospf_spf.c
1 /* OSPF SPF calculation.
2 * Copyright (C) 1999, 2000 Kunihiro Ishiguro, Toshiaki Takada
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <zebra.h>
22
23 #include "monotime.h"
24 #include "thread.h"
25 #include "memory.h"
26 #include "hash.h"
27 #include "linklist.h"
28 #include "prefix.h"
29 #include "if.h"
30 #include "table.h"
31 #include "log.h"
32 #include "sockunion.h" /* for inet_ntop () */
33
34 #include "ospfd/ospfd.h"
35 #include "ospfd/ospf_interface.h"
36 #include "ospfd/ospf_ism.h"
37 #include "ospfd/ospf_asbr.h"
38 #include "ospfd/ospf_lsa.h"
39 #include "ospfd/ospf_lsdb.h"
40 #include "ospfd/ospf_neighbor.h"
41 #include "ospfd/ospf_nsm.h"
42 #include "ospfd/ospf_spf.h"
43 #include "ospfd/ospf_route.h"
44 #include "ospfd/ospf_ia.h"
45 #include "ospfd/ospf_ase.h"
46 #include "ospfd/ospf_abr.h"
47 #include "ospfd/ospf_dump.h"
48 #include "ospfd/ospf_sr.h"
49 #include "ospfd/ospf_ti_lfa.h"
50 #include "ospfd/ospf_errors.h"
51 #include "ospfd/ospf_apiserver.h"
52
53 /* Variables to ensure a SPF scheduled log message is printed only once */
54
55 static unsigned int spf_reason_flags = 0;
56
57 /* dummy vertex to flag "in spftree" */
58 static const struct vertex vertex_in_spftree = {};
59 #define LSA_SPF_IN_SPFTREE (struct vertex *)&vertex_in_spftree
60 #define LSA_SPF_NOT_EXPLORED NULL
61
62 static void ospf_clear_spf_reason_flags(void)
63 {
64 spf_reason_flags = 0;
65 }
66
67 static void ospf_spf_set_reason(ospf_spf_reason_t reason)
68 {
69 spf_reason_flags |= 1 << reason;
70 }
71
72 static void ospf_vertex_free(void *);
73
74 /*
75 * Heap related functions, for the managment of the candidates, to
76 * be used with pqueue.
77 */
78 static int vertex_cmp(const struct vertex *v1, const struct vertex *v2)
79 {
80 if (v1->distance != v2->distance)
81 return v1->distance - v2->distance;
82
83 if (v1->type != v2->type) {
84 switch (v1->type) {
85 case OSPF_VERTEX_NETWORK:
86 return -1;
87 case OSPF_VERTEX_ROUTER:
88 return 1;
89 }
90 }
91 return 0;
92 }
93 DECLARE_SKIPLIST_NONUNIQ(vertex_pqueue, struct vertex, pqi, vertex_cmp);
94
95 static void lsdb_clean_stat(struct ospf_lsdb *lsdb)
96 {
97 struct route_table *table;
98 struct route_node *rn;
99 struct ospf_lsa *lsa;
100 int i;
101
102 for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) {
103 table = lsdb->type[i].db;
104 for (rn = route_top(table); rn; rn = route_next(rn))
105 if ((lsa = (rn->info)) != NULL)
106 lsa->stat = LSA_SPF_NOT_EXPLORED;
107 }
108 }
109
110 static struct vertex_nexthop *vertex_nexthop_new(void)
111 {
112 return XCALLOC(MTYPE_OSPF_NEXTHOP, sizeof(struct vertex_nexthop));
113 }
114
115 static void vertex_nexthop_free(struct vertex_nexthop *nh)
116 {
117 XFREE(MTYPE_OSPF_NEXTHOP, nh);
118 }
119
120 /*
121 * Free the canonical nexthop objects for an area, ie the nexthop objects
122 * attached to the first-hop router vertices, and any intervening network
123 * vertices.
124 */
125 static void ospf_canonical_nexthops_free(struct vertex *root)
126 {
127 struct listnode *node, *nnode;
128 struct vertex *child;
129
130 for (ALL_LIST_ELEMENTS(root->children, node, nnode, child)) {
131 struct listnode *n2, *nn2;
132 struct vertex_parent *vp;
133
134 /*
135 * router vertices through an attached network each
136 * have a distinct (canonical / not inherited) nexthop
137 * which must be freed.
138 *
139 * A network vertex can only have router vertices as its
140 * children, so only one level of recursion is possible.
141 */
142 if (child->type == OSPF_VERTEX_NETWORK)
143 ospf_canonical_nexthops_free(child);
144
145 /* Free child nexthops pointing back to this root vertex */
146 for (ALL_LIST_ELEMENTS(child->parents, n2, nn2, vp)) {
147 if (vp->parent == root && vp->nexthop) {
148 vertex_nexthop_free(vp->nexthop);
149 vp->nexthop = NULL;
150 if (vp->local_nexthop) {
151 vertex_nexthop_free(vp->local_nexthop);
152 vp->local_nexthop = NULL;
153 }
154 }
155 }
156 }
157 }
158
159 /*
160 * TODO: Parent list should be excised, in favour of maintaining only
161 * vertex_nexthop, with refcounts.
162 */
163 static struct vertex_parent *vertex_parent_new(struct vertex *v, int backlink,
164 struct vertex_nexthop *hop,
165 struct vertex_nexthop *lhop)
166 {
167 struct vertex_parent *new;
168
169 new = XMALLOC(MTYPE_OSPF_VERTEX_PARENT, sizeof(struct vertex_parent));
170
171 new->parent = v;
172 new->backlink = backlink;
173 new->nexthop = hop;
174 new->local_nexthop = lhop;
175
176 return new;
177 }
178
179 static void vertex_parent_free(void *p)
180 {
181 XFREE(MTYPE_OSPF_VERTEX_PARENT, p);
182 }
183
184 int vertex_parent_cmp(void *aa, void *bb)
185 {
186 struct vertex_parent *a = aa, *b = bb;
187 return IPV4_ADDR_CMP(&a->nexthop->router, &b->nexthop->router);
188 }
189
190 static struct vertex *ospf_vertex_new(struct ospf_area *area,
191 struct ospf_lsa *lsa)
192 {
193 struct vertex *new;
194
195 new = XCALLOC(MTYPE_OSPF_VERTEX, sizeof(struct vertex));
196
197 new->flags = 0;
198 new->type = lsa->data->type;
199 new->id = lsa->data->id;
200 new->lsa = lsa->data;
201 new->children = list_new();
202 new->parents = list_new();
203 new->parents->del = vertex_parent_free;
204 new->parents->cmp = vertex_parent_cmp;
205 new->lsa_p = lsa;
206
207 lsa->stat = new;
208
209 listnode_add(area->spf_vertex_list, new);
210
211 if (IS_DEBUG_OSPF_EVENT)
212 zlog_debug("%s: Created %s vertex %pI4", __func__,
213 new->type == OSPF_VERTEX_ROUTER ? "Router"
214 : "Network",
215 &new->lsa->id);
216
217 return new;
218 }
219
220 static void ospf_vertex_free(void *data)
221 {
222 struct vertex *v = data;
223
224 if (IS_DEBUG_OSPF_EVENT)
225 zlog_debug("%s: Free %s vertex %pI4", __func__,
226 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
227 &v->lsa->id);
228
229 if (v->children)
230 list_delete(&v->children);
231
232 if (v->parents)
233 list_delete(&v->parents);
234
235 v->lsa = NULL;
236
237 XFREE(MTYPE_OSPF_VERTEX, v);
238 }
239
240 static void ospf_vertex_dump(const char *msg, struct vertex *v,
241 int print_parents, int print_children)
242 {
243 if (!IS_DEBUG_OSPF_EVENT)
244 return;
245
246 zlog_debug("%s %s vertex %pI4 distance %u flags %u", msg,
247 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
248 &v->lsa->id, v->distance, (unsigned int)v->flags);
249
250 if (print_parents) {
251 struct listnode *node;
252 struct vertex_parent *vp;
253
254 for (ALL_LIST_ELEMENTS_RO(v->parents, node, vp)) {
255 if (vp) {
256 zlog_debug(
257 "parent %pI4 backlink %d nexthop %pI4 lsa pos %d",
258 &vp->parent->lsa->id, vp->backlink,
259 &vp->nexthop->router,
260 vp->nexthop->lsa_pos);
261 }
262 }
263 }
264
265 if (print_children) {
266 struct listnode *cnode;
267 struct vertex *cv;
268
269 for (ALL_LIST_ELEMENTS_RO(v->children, cnode, cv))
270 ospf_vertex_dump(" child:", cv, 0, 0);
271 }
272 }
273
274
275 /* Add a vertex to the list of children in each of its parents. */
276 static void ospf_vertex_add_parent(struct vertex *v)
277 {
278 struct vertex_parent *vp;
279 struct listnode *node;
280
281 assert(v && v->parents);
282
283 for (ALL_LIST_ELEMENTS_RO(v->parents, node, vp)) {
284 assert(vp->parent && vp->parent->children);
285
286 /* No need to add two links from the same parent. */
287 if (listnode_lookup(vp->parent->children, v) == NULL)
288 listnode_add(vp->parent->children, v);
289 }
290 }
291
292 /* Find a vertex according to its router id */
293 struct vertex *ospf_spf_vertex_find(struct in_addr id, struct list *vertex_list)
294 {
295 struct listnode *node;
296 struct vertex *found;
297
298 for (ALL_LIST_ELEMENTS_RO(vertex_list, node, found)) {
299 if (found->id.s_addr == id.s_addr)
300 return found;
301 }
302
303 return NULL;
304 }
305
306 /* Find a vertex parent according to its router id */
307 struct vertex_parent *ospf_spf_vertex_parent_find(struct in_addr id,
308 struct vertex *vertex)
309 {
310 struct listnode *node;
311 struct vertex_parent *found;
312
313 for (ALL_LIST_ELEMENTS_RO(vertex->parents, node, found)) {
314 if (found->parent->id.s_addr == id.s_addr)
315 return found;
316 }
317
318 return NULL;
319 }
320
321 struct vertex *ospf_spf_vertex_by_nexthop(struct vertex *root,
322 struct in_addr *nexthop)
323 {
324 struct listnode *node;
325 struct vertex *child;
326 struct vertex_parent *vertex_parent;
327
328 for (ALL_LIST_ELEMENTS_RO(root->children, node, child)) {
329 vertex_parent = ospf_spf_vertex_parent_find(root->id, child);
330 if (vertex_parent->nexthop->router.s_addr == nexthop->s_addr)
331 return child;
332 }
333
334 return NULL;
335 }
336
337 /* Create a deep copy of a SPF vertex without children and parents */
338 static struct vertex *ospf_spf_vertex_copy(struct vertex *vertex)
339 {
340 struct vertex *copy;
341
342 copy = XCALLOC(MTYPE_OSPF_VERTEX, sizeof(struct vertex));
343
344 memcpy(copy, vertex, sizeof(struct vertex));
345 copy->parents = list_new();
346 copy->parents->del = vertex_parent_free;
347 copy->parents->cmp = vertex_parent_cmp;
348 copy->children = list_new();
349
350 return copy;
351 }
352
353 /* Create a deep copy of a SPF vertex_parent */
354 static struct vertex_parent *
355 ospf_spf_vertex_parent_copy(struct vertex_parent *vertex_parent)
356 {
357 struct vertex_parent *vertex_parent_copy;
358 struct vertex_nexthop *nexthop_copy, *local_nexthop_copy;
359
360 vertex_parent_copy =
361 XCALLOC(MTYPE_OSPF_VERTEX, sizeof(struct vertex_parent));
362
363 nexthop_copy = vertex_nexthop_new();
364 local_nexthop_copy = vertex_nexthop_new();
365
366 memcpy(vertex_parent_copy, vertex_parent, sizeof(struct vertex_parent));
367 memcpy(nexthop_copy, vertex_parent->nexthop,
368 sizeof(struct vertex_nexthop));
369 memcpy(local_nexthop_copy, vertex_parent->local_nexthop,
370 sizeof(struct vertex_nexthop));
371
372 vertex_parent_copy->nexthop = nexthop_copy;
373 vertex_parent_copy->local_nexthop = local_nexthop_copy;
374
375 return vertex_parent_copy;
376 }
377
378 /* Create a deep copy of a SPF tree */
379 void ospf_spf_copy(struct vertex *vertex, struct list *vertex_list)
380 {
381 struct listnode *node;
382 struct vertex *vertex_copy, *child, *child_copy, *parent_copy;
383 struct vertex_parent *vertex_parent, *vertex_parent_copy;
384
385 /* First check if the node is already in the vertex list */
386 vertex_copy = ospf_spf_vertex_find(vertex->id, vertex_list);
387 if (!vertex_copy) {
388 vertex_copy = ospf_spf_vertex_copy(vertex);
389 listnode_add(vertex_list, vertex_copy);
390 }
391
392 /* Copy all parents, create parent nodes if necessary */
393 for (ALL_LIST_ELEMENTS_RO(vertex->parents, node, vertex_parent)) {
394 parent_copy = ospf_spf_vertex_find(vertex_parent->parent->id,
395 vertex_list);
396 if (!parent_copy) {
397 parent_copy =
398 ospf_spf_vertex_copy(vertex_parent->parent);
399 listnode_add(vertex_list, parent_copy);
400 }
401 vertex_parent_copy = ospf_spf_vertex_parent_copy(vertex_parent);
402 vertex_parent_copy->parent = parent_copy;
403 listnode_add(vertex_copy->parents, vertex_parent_copy);
404 }
405
406 /* Copy all children, create child nodes if necessary */
407 for (ALL_LIST_ELEMENTS_RO(vertex->children, node, child)) {
408 child_copy = ospf_spf_vertex_find(child->id, vertex_list);
409 if (!child_copy) {
410 child_copy = ospf_spf_vertex_copy(child);
411 listnode_add(vertex_list, child_copy);
412 }
413 listnode_add(vertex_copy->children, child_copy);
414 }
415
416 /* Finally continue copying with child nodes */
417 for (ALL_LIST_ELEMENTS_RO(vertex->children, node, child))
418 ospf_spf_copy(child, vertex_list);
419 }
420
421 static void ospf_spf_remove_branch(struct vertex_parent *vertex_parent,
422 struct vertex *child,
423 struct list *vertex_list)
424 {
425 struct listnode *node, *nnode, *inner_node, *inner_nnode;
426 struct vertex *grandchild;
427 struct vertex_parent *vertex_parent_found;
428 bool has_more_links = false;
429
430 /*
431 * First check if there are more nexthops for that parent to that child
432 */
433 for (ALL_LIST_ELEMENTS_RO(child->parents, node, vertex_parent_found)) {
434 if (vertex_parent_found->parent->id.s_addr
435 == vertex_parent->parent->id.s_addr
436 && vertex_parent_found->nexthop->router.s_addr
437 != vertex_parent->nexthop->router.s_addr)
438 has_more_links = true;
439 }
440
441 /*
442 * No more links from that parent? Then delete the child from its
443 * children list.
444 */
445 if (!has_more_links)
446 listnode_delete(vertex_parent->parent->children, child);
447
448 /*
449 * Delete the vertex_parent from the child parents list, this needs to
450 * be done anyway.
451 */
452 listnode_delete(child->parents, vertex_parent);
453
454 /*
455 * Are there actually more parents left? If not, then delete the child!
456 * This is done by recursively removing the links to the grandchildren,
457 * such that finally the child can be removed without leaving unused
458 * partial branches.
459 */
460 if (child->parents->count == 0) {
461 for (ALL_LIST_ELEMENTS(child->children, node, nnode,
462 grandchild)) {
463 for (ALL_LIST_ELEMENTS(grandchild->parents, inner_node,
464 inner_nnode,
465 vertex_parent_found)) {
466 ospf_spf_remove_branch(vertex_parent_found,
467 grandchild, vertex_list);
468 }
469 }
470 listnode_delete(vertex_list, child);
471 ospf_vertex_free(child);
472 }
473 }
474
475 static int ospf_spf_remove_link(struct vertex *vertex, struct list *vertex_list,
476 struct router_lsa_link *link)
477 {
478 struct listnode *node, *inner_node;
479 struct vertex *child;
480 struct vertex_parent *vertex_parent;
481
482 /*
483 * Identify the node who shares a subnet (given by the link) with a
484 * child and remove the branch of this particular child.
485 */
486 for (ALL_LIST_ELEMENTS_RO(vertex->children, node, child)) {
487 for (ALL_LIST_ELEMENTS_RO(child->parents, inner_node,
488 vertex_parent)) {
489 if ((vertex_parent->local_nexthop->router.s_addr
490 & link->link_data.s_addr)
491 == (link->link_id.s_addr
492 & link->link_data.s_addr)) {
493 ospf_spf_remove_branch(vertex_parent, child,
494 vertex_list);
495 return 0;
496 }
497 }
498 }
499
500 /* No link found yet, move on recursively */
501 for (ALL_LIST_ELEMENTS_RO(vertex->children, node, child)) {
502 if (ospf_spf_remove_link(child, vertex_list, link) == 0)
503 return 0;
504 }
505
506 /* link was not removed yet */
507 return 1;
508 }
509
510 void ospf_spf_remove_resource(struct vertex *vertex, struct list *vertex_list,
511 struct protected_resource *resource)
512 {
513 struct listnode *node, *nnode;
514 struct vertex *found;
515 struct vertex_parent *vertex_parent;
516
517 switch (resource->type) {
518 case OSPF_TI_LFA_LINK_PROTECTION:
519 ospf_spf_remove_link(vertex, vertex_list, resource->link);
520 break;
521 case OSPF_TI_LFA_NODE_PROTECTION:
522 found = ospf_spf_vertex_find(resource->router_id, vertex_list);
523 if (!found)
524 break;
525
526 /*
527 * Remove the node by removing all links from its parents. Note
528 * that the child is automatically removed here with the last
529 * link from a parent, hence no explicit removal of the node.
530 */
531 for (ALL_LIST_ELEMENTS(found->parents, node, nnode,
532 vertex_parent))
533 ospf_spf_remove_branch(vertex_parent, found,
534 vertex_list);
535
536 break;
537 default:
538 /* do nothing */
539 break;
540 }
541 }
542
543 static void ospf_spf_init(struct ospf_area *area, struct ospf_lsa *root_lsa,
544 bool is_dry_run, bool is_root_node)
545 {
546 struct list *vertex_list;
547 struct vertex *v;
548
549 /* Create vertex list */
550 vertex_list = list_new();
551 vertex_list->del = ospf_vertex_free;
552 area->spf_vertex_list = vertex_list;
553
554 /* Create root node. */
555 v = ospf_vertex_new(area, root_lsa);
556 area->spf = v;
557
558 area->spf_dry_run = is_dry_run;
559 area->spf_root_node = is_root_node;
560
561 /* Reset ABR and ASBR router counts. */
562 area->abr_count = 0;
563 area->asbr_count = 0;
564 }
565
566 /* return index of link back to V from W, or -1 if no link found */
567 static int ospf_lsa_has_link(struct lsa_header *w, struct lsa_header *v)
568 {
569 unsigned int i, length;
570 struct router_lsa *rl;
571 struct network_lsa *nl;
572
573 /* In case of W is Network LSA. */
574 if (w->type == OSPF_NETWORK_LSA) {
575 if (v->type == OSPF_NETWORK_LSA)
576 return -1;
577
578 nl = (struct network_lsa *)w;
579 length = (ntohs(w->length) - OSPF_LSA_HEADER_SIZE - 4) / 4;
580
581 for (i = 0; i < length; i++)
582 if (IPV4_ADDR_SAME(&nl->routers[i], &v->id))
583 return i;
584 return -1;
585 }
586
587 /* In case of W is Router LSA. */
588 if (w->type == OSPF_ROUTER_LSA) {
589 rl = (struct router_lsa *)w;
590
591 length = ntohs(w->length);
592
593 for (i = 0; i < ntohs(rl->links)
594 && length >= sizeof(struct router_lsa);
595 i++, length -= 12) {
596 switch (rl->link[i].type) {
597 case LSA_LINK_TYPE_POINTOPOINT:
598 case LSA_LINK_TYPE_VIRTUALLINK:
599 /* Router LSA ID. */
600 if (v->type == OSPF_ROUTER_LSA
601 && IPV4_ADDR_SAME(&rl->link[i].link_id,
602 &v->id)) {
603 return i;
604 }
605 break;
606 case LSA_LINK_TYPE_TRANSIT:
607 /* Network LSA ID. */
608 if (v->type == OSPF_NETWORK_LSA
609 && IPV4_ADDR_SAME(&rl->link[i].link_id,
610 &v->id)) {
611 return i;
612 }
613 break;
614 case LSA_LINK_TYPE_STUB:
615 /* Stub can't lead anywhere, carry on */
616 continue;
617 default:
618 break;
619 }
620 }
621 }
622 return -1;
623 }
624
625 /*
626 * Find the next link after prev_link from v to w. If prev_link is
627 * NULL, return the first link from v to w. Ignore stub and virtual links;
628 * these link types will never be returned.
629 */
630 static struct router_lsa_link *
631 ospf_get_next_link(struct vertex *v, struct vertex *w,
632 struct router_lsa_link *prev_link)
633 {
634 uint8_t *p;
635 uint8_t *lim;
636 uint8_t lsa_type = LSA_LINK_TYPE_TRANSIT;
637 struct router_lsa_link *l;
638
639 if (w->type == OSPF_VERTEX_ROUTER)
640 lsa_type = LSA_LINK_TYPE_POINTOPOINT;
641
642 if (prev_link == NULL)
643 p = ((uint8_t *)v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
644 else {
645 p = (uint8_t *)prev_link;
646 p += (OSPF_ROUTER_LSA_LINK_SIZE
647 + (prev_link->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
648 }
649
650 lim = ((uint8_t *)v->lsa) + ntohs(v->lsa->length);
651
652 while (p < lim) {
653 l = (struct router_lsa_link *)p;
654
655 p += (OSPF_ROUTER_LSA_LINK_SIZE
656 + (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
657
658 if (l->m[0].type != lsa_type)
659 continue;
660
661 if (IPV4_ADDR_SAME(&l->link_id, &w->id))
662 return l;
663 }
664
665 return NULL;
666 }
667
668 static void ospf_spf_flush_parents(struct vertex *w)
669 {
670 struct vertex_parent *vp;
671 struct listnode *ln, *nn;
672
673 /* delete the existing nexthops */
674 for (ALL_LIST_ELEMENTS(w->parents, ln, nn, vp)) {
675 list_delete_node(w->parents, ln);
676 vertex_parent_free(vp);
677 }
678 }
679
680 /*
681 * Consider supplied next-hop for inclusion to the supplied list of
682 * equal-cost next-hops, adjust list as necessary.
683 */
684 static void ospf_spf_add_parent(struct vertex *v, struct vertex *w,
685 struct vertex_nexthop *newhop,
686 struct vertex_nexthop *newlhop,
687 unsigned int distance)
688 {
689 struct vertex_parent *vp, *wp;
690 struct listnode *node;
691
692 /* we must have a newhop, and a distance */
693 assert(v && w && newhop);
694 assert(distance);
695
696 /*
697 * IFF w has already been assigned a distance, then we shouldn't get
698 * here unless callers have determined V(l)->W is shortest /
699 * equal-shortest path (0 is a special case distance (no distance yet
700 * assigned)).
701 */
702 if (w->distance)
703 assert(distance <= w->distance);
704 else
705 w->distance = distance;
706
707 if (IS_DEBUG_OSPF_EVENT)
708 zlog_debug("%s: Adding %pI4 as parent of %pI4", __func__,
709 &v->lsa->id, &w->lsa->id);
710
711 /*
712 * Adding parent for a new, better path: flush existing parents from W.
713 */
714 if (distance < w->distance) {
715 if (IS_DEBUG_OSPF_EVENT)
716 zlog_debug(
717 "%s: distance %d better than %d, flushing existing parents",
718 __func__, distance, w->distance);
719 ospf_spf_flush_parents(w);
720 w->distance = distance;
721 }
722
723 /*
724 * new parent is <= existing parents, add it to parent list (if nexthop
725 * not on parent list)
726 */
727 for (ALL_LIST_ELEMENTS_RO(w->parents, node, wp)) {
728 if (memcmp(newhop, wp->nexthop, sizeof(*newhop)) == 0) {
729 if (IS_DEBUG_OSPF_EVENT)
730 zlog_debug(
731 "%s: ... nexthop already on parent list, skipping add",
732 __func__);
733 return;
734 }
735 }
736
737 vp = vertex_parent_new(v, ospf_lsa_has_link(w->lsa, v->lsa), newhop,
738 newlhop);
739 listnode_add_sort(w->parents, vp);
740
741 return;
742 }
743
744 static int match_stub_prefix(struct lsa_header *lsa, struct in_addr v_link_addr,
745 struct in_addr w_link_addr)
746 {
747 uint8_t *p, *lim;
748 struct router_lsa_link *l = NULL;
749 struct in_addr masked_lsa_addr;
750
751 if (lsa->type != OSPF_ROUTER_LSA)
752 return 0;
753
754 p = ((uint8_t *)lsa) + OSPF_LSA_HEADER_SIZE + 4;
755 lim = ((uint8_t *)lsa) + ntohs(lsa->length);
756
757 while (p < lim) {
758 l = (struct router_lsa_link *)p;
759 p += (OSPF_ROUTER_LSA_LINK_SIZE
760 + (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
761
762 if (l->m[0].type != LSA_LINK_TYPE_STUB)
763 continue;
764
765 masked_lsa_addr.s_addr =
766 (l->link_id.s_addr & l->link_data.s_addr);
767
768 /* check that both links belong to the same stub subnet */
769 if ((masked_lsa_addr.s_addr
770 == (v_link_addr.s_addr & l->link_data.s_addr))
771 && (masked_lsa_addr.s_addr
772 == (w_link_addr.s_addr & l->link_data.s_addr)))
773 return 1;
774 }
775
776 return 0;
777 }
778
779 /*
780 * 16.1.1. Calculate nexthop from root through V (parent) to
781 * vertex W (destination), with given distance from root->W.
782 *
783 * The link must be supplied if V is the root vertex. In all other cases
784 * it may be NULL.
785 *
786 * Note that this function may fail, hence the state of the destination
787 * vertex, W, should /not/ be modified in a dependent manner until
788 * this function returns. This function will update the W vertex with the
789 * provided distance as appropriate.
790 */
791 static unsigned int ospf_nexthop_calculation(struct ospf_area *area,
792 struct vertex *v, struct vertex *w,
793 struct router_lsa_link *l,
794 unsigned int distance, int lsa_pos)
795 {
796 struct listnode *node, *nnode;
797 struct vertex_nexthop *nh, *lnh;
798 struct vertex_parent *vp;
799 unsigned int added = 0;
800
801 if (IS_DEBUG_OSPF_EVENT) {
802 zlog_debug("ospf_nexthop_calculation(): Start");
803 ospf_vertex_dump("V (parent):", v, 1, 1);
804 ospf_vertex_dump("W (dest) :", w, 1, 1);
805 zlog_debug("V->W distance: %d", distance);
806 }
807
808 if (v == area->spf) {
809 /*
810 * 16.1.1 para 4. In the first case, the parent vertex (V) is
811 * the root (the calculating router itself). This means that
812 * the destination is either a directly connected network or
813 * directly connected router. The outgoing interface in this
814 * case is simply the OSPF interface connecting to the
815 * destination network/router.
816 */
817
818 /* we *must* be supplied with the link data */
819 assert(l != NULL);
820
821 if (IS_DEBUG_OSPF_EVENT)
822 zlog_debug(
823 "%s: considering link type:%d link_id:%pI4 link_data:%pI4",
824 __func__, l->m[0].type, &l->link_id,
825 &l->link_data);
826
827 if (w->type == OSPF_VERTEX_ROUTER) {
828 /*
829 * l is a link from v to w l2 will be link from w to v
830 */
831 struct router_lsa_link *l2 = NULL;
832
833 if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT) {
834 struct ospf_interface *oi = NULL;
835 struct in_addr nexthop = {.s_addr = 0};
836
837 if (area->spf_root_node) {
838 oi = ospf_if_lookup_by_lsa_pos(area,
839 lsa_pos);
840 if (!oi) {
841 zlog_debug(
842 "%s: OI not found in LSA: lsa_pos: %d link_id:%pI4 link_data:%pI4",
843 __func__, lsa_pos,
844 &l->link_id,
845 &l->link_data);
846 return 0;
847 }
848 }
849
850 /*
851 * If the destination is a router which connects
852 * to the calculating router via a
853 * Point-to-MultiPoint network, the
854 * destination's next hop IP address(es) can be
855 * determined by examining the destination's
856 * router-LSA: each link pointing back to the
857 * calculating router and having a Link Data
858 * field belonging to the Point-to-MultiPoint
859 * network provides an IP address of the next
860 * hop router.
861 *
862 * At this point l is a link from V to W, and V
863 * is the root ("us"). If it is a point-to-
864 * multipoint interface, then look through the
865 * links in the opposite direction (W to V).
866 * If any of them have an address that lands
867 * within the subnet declared by the PtMP link,
868 * then that link is a constituent of the PtMP
869 * link, and its address is a nexthop address
870 * for V.
871 *
872 * Note for point-to-point interfaces:
873 *
874 * Having nexthop = 0 (as proposed in the RFC)
875 * is tempting, but NOT acceptable. It breaks
876 * AS-External routes with a forwarding address,
877 * since ospf_ase_complete_direct_routes() will
878 * mistakenly assume we've reached the last hop
879 * and should place the forwarding address as
880 * nexthop. Also, users may configure multi-
881 * access links in p2p mode, so we need the IP
882 * to ARP the nexthop.
883 *
884 * If the calculating router is the SPF root
885 * node and the link is P2P then access the
886 * interface information directly. This can be
887 * crucial when e.g. IP unnumbered is used
888 * where 'correct' nexthop information are not
889 * available via Router LSAs.
890 *
891 * Otherwise handle P2P and P2MP the same way
892 * as described above using a reverse lookup to
893 * figure out the nexthop.
894 */
895
896 /*
897 * HACK: we don't know (yet) how to distinguish
898 * between P2P and P2MP interfaces by just
899 * looking at LSAs, which is important for
900 * TI-LFA since you want to do SPF calculations
901 * from the perspective of other nodes. Since
902 * TI-LFA is currently not implemented for P2MP
903 * we just check here if it is enabled and then
904 * blindly assume that P2P is used. Ultimately
905 * the interface code needs to be removed
906 * somehow.
907 */
908 if (area->ospf->ti_lfa_enabled
909 || (oi && oi->type == OSPF_IFTYPE_POINTOPOINT)
910 || (oi && oi->type == OSPF_IFTYPE_POINTOMULTIPOINT
911 && oi->address->prefixlen == IPV4_MAX_BITLEN)) {
912 struct ospf_neighbor *nbr_w = NULL;
913
914 /* Calculating node is root node, link
915 * is P2P */
916 if (area->spf_root_node) {
917 nbr_w = ospf_nbr_lookup_by_routerid(
918 oi->nbrs, &l->link_id);
919 if (nbr_w) {
920 added = 1;
921 nexthop = nbr_w->src;
922 }
923 }
924
925 /* Reverse lookup */
926 if (!added) {
927 while ((l2 = ospf_get_next_link(
928 w, v, l2))) {
929 if (match_stub_prefix(
930 v->lsa,
931 l->link_data,
932 l2->link_data)) {
933 added = 1;
934 nexthop =
935 l2->link_data;
936 break;
937 }
938 }
939 }
940 } else if (oi && oi->type
941 == OSPF_IFTYPE_POINTOMULTIPOINT) {
942 struct prefix_ipv4 la;
943
944 la.family = AF_INET;
945 la.prefixlen = oi->address->prefixlen;
946
947 /*
948 * V links to W on PtMP interface;
949 * find the interface address on W
950 */
951 while ((l2 = ospf_get_next_link(w, v,
952 l2))) {
953 la.prefix = l2->link_data;
954
955 if (prefix_cmp((struct prefix
956 *)&la,
957 oi->address)
958 != 0)
959 continue;
960 added = 1;
961 nexthop = l2->link_data;
962 break;
963 }
964 }
965
966 if (added) {
967 nh = vertex_nexthop_new();
968 nh->router = nexthop;
969 nh->lsa_pos = lsa_pos;
970
971 /*
972 * Since v is the root the nexthop and
973 * local nexthop are the same.
974 */
975 lnh = vertex_nexthop_new();
976 memcpy(lnh, nh,
977 sizeof(struct vertex_nexthop));
978
979 ospf_spf_add_parent(v, w, nh, lnh,
980 distance);
981 return 1;
982 } else
983 zlog_info(
984 "%s: could not determine nexthop for link %s",
985 __func__, oi ? oi->ifp->name : "");
986 } /* end point-to-point link from V to W */
987 else if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK) {
988 /*
989 * VLink implementation limitations:
990 * a) vl_data can only reference one nexthop,
991 * so no ECMP to backbone through VLinks.
992 * Though transit-area summaries may be
993 * considered, and those can be ECMP.
994 * b) We can only use /one/ VLink, even if
995 * multiple ones exist this router through
996 * multiple transit-areas.
997 */
998
999 struct ospf_vl_data *vl_data;
1000
1001 vl_data = ospf_vl_lookup(area->ospf, NULL,
1002 l->link_id);
1003
1004 if (vl_data
1005 && CHECK_FLAG(vl_data->flags,
1006 OSPF_VL_FLAG_APPROVED)) {
1007 nh = vertex_nexthop_new();
1008 nh->router = vl_data->nexthop.router;
1009 nh->lsa_pos = vl_data->nexthop.lsa_pos;
1010
1011 /*
1012 * Since v is the root the nexthop and
1013 * local nexthop are the same.
1014 */
1015 lnh = vertex_nexthop_new();
1016 memcpy(lnh, nh,
1017 sizeof(struct vertex_nexthop));
1018
1019 ospf_spf_add_parent(v, w, nh, lnh,
1020 distance);
1021 return 1;
1022 } else
1023 zlog_info(
1024 "ospf_nexthop_calculation(): vl_data for VL link not found");
1025 } /* end virtual-link from V to W */
1026 return 0;
1027 } /* end W is a Router vertex */
1028 else {
1029 assert(w->type == OSPF_VERTEX_NETWORK);
1030
1031 nh = vertex_nexthop_new();
1032 nh->router.s_addr = 0; /* Nexthop not required */
1033 nh->lsa_pos = lsa_pos;
1034
1035 /*
1036 * Since v is the root the nexthop and
1037 * local nexthop are the same.
1038 */
1039 lnh = vertex_nexthop_new();
1040 memcpy(lnh, nh, sizeof(struct vertex_nexthop));
1041
1042 ospf_spf_add_parent(v, w, nh, lnh, distance);
1043 return 1;
1044 }
1045 } /* end V is the root */
1046 /* Check if W's parent is a network connected to root. */
1047 else if (v->type == OSPF_VERTEX_NETWORK) {
1048 /* See if any of V's parents are the root. */
1049 for (ALL_LIST_ELEMENTS(v->parents, node, nnode, vp)) {
1050 if (vp->parent == area->spf) {
1051 /*
1052 * 16.1.1 para 5. ...the parent vertex is a
1053 * network that directly connects the
1054 * calculating router to the destination
1055 * router. The list of next hops is then
1056 * determined by examining the destination's
1057 * router-LSA ...
1058 */
1059
1060 assert(w->type == OSPF_VERTEX_ROUTER);
1061 while ((l = ospf_get_next_link(w, v, l))) {
1062 /*
1063 * ... For each link in the router-LSA
1064 * that points back to the parent
1065 * network, the link's Link Data field
1066 * provides the IP address of a next hop
1067 * router. The outgoing interface to use
1068 * can then be derived from the next
1069 * hop IP address (or it can be
1070 * inherited from the parent network).
1071 */
1072 nh = vertex_nexthop_new();
1073 nh->router = l->link_data;
1074 nh->lsa_pos = vp->nexthop->lsa_pos;
1075
1076 /*
1077 * Since v is the root the nexthop and
1078 * local nexthop are the same.
1079 */
1080 lnh = vertex_nexthop_new();
1081 memcpy(lnh, nh,
1082 sizeof(struct vertex_nexthop));
1083
1084 added = 1;
1085 ospf_spf_add_parent(v, w, nh, lnh,
1086 distance);
1087 }
1088 /*
1089 * Note lack of return is deliberate. See next
1090 * comment.
1091 */
1092 }
1093 }
1094 /*
1095 * NB: This code is non-trivial.
1096 *
1097 * E.g. it is not enough to know that V connects to the root. It
1098 * is also important that the while above, looping through all
1099 * links from W->V found at least one link, so that we know
1100 * there is bi-directional connectivity between V and W (which
1101 * need not be the case, e.g. when OSPF has not yet converged
1102 * fully). Otherwise, if we /always/ return here, without having
1103 * checked that root->V->-W actually resulted in a valid nexthop
1104 * being created, then we we will prevent SPF from finding/using
1105 * higher cost paths.
1106 *
1107 * It is important, if root->V->W has not been added, that we
1108 * continue through to the intervening-router nexthop code
1109 * below. So as to ensure other paths to V may be used. This
1110 * avoids unnecessary blackholes while OSPF is converging.
1111 *
1112 * I.e. we may have arrived at this function, examining V -> W,
1113 * via workable paths other than root -> V, and it's important
1114 * to avoid getting "confused" by non-working root->V->W path
1115 * - it's important to *not* lose the working non-root paths,
1116 * just because of a non-viable root->V->W.
1117 */
1118 if (added)
1119 return added;
1120 }
1121
1122 /*
1123 * 16.1.1 para 4. If there is at least one intervening router in the
1124 * current shortest path between the destination and the root, the
1125 * destination simply inherits the set of next hops from the
1126 * parent.
1127 */
1128 if (IS_DEBUG_OSPF_EVENT)
1129 zlog_debug("%s: Intervening routers, adding parent(s)",
1130 __func__);
1131
1132 for (ALL_LIST_ELEMENTS(v->parents, node, nnode, vp)) {
1133 added = 1;
1134
1135 /*
1136 * The nexthop is inherited, but the local nexthop still needs
1137 * to be created.
1138 */
1139 if (l) {
1140 lnh = vertex_nexthop_new();
1141 lnh->router = l->link_data;
1142 lnh->lsa_pos = lsa_pos;
1143 } else {
1144 lnh = NULL;
1145 }
1146
1147 ospf_spf_add_parent(v, w, vp->nexthop, lnh, distance);
1148 }
1149
1150 return added;
1151 }
1152
1153 static int ospf_spf_is_protected_resource(struct ospf_area *area,
1154 struct router_lsa_link *link,
1155 struct lsa_header *lsa)
1156 {
1157 uint8_t *p, *lim;
1158 struct router_lsa_link *p_link;
1159 struct router_lsa_link *l = NULL;
1160 struct in_addr router_id;
1161 int link_type;
1162
1163 if (!area->spf_protected_resource)
1164 return 0;
1165
1166 link_type = link->m[0].type;
1167
1168 switch (area->spf_protected_resource->type) {
1169 case OSPF_TI_LFA_LINK_PROTECTION:
1170 p_link = area->spf_protected_resource->link;
1171 if (!p_link)
1172 return 0;
1173
1174 /* For P2P: check if the link belongs to the same subnet */
1175 if (link_type == LSA_LINK_TYPE_POINTOPOINT
1176 && (p_link->link_id.s_addr & p_link->link_data.s_addr)
1177 == (link->link_data.s_addr
1178 & p_link->link_data.s_addr))
1179 return 1;
1180
1181 /* For stub: check if this the same subnet */
1182 if (link_type == LSA_LINK_TYPE_STUB
1183 && (p_link->link_id.s_addr == link->link_id.s_addr)
1184 && (p_link->link_data.s_addr == link->link_data.s_addr))
1185 return 1;
1186
1187 break;
1188 case OSPF_TI_LFA_NODE_PROTECTION:
1189 router_id = area->spf_protected_resource->router_id;
1190 if (router_id.s_addr == INADDR_ANY)
1191 return 0;
1192
1193 /* For P2P: check if the link leads to the protected node */
1194 if (link_type == LSA_LINK_TYPE_POINTOPOINT
1195 && link->link_id.s_addr == router_id.s_addr)
1196 return 1;
1197
1198 /* The rest is about stub links! */
1199 if (link_type != LSA_LINK_TYPE_STUB)
1200 return 0;
1201
1202 /*
1203 * Check if there's a P2P link in the router LSA with the
1204 * corresponding link data in the same subnet.
1205 */
1206
1207 p = ((uint8_t *)lsa) + OSPF_LSA_HEADER_SIZE + 4;
1208 lim = ((uint8_t *)lsa) + ntohs(lsa->length);
1209
1210 while (p < lim) {
1211 l = (struct router_lsa_link *)p;
1212 p += (OSPF_ROUTER_LSA_LINK_SIZE
1213 + (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
1214
1215 /* We only care about P2P with the proper link id */
1216 if ((l->m[0].type != LSA_LINK_TYPE_POINTOPOINT)
1217 || (l->link_id.s_addr != router_id.s_addr))
1218 continue;
1219
1220 /* Link data in the subnet given by the link? */
1221 if ((link->link_id.s_addr & link->link_data.s_addr)
1222 == (l->link_data.s_addr & link->link_data.s_addr))
1223 return 1;
1224 }
1225
1226 break;
1227 case OSPF_TI_LFA_UNDEFINED_PROTECTION:
1228 break;
1229 }
1230
1231 return 0;
1232 }
1233
1234 /*
1235 * For TI-LFA we need the reverse SPF for Q spaces. The reverse SPF is created
1236 * by honoring the weight of the reverse 'edge', e.g. the edge from W to V, and
1237 * NOT the weight of the 'edge' from V to W as usual. Hence we need to find the
1238 * corresponding link in the LSA of W and extract the particular weight.
1239 *
1240 * TODO: Only P2P supported by now!
1241 */
1242 static uint16_t get_reverse_distance(struct vertex *v,
1243 struct router_lsa_link *l,
1244 struct ospf_lsa *w_lsa)
1245 {
1246 uint8_t *p, *lim;
1247 struct router_lsa_link *w_link;
1248 uint16_t distance = 0;
1249
1250 assert(w_lsa && w_lsa->data);
1251
1252 p = ((uint8_t *)w_lsa->data) + OSPF_LSA_HEADER_SIZE + 4;
1253 lim = ((uint8_t *)w_lsa->data) + ntohs(w_lsa->data->length);
1254
1255 while (p < lim) {
1256 w_link = (struct router_lsa_link *)p;
1257 p += (OSPF_ROUTER_LSA_LINK_SIZE
1258 + (w_link->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
1259
1260 /* Only care about P2P with link ID equal to V's router id */
1261 if (w_link->m[0].type == LSA_LINK_TYPE_POINTOPOINT
1262 && w_link->link_id.s_addr == v->id.s_addr) {
1263 distance = ntohs(w_link->m[0].metric);
1264 break;
1265 }
1266 }
1267
1268 /*
1269 * This might happen if the LSA for W is not complete yet. In this
1270 * case we take the weight of the 'forward' link from V. When the LSA
1271 * for W is completed the reverse SPF is run again anyway.
1272 */
1273 if (distance == 0)
1274 distance = ntohs(l->m[0].metric);
1275
1276 if (IS_DEBUG_OSPF_EVENT)
1277 zlog_debug("%s: reversed distance is %u", __func__, distance);
1278
1279 return distance;
1280 }
1281
1282 /*
1283 * RFC2328 16.1 (2).
1284 * v is on the SPF tree. Examine the links in v's LSA. Update the list of
1285 * candidates with any vertices not already on the list. If a lower-cost path
1286 * is found to a vertex already on the candidate list, store the new cost.
1287 */
1288 static void ospf_spf_next(struct vertex *v, struct ospf_area *area,
1289 struct vertex_pqueue_head *candidate)
1290 {
1291 struct ospf_lsa *w_lsa = NULL;
1292 uint8_t *p;
1293 uint8_t *lim;
1294 struct router_lsa_link *l = NULL;
1295 struct in_addr *r;
1296 int type = 0, lsa_pos = -1, lsa_pos_next = 0;
1297 uint16_t link_distance;
1298
1299 /*
1300 * If this is a router-LSA, and bit V of the router-LSA (see Section
1301 * A.4.2:RFC2328) is set, set Area A's TransitCapability to true.
1302 */
1303 if (v->type == OSPF_VERTEX_ROUTER) {
1304 if (IS_ROUTER_LSA_VIRTUAL((struct router_lsa *)v->lsa))
1305 area->transit = OSPF_TRANSIT_TRUE;
1306 }
1307
1308 if (IS_DEBUG_OSPF_EVENT)
1309 zlog_debug("%s: Next vertex of %s vertex %pI4", __func__,
1310 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
1311 &v->lsa->id);
1312
1313 p = ((uint8_t *)v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
1314 lim = ((uint8_t *)v->lsa) + ntohs(v->lsa->length);
1315
1316 while (p < lim) {
1317 struct vertex *w;
1318 unsigned int distance;
1319
1320 /* In case of V is Router-LSA. */
1321 if (v->lsa->type == OSPF_ROUTER_LSA) {
1322 l = (struct router_lsa_link *)p;
1323
1324 lsa_pos = lsa_pos_next; /* LSA link position */
1325 lsa_pos_next++;
1326
1327 p += (OSPF_ROUTER_LSA_LINK_SIZE
1328 + (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
1329
1330 /*
1331 * (a) If this is a link to a stub network, examine the
1332 * next link in V's LSA. Links to stub networks will
1333 * be considered in the second stage of the shortest
1334 * path calculation.
1335 */
1336 if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB)
1337 continue;
1338
1339 /*
1340 * Don't process TI-LFA protected resources.
1341 *
1342 * TODO: Replace this by a proper solution, e.g. remove
1343 * corresponding links from the LSDB and run the SPF
1344 * algo with the stripped-down LSDB.
1345 */
1346 if (ospf_spf_is_protected_resource(area, l, v->lsa))
1347 continue;
1348
1349 /*
1350 * (b) Otherwise, W is a transit vertex (router or
1351 * transit network). Look up the vertex W's LSA
1352 * (router-LSA or network-LSA) in Area A's link state
1353 * database.
1354 */
1355 switch (type) {
1356 case LSA_LINK_TYPE_POINTOPOINT:
1357 case LSA_LINK_TYPE_VIRTUALLINK:
1358 if (type == LSA_LINK_TYPE_VIRTUALLINK
1359 && IS_DEBUG_OSPF_EVENT)
1360 zlog_debug(
1361 "looking up LSA through VL: %pI4",
1362 &l->link_id);
1363 w_lsa = ospf_lsa_lookup(area->ospf, area,
1364 OSPF_ROUTER_LSA,
1365 l->link_id, l->link_id);
1366 if (w_lsa && IS_DEBUG_OSPF_EVENT)
1367 zlog_debug("found Router LSA %pI4",
1368 &l->link_id);
1369 break;
1370 case LSA_LINK_TYPE_TRANSIT:
1371 if (IS_DEBUG_OSPF_EVENT)
1372 zlog_debug(
1373 "Looking up Network LSA, ID: %pI4",
1374 &l->link_id);
1375 w_lsa = ospf_lsa_lookup_by_id(
1376 area, OSPF_NETWORK_LSA, l->link_id);
1377 if (w_lsa && IS_DEBUG_OSPF_EVENT)
1378 zlog_debug("found the LSA");
1379 break;
1380 default:
1381 flog_warn(EC_OSPF_LSA,
1382 "Invalid LSA link type %d", type);
1383 continue;
1384 }
1385
1386 /*
1387 * For TI-LFA we might need the reverse SPF.
1388 * Currently only works with P2P!
1389 */
1390 if (type == LSA_LINK_TYPE_POINTOPOINT
1391 && area->spf_reversed)
1392 link_distance =
1393 get_reverse_distance(v, l, w_lsa);
1394 else
1395 link_distance = ntohs(l->m[0].metric);
1396
1397 /* step (d) below */
1398 distance = v->distance + link_distance;
1399 } else {
1400 /* In case of V is Network-LSA. */
1401 r = (struct in_addr *)p;
1402 p += sizeof(struct in_addr);
1403
1404 /* Lookup the vertex W's LSA. */
1405 w_lsa = ospf_lsa_lookup_by_id(area, OSPF_ROUTER_LSA,
1406 *r);
1407 if (w_lsa && IS_DEBUG_OSPF_EVENT)
1408 zlog_debug("found Router LSA %pI4",
1409 &w_lsa->data->id);
1410
1411 /* step (d) below */
1412 distance = v->distance;
1413 }
1414
1415 /*
1416 * (b cont.) If the LSA does not exist, or its LS age is equal
1417 * to MaxAge, or it does not have a link back to vertex V,
1418 * examine the next link in V's LSA.[23]
1419 */
1420 if (w_lsa == NULL) {
1421 if (IS_DEBUG_OSPF_EVENT)
1422 zlog_debug("No LSA found");
1423 continue;
1424 }
1425
1426 if (IS_LSA_MAXAGE(w_lsa)) {
1427 if (IS_DEBUG_OSPF_EVENT)
1428 zlog_debug("LSA is MaxAge");
1429 continue;
1430 }
1431
1432 if (ospf_lsa_has_link(w_lsa->data, v->lsa) < 0) {
1433 if (IS_DEBUG_OSPF_EVENT)
1434 zlog_debug("The LSA doesn't have a link back");
1435 continue;
1436 }
1437
1438 /*
1439 * (c) If vertex W is already on the shortest-path tree, examine
1440 * the next link in the LSA.
1441 */
1442 if (w_lsa->stat == LSA_SPF_IN_SPFTREE) {
1443 if (IS_DEBUG_OSPF_EVENT)
1444 zlog_debug("The LSA is already in SPF");
1445 continue;
1446 }
1447
1448 /*
1449 * (d) Calculate the link state cost D of the resulting path
1450 * from the root to vertex W. D is equal to the sum of the link
1451 * state cost of the (already calculated) shortest path to
1452 * vertex V and the advertised cost of the link between vertices
1453 * V and W. If D is:
1454 */
1455
1456 /* calculate link cost D -- moved above */
1457
1458 /* Is there already vertex W in candidate list? */
1459 if (w_lsa->stat == LSA_SPF_NOT_EXPLORED) {
1460 /* prepare vertex W. */
1461 w = ospf_vertex_new(area, w_lsa);
1462
1463 /* Calculate nexthop to W. */
1464 if (ospf_nexthop_calculation(area, v, w, l, distance,
1465 lsa_pos))
1466 vertex_pqueue_add(candidate, w);
1467 else if (IS_DEBUG_OSPF_EVENT)
1468 zlog_debug("Nexthop Calc failed");
1469 } else if (w_lsa->stat != LSA_SPF_IN_SPFTREE) {
1470 w = w_lsa->stat;
1471 if (w->distance < distance) {
1472 continue;
1473 }
1474 else if (w->distance == distance) {
1475 /*
1476 * Found an equal-cost path to W.
1477 * Calculate nexthop of to W from V.
1478 */
1479 ospf_nexthop_calculation(area, v, w, l,
1480 distance, lsa_pos);
1481 }
1482 else {
1483 /*
1484 * Found a lower-cost path to W.
1485 * nexthop_calculation is conditional, if it
1486 * finds valid nexthop it will call
1487 * spf_add_parents, which will flush the old
1488 * parents.
1489 */
1490 vertex_pqueue_del(candidate, w);
1491 ospf_nexthop_calculation(area, v, w, l,
1492 distance, lsa_pos);
1493 vertex_pqueue_add(candidate, w);
1494 }
1495 } /* end W is already on the candidate list */
1496 } /* end loop over the links in V's LSA */
1497 }
1498
1499 static void ospf_spf_dump(struct vertex *v, int i)
1500 {
1501 struct listnode *cnode;
1502 struct listnode *nnode;
1503 struct vertex_parent *parent;
1504
1505 if (v->type == OSPF_VERTEX_ROUTER) {
1506 if (IS_DEBUG_OSPF_EVENT)
1507 zlog_debug("SPF Result: %d [R] %pI4", i,
1508 &v->lsa->id);
1509 } else {
1510 struct network_lsa *lsa = (struct network_lsa *)v->lsa;
1511 if (IS_DEBUG_OSPF_EVENT)
1512 zlog_debug("SPF Result: %d [N] %pI4/%d", i,
1513 &v->lsa->id,
1514 ip_masklen(lsa->mask));
1515 }
1516
1517 if (IS_DEBUG_OSPF_EVENT)
1518 for (ALL_LIST_ELEMENTS_RO(v->parents, nnode, parent)) {
1519 zlog_debug(" nexthop %p %pI4 %d",
1520 (void *)parent->nexthop,
1521 &parent->nexthop->router,
1522 parent->nexthop->lsa_pos);
1523 }
1524
1525 i++;
1526
1527 for (ALL_LIST_ELEMENTS_RO(v->children, cnode, v))
1528 ospf_spf_dump(v, i);
1529 }
1530
1531 void ospf_spf_print(struct vty *vty, struct vertex *v, int i)
1532 {
1533 struct listnode *cnode;
1534 struct listnode *nnode;
1535 struct vertex_parent *parent;
1536
1537 if (v->type == OSPF_VERTEX_ROUTER) {
1538 vty_out(vty, "SPF Result: depth %d [R] %pI4\n", i, &v->lsa->id);
1539 } else {
1540 struct network_lsa *lsa = (struct network_lsa *)v->lsa;
1541 vty_out(vty, "SPF Result: depth %d [N] %pI4/%d\n", i,
1542 &v->lsa->id, ip_masklen(lsa->mask));
1543 }
1544
1545 for (ALL_LIST_ELEMENTS_RO(v->parents, nnode, parent)) {
1546 vty_out(vty,
1547 " nexthop %pI4 lsa pos %d -- local nexthop %pI4 lsa pos %d\n",
1548 &parent->nexthop->router, parent->nexthop->lsa_pos,
1549 &parent->local_nexthop->router,
1550 parent->local_nexthop->lsa_pos);
1551 }
1552
1553 i++;
1554
1555 for (ALL_LIST_ELEMENTS_RO(v->children, cnode, v))
1556 ospf_spf_print(vty, v, i);
1557 }
1558
1559 /* Second stage of SPF calculation. */
1560 static void ospf_spf_process_stubs(struct ospf_area *area, struct vertex *v,
1561 struct route_table *rt, int parent_is_root)
1562 {
1563 struct listnode *cnode, *cnnode;
1564 struct vertex *child;
1565
1566 if (IS_DEBUG_OSPF_EVENT)
1567 zlog_debug("ospf_process_stub():processing stubs for area %pI4",
1568 &area->area_id);
1569
1570 if (v->type == OSPF_VERTEX_ROUTER) {
1571 uint8_t *p;
1572 uint8_t *lim;
1573 struct router_lsa_link *l;
1574 struct router_lsa *router_lsa;
1575 int lsa_pos = 0;
1576
1577 if (IS_DEBUG_OSPF_EVENT)
1578 zlog_debug(
1579 "ospf_process_stubs():processing router LSA, id: %pI4",
1580 &v->lsa->id);
1581
1582 router_lsa = (struct router_lsa *)v->lsa;
1583
1584 if (IS_DEBUG_OSPF_EVENT)
1585 zlog_debug(
1586 "ospf_process_stubs(): we have %d links to process",
1587 ntohs(router_lsa->links));
1588
1589 p = ((uint8_t *)v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
1590 lim = ((uint8_t *)v->lsa) + ntohs(v->lsa->length);
1591
1592 while (p < lim) {
1593 l = (struct router_lsa_link *)p;
1594
1595 p += (OSPF_ROUTER_LSA_LINK_SIZE
1596 + (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
1597
1598 /* Don't process TI-LFA protected resources */
1599 if (l->m[0].type == LSA_LINK_TYPE_STUB
1600 && !ospf_spf_is_protected_resource(area, l, v->lsa))
1601 ospf_intra_add_stub(rt, l, v, area,
1602 parent_is_root, lsa_pos);
1603 lsa_pos++;
1604 }
1605 }
1606
1607 ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1,
1608 1);
1609
1610 for (ALL_LIST_ELEMENTS(v->children, cnode, cnnode, child)) {
1611 if (CHECK_FLAG(child->flags, OSPF_VERTEX_PROCESSED))
1612 continue;
1613
1614 /*
1615 * The first level of routers connected to the root
1616 * should have 'parent_is_root' set, including those
1617 * connected via a network vertex.
1618 */
1619 if (area->spf == v)
1620 parent_is_root = 1;
1621 else if (v->type == OSPF_VERTEX_ROUTER)
1622 parent_is_root = 0;
1623
1624 ospf_spf_process_stubs(area, child, rt, parent_is_root);
1625
1626 SET_FLAG(child->flags, OSPF_VERTEX_PROCESSED);
1627 }
1628 }
1629
1630 void ospf_rtrs_free(struct route_table *rtrs)
1631 {
1632 struct route_node *rn;
1633 struct list *or_list;
1634 struct ospf_route * or ;
1635 struct listnode *node, *nnode;
1636
1637 if (IS_DEBUG_OSPF_EVENT)
1638 zlog_debug("Route: Router Routing Table free");
1639
1640 for (rn = route_top(rtrs); rn; rn = route_next(rn))
1641 if ((or_list = rn->info) != NULL) {
1642 for (ALL_LIST_ELEMENTS(or_list, node, nnode, or))
1643 ospf_route_free(or);
1644
1645 list_delete(&or_list);
1646
1647 /* Unlock the node. */
1648 rn->info = NULL;
1649 route_unlock_node(rn);
1650 }
1651
1652 route_table_finish(rtrs);
1653 }
1654
1655 void ospf_spf_cleanup(struct vertex *spf, struct list *vertex_list)
1656 {
1657 /*
1658 * Free nexthop information, canonical versions of which are
1659 * attached the first level of router vertices attached to the
1660 * root vertex, see ospf_nexthop_calculation.
1661 */
1662 if (spf)
1663 ospf_canonical_nexthops_free(spf);
1664
1665 /* Free SPF vertices list with deconstructor ospf_vertex_free. */
1666 if (vertex_list)
1667 list_delete(&vertex_list);
1668 }
1669
1670 /* Calculating the shortest-path tree for an area, see RFC2328 16.1. */
1671 void ospf_spf_calculate(struct ospf_area *area, struct ospf_lsa *root_lsa,
1672 struct route_table *new_table,
1673 struct route_table *all_rtrs,
1674 struct route_table *new_rtrs, bool is_dry_run,
1675 bool is_root_node)
1676 {
1677 struct vertex_pqueue_head candidate;
1678 struct vertex *v;
1679
1680 if (IS_DEBUG_OSPF_EVENT) {
1681 zlog_debug("ospf_spf_calculate: Start");
1682 zlog_debug("ospf_spf_calculate: running Dijkstra for area %pI4",
1683 &area->area_id);
1684 }
1685
1686 /*
1687 * If the router LSA of the root is not yet allocated, return this
1688 * area's calculation. In the 'usual' case the root_lsa is the
1689 * self-originated router LSA of the node itself.
1690 */
1691 if (!root_lsa) {
1692 if (IS_DEBUG_OSPF_EVENT)
1693 zlog_debug(
1694 "ospf_spf_calculate: Skip area %pI4's calculation due to empty root LSA",
1695 &area->area_id);
1696 return;
1697 }
1698
1699 /* Initialize the algorithm's data structures, see RFC2328 16.1. (1). */
1700
1701 /*
1702 * This function scans all the LSA database and set the stat field to
1703 * LSA_SPF_NOT_EXPLORED.
1704 */
1705 lsdb_clean_stat(area->lsdb);
1706
1707 /* Create a new heap for the candidates. */
1708 vertex_pqueue_init(&candidate);
1709
1710 /*
1711 * Initialize the shortest-path tree to only the root (which is usually
1712 * the router doing the calculation).
1713 */
1714 ospf_spf_init(area, root_lsa, is_dry_run, is_root_node);
1715
1716 /* Set Area A's TransitCapability to false. */
1717 area->transit = OSPF_TRANSIT_FALSE;
1718 area->shortcut_capability = 1;
1719
1720 /*
1721 * Use the root vertex for the start of the SPF algorithm and make it
1722 * part of the tree.
1723 */
1724 v = area->spf;
1725 v->lsa_p->stat = LSA_SPF_IN_SPFTREE;
1726
1727 for (;;) {
1728 /* RFC2328 16.1. (2). */
1729 ospf_spf_next(v, area, &candidate);
1730
1731 /* RFC2328 16.1. (3). */
1732 v = vertex_pqueue_pop(&candidate);
1733 if (!v)
1734 /* No more vertices left. */
1735 break;
1736
1737 v->lsa_p->stat = LSA_SPF_IN_SPFTREE;
1738
1739 ospf_vertex_add_parent(v);
1740
1741 /* RFC2328 16.1. (4). */
1742 if (v->type != OSPF_VERTEX_ROUTER)
1743 ospf_intra_add_transit(new_table, v, area);
1744 else {
1745 ospf_intra_add_router(new_rtrs, v, area, false);
1746 if (all_rtrs)
1747 ospf_intra_add_router(all_rtrs, v, area, true);
1748 }
1749
1750 /* Iterate back to (2), see RFC2328 16.1. (5). */
1751 }
1752
1753 if (IS_DEBUG_OSPF_EVENT) {
1754 ospf_spf_dump(area->spf, 0);
1755 ospf_route_table_dump(new_table);
1756 if (all_rtrs)
1757 ospf_router_route_table_dump(all_rtrs);
1758 }
1759
1760 /*
1761 * Second stage of SPF calculation procedure's, add leaves to the tree
1762 * for stub networks.
1763 */
1764 ospf_spf_process_stubs(area, area->spf, new_table, 0);
1765
1766 ospf_vertex_dump(__func__, area->spf, 0, 1);
1767
1768 /* Increment SPF Calculation Counter. */
1769 area->spf_calculation++;
1770
1771 monotime(&area->ospf->ts_spf);
1772 area->ts_spf = area->ospf->ts_spf;
1773
1774 if (IS_DEBUG_OSPF_EVENT)
1775 zlog_debug("ospf_spf_calculate: Stop. %zd vertices",
1776 mtype_stats_alloc(MTYPE_OSPF_VERTEX));
1777 }
1778
1779 void ospf_spf_calculate_area(struct ospf *ospf, struct ospf_area *area,
1780 struct route_table *new_table,
1781 struct route_table *all_rtrs,
1782 struct route_table *new_rtrs)
1783 {
1784 ospf_spf_calculate(area, area->router_lsa_self, new_table, all_rtrs,
1785 new_rtrs, false, true);
1786
1787 if (ospf->ti_lfa_enabled)
1788 ospf_ti_lfa_compute(area, new_table,
1789 ospf->ti_lfa_protection_type);
1790
1791 ospf_spf_cleanup(area->spf, area->spf_vertex_list);
1792
1793 area->spf = NULL;
1794 area->spf_vertex_list = NULL;
1795 }
1796
1797 void ospf_spf_calculate_areas(struct ospf *ospf, struct route_table *new_table,
1798 struct route_table *all_rtrs,
1799 struct route_table *new_rtrs)
1800 {
1801 struct ospf_area *area;
1802 struct listnode *node, *nnode;
1803
1804 /* Calculate SPF for each area. */
1805 for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) {
1806 /* Do backbone last, so as to first discover intra-area paths
1807 * for any back-bone virtual-links */
1808 if (ospf->backbone && ospf->backbone == area)
1809 continue;
1810
1811 ospf_spf_calculate_area(ospf, area, new_table, all_rtrs,
1812 new_rtrs);
1813 }
1814
1815 /* SPF for backbone, if required */
1816 if (ospf->backbone)
1817 ospf_spf_calculate_area(ospf, ospf->backbone, new_table,
1818 all_rtrs, new_rtrs);
1819 }
1820
1821 /* Worker for SPF calculation scheduler. */
1822 static void ospf_spf_calculate_schedule_worker(struct thread *thread)
1823 {
1824 struct ospf *ospf = THREAD_ARG(thread);
1825 struct route_table *new_table, *new_rtrs;
1826 struct route_table *all_rtrs = NULL;
1827 struct timeval start_time, spf_start_time;
1828 unsigned long ia_time, prune_time, rt_time;
1829 unsigned long abr_time, total_spf_time, spf_time;
1830 char rbuf[32]; /* reason_buf */
1831
1832 if (IS_DEBUG_OSPF_EVENT)
1833 zlog_debug("SPF: Timer (SPF calculation expire)");
1834
1835 ospf->t_spf_calc = NULL;
1836
1837 ospf_vl_unapprove(ospf);
1838
1839 /* Execute SPF for each area including backbone, see RFC 2328 16.1. */
1840 monotime(&spf_start_time);
1841 new_table = route_table_init(); /* routing table */
1842 new_rtrs = route_table_init(); /* ABR/ASBR routing table */
1843
1844 /* If we have opaque enabled then track all router reachability */
1845 if (CHECK_FLAG(ospf->opaque, OPAQUE_OPERATION_READY_BIT))
1846 all_rtrs = route_table_init();
1847
1848 ospf_spf_calculate_areas(ospf, new_table, all_rtrs, new_rtrs);
1849 spf_time = monotime_since(&spf_start_time, NULL);
1850
1851 ospf_vl_shut_unapproved(ospf);
1852
1853 /* Calculate inter-area routes, see RFC 2328 16.2. */
1854 monotime(&start_time);
1855 ospf_ia_routing(ospf, new_table, new_rtrs);
1856 ia_time = monotime_since(&start_time, NULL);
1857
1858 /* Get rid of transit networks and routers we cannot reach anyway. */
1859 monotime(&start_time);
1860 ospf_prune_unreachable_networks(new_table);
1861 if (all_rtrs)
1862 ospf_prune_unreachable_routers(all_rtrs);
1863 ospf_prune_unreachable_routers(new_rtrs);
1864 prune_time = monotime_since(&start_time, NULL);
1865
1866 /* Note: RFC 2328 16.3. is apparently missing. */
1867
1868 /*
1869 * Calculate AS external routes, see RFC 2328 16.4.
1870 * There is a dedicated routing table for external routes which is not
1871 * handled here directly
1872 */
1873 ospf_ase_calculate_schedule(ospf);
1874 ospf_ase_calculate_timer_add(ospf);
1875
1876 if (IS_DEBUG_OSPF_EVENT)
1877 zlog_debug(
1878 "%s: ospf install new route, vrf %s id %u new_table count %lu",
1879 __func__, ospf_vrf_id_to_name(ospf->vrf_id),
1880 ospf->vrf_id, new_table->count);
1881
1882 /* Update routing table. */
1883 monotime(&start_time);
1884 ospf_route_install(ospf, new_table);
1885 rt_time = monotime_since(&start_time, NULL);
1886
1887 /* Free old all routers routing table */
1888 if (ospf->oall_rtrs)
1889 /* ospf_route_delete (ospf->old_rtrs); */
1890 ospf_rtrs_free(ospf->oall_rtrs);
1891
1892 /* Update all routers routing table */
1893 ospf->oall_rtrs = ospf->all_rtrs;
1894 ospf->all_rtrs = all_rtrs;
1895 ospf_apiserver_notify_reachable(ospf->oall_rtrs, ospf->all_rtrs);
1896
1897 /* Free old ABR/ASBR routing table */
1898 if (ospf->old_rtrs)
1899 /* ospf_route_delete (ospf->old_rtrs); */
1900 ospf_rtrs_free(ospf->old_rtrs);
1901
1902 /* Update ABR/ASBR routing table */
1903 ospf->old_rtrs = ospf->new_rtrs;
1904 ospf->new_rtrs = new_rtrs;
1905
1906 /* ABRs may require additional changes, see RFC 2328 16.7. */
1907 monotime(&start_time);
1908 if (IS_OSPF_ABR(ospf)) {
1909 if (ospf->anyNSSA)
1910 ospf_abr_nssa_check_status(ospf);
1911 ospf_abr_task(ospf);
1912 }
1913 abr_time = monotime_since(&start_time, NULL);
1914
1915 /* Schedule Segment Routing update */
1916 ospf_sr_update_task(ospf);
1917
1918 total_spf_time =
1919 monotime_since(&spf_start_time, &ospf->ts_spf_duration);
1920
1921 rbuf[0] = '\0';
1922 if (spf_reason_flags) {
1923 if (spf_reason_flags & (1 << SPF_FLAG_ROUTER_LSA_INSTALL))
1924 strlcat(rbuf, "R, ", sizeof(rbuf));
1925 if (spf_reason_flags & (1 << SPF_FLAG_NETWORK_LSA_INSTALL))
1926 strlcat(rbuf, "N, ", sizeof(rbuf));
1927 if (spf_reason_flags & (1 << SPF_FLAG_SUMMARY_LSA_INSTALL))
1928 strlcat(rbuf, "S, ", sizeof(rbuf));
1929 if (spf_reason_flags & (1 << SPF_FLAG_ASBR_SUMMARY_LSA_INSTALL))
1930 strlcat(rbuf, "AS, ", sizeof(rbuf));
1931 if (spf_reason_flags & (1 << SPF_FLAG_ABR_STATUS_CHANGE))
1932 strlcat(rbuf, "ABR, ", sizeof(rbuf));
1933 if (spf_reason_flags & (1 << SPF_FLAG_ASBR_STATUS_CHANGE))
1934 strlcat(rbuf, "ASBR, ", sizeof(rbuf));
1935 if (spf_reason_flags & (1 << SPF_FLAG_MAXAGE))
1936 strlcat(rbuf, "M, ", sizeof(rbuf));
1937 if (spf_reason_flags & (1 << SPF_FLAG_GR_FINISH))
1938 strlcat(rbuf, "GR, ", sizeof(rbuf));
1939
1940 size_t rbuflen = strlen(rbuf);
1941 if (rbuflen >= 2)
1942 rbuf[rbuflen - 2] = '\0'; /* skip the last ", " */
1943 else
1944 rbuf[0] = '\0';
1945 }
1946
1947 if (IS_DEBUG_OSPF_EVENT) {
1948 zlog_info("SPF Processing Time(usecs): %ld", total_spf_time);
1949 zlog_info(" SPF Time: %ld", spf_time);
1950 zlog_info(" InterArea: %ld", ia_time);
1951 zlog_info(" Prune: %ld", prune_time);
1952 zlog_info(" RouteInstall: %ld", rt_time);
1953 if (IS_OSPF_ABR(ospf))
1954 zlog_info(" ABR: %ld (%d areas)",
1955 abr_time, ospf->areas->count);
1956 zlog_info("Reason(s) for SPF: %s", rbuf);
1957 }
1958
1959 ospf_clear_spf_reason_flags();
1960 }
1961
1962 /*
1963 * Add schedule for SPF calculation. To avoid frequenst SPF calc, we set timer
1964 * for SPF calc.
1965 */
1966 void ospf_spf_calculate_schedule(struct ospf *ospf, ospf_spf_reason_t reason)
1967 {
1968 unsigned long delay, elapsed, ht;
1969
1970 if (IS_DEBUG_OSPF_EVENT)
1971 zlog_debug("SPF: calculation timer scheduled");
1972
1973 /* OSPF instance does not exist. */
1974 if (ospf == NULL)
1975 return;
1976
1977 ospf_spf_set_reason(reason);
1978
1979 /* SPF calculation timer is already scheduled. */
1980 if (ospf->t_spf_calc) {
1981 if (IS_DEBUG_OSPF_EVENT)
1982 zlog_debug(
1983 "SPF: calculation timer is already scheduled: %p",
1984 (void *)ospf->t_spf_calc);
1985 return;
1986 }
1987
1988 elapsed = monotime_since(&ospf->ts_spf, NULL) / 1000;
1989
1990 ht = ospf->spf_holdtime * ospf->spf_hold_multiplier;
1991
1992 if (ht > ospf->spf_max_holdtime)
1993 ht = ospf->spf_max_holdtime;
1994
1995 /* Get SPF calculation delay time. */
1996 if (elapsed < ht) {
1997 /*
1998 * Got an event within the hold time of last SPF. We need to
1999 * increase the hold_multiplier, if it's not already at/past
2000 * maximum value, and wasn't already increased.
2001 */
2002 if (ht < ospf->spf_max_holdtime)
2003 ospf->spf_hold_multiplier++;
2004
2005 /* always honour the SPF initial delay */
2006 if ((ht - elapsed) < ospf->spf_delay)
2007 delay = ospf->spf_delay;
2008 else
2009 delay = ht - elapsed;
2010 } else {
2011 /* Event is past required hold-time of last SPF */
2012 delay = ospf->spf_delay;
2013 ospf->spf_hold_multiplier = 1;
2014 }
2015
2016 if (IS_DEBUG_OSPF_EVENT)
2017 zlog_debug("SPF: calculation timer delay = %ld msec", delay);
2018
2019 ospf->t_spf_calc = NULL;
2020 thread_add_timer_msec(master, ospf_spf_calculate_schedule_worker, ospf,
2021 delay, &ospf->t_spf_calc);
2022 }
2023
2024 /* Restart OSPF SPF algorithm*/
2025 void ospf_restart_spf(struct ospf *ospf)
2026 {
2027 if (IS_DEBUG_OSPF_EVENT)
2028 zlog_debug("%s: Restart SPF.", __func__);
2029
2030 /* Handling inter area and intra area routes*/
2031 if (ospf->new_table) {
2032 ospf_route_delete(ospf, ospf->new_table);
2033 ospf_route_table_free(ospf->new_table);
2034 ospf->new_table = route_table_init();
2035 }
2036
2037 /* Handling of TYPE-5 lsa(external routes) */
2038 if (ospf->old_external_route) {
2039 ospf_route_delete(ospf, ospf->old_external_route);
2040 ospf_route_table_free(ospf->old_external_route);
2041 ospf->old_external_route = route_table_init();
2042 }
2043
2044 /* Trigger SPF */
2045 ospf_spf_calculate_schedule(ospf, SPF_FLAG_CONFIG_CHANGE);
2046 }