blob: ca20022248b2e9665c15a5fad66a85af140edb5b [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;
pauleb3da6d2005-10-18 04:20:33 +0000175 new->children = list_new ();
176 new->parents = list_new ();
Paul Jakma9c27ef92006-05-04 07:32:57 +0000177 new->parents->del = vertex_parent_free;
pauleb3da6d2005-10-18 04:20:33 +0000178
Paul Jakma9c27ef92006-05-04 07:32:57 +0000179 listnode_add (&vertex_list, new);
180
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));
paul718e3742002-12-13 20:15:29 +0000185 return new;
186}
187
paul4dadc292005-05-06 21:37:42 +0000188static void
Paul Jakma9c27ef92006-05-04 07:32:57 +0000189ospf_vertex_free (void *data)
paul718e3742002-12-13 20:15:29 +0000190{
Paul Jakma9c27ef92006-05-04 07:32:57 +0000191 struct vertex *v = data;
paul7461d452005-06-13 13:57:16 +0000192
Paul Jakma9c27ef92006-05-04 07:32:57 +0000193 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));
pauleb3da6d2005-10-18 04:20:33 +0000197
Paul Jakma9c27ef92006-05-04 07:32:57 +0000198 /* 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
pauleb3da6d2005-10-18 04:20:33 +0000201 */
Paul Jakma9c27ef92006-05-04 07:32:57 +0000202 //assert (listcount (v->parents) == 0);
pauleb3da6d2005-10-18 04:20:33 +0000203
Paul Jakma9c27ef92006-05-04 07:32:57 +0000204 if (v->children)
205 list_delete (v->children);
206 v->children = NULL;
207
208 if (v->parents)
209 list_delete (v->parents);
pauleb3da6d2005-10-18 04:20:33 +0000210 v->parents = NULL;
211
212 v->lsa = NULL;
paul7461d452005-06-13 13:57:16 +0000213
paul718e3742002-12-13 20:15:29 +0000214 XFREE (MTYPE_OSPF_VERTEX, v);
215}
216
paul4dadc292005-05-06 21:37:42 +0000217static void
hassoeb1ce602004-10-08 08:17:22 +0000218ospf_vertex_dump(const char *msg, struct vertex *v,
pauleb3da6d2005-10-18 04:20:33 +0000219 int print_parents, int print_children)
gdt630e4802004-08-31 17:28:41 +0000220{
221 if ( ! IS_DEBUG_OSPF_EVENT)
222 return;
223
pauleb3da6d2005-10-18 04:20:33 +0000224 zlog_debug("%s %s vertex %s distance %u flags %u",
gdt630e4802004-08-31 17:28:41 +0000225 msg,
226 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
227 inet_ntoa(v->lsa->id),
228 v->distance,
gdt630e4802004-08-31 17:28:41 +0000229 (unsigned int)v->flags);
230
pauleb3da6d2005-10-18 04:20:33 +0000231 if (print_parents)
gdt630e4802004-08-31 17:28:41 +0000232 {
paul1eb8ef22005-04-07 07:30:20 +0000233 struct listnode *node;
pauleb3da6d2005-10-18 04:20:33 +0000234 struct vertex_parent *vp;
paul1eb8ef22005-04-07 07:30:20 +0000235
pauleb3da6d2005-10-18 04:20:33 +0000236 for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
gdt630e4802004-08-31 17:28:41 +0000237 {
238 char buf1[BUFSIZ];
pauleb3da6d2005-10-18 04:20:33 +0000239
240 if (vp)
gdt630e4802004-08-31 17:28:41 +0000241 {
pauleb3da6d2005-10-18 04:20:33 +0000242 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");
gdt630e4802004-08-31 17:28:41 +0000246 }
247 }
248 }
249
250 if (print_children)
251 {
hasso52dc7ee2004-09-23 19:18:23 +0000252 struct listnode *cnode;
paul1eb8ef22005-04-07 07:30:20 +0000253 struct vertex *cv;
254
pauleb3da6d2005-10-18 04:20:33 +0000255 for (ALL_LIST_ELEMENTS_RO (v->children, cnode, cv))
paul1eb8ef22005-04-07 07:30:20 +0000256 ospf_vertex_dump(" child:", cv, 0, 0);
gdt630e4802004-08-31 17:28:41 +0000257 }
258}
259
260
261/* Add a vertex to the list of children in each of its parents. */
paul4dadc292005-05-06 21:37:42 +0000262static void
paul718e3742002-12-13 20:15:29 +0000263ospf_vertex_add_parent (struct vertex *v)
264{
pauleb3da6d2005-10-18 04:20:33 +0000265 struct vertex_parent *vp;
hasso52dc7ee2004-09-23 19:18:23 +0000266 struct listnode *node;
paul7461d452005-06-13 13:57:16 +0000267
Paul Jakma9c27ef92006-05-04 07:32:57 +0000268 assert (v && v->parents);
paul7461d452005-06-13 13:57:16 +0000269
pauleb3da6d2005-10-18 04:20:33 +0000270 for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
paul718e3742002-12-13 20:15:29 +0000271 {
pauleb3da6d2005-10-18 04:20:33 +0000272 assert (vp->parent && vp->parent->children);
paul7461d452005-06-13 13:57:16 +0000273
paul718e3742002-12-13 20:15:29 +0000274 /* No need to add two links from the same parent. */
pauleb3da6d2005-10-18 04:20:33 +0000275 if (listnode_lookup (vp->parent->children, v) == NULL)
276 listnode_add (vp->parent->children, v);
paul718e3742002-12-13 20:15:29 +0000277 }
278}
279
paul4dadc292005-05-06 21:37:42 +0000280static void
paul718e3742002-12-13 20:15:29 +0000281ospf_spf_init (struct ospf_area *area)
282{
283 struct vertex *v;
Paul Jakma9c27ef92006-05-04 07:32:57 +0000284
paul718e3742002-12-13 20:15:29 +0000285 /* Create root node. */
286 v = ospf_vertex_new (area->router_lsa_self);
Paul Jakmabd34fb32007-02-26 17:14:48 +0000287
paul718e3742002-12-13 20:15:29 +0000288 area->spf = v;
289
290 /* Reset ABR and ASBR router counts. */
291 area->abr_count = 0;
292 area->asbr_count = 0;
293}
294
pauld355bfa2004-04-08 07:43:45 +0000295/* return index of link back to V from W, or -1 if no link found */
paul4dadc292005-05-06 21:37:42 +0000296static int
paul718e3742002-12-13 20:15:29 +0000297ospf_lsa_has_link (struct lsa_header *w, struct lsa_header *v)
298{
hassoeb1ce602004-10-08 08:17:22 +0000299 unsigned int i, length;
paul718e3742002-12-13 20:15:29 +0000300 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)
pauld355bfa2004-04-08 07:43:45 +0000307 return -1;
paul718e3742002-12-13 20:15:29 +0000308
309 nl = (struct network_lsa *) w;
310 length = (ntohs (w->length) - OSPF_LSA_HEADER_SIZE - 4) / 4;
paul0c0f9cd2003-06-06 23:27:04 +0000311
paul718e3742002-12-13 20:15:29 +0000312 for (i = 0; i < length; i++)
313 if (IPV4_ADDR_SAME (&nl->routers[i], &v->id))
pauld355bfa2004-04-08 07:43:45 +0000314 return i;
315 return -1;
paul718e3742002-12-13 20:15:29 +0000316 }
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;
paul0c0f9cd2003-06-06 23:27:04 +0000326 i < ntohs (rl->links) && length >= sizeof (struct router_lsa);
327 i++, length -= 12)
paul718e3742002-12-13 20:15:29 +0000328 {
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 {
pauld355bfa2004-04-08 07:43:45 +0000337 return i;
paul718e3742002-12-13 20:15:29 +0000338 }
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 {
pauld355bfa2004-04-08 07:43:45 +0000345 return i;
paul0c0f9cd2003-06-06 23:27:04 +0000346 }
paul718e3742002-12-13 20:15:29 +0000347 break;
348 case LSA_LINK_TYPE_STUB:
pauleb3da6d2005-10-18 04:20:33 +0000349 /* Stub can't lead anywhere, carry on */
paul718e3742002-12-13 20:15:29 +0000350 continue;
351 default:
352 break;
353 }
354 }
355 }
pauld355bfa2004-04-08 07:43:45 +0000356 return -1;
paul718e3742002-12-13 20:15:29 +0000357}
358
paul718e3742002-12-13 20:15:29 +0000359#define ROUTER_LSA_MIN_SIZE 12
360#define ROUTER_LSA_TOS_SIZE 4
361
gdt630e4802004-08-31 17:28:41 +0000362/* 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 */
paul4dadc292005-05-06 21:37:42 +0000366static struct router_lsa_link *
paul718e3742002-12-13 20:15:29 +0000367ospf_get_next_link (struct vertex *v, struct vertex *w,
paul0c0f9cd2003-06-06 23:27:04 +0000368 struct router_lsa_link *prev_link)
paul718e3742002-12-13 20:15:29 +0000369{
370 u_char *p;
371 u_char *lim;
Joakim Tjernlundbd540372009-07-27 12:42:31 +0200372 u_char lsa_type = LSA_LINK_TYPE_TRANSIT;
paul718e3742002-12-13 20:15:29 +0000373 struct router_lsa_link *l;
374
Joakim Tjernlundbd540372009-07-27 12:42:31 +0200375 if (w->type == OSPF_VERTEX_ROUTER)
376 lsa_type = LSA_LINK_TYPE_POINTOPOINT;
377
paul718e3742002-12-13 20:15:29 +0000378 if (prev_link == NULL)
gdt630e4802004-08-31 17:28:41 +0000379 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +0000380 else
381 {
paul0c0f9cd2003-06-06 23:27:04 +0000382 p = (u_char *) prev_link;
paul718e3742002-12-13 20:15:29 +0000383 p += (ROUTER_LSA_MIN_SIZE +
384 (prev_link->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
385 }
paul0c0f9cd2003-06-06 23:27:04 +0000386
paul718e3742002-12-13 20:15:29 +0000387 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
388
389 while (p < lim)
390 {
391 l = (struct router_lsa_link *) p;
392
paul0c0f9cd2003-06-06 23:27:04 +0000393 p += (ROUTER_LSA_MIN_SIZE + (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
paul718e3742002-12-13 20:15:29 +0000394
Joakim Tjernlundbd540372009-07-27 12:42:31 +0200395 if (l->m[0].type != lsa_type)
paul0c0f9cd2003-06-06 23:27:04 +0000396 continue;
paul718e3742002-12-13 20:15:29 +0000397
398 if (IPV4_ADDR_SAME (&l->link_id, &w->id))
paul0c0f9cd2003-06-06 23:27:04 +0000399 return l;
paul718e3742002-12-13 20:15:29 +0000400 }
401
402 return NULL;
403}
404
pauleb3da6d2005-10-18 04:20:33 +0000405static void
406ospf_spf_flush_parents (struct vertex *w)
407{
408 struct vertex_parent *vp;
409 struct listnode *ln, *nn;
410
411 /* delete the existing nexthops */
412 for (ALL_LIST_ELEMENTS (w->parents, ln, nn, vp))
413 {
414 list_delete_node (w->parents, ln);
415 vertex_parent_free (vp);
416 }
417}
418
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000419/*
420 * Consider supplied next-hop for inclusion to the supplied list of
421 * equal-cost next-hops, adjust list as neccessary.
422 */
423static void
424ospf_spf_add_parent (struct vertex *v, struct vertex *w,
425 struct vertex_nexthop *newhop,
Paul Jakmabd34fb32007-02-26 17:14:48 +0000426 unsigned int distance)
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000427{
428 struct vertex_parent *vp;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000429
Paul Jakma08d3d5b2007-05-07 16:38:35 +0000430 /* we must have a newhop, and a distance */
Paul Jakmabd34fb32007-02-26 17:14:48 +0000431 assert (v && w && newhop);
Paul Jakma08d3d5b2007-05-07 16:38:35 +0000432 assert (distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000433
Paul Jakma08d3d5b2007-05-07 16:38:35 +0000434 /* IFF w has already been assigned a distance, then we shouldn't get here
435 * unless callers have determined V(l)->W is shortest / equal-shortest
436 * path (0 is a special case distance (no distance yet assigned)).
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000437 */
Paul Jakma08d3d5b2007-05-07 16:38:35 +0000438 if (w->distance)
439 assert (distance <= w->distance);
440 else
441 w->distance = distance;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000442
Paul Jakmab75ae992007-03-23 11:17:28 +0000443 if (IS_DEBUG_OSPF_EVENT)
444 {
445 char buf[2][INET_ADDRSTRLEN];
446 zlog_debug ("%s: Adding %s as parent of %s",
447 __func__,
448 inet_ntop(AF_INET, &v->lsa->id, buf[0], sizeof(buf[0])),
449 inet_ntop(AF_INET, &w->lsa->id, buf[1], sizeof(buf[1])));
450 }
451
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000452 /* Adding parent for a new, better path: flush existing parents from W. */
Paul Jakmabd34fb32007-02-26 17:14:48 +0000453 if (distance < w->distance)
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000454 {
Paul Jakmab75ae992007-03-23 11:17:28 +0000455 if (IS_DEBUG_OSPF_EVENT)
456 zlog_debug ("%s: distance %d better than %d, flushing existing parents",
457 __func__, distance, w->distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000458 ospf_spf_flush_parents (w);
Paul Jakmabd34fb32007-02-26 17:14:48 +0000459 w->distance = distance;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000460 }
461
462 /* new parent is <= existing parents, add it to parent list */
463 vp = vertex_parent_new (v, ospf_lsa_has_link (w->lsa, v->lsa), newhop);
464 listnode_add (w->parents, vp);
465
466 return;
467}
468
gdt630e4802004-08-31 17:28:41 +0000469/* 16.1.1. Calculate nexthop from root through V (parent) to
Paul Jakmabd34fb32007-02-26 17:14:48 +0000470 * vertex W (destination), with given distance from root->W.
pauleb3da6d2005-10-18 04:20:33 +0000471 *
472 * The link must be supplied if V is the root vertex. In all other cases
473 * it may be NULL.
Paul Jakmabd34fb32007-02-26 17:14:48 +0000474 *
475 * Note that this function may fail, hence the state of the destination
476 * vertex, W, should /not/ be modified in a dependent manner until
477 * this function returns. This function will update the W vertex with the
478 * provided distance as appropriate.
gdt630e4802004-08-31 17:28:41 +0000479 */
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000480static unsigned int
pauleb3da6d2005-10-18 04:20:33 +0000481ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v,
Paul Jakmabd34fb32007-02-26 17:14:48 +0000482 struct vertex *w, struct router_lsa_link *l,
483 unsigned int distance)
paul718e3742002-12-13 20:15:29 +0000484{
paul1eb8ef22005-04-07 07:30:20 +0000485 struct listnode *node, *nnode;
pauleb3da6d2005-10-18 04:20:33 +0000486 struct vertex_nexthop *nh;
487 struct vertex_parent *vp;
paul718e3742002-12-13 20:15:29 +0000488 struct ospf_interface *oi = NULL;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000489 unsigned int added = 0;
paul0c0f9cd2003-06-06 23:27:04 +0000490
paul718e3742002-12-13 20:15:29 +0000491 if (IS_DEBUG_OSPF_EVENT)
gdt630e4802004-08-31 17:28:41 +0000492 {
ajs2a42e282004-12-08 18:43:03 +0000493 zlog_debug ("ospf_nexthop_calculation(): Start");
gdt630e4802004-08-31 17:28:41 +0000494 ospf_vertex_dump("V (parent):", v, 1, 1);
495 ospf_vertex_dump("W (dest) :", w, 1, 1);
Paul Jakmabd34fb32007-02-26 17:14:48 +0000496 zlog_debug ("V->W distance: %d", distance);
gdt630e4802004-08-31 17:28:41 +0000497 }
paul718e3742002-12-13 20:15:29 +0000498
paul718e3742002-12-13 20:15:29 +0000499 if (v == area->spf)
Paul Jakma9c27ef92006-05-04 07:32:57 +0000500 {
gdt630e4802004-08-31 17:28:41 +0000501 /* 16.1.1 para 4. In the first case, the parent vertex (V) is the
502 root (the calculating router itself). This means that the
503 destination is either a directly connected network or directly
504 connected router. The outgoing interface in this case is simply
505 the OSPF interface connecting to the destination network/router.
506 */
507
paul718e3742002-12-13 20:15:29 +0000508 if (w->type == OSPF_VERTEX_ROUTER)
paul0c0f9cd2003-06-06 23:27:04 +0000509 {
pauleb3da6d2005-10-18 04:20:33 +0000510 /* l is a link from v to w
511 * l2 will be link from w to v
512 */
513 struct router_lsa_link *l2 = NULL;
514
515 /* we *must* be supplied with the link data */
516 assert (l != NULL);
517
518 if (IS_DEBUG_OSPF_EVENT)
paul0c0f9cd2003-06-06 23:27:04 +0000519 {
pauleb3da6d2005-10-18 04:20:33 +0000520 char buf1[BUFSIZ];
521 char buf2[BUFSIZ];
522
523 zlog_debug("ospf_nexthop_calculation(): considering link "
524 "type %d link_id %s link_data %s",
525 l->m[0].type,
526 inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ),
527 inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ));
528 }
paul0c0f9cd2003-06-06 23:27:04 +0000529
pauleb3da6d2005-10-18 04:20:33 +0000530 if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT)
531 {
532 /* If the destination is a router which connects to
533 the calculating router via a Point-to-MultiPoint
534 network, the destination's next hop IP address(es)
535 can be determined by examining the destination's
536 router-LSA: each link pointing back to the
537 calculating router and having a Link Data field
538 belonging to the Point-to-MultiPoint network
539 provides an IP address of the next hop router.
gdt630e4802004-08-31 17:28:41 +0000540
pauleb3da6d2005-10-18 04:20:33 +0000541 At this point l is a link from V to W, and V is the
542 root ("us"). Find the local interface associated
543 with l (its address is in l->link_data). If it
544 is a point-to-multipoint interface, then look through
545 the links in the opposite direction (W to V). If
546 any of them have an address that lands within the
547 subnet declared by the PtMP link, then that link
548 is a constituent of the PtMP link, and its address is
549 a nexthop address for V.
550 */
551 oi = ospf_if_is_configured (area->ospf, &l->link_data);
552 if (oi && oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
paul0c0f9cd2003-06-06 23:27:04 +0000553 {
pauleb3da6d2005-10-18 04:20:33 +0000554 struct prefix_ipv4 la;
gdt630e4802004-08-31 17:28:41 +0000555
pauleb3da6d2005-10-18 04:20:33 +0000556 la.family = AF_INET;
557 la.prefixlen = oi->address->prefixlen;
558
559 /* V links to W on PtMP interface
560 - find the interface address on W */
561 while ((l2 = ospf_get_next_link (w, v, l2)))
paul0c0f9cd2003-06-06 23:27:04 +0000562 {
pauleb3da6d2005-10-18 04:20:33 +0000563 la.prefix = l2->link_data;
gdt630e4802004-08-31 17:28:41 +0000564
pauleb3da6d2005-10-18 04:20:33 +0000565 if (prefix_cmp ((struct prefix *) &la,
566 oi->address) == 0)
567 /* link_data is on our PtMP network */
568 break;
paul0c0f9cd2003-06-06 23:27:04 +0000569 }
pauleb3da6d2005-10-18 04:20:33 +0000570 } /* end l is on point-to-multipoint link */
571 else
572 {
573 /* l is a regular point-to-point link.
574 Look for a link from W to V.
575 */
576 while ((l2 = ospf_get_next_link (w, v, l2)))
paul0c0f9cd2003-06-06 23:27:04 +0000577 {
pauleb3da6d2005-10-18 04:20:33 +0000578 oi = ospf_if_is_configured (area->ospf,
579 &(l2->link_data));
580
581 if (oi == NULL)
582 continue;
583
584 if (!IPV4_ADDR_SAME (&oi->address->u.prefix4,
585 &l->link_data))
586 continue;
587
588 break;
paul0c0f9cd2003-06-06 23:27:04 +0000589 }
pauleb3da6d2005-10-18 04:20:33 +0000590 }
591
592 if (oi && l2)
593 {
594 /* found all necessary info to build nexthop */
595 nh = vertex_nexthop_new ();
596 nh->oi = oi;
597 nh->router = l2->link_data;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000598 ospf_spf_add_parent (v, w, nh, distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000599 return 1;
pauleb3da6d2005-10-18 04:20:33 +0000600 }
601 else
Paul Jakma9c27ef92006-05-04 07:32:57 +0000602 zlog_info("ospf_nexthop_calculation(): "
603 "could not determine nexthop for link");
pauleb3da6d2005-10-18 04:20:33 +0000604 } /* end point-to-point link from V to W */
Paul Jakma9c27ef92006-05-04 07:32:57 +0000605 else if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK)
606 {
607 struct ospf_vl_data *vl_data;
608
609 /* VLink implementation limitations:
610 * a) vl_data can only reference one nexthop, so no ECMP
611 * to backbone through VLinks. Though transit-area
612 * summaries may be considered, and those can be ECMP.
613 * b) We can only use /one/ VLink, even if multiple ones
614 * exist this router through multiple transit-areas.
615 */
616 vl_data = ospf_vl_lookup (area->ospf, NULL, l->link_id);
617
618 if (vl_data
619 && CHECK_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED))
620 {
621 nh = vertex_nexthop_new ();
622 nh->oi = vl_data->nexthop.oi;
623 nh->router = vl_data->nexthop.router;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000624 ospf_spf_add_parent (v, w, nh, distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000625 return 1;
Paul Jakma9c27ef92006-05-04 07:32:57 +0000626 }
627 else
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000628 zlog_info("ospf_nexthop_calculation(): "
629 "vl_data for VL link not found");
Paul Jakma9c27ef92006-05-04 07:32:57 +0000630 } /* end virtual-link from V to W */
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000631 return 0;
gdt630e4802004-08-31 17:28:41 +0000632 } /* end W is a Router vertex */
paul718e3742002-12-13 20:15:29 +0000633 else
paul0c0f9cd2003-06-06 23:27:04 +0000634 {
pauleb3da6d2005-10-18 04:20:33 +0000635 assert(w->type == OSPF_VERTEX_NETWORK);
636 oi = ospf_if_is_configured (area->ospf, &(l->link_data));
637 if (oi)
paul0c0f9cd2003-06-06 23:27:04 +0000638 {
pauleb3da6d2005-10-18 04:20:33 +0000639 nh = vertex_nexthop_new ();
640 nh->oi = oi;
641 nh->router.s_addr = 0;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000642 ospf_spf_add_parent (v, w, nh, distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000643 return 1;
paul0c0f9cd2003-06-06 23:27:04 +0000644 }
645 }
Paul Jakma9c27ef92006-05-04 07:32:57 +0000646 zlog_info("ospf_nexthop_calculation(): "
647 "Unknown attached link");
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000648 return 0;
gdt630e4802004-08-31 17:28:41 +0000649 } /* end V is the root */
gdt630e4802004-08-31 17:28:41 +0000650 /* Check if W's parent is a network connected to root. */
paul718e3742002-12-13 20:15:29 +0000651 else if (v->type == OSPF_VERTEX_NETWORK)
652 {
gdt630e4802004-08-31 17:28:41 +0000653 /* See if any of V's parents are the root. */
pauleb3da6d2005-10-18 04:20:33 +0000654 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
paul718e3742002-12-13 20:15:29 +0000655 {
pauleb3da6d2005-10-18 04:20:33 +0000656 if (vp->parent == area->spf) /* connects to root? */
gdt630e4802004-08-31 17:28:41 +0000657 {
658 /* 16.1.1 para 5. ...the parent vertex is a network that
659 * directly connects the calculating router to the destination
660 * router. The list of next hops is then determined by
661 * examining the destination's router-LSA...
662 */
663
664 assert(w->type == OSPF_VERTEX_ROUTER);
paul0c0f9cd2003-06-06 23:27:04 +0000665 while ((l = ospf_get_next_link (w, v, l)))
666 {
gdt630e4802004-08-31 17:28:41 +0000667 /* ...For each link in the router-LSA that points back to the
668 * parent network, the link's Link Data field provides the IP
669 * address of a next hop router. The outgoing interface to
670 * use can then be derived from the next hop IP address (or
671 * it can be inherited from the parent network).
672 */
pauleb3da6d2005-10-18 04:20:33 +0000673 nh = vertex_nexthop_new ();
674 nh->oi = vp->nexthop->oi;
675 nh->router = l->link_data;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000676 added = 1;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000677 ospf_spf_add_parent (v, w, nh, distance);
paul0c0f9cd2003-06-06 23:27:04 +0000678 }
paul0c0f9cd2003-06-06 23:27:04 +0000679 }
paul718e3742002-12-13 20:15:29 +0000680 }
Paul Jakma4ca15d42009-08-03 15:16:41 +0100681 /* NB: This code is non-trivial.
682 *
683 * E.g. it is not enough to know that V connects to the root. It is
684 * also important that the while above, looping through all links from
685 * W->V found at least one link, so that we know there is
686 * bi-directional connectivity between V and W. Otherwise, if we
687 * /always/ return here, but don't check that W->V exists then we
688 * we will prevent SPF from finding/using higher cost paths..
689 *
690 * See also bug #330, and also:
691 *
692 * http://blogs.sun.com/paulj/entry/the_difference_a_line_makes
693 */
Paul Jakma85ef7842007-03-23 11:19:08 +0000694 if (added)
695 return added;
paul718e3742002-12-13 20:15:29 +0000696 }
697
gdt630e4802004-08-31 17:28:41 +0000698 /* 16.1.1 para 4. If there is at least one intervening router in the
699 * current shortest path between the destination and the root, the
700 * destination simply inherits the set of next hops from the
701 * parent.
702 */
Paul Jakmab75ae992007-03-23 11:17:28 +0000703 if (IS_DEBUG_OSPF_EVENT)
704 zlog_debug ("%s: Intervening routers, adding parent(s)", __func__);
705
pauleb3da6d2005-10-18 04:20:33 +0000706 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000707 {
708 added = 1;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000709 ospf_spf_add_parent (v, w, vp->nexthop, distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000710 }
Paul Jakma9c27ef92006-05-04 07:32:57 +0000711
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000712 return added;
paul718e3742002-12-13 20:15:29 +0000713}
714
gdt630e4802004-08-31 17:28:41 +0000715/* RFC2328 Section 16.1 (2).
716 * v is on the SPF tree. Examine the links in v's LSA. Update the list
717 * of candidates with any vertices not already on the list. If a lower-cost
718 * path is found to a vertex already on the candidate list, store the new cost.
719 */
paul4dadc292005-05-06 21:37:42 +0000720static void
paul718e3742002-12-13 20:15:29 +0000721ospf_spf_next (struct vertex *v, struct ospf_area *area,
hasso462f20d2005-02-23 11:29:02 +0000722 struct pqueue * candidate)
paul718e3742002-12-13 20:15:29 +0000723{
724 struct ospf_lsa *w_lsa = NULL;
paul718e3742002-12-13 20:15:29 +0000725 u_char *p;
726 u_char *lim;
727 struct router_lsa_link *l = NULL;
728 struct in_addr *r;
paul718e3742002-12-13 20:15:29 +0000729 int type = 0;
730
731 /* If this is a router-LSA, and bit V of the router-LSA (see Section
732 A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE. */
733 if (v->type == OSPF_VERTEX_ROUTER)
734 {
735 if (IS_ROUTER_LSA_VIRTUAL ((struct router_lsa *) v->lsa))
736 area->transit = OSPF_TRANSIT_TRUE;
737 }
Paul Jakmab75ae992007-03-23 11:17:28 +0000738
739 if (IS_DEBUG_OSPF_EVENT)
740 zlog_debug ("%s: Next vertex of %s vertex %s",
741 __func__,
742 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
743 inet_ntoa(v->lsa->id));
744
paul718e3742002-12-13 20:15:29 +0000745 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul0c0f9cd2003-06-06 23:27:04 +0000746 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
747
paul718e3742002-12-13 20:15:29 +0000748 while (p < lim)
749 {
pauleb3da6d2005-10-18 04:20:33 +0000750 struct vertex *w;
751 unsigned int distance;
pauld355bfa2004-04-08 07:43:45 +0000752
paul718e3742002-12-13 20:15:29 +0000753 /* In case of V is Router-LSA. */
754 if (v->lsa->type == OSPF_ROUTER_LSA)
755 {
756 l = (struct router_lsa_link *) p;
757
paul0c0f9cd2003-06-06 23:27:04 +0000758 p += (ROUTER_LSA_MIN_SIZE +
paul718e3742002-12-13 20:15:29 +0000759 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
760
761 /* (a) If this is a link to a stub network, examine the next
762 link in V's LSA. Links to stub networks will be
763 considered in the second stage of the shortest path
764 calculation. */
765 if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB)
766 continue;
Paul Jakma08d3d5b2007-05-07 16:38:35 +0000767
768 /* Infinite distance links shouldn't be followed, except
769 * for local links (a stub-routed router still wants to
770 * calculate tree, so must follow its own links).
771 */
772 if ((v != area->spf) && l->m[0].metric >= OSPF_OUTPUT_COST_INFINITE)
773 continue;
paul718e3742002-12-13 20:15:29 +0000774
775 /* (b) Otherwise, W is a transit vertex (router or transit
776 network). Look up the vertex W's LSA (router-LSA or
777 network-LSA) in Area A's link state database. */
778 switch (type)
779 {
780 case LSA_LINK_TYPE_POINTOPOINT:
781 case LSA_LINK_TYPE_VIRTUALLINK:
782 if (type == LSA_LINK_TYPE_VIRTUALLINK)
paul0c0f9cd2003-06-06 23:27:04 +0000783 {
784 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000785 zlog_debug ("looking up LSA through VL: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000786 inet_ntoa (l->link_id));
787 }
paul718e3742002-12-13 20:15:29 +0000788
789 w_lsa = ospf_lsa_lookup (area, OSPF_ROUTER_LSA, l->link_id,
790 l->link_id);
791 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000792 {
793 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000794 zlog_debug ("found Router LSA %s", inet_ntoa (l->link_id));
paul0c0f9cd2003-06-06 23:27:04 +0000795 }
paul718e3742002-12-13 20:15:29 +0000796 break;
797 case LSA_LINK_TYPE_TRANSIT:
paul0c0f9cd2003-06-06 23:27:04 +0000798 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000799 zlog_debug ("Looking up Network LSA, ID: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000800 inet_ntoa (l->link_id));
paul718e3742002-12-13 20:15:29 +0000801 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_NETWORK_LSA,
paul0c0f9cd2003-06-06 23:27:04 +0000802 l->link_id);
paul718e3742002-12-13 20:15:29 +0000803 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000804 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000805 zlog_debug ("found the LSA");
paul718e3742002-12-13 20:15:29 +0000806 break;
807 default:
paul0c0f9cd2003-06-06 23:27:04 +0000808 zlog_warn ("Invalid LSA link type %d", type);
paul718e3742002-12-13 20:15:29 +0000809 continue;
810 }
811 }
812 else
813 {
814 /* In case of V is Network-LSA. */
paul0c0f9cd2003-06-06 23:27:04 +0000815 r = (struct in_addr *) p;
paul718e3742002-12-13 20:15:29 +0000816 p += sizeof (struct in_addr);
817
818 /* Lookup the vertex W's LSA. */
819 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_ROUTER_LSA, *r);
Paul Jakmab75ae992007-03-23 11:17:28 +0000820 if (w_lsa)
821 {
822 if (IS_DEBUG_OSPF_EVENT)
823 zlog_debug ("found Router LSA %s", inet_ntoa (w_lsa->data->id));
824 }
paul718e3742002-12-13 20:15:29 +0000825 }
826
827 /* (b cont.) If the LSA does not exist, or its LS age is equal
828 to MaxAge, or it does not have a link back to vertex V,
829 examine the next link in V's LSA.[23] */
830 if (w_lsa == NULL)
Paul Jakmab75ae992007-03-23 11:17:28 +0000831 {
832 if (IS_DEBUG_OSPF_EVENT)
833 zlog_debug ("No LSA found");
834 continue;
835 }
paul718e3742002-12-13 20:15:29 +0000836
837 if (IS_LSA_MAXAGE (w_lsa))
Paul Jakmab75ae992007-03-23 11:17:28 +0000838 {
839 if (IS_DEBUG_OSPF_EVENT)
840 zlog_debug ("LSA is MaxAge");
841 continue;
842 }
paul718e3742002-12-13 20:15:29 +0000843
pauleb3da6d2005-10-18 04:20:33 +0000844 if (ospf_lsa_has_link (w_lsa->data, v->lsa) < 0 )
paul718e3742002-12-13 20:15:29 +0000845 {
paul0c0f9cd2003-06-06 23:27:04 +0000846 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000847 zlog_debug ("The LSA doesn't have a link back");
paul718e3742002-12-13 20:15:29 +0000848 continue;
849 }
850
851 /* (c) If vertex W is already on the shortest-path tree, examine
852 the next link in the LSA. */
hasso462f20d2005-02-23 11:29:02 +0000853 if (w_lsa->stat == LSA_SPF_IN_SPFTREE)
854 {
855 if (IS_DEBUG_OSPF_EVENT)
856 zlog_debug ("The LSA is already in SPF");
857 continue;
858 }
paul718e3742002-12-13 20:15:29 +0000859
860 /* (d) Calculate the link state cost D of the resulting path
861 from the root to vertex W. D is equal to the sum of the link
862 state cost of the (already calculated) shortest path to
863 vertex V and the advertised cost of the link between vertices
864 V and W. If D is: */
865
paul718e3742002-12-13 20:15:29 +0000866 /* calculate link cost D. */
867 if (v->lsa->type == OSPF_ROUTER_LSA)
pauleb3da6d2005-10-18 04:20:33 +0000868 distance = v->distance + ntohs (l->m[0].metric);
gdt630e4802004-08-31 17:28:41 +0000869 else /* v is not a Router-LSA */
pauleb3da6d2005-10-18 04:20:33 +0000870 distance = v->distance;
paul718e3742002-12-13 20:15:29 +0000871
872 /* Is there already vertex W in candidate list? */
hasso462f20d2005-02-23 11:29:02 +0000873 if (w_lsa->stat == LSA_SPF_NOT_EXPLORED)
874 {
pauleb3da6d2005-10-18 04:20:33 +0000875 /* prepare vertex W. */
876 w = ospf_vertex_new (w_lsa);
877
hasso462f20d2005-02-23 11:29:02 +0000878 /* Calculate nexthop to W. */
Paul Jakmabd34fb32007-02-26 17:14:48 +0000879 if (ospf_nexthop_calculation (area, v, w, l, distance))
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000880 pqueue_enqueue (w, candidate);
Paul Jakmab75ae992007-03-23 11:17:28 +0000881 else if (IS_DEBUG_OSPF_EVENT)
882 zlog_debug ("Nexthop Calc failed");
hasso462f20d2005-02-23 11:29:02 +0000883 }
884 else if (w_lsa->stat >= 0)
885 {
886 /* Get the vertex from candidates. */
pauleb3da6d2005-10-18 04:20:33 +0000887 w = candidate->array[w_lsa->stat];
paul718e3742002-12-13 20:15:29 +0000888
hasso462f20d2005-02-23 11:29:02 +0000889 /* if D is greater than. */
pauleb3da6d2005-10-18 04:20:33 +0000890 if (w->distance < distance)
paul718e3742002-12-13 20:15:29 +0000891 {
paul718e3742002-12-13 20:15:29 +0000892 continue;
893 }
hasso462f20d2005-02-23 11:29:02 +0000894 /* equal to. */
pauleb3da6d2005-10-18 04:20:33 +0000895 else if (w->distance == distance)
paul718e3742002-12-13 20:15:29 +0000896 {
pauleb3da6d2005-10-18 04:20:33 +0000897 /* Found an equal-cost path to W.
898 * Calculate nexthop of to W from V. */
Paul Jakmabd34fb32007-02-26 17:14:48 +0000899 ospf_nexthop_calculation (area, v, w, l, distance);
paul718e3742002-12-13 20:15:29 +0000900 }
hasso462f20d2005-02-23 11:29:02 +0000901 /* less than. */
902 else
paul718e3742002-12-13 20:15:29 +0000903 {
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000904 /* Found a lower-cost path to W.
905 * nexthop_calculation is conditional, if it finds
906 * valid nexthop it will call spf_add_parents, which
907 * will flush the old parents
908 */
Paul Jakmabd34fb32007-02-26 17:14:48 +0000909 if (ospf_nexthop_calculation (area, v, w, l, distance))
Paul Jakma7591d8b2007-08-06 18:52:45 +0000910 /* Decrease the key of the node in the heap.
911 * trickle-sort it up towards root, just in case this
912 * node should now be the new root due the cost change.
Paul Jakmae95537f2007-08-07 16:22:05 +0000913 * (next pqueu_{de,en}queue will fully re-heap the queue).
Paul Jakma7591d8b2007-08-06 18:52:45 +0000914 */
915 trickle_up (w_lsa->stat, candidate);
paul718e3742002-12-13 20:15:29 +0000916 }
gdt630e4802004-08-31 17:28:41 +0000917 } /* end W is already on the candidate list */
918 } /* end loop over the links in V's LSA */
paul718e3742002-12-13 20:15:29 +0000919}
920
paul4dadc292005-05-06 21:37:42 +0000921static void
paul718e3742002-12-13 20:15:29 +0000922ospf_spf_dump (struct vertex *v, int i)
923{
hasso52dc7ee2004-09-23 19:18:23 +0000924 struct listnode *cnode;
925 struct listnode *nnode;
pauleb3da6d2005-10-18 04:20:33 +0000926 struct vertex_parent *parent;
paul718e3742002-12-13 20:15:29 +0000927
928 if (v->type == OSPF_VERTEX_ROUTER)
929 {
930 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000931 zlog_debug ("SPF Result: %d [R] %s", i, inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000932 }
933 else
934 {
935 struct network_lsa *lsa = (struct network_lsa *) v->lsa;
936 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000937 zlog_debug ("SPF Result: %d [N] %s/%d", i, inet_ntoa (v->lsa->id),
paul0c0f9cd2003-06-06 23:27:04 +0000938 ip_masklen (lsa->mask));
gdt630e4802004-08-31 17:28:41 +0000939 }
paul718e3742002-12-13 20:15:29 +0000940
paul1eb8ef22005-04-07 07:30:20 +0000941 if (IS_DEBUG_OSPF_EVENT)
pauleb3da6d2005-10-18 04:20:33 +0000942 for (ALL_LIST_ELEMENTS_RO (v->parents, nnode, parent))
943 {
944 zlog_debug (" nexthop %p %s %s",
945 parent->nexthop,
946 inet_ntoa (parent->nexthop->router),
947 parent->nexthop->oi ? IF_NAME(parent->nexthop->oi)
948 : "NULL");
949 }
paul718e3742002-12-13 20:15:29 +0000950
951 i++;
952
pauleb3da6d2005-10-18 04:20:33 +0000953 for (ALL_LIST_ELEMENTS_RO (v->children, cnode, v))
paul1eb8ef22005-04-07 07:30:20 +0000954 ospf_spf_dump (v, i);
paul718e3742002-12-13 20:15:29 +0000955}
956
957/* Second stage of SPF calculation. */
paul4dadc292005-05-06 21:37:42 +0000958static void
paul0c0f9cd2003-06-06 23:27:04 +0000959ospf_spf_process_stubs (struct ospf_area *area, struct vertex *v,
Paul Jakmab3bc68e2008-09-04 13:52:07 +0100960 struct route_table *rt,
961 int parent_is_root)
paul718e3742002-12-13 20:15:29 +0000962{
paul1eb8ef22005-04-07 07:30:20 +0000963 struct listnode *cnode, *cnnode;
paul718e3742002-12-13 20:15:29 +0000964 struct vertex *child;
965
966 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000967 zlog_debug ("ospf_process_stub():processing stubs for area %s",
paul0c0f9cd2003-06-06 23:27:04 +0000968 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +0000969 if (v->type == OSPF_VERTEX_ROUTER)
970 {
971 u_char *p;
972 u_char *lim;
973 struct router_lsa_link *l;
974 struct router_lsa *rlsa;
975
paul0c0f9cd2003-06-06 23:27:04 +0000976 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000977 zlog_debug ("ospf_process_stubs():processing router LSA, id: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000978 inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000979 rlsa = (struct router_lsa *) v->lsa;
980
981
paul0c0f9cd2003-06-06 23:27:04 +0000982 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000983 zlog_debug ("ospf_process_stubs(): we have %d links to process",
paul0c0f9cd2003-06-06 23:27:04 +0000984 ntohs (rlsa->links));
gdt630e4802004-08-31 17:28:41 +0000985 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +0000986 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
987
988 while (p < lim)
989 {
990 l = (struct router_lsa_link *) p;
991
992 p += (ROUTER_LSA_MIN_SIZE +
993 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
994
995 if (l->m[0].type == LSA_LINK_TYPE_STUB)
Paul Jakmab3bc68e2008-09-04 13:52:07 +0100996 ospf_intra_add_stub (rt, l, v, area, parent_is_root);
paul718e3742002-12-13 20:15:29 +0000997 }
998 }
999
gdt630e4802004-08-31 17:28:41 +00001000 ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1, 1);
paul718e3742002-12-13 20:15:29 +00001001
pauleb3da6d2005-10-18 04:20:33 +00001002 for (ALL_LIST_ELEMENTS (v->children, cnode, cnnode, child))
paul718e3742002-12-13 20:15:29 +00001003 {
paul718e3742002-12-13 20:15:29 +00001004 if (CHECK_FLAG (child->flags, OSPF_VERTEX_PROCESSED))
paul0c0f9cd2003-06-06 23:27:04 +00001005 continue;
Paul Jakmab3bc68e2008-09-04 13:52:07 +01001006
1007 /* the first level of routers connected to the root
1008 * should have 'parent_is_root' set, including those
1009 * connected via a network vertex.
1010 */
1011 if (area->spf == v)
1012 parent_is_root = 1;
1013 else if (v->type == OSPF_VERTEX_ROUTER)
1014 parent_is_root = 0;
1015
1016 ospf_spf_process_stubs (area, child, rt, parent_is_root);
paul718e3742002-12-13 20:15:29 +00001017
1018 SET_FLAG (child->flags, OSPF_VERTEX_PROCESSED);
1019 }
1020}
1021
1022void
1023ospf_rtrs_free (struct route_table *rtrs)
1024{
1025 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001026 struct list *or_list;
paul1eb8ef22005-04-07 07:30:20 +00001027 struct ospf_route *or;
1028 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001029
1030 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001031 zlog_debug ("Route: Router Routing Table free");
paul718e3742002-12-13 20:15:29 +00001032
1033 for (rn = route_top (rtrs); rn; rn = route_next (rn))
1034 if ((or_list = rn->info) != NULL)
1035 {
paul1eb8ef22005-04-07 07:30:20 +00001036 for (ALL_LIST_ELEMENTS (or_list, node, nnode, or))
1037 ospf_route_free (or);
paul718e3742002-12-13 20:15:29 +00001038
paul0c0f9cd2003-06-06 23:27:04 +00001039 list_delete (or_list);
paul718e3742002-12-13 20:15:29 +00001040
paul0c0f9cd2003-06-06 23:27:04 +00001041 /* Unlock the node. */
1042 rn->info = NULL;
1043 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001044 }
1045 route_table_finish (rtrs);
1046}
1047
paul4dadc292005-05-06 21:37:42 +00001048static void
paul718e3742002-12-13 20:15:29 +00001049ospf_rtrs_print (struct route_table *rtrs)
1050{
1051 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001052 struct list *or_list;
1053 struct listnode *ln;
1054 struct listnode *pnode;
paul718e3742002-12-13 20:15:29 +00001055 struct ospf_route *or;
1056 struct ospf_path *path;
1057 char buf1[BUFSIZ];
1058 char buf2[BUFSIZ];
1059
1060 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001061 zlog_debug ("ospf_rtrs_print() start");
paul718e3742002-12-13 20:15:29 +00001062
1063 for (rn = route_top (rtrs); rn; rn = route_next (rn))
1064 if ((or_list = rn->info) != NULL)
paul1eb8ef22005-04-07 07:30:20 +00001065 for (ALL_LIST_ELEMENTS_RO (or_list, ln, or))
paul718e3742002-12-13 20:15:29 +00001066 {
paul718e3742002-12-13 20:15:29 +00001067 switch (or->path_type)
1068 {
1069 case OSPF_PATH_INTRA_AREA:
paul0c0f9cd2003-06-06 23:27:04 +00001070 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001071 zlog_debug ("%s [%d] area: %s",
paul0c0f9cd2003-06-06 23:27:04 +00001072 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1073 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1074 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +00001075 break;
1076 case OSPF_PATH_INTER_AREA:
paul0c0f9cd2003-06-06 23:27:04 +00001077 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001078 zlog_debug ("%s IA [%d] area: %s",
paul0c0f9cd2003-06-06 23:27:04 +00001079 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1080 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1081 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +00001082 break;
1083 default:
1084 break;
1085 }
1086
paul1eb8ef22005-04-07 07:30:20 +00001087 for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path))
paul718e3742002-12-13 20:15:29 +00001088 {
paul718e3742002-12-13 20:15:29 +00001089 if (path->nexthop.s_addr == 0)
paul0c0f9cd2003-06-06 23:27:04 +00001090 {
1091 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001092 zlog_debug (" directly attached to %s\r\n",
Joakim Tjernlunda8ba8472009-07-27 12:42:34 +02001093 ifindex2ifname (path->ifindex));
paul0c0f9cd2003-06-06 23:27:04 +00001094 }
1095 else
1096 {
1097 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001098 zlog_debug (" via %s, %s\r\n",
Joakim Tjernlunda8ba8472009-07-27 12:42:34 +02001099 inet_ntoa (path->nexthop),
1100 ifindex2ifname (path->ifindex));
paul0c0f9cd2003-06-06 23:27:04 +00001101 }
paul718e3742002-12-13 20:15:29 +00001102 }
1103 }
1104
ajs2a42e282004-12-08 18:43:03 +00001105 zlog_debug ("ospf_rtrs_print() end");
paul718e3742002-12-13 20:15:29 +00001106}
1107
1108/* Calculating the shortest-path tree for an area. */
paul4dadc292005-05-06 21:37:42 +00001109static void
paul0c0f9cd2003-06-06 23:27:04 +00001110ospf_spf_calculate (struct ospf_area *area, struct route_table *new_table,
paul718e3742002-12-13 20:15:29 +00001111 struct route_table *new_rtrs)
1112{
hasso462f20d2005-02-23 11:29:02 +00001113 struct pqueue *candidate;
paul718e3742002-12-13 20:15:29 +00001114 struct vertex *v;
pauleb3da6d2005-10-18 04:20:33 +00001115
paul718e3742002-12-13 20:15:29 +00001116 if (IS_DEBUG_OSPF_EVENT)
1117 {
ajs2a42e282004-12-08 18:43:03 +00001118 zlog_debug ("ospf_spf_calculate: Start");
1119 zlog_debug ("ospf_spf_calculate: running Dijkstra for area %s",
paul0c0f9cd2003-06-06 23:27:04 +00001120 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001121 }
1122
1123 /* Check router-lsa-self. If self-router-lsa is not yet allocated,
1124 return this area's calculation. */
paul0c0f9cd2003-06-06 23:27:04 +00001125 if (!area->router_lsa_self)
paul718e3742002-12-13 20:15:29 +00001126 {
1127 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001128 zlog_debug ("ospf_spf_calculate: "
paul0c0f9cd2003-06-06 23:27:04 +00001129 "Skip area %s's calculation due to empty router_lsa_self",
1130 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001131 return;
1132 }
1133
1134 /* RFC2328 16.1. (1). */
paul0c0f9cd2003-06-06 23:27:04 +00001135 /* Initialize the algorithm's data structures. */
hasso462f20d2005-02-23 11:29:02 +00001136
1137 /* This function scans all the LSA database and set the stat field to
1138 * LSA_SPF_NOT_EXPLORED. */
1139 ospf_lsdb_clean_stat (area->lsdb);
1140 /* Create a new heap for the candidates. */
1141 candidate = pqueue_create();
1142 candidate->cmp = cmp;
1143 candidate->update = update_stat;
paul718e3742002-12-13 20:15:29 +00001144
1145 /* Initialize the shortest-path tree to only the root (which is the
1146 router doing the calculation). */
1147 ospf_spf_init (area);
1148 v = area->spf;
hasso462f20d2005-02-23 11:29:02 +00001149 /* Set LSA position to LSA_SPF_IN_SPFTREE. This vertex is the root of the
1150 * spanning tree. */
1151 *(v->stat) = LSA_SPF_IN_SPFTREE;
paul718e3742002-12-13 20:15:29 +00001152
1153 /* Set Area A's TransitCapability to FALSE. */
1154 area->transit = OSPF_TRANSIT_FALSE;
1155 area->shortcut_capability = 1;
pauleb3da6d2005-10-18 04:20:33 +00001156
paul718e3742002-12-13 20:15:29 +00001157 for (;;)
1158 {
1159 /* RFC2328 16.1. (2). */
hasso462f20d2005-02-23 11:29:02 +00001160 ospf_spf_next (v, area, candidate);
paul718e3742002-12-13 20:15:29 +00001161
1162 /* RFC2328 16.1. (3). */
1163 /* If at this step the candidate list is empty, the shortest-
1164 path tree (of transit vertices) has been completely built and
1165 this stage of the procedure terminates. */
hasso462f20d2005-02-23 11:29:02 +00001166 if (candidate->size == 0)
paul718e3742002-12-13 20:15:29 +00001167 break;
1168
1169 /* Otherwise, choose the vertex belonging to the candidate list
1170 that is closest to the root, and add it to the shortest-path
1171 tree (removing it from the candidate list in the
paul0c0f9cd2003-06-06 23:27:04 +00001172 process). */
hasso462f20d2005-02-23 11:29:02 +00001173 /* Extract from the candidates the node with the lower key. */
1174 v = (struct vertex *) pqueue_dequeue (candidate);
1175 /* Update stat field in vertex. */
1176 *(v->stat) = LSA_SPF_IN_SPFTREE;
pauleb3da6d2005-10-18 04:20:33 +00001177
paul718e3742002-12-13 20:15:29 +00001178 ospf_vertex_add_parent (v);
1179
paul718e3742002-12-13 20:15:29 +00001180 /* RFC2328 16.1. (4). */
1181 if (v->type == OSPF_VERTEX_ROUTER)
1182 ospf_intra_add_router (new_rtrs, v, area);
paul0c0f9cd2003-06-06 23:27:04 +00001183 else
paul718e3742002-12-13 20:15:29 +00001184 ospf_intra_add_transit (new_table, v, area);
1185
1186 /* RFC2328 16.1. (5). */
1187 /* Iterate the algorithm by returning to Step 2. */
gdt630e4802004-08-31 17:28:41 +00001188
1189 } /* end loop until no more candidate vertices */
paul718e3742002-12-13 20:15:29 +00001190
1191 if (IS_DEBUG_OSPF_EVENT)
1192 {
1193 ospf_spf_dump (area->spf, 0);
1194 ospf_route_table_dump (new_table);
1195 }
1196
1197 /* Second stage of SPF calculation procedure's */
Paul Jakmab3bc68e2008-09-04 13:52:07 +01001198 ospf_spf_process_stubs (area, area->spf, new_table, 0);
paul718e3742002-12-13 20:15:29 +00001199
pauleb3da6d2005-10-18 04:20:33 +00001200 /* Free candidate queue. */
hasso462f20d2005-02-23 11:29:02 +00001201 pqueue_delete (candidate);
pauleb3da6d2005-10-18 04:20:33 +00001202
1203 ospf_vertex_dump (__func__, area->spf, 0, 1);
1204 /* Free nexthop information, canonical versions of which are attached
1205 * the first level of router vertices attached to the root vertex, see
1206 * ospf_nexthop_calculation.
1207 */
1208 ospf_canonical_nexthops_free (area->spf);
1209
Paul Jakma9c27ef92006-05-04 07:32:57 +00001210 /* Free SPF vertices, but not the list. List has ospf_vertex_free
1211 * as deconstructor.
1212 */
1213 list_delete_all_node (&vertex_list);
pauleb3da6d2005-10-18 04:20:33 +00001214
paul718e3742002-12-13 20:15:29 +00001215 /* Increment SPF Calculation Counter. */
1216 area->spf_calculation++;
1217
Paul Jakma2518efd2006-08-27 06:49:29 +00001218 quagga_gettime (QUAGGA_CLK_MONOTONIC, &area->ospf->ts_spf);
paul718e3742002-12-13 20:15:29 +00001219
1220 if (IS_DEBUG_OSPF_EVENT)
Paul Jakma9c27ef92006-05-04 07:32:57 +00001221 zlog_debug ("ospf_spf_calculate: Stop. %ld vertices",
1222 mtype_stats_alloc(MTYPE_OSPF_VERTEX));
paul718e3742002-12-13 20:15:29 +00001223}
1224
1225/* Timer for SPF calculation. */
paul4dadc292005-05-06 21:37:42 +00001226static int
paul68980082003-03-25 05:07:42 +00001227ospf_spf_calculate_timer (struct thread *thread)
paul718e3742002-12-13 20:15:29 +00001228{
paul68980082003-03-25 05:07:42 +00001229 struct ospf *ospf = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +00001230 struct route_table *new_table, *new_rtrs;
paul1eb8ef22005-04-07 07:30:20 +00001231 struct ospf_area *area;
1232 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001233
1234 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001235 zlog_debug ("SPF: Timer (SPF calculation expire)");
paul0c0f9cd2003-06-06 23:27:04 +00001236
paul718e3742002-12-13 20:15:29 +00001237 ospf->t_spf_calc = NULL;
1238
1239 /* Allocate new table tree. */
1240 new_table = route_table_init ();
paul0c0f9cd2003-06-06 23:27:04 +00001241 new_rtrs = route_table_init ();
paul718e3742002-12-13 20:15:29 +00001242
paul68980082003-03-25 05:07:42 +00001243 ospf_vl_unapprove (ospf);
paul718e3742002-12-13 20:15:29 +00001244
1245 /* Calculate SPF for each area. */
paul1eb8ef22005-04-07 07:30:20 +00001246 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
Paul Jakma9c27ef92006-05-04 07:32:57 +00001247 {
1248 /* Do backbone last, so as to first discover intra-area paths
1249 * for any back-bone virtual-links
1250 */
1251 if (ospf->backbone && ospf->backbone == area)
1252 continue;
1253
1254 ospf_spf_calculate (area, new_table, new_rtrs);
1255 }
1256
1257 /* SPF for backbone, if required */
1258 if (ospf->backbone)
1259 ospf_spf_calculate (ospf->backbone, new_table, new_rtrs);
1260
paul68980082003-03-25 05:07:42 +00001261 ospf_vl_shut_unapproved (ospf);
paul718e3742002-12-13 20:15:29 +00001262
paul68980082003-03-25 05:07:42 +00001263 ospf_ia_routing (ospf, new_table, new_rtrs);
paul718e3742002-12-13 20:15:29 +00001264
1265 ospf_prune_unreachable_networks (new_table);
1266 ospf_prune_unreachable_routers (new_rtrs);
1267
1268 /* AS-external-LSA calculation should not be performed here. */
1269
1270 /* If new Router Route is installed,
1271 then schedule re-calculate External routes. */
1272 if (1)
paul68980082003-03-25 05:07:42 +00001273 ospf_ase_calculate_schedule (ospf);
paul718e3742002-12-13 20:15:29 +00001274
paul68980082003-03-25 05:07:42 +00001275 ospf_ase_calculate_timer_add (ospf);
paul718e3742002-12-13 20:15:29 +00001276
1277 /* Update routing table. */
paul68980082003-03-25 05:07:42 +00001278 ospf_route_install (ospf, new_table);
paul718e3742002-12-13 20:15:29 +00001279
1280 /* Update ABR/ASBR routing table */
paul68980082003-03-25 05:07:42 +00001281 if (ospf->old_rtrs)
paul718e3742002-12-13 20:15:29 +00001282 {
1283 /* old_rtrs's node holds linked list of ospf_route. --kunihiro. */
paul68980082003-03-25 05:07:42 +00001284 /* ospf_route_delete (ospf->old_rtrs); */
1285 ospf_rtrs_free (ospf->old_rtrs);
paul718e3742002-12-13 20:15:29 +00001286 }
1287
paul68980082003-03-25 05:07:42 +00001288 ospf->old_rtrs = ospf->new_rtrs;
1289 ospf->new_rtrs = new_rtrs;
paul718e3742002-12-13 20:15:29 +00001290
paul0c0f9cd2003-06-06 23:27:04 +00001291 if (IS_OSPF_ABR (ospf))
paul68980082003-03-25 05:07:42 +00001292 ospf_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001293
1294 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001295 zlog_debug ("SPF: calculation complete");
paul718e3742002-12-13 20:15:29 +00001296
1297 return 0;
1298}
1299
1300/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
1301 set timer for SPF calc. */
1302void
paul68980082003-03-25 05:07:42 +00001303ospf_spf_calculate_schedule (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00001304{
pauld24f6e22005-10-21 09:23:12 +00001305 unsigned long delay, elapsed, ht;
1306 struct timeval result;
paul718e3742002-12-13 20:15:29 +00001307
1308 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001309 zlog_debug ("SPF: calculation timer scheduled");
paul718e3742002-12-13 20:15:29 +00001310
1311 /* OSPF instance does not exist. */
paul68980082003-03-25 05:07:42 +00001312 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001313 return;
pauld24f6e22005-10-21 09:23:12 +00001314
paul718e3742002-12-13 20:15:29 +00001315 /* SPF calculation timer is already scheduled. */
paul68980082003-03-25 05:07:42 +00001316 if (ospf->t_spf_calc)
paul718e3742002-12-13 20:15:29 +00001317 {
1318 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001319 zlog_debug ("SPF: calculation timer is already scheduled: %p",
paul0c0f9cd2003-06-06 23:27:04 +00001320 ospf->t_spf_calc);
paul718e3742002-12-13 20:15:29 +00001321 return;
1322 }
pauld24f6e22005-10-21 09:23:12 +00001323
1324 /* XXX Monotic timers: we only care about relative time here. */
Paul Jakma2518efd2006-08-27 06:49:29 +00001325 result = tv_sub (recent_relative_time (), ospf->ts_spf);
pauld24f6e22005-10-21 09:23:12 +00001326
1327 elapsed = (result.tv_sec * 1000) + (result.tv_usec / 1000);
1328 ht = ospf->spf_holdtime * ospf->spf_hold_multiplier;
1329
1330 if (ht > ospf->spf_max_holdtime)
1331 ht = ospf->spf_max_holdtime;
1332
paul718e3742002-12-13 20:15:29 +00001333 /* Get SPF calculation delay time. */
pauld24f6e22005-10-21 09:23:12 +00001334 if (elapsed < ht)
paul718e3742002-12-13 20:15:29 +00001335 {
pauld24f6e22005-10-21 09:23:12 +00001336 /* Got an event within the hold time of last SPF. We need to
1337 * increase the hold_multiplier, if it's not already at/past
1338 * maximum value, and wasn't already increased..
1339 */
1340 if (ht < ospf->spf_max_holdtime)
1341 ospf->spf_hold_multiplier++;
1342
1343 /* always honour the SPF initial delay */
1344 if ( (ht - elapsed) < ospf->spf_delay)
paul0c0f9cd2003-06-06 23:27:04 +00001345 delay = ospf->spf_delay;
paul718e3742002-12-13 20:15:29 +00001346 else
pauld24f6e22005-10-21 09:23:12 +00001347 delay = ht - elapsed;
paul718e3742002-12-13 20:15:29 +00001348 }
1349 else
pauld24f6e22005-10-21 09:23:12 +00001350 {
1351 /* Event is past required hold-time of last SPF */
1352 delay = ospf->spf_delay;
1353 ospf->spf_hold_multiplier = 1;
1354 }
1355
paul718e3742002-12-13 20:15:29 +00001356 if (IS_DEBUG_OSPF_EVENT)
pauld24f6e22005-10-21 09:23:12 +00001357 zlog_debug ("SPF: calculation timer delay = %ld", delay);
1358
paul68980082003-03-25 05:07:42 +00001359 ospf->t_spf_calc =
pauld24f6e22005-10-21 09:23:12 +00001360 thread_add_timer_msec (master, ospf_spf_calculate_timer, ospf, delay);
paul718e3742002-12-13 20:15:29 +00001361}