]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_spf.c
[zebra] Add extra debug logging for RIB and RIB queueing
[mirror_frr.git] / ospfd / ospf_spf.c
CommitLineData
718e3744 1/* OSPF SPF calculation.
2 Copyright (C) 1999, 2000 Kunihiro Ishiguro, Toshiaki Takada
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22
23#include "thread.h"
24#include "memory.h"
25#include "hash.h"
26#include "linklist.h"
27#include "prefix.h"
28#include "if.h"
29#include "table.h"
30#include "log.h"
31#include "sockunion.h" /* for inet_ntop () */
462f20d5 32#include "pqueue.h"
718e3744 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
9c27ef9b
PJ
49static void ospf_vertex_free (void *);
50/* List of allocated vertices, to simplify cleanup of SPF.
51 * Not thread-safe obviously. If it ever needs to be, it'd have to be
52 * dynamically allocated at begin of ospf_spf_calculate
53 */
54static struct list vertex_list = { .del = ospf_vertex_free };
55\f
462f20d5 56/* Heap related functions, for the managment of the candidates, to
57 * be used with pqueue. */
58static int
59cmp (void * node1 , void * node2)
60{
61 struct vertex * v1 = (struct vertex *) node1;
62 struct vertex * v2 = (struct vertex *) node2;
63 if (v1 != NULL && v2 != NULL )
9c27ef9b
PJ
64 {
65 /* network vertices must be chosen before router vertices of same
66 * cost in order to find all shortest paths
67 */
68 if ( ((v1->distance - v2->distance) == 0)
69 && (v1->type != v2->type))
70 {
71 switch (v1->type)
72 {
73 case OSPF_VERTEX_NETWORK:
74 return -1;
75 case OSPF_VERTEX_ROUTER:
76 return 1;
77 }
78 }
79 else
80 return (v1->distance - v2->distance);
81 }
82 return 0;
462f20d5 83}
84
85static void
eb3da6df 86update_stat (void *node , int position)
462f20d5 87{
eb3da6df 88 struct vertex *v = node;
89
462f20d5 90 /* Set the status of the vertex, when its position changes. */
91 *(v->stat) = position;
92}
eb3da6df 93\f
4dadc291 94static struct vertex_nexthop *
eb3da6df 95vertex_nexthop_new (void)
718e3744 96{
eb3da6df 97 return XCALLOC (MTYPE_OSPF_NEXTHOP, sizeof (struct vertex_nexthop));
718e3744 98}
99
4dadc291 100static void
718e3744 101vertex_nexthop_free (struct vertex_nexthop *nh)
102{
103 XFREE (MTYPE_OSPF_NEXTHOP, nh);
104}
105
eb3da6df 106/* Free the canonical nexthop objects for an area, ie the nexthop objects
9c27ef9b
PJ
107 * attached to the first-hop router vertices, and any intervening network
108 * vertices.
eb3da6df 109 */
110static void
111ospf_canonical_nexthops_free (struct vertex *root)
718e3744 112{
eb3da6df 113 struct listnode *node, *nnode;
114 struct vertex *child;
115
116 for (ALL_LIST_ELEMENTS (root->children, node, nnode, child))
117 {
118 struct listnode *n2, *nn2;
119 struct vertex_parent *vp;
120
58e1befe 121 /* router vertices through an attached network each
122 * have a distinct (canonical / not inherited) nexthop
123 * which must be freed.
124 *
125 * A network vertex can only have router vertices as its
126 * children, so only one level of recursion is possible.
127 */
eb3da6df 128 if (child->type == OSPF_VERTEX_NETWORK)
129 ospf_canonical_nexthops_free (child);
130
58e1befe 131 /* Free child nexthops pointing back to this root vertex */
eb3da6df 132 for (ALL_LIST_ELEMENTS (child->parents, n2, nn2, vp))
9c27ef9b 133 if (vp->parent == root && vp->nexthop)
58e1befe 134 vertex_nexthop_free (vp->nexthop);
eb3da6df 135 }
136}
137\f
9c27ef9b
PJ
138/* TODO: Parent list should be excised, in favour of maintaining only
139 * vertex_nexthop, with refcounts.
140 */
eb3da6df 141static struct vertex_parent *
142vertex_parent_new (struct vertex *v, int backlink, struct vertex_nexthop *hop)
143{
144 struct vertex_parent *new;
145
146 new = XMALLOC (MTYPE_OSPF_VERTEX_PARENT, sizeof (struct vertex_parent));
147
148 if (new == NULL)
149 return NULL;
150
151 new->parent = v;
152 new->backlink = backlink;
153 new->nexthop = hop;
718e3744 154 return new;
155}
0c0f9cd5 156
eb3da6df 157static void
9c27ef9b 158vertex_parent_free (void *p)
eb3da6df 159{
160 XFREE (MTYPE_OSPF_VERTEX_PARENT, p);
161}
162\f
4dadc291 163static struct vertex *
718e3744 164ospf_vertex_new (struct ospf_lsa *lsa)
165{
166 struct vertex *new;
167
eb3da6df 168 new = XCALLOC (MTYPE_OSPF_VERTEX, sizeof (struct vertex));
718e3744 169
170 new->flags = 0;
462f20d5 171 new->stat = &(lsa->stat);
718e3744 172 new->type = lsa->data->type;
173 new->id = lsa->data->id;
174 new->lsa = lsa->data;
eb3da6df 175 new->children = list_new ();
176 new->parents = list_new ();
9c27ef9b
PJ
177 new->parents->del = vertex_parent_free;
178
179 listnode_add (&vertex_list, new);
eb3da6df 180
9c27ef9b
PJ
181 if (IS_DEBUG_OSPF_EVENT)
182 zlog_debug ("%s: Created %s vertex %s", __func__,
183 new->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
184 inet_ntoa (new->lsa->id));
718e3744 185 return new;
186}
187
4dadc291 188static void
9c27ef9b 189ospf_vertex_free (void *data)
718e3744 190{
9c27ef9b 191 struct vertex *v = data;
eb3da6df 192
9c27ef9b
PJ
193 if (IS_DEBUG_OSPF_EVENT)
194 zlog_debug ("%s: Free %s vertex %s", __func__,
195 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
196 inet_ntoa (v->lsa->id));
7461d459 197
9c27ef9b
PJ
198 /* There should be no parents potentially holding references to this vertex
199 * Children however may still be there, but presumably referenced by other
200 * vertices
eb3da6df 201 */
9c27ef9b 202 //assert (listcount (v->parents) == 0);
eb3da6df 203
9c27ef9b
PJ
204 if (v->children)
205 list_delete (v->children);
206 v->children = NULL;
207
208 if (v->parents)
209 list_delete (v->parents);
eb3da6df 210 v->parents = NULL;
211
212 v->lsa = NULL;
7461d459 213
718e3744 214 XFREE (MTYPE_OSPF_VERTEX, v);
215}
216
4dadc291 217static void
eb1ce605 218ospf_vertex_dump(const char *msg, struct vertex *v,
eb3da6df 219 int print_parents, int print_children)
630e4807 220{
221 if ( ! IS_DEBUG_OSPF_EVENT)
222 return;
223
eb3da6df 224 zlog_debug("%s %s vertex %s distance %u flags %u",
630e4807 225 msg,
226 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
227 inet_ntoa(v->lsa->id),
228 v->distance,
630e4807 229 (unsigned int)v->flags);
230
eb3da6df 231 if (print_parents)
630e4807 232 {
1eb8ef25 233 struct listnode *node;
eb3da6df 234 struct vertex_parent *vp;
1eb8ef25 235
eb3da6df 236 for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
630e4807 237 {
238 char buf1[BUFSIZ];
eb3da6df 239
240 if (vp)
630e4807 241 {
eb3da6df 242 zlog_debug ("parent %s backlink %d nexthop %s interface %s",
243 inet_ntoa(vp->parent->lsa->id), vp->backlink,
244 inet_ntop(AF_INET, &vp->nexthop->router, buf1, BUFSIZ),
245 vp->nexthop->oi ? IF_NAME(vp->nexthop->oi) : "NULL");
630e4807 246 }
247 }
248 }
249
250 if (print_children)
251 {
52dc7ee6 252 struct listnode *cnode;
1eb8ef25 253 struct vertex *cv;
254
eb3da6df 255 for (ALL_LIST_ELEMENTS_RO (v->children, cnode, cv))
1eb8ef25 256 ospf_vertex_dump(" child:", cv, 0, 0);
630e4807 257 }
258}
259
260
261/* Add a vertex to the list of children in each of its parents. */
4dadc291 262static void
718e3744 263ospf_vertex_add_parent (struct vertex *v)
264{
eb3da6df 265 struct vertex_parent *vp;
52dc7ee6 266 struct listnode *node;
7461d459 267
9c27ef9b 268 assert (v && v->parents);
7461d459 269
eb3da6df 270 for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
718e3744 271 {
eb3da6df 272 assert (vp->parent && vp->parent->children);
7461d459 273
718e3744 274 /* No need to add two links from the same parent. */
eb3da6df 275 if (listnode_lookup (vp->parent->children, v) == NULL)
276 listnode_add (vp->parent->children, v);
718e3744 277 }
278}
279\f
4dadc291 280static void
718e3744 281ospf_spf_init (struct ospf_area *area)
282{
283 struct vertex *v;
9c27ef9b 284
718e3744 285 /* Create root node. */
286 v = ospf_vertex_new (area->router_lsa_self);
bd34fb34 287
718e3744 288 area->spf = v;
289
290 /* Reset ABR and ASBR router counts. */
291 area->abr_count = 0;
292 area->asbr_count = 0;
293}
294
d355bfa7 295/* return index of link back to V from W, or -1 if no link found */
4dadc291 296static int
718e3744 297ospf_lsa_has_link (struct lsa_header *w, struct lsa_header *v)
298{
eb1ce605 299 unsigned int i, length;
718e3744 300 struct router_lsa *rl;
301 struct network_lsa *nl;
302
303 /* In case of W is Network LSA. */
304 if (w->type == OSPF_NETWORK_LSA)
305 {
306 if (v->type == OSPF_NETWORK_LSA)
d355bfa7 307 return -1;
718e3744 308
309 nl = (struct network_lsa *) w;
310 length = (ntohs (w->length) - OSPF_LSA_HEADER_SIZE - 4) / 4;
0c0f9cd5 311
718e3744 312 for (i = 0; i < length; i++)
313 if (IPV4_ADDR_SAME (&nl->routers[i], &v->id))
d355bfa7 314 return i;
315 return -1;
718e3744 316 }
317
318 /* In case of W is Router LSA. */
319 if (w->type == OSPF_ROUTER_LSA)
320 {
321 rl = (struct router_lsa *) w;
322
323 length = ntohs (w->length);
324
325 for (i = 0;
0c0f9cd5 326 i < ntohs (rl->links) && length >= sizeof (struct router_lsa);
327 i++, length -= 12)
718e3744 328 {
329 switch (rl->link[i].type)
330 {
331 case LSA_LINK_TYPE_POINTOPOINT:
332 case LSA_LINK_TYPE_VIRTUALLINK:
333 /* Router LSA ID. */
334 if (v->type == OSPF_ROUTER_LSA &&
335 IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
336 {
d355bfa7 337 return i;
718e3744 338 }
339 break;
340 case LSA_LINK_TYPE_TRANSIT:
341 /* Network LSA ID. */
342 if (v->type == OSPF_NETWORK_LSA &&
343 IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
344 {
d355bfa7 345 return i;
0c0f9cd5 346 }
718e3744 347 break;
348 case LSA_LINK_TYPE_STUB:
eb3da6df 349 /* Stub can't lead anywhere, carry on */
718e3744 350 continue;
351 default:
352 break;
353 }
354 }
355 }
d355bfa7 356 return -1;
718e3744 357}
358
718e3744 359#define ROUTER_LSA_MIN_SIZE 12
360#define ROUTER_LSA_TOS_SIZE 4
361
630e4807 362/* Find the next link after prev_link from v to w. If prev_link is
363 * NULL, return the first link from v to w. Ignore stub and virtual links;
364 * these link types will never be returned.
365 */
4dadc291 366static struct router_lsa_link *
718e3744 367ospf_get_next_link (struct vertex *v, struct vertex *w,
0c0f9cd5 368 struct router_lsa_link *prev_link)
718e3744 369{
370 u_char *p;
371 u_char *lim;
372 struct router_lsa_link *l;
373
374 if (prev_link == NULL)
630e4807 375 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
718e3744 376 else
377 {
0c0f9cd5 378 p = (u_char *) prev_link;
718e3744 379 p += (ROUTER_LSA_MIN_SIZE +
380 (prev_link->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
381 }
0c0f9cd5 382
718e3744 383 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
384
385 while (p < lim)
386 {
387 l = (struct router_lsa_link *) p;
388
0c0f9cd5 389 p += (ROUTER_LSA_MIN_SIZE + (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
718e3744 390
391 if (l->m[0].type == LSA_LINK_TYPE_STUB)
392 continue;
393
394 /* Defer NH calculation via VLs until summaries from
395 transit areas area confidered */
396
397 if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK)
0c0f9cd5 398 continue;
718e3744 399
400 if (IPV4_ADDR_SAME (&l->link_id, &w->id))
0c0f9cd5 401 return l;
718e3744 402 }
403
404 return NULL;
405}
406
bc20c1a4
PJ
407static void
408ospf_spf_flush_parents (struct vertex *w)
409{
410 struct vertex_parent *vp;
411 struct listnode *ln, *nn;
412
413 /* delete the existing nexthops */
414 for (ALL_LIST_ELEMENTS (w->parents, ln, nn, vp))
415 {
416 list_delete_node (w->parents, ln);
417 vertex_parent_free (vp);
418 }
419}
420
75ee0b8e 421/*
422 * Consider supplied next-hop for inclusion to the supplied list of
423 * equal-cost next-hops, adjust list as neccessary.
bf9392c6 424 */
4dadc291 425static void
eb3da6df 426ospf_spf_add_parent (struct vertex *v, struct vertex *w,
bc20c1a4 427 struct vertex_nexthop *newhop,
bd34fb34 428 unsigned int distance)
bf9392c6 429{
eb3da6df 430 struct vertex_parent *vp;
431
08d3d5b3 432 /* we must have a newhop, and a distance */
bd34fb34 433 assert (v && w && newhop);
08d3d5b3 434 assert (distance);
eb3da6df 435
08d3d5b3
PJ
436 /* IFF w has already been assigned a distance, then we shouldn't get here
437 * unless callers have determined V(l)->W is shortest / equal-shortest
438 * path (0 is a special case distance (no distance yet assigned)).
bc20c1a4 439 */
08d3d5b3
PJ
440 if (w->distance)
441 assert (distance <= w->distance);
442 else
443 w->distance = distance;
bc20c1a4 444
b75ae99e
PJ
445 if (IS_DEBUG_OSPF_EVENT)
446 {
447 char buf[2][INET_ADDRSTRLEN];
448 zlog_debug ("%s: Adding %s as parent of %s",
449 __func__,
450 inet_ntop(AF_INET, &v->lsa->id, buf[0], sizeof(buf[0])),
451 inet_ntop(AF_INET, &w->lsa->id, buf[1], sizeof(buf[1])));
452 }
453
bc20c1a4 454 /* Adding parent for a new, better path: flush existing parents from W. */
bd34fb34 455 if (distance < w->distance)
bc20c1a4 456 {
b75ae99e
PJ
457 if (IS_DEBUG_OSPF_EVENT)
458 zlog_debug ("%s: distance %d better than %d, flushing existing parents",
459 __func__, distance, w->distance);
bc20c1a4 460 ospf_spf_flush_parents (w);
bd34fb34 461 w->distance = distance;
bc20c1a4
PJ
462 }
463
464 /* new parent is <= existing parents, add it to parent list */
eb3da6df 465 vp = vertex_parent_new (v, ospf_lsa_has_link (w->lsa, v->lsa), newhop);
466 listnode_add (w->parents, vp);
0c0f9cd5 467
eb3da6df 468 return;
469}
470
630e4807 471/* 16.1.1. Calculate nexthop from root through V (parent) to
bd34fb34 472 * vertex W (destination), with given distance from root->W.
eb3da6df 473 *
474 * The link must be supplied if V is the root vertex. In all other cases
475 * it may be NULL.
bd34fb34
PJ
476 *
477 * Note that this function may fail, hence the state of the destination
478 * vertex, W, should /not/ be modified in a dependent manner until
479 * this function returns. This function will update the W vertex with the
480 * provided distance as appropriate.
630e4807 481 */
bc20c1a4 482static unsigned int
eb3da6df 483ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v,
bd34fb34
PJ
484 struct vertex *w, struct router_lsa_link *l,
485 unsigned int distance)
718e3744 486{
1eb8ef25 487 struct listnode *node, *nnode;
eb3da6df 488 struct vertex_nexthop *nh;
489 struct vertex_parent *vp;
718e3744 490 struct ospf_interface *oi = NULL;
bc20c1a4 491 unsigned int added = 0;
0c0f9cd5 492
718e3744 493 if (IS_DEBUG_OSPF_EVENT)
630e4807 494 {
2a42e285 495 zlog_debug ("ospf_nexthop_calculation(): Start");
630e4807 496 ospf_vertex_dump("V (parent):", v, 1, 1);
497 ospf_vertex_dump("W (dest) :", w, 1, 1);
bd34fb34 498 zlog_debug ("V->W distance: %d", distance);
630e4807 499 }
718e3744 500
718e3744 501 if (v == area->spf)
9c27ef9b 502 {
630e4807 503 /* 16.1.1 para 4. In the first case, the parent vertex (V) is the
504 root (the calculating router itself). This means that the
505 destination is either a directly connected network or directly
506 connected router. The outgoing interface in this case is simply
507 the OSPF interface connecting to the destination network/router.
508 */
509
718e3744 510 if (w->type == OSPF_VERTEX_ROUTER)
0c0f9cd5 511 {
eb3da6df 512 /* l is a link from v to w
513 * l2 will be link from w to v
514 */
515 struct router_lsa_link *l2 = NULL;
516
517 /* we *must* be supplied with the link data */
518 assert (l != NULL);
519
520 if (IS_DEBUG_OSPF_EVENT)
0c0f9cd5 521 {
eb3da6df 522 char buf1[BUFSIZ];
523 char buf2[BUFSIZ];
524
525 zlog_debug("ospf_nexthop_calculation(): considering link "
526 "type %d link_id %s link_data %s",
527 l->m[0].type,
528 inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ),
529 inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ));
530 }
531
532 if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT)
533 {
534 /* If the destination is a router which connects to
535 the calculating router via a Point-to-MultiPoint
536 network, the destination's next hop IP address(es)
537 can be determined by examining the destination's
538 router-LSA: each link pointing back to the
539 calculating router and having a Link Data field
540 belonging to the Point-to-MultiPoint network
541 provides an IP address of the next hop router.
542
543 At this point l is a link from V to W, and V is the
544 root ("us"). Find the local interface associated
545 with l (its address is in l->link_data). If it
546 is a point-to-multipoint interface, then look through
547 the links in the opposite direction (W to V). If
548 any of them have an address that lands within the
549 subnet declared by the PtMP link, then that link
550 is a constituent of the PtMP link, and its address is
551 a nexthop address for V.
552 */
553 oi = ospf_if_is_configured (area->ospf, &l->link_data);
554 if (oi && oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
0c0f9cd5 555 {
eb3da6df 556 struct prefix_ipv4 la;
557
558 la.family = AF_INET;
559 la.prefixlen = oi->address->prefixlen;
560
561 /* V links to W on PtMP interface
562 - find the interface address on W */
563 while ((l2 = ospf_get_next_link (w, v, l2)))
0c0f9cd5 564 {
eb3da6df 565 la.prefix = l2->link_data;
0c0f9cd5 566
eb3da6df 567 if (prefix_cmp ((struct prefix *) &la,
568 oi->address) == 0)
569 /* link_data is on our PtMP network */
570 break;
571 }
572 } /* end l is on point-to-multipoint link */
573 else
574 {
575 /* l is a regular point-to-point link.
576 Look for a link from W to V.
577 */
578 while ((l2 = ospf_get_next_link (w, v, l2)))
0c0f9cd5 579 {
eb3da6df 580 oi = ospf_if_is_configured (area->ospf,
581 &(l2->link_data));
582
583 if (oi == NULL)
584 continue;
585
586 if (!IPV4_ADDR_SAME (&oi->address->u.prefix4,
587 &l->link_data))
588 continue;
589
590 break;
0c0f9cd5 591 }
eb3da6df 592 }
593
594 if (oi && l2)
595 {
596 /* found all necessary info to build nexthop */
597 nh = vertex_nexthop_new ();
598 nh->oi = oi;
599 nh->router = l2->link_data;
bd34fb34 600 ospf_spf_add_parent (v, w, nh, distance);
bc20c1a4 601 return 1;
eb3da6df 602 }
603 else
9c27ef9b
PJ
604 zlog_info("ospf_nexthop_calculation(): "
605 "could not determine nexthop for link");
606 } /* end point-to-point link from V to W */
607 else if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK)
608 {
609 struct ospf_vl_data *vl_data;
610
611 /* VLink implementation limitations:
612 * a) vl_data can only reference one nexthop, so no ECMP
613 * to backbone through VLinks. Though transit-area
614 * summaries may be considered, and those can be ECMP.
615 * b) We can only use /one/ VLink, even if multiple ones
616 * exist this router through multiple transit-areas.
617 */
618 vl_data = ospf_vl_lookup (area->ospf, NULL, l->link_id);
619
620 if (vl_data
621 && CHECK_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED))
eb3da6df 622 {
9c27ef9b
PJ
623 nh = vertex_nexthop_new ();
624 nh->oi = vl_data->nexthop.oi;
625 nh->router = vl_data->nexthop.router;
bd34fb34 626 ospf_spf_add_parent (v, w, nh, distance);
bc20c1a4 627 return 1;
eb3da6df 628 }
9c27ef9b 629 else
bc20c1a4
PJ
630 zlog_info("ospf_nexthop_calculation(): "
631 "vl_data for VL link not found");
9c27ef9b 632 } /* end virtual-link from V to W */
bc20c1a4 633 return 0;
630e4807 634 } /* end W is a Router vertex */
718e3744 635 else
0c0f9cd5 636 {
eb3da6df 637 assert(w->type == OSPF_VERTEX_NETWORK);
638 oi = ospf_if_is_configured (area->ospf, &(l->link_data));
639 if (oi)
0c0f9cd5 640 {
eb3da6df 641 nh = vertex_nexthop_new ();
642 nh->oi = oi;
643 nh->router.s_addr = 0;
bd34fb34 644 ospf_spf_add_parent (v, w, nh, distance);
bc20c1a4 645 return 1;
0c0f9cd5 646 }
647 }
9c27ef9b
PJ
648 zlog_info("ospf_nexthop_calculation(): "
649 "Unknown attached link");
bc20c1a4 650 return 0;
630e4807 651 } /* end V is the root */
630e4807 652 /* Check if W's parent is a network connected to root. */
718e3744 653 else if (v->type == OSPF_VERTEX_NETWORK)
654 {
630e4807 655 /* See if any of V's parents are the root. */
eb3da6df 656 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
718e3744 657 {
eb3da6df 658 if (vp->parent == area->spf) /* connects to root? */
630e4807 659 {
660 /* 16.1.1 para 5. ...the parent vertex is a network that
661 * directly connects the calculating router to the destination
662 * router. The list of next hops is then determined by
663 * examining the destination's router-LSA...
664 */
665
666 assert(w->type == OSPF_VERTEX_ROUTER);
0c0f9cd5 667 while ((l = ospf_get_next_link (w, v, l)))
668 {
630e4807 669 /* ...For each link in the router-LSA that points back to the
670 * parent network, the link's Link Data field provides the IP
671 * address of a next hop router. The outgoing interface to
672 * use can then be derived from the next hop IP address (or
673 * it can be inherited from the parent network).
674 */
eb3da6df 675 nh = vertex_nexthop_new ();
676 nh->oi = vp->nexthop->oi;
677 nh->router = l->link_data;
bc20c1a4 678 added = 1;
bd34fb34 679 ospf_spf_add_parent (v, w, nh, distance);
0c0f9cd5 680 }
0c0f9cd5 681 }
718e3744 682 }
85ef784e
PJ
683 if (added)
684 return added;
718e3744 685 }
686
630e4807 687 /* 16.1.1 para 4. If there is at least one intervening router in the
688 * current shortest path between the destination and the root, the
689 * destination simply inherits the set of next hops from the
690 * parent.
691 */
b75ae99e
PJ
692 if (IS_DEBUG_OSPF_EVENT)
693 zlog_debug ("%s: Intervening routers, adding parent(s)", __func__);
694
eb3da6df 695 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
bc20c1a4
PJ
696 {
697 added = 1;
bd34fb34 698 ospf_spf_add_parent (v, w, vp->nexthop, distance);
bc20c1a4 699 }
9c27ef9b 700
bc20c1a4 701 return added;
718e3744 702}
703
630e4807 704/* RFC2328 Section 16.1 (2).
705 * v is on the SPF tree. Examine the links in v's LSA. Update the list
706 * of candidates with any vertices not already on the list. If a lower-cost
707 * path is found to a vertex already on the candidate list, store the new cost.
708 */
4dadc291 709static void
718e3744 710ospf_spf_next (struct vertex *v, struct ospf_area *area,
462f20d5 711 struct pqueue * candidate)
718e3744 712{
713 struct ospf_lsa *w_lsa = NULL;
718e3744 714 u_char *p;
715 u_char *lim;
716 struct router_lsa_link *l = NULL;
717 struct in_addr *r;
718e3744 718 int type = 0;
719
720 /* If this is a router-LSA, and bit V of the router-LSA (see Section
721 A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE. */
722 if (v->type == OSPF_VERTEX_ROUTER)
723 {
724 if (IS_ROUTER_LSA_VIRTUAL ((struct router_lsa *) v->lsa))
725 area->transit = OSPF_TRANSIT_TRUE;
726 }
b75ae99e
PJ
727
728 if (IS_DEBUG_OSPF_EVENT)
729 zlog_debug ("%s: Next vertex of %s vertex %s",
730 __func__,
731 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
732 inet_ntoa(v->lsa->id));
733
718e3744 734 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
0c0f9cd5 735 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
736
718e3744 737 while (p < lim)
738 {
eb3da6df 739 struct vertex *w;
740 unsigned int distance;
d355bfa7 741
718e3744 742 /* In case of V is Router-LSA. */
743 if (v->lsa->type == OSPF_ROUTER_LSA)
744 {
745 l = (struct router_lsa_link *) p;
746
0c0f9cd5 747 p += (ROUTER_LSA_MIN_SIZE +
718e3744 748 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
749
750 /* (a) If this is a link to a stub network, examine the next
751 link in V's LSA. Links to stub networks will be
752 considered in the second stage of the shortest path
753 calculation. */
754 if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB)
755 continue;
08d3d5b3
PJ
756
757 /* Infinite distance links shouldn't be followed, except
758 * for local links (a stub-routed router still wants to
759 * calculate tree, so must follow its own links).
760 */
761 if ((v != area->spf) && l->m[0].metric >= OSPF_OUTPUT_COST_INFINITE)
762 continue;
718e3744 763
764 /* (b) Otherwise, W is a transit vertex (router or transit
765 network). Look up the vertex W's LSA (router-LSA or
766 network-LSA) in Area A's link state database. */
767 switch (type)
768 {
769 case LSA_LINK_TYPE_POINTOPOINT:
770 case LSA_LINK_TYPE_VIRTUALLINK:
771 if (type == LSA_LINK_TYPE_VIRTUALLINK)
0c0f9cd5 772 {
773 if (IS_DEBUG_OSPF_EVENT)
2a42e285 774 zlog_debug ("looking up LSA through VL: %s",
0c0f9cd5 775 inet_ntoa (l->link_id));
776 }
718e3744 777
778 w_lsa = ospf_lsa_lookup (area, OSPF_ROUTER_LSA, l->link_id,
779 l->link_id);
780 if (w_lsa)
0c0f9cd5 781 {
782 if (IS_DEBUG_OSPF_EVENT)
2a42e285 783 zlog_debug ("found Router LSA %s", inet_ntoa (l->link_id));
0c0f9cd5 784 }
718e3744 785 break;
786 case LSA_LINK_TYPE_TRANSIT:
0c0f9cd5 787 if (IS_DEBUG_OSPF_EVENT)
2a42e285 788 zlog_debug ("Looking up Network LSA, ID: %s",
0c0f9cd5 789 inet_ntoa (l->link_id));
718e3744 790 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_NETWORK_LSA,
0c0f9cd5 791 l->link_id);
718e3744 792 if (w_lsa)
0c0f9cd5 793 if (IS_DEBUG_OSPF_EVENT)
2a42e285 794 zlog_debug ("found the LSA");
718e3744 795 break;
796 default:
0c0f9cd5 797 zlog_warn ("Invalid LSA link type %d", type);
718e3744 798 continue;
799 }
800 }
801 else
802 {
803 /* In case of V is Network-LSA. */
0c0f9cd5 804 r = (struct in_addr *) p;
718e3744 805 p += sizeof (struct in_addr);
806
807 /* Lookup the vertex W's LSA. */
808 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_ROUTER_LSA, *r);
b75ae99e
PJ
809 if (w_lsa)
810 {
811 if (IS_DEBUG_OSPF_EVENT)
812 zlog_debug ("found Router LSA %s", inet_ntoa (w_lsa->data->id));
813 }
718e3744 814 }
815
816 /* (b cont.) If the LSA does not exist, or its LS age is equal
817 to MaxAge, or it does not have a link back to vertex V,
818 examine the next link in V's LSA.[23] */
819 if (w_lsa == NULL)
b75ae99e
PJ
820 {
821 if (IS_DEBUG_OSPF_EVENT)
822 zlog_debug ("No LSA found");
823 continue;
824 }
718e3744 825
826 if (IS_LSA_MAXAGE (w_lsa))
b75ae99e
PJ
827 {
828 if (IS_DEBUG_OSPF_EVENT)
829 zlog_debug ("LSA is MaxAge");
830 continue;
831 }
718e3744 832
eb3da6df 833 if (ospf_lsa_has_link (w_lsa->data, v->lsa) < 0 )
718e3744 834 {
0c0f9cd5 835 if (IS_DEBUG_OSPF_EVENT)
2a42e285 836 zlog_debug ("The LSA doesn't have a link back");
718e3744 837 continue;
838 }
839
840 /* (c) If vertex W is already on the shortest-path tree, examine
841 the next link in the LSA. */
462f20d5 842 if (w_lsa->stat == LSA_SPF_IN_SPFTREE)
843 {
844 if (IS_DEBUG_OSPF_EVENT)
845 zlog_debug ("The LSA is already in SPF");
846 continue;
847 }
718e3744 848
849 /* (d) Calculate the link state cost D of the resulting path
850 from the root to vertex W. D is equal to the sum of the link
851 state cost of the (already calculated) shortest path to
852 vertex V and the advertised cost of the link between vertices
853 V and W. If D is: */
854
718e3744 855 /* calculate link cost D. */
856 if (v->lsa->type == OSPF_ROUTER_LSA)
eb3da6df 857 distance = v->distance + ntohs (l->m[0].metric);
630e4807 858 else /* v is not a Router-LSA */
eb3da6df 859 distance = v->distance;
718e3744 860
861 /* Is there already vertex W in candidate list? */
462f20d5 862 if (w_lsa->stat == LSA_SPF_NOT_EXPLORED)
863 {
eb3da6df 864 /* prepare vertex W. */
865 w = ospf_vertex_new (w_lsa);
866
462f20d5 867 /* Calculate nexthop to W. */
bd34fb34 868 if (ospf_nexthop_calculation (area, v, w, l, distance))
bc20c1a4 869 pqueue_enqueue (w, candidate);
b75ae99e
PJ
870 else if (IS_DEBUG_OSPF_EVENT)
871 zlog_debug ("Nexthop Calc failed");
462f20d5 872 }
873 else if (w_lsa->stat >= 0)
874 {
875 /* Get the vertex from candidates. */
eb3da6df 876 w = candidate->array[w_lsa->stat];
718e3744 877
462f20d5 878 /* if D is greater than. */
eb3da6df 879 if (w->distance < distance)
718e3744 880 {
718e3744 881 continue;
882 }
462f20d5 883 /* equal to. */
eb3da6df 884 else if (w->distance == distance)
718e3744 885 {
eb3da6df 886 /* Found an equal-cost path to W.
887 * Calculate nexthop of to W from V. */
bd34fb34 888 ospf_nexthop_calculation (area, v, w, l, distance);
718e3744 889 }
462f20d5 890 /* less than. */
891 else
718e3744 892 {
bc20c1a4
PJ
893 /* Found a lower-cost path to W.
894 * nexthop_calculation is conditional, if it finds
895 * valid nexthop it will call spf_add_parents, which
896 * will flush the old parents
897 */
bd34fb34 898 if (ospf_nexthop_calculation (area, v, w, l, distance))
7591d8b8
PJ
899 /* Decrease the key of the node in the heap.
900 * trickle-sort it up towards root, just in case this
901 * node should now be the new root due the cost change.
902 * (pqueu_{de,en}queue
903 */
904 trickle_up (w_lsa->stat, candidate);
718e3744 905 }
630e4807 906 } /* end W is already on the candidate list */
907 } /* end loop over the links in V's LSA */
718e3744 908}
909
4dadc291 910static void
718e3744 911ospf_spf_dump (struct vertex *v, int i)
912{
52dc7ee6 913 struct listnode *cnode;
914 struct listnode *nnode;
eb3da6df 915 struct vertex_parent *parent;
718e3744 916
917 if (v->type == OSPF_VERTEX_ROUTER)
918 {
919 if (IS_DEBUG_OSPF_EVENT)
2a42e285 920 zlog_debug ("SPF Result: %d [R] %s", i, inet_ntoa (v->lsa->id));
718e3744 921 }
922 else
923 {
924 struct network_lsa *lsa = (struct network_lsa *) v->lsa;
925 if (IS_DEBUG_OSPF_EVENT)
2a42e285 926 zlog_debug ("SPF Result: %d [N] %s/%d", i, inet_ntoa (v->lsa->id),
0c0f9cd5 927 ip_masklen (lsa->mask));
630e4807 928 }
718e3744 929
1eb8ef25 930 if (IS_DEBUG_OSPF_EVENT)
eb3da6df 931 for (ALL_LIST_ELEMENTS_RO (v->parents, nnode, parent))
932 {
933 zlog_debug (" nexthop %p %s %s",
934 parent->nexthop,
935 inet_ntoa (parent->nexthop->router),
936 parent->nexthop->oi ? IF_NAME(parent->nexthop->oi)
937 : "NULL");
938 }
718e3744 939
940 i++;
941
eb3da6df 942 for (ALL_LIST_ELEMENTS_RO (v->children, cnode, v))
1eb8ef25 943 ospf_spf_dump (v, i);
718e3744 944}
945
946/* Second stage of SPF calculation. */
4dadc291 947static void
0c0f9cd5 948ospf_spf_process_stubs (struct ospf_area *area, struct vertex *v,
718e3744 949 struct route_table *rt)
950{
1eb8ef25 951 struct listnode *cnode, *cnnode;
718e3744 952 struct vertex *child;
953
954 if (IS_DEBUG_OSPF_EVENT)
2a42e285 955 zlog_debug ("ospf_process_stub():processing stubs for area %s",
0c0f9cd5 956 inet_ntoa (area->area_id));
718e3744 957 if (v->type == OSPF_VERTEX_ROUTER)
958 {
959 u_char *p;
960 u_char *lim;
961 struct router_lsa_link *l;
962 struct router_lsa *rlsa;
963
0c0f9cd5 964 if (IS_DEBUG_OSPF_EVENT)
2a42e285 965 zlog_debug ("ospf_process_stubs():processing router LSA, id: %s",
0c0f9cd5 966 inet_ntoa (v->lsa->id));
718e3744 967 rlsa = (struct router_lsa *) v->lsa;
968
969
0c0f9cd5 970 if (IS_DEBUG_OSPF_EVENT)
2a42e285 971 zlog_debug ("ospf_process_stubs(): we have %d links to process",
0c0f9cd5 972 ntohs (rlsa->links));
630e4807 973 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
718e3744 974 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
975
976 while (p < lim)
977 {
978 l = (struct router_lsa_link *) p;
979
980 p += (ROUTER_LSA_MIN_SIZE +
981 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
982
983 if (l->m[0].type == LSA_LINK_TYPE_STUB)
984 ospf_intra_add_stub (rt, l, v, area);
985 }
986 }
987
630e4807 988 ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1, 1);
718e3744 989
eb3da6df 990 for (ALL_LIST_ELEMENTS (v->children, cnode, cnnode, child))
718e3744 991 {
718e3744 992 if (CHECK_FLAG (child->flags, OSPF_VERTEX_PROCESSED))
0c0f9cd5 993 continue;
718e3744 994
995 ospf_spf_process_stubs (area, child, rt);
996
997 SET_FLAG (child->flags, OSPF_VERTEX_PROCESSED);
998 }
999}
1000
1001void
1002ospf_rtrs_free (struct route_table *rtrs)
1003{
1004 struct route_node *rn;
52dc7ee6 1005 struct list *or_list;
1eb8ef25 1006 struct ospf_route *or;
1007 struct listnode *node, *nnode;
718e3744 1008
1009 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1010 zlog_debug ("Route: Router Routing Table free");
718e3744 1011
1012 for (rn = route_top (rtrs); rn; rn = route_next (rn))
1013 if ((or_list = rn->info) != NULL)
1014 {
1eb8ef25 1015 for (ALL_LIST_ELEMENTS (or_list, node, nnode, or))
1016 ospf_route_free (or);
718e3744 1017
0c0f9cd5 1018 list_delete (or_list);
718e3744 1019
0c0f9cd5 1020 /* Unlock the node. */
1021 rn->info = NULL;
1022 route_unlock_node (rn);
718e3744 1023 }
1024 route_table_finish (rtrs);
1025}
1026
4dadc291 1027static void
718e3744 1028ospf_rtrs_print (struct route_table *rtrs)
1029{
1030 struct route_node *rn;
52dc7ee6 1031 struct list *or_list;
1032 struct listnode *ln;
1033 struct listnode *pnode;
718e3744 1034 struct ospf_route *or;
1035 struct ospf_path *path;
1036 char buf1[BUFSIZ];
1037 char buf2[BUFSIZ];
1038
1039 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1040 zlog_debug ("ospf_rtrs_print() start");
718e3744 1041
1042 for (rn = route_top (rtrs); rn; rn = route_next (rn))
1043 if ((or_list = rn->info) != NULL)
1eb8ef25 1044 for (ALL_LIST_ELEMENTS_RO (or_list, ln, or))
718e3744 1045 {
718e3744 1046 switch (or->path_type)
1047 {
1048 case OSPF_PATH_INTRA_AREA:
0c0f9cd5 1049 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1050 zlog_debug ("%s [%d] area: %s",
0c0f9cd5 1051 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1052 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1053 buf2, BUFSIZ));
718e3744 1054 break;
1055 case OSPF_PATH_INTER_AREA:
0c0f9cd5 1056 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1057 zlog_debug ("%s IA [%d] area: %s",
0c0f9cd5 1058 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1059 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1060 buf2, BUFSIZ));
718e3744 1061 break;
1062 default:
1063 break;
1064 }
1065
1eb8ef25 1066 for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path))
718e3744 1067 {
718e3744 1068 if (path->nexthop.s_addr == 0)
0c0f9cd5 1069 {
1070 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1071 zlog_debug (" directly attached to %s\r\n",
0c0f9cd5 1072 IF_NAME (path->oi));
1073 }
1074 else
1075 {
1076 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1077 zlog_debug (" via %s, %s\r\n",
0c0f9cd5 1078 inet_ntoa (path->nexthop), IF_NAME (path->oi));
1079 }
718e3744 1080 }
1081 }
1082
2a42e285 1083 zlog_debug ("ospf_rtrs_print() end");
718e3744 1084}
1085
1086/* Calculating the shortest-path tree for an area. */
4dadc291 1087static void
0c0f9cd5 1088ospf_spf_calculate (struct ospf_area *area, struct route_table *new_table,
718e3744 1089 struct route_table *new_rtrs)
1090{
462f20d5 1091 struct pqueue *candidate;
718e3744 1092 struct vertex *v;
eb3da6df 1093
718e3744 1094 if (IS_DEBUG_OSPF_EVENT)
1095 {
2a42e285 1096 zlog_debug ("ospf_spf_calculate: Start");
1097 zlog_debug ("ospf_spf_calculate: running Dijkstra for area %s",
0c0f9cd5 1098 inet_ntoa (area->area_id));
718e3744 1099 }
1100
1101 /* Check router-lsa-self. If self-router-lsa is not yet allocated,
1102 return this area's calculation. */
0c0f9cd5 1103 if (!area->router_lsa_self)
718e3744 1104 {
1105 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1106 zlog_debug ("ospf_spf_calculate: "
0c0f9cd5 1107 "Skip area %s's calculation due to empty router_lsa_self",
1108 inet_ntoa (area->area_id));
718e3744 1109 return;
1110 }
1111
1112 /* RFC2328 16.1. (1). */
0c0f9cd5 1113 /* Initialize the algorithm's data structures. */
462f20d5 1114
1115 /* This function scans all the LSA database and set the stat field to
1116 * LSA_SPF_NOT_EXPLORED. */
1117 ospf_lsdb_clean_stat (area->lsdb);
1118 /* Create a new heap for the candidates. */
1119 candidate = pqueue_create();
1120 candidate->cmp = cmp;
1121 candidate->update = update_stat;
718e3744 1122
1123 /* Initialize the shortest-path tree to only the root (which is the
1124 router doing the calculation). */
1125 ospf_spf_init (area);
1126 v = area->spf;
462f20d5 1127 /* Set LSA position to LSA_SPF_IN_SPFTREE. This vertex is the root of the
1128 * spanning tree. */
1129 *(v->stat) = LSA_SPF_IN_SPFTREE;
718e3744 1130
1131 /* Set Area A's TransitCapability to FALSE. */
1132 area->transit = OSPF_TRANSIT_FALSE;
1133 area->shortcut_capability = 1;
eb3da6df 1134
718e3744 1135 for (;;)
1136 {
1137 /* RFC2328 16.1. (2). */
462f20d5 1138 ospf_spf_next (v, area, candidate);
718e3744 1139
1140 /* RFC2328 16.1. (3). */
1141 /* If at this step the candidate list is empty, the shortest-
1142 path tree (of transit vertices) has been completely built and
1143 this stage of the procedure terminates. */
462f20d5 1144 if (candidate->size == 0)
718e3744 1145 break;
1146
1147 /* Otherwise, choose the vertex belonging to the candidate list
1148 that is closest to the root, and add it to the shortest-path
1149 tree (removing it from the candidate list in the
0c0f9cd5 1150 process). */
462f20d5 1151 /* Extract from the candidates the node with the lower key. */
1152 v = (struct vertex *) pqueue_dequeue (candidate);
1153 /* Update stat field in vertex. */
1154 *(v->stat) = LSA_SPF_IN_SPFTREE;
eb3da6df 1155
718e3744 1156 ospf_vertex_add_parent (v);
1157
718e3744 1158 /* Note that when there is a choice of vertices closest to the
1159 root, network vertices must be chosen before router vertices
1160 in order to necessarily find all equal-cost paths. */
1161 /* We don't do this at this moment, we should add the treatment
1162 above codes. -- kunihiro. */
1163
1164 /* RFC2328 16.1. (4). */
1165 if (v->type == OSPF_VERTEX_ROUTER)
1166 ospf_intra_add_router (new_rtrs, v, area);
0c0f9cd5 1167 else
718e3744 1168 ospf_intra_add_transit (new_table, v, area);
1169
1170 /* RFC2328 16.1. (5). */
1171 /* Iterate the algorithm by returning to Step 2. */
630e4807 1172
1173 } /* end loop until no more candidate vertices */
718e3744 1174
1175 if (IS_DEBUG_OSPF_EVENT)
1176 {
1177 ospf_spf_dump (area->spf, 0);
1178 ospf_route_table_dump (new_table);
1179 }
1180
1181 /* Second stage of SPF calculation procedure's */
1182 ospf_spf_process_stubs (area, area->spf, new_table);
1183
eb3da6df 1184 /* Free candidate queue. */
462f20d5 1185 pqueue_delete (candidate);
eb3da6df 1186
1187 ospf_vertex_dump (__func__, area->spf, 0, 1);
1188 /* Free nexthop information, canonical versions of which are attached
1189 * the first level of router vertices attached to the root vertex, see
1190 * ospf_nexthop_calculation.
1191 */
1192 ospf_canonical_nexthops_free (area->spf);
1193
9c27ef9b
PJ
1194 /* Free SPF vertices, but not the list. List has ospf_vertex_free
1195 * as deconstructor.
1196 */
1197 list_delete_all_node (&vertex_list);
eb3da6df 1198
718e3744 1199 /* Increment SPF Calculation Counter. */
1200 area->spf_calculation++;
1201
2518efd1 1202 quagga_gettime (QUAGGA_CLK_MONOTONIC, &area->ospf->ts_spf);
718e3744 1203
1204 if (IS_DEBUG_OSPF_EVENT)
9c27ef9b
PJ
1205 zlog_debug ("ospf_spf_calculate: Stop. %ld vertices",
1206 mtype_stats_alloc(MTYPE_OSPF_VERTEX));
718e3744 1207}
1208\f
1209/* Timer for SPF calculation. */
4dadc291 1210static int
68980084 1211ospf_spf_calculate_timer (struct thread *thread)
718e3744 1212{
68980084 1213 struct ospf *ospf = THREAD_ARG (thread);
718e3744 1214 struct route_table *new_table, *new_rtrs;
1eb8ef25 1215 struct ospf_area *area;
1216 struct listnode *node, *nnode;
718e3744 1217
1218 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1219 zlog_debug ("SPF: Timer (SPF calculation expire)");
0c0f9cd5 1220
718e3744 1221 ospf->t_spf_calc = NULL;
1222
1223 /* Allocate new table tree. */
1224 new_table = route_table_init ();
0c0f9cd5 1225 new_rtrs = route_table_init ();
718e3744 1226
68980084 1227 ospf_vl_unapprove (ospf);
718e3744 1228
1229 /* Calculate SPF for each area. */
1eb8ef25 1230 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
9c27ef9b
PJ
1231 {
1232 /* Do backbone last, so as to first discover intra-area paths
1233 * for any back-bone virtual-links
1234 */
1235 if (ospf->backbone && ospf->backbone == area)
1236 continue;
1237
1238 ospf_spf_calculate (area, new_table, new_rtrs);
1239 }
1240
1241 /* SPF for backbone, if required */
1242 if (ospf->backbone)
1243 ospf_spf_calculate (ospf->backbone, new_table, new_rtrs);
1244
68980084 1245 ospf_vl_shut_unapproved (ospf);
718e3744 1246
68980084 1247 ospf_ia_routing (ospf, new_table, new_rtrs);
718e3744 1248
1249 ospf_prune_unreachable_networks (new_table);
1250 ospf_prune_unreachable_routers (new_rtrs);
1251
1252 /* AS-external-LSA calculation should not be performed here. */
1253
1254 /* If new Router Route is installed,
1255 then schedule re-calculate External routes. */
1256 if (1)
68980084 1257 ospf_ase_calculate_schedule (ospf);
718e3744 1258
68980084 1259 ospf_ase_calculate_timer_add (ospf);
718e3744 1260
1261 /* Update routing table. */
68980084 1262 ospf_route_install (ospf, new_table);
718e3744 1263
1264 /* Update ABR/ASBR routing table */
68980084 1265 if (ospf->old_rtrs)
718e3744 1266 {
1267 /* old_rtrs's node holds linked list of ospf_route. --kunihiro. */
68980084 1268 /* ospf_route_delete (ospf->old_rtrs); */
1269 ospf_rtrs_free (ospf->old_rtrs);
718e3744 1270 }
1271
68980084 1272 ospf->old_rtrs = ospf->new_rtrs;
1273 ospf->new_rtrs = new_rtrs;
718e3744 1274
0c0f9cd5 1275 if (IS_OSPF_ABR (ospf))
68980084 1276 ospf_abr_task (ospf);
718e3744 1277
1278 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1279 zlog_debug ("SPF: calculation complete");
718e3744 1280
1281 return 0;
1282}
1283
1284/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
1285 set timer for SPF calc. */
1286void
68980084 1287ospf_spf_calculate_schedule (struct ospf *ospf)
718e3744 1288{
d24f6e2a 1289 unsigned long delay, elapsed, ht;
1290 struct timeval result;
718e3744 1291
1292 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1293 zlog_debug ("SPF: calculation timer scheduled");
718e3744 1294
1295 /* OSPF instance does not exist. */
68980084 1296 if (ospf == NULL)
718e3744 1297 return;
d24f6e2a 1298
718e3744 1299 /* SPF calculation timer is already scheduled. */
68980084 1300 if (ospf->t_spf_calc)
718e3744 1301 {
1302 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1303 zlog_debug ("SPF: calculation timer is already scheduled: %p",
0c0f9cd5 1304 ospf->t_spf_calc);
718e3744 1305 return;
1306 }
d24f6e2a 1307
1308 /* XXX Monotic timers: we only care about relative time here. */
2518efd1 1309 result = tv_sub (recent_relative_time (), ospf->ts_spf);
d24f6e2a 1310
1311 elapsed = (result.tv_sec * 1000) + (result.tv_usec / 1000);
1312 ht = ospf->spf_holdtime * ospf->spf_hold_multiplier;
1313
1314 if (ht > ospf->spf_max_holdtime)
1315 ht = ospf->spf_max_holdtime;
1316
718e3744 1317 /* Get SPF calculation delay time. */
d24f6e2a 1318 if (elapsed < ht)
718e3744 1319 {
d24f6e2a 1320 /* Got an event within the hold time of last SPF. We need to
1321 * increase the hold_multiplier, if it's not already at/past
1322 * maximum value, and wasn't already increased..
1323 */
1324 if (ht < ospf->spf_max_holdtime)
1325 ospf->spf_hold_multiplier++;
1326
1327 /* always honour the SPF initial delay */
1328 if ( (ht - elapsed) < ospf->spf_delay)
0c0f9cd5 1329 delay = ospf->spf_delay;
718e3744 1330 else
d24f6e2a 1331 delay = ht - elapsed;
718e3744 1332 }
1333 else
d24f6e2a 1334 {
1335 /* Event is past required hold-time of last SPF */
1336 delay = ospf->spf_delay;
1337 ospf->spf_hold_multiplier = 1;
1338 }
1339
718e3744 1340 if (IS_DEBUG_OSPF_EVENT)
d24f6e2a 1341 zlog_debug ("SPF: calculation timer delay = %ld", delay);
1342
68980084 1343 ospf->t_spf_calc =
d24f6e2a 1344 thread_add_timer_msec (master, ospf_spf_calculate_timer, ospf, delay);
718e3744 1345}