blob: c8cbe3f6f0b862df1cf49680ffd5058875d41923 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* 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 () */
hasso462f20d2005-02-23 11:29:02 +000032#include "pqueue.h"
paul718e3742002-12-13 20:15:29 +000033
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
Paul Jakma9c27ef92006-05-04 07:32:57 +000049static 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
hasso462f20d2005-02-23 11:29:02 +000056/* 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 )
Paul Jakma9c27ef92006-05-04 07:32:57 +000064 {
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;
hasso462f20d2005-02-23 11:29:02 +000083}
84
85static void
pauleb3da6d2005-10-18 04:20:33 +000086update_stat (void *node , int position)
hasso462f20d2005-02-23 11:29:02 +000087{
pauleb3da6d2005-10-18 04:20:33 +000088 struct vertex *v = node;
89
hasso462f20d2005-02-23 11:29:02 +000090 /* Set the status of the vertex, when its position changes. */
91 *(v->stat) = position;
92}
pauleb3da6d2005-10-18 04:20:33 +000093
paul4dadc292005-05-06 21:37:42 +000094static struct vertex_nexthop *
pauleb3da6d2005-10-18 04:20:33 +000095vertex_nexthop_new (void)
paul718e3742002-12-13 20:15:29 +000096{
pauleb3da6d2005-10-18 04:20:33 +000097 return XCALLOC (MTYPE_OSPF_NEXTHOP, sizeof (struct vertex_nexthop));
paul718e3742002-12-13 20:15:29 +000098}
99
paul4dadc292005-05-06 21:37:42 +0000100static void
paul718e3742002-12-13 20:15:29 +0000101vertex_nexthop_free (struct vertex_nexthop *nh)
102{
103 XFREE (MTYPE_OSPF_NEXTHOP, nh);
104}
105
pauleb3da6d2005-10-18 04:20:33 +0000106/* Free the canonical nexthop objects for an area, ie the nexthop objects
Paul Jakma9c27ef92006-05-04 07:32:57 +0000107 * attached to the first-hop router vertices, and any intervening network
108 * vertices.
pauleb3da6d2005-10-18 04:20:33 +0000109 */
110static void
111ospf_canonical_nexthops_free (struct vertex *root)
paul718e3742002-12-13 20:15:29 +0000112{
pauleb3da6d2005-10-18 04:20:33 +0000113 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
paul58e1bef2005-11-11 12:10:03 +0000121 /* 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 */
pauleb3da6d2005-10-18 04:20:33 +0000128 if (child->type == OSPF_VERTEX_NETWORK)
129 ospf_canonical_nexthops_free (child);
130
paul58e1bef2005-11-11 12:10:03 +0000131 /* Free child nexthops pointing back to this root vertex */
pauleb3da6d2005-10-18 04:20:33 +0000132 for (ALL_LIST_ELEMENTS (child->parents, n2, nn2, vp))
Paul Jakma9c27ef92006-05-04 07:32:57 +0000133 if (vp->parent == root && vp->nexthop)
paul58e1bef2005-11-11 12:10:03 +0000134 vertex_nexthop_free (vp->nexthop);
pauleb3da6d2005-10-18 04:20:33 +0000135 }
136}
137
Paul Jakma9c27ef92006-05-04 07:32:57 +0000138/* TODO: Parent list should be excised, in favour of maintaining only
139 * vertex_nexthop, with refcounts.
140 */
pauleb3da6d2005-10-18 04:20:33 +0000141static 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;
paul718e3742002-12-13 20:15:29 +0000154 return new;
155}
paul0c0f9cd2003-06-06 23:27:04 +0000156
pauleb3da6d2005-10-18 04:20:33 +0000157static void
Paul Jakma9c27ef92006-05-04 07:32:57 +0000158vertex_parent_free (void *p)
pauleb3da6d2005-10-18 04:20:33 +0000159{
160 XFREE (MTYPE_OSPF_VERTEX_PARENT, p);
161}
162
paul4dadc292005-05-06 21:37:42 +0000163static struct vertex *
paul718e3742002-12-13 20:15:29 +0000164ospf_vertex_new (struct ospf_lsa *lsa)
165{
166 struct vertex *new;
167
pauleb3da6d2005-10-18 04:20:33 +0000168 new = XCALLOC (MTYPE_OSPF_VERTEX, sizeof (struct vertex));
paul718e3742002-12-13 20:15:29 +0000169
170 new->flags = 0;
hasso462f20d2005-02-23 11:29:02 +0000171 new->stat = &(lsa->stat);
paul718e3742002-12-13 20:15:29 +0000172 new->type = lsa->data->type;
173 new->id = lsa->data->id;
174 new->lsa = lsa->data;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000175 new->distance = OSPF_OUTPUT_COST_INFINITE;
pauleb3da6d2005-10-18 04:20:33 +0000176 new->children = list_new ();
177 new->parents = list_new ();
Paul Jakma9c27ef92006-05-04 07:32:57 +0000178 new->parents->del = vertex_parent_free;
pauleb3da6d2005-10-18 04:20:33 +0000179
Paul Jakma9c27ef92006-05-04 07:32:57 +0000180 listnode_add (&vertex_list, new);
181
182 if (IS_DEBUG_OSPF_EVENT)
183 zlog_debug ("%s: Created %s vertex %s", __func__,
184 new->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
185 inet_ntoa (new->lsa->id));
paul718e3742002-12-13 20:15:29 +0000186 return new;
187}
188
paul4dadc292005-05-06 21:37:42 +0000189static void
Paul Jakma9c27ef92006-05-04 07:32:57 +0000190ospf_vertex_free (void *data)
paul718e3742002-12-13 20:15:29 +0000191{
Paul Jakma9c27ef92006-05-04 07:32:57 +0000192 struct vertex *v = data;
paul7461d452005-06-13 13:57:16 +0000193
Paul Jakma9c27ef92006-05-04 07:32:57 +0000194 if (IS_DEBUG_OSPF_EVENT)
195 zlog_debug ("%s: Free %s vertex %s", __func__,
196 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
197 inet_ntoa (v->lsa->id));
pauleb3da6d2005-10-18 04:20:33 +0000198
Paul Jakma9c27ef92006-05-04 07:32:57 +0000199 /* There should be no parents potentially holding references to this vertex
200 * Children however may still be there, but presumably referenced by other
201 * vertices
pauleb3da6d2005-10-18 04:20:33 +0000202 */
Paul Jakma9c27ef92006-05-04 07:32:57 +0000203 //assert (listcount (v->parents) == 0);
pauleb3da6d2005-10-18 04:20:33 +0000204
Paul Jakma9c27ef92006-05-04 07:32:57 +0000205 if (v->children)
206 list_delete (v->children);
207 v->children = NULL;
208
209 if (v->parents)
210 list_delete (v->parents);
pauleb3da6d2005-10-18 04:20:33 +0000211 v->parents = NULL;
212
213 v->lsa = NULL;
paul7461d452005-06-13 13:57:16 +0000214
paul718e3742002-12-13 20:15:29 +0000215 XFREE (MTYPE_OSPF_VERTEX, v);
216}
217
paul4dadc292005-05-06 21:37:42 +0000218static void
hassoeb1ce602004-10-08 08:17:22 +0000219ospf_vertex_dump(const char *msg, struct vertex *v,
pauleb3da6d2005-10-18 04:20:33 +0000220 int print_parents, int print_children)
gdt630e4802004-08-31 17:28:41 +0000221{
222 if ( ! IS_DEBUG_OSPF_EVENT)
223 return;
224
pauleb3da6d2005-10-18 04:20:33 +0000225 zlog_debug("%s %s vertex %s distance %u flags %u",
gdt630e4802004-08-31 17:28:41 +0000226 msg,
227 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
228 inet_ntoa(v->lsa->id),
229 v->distance,
gdt630e4802004-08-31 17:28:41 +0000230 (unsigned int)v->flags);
231
pauleb3da6d2005-10-18 04:20:33 +0000232 if (print_parents)
gdt630e4802004-08-31 17:28:41 +0000233 {
paul1eb8ef22005-04-07 07:30:20 +0000234 struct listnode *node;
pauleb3da6d2005-10-18 04:20:33 +0000235 struct vertex_parent *vp;
paul1eb8ef22005-04-07 07:30:20 +0000236
pauleb3da6d2005-10-18 04:20:33 +0000237 for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
gdt630e4802004-08-31 17:28:41 +0000238 {
239 char buf1[BUFSIZ];
pauleb3da6d2005-10-18 04:20:33 +0000240
241 if (vp)
gdt630e4802004-08-31 17:28:41 +0000242 {
pauleb3da6d2005-10-18 04:20:33 +0000243 zlog_debug ("parent %s backlink %d nexthop %s interface %s",
244 inet_ntoa(vp->parent->lsa->id), vp->backlink,
245 inet_ntop(AF_INET, &vp->nexthop->router, buf1, BUFSIZ),
246 vp->nexthop->oi ? IF_NAME(vp->nexthop->oi) : "NULL");
gdt630e4802004-08-31 17:28:41 +0000247 }
248 }
249 }
250
251 if (print_children)
252 {
hasso52dc7ee2004-09-23 19:18:23 +0000253 struct listnode *cnode;
paul1eb8ef22005-04-07 07:30:20 +0000254 struct vertex *cv;
255
pauleb3da6d2005-10-18 04:20:33 +0000256 for (ALL_LIST_ELEMENTS_RO (v->children, cnode, cv))
paul1eb8ef22005-04-07 07:30:20 +0000257 ospf_vertex_dump(" child:", cv, 0, 0);
gdt630e4802004-08-31 17:28:41 +0000258 }
259}
260
261
262/* Add a vertex to the list of children in each of its parents. */
paul4dadc292005-05-06 21:37:42 +0000263static void
paul718e3742002-12-13 20:15:29 +0000264ospf_vertex_add_parent (struct vertex *v)
265{
pauleb3da6d2005-10-18 04:20:33 +0000266 struct vertex_parent *vp;
hasso52dc7ee2004-09-23 19:18:23 +0000267 struct listnode *node;
paul7461d452005-06-13 13:57:16 +0000268
Paul Jakma9c27ef92006-05-04 07:32:57 +0000269 assert (v && v->parents);
paul7461d452005-06-13 13:57:16 +0000270
pauleb3da6d2005-10-18 04:20:33 +0000271 for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
paul718e3742002-12-13 20:15:29 +0000272 {
pauleb3da6d2005-10-18 04:20:33 +0000273 assert (vp->parent && vp->parent->children);
paul7461d452005-06-13 13:57:16 +0000274
paul718e3742002-12-13 20:15:29 +0000275 /* No need to add two links from the same parent. */
pauleb3da6d2005-10-18 04:20:33 +0000276 if (listnode_lookup (vp->parent->children, v) == NULL)
277 listnode_add (vp->parent->children, v);
paul718e3742002-12-13 20:15:29 +0000278 }
279}
280
paul4dadc292005-05-06 21:37:42 +0000281static void
paul718e3742002-12-13 20:15:29 +0000282ospf_spf_init (struct ospf_area *area)
283{
284 struct vertex *v;
Paul Jakma9c27ef92006-05-04 07:32:57 +0000285
paul718e3742002-12-13 20:15:29 +0000286 /* Create root node. */
287 v = ospf_vertex_new (area->router_lsa_self);
Paul Jakmabd34fb32007-02-26 17:14:48 +0000288 v->distance = 0;
289
paul718e3742002-12-13 20:15:29 +0000290 area->spf = v;
291
292 /* Reset ABR and ASBR router counts. */
293 area->abr_count = 0;
294 area->asbr_count = 0;
295}
296
pauld355bfa2004-04-08 07:43:45 +0000297/* return index of link back to V from W, or -1 if no link found */
paul4dadc292005-05-06 21:37:42 +0000298static int
paul718e3742002-12-13 20:15:29 +0000299ospf_lsa_has_link (struct lsa_header *w, struct lsa_header *v)
300{
hassoeb1ce602004-10-08 08:17:22 +0000301 unsigned int i, length;
paul718e3742002-12-13 20:15:29 +0000302 struct router_lsa *rl;
303 struct network_lsa *nl;
304
305 /* In case of W is Network LSA. */
306 if (w->type == OSPF_NETWORK_LSA)
307 {
308 if (v->type == OSPF_NETWORK_LSA)
pauld355bfa2004-04-08 07:43:45 +0000309 return -1;
paul718e3742002-12-13 20:15:29 +0000310
311 nl = (struct network_lsa *) w;
312 length = (ntohs (w->length) - OSPF_LSA_HEADER_SIZE - 4) / 4;
paul0c0f9cd2003-06-06 23:27:04 +0000313
paul718e3742002-12-13 20:15:29 +0000314 for (i = 0; i < length; i++)
315 if (IPV4_ADDR_SAME (&nl->routers[i], &v->id))
pauld355bfa2004-04-08 07:43:45 +0000316 return i;
317 return -1;
paul718e3742002-12-13 20:15:29 +0000318 }
319
320 /* In case of W is Router LSA. */
321 if (w->type == OSPF_ROUTER_LSA)
322 {
323 rl = (struct router_lsa *) w;
324
325 length = ntohs (w->length);
326
327 for (i = 0;
paul0c0f9cd2003-06-06 23:27:04 +0000328 i < ntohs (rl->links) && length >= sizeof (struct router_lsa);
329 i++, length -= 12)
paul718e3742002-12-13 20:15:29 +0000330 {
331 switch (rl->link[i].type)
332 {
333 case LSA_LINK_TYPE_POINTOPOINT:
334 case LSA_LINK_TYPE_VIRTUALLINK:
335 /* Router LSA ID. */
336 if (v->type == OSPF_ROUTER_LSA &&
337 IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
338 {
pauld355bfa2004-04-08 07:43:45 +0000339 return i;
paul718e3742002-12-13 20:15:29 +0000340 }
341 break;
342 case LSA_LINK_TYPE_TRANSIT:
343 /* Network LSA ID. */
344 if (v->type == OSPF_NETWORK_LSA &&
345 IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
346 {
pauld355bfa2004-04-08 07:43:45 +0000347 return i;
paul0c0f9cd2003-06-06 23:27:04 +0000348 }
paul718e3742002-12-13 20:15:29 +0000349 break;
350 case LSA_LINK_TYPE_STUB:
pauleb3da6d2005-10-18 04:20:33 +0000351 /* Stub can't lead anywhere, carry on */
paul718e3742002-12-13 20:15:29 +0000352 continue;
353 default:
354 break;
355 }
356 }
357 }
pauld355bfa2004-04-08 07:43:45 +0000358 return -1;
paul718e3742002-12-13 20:15:29 +0000359}
360
paul718e3742002-12-13 20:15:29 +0000361#define ROUTER_LSA_MIN_SIZE 12
362#define ROUTER_LSA_TOS_SIZE 4
363
gdt630e4802004-08-31 17:28:41 +0000364/* Find the next link after prev_link from v to w. If prev_link is
365 * NULL, return the first link from v to w. Ignore stub and virtual links;
366 * these link types will never be returned.
367 */
paul4dadc292005-05-06 21:37:42 +0000368static struct router_lsa_link *
paul718e3742002-12-13 20:15:29 +0000369ospf_get_next_link (struct vertex *v, struct vertex *w,
paul0c0f9cd2003-06-06 23:27:04 +0000370 struct router_lsa_link *prev_link)
paul718e3742002-12-13 20:15:29 +0000371{
372 u_char *p;
373 u_char *lim;
374 struct router_lsa_link *l;
375
376 if (prev_link == NULL)
gdt630e4802004-08-31 17:28:41 +0000377 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +0000378 else
379 {
paul0c0f9cd2003-06-06 23:27:04 +0000380 p = (u_char *) prev_link;
paul718e3742002-12-13 20:15:29 +0000381 p += (ROUTER_LSA_MIN_SIZE +
382 (prev_link->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
383 }
paul0c0f9cd2003-06-06 23:27:04 +0000384
paul718e3742002-12-13 20:15:29 +0000385 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
386
387 while (p < lim)
388 {
389 l = (struct router_lsa_link *) p;
390
paul0c0f9cd2003-06-06 23:27:04 +0000391 p += (ROUTER_LSA_MIN_SIZE + (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
paul718e3742002-12-13 20:15:29 +0000392
393 if (l->m[0].type == LSA_LINK_TYPE_STUB)
394 continue;
395
396 /* Defer NH calculation via VLs until summaries from
397 transit areas area confidered */
398
399 if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK)
paul0c0f9cd2003-06-06 23:27:04 +0000400 continue;
paul718e3742002-12-13 20:15:29 +0000401
402 if (IPV4_ADDR_SAME (&l->link_id, &w->id))
paul0c0f9cd2003-06-06 23:27:04 +0000403 return l;
paul718e3742002-12-13 20:15:29 +0000404 }
405
406 return NULL;
407}
408
pauleb3da6d2005-10-18 04:20:33 +0000409static void
410ospf_spf_flush_parents (struct vertex *w)
411{
412 struct vertex_parent *vp;
413 struct listnode *ln, *nn;
414
415 /* delete the existing nexthops */
416 for (ALL_LIST_ELEMENTS (w->parents, ln, nn, vp))
417 {
418 list_delete_node (w->parents, ln);
419 vertex_parent_free (vp);
420 }
421}
422
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000423/*
424 * Consider supplied next-hop for inclusion to the supplied list of
425 * equal-cost next-hops, adjust list as neccessary.
426 */
427static void
428ospf_spf_add_parent (struct vertex *v, struct vertex *w,
429 struct vertex_nexthop *newhop,
Paul Jakmabd34fb32007-02-26 17:14:48 +0000430 unsigned int distance)
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000431{
432 struct vertex_parent *vp;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000433
434 /* we must have a newhop.. */
Paul Jakmabd34fb32007-02-26 17:14:48 +0000435 assert (v && w && newhop);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000436
437 /* We shouldn't get here unless callers have determined V(l)->W is
438 * shortest / equal-shortest path.
439 */
Paul Jakmabd34fb32007-02-26 17:14:48 +0000440 assert (distance <= w->distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000441
Paul Jakmab75ae992007-03-23 11:17:28 +0000442 if (IS_DEBUG_OSPF_EVENT)
443 {
444 char buf[2][INET_ADDRSTRLEN];
445 zlog_debug ("%s: Adding %s as parent of %s",
446 __func__,
447 inet_ntop(AF_INET, &v->lsa->id, buf[0], sizeof(buf[0])),
448 inet_ntop(AF_INET, &w->lsa->id, buf[1], sizeof(buf[1])));
449 }
450
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000451 /* Adding parent for a new, better path: flush existing parents from W. */
Paul Jakmabd34fb32007-02-26 17:14:48 +0000452 if (distance < w->distance)
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000453 {
Paul Jakmab75ae992007-03-23 11:17:28 +0000454 if (IS_DEBUG_OSPF_EVENT)
455 zlog_debug ("%s: distance %d better than %d, flushing existing parents",
456 __func__, distance, w->distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000457 ospf_spf_flush_parents (w);
Paul Jakmabd34fb32007-02-26 17:14:48 +0000458 w->distance = distance;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000459 }
460
461 /* new parent is <= existing parents, add it to parent list */
462 vp = vertex_parent_new (v, ospf_lsa_has_link (w->lsa, v->lsa), newhop);
463 listnode_add (w->parents, vp);
464
465 return;
466}
467
gdt630e4802004-08-31 17:28:41 +0000468/* 16.1.1. Calculate nexthop from root through V (parent) to
Paul Jakmabd34fb32007-02-26 17:14:48 +0000469 * vertex W (destination), with given distance from root->W.
pauleb3da6d2005-10-18 04:20:33 +0000470 *
471 * The link must be supplied if V is the root vertex. In all other cases
472 * it may be NULL.
Paul Jakmabd34fb32007-02-26 17:14:48 +0000473 *
474 * Note that this function may fail, hence the state of the destination
475 * vertex, W, should /not/ be modified in a dependent manner until
476 * this function returns. This function will update the W vertex with the
477 * provided distance as appropriate.
gdt630e4802004-08-31 17:28:41 +0000478 */
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000479static unsigned int
pauleb3da6d2005-10-18 04:20:33 +0000480ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v,
Paul Jakmabd34fb32007-02-26 17:14:48 +0000481 struct vertex *w, struct router_lsa_link *l,
482 unsigned int distance)
paul718e3742002-12-13 20:15:29 +0000483{
paul1eb8ef22005-04-07 07:30:20 +0000484 struct listnode *node, *nnode;
pauleb3da6d2005-10-18 04:20:33 +0000485 struct vertex_nexthop *nh;
486 struct vertex_parent *vp;
paul718e3742002-12-13 20:15:29 +0000487 struct ospf_interface *oi = NULL;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000488 unsigned int added = 0;
paul0c0f9cd2003-06-06 23:27:04 +0000489
paul718e3742002-12-13 20:15:29 +0000490 if (IS_DEBUG_OSPF_EVENT)
gdt630e4802004-08-31 17:28:41 +0000491 {
ajs2a42e282004-12-08 18:43:03 +0000492 zlog_debug ("ospf_nexthop_calculation(): Start");
gdt630e4802004-08-31 17:28:41 +0000493 ospf_vertex_dump("V (parent):", v, 1, 1);
494 ospf_vertex_dump("W (dest) :", w, 1, 1);
Paul Jakmabd34fb32007-02-26 17:14:48 +0000495 zlog_debug ("V->W distance: %d", distance);
gdt630e4802004-08-31 17:28:41 +0000496 }
paul718e3742002-12-13 20:15:29 +0000497
paul718e3742002-12-13 20:15:29 +0000498 if (v == area->spf)
Paul Jakma9c27ef92006-05-04 07:32:57 +0000499 {
gdt630e4802004-08-31 17:28:41 +0000500 /* 16.1.1 para 4. In the first case, the parent vertex (V) is the
501 root (the calculating router itself). This means that the
502 destination is either a directly connected network or directly
503 connected router. The outgoing interface in this case is simply
504 the OSPF interface connecting to the destination network/router.
505 */
506
paul718e3742002-12-13 20:15:29 +0000507 if (w->type == OSPF_VERTEX_ROUTER)
paul0c0f9cd2003-06-06 23:27:04 +0000508 {
pauleb3da6d2005-10-18 04:20:33 +0000509 /* l is a link from v to w
510 * l2 will be link from w to v
511 */
512 struct router_lsa_link *l2 = NULL;
513
514 /* we *must* be supplied with the link data */
515 assert (l != NULL);
516
517 if (IS_DEBUG_OSPF_EVENT)
paul0c0f9cd2003-06-06 23:27:04 +0000518 {
pauleb3da6d2005-10-18 04:20:33 +0000519 char buf1[BUFSIZ];
520 char buf2[BUFSIZ];
521
522 zlog_debug("ospf_nexthop_calculation(): considering link "
523 "type %d link_id %s link_data %s",
524 l->m[0].type,
525 inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ),
526 inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ));
527 }
paul0c0f9cd2003-06-06 23:27:04 +0000528
pauleb3da6d2005-10-18 04:20:33 +0000529 if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT)
530 {
531 /* If the destination is a router which connects to
532 the calculating router via a Point-to-MultiPoint
533 network, the destination's next hop IP address(es)
534 can be determined by examining the destination's
535 router-LSA: each link pointing back to the
536 calculating router and having a Link Data field
537 belonging to the Point-to-MultiPoint network
538 provides an IP address of the next hop router.
gdt630e4802004-08-31 17:28:41 +0000539
pauleb3da6d2005-10-18 04:20:33 +0000540 At this point l is a link from V to W, and V is the
541 root ("us"). Find the local interface associated
542 with l (its address is in l->link_data). If it
543 is a point-to-multipoint interface, then look through
544 the links in the opposite direction (W to V). If
545 any of them have an address that lands within the
546 subnet declared by the PtMP link, then that link
547 is a constituent of the PtMP link, and its address is
548 a nexthop address for V.
549 */
550 oi = ospf_if_is_configured (area->ospf, &l->link_data);
551 if (oi && oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
paul0c0f9cd2003-06-06 23:27:04 +0000552 {
pauleb3da6d2005-10-18 04:20:33 +0000553 struct prefix_ipv4 la;
gdt630e4802004-08-31 17:28:41 +0000554
pauleb3da6d2005-10-18 04:20:33 +0000555 la.family = AF_INET;
556 la.prefixlen = oi->address->prefixlen;
557
558 /* V links to W on PtMP interface
559 - find the interface address on W */
560 while ((l2 = ospf_get_next_link (w, v, l2)))
paul0c0f9cd2003-06-06 23:27:04 +0000561 {
pauleb3da6d2005-10-18 04:20:33 +0000562 la.prefix = l2->link_data;
gdt630e4802004-08-31 17:28:41 +0000563
pauleb3da6d2005-10-18 04:20:33 +0000564 if (prefix_cmp ((struct prefix *) &la,
565 oi->address) == 0)
566 /* link_data is on our PtMP network */
567 break;
paul0c0f9cd2003-06-06 23:27:04 +0000568 }
pauleb3da6d2005-10-18 04:20:33 +0000569 } /* end l is on point-to-multipoint link */
570 else
571 {
572 /* l is a regular point-to-point link.
573 Look for a link from W to V.
574 */
575 while ((l2 = ospf_get_next_link (w, v, l2)))
paul0c0f9cd2003-06-06 23:27:04 +0000576 {
pauleb3da6d2005-10-18 04:20:33 +0000577 oi = ospf_if_is_configured (area->ospf,
578 &(l2->link_data));
579
580 if (oi == NULL)
581 continue;
582
583 if (!IPV4_ADDR_SAME (&oi->address->u.prefix4,
584 &l->link_data))
585 continue;
586
587 break;
paul0c0f9cd2003-06-06 23:27:04 +0000588 }
pauleb3da6d2005-10-18 04:20:33 +0000589 }
590
591 if (oi && l2)
592 {
593 /* found all necessary info to build nexthop */
594 nh = vertex_nexthop_new ();
595 nh->oi = oi;
596 nh->router = l2->link_data;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000597 ospf_spf_add_parent (v, w, nh, distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000598 return 1;
pauleb3da6d2005-10-18 04:20:33 +0000599 }
600 else
Paul Jakma9c27ef92006-05-04 07:32:57 +0000601 zlog_info("ospf_nexthop_calculation(): "
602 "could not determine nexthop for link");
pauleb3da6d2005-10-18 04:20:33 +0000603 } /* end point-to-point link from V to W */
Paul Jakma9c27ef92006-05-04 07:32:57 +0000604 else if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK)
605 {
606 struct ospf_vl_data *vl_data;
607
608 /* VLink implementation limitations:
609 * a) vl_data can only reference one nexthop, so no ECMP
610 * to backbone through VLinks. Though transit-area
611 * summaries may be considered, and those can be ECMP.
612 * b) We can only use /one/ VLink, even if multiple ones
613 * exist this router through multiple transit-areas.
614 */
615 vl_data = ospf_vl_lookup (area->ospf, NULL, l->link_id);
616
617 if (vl_data
618 && CHECK_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED))
619 {
620 nh = vertex_nexthop_new ();
621 nh->oi = vl_data->nexthop.oi;
622 nh->router = vl_data->nexthop.router;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000623 ospf_spf_add_parent (v, w, nh, distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000624 return 1;
Paul Jakma9c27ef92006-05-04 07:32:57 +0000625 }
626 else
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000627 zlog_info("ospf_nexthop_calculation(): "
628 "vl_data for VL link not found");
Paul Jakma9c27ef92006-05-04 07:32:57 +0000629 } /* end virtual-link from V to W */
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000630 return 0;
gdt630e4802004-08-31 17:28:41 +0000631 } /* end W is a Router vertex */
paul718e3742002-12-13 20:15:29 +0000632 else
paul0c0f9cd2003-06-06 23:27:04 +0000633 {
pauleb3da6d2005-10-18 04:20:33 +0000634 assert(w->type == OSPF_VERTEX_NETWORK);
635 oi = ospf_if_is_configured (area->ospf, &(l->link_data));
636 if (oi)
paul0c0f9cd2003-06-06 23:27:04 +0000637 {
pauleb3da6d2005-10-18 04:20:33 +0000638 nh = vertex_nexthop_new ();
639 nh->oi = oi;
640 nh->router.s_addr = 0;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000641 ospf_spf_add_parent (v, w, nh, distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000642 return 1;
paul0c0f9cd2003-06-06 23:27:04 +0000643 }
644 }
Paul Jakma9c27ef92006-05-04 07:32:57 +0000645 zlog_info("ospf_nexthop_calculation(): "
646 "Unknown attached link");
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000647 return 0;
gdt630e4802004-08-31 17:28:41 +0000648 } /* end V is the root */
gdt630e4802004-08-31 17:28:41 +0000649 /* Check if W's parent is a network connected to root. */
paul718e3742002-12-13 20:15:29 +0000650 else if (v->type == OSPF_VERTEX_NETWORK)
651 {
gdt630e4802004-08-31 17:28:41 +0000652 /* See if any of V's parents are the root. */
pauleb3da6d2005-10-18 04:20:33 +0000653 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
paul718e3742002-12-13 20:15:29 +0000654 {
pauleb3da6d2005-10-18 04:20:33 +0000655 if (vp->parent == area->spf) /* connects to root? */
gdt630e4802004-08-31 17:28:41 +0000656 {
657 /* 16.1.1 para 5. ...the parent vertex is a network that
658 * directly connects the calculating router to the destination
659 * router. The list of next hops is then determined by
660 * examining the destination's router-LSA...
661 */
662
663 assert(w->type == OSPF_VERTEX_ROUTER);
paul0c0f9cd2003-06-06 23:27:04 +0000664 while ((l = ospf_get_next_link (w, v, l)))
665 {
gdt630e4802004-08-31 17:28:41 +0000666 /* ...For each link in the router-LSA that points back to the
667 * parent network, the link's Link Data field provides the IP
668 * address of a next hop router. The outgoing interface to
669 * use can then be derived from the next hop IP address (or
670 * it can be inherited from the parent network).
671 */
pauleb3da6d2005-10-18 04:20:33 +0000672 nh = vertex_nexthop_new ();
673 nh->oi = vp->nexthop->oi;
674 nh->router = l->link_data;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000675 added = 1;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000676 ospf_spf_add_parent (v, w, nh, distance);
paul0c0f9cd2003-06-06 23:27:04 +0000677 }
paul0c0f9cd2003-06-06 23:27:04 +0000678 }
paul718e3742002-12-13 20:15:29 +0000679 }
Paul Jakma85ef7842007-03-23 11:19:08 +0000680 if (added)
681 return added;
paul718e3742002-12-13 20:15:29 +0000682 }
683
gdt630e4802004-08-31 17:28:41 +0000684 /* 16.1.1 para 4. If there is at least one intervening router in the
685 * current shortest path between the destination and the root, the
686 * destination simply inherits the set of next hops from the
687 * parent.
688 */
Paul Jakmab75ae992007-03-23 11:17:28 +0000689 if (IS_DEBUG_OSPF_EVENT)
690 zlog_debug ("%s: Intervening routers, adding parent(s)", __func__);
691
pauleb3da6d2005-10-18 04:20:33 +0000692 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000693 {
694 added = 1;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000695 ospf_spf_add_parent (v, w, vp->nexthop, distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000696 }
Paul Jakma9c27ef92006-05-04 07:32:57 +0000697
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000698 return added;
paul718e3742002-12-13 20:15:29 +0000699}
700
gdt630e4802004-08-31 17:28:41 +0000701/* RFC2328 Section 16.1 (2).
702 * v is on the SPF tree. Examine the links in v's LSA. Update the list
703 * of candidates with any vertices not already on the list. If a lower-cost
704 * path is found to a vertex already on the candidate list, store the new cost.
705 */
paul4dadc292005-05-06 21:37:42 +0000706static void
paul718e3742002-12-13 20:15:29 +0000707ospf_spf_next (struct vertex *v, struct ospf_area *area,
hasso462f20d2005-02-23 11:29:02 +0000708 struct pqueue * candidate)
paul718e3742002-12-13 20:15:29 +0000709{
710 struct ospf_lsa *w_lsa = NULL;
paul718e3742002-12-13 20:15:29 +0000711 u_char *p;
712 u_char *lim;
713 struct router_lsa_link *l = NULL;
714 struct in_addr *r;
paul718e3742002-12-13 20:15:29 +0000715 int type = 0;
716
717 /* If this is a router-LSA, and bit V of the router-LSA (see Section
718 A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE. */
719 if (v->type == OSPF_VERTEX_ROUTER)
720 {
721 if (IS_ROUTER_LSA_VIRTUAL ((struct router_lsa *) v->lsa))
722 area->transit = OSPF_TRANSIT_TRUE;
723 }
Paul Jakmab75ae992007-03-23 11:17:28 +0000724
725 if (IS_DEBUG_OSPF_EVENT)
726 zlog_debug ("%s: Next vertex of %s vertex %s",
727 __func__,
728 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
729 inet_ntoa(v->lsa->id));
730
paul718e3742002-12-13 20:15:29 +0000731 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul0c0f9cd2003-06-06 23:27:04 +0000732 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
733
paul718e3742002-12-13 20:15:29 +0000734 while (p < lim)
735 {
pauleb3da6d2005-10-18 04:20:33 +0000736 struct vertex *w;
737 unsigned int distance;
pauld355bfa2004-04-08 07:43:45 +0000738
paul718e3742002-12-13 20:15:29 +0000739 /* In case of V is Router-LSA. */
740 if (v->lsa->type == OSPF_ROUTER_LSA)
741 {
742 l = (struct router_lsa_link *) p;
743
paul0c0f9cd2003-06-06 23:27:04 +0000744 p += (ROUTER_LSA_MIN_SIZE +
paul718e3742002-12-13 20:15:29 +0000745 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
746
747 /* (a) If this is a link to a stub network, examine the next
748 link in V's LSA. Links to stub networks will be
749 considered in the second stage of the shortest path
750 calculation. */
751 if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB)
752 continue;
753
754 /* (b) Otherwise, W is a transit vertex (router or transit
755 network). Look up the vertex W's LSA (router-LSA or
756 network-LSA) in Area A's link state database. */
757 switch (type)
758 {
759 case LSA_LINK_TYPE_POINTOPOINT:
760 case LSA_LINK_TYPE_VIRTUALLINK:
761 if (type == LSA_LINK_TYPE_VIRTUALLINK)
paul0c0f9cd2003-06-06 23:27:04 +0000762 {
763 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000764 zlog_debug ("looking up LSA through VL: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000765 inet_ntoa (l->link_id));
766 }
paul718e3742002-12-13 20:15:29 +0000767
768 w_lsa = ospf_lsa_lookup (area, OSPF_ROUTER_LSA, l->link_id,
769 l->link_id);
770 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000771 {
772 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000773 zlog_debug ("found Router LSA %s", inet_ntoa (l->link_id));
paul0c0f9cd2003-06-06 23:27:04 +0000774 }
paul718e3742002-12-13 20:15:29 +0000775 break;
776 case LSA_LINK_TYPE_TRANSIT:
paul0c0f9cd2003-06-06 23:27:04 +0000777 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000778 zlog_debug ("Looking up Network LSA, ID: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000779 inet_ntoa (l->link_id));
paul718e3742002-12-13 20:15:29 +0000780 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_NETWORK_LSA,
paul0c0f9cd2003-06-06 23:27:04 +0000781 l->link_id);
paul718e3742002-12-13 20:15:29 +0000782 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000783 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000784 zlog_debug ("found the LSA");
paul718e3742002-12-13 20:15:29 +0000785 break;
786 default:
paul0c0f9cd2003-06-06 23:27:04 +0000787 zlog_warn ("Invalid LSA link type %d", type);
paul718e3742002-12-13 20:15:29 +0000788 continue;
789 }
790 }
791 else
792 {
793 /* In case of V is Network-LSA. */
paul0c0f9cd2003-06-06 23:27:04 +0000794 r = (struct in_addr *) p;
paul718e3742002-12-13 20:15:29 +0000795 p += sizeof (struct in_addr);
796
797 /* Lookup the vertex W's LSA. */
798 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_ROUTER_LSA, *r);
Paul Jakmab75ae992007-03-23 11:17:28 +0000799 if (w_lsa)
800 {
801 if (IS_DEBUG_OSPF_EVENT)
802 zlog_debug ("found Router LSA %s", inet_ntoa (w_lsa->data->id));
803 }
paul718e3742002-12-13 20:15:29 +0000804 }
805
806 /* (b cont.) If the LSA does not exist, or its LS age is equal
807 to MaxAge, or it does not have a link back to vertex V,
808 examine the next link in V's LSA.[23] */
809 if (w_lsa == NULL)
Paul Jakmab75ae992007-03-23 11:17:28 +0000810 {
811 if (IS_DEBUG_OSPF_EVENT)
812 zlog_debug ("No LSA found");
813 continue;
814 }
paul718e3742002-12-13 20:15:29 +0000815
816 if (IS_LSA_MAXAGE (w_lsa))
Paul Jakmab75ae992007-03-23 11:17:28 +0000817 {
818 if (IS_DEBUG_OSPF_EVENT)
819 zlog_debug ("LSA is MaxAge");
820 continue;
821 }
paul718e3742002-12-13 20:15:29 +0000822
pauleb3da6d2005-10-18 04:20:33 +0000823 if (ospf_lsa_has_link (w_lsa->data, v->lsa) < 0 )
paul718e3742002-12-13 20:15:29 +0000824 {
paul0c0f9cd2003-06-06 23:27:04 +0000825 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000826 zlog_debug ("The LSA doesn't have a link back");
paul718e3742002-12-13 20:15:29 +0000827 continue;
828 }
829
830 /* (c) If vertex W is already on the shortest-path tree, examine
831 the next link in the LSA. */
hasso462f20d2005-02-23 11:29:02 +0000832 if (w_lsa->stat == LSA_SPF_IN_SPFTREE)
833 {
834 if (IS_DEBUG_OSPF_EVENT)
835 zlog_debug ("The LSA is already in SPF");
836 continue;
837 }
paul718e3742002-12-13 20:15:29 +0000838
839 /* (d) Calculate the link state cost D of the resulting path
840 from the root to vertex W. D is equal to the sum of the link
841 state cost of the (already calculated) shortest path to
842 vertex V and the advertised cost of the link between vertices
843 V and W. If D is: */
844
paul718e3742002-12-13 20:15:29 +0000845 /* calculate link cost D. */
846 if (v->lsa->type == OSPF_ROUTER_LSA)
pauleb3da6d2005-10-18 04:20:33 +0000847 distance = v->distance + ntohs (l->m[0].metric);
gdt630e4802004-08-31 17:28:41 +0000848 else /* v is not a Router-LSA */
pauleb3da6d2005-10-18 04:20:33 +0000849 distance = v->distance;
paul718e3742002-12-13 20:15:29 +0000850
851 /* Is there already vertex W in candidate list? */
hasso462f20d2005-02-23 11:29:02 +0000852 if (w_lsa->stat == LSA_SPF_NOT_EXPLORED)
853 {
pauleb3da6d2005-10-18 04:20:33 +0000854 /* prepare vertex W. */
855 w = ospf_vertex_new (w_lsa);
856
hasso462f20d2005-02-23 11:29:02 +0000857 /* Calculate nexthop to W. */
Paul Jakmabd34fb32007-02-26 17:14:48 +0000858 if (ospf_nexthop_calculation (area, v, w, l, distance))
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000859 pqueue_enqueue (w, candidate);
Paul Jakmab75ae992007-03-23 11:17:28 +0000860 else if (IS_DEBUG_OSPF_EVENT)
861 zlog_debug ("Nexthop Calc failed");
hasso462f20d2005-02-23 11:29:02 +0000862 }
863 else if (w_lsa->stat >= 0)
864 {
865 /* Get the vertex from candidates. */
pauleb3da6d2005-10-18 04:20:33 +0000866 w = candidate->array[w_lsa->stat];
paul718e3742002-12-13 20:15:29 +0000867
hasso462f20d2005-02-23 11:29:02 +0000868 /* if D is greater than. */
pauleb3da6d2005-10-18 04:20:33 +0000869 if (w->distance < distance)
paul718e3742002-12-13 20:15:29 +0000870 {
paul718e3742002-12-13 20:15:29 +0000871 continue;
872 }
hasso462f20d2005-02-23 11:29:02 +0000873 /* equal to. */
pauleb3da6d2005-10-18 04:20:33 +0000874 else if (w->distance == distance)
paul718e3742002-12-13 20:15:29 +0000875 {
pauleb3da6d2005-10-18 04:20:33 +0000876 /* Found an equal-cost path to W.
877 * Calculate nexthop of to W from V. */
Paul Jakmabd34fb32007-02-26 17:14:48 +0000878 ospf_nexthop_calculation (area, v, w, l, distance);
paul718e3742002-12-13 20:15:29 +0000879 }
hasso462f20d2005-02-23 11:29:02 +0000880 /* less than. */
881 else
paul718e3742002-12-13 20:15:29 +0000882 {
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000883 /* Found a lower-cost path to W.
884 * nexthop_calculation is conditional, if it finds
885 * valid nexthop it will call spf_add_parents, which
886 * will flush the old parents
887 */
Paul Jakmabd34fb32007-02-26 17:14:48 +0000888 if (ospf_nexthop_calculation (area, v, w, l, distance))
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000889 /* Decrease the key of the node in the heap,
890 * re-sort the heap. */
891 trickle_down (w_lsa->stat, candidate);
paul718e3742002-12-13 20:15:29 +0000892 }
gdt630e4802004-08-31 17:28:41 +0000893 } /* end W is already on the candidate list */
894 } /* end loop over the links in V's LSA */
paul718e3742002-12-13 20:15:29 +0000895}
896
paul4dadc292005-05-06 21:37:42 +0000897static void
paul718e3742002-12-13 20:15:29 +0000898ospf_spf_dump (struct vertex *v, int i)
899{
hasso52dc7ee2004-09-23 19:18:23 +0000900 struct listnode *cnode;
901 struct listnode *nnode;
pauleb3da6d2005-10-18 04:20:33 +0000902 struct vertex_parent *parent;
paul718e3742002-12-13 20:15:29 +0000903
904 if (v->type == OSPF_VERTEX_ROUTER)
905 {
906 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000907 zlog_debug ("SPF Result: %d [R] %s", i, inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000908 }
909 else
910 {
911 struct network_lsa *lsa = (struct network_lsa *) v->lsa;
912 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000913 zlog_debug ("SPF Result: %d [N] %s/%d", i, inet_ntoa (v->lsa->id),
paul0c0f9cd2003-06-06 23:27:04 +0000914 ip_masklen (lsa->mask));
gdt630e4802004-08-31 17:28:41 +0000915 }
paul718e3742002-12-13 20:15:29 +0000916
paul1eb8ef22005-04-07 07:30:20 +0000917 if (IS_DEBUG_OSPF_EVENT)
pauleb3da6d2005-10-18 04:20:33 +0000918 for (ALL_LIST_ELEMENTS_RO (v->parents, nnode, parent))
919 {
920 zlog_debug (" nexthop %p %s %s",
921 parent->nexthop,
922 inet_ntoa (parent->nexthop->router),
923 parent->nexthop->oi ? IF_NAME(parent->nexthop->oi)
924 : "NULL");
925 }
paul718e3742002-12-13 20:15:29 +0000926
927 i++;
928
pauleb3da6d2005-10-18 04:20:33 +0000929 for (ALL_LIST_ELEMENTS_RO (v->children, cnode, v))
paul1eb8ef22005-04-07 07:30:20 +0000930 ospf_spf_dump (v, i);
paul718e3742002-12-13 20:15:29 +0000931}
932
933/* Second stage of SPF calculation. */
paul4dadc292005-05-06 21:37:42 +0000934static void
paul0c0f9cd2003-06-06 23:27:04 +0000935ospf_spf_process_stubs (struct ospf_area *area, struct vertex *v,
paul718e3742002-12-13 20:15:29 +0000936 struct route_table *rt)
937{
paul1eb8ef22005-04-07 07:30:20 +0000938 struct listnode *cnode, *cnnode;
paul718e3742002-12-13 20:15:29 +0000939 struct vertex *child;
940
941 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000942 zlog_debug ("ospf_process_stub():processing stubs for area %s",
paul0c0f9cd2003-06-06 23:27:04 +0000943 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +0000944 if (v->type == OSPF_VERTEX_ROUTER)
945 {
946 u_char *p;
947 u_char *lim;
948 struct router_lsa_link *l;
949 struct router_lsa *rlsa;
950
paul0c0f9cd2003-06-06 23:27:04 +0000951 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000952 zlog_debug ("ospf_process_stubs():processing router LSA, id: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000953 inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000954 rlsa = (struct router_lsa *) v->lsa;
955
956
paul0c0f9cd2003-06-06 23:27:04 +0000957 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000958 zlog_debug ("ospf_process_stubs(): we have %d links to process",
paul0c0f9cd2003-06-06 23:27:04 +0000959 ntohs (rlsa->links));
gdt630e4802004-08-31 17:28:41 +0000960 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +0000961 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
962
963 while (p < lim)
964 {
965 l = (struct router_lsa_link *) p;
966
967 p += (ROUTER_LSA_MIN_SIZE +
968 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
969
970 if (l->m[0].type == LSA_LINK_TYPE_STUB)
971 ospf_intra_add_stub (rt, l, v, area);
972 }
973 }
974
gdt630e4802004-08-31 17:28:41 +0000975 ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1, 1);
paul718e3742002-12-13 20:15:29 +0000976
pauleb3da6d2005-10-18 04:20:33 +0000977 for (ALL_LIST_ELEMENTS (v->children, cnode, cnnode, child))
paul718e3742002-12-13 20:15:29 +0000978 {
paul718e3742002-12-13 20:15:29 +0000979 if (CHECK_FLAG (child->flags, OSPF_VERTEX_PROCESSED))
paul0c0f9cd2003-06-06 23:27:04 +0000980 continue;
paul718e3742002-12-13 20:15:29 +0000981
982 ospf_spf_process_stubs (area, child, rt);
983
984 SET_FLAG (child->flags, OSPF_VERTEX_PROCESSED);
985 }
986}
987
988void
989ospf_rtrs_free (struct route_table *rtrs)
990{
991 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +0000992 struct list *or_list;
paul1eb8ef22005-04-07 07:30:20 +0000993 struct ospf_route *or;
994 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000995
996 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000997 zlog_debug ("Route: Router Routing Table free");
paul718e3742002-12-13 20:15:29 +0000998
999 for (rn = route_top (rtrs); rn; rn = route_next (rn))
1000 if ((or_list = rn->info) != NULL)
1001 {
paul1eb8ef22005-04-07 07:30:20 +00001002 for (ALL_LIST_ELEMENTS (or_list, node, nnode, or))
1003 ospf_route_free (or);
paul718e3742002-12-13 20:15:29 +00001004
paul0c0f9cd2003-06-06 23:27:04 +00001005 list_delete (or_list);
paul718e3742002-12-13 20:15:29 +00001006
paul0c0f9cd2003-06-06 23:27:04 +00001007 /* Unlock the node. */
1008 rn->info = NULL;
1009 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001010 }
1011 route_table_finish (rtrs);
1012}
1013
paul4dadc292005-05-06 21:37:42 +00001014static void
paul718e3742002-12-13 20:15:29 +00001015ospf_rtrs_print (struct route_table *rtrs)
1016{
1017 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001018 struct list *or_list;
1019 struct listnode *ln;
1020 struct listnode *pnode;
paul718e3742002-12-13 20:15:29 +00001021 struct ospf_route *or;
1022 struct ospf_path *path;
1023 char buf1[BUFSIZ];
1024 char buf2[BUFSIZ];
1025
1026 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001027 zlog_debug ("ospf_rtrs_print() start");
paul718e3742002-12-13 20:15:29 +00001028
1029 for (rn = route_top (rtrs); rn; rn = route_next (rn))
1030 if ((or_list = rn->info) != NULL)
paul1eb8ef22005-04-07 07:30:20 +00001031 for (ALL_LIST_ELEMENTS_RO (or_list, ln, or))
paul718e3742002-12-13 20:15:29 +00001032 {
paul718e3742002-12-13 20:15:29 +00001033 switch (or->path_type)
1034 {
1035 case OSPF_PATH_INTRA_AREA:
paul0c0f9cd2003-06-06 23:27:04 +00001036 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001037 zlog_debug ("%s [%d] area: %s",
paul0c0f9cd2003-06-06 23:27:04 +00001038 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1039 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1040 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +00001041 break;
1042 case OSPF_PATH_INTER_AREA:
paul0c0f9cd2003-06-06 23:27:04 +00001043 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001044 zlog_debug ("%s IA [%d] area: %s",
paul0c0f9cd2003-06-06 23:27:04 +00001045 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1046 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1047 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +00001048 break;
1049 default:
1050 break;
1051 }
1052
paul1eb8ef22005-04-07 07:30:20 +00001053 for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path))
paul718e3742002-12-13 20:15:29 +00001054 {
paul718e3742002-12-13 20:15:29 +00001055 if (path->nexthop.s_addr == 0)
paul0c0f9cd2003-06-06 23:27:04 +00001056 {
1057 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001058 zlog_debug (" directly attached to %s\r\n",
paul0c0f9cd2003-06-06 23:27:04 +00001059 IF_NAME (path->oi));
1060 }
1061 else
1062 {
1063 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001064 zlog_debug (" via %s, %s\r\n",
paul0c0f9cd2003-06-06 23:27:04 +00001065 inet_ntoa (path->nexthop), IF_NAME (path->oi));
1066 }
paul718e3742002-12-13 20:15:29 +00001067 }
1068 }
1069
ajs2a42e282004-12-08 18:43:03 +00001070 zlog_debug ("ospf_rtrs_print() end");
paul718e3742002-12-13 20:15:29 +00001071}
1072
1073/* Calculating the shortest-path tree for an area. */
paul4dadc292005-05-06 21:37:42 +00001074static void
paul0c0f9cd2003-06-06 23:27:04 +00001075ospf_spf_calculate (struct ospf_area *area, struct route_table *new_table,
paul718e3742002-12-13 20:15:29 +00001076 struct route_table *new_rtrs)
1077{
hasso462f20d2005-02-23 11:29:02 +00001078 struct pqueue *candidate;
paul718e3742002-12-13 20:15:29 +00001079 struct vertex *v;
pauleb3da6d2005-10-18 04:20:33 +00001080
paul718e3742002-12-13 20:15:29 +00001081 if (IS_DEBUG_OSPF_EVENT)
1082 {
ajs2a42e282004-12-08 18:43:03 +00001083 zlog_debug ("ospf_spf_calculate: Start");
1084 zlog_debug ("ospf_spf_calculate: running Dijkstra for area %s",
paul0c0f9cd2003-06-06 23:27:04 +00001085 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001086 }
1087
1088 /* Check router-lsa-self. If self-router-lsa is not yet allocated,
1089 return this area's calculation. */
paul0c0f9cd2003-06-06 23:27:04 +00001090 if (!area->router_lsa_self)
paul718e3742002-12-13 20:15:29 +00001091 {
1092 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001093 zlog_debug ("ospf_spf_calculate: "
paul0c0f9cd2003-06-06 23:27:04 +00001094 "Skip area %s's calculation due to empty router_lsa_self",
1095 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001096 return;
1097 }
1098
1099 /* RFC2328 16.1. (1). */
paul0c0f9cd2003-06-06 23:27:04 +00001100 /* Initialize the algorithm's data structures. */
hasso462f20d2005-02-23 11:29:02 +00001101
1102 /* This function scans all the LSA database and set the stat field to
1103 * LSA_SPF_NOT_EXPLORED. */
1104 ospf_lsdb_clean_stat (area->lsdb);
1105 /* Create a new heap for the candidates. */
1106 candidate = pqueue_create();
1107 candidate->cmp = cmp;
1108 candidate->update = update_stat;
paul718e3742002-12-13 20:15:29 +00001109
1110 /* Initialize the shortest-path tree to only the root (which is the
1111 router doing the calculation). */
1112 ospf_spf_init (area);
1113 v = area->spf;
hasso462f20d2005-02-23 11:29:02 +00001114 /* Set LSA position to LSA_SPF_IN_SPFTREE. This vertex is the root of the
1115 * spanning tree. */
1116 *(v->stat) = LSA_SPF_IN_SPFTREE;
paul718e3742002-12-13 20:15:29 +00001117
1118 /* Set Area A's TransitCapability to FALSE. */
1119 area->transit = OSPF_TRANSIT_FALSE;
1120 area->shortcut_capability = 1;
pauleb3da6d2005-10-18 04:20:33 +00001121
paul718e3742002-12-13 20:15:29 +00001122 for (;;)
1123 {
1124 /* RFC2328 16.1. (2). */
hasso462f20d2005-02-23 11:29:02 +00001125 ospf_spf_next (v, area, candidate);
paul718e3742002-12-13 20:15:29 +00001126
1127 /* RFC2328 16.1. (3). */
1128 /* If at this step the candidate list is empty, the shortest-
1129 path tree (of transit vertices) has been completely built and
1130 this stage of the procedure terminates. */
hasso462f20d2005-02-23 11:29:02 +00001131 if (candidate->size == 0)
paul718e3742002-12-13 20:15:29 +00001132 break;
1133
1134 /* Otherwise, choose the vertex belonging to the candidate list
1135 that is closest to the root, and add it to the shortest-path
1136 tree (removing it from the candidate list in the
paul0c0f9cd2003-06-06 23:27:04 +00001137 process). */
hasso462f20d2005-02-23 11:29:02 +00001138 /* Extract from the candidates the node with the lower key. */
1139 v = (struct vertex *) pqueue_dequeue (candidate);
1140 /* Update stat field in vertex. */
1141 *(v->stat) = LSA_SPF_IN_SPFTREE;
pauleb3da6d2005-10-18 04:20:33 +00001142
paul718e3742002-12-13 20:15:29 +00001143 ospf_vertex_add_parent (v);
1144
paul718e3742002-12-13 20:15:29 +00001145 /* Note that when there is a choice of vertices closest to the
1146 root, network vertices must be chosen before router vertices
1147 in order to necessarily find all equal-cost paths. */
1148 /* We don't do this at this moment, we should add the treatment
1149 above codes. -- kunihiro. */
1150
1151 /* RFC2328 16.1. (4). */
1152 if (v->type == OSPF_VERTEX_ROUTER)
1153 ospf_intra_add_router (new_rtrs, v, area);
paul0c0f9cd2003-06-06 23:27:04 +00001154 else
paul718e3742002-12-13 20:15:29 +00001155 ospf_intra_add_transit (new_table, v, area);
1156
1157 /* RFC2328 16.1. (5). */
1158 /* Iterate the algorithm by returning to Step 2. */
gdt630e4802004-08-31 17:28:41 +00001159
1160 } /* end loop until no more candidate vertices */
paul718e3742002-12-13 20:15:29 +00001161
1162 if (IS_DEBUG_OSPF_EVENT)
1163 {
1164 ospf_spf_dump (area->spf, 0);
1165 ospf_route_table_dump (new_table);
1166 }
1167
1168 /* Second stage of SPF calculation procedure's */
1169 ospf_spf_process_stubs (area, area->spf, new_table);
1170
pauleb3da6d2005-10-18 04:20:33 +00001171 /* Free candidate queue. */
hasso462f20d2005-02-23 11:29:02 +00001172 pqueue_delete (candidate);
pauleb3da6d2005-10-18 04:20:33 +00001173
1174 ospf_vertex_dump (__func__, area->spf, 0, 1);
1175 /* Free nexthop information, canonical versions of which are attached
1176 * the first level of router vertices attached to the root vertex, see
1177 * ospf_nexthop_calculation.
1178 */
1179 ospf_canonical_nexthops_free (area->spf);
1180
Paul Jakma9c27ef92006-05-04 07:32:57 +00001181 /* Free SPF vertices, but not the list. List has ospf_vertex_free
1182 * as deconstructor.
1183 */
1184 list_delete_all_node (&vertex_list);
pauleb3da6d2005-10-18 04:20:33 +00001185
paul718e3742002-12-13 20:15:29 +00001186 /* Increment SPF Calculation Counter. */
1187 area->spf_calculation++;
1188
Paul Jakma2518efd2006-08-27 06:49:29 +00001189 quagga_gettime (QUAGGA_CLK_MONOTONIC, &area->ospf->ts_spf);
paul718e3742002-12-13 20:15:29 +00001190
1191 if (IS_DEBUG_OSPF_EVENT)
Paul Jakma9c27ef92006-05-04 07:32:57 +00001192 zlog_debug ("ospf_spf_calculate: Stop. %ld vertices",
1193 mtype_stats_alloc(MTYPE_OSPF_VERTEX));
paul718e3742002-12-13 20:15:29 +00001194}
1195
1196/* Timer for SPF calculation. */
paul4dadc292005-05-06 21:37:42 +00001197static int
paul68980082003-03-25 05:07:42 +00001198ospf_spf_calculate_timer (struct thread *thread)
paul718e3742002-12-13 20:15:29 +00001199{
paul68980082003-03-25 05:07:42 +00001200 struct ospf *ospf = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +00001201 struct route_table *new_table, *new_rtrs;
paul1eb8ef22005-04-07 07:30:20 +00001202 struct ospf_area *area;
1203 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001204
1205 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001206 zlog_debug ("SPF: Timer (SPF calculation expire)");
paul0c0f9cd2003-06-06 23:27:04 +00001207
paul718e3742002-12-13 20:15:29 +00001208 ospf->t_spf_calc = NULL;
1209
1210 /* Allocate new table tree. */
1211 new_table = route_table_init ();
paul0c0f9cd2003-06-06 23:27:04 +00001212 new_rtrs = route_table_init ();
paul718e3742002-12-13 20:15:29 +00001213
paul68980082003-03-25 05:07:42 +00001214 ospf_vl_unapprove (ospf);
paul718e3742002-12-13 20:15:29 +00001215
1216 /* Calculate SPF for each area. */
paul1eb8ef22005-04-07 07:30:20 +00001217 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
Paul Jakma9c27ef92006-05-04 07:32:57 +00001218 {
1219 /* Do backbone last, so as to first discover intra-area paths
1220 * for any back-bone virtual-links
1221 */
1222 if (ospf->backbone && ospf->backbone == area)
1223 continue;
1224
1225 ospf_spf_calculate (area, new_table, new_rtrs);
1226 }
1227
1228 /* SPF for backbone, if required */
1229 if (ospf->backbone)
1230 ospf_spf_calculate (ospf->backbone, new_table, new_rtrs);
1231
paul68980082003-03-25 05:07:42 +00001232 ospf_vl_shut_unapproved (ospf);
paul718e3742002-12-13 20:15:29 +00001233
paul68980082003-03-25 05:07:42 +00001234 ospf_ia_routing (ospf, new_table, new_rtrs);
paul718e3742002-12-13 20:15:29 +00001235
1236 ospf_prune_unreachable_networks (new_table);
1237 ospf_prune_unreachable_routers (new_rtrs);
1238
1239 /* AS-external-LSA calculation should not be performed here. */
1240
1241 /* If new Router Route is installed,
1242 then schedule re-calculate External routes. */
1243 if (1)
paul68980082003-03-25 05:07:42 +00001244 ospf_ase_calculate_schedule (ospf);
paul718e3742002-12-13 20:15:29 +00001245
paul68980082003-03-25 05:07:42 +00001246 ospf_ase_calculate_timer_add (ospf);
paul718e3742002-12-13 20:15:29 +00001247
1248 /* Update routing table. */
paul68980082003-03-25 05:07:42 +00001249 ospf_route_install (ospf, new_table);
paul718e3742002-12-13 20:15:29 +00001250
1251 /* Update ABR/ASBR routing table */
paul68980082003-03-25 05:07:42 +00001252 if (ospf->old_rtrs)
paul718e3742002-12-13 20:15:29 +00001253 {
1254 /* old_rtrs's node holds linked list of ospf_route. --kunihiro. */
paul68980082003-03-25 05:07:42 +00001255 /* ospf_route_delete (ospf->old_rtrs); */
1256 ospf_rtrs_free (ospf->old_rtrs);
paul718e3742002-12-13 20:15:29 +00001257 }
1258
paul68980082003-03-25 05:07:42 +00001259 ospf->old_rtrs = ospf->new_rtrs;
1260 ospf->new_rtrs = new_rtrs;
paul718e3742002-12-13 20:15:29 +00001261
paul0c0f9cd2003-06-06 23:27:04 +00001262 if (IS_OSPF_ABR (ospf))
paul68980082003-03-25 05:07:42 +00001263 ospf_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001264
1265 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001266 zlog_debug ("SPF: calculation complete");
paul718e3742002-12-13 20:15:29 +00001267
1268 return 0;
1269}
1270
1271/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
1272 set timer for SPF calc. */
1273void
paul68980082003-03-25 05:07:42 +00001274ospf_spf_calculate_schedule (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00001275{
pauld24f6e22005-10-21 09:23:12 +00001276 unsigned long delay, elapsed, ht;
1277 struct timeval result;
paul718e3742002-12-13 20:15:29 +00001278
1279 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001280 zlog_debug ("SPF: calculation timer scheduled");
paul718e3742002-12-13 20:15:29 +00001281
1282 /* OSPF instance does not exist. */
paul68980082003-03-25 05:07:42 +00001283 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001284 return;
pauld24f6e22005-10-21 09:23:12 +00001285
paul718e3742002-12-13 20:15:29 +00001286 /* SPF calculation timer is already scheduled. */
paul68980082003-03-25 05:07:42 +00001287 if (ospf->t_spf_calc)
paul718e3742002-12-13 20:15:29 +00001288 {
1289 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001290 zlog_debug ("SPF: calculation timer is already scheduled: %p",
paul0c0f9cd2003-06-06 23:27:04 +00001291 ospf->t_spf_calc);
paul718e3742002-12-13 20:15:29 +00001292 return;
1293 }
pauld24f6e22005-10-21 09:23:12 +00001294
1295 /* XXX Monotic timers: we only care about relative time here. */
Paul Jakma2518efd2006-08-27 06:49:29 +00001296 result = tv_sub (recent_relative_time (), ospf->ts_spf);
pauld24f6e22005-10-21 09:23:12 +00001297
1298 elapsed = (result.tv_sec * 1000) + (result.tv_usec / 1000);
1299 ht = ospf->spf_holdtime * ospf->spf_hold_multiplier;
1300
1301 if (ht > ospf->spf_max_holdtime)
1302 ht = ospf->spf_max_holdtime;
1303
paul718e3742002-12-13 20:15:29 +00001304 /* Get SPF calculation delay time. */
pauld24f6e22005-10-21 09:23:12 +00001305 if (elapsed < ht)
paul718e3742002-12-13 20:15:29 +00001306 {
pauld24f6e22005-10-21 09:23:12 +00001307 /* Got an event within the hold time of last SPF. We need to
1308 * increase the hold_multiplier, if it's not already at/past
1309 * maximum value, and wasn't already increased..
1310 */
1311 if (ht < ospf->spf_max_holdtime)
1312 ospf->spf_hold_multiplier++;
1313
1314 /* always honour the SPF initial delay */
1315 if ( (ht - elapsed) < ospf->spf_delay)
paul0c0f9cd2003-06-06 23:27:04 +00001316 delay = ospf->spf_delay;
paul718e3742002-12-13 20:15:29 +00001317 else
pauld24f6e22005-10-21 09:23:12 +00001318 delay = ht - elapsed;
paul718e3742002-12-13 20:15:29 +00001319 }
1320 else
pauld24f6e22005-10-21 09:23:12 +00001321 {
1322 /* Event is past required hold-time of last SPF */
1323 delay = ospf->spf_delay;
1324 ospf->spf_hold_multiplier = 1;
1325 }
1326
paul718e3742002-12-13 20:15:29 +00001327 if (IS_DEBUG_OSPF_EVENT)
pauld24f6e22005-10-21 09:23:12 +00001328 zlog_debug ("SPF: calculation timer delay = %ld", delay);
1329
paul68980082003-03-25 05:07:42 +00001330 ospf->t_spf_calc =
pauld24f6e22005-10-21 09:23:12 +00001331 thread_add_timer_msec (master, ospf_spf_calculate_timer, ospf, delay);
paul718e3742002-12-13 20:15:29 +00001332}