]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_spf.c
Merge commit 'remotes/jocke/delete_ghost_route'
[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.
e95537f0 902 * (next pqueu_{de,en}queue will fully re-heap the queue).
7591d8b8
PJ
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)
910e2704
JT
984 {
985 /* PtP links with /32 masks adds host routes to the remote host,
986 see RFC 2328, 12.4.1.1, Option 1.
987 Make sure that such routes are ignored */
988 /* XXX: Change to breadth-first and avoid the lookup */
989 if (l->link_data.s_addr == 0xffffffff &&
990 ospf_if_lookup_by_local_addr (area->ospf, NULL, l->link_id))
991 {
992 if (IS_DEBUG_OSPF_EVENT)
993 zlog_debug ("ospf_spf_process_stubs(): ignoring host route "
994 "%s/32 to self.", inet_ntoa (l->link_id));
995 continue;
996 }
997 ospf_intra_add_stub (rt, l, v, area);
998 }
718e3744 999 }
1000 }
1001
630e4807 1002 ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1, 1);
718e3744 1003
eb3da6df 1004 for (ALL_LIST_ELEMENTS (v->children, cnode, cnnode, child))
718e3744 1005 {
718e3744 1006 if (CHECK_FLAG (child->flags, OSPF_VERTEX_PROCESSED))
0c0f9cd5 1007 continue;
718e3744 1008
1009 ospf_spf_process_stubs (area, child, rt);
1010
1011 SET_FLAG (child->flags, OSPF_VERTEX_PROCESSED);
1012 }
1013}
1014
1015void
1016ospf_rtrs_free (struct route_table *rtrs)
1017{
1018 struct route_node *rn;
52dc7ee6 1019 struct list *or_list;
1eb8ef25 1020 struct ospf_route *or;
1021 struct listnode *node, *nnode;
718e3744 1022
1023 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1024 zlog_debug ("Route: Router Routing Table free");
718e3744 1025
1026 for (rn = route_top (rtrs); rn; rn = route_next (rn))
1027 if ((or_list = rn->info) != NULL)
1028 {
1eb8ef25 1029 for (ALL_LIST_ELEMENTS (or_list, node, nnode, or))
1030 ospf_route_free (or);
718e3744 1031
0c0f9cd5 1032 list_delete (or_list);
718e3744 1033
0c0f9cd5 1034 /* Unlock the node. */
1035 rn->info = NULL;
1036 route_unlock_node (rn);
718e3744 1037 }
1038 route_table_finish (rtrs);
1039}
1040
4dadc291 1041static void
718e3744 1042ospf_rtrs_print (struct route_table *rtrs)
1043{
1044 struct route_node *rn;
52dc7ee6 1045 struct list *or_list;
1046 struct listnode *ln;
1047 struct listnode *pnode;
718e3744 1048 struct ospf_route *or;
1049 struct ospf_path *path;
1050 char buf1[BUFSIZ];
1051 char buf2[BUFSIZ];
1052
1053 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1054 zlog_debug ("ospf_rtrs_print() start");
718e3744 1055
1056 for (rn = route_top (rtrs); rn; rn = route_next (rn))
1057 if ((or_list = rn->info) != NULL)
1eb8ef25 1058 for (ALL_LIST_ELEMENTS_RO (or_list, ln, or))
718e3744 1059 {
718e3744 1060 switch (or->path_type)
1061 {
1062 case OSPF_PATH_INTRA_AREA:
0c0f9cd5 1063 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1064 zlog_debug ("%s [%d] area: %s",
0c0f9cd5 1065 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1066 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1067 buf2, BUFSIZ));
718e3744 1068 break;
1069 case OSPF_PATH_INTER_AREA:
0c0f9cd5 1070 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1071 zlog_debug ("%s IA [%d] area: %s",
0c0f9cd5 1072 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1073 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1074 buf2, BUFSIZ));
718e3744 1075 break;
1076 default:
1077 break;
1078 }
1079
1eb8ef25 1080 for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path))
718e3744 1081 {
718e3744 1082 if (path->nexthop.s_addr == 0)
0c0f9cd5 1083 {
1084 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1085 zlog_debug (" directly attached to %s\r\n",
0c0f9cd5 1086 IF_NAME (path->oi));
1087 }
1088 else
1089 {
1090 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1091 zlog_debug (" via %s, %s\r\n",
0c0f9cd5 1092 inet_ntoa (path->nexthop), IF_NAME (path->oi));
1093 }
718e3744 1094 }
1095 }
1096
2a42e285 1097 zlog_debug ("ospf_rtrs_print() end");
718e3744 1098}
1099
1100/* Calculating the shortest-path tree for an area. */
4dadc291 1101static void
0c0f9cd5 1102ospf_spf_calculate (struct ospf_area *area, struct route_table *new_table,
718e3744 1103 struct route_table *new_rtrs)
1104{
462f20d5 1105 struct pqueue *candidate;
718e3744 1106 struct vertex *v;
eb3da6df 1107
718e3744 1108 if (IS_DEBUG_OSPF_EVENT)
1109 {
2a42e285 1110 zlog_debug ("ospf_spf_calculate: Start");
1111 zlog_debug ("ospf_spf_calculate: running Dijkstra for area %s",
0c0f9cd5 1112 inet_ntoa (area->area_id));
718e3744 1113 }
1114
1115 /* Check router-lsa-self. If self-router-lsa is not yet allocated,
1116 return this area's calculation. */
0c0f9cd5 1117 if (!area->router_lsa_self)
718e3744 1118 {
1119 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1120 zlog_debug ("ospf_spf_calculate: "
0c0f9cd5 1121 "Skip area %s's calculation due to empty router_lsa_self",
1122 inet_ntoa (area->area_id));
718e3744 1123 return;
1124 }
1125
1126 /* RFC2328 16.1. (1). */
0c0f9cd5 1127 /* Initialize the algorithm's data structures. */
462f20d5 1128
1129 /* This function scans all the LSA database and set the stat field to
1130 * LSA_SPF_NOT_EXPLORED. */
1131 ospf_lsdb_clean_stat (area->lsdb);
1132 /* Create a new heap for the candidates. */
1133 candidate = pqueue_create();
1134 candidate->cmp = cmp;
1135 candidate->update = update_stat;
718e3744 1136
1137 /* Initialize the shortest-path tree to only the root (which is the
1138 router doing the calculation). */
1139 ospf_spf_init (area);
1140 v = area->spf;
462f20d5 1141 /* Set LSA position to LSA_SPF_IN_SPFTREE. This vertex is the root of the
1142 * spanning tree. */
1143 *(v->stat) = LSA_SPF_IN_SPFTREE;
718e3744 1144
1145 /* Set Area A's TransitCapability to FALSE. */
1146 area->transit = OSPF_TRANSIT_FALSE;
1147 area->shortcut_capability = 1;
eb3da6df 1148
718e3744 1149 for (;;)
1150 {
1151 /* RFC2328 16.1. (2). */
462f20d5 1152 ospf_spf_next (v, area, candidate);
718e3744 1153
1154 /* RFC2328 16.1. (3). */
1155 /* If at this step the candidate list is empty, the shortest-
1156 path tree (of transit vertices) has been completely built and
1157 this stage of the procedure terminates. */
462f20d5 1158 if (candidate->size == 0)
718e3744 1159 break;
1160
1161 /* Otherwise, choose the vertex belonging to the candidate list
1162 that is closest to the root, and add it to the shortest-path
1163 tree (removing it from the candidate list in the
0c0f9cd5 1164 process). */
462f20d5 1165 /* Extract from the candidates the node with the lower key. */
1166 v = (struct vertex *) pqueue_dequeue (candidate);
1167 /* Update stat field in vertex. */
1168 *(v->stat) = LSA_SPF_IN_SPFTREE;
eb3da6df 1169
718e3744 1170 ospf_vertex_add_parent (v);
1171
718e3744 1172 /* Note that when there is a choice of vertices closest to the
1173 root, network vertices must be chosen before router vertices
1174 in order to necessarily find all equal-cost paths. */
1175 /* We don't do this at this moment, we should add the treatment
1176 above codes. -- kunihiro. */
1177
1178 /* RFC2328 16.1. (4). */
1179 if (v->type == OSPF_VERTEX_ROUTER)
1180 ospf_intra_add_router (new_rtrs, v, area);
0c0f9cd5 1181 else
718e3744 1182 ospf_intra_add_transit (new_table, v, area);
1183
1184 /* RFC2328 16.1. (5). */
1185 /* Iterate the algorithm by returning to Step 2. */
630e4807 1186
1187 } /* end loop until no more candidate vertices */
718e3744 1188
1189 if (IS_DEBUG_OSPF_EVENT)
1190 {
1191 ospf_spf_dump (area->spf, 0);
1192 ospf_route_table_dump (new_table);
1193 }
1194
1195 /* Second stage of SPF calculation procedure's */
1196 ospf_spf_process_stubs (area, area->spf, new_table);
1197
eb3da6df 1198 /* Free candidate queue. */
462f20d5 1199 pqueue_delete (candidate);
eb3da6df 1200
1201 ospf_vertex_dump (__func__, area->spf, 0, 1);
1202 /* Free nexthop information, canonical versions of which are attached
1203 * the first level of router vertices attached to the root vertex, see
1204 * ospf_nexthop_calculation.
1205 */
1206 ospf_canonical_nexthops_free (area->spf);
1207
9c27ef9b
PJ
1208 /* Free SPF vertices, but not the list. List has ospf_vertex_free
1209 * as deconstructor.
1210 */
1211 list_delete_all_node (&vertex_list);
eb3da6df 1212
718e3744 1213 /* Increment SPF Calculation Counter. */
1214 area->spf_calculation++;
1215
2518efd1 1216 quagga_gettime (QUAGGA_CLK_MONOTONIC, &area->ospf->ts_spf);
718e3744 1217
1218 if (IS_DEBUG_OSPF_EVENT)
9c27ef9b
PJ
1219 zlog_debug ("ospf_spf_calculate: Stop. %ld vertices",
1220 mtype_stats_alloc(MTYPE_OSPF_VERTEX));
718e3744 1221}
1222\f
1223/* Timer for SPF calculation. */
4dadc291 1224static int
68980084 1225ospf_spf_calculate_timer (struct thread *thread)
718e3744 1226{
68980084 1227 struct ospf *ospf = THREAD_ARG (thread);
718e3744 1228 struct route_table *new_table, *new_rtrs;
1eb8ef25 1229 struct ospf_area *area;
1230 struct listnode *node, *nnode;
718e3744 1231
1232 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1233 zlog_debug ("SPF: Timer (SPF calculation expire)");
0c0f9cd5 1234
718e3744 1235 ospf->t_spf_calc = NULL;
1236
1237 /* Allocate new table tree. */
1238 new_table = route_table_init ();
0c0f9cd5 1239 new_rtrs = route_table_init ();
718e3744 1240
68980084 1241 ospf_vl_unapprove (ospf);
718e3744 1242
1243 /* Calculate SPF for each area. */
1eb8ef25 1244 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
9c27ef9b
PJ
1245 {
1246 /* Do backbone last, so as to first discover intra-area paths
1247 * for any back-bone virtual-links
1248 */
1249 if (ospf->backbone && ospf->backbone == area)
1250 continue;
1251
1252 ospf_spf_calculate (area, new_table, new_rtrs);
1253 }
1254
1255 /* SPF for backbone, if required */
1256 if (ospf->backbone)
1257 ospf_spf_calculate (ospf->backbone, new_table, new_rtrs);
1258
68980084 1259 ospf_vl_shut_unapproved (ospf);
718e3744 1260
68980084 1261 ospf_ia_routing (ospf, new_table, new_rtrs);
718e3744 1262
1263 ospf_prune_unreachable_networks (new_table);
1264 ospf_prune_unreachable_routers (new_rtrs);
1265
1266 /* AS-external-LSA calculation should not be performed here. */
1267
1268 /* If new Router Route is installed,
1269 then schedule re-calculate External routes. */
1270 if (1)
68980084 1271 ospf_ase_calculate_schedule (ospf);
718e3744 1272
68980084 1273 ospf_ase_calculate_timer_add (ospf);
718e3744 1274
1275 /* Update routing table. */
68980084 1276 ospf_route_install (ospf, new_table);
718e3744 1277
1278 /* Update ABR/ASBR routing table */
68980084 1279 if (ospf->old_rtrs)
718e3744 1280 {
1281 /* old_rtrs's node holds linked list of ospf_route. --kunihiro. */
68980084 1282 /* ospf_route_delete (ospf->old_rtrs); */
1283 ospf_rtrs_free (ospf->old_rtrs);
718e3744 1284 }
1285
68980084 1286 ospf->old_rtrs = ospf->new_rtrs;
1287 ospf->new_rtrs = new_rtrs;
718e3744 1288
0c0f9cd5 1289 if (IS_OSPF_ABR (ospf))
68980084 1290 ospf_abr_task (ospf);
718e3744 1291
1292 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1293 zlog_debug ("SPF: calculation complete");
718e3744 1294
1295 return 0;
1296}
1297
1298/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
1299 set timer for SPF calc. */
1300void
68980084 1301ospf_spf_calculate_schedule (struct ospf *ospf)
718e3744 1302{
d24f6e2a 1303 unsigned long delay, elapsed, ht;
1304 struct timeval result;
718e3744 1305
1306 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1307 zlog_debug ("SPF: calculation timer scheduled");
718e3744 1308
1309 /* OSPF instance does not exist. */
68980084 1310 if (ospf == NULL)
718e3744 1311 return;
d24f6e2a 1312
718e3744 1313 /* SPF calculation timer is already scheduled. */
68980084 1314 if (ospf->t_spf_calc)
718e3744 1315 {
1316 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1317 zlog_debug ("SPF: calculation timer is already scheduled: %p",
0c0f9cd5 1318 ospf->t_spf_calc);
718e3744 1319 return;
1320 }
d24f6e2a 1321
1322 /* XXX Monotic timers: we only care about relative time here. */
2518efd1 1323 result = tv_sub (recent_relative_time (), ospf->ts_spf);
d24f6e2a 1324
1325 elapsed = (result.tv_sec * 1000) + (result.tv_usec / 1000);
1326 ht = ospf->spf_holdtime * ospf->spf_hold_multiplier;
1327
1328 if (ht > ospf->spf_max_holdtime)
1329 ht = ospf->spf_max_holdtime;
1330
718e3744 1331 /* Get SPF calculation delay time. */
d24f6e2a 1332 if (elapsed < ht)
718e3744 1333 {
d24f6e2a 1334 /* Got an event within the hold time of last SPF. We need to
1335 * increase the hold_multiplier, if it's not already at/past
1336 * maximum value, and wasn't already increased..
1337 */
1338 if (ht < ospf->spf_max_holdtime)
1339 ospf->spf_hold_multiplier++;
1340
1341 /* always honour the SPF initial delay */
1342 if ( (ht - elapsed) < ospf->spf_delay)
0c0f9cd5 1343 delay = ospf->spf_delay;
718e3744 1344 else
d24f6e2a 1345 delay = ht - elapsed;
718e3744 1346 }
1347 else
d24f6e2a 1348 {
1349 /* Event is past required hold-time of last SPF */
1350 delay = ospf->spf_delay;
1351 ospf->spf_hold_multiplier = 1;
1352 }
1353
718e3744 1354 if (IS_DEBUG_OSPF_EVENT)
d24f6e2a 1355 zlog_debug ("SPF: calculation timer delay = %ld", delay);
1356
68980084 1357 ospf->t_spf_calc =
d24f6e2a 1358 thread_add_timer_msec (master, ospf_spf_calculate_timer, ospf, delay);
718e3744 1359}