]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_spf.c
ospfd: Discriminate better when selecting links between vertices in SPF
[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;
bd540377 372 u_char lsa_type = LSA_LINK_TYPE_TRANSIT;
718e3744 373 struct router_lsa_link *l;
374
bd540377
JT
375 if (w->type == OSPF_VERTEX_ROUTER)
376 lsa_type = LSA_LINK_TYPE_POINTOPOINT;
377
718e3744 378 if (prev_link == NULL)
630e4807 379 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
718e3744 380 else
381 {
0c0f9cd5 382 p = (u_char *) prev_link;
718e3744 383 p += (ROUTER_LSA_MIN_SIZE +
384 (prev_link->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
385 }
0c0f9cd5 386
718e3744 387 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
388
389 while (p < lim)
390 {
391 l = (struct router_lsa_link *) p;
392
0c0f9cd5 393 p += (ROUTER_LSA_MIN_SIZE + (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
718e3744 394
bd540377 395 if (l->m[0].type != lsa_type)
0c0f9cd5 396 continue;
718e3744 397
398 if (IPV4_ADDR_SAME (&l->link_id, &w->id))
0c0f9cd5 399 return l;
718e3744 400 }
401
402 return NULL;
403}
404
bc20c1a4
PJ
405static void
406ospf_spf_flush_parents (struct vertex *w)
407{
408 struct vertex_parent *vp;
409 struct listnode *ln, *nn;
410
411 /* delete the existing nexthops */
412 for (ALL_LIST_ELEMENTS (w->parents, ln, nn, vp))
413 {
414 list_delete_node (w->parents, ln);
415 vertex_parent_free (vp);
416 }
417}
418
75ee0b8e 419/*
420 * Consider supplied next-hop for inclusion to the supplied list of
421 * equal-cost next-hops, adjust list as neccessary.
bf9392c6 422 */
4dadc291 423static void
eb3da6df 424ospf_spf_add_parent (struct vertex *v, struct vertex *w,
bc20c1a4 425 struct vertex_nexthop *newhop,
bd34fb34 426 unsigned int distance)
bf9392c6 427{
eb3da6df 428 struct vertex_parent *vp;
429
08d3d5b3 430 /* we must have a newhop, and a distance */
bd34fb34 431 assert (v && w && newhop);
08d3d5b3 432 assert (distance);
eb3da6df 433
08d3d5b3
PJ
434 /* IFF w has already been assigned a distance, then we shouldn't get here
435 * unless callers have determined V(l)->W is shortest / equal-shortest
436 * path (0 is a special case distance (no distance yet assigned)).
bc20c1a4 437 */
08d3d5b3
PJ
438 if (w->distance)
439 assert (distance <= w->distance);
440 else
441 w->distance = distance;
bc20c1a4 442
b75ae99e
PJ
443 if (IS_DEBUG_OSPF_EVENT)
444 {
445 char buf[2][INET_ADDRSTRLEN];
446 zlog_debug ("%s: Adding %s as parent of %s",
447 __func__,
448 inet_ntop(AF_INET, &v->lsa->id, buf[0], sizeof(buf[0])),
449 inet_ntop(AF_INET, &w->lsa->id, buf[1], sizeof(buf[1])));
450 }
451
bc20c1a4 452 /* Adding parent for a new, better path: flush existing parents from W. */
bd34fb34 453 if (distance < w->distance)
bc20c1a4 454 {
b75ae99e
PJ
455 if (IS_DEBUG_OSPF_EVENT)
456 zlog_debug ("%s: distance %d better than %d, flushing existing parents",
457 __func__, distance, w->distance);
bc20c1a4 458 ospf_spf_flush_parents (w);
bd34fb34 459 w->distance = distance;
bc20c1a4
PJ
460 }
461
462 /* new parent is <= existing parents, add it to parent list */
eb3da6df 463 vp = vertex_parent_new (v, ospf_lsa_has_link (w->lsa, v->lsa), newhop);
464 listnode_add (w->parents, vp);
0c0f9cd5 465
eb3da6df 466 return;
467}
468
630e4807 469/* 16.1.1. Calculate nexthop from root through V (parent) to
bd34fb34 470 * vertex W (destination), with given distance from root->W.
eb3da6df 471 *
472 * The link must be supplied if V is the root vertex. In all other cases
473 * it may be NULL.
bd34fb34
PJ
474 *
475 * Note that this function may fail, hence the state of the destination
476 * vertex, W, should /not/ be modified in a dependent manner until
477 * this function returns. This function will update the W vertex with the
478 * provided distance as appropriate.
630e4807 479 */
bc20c1a4 480static unsigned int
eb3da6df 481ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v,
bd34fb34
PJ
482 struct vertex *w, struct router_lsa_link *l,
483 unsigned int distance)
718e3744 484{
1eb8ef25 485 struct listnode *node, *nnode;
eb3da6df 486 struct vertex_nexthop *nh;
487 struct vertex_parent *vp;
718e3744 488 struct ospf_interface *oi = NULL;
bc20c1a4 489 unsigned int added = 0;
0c0f9cd5 490
718e3744 491 if (IS_DEBUG_OSPF_EVENT)
630e4807 492 {
2a42e285 493 zlog_debug ("ospf_nexthop_calculation(): Start");
630e4807 494 ospf_vertex_dump("V (parent):", v, 1, 1);
495 ospf_vertex_dump("W (dest) :", w, 1, 1);
bd34fb34 496 zlog_debug ("V->W distance: %d", distance);
630e4807 497 }
718e3744 498
718e3744 499 if (v == area->spf)
9c27ef9b 500 {
630e4807 501 /* 16.1.1 para 4. In the first case, the parent vertex (V) is the
502 root (the calculating router itself). This means that the
503 destination is either a directly connected network or directly
504 connected router. The outgoing interface in this case is simply
505 the OSPF interface connecting to the destination network/router.
506 */
507
718e3744 508 if (w->type == OSPF_VERTEX_ROUTER)
0c0f9cd5 509 {
eb3da6df 510 /* l is a link from v to w
511 * l2 will be link from w to v
512 */
513 struct router_lsa_link *l2 = NULL;
514
515 /* we *must* be supplied with the link data */
516 assert (l != NULL);
517
518 if (IS_DEBUG_OSPF_EVENT)
0c0f9cd5 519 {
eb3da6df 520 char buf1[BUFSIZ];
521 char buf2[BUFSIZ];
522
523 zlog_debug("ospf_nexthop_calculation(): considering link "
524 "type %d link_id %s link_data %s",
525 l->m[0].type,
526 inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ),
527 inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ));
528 }
529
530 if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT)
531 {
532 /* If the destination is a router which connects to
533 the calculating router via a Point-to-MultiPoint
534 network, the destination's next hop IP address(es)
535 can be determined by examining the destination's
536 router-LSA: each link pointing back to the
537 calculating router and having a Link Data field
538 belonging to the Point-to-MultiPoint network
539 provides an IP address of the next hop router.
540
541 At this point l is a link from V to W, and V is the
542 root ("us"). Find the local interface associated
543 with l (its address is in l->link_data). If it
544 is a point-to-multipoint interface, then look through
545 the links in the opposite direction (W to V). If
546 any of them have an address that lands within the
547 subnet declared by the PtMP link, then that link
548 is a constituent of the PtMP link, and its address is
549 a nexthop address for V.
550 */
551 oi = ospf_if_is_configured (area->ospf, &l->link_data);
552 if (oi && oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
0c0f9cd5 553 {
eb3da6df 554 struct prefix_ipv4 la;
555
556 la.family = AF_INET;
557 la.prefixlen = oi->address->prefixlen;
558
559 /* V links to W on PtMP interface
560 - find the interface address on W */
561 while ((l2 = ospf_get_next_link (w, v, l2)))
0c0f9cd5 562 {
eb3da6df 563 la.prefix = l2->link_data;
0c0f9cd5 564
eb3da6df 565 if (prefix_cmp ((struct prefix *) &la,
566 oi->address) == 0)
567 /* link_data is on our PtMP network */
568 break;
569 }
570 } /* end l is on point-to-multipoint link */
571 else
572 {
573 /* l is a regular point-to-point link.
574 Look for a link from W to V.
575 */
576 while ((l2 = ospf_get_next_link (w, v, l2)))
0c0f9cd5 577 {
eb3da6df 578 oi = ospf_if_is_configured (area->ospf,
579 &(l2->link_data));
580
581 if (oi == NULL)
582 continue;
583
584 if (!IPV4_ADDR_SAME (&oi->address->u.prefix4,
585 &l->link_data))
586 continue;
587
588 break;
0c0f9cd5 589 }
eb3da6df 590 }
591
592 if (oi && l2)
593 {
594 /* found all necessary info to build nexthop */
595 nh = vertex_nexthop_new ();
596 nh->oi = oi;
597 nh->router = l2->link_data;
bd34fb34 598 ospf_spf_add_parent (v, w, nh, distance);
bc20c1a4 599 return 1;
eb3da6df 600 }
601 else
9c27ef9b
PJ
602 zlog_info("ospf_nexthop_calculation(): "
603 "could not determine nexthop for link");
604 } /* end point-to-point link from V to W */
605 else if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK)
606 {
607 struct ospf_vl_data *vl_data;
608
609 /* VLink implementation limitations:
610 * a) vl_data can only reference one nexthop, so no ECMP
611 * to backbone through VLinks. Though transit-area
612 * summaries may be considered, and those can be ECMP.
613 * b) We can only use /one/ VLink, even if multiple ones
614 * exist this router through multiple transit-areas.
615 */
616 vl_data = ospf_vl_lookup (area->ospf, NULL, l->link_id);
617
618 if (vl_data
619 && CHECK_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED))
eb3da6df 620 {
9c27ef9b
PJ
621 nh = vertex_nexthop_new ();
622 nh->oi = vl_data->nexthop.oi;
623 nh->router = vl_data->nexthop.router;
bd34fb34 624 ospf_spf_add_parent (v, w, nh, distance);
bc20c1a4 625 return 1;
eb3da6df 626 }
9c27ef9b 627 else
bc20c1a4
PJ
628 zlog_info("ospf_nexthop_calculation(): "
629 "vl_data for VL link not found");
9c27ef9b 630 } /* end virtual-link from V to W */
bc20c1a4 631 return 0;
630e4807 632 } /* end W is a Router vertex */
718e3744 633 else
0c0f9cd5 634 {
eb3da6df 635 assert(w->type == OSPF_VERTEX_NETWORK);
636 oi = ospf_if_is_configured (area->ospf, &(l->link_data));
637 if (oi)
0c0f9cd5 638 {
eb3da6df 639 nh = vertex_nexthop_new ();
640 nh->oi = oi;
641 nh->router.s_addr = 0;
bd34fb34 642 ospf_spf_add_parent (v, w, nh, distance);
bc20c1a4 643 return 1;
0c0f9cd5 644 }
645 }
9c27ef9b
PJ
646 zlog_info("ospf_nexthop_calculation(): "
647 "Unknown attached link");
bc20c1a4 648 return 0;
630e4807 649 } /* end V is the root */
630e4807 650 /* Check if W's parent is a network connected to root. */
718e3744 651 else if (v->type == OSPF_VERTEX_NETWORK)
652 {
630e4807 653 /* See if any of V's parents are the root. */
eb3da6df 654 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
718e3744 655 {
eb3da6df 656 if (vp->parent == area->spf) /* connects to root? */
630e4807 657 {
658 /* 16.1.1 para 5. ...the parent vertex is a network that
659 * directly connects the calculating router to the destination
660 * router. The list of next hops is then determined by
661 * examining the destination's router-LSA...
662 */
663
664 assert(w->type == OSPF_VERTEX_ROUTER);
0c0f9cd5 665 while ((l = ospf_get_next_link (w, v, l)))
666 {
630e4807 667 /* ...For each link in the router-LSA that points back to the
668 * parent network, the link's Link Data field provides the IP
669 * address of a next hop router. The outgoing interface to
670 * use can then be derived from the next hop IP address (or
671 * it can be inherited from the parent network).
672 */
eb3da6df 673 nh = vertex_nexthop_new ();
674 nh->oi = vp->nexthop->oi;
675 nh->router = l->link_data;
bc20c1a4 676 added = 1;
bd34fb34 677 ospf_spf_add_parent (v, w, nh, distance);
0c0f9cd5 678 }
0c0f9cd5 679 }
718e3744 680 }
85ef784e
PJ
681 if (added)
682 return added;
718e3744 683 }
684
630e4807 685 /* 16.1.1 para 4. If there is at least one intervening router in the
686 * current shortest path between the destination and the root, the
687 * destination simply inherits the set of next hops from the
688 * parent.
689 */
b75ae99e
PJ
690 if (IS_DEBUG_OSPF_EVENT)
691 zlog_debug ("%s: Intervening routers, adding parent(s)", __func__);
692
eb3da6df 693 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
bc20c1a4
PJ
694 {
695 added = 1;
bd34fb34 696 ospf_spf_add_parent (v, w, vp->nexthop, distance);
bc20c1a4 697 }
9c27ef9b 698
bc20c1a4 699 return added;
718e3744 700}
701
630e4807 702/* RFC2328 Section 16.1 (2).
703 * v is on the SPF tree. Examine the links in v's LSA. Update the list
704 * of candidates with any vertices not already on the list. If a lower-cost
705 * path is found to a vertex already on the candidate list, store the new cost.
706 */
4dadc291 707static void
718e3744 708ospf_spf_next (struct vertex *v, struct ospf_area *area,
462f20d5 709 struct pqueue * candidate)
718e3744 710{
711 struct ospf_lsa *w_lsa = NULL;
718e3744 712 u_char *p;
713 u_char *lim;
714 struct router_lsa_link *l = NULL;
715 struct in_addr *r;
718e3744 716 int type = 0;
717
718 /* If this is a router-LSA, and bit V of the router-LSA (see Section
719 A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE. */
720 if (v->type == OSPF_VERTEX_ROUTER)
721 {
722 if (IS_ROUTER_LSA_VIRTUAL ((struct router_lsa *) v->lsa))
723 area->transit = OSPF_TRANSIT_TRUE;
724 }
b75ae99e
PJ
725
726 if (IS_DEBUG_OSPF_EVENT)
727 zlog_debug ("%s: Next vertex of %s vertex %s",
728 __func__,
729 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
730 inet_ntoa(v->lsa->id));
731
718e3744 732 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
0c0f9cd5 733 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
734
718e3744 735 while (p < lim)
736 {
eb3da6df 737 struct vertex *w;
738 unsigned int distance;
d355bfa7 739
718e3744 740 /* In case of V is Router-LSA. */
741 if (v->lsa->type == OSPF_ROUTER_LSA)
742 {
743 l = (struct router_lsa_link *) p;
744
0c0f9cd5 745 p += (ROUTER_LSA_MIN_SIZE +
718e3744 746 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
747
748 /* (a) If this is a link to a stub network, examine the next
749 link in V's LSA. Links to stub networks will be
750 considered in the second stage of the shortest path
751 calculation. */
752 if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB)
753 continue;
08d3d5b3
PJ
754
755 /* Infinite distance links shouldn't be followed, except
756 * for local links (a stub-routed router still wants to
757 * calculate tree, so must follow its own links).
758 */
759 if ((v != area->spf) && l->m[0].metric >= OSPF_OUTPUT_COST_INFINITE)
760 continue;
718e3744 761
762 /* (b) Otherwise, W is a transit vertex (router or transit
763 network). Look up the vertex W's LSA (router-LSA or
764 network-LSA) in Area A's link state database. */
765 switch (type)
766 {
767 case LSA_LINK_TYPE_POINTOPOINT:
768 case LSA_LINK_TYPE_VIRTUALLINK:
769 if (type == LSA_LINK_TYPE_VIRTUALLINK)
0c0f9cd5 770 {
771 if (IS_DEBUG_OSPF_EVENT)
2a42e285 772 zlog_debug ("looking up LSA through VL: %s",
0c0f9cd5 773 inet_ntoa (l->link_id));
774 }
718e3744 775
776 w_lsa = ospf_lsa_lookup (area, OSPF_ROUTER_LSA, l->link_id,
777 l->link_id);
778 if (w_lsa)
0c0f9cd5 779 {
780 if (IS_DEBUG_OSPF_EVENT)
2a42e285 781 zlog_debug ("found Router LSA %s", inet_ntoa (l->link_id));
0c0f9cd5 782 }
718e3744 783 break;
784 case LSA_LINK_TYPE_TRANSIT:
0c0f9cd5 785 if (IS_DEBUG_OSPF_EVENT)
2a42e285 786 zlog_debug ("Looking up Network LSA, ID: %s",
0c0f9cd5 787 inet_ntoa (l->link_id));
718e3744 788 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_NETWORK_LSA,
0c0f9cd5 789 l->link_id);
718e3744 790 if (w_lsa)
0c0f9cd5 791 if (IS_DEBUG_OSPF_EVENT)
2a42e285 792 zlog_debug ("found the LSA");
718e3744 793 break;
794 default:
0c0f9cd5 795 zlog_warn ("Invalid LSA link type %d", type);
718e3744 796 continue;
797 }
798 }
799 else
800 {
801 /* In case of V is Network-LSA. */
0c0f9cd5 802 r = (struct in_addr *) p;
718e3744 803 p += sizeof (struct in_addr);
804
805 /* Lookup the vertex W's LSA. */
806 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_ROUTER_LSA, *r);
b75ae99e
PJ
807 if (w_lsa)
808 {
809 if (IS_DEBUG_OSPF_EVENT)
810 zlog_debug ("found Router LSA %s", inet_ntoa (w_lsa->data->id));
811 }
718e3744 812 }
813
814 /* (b cont.) If the LSA does not exist, or its LS age is equal
815 to MaxAge, or it does not have a link back to vertex V,
816 examine the next link in V's LSA.[23] */
817 if (w_lsa == NULL)
b75ae99e
PJ
818 {
819 if (IS_DEBUG_OSPF_EVENT)
820 zlog_debug ("No LSA found");
821 continue;
822 }
718e3744 823
824 if (IS_LSA_MAXAGE (w_lsa))
b75ae99e
PJ
825 {
826 if (IS_DEBUG_OSPF_EVENT)
827 zlog_debug ("LSA is MaxAge");
828 continue;
829 }
718e3744 830
eb3da6df 831 if (ospf_lsa_has_link (w_lsa->data, v->lsa) < 0 )
718e3744 832 {
0c0f9cd5 833 if (IS_DEBUG_OSPF_EVENT)
2a42e285 834 zlog_debug ("The LSA doesn't have a link back");
718e3744 835 continue;
836 }
837
838 /* (c) If vertex W is already on the shortest-path tree, examine
839 the next link in the LSA. */
462f20d5 840 if (w_lsa->stat == LSA_SPF_IN_SPFTREE)
841 {
842 if (IS_DEBUG_OSPF_EVENT)
843 zlog_debug ("The LSA is already in SPF");
844 continue;
845 }
718e3744 846
847 /* (d) Calculate the link state cost D of the resulting path
848 from the root to vertex W. D is equal to the sum of the link
849 state cost of the (already calculated) shortest path to
850 vertex V and the advertised cost of the link between vertices
851 V and W. If D is: */
852
718e3744 853 /* calculate link cost D. */
854 if (v->lsa->type == OSPF_ROUTER_LSA)
eb3da6df 855 distance = v->distance + ntohs (l->m[0].metric);
630e4807 856 else /* v is not a Router-LSA */
eb3da6df 857 distance = v->distance;
718e3744 858
859 /* Is there already vertex W in candidate list? */
462f20d5 860 if (w_lsa->stat == LSA_SPF_NOT_EXPLORED)
861 {
eb3da6df 862 /* prepare vertex W. */
863 w = ospf_vertex_new (w_lsa);
864
462f20d5 865 /* Calculate nexthop to W. */
bd34fb34 866 if (ospf_nexthop_calculation (area, v, w, l, distance))
bc20c1a4 867 pqueue_enqueue (w, candidate);
b75ae99e
PJ
868 else if (IS_DEBUG_OSPF_EVENT)
869 zlog_debug ("Nexthop Calc failed");
462f20d5 870 }
871 else if (w_lsa->stat >= 0)
872 {
873 /* Get the vertex from candidates. */
eb3da6df 874 w = candidate->array[w_lsa->stat];
718e3744 875
462f20d5 876 /* if D is greater than. */
eb3da6df 877 if (w->distance < distance)
718e3744 878 {
718e3744 879 continue;
880 }
462f20d5 881 /* equal to. */
eb3da6df 882 else if (w->distance == distance)
718e3744 883 {
eb3da6df 884 /* Found an equal-cost path to W.
885 * Calculate nexthop of to W from V. */
bd34fb34 886 ospf_nexthop_calculation (area, v, w, l, distance);
718e3744 887 }
462f20d5 888 /* less than. */
889 else
718e3744 890 {
bc20c1a4
PJ
891 /* Found a lower-cost path to W.
892 * nexthop_calculation is conditional, if it finds
893 * valid nexthop it will call spf_add_parents, which
894 * will flush the old parents
895 */
bd34fb34 896 if (ospf_nexthop_calculation (area, v, w, l, distance))
7591d8b8
PJ
897 /* Decrease the key of the node in the heap.
898 * trickle-sort it up towards root, just in case this
899 * node should now be the new root due the cost change.
e95537f0 900 * (next pqueu_{de,en}queue will fully re-heap the queue).
7591d8b8
PJ
901 */
902 trickle_up (w_lsa->stat, candidate);
718e3744 903 }
630e4807 904 } /* end W is already on the candidate list */
905 } /* end loop over the links in V's LSA */
718e3744 906}
907
4dadc291 908static void
718e3744 909ospf_spf_dump (struct vertex *v, int i)
910{
52dc7ee6 911 struct listnode *cnode;
912 struct listnode *nnode;
eb3da6df 913 struct vertex_parent *parent;
718e3744 914
915 if (v->type == OSPF_VERTEX_ROUTER)
916 {
917 if (IS_DEBUG_OSPF_EVENT)
2a42e285 918 zlog_debug ("SPF Result: %d [R] %s", i, inet_ntoa (v->lsa->id));
718e3744 919 }
920 else
921 {
922 struct network_lsa *lsa = (struct network_lsa *) v->lsa;
923 if (IS_DEBUG_OSPF_EVENT)
2a42e285 924 zlog_debug ("SPF Result: %d [N] %s/%d", i, inet_ntoa (v->lsa->id),
0c0f9cd5 925 ip_masklen (lsa->mask));
630e4807 926 }
718e3744 927
1eb8ef25 928 if (IS_DEBUG_OSPF_EVENT)
eb3da6df 929 for (ALL_LIST_ELEMENTS_RO (v->parents, nnode, parent))
930 {
931 zlog_debug (" nexthop %p %s %s",
932 parent->nexthop,
933 inet_ntoa (parent->nexthop->router),
934 parent->nexthop->oi ? IF_NAME(parent->nexthop->oi)
935 : "NULL");
936 }
718e3744 937
938 i++;
939
eb3da6df 940 for (ALL_LIST_ELEMENTS_RO (v->children, cnode, v))
1eb8ef25 941 ospf_spf_dump (v, i);
718e3744 942}
943
944/* Second stage of SPF calculation. */
4dadc291 945static void
0c0f9cd5 946ospf_spf_process_stubs (struct ospf_area *area, struct vertex *v,
b3bc68e5
PJ
947 struct route_table *rt,
948 int parent_is_root)
718e3744 949{
1eb8ef25 950 struct listnode *cnode, *cnnode;
718e3744 951 struct vertex *child;
952
953 if (IS_DEBUG_OSPF_EVENT)
2a42e285 954 zlog_debug ("ospf_process_stub():processing stubs for area %s",
0c0f9cd5 955 inet_ntoa (area->area_id));
718e3744 956 if (v->type == OSPF_VERTEX_ROUTER)
957 {
958 u_char *p;
959 u_char *lim;
960 struct router_lsa_link *l;
961 struct router_lsa *rlsa;
962
0c0f9cd5 963 if (IS_DEBUG_OSPF_EVENT)
2a42e285 964 zlog_debug ("ospf_process_stubs():processing router LSA, id: %s",
0c0f9cd5 965 inet_ntoa (v->lsa->id));
718e3744 966 rlsa = (struct router_lsa *) v->lsa;
967
968
0c0f9cd5 969 if (IS_DEBUG_OSPF_EVENT)
2a42e285 970 zlog_debug ("ospf_process_stubs(): we have %d links to process",
0c0f9cd5 971 ntohs (rlsa->links));
630e4807 972 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
718e3744 973 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
974
975 while (p < lim)
976 {
977 l = (struct router_lsa_link *) p;
978
979 p += (ROUTER_LSA_MIN_SIZE +
980 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
981
982 if (l->m[0].type == LSA_LINK_TYPE_STUB)
b3bc68e5 983 ospf_intra_add_stub (rt, l, v, area, parent_is_root);
718e3744 984 }
985 }
986
630e4807 987 ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1, 1);
718e3744 988
eb3da6df 989 for (ALL_LIST_ELEMENTS (v->children, cnode, cnnode, child))
718e3744 990 {
718e3744 991 if (CHECK_FLAG (child->flags, OSPF_VERTEX_PROCESSED))
0c0f9cd5 992 continue;
b3bc68e5
PJ
993
994 /* the first level of routers connected to the root
995 * should have 'parent_is_root' set, including those
996 * connected via a network vertex.
997 */
998 if (area->spf == v)
999 parent_is_root = 1;
1000 else if (v->type == OSPF_VERTEX_ROUTER)
1001 parent_is_root = 0;
1002
1003 ospf_spf_process_stubs (area, child, rt, parent_is_root);
718e3744 1004
1005 SET_FLAG (child->flags, OSPF_VERTEX_PROCESSED);
1006 }
1007}
1008
1009void
1010ospf_rtrs_free (struct route_table *rtrs)
1011{
1012 struct route_node *rn;
52dc7ee6 1013 struct list *or_list;
1eb8ef25 1014 struct ospf_route *or;
1015 struct listnode *node, *nnode;
718e3744 1016
1017 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1018 zlog_debug ("Route: Router Routing Table free");
718e3744 1019
1020 for (rn = route_top (rtrs); rn; rn = route_next (rn))
1021 if ((or_list = rn->info) != NULL)
1022 {
1eb8ef25 1023 for (ALL_LIST_ELEMENTS (or_list, node, nnode, or))
1024 ospf_route_free (or);
718e3744 1025
0c0f9cd5 1026 list_delete (or_list);
718e3744 1027
0c0f9cd5 1028 /* Unlock the node. */
1029 rn->info = NULL;
1030 route_unlock_node (rn);
718e3744 1031 }
1032 route_table_finish (rtrs);
1033}
1034
4dadc291 1035static void
718e3744 1036ospf_rtrs_print (struct route_table *rtrs)
1037{
1038 struct route_node *rn;
52dc7ee6 1039 struct list *or_list;
1040 struct listnode *ln;
1041 struct listnode *pnode;
718e3744 1042 struct ospf_route *or;
1043 struct ospf_path *path;
1044 char buf1[BUFSIZ];
1045 char buf2[BUFSIZ];
1046
1047 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1048 zlog_debug ("ospf_rtrs_print() start");
718e3744 1049
1050 for (rn = route_top (rtrs); rn; rn = route_next (rn))
1051 if ((or_list = rn->info) != NULL)
1eb8ef25 1052 for (ALL_LIST_ELEMENTS_RO (or_list, ln, or))
718e3744 1053 {
718e3744 1054 switch (or->path_type)
1055 {
1056 case OSPF_PATH_INTRA_AREA:
0c0f9cd5 1057 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1058 zlog_debug ("%s [%d] area: %s",
0c0f9cd5 1059 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1060 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1061 buf2, BUFSIZ));
718e3744 1062 break;
1063 case OSPF_PATH_INTER_AREA:
0c0f9cd5 1064 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1065 zlog_debug ("%s IA [%d] area: %s",
0c0f9cd5 1066 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1067 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1068 buf2, BUFSIZ));
718e3744 1069 break;
1070 default:
1071 break;
1072 }
1073
1eb8ef25 1074 for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path))
718e3744 1075 {
718e3744 1076 if (path->nexthop.s_addr == 0)
0c0f9cd5 1077 {
1078 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1079 zlog_debug (" directly attached to %s\r\n",
0c0f9cd5 1080 IF_NAME (path->oi));
1081 }
1082 else
1083 {
1084 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1085 zlog_debug (" via %s, %s\r\n",
0c0f9cd5 1086 inet_ntoa (path->nexthop), IF_NAME (path->oi));
1087 }
718e3744 1088 }
1089 }
1090
2a42e285 1091 zlog_debug ("ospf_rtrs_print() end");
718e3744 1092}
1093
1094/* Calculating the shortest-path tree for an area. */
4dadc291 1095static void
0c0f9cd5 1096ospf_spf_calculate (struct ospf_area *area, struct route_table *new_table,
718e3744 1097 struct route_table *new_rtrs)
1098{
462f20d5 1099 struct pqueue *candidate;
718e3744 1100 struct vertex *v;
eb3da6df 1101
718e3744 1102 if (IS_DEBUG_OSPF_EVENT)
1103 {
2a42e285 1104 zlog_debug ("ospf_spf_calculate: Start");
1105 zlog_debug ("ospf_spf_calculate: running Dijkstra for area %s",
0c0f9cd5 1106 inet_ntoa (area->area_id));
718e3744 1107 }
1108
1109 /* Check router-lsa-self. If self-router-lsa is not yet allocated,
1110 return this area's calculation. */
0c0f9cd5 1111 if (!area->router_lsa_self)
718e3744 1112 {
1113 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1114 zlog_debug ("ospf_spf_calculate: "
0c0f9cd5 1115 "Skip area %s's calculation due to empty router_lsa_self",
1116 inet_ntoa (area->area_id));
718e3744 1117 return;
1118 }
1119
1120 /* RFC2328 16.1. (1). */
0c0f9cd5 1121 /* Initialize the algorithm's data structures. */
462f20d5 1122
1123 /* This function scans all the LSA database and set the stat field to
1124 * LSA_SPF_NOT_EXPLORED. */
1125 ospf_lsdb_clean_stat (area->lsdb);
1126 /* Create a new heap for the candidates. */
1127 candidate = pqueue_create();
1128 candidate->cmp = cmp;
1129 candidate->update = update_stat;
718e3744 1130
1131 /* Initialize the shortest-path tree to only the root (which is the
1132 router doing the calculation). */
1133 ospf_spf_init (area);
1134 v = area->spf;
462f20d5 1135 /* Set LSA position to LSA_SPF_IN_SPFTREE. This vertex is the root of the
1136 * spanning tree. */
1137 *(v->stat) = LSA_SPF_IN_SPFTREE;
718e3744 1138
1139 /* Set Area A's TransitCapability to FALSE. */
1140 area->transit = OSPF_TRANSIT_FALSE;
1141 area->shortcut_capability = 1;
eb3da6df 1142
718e3744 1143 for (;;)
1144 {
1145 /* RFC2328 16.1. (2). */
462f20d5 1146 ospf_spf_next (v, area, candidate);
718e3744 1147
1148 /* RFC2328 16.1. (3). */
1149 /* If at this step the candidate list is empty, the shortest-
1150 path tree (of transit vertices) has been completely built and
1151 this stage of the procedure terminates. */
462f20d5 1152 if (candidate->size == 0)
718e3744 1153 break;
1154
1155 /* Otherwise, choose the vertex belonging to the candidate list
1156 that is closest to the root, and add it to the shortest-path
1157 tree (removing it from the candidate list in the
0c0f9cd5 1158 process). */
462f20d5 1159 /* Extract from the candidates the node with the lower key. */
1160 v = (struct vertex *) pqueue_dequeue (candidate);
1161 /* Update stat field in vertex. */
1162 *(v->stat) = LSA_SPF_IN_SPFTREE;
eb3da6df 1163
718e3744 1164 ospf_vertex_add_parent (v);
1165
718e3744 1166 /* Note that when there is a choice of vertices closest to the
1167 root, network vertices must be chosen before router vertices
1168 in order to necessarily find all equal-cost paths. */
1169 /* We don't do this at this moment, we should add the treatment
1170 above codes. -- kunihiro. */
1171
1172 /* RFC2328 16.1. (4). */
1173 if (v->type == OSPF_VERTEX_ROUTER)
1174 ospf_intra_add_router (new_rtrs, v, area);
0c0f9cd5 1175 else
718e3744 1176 ospf_intra_add_transit (new_table, v, area);
1177
1178 /* RFC2328 16.1. (5). */
1179 /* Iterate the algorithm by returning to Step 2. */
630e4807 1180
1181 } /* end loop until no more candidate vertices */
718e3744 1182
1183 if (IS_DEBUG_OSPF_EVENT)
1184 {
1185 ospf_spf_dump (area->spf, 0);
1186 ospf_route_table_dump (new_table);
1187 }
1188
1189 /* Second stage of SPF calculation procedure's */
b3bc68e5 1190 ospf_spf_process_stubs (area, area->spf, new_table, 0);
718e3744 1191
eb3da6df 1192 /* Free candidate queue. */
462f20d5 1193 pqueue_delete (candidate);
eb3da6df 1194
1195 ospf_vertex_dump (__func__, area->spf, 0, 1);
1196 /* Free nexthop information, canonical versions of which are attached
1197 * the first level of router vertices attached to the root vertex, see
1198 * ospf_nexthop_calculation.
1199 */
1200 ospf_canonical_nexthops_free (area->spf);
1201
9c27ef9b
PJ
1202 /* Free SPF vertices, but not the list. List has ospf_vertex_free
1203 * as deconstructor.
1204 */
1205 list_delete_all_node (&vertex_list);
eb3da6df 1206
718e3744 1207 /* Increment SPF Calculation Counter. */
1208 area->spf_calculation++;
1209
2518efd1 1210 quagga_gettime (QUAGGA_CLK_MONOTONIC, &area->ospf->ts_spf);
718e3744 1211
1212 if (IS_DEBUG_OSPF_EVENT)
9c27ef9b
PJ
1213 zlog_debug ("ospf_spf_calculate: Stop. %ld vertices",
1214 mtype_stats_alloc(MTYPE_OSPF_VERTEX));
718e3744 1215}
1216\f
1217/* Timer for SPF calculation. */
4dadc291 1218static int
68980084 1219ospf_spf_calculate_timer (struct thread *thread)
718e3744 1220{
68980084 1221 struct ospf *ospf = THREAD_ARG (thread);
718e3744 1222 struct route_table *new_table, *new_rtrs;
1eb8ef25 1223 struct ospf_area *area;
1224 struct listnode *node, *nnode;
718e3744 1225
1226 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1227 zlog_debug ("SPF: Timer (SPF calculation expire)");
0c0f9cd5 1228
718e3744 1229 ospf->t_spf_calc = NULL;
1230
1231 /* Allocate new table tree. */
1232 new_table = route_table_init ();
0c0f9cd5 1233 new_rtrs = route_table_init ();
718e3744 1234
68980084 1235 ospf_vl_unapprove (ospf);
718e3744 1236
1237 /* Calculate SPF for each area. */
1eb8ef25 1238 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
9c27ef9b
PJ
1239 {
1240 /* Do backbone last, so as to first discover intra-area paths
1241 * for any back-bone virtual-links
1242 */
1243 if (ospf->backbone && ospf->backbone == area)
1244 continue;
1245
1246 ospf_spf_calculate (area, new_table, new_rtrs);
1247 }
1248
1249 /* SPF for backbone, if required */
1250 if (ospf->backbone)
1251 ospf_spf_calculate (ospf->backbone, new_table, new_rtrs);
1252
68980084 1253 ospf_vl_shut_unapproved (ospf);
718e3744 1254
68980084 1255 ospf_ia_routing (ospf, new_table, new_rtrs);
718e3744 1256
1257 ospf_prune_unreachable_networks (new_table);
1258 ospf_prune_unreachable_routers (new_rtrs);
1259
1260 /* AS-external-LSA calculation should not be performed here. */
1261
1262 /* If new Router Route is installed,
1263 then schedule re-calculate External routes. */
1264 if (1)
68980084 1265 ospf_ase_calculate_schedule (ospf);
718e3744 1266
68980084 1267 ospf_ase_calculate_timer_add (ospf);
718e3744 1268
1269 /* Update routing table. */
68980084 1270 ospf_route_install (ospf, new_table);
718e3744 1271
1272 /* Update ABR/ASBR routing table */
68980084 1273 if (ospf->old_rtrs)
718e3744 1274 {
1275 /* old_rtrs's node holds linked list of ospf_route. --kunihiro. */
68980084 1276 /* ospf_route_delete (ospf->old_rtrs); */
1277 ospf_rtrs_free (ospf->old_rtrs);
718e3744 1278 }
1279
68980084 1280 ospf->old_rtrs = ospf->new_rtrs;
1281 ospf->new_rtrs = new_rtrs;
718e3744 1282
0c0f9cd5 1283 if (IS_OSPF_ABR (ospf))
68980084 1284 ospf_abr_task (ospf);
718e3744 1285
1286 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1287 zlog_debug ("SPF: calculation complete");
718e3744 1288
1289 return 0;
1290}
1291
1292/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
1293 set timer for SPF calc. */
1294void
68980084 1295ospf_spf_calculate_schedule (struct ospf *ospf)
718e3744 1296{
d24f6e2a 1297 unsigned long delay, elapsed, ht;
1298 struct timeval result;
718e3744 1299
1300 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1301 zlog_debug ("SPF: calculation timer scheduled");
718e3744 1302
1303 /* OSPF instance does not exist. */
68980084 1304 if (ospf == NULL)
718e3744 1305 return;
d24f6e2a 1306
718e3744 1307 /* SPF calculation timer is already scheduled. */
68980084 1308 if (ospf->t_spf_calc)
718e3744 1309 {
1310 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1311 zlog_debug ("SPF: calculation timer is already scheduled: %p",
0c0f9cd5 1312 ospf->t_spf_calc);
718e3744 1313 return;
1314 }
d24f6e2a 1315
1316 /* XXX Monotic timers: we only care about relative time here. */
2518efd1 1317 result = tv_sub (recent_relative_time (), ospf->ts_spf);
d24f6e2a 1318
1319 elapsed = (result.tv_sec * 1000) + (result.tv_usec / 1000);
1320 ht = ospf->spf_holdtime * ospf->spf_hold_multiplier;
1321
1322 if (ht > ospf->spf_max_holdtime)
1323 ht = ospf->spf_max_holdtime;
1324
718e3744 1325 /* Get SPF calculation delay time. */
d24f6e2a 1326 if (elapsed < ht)
718e3744 1327 {
d24f6e2a 1328 /* Got an event within the hold time of last SPF. We need to
1329 * increase the hold_multiplier, if it's not already at/past
1330 * maximum value, and wasn't already increased..
1331 */
1332 if (ht < ospf->spf_max_holdtime)
1333 ospf->spf_hold_multiplier++;
1334
1335 /* always honour the SPF initial delay */
1336 if ( (ht - elapsed) < ospf->spf_delay)
0c0f9cd5 1337 delay = ospf->spf_delay;
718e3744 1338 else
d24f6e2a 1339 delay = ht - elapsed;
718e3744 1340 }
1341 else
d24f6e2a 1342 {
1343 /* Event is past required hold-time of last SPF */
1344 delay = ospf->spf_delay;
1345 ospf->spf_hold_multiplier = 1;
1346 }
1347
718e3744 1348 if (IS_DEBUG_OSPF_EVENT)
d24f6e2a 1349 zlog_debug ("SPF: calculation timer delay = %ld", delay);
1350
68980084 1351 ospf->t_spf_calc =
d24f6e2a 1352 thread_add_timer_msec (master, ospf_spf_calculate_timer, ospf, delay);
718e3744 1353}