blob: f4adc114dbcda2d1836182e43fbf46b0cccea0e8 [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;
175 new->distance = 0;
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);
288
289 area->spf = v;
290
291 /* Reset ABR and ASBR router counts. */
292 area->abr_count = 0;
293 area->asbr_count = 0;
294}
295
pauld355bfa2004-04-08 07:43:45 +0000296/* return index of link back to V from W, or -1 if no link found */
paul4dadc292005-05-06 21:37:42 +0000297static int
paul718e3742002-12-13 20:15:29 +0000298ospf_lsa_has_link (struct lsa_header *w, struct lsa_header *v)
299{
hassoeb1ce602004-10-08 08:17:22 +0000300 unsigned int i, length;
paul718e3742002-12-13 20:15:29 +0000301 struct router_lsa *rl;
302 struct network_lsa *nl;
303
304 /* In case of W is Network LSA. */
305 if (w->type == OSPF_NETWORK_LSA)
306 {
307 if (v->type == OSPF_NETWORK_LSA)
pauld355bfa2004-04-08 07:43:45 +0000308 return -1;
paul718e3742002-12-13 20:15:29 +0000309
310 nl = (struct network_lsa *) w;
311 length = (ntohs (w->length) - OSPF_LSA_HEADER_SIZE - 4) / 4;
paul0c0f9cd2003-06-06 23:27:04 +0000312
paul718e3742002-12-13 20:15:29 +0000313 for (i = 0; i < length; i++)
314 if (IPV4_ADDR_SAME (&nl->routers[i], &v->id))
pauld355bfa2004-04-08 07:43:45 +0000315 return i;
316 return -1;
paul718e3742002-12-13 20:15:29 +0000317 }
318
319 /* In case of W is Router LSA. */
320 if (w->type == OSPF_ROUTER_LSA)
321 {
322 rl = (struct router_lsa *) w;
323
324 length = ntohs (w->length);
325
326 for (i = 0;
paul0c0f9cd2003-06-06 23:27:04 +0000327 i < ntohs (rl->links) && length >= sizeof (struct router_lsa);
328 i++, length -= 12)
paul718e3742002-12-13 20:15:29 +0000329 {
330 switch (rl->link[i].type)
331 {
332 case LSA_LINK_TYPE_POINTOPOINT:
333 case LSA_LINK_TYPE_VIRTUALLINK:
334 /* Router LSA ID. */
335 if (v->type == OSPF_ROUTER_LSA &&
336 IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
337 {
pauld355bfa2004-04-08 07:43:45 +0000338 return i;
paul718e3742002-12-13 20:15:29 +0000339 }
340 break;
341 case LSA_LINK_TYPE_TRANSIT:
342 /* Network LSA ID. */
343 if (v->type == OSPF_NETWORK_LSA &&
344 IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
345 {
pauld355bfa2004-04-08 07:43:45 +0000346 return i;
paul0c0f9cd2003-06-06 23:27:04 +0000347 }
paul718e3742002-12-13 20:15:29 +0000348 break;
349 case LSA_LINK_TYPE_STUB:
pauleb3da6d2005-10-18 04:20:33 +0000350 /* Stub can't lead anywhere, carry on */
paul718e3742002-12-13 20:15:29 +0000351 continue;
352 default:
353 break;
354 }
355 }
356 }
pauld355bfa2004-04-08 07:43:45 +0000357 return -1;
paul718e3742002-12-13 20:15:29 +0000358}
359
paul718e3742002-12-13 20:15:29 +0000360#define ROUTER_LSA_MIN_SIZE 12
361#define ROUTER_LSA_TOS_SIZE 4
362
gdt630e4802004-08-31 17:28:41 +0000363/* Find the next link after prev_link from v to w. If prev_link is
364 * NULL, return the first link from v to w. Ignore stub and virtual links;
365 * these link types will never be returned.
366 */
paul4dadc292005-05-06 21:37:42 +0000367static struct router_lsa_link *
paul718e3742002-12-13 20:15:29 +0000368ospf_get_next_link (struct vertex *v, struct vertex *w,
paul0c0f9cd2003-06-06 23:27:04 +0000369 struct router_lsa_link *prev_link)
paul718e3742002-12-13 20:15:29 +0000370{
371 u_char *p;
372 u_char *lim;
373 struct router_lsa_link *l;
374
375 if (prev_link == NULL)
gdt630e4802004-08-31 17:28:41 +0000376 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +0000377 else
378 {
paul0c0f9cd2003-06-06 23:27:04 +0000379 p = (u_char *) prev_link;
paul718e3742002-12-13 20:15:29 +0000380 p += (ROUTER_LSA_MIN_SIZE +
381 (prev_link->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
382 }
paul0c0f9cd2003-06-06 23:27:04 +0000383
paul718e3742002-12-13 20:15:29 +0000384 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
385
386 while (p < lim)
387 {
388 l = (struct router_lsa_link *) p;
389
paul0c0f9cd2003-06-06 23:27:04 +0000390 p += (ROUTER_LSA_MIN_SIZE + (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
paul718e3742002-12-13 20:15:29 +0000391
392 if (l->m[0].type == LSA_LINK_TYPE_STUB)
393 continue;
394
395 /* Defer NH calculation via VLs until summaries from
396 transit areas area confidered */
397
398 if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK)
paul0c0f9cd2003-06-06 23:27:04 +0000399 continue;
paul718e3742002-12-13 20:15:29 +0000400
401 if (IPV4_ADDR_SAME (&l->link_id, &w->id))
paul0c0f9cd2003-06-06 23:27:04 +0000402 return l;
paul718e3742002-12-13 20:15:29 +0000403 }
404
405 return NULL;
406}
407
pauleb3da6d2005-10-18 04:20:33 +0000408static void
409ospf_spf_flush_parents (struct vertex *w)
410{
411 struct vertex_parent *vp;
412 struct listnode *ln, *nn;
413
414 /* delete the existing nexthops */
415 for (ALL_LIST_ELEMENTS (w->parents, ln, nn, vp))
416 {
417 list_delete_node (w->parents, ln);
418 vertex_parent_free (vp);
419 }
420}
421
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000422/*
423 * Consider supplied next-hop for inclusion to the supplied list of
424 * equal-cost next-hops, adjust list as neccessary.
425 */
426static void
427ospf_spf_add_parent (struct vertex *v, struct vertex *w,
428 struct vertex_nexthop *newhop,
429 struct router_lsa_link *l)
430{
431 struct vertex_parent *vp;
432 unsigned int new_distance;
433
434 /* we must have a newhop.. */
435 assert (v && w && l && newhop);
436
437 new_distance = v->distance + ntohs (l->m[0].metric);
438
439 /* We shouldn't get here unless callers have determined V(l)->W is
440 * shortest / equal-shortest path.
441 */
442 assert (new_distance <= w->distance);
443
444 /* Adding parent for a new, better path: flush existing parents from W. */
445 if (new_distance < w->distance)
446 {
447 ospf_spf_flush_parents (w);
448 w->distance = new_distance;
449 }
450
451 /* new parent is <= existing parents, add it to parent list */
452 vp = vertex_parent_new (v, ospf_lsa_has_link (w->lsa, v->lsa), newhop);
453 listnode_add (w->parents, vp);
454
455 return;
456}
457
gdt630e4802004-08-31 17:28:41 +0000458/* 16.1.1. Calculate nexthop from root through V (parent) to
459 * vertex W (destination).
pauleb3da6d2005-10-18 04:20:33 +0000460 *
461 * The link must be supplied if V is the root vertex. In all other cases
462 * it may be NULL.
gdt630e4802004-08-31 17:28:41 +0000463 */
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000464static unsigned int
pauleb3da6d2005-10-18 04:20:33 +0000465ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v,
466 struct vertex *w, struct router_lsa_link *l)
paul718e3742002-12-13 20:15:29 +0000467{
paul1eb8ef22005-04-07 07:30:20 +0000468 struct listnode *node, *nnode;
pauleb3da6d2005-10-18 04:20:33 +0000469 struct vertex_nexthop *nh;
470 struct vertex_parent *vp;
paul718e3742002-12-13 20:15:29 +0000471 struct ospf_interface *oi = NULL;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000472 unsigned int added = 0;
paul0c0f9cd2003-06-06 23:27:04 +0000473
paul718e3742002-12-13 20:15:29 +0000474 if (IS_DEBUG_OSPF_EVENT)
gdt630e4802004-08-31 17:28:41 +0000475 {
ajs2a42e282004-12-08 18:43:03 +0000476 zlog_debug ("ospf_nexthop_calculation(): Start");
gdt630e4802004-08-31 17:28:41 +0000477 ospf_vertex_dump("V (parent):", v, 1, 1);
478 ospf_vertex_dump("W (dest) :", w, 1, 1);
479 }
paul718e3742002-12-13 20:15:29 +0000480
paul718e3742002-12-13 20:15:29 +0000481 if (v == area->spf)
Paul Jakma9c27ef92006-05-04 07:32:57 +0000482 {
gdt630e4802004-08-31 17:28:41 +0000483 /* 16.1.1 para 4. In the first case, the parent vertex (V) is the
484 root (the calculating router itself). This means that the
485 destination is either a directly connected network or directly
486 connected router. The outgoing interface in this case is simply
487 the OSPF interface connecting to the destination network/router.
488 */
489
paul718e3742002-12-13 20:15:29 +0000490 if (w->type == OSPF_VERTEX_ROUTER)
paul0c0f9cd2003-06-06 23:27:04 +0000491 {
pauleb3da6d2005-10-18 04:20:33 +0000492 /* l is a link from v to w
493 * l2 will be link from w to v
494 */
495 struct router_lsa_link *l2 = NULL;
496
497 /* we *must* be supplied with the link data */
498 assert (l != NULL);
499
500 if (IS_DEBUG_OSPF_EVENT)
paul0c0f9cd2003-06-06 23:27:04 +0000501 {
pauleb3da6d2005-10-18 04:20:33 +0000502 char buf1[BUFSIZ];
503 char buf2[BUFSIZ];
504
505 zlog_debug("ospf_nexthop_calculation(): considering link "
506 "type %d link_id %s link_data %s",
507 l->m[0].type,
508 inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ),
509 inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ));
510 }
paul0c0f9cd2003-06-06 23:27:04 +0000511
pauleb3da6d2005-10-18 04:20:33 +0000512 if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT)
513 {
514 /* If the destination is a router which connects to
515 the calculating router via a Point-to-MultiPoint
516 network, the destination's next hop IP address(es)
517 can be determined by examining the destination's
518 router-LSA: each link pointing back to the
519 calculating router and having a Link Data field
520 belonging to the Point-to-MultiPoint network
521 provides an IP address of the next hop router.
gdt630e4802004-08-31 17:28:41 +0000522
pauleb3da6d2005-10-18 04:20:33 +0000523 At this point l is a link from V to W, and V is the
524 root ("us"). Find the local interface associated
525 with l (its address is in l->link_data). If it
526 is a point-to-multipoint interface, then look through
527 the links in the opposite direction (W to V). If
528 any of them have an address that lands within the
529 subnet declared by the PtMP link, then that link
530 is a constituent of the PtMP link, and its address is
531 a nexthop address for V.
532 */
533 oi = ospf_if_is_configured (area->ospf, &l->link_data);
534 if (oi && oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
paul0c0f9cd2003-06-06 23:27:04 +0000535 {
pauleb3da6d2005-10-18 04:20:33 +0000536 struct prefix_ipv4 la;
gdt630e4802004-08-31 17:28:41 +0000537
pauleb3da6d2005-10-18 04:20:33 +0000538 la.family = AF_INET;
539 la.prefixlen = oi->address->prefixlen;
540
541 /* V links to W on PtMP interface
542 - find the interface address on W */
543 while ((l2 = ospf_get_next_link (w, v, l2)))
paul0c0f9cd2003-06-06 23:27:04 +0000544 {
pauleb3da6d2005-10-18 04:20:33 +0000545 la.prefix = l2->link_data;
gdt630e4802004-08-31 17:28:41 +0000546
pauleb3da6d2005-10-18 04:20:33 +0000547 if (prefix_cmp ((struct prefix *) &la,
548 oi->address) == 0)
549 /* link_data is on our PtMP network */
550 break;
paul0c0f9cd2003-06-06 23:27:04 +0000551 }
pauleb3da6d2005-10-18 04:20:33 +0000552 } /* end l is on point-to-multipoint link */
553 else
554 {
555 /* l is a regular point-to-point link.
556 Look for a link from W to V.
557 */
558 while ((l2 = ospf_get_next_link (w, v, l2)))
paul0c0f9cd2003-06-06 23:27:04 +0000559 {
pauleb3da6d2005-10-18 04:20:33 +0000560 oi = ospf_if_is_configured (area->ospf,
561 &(l2->link_data));
562
563 if (oi == NULL)
564 continue;
565
566 if (!IPV4_ADDR_SAME (&oi->address->u.prefix4,
567 &l->link_data))
568 continue;
569
570 break;
paul0c0f9cd2003-06-06 23:27:04 +0000571 }
pauleb3da6d2005-10-18 04:20:33 +0000572 }
573
574 if (oi && l2)
575 {
576 /* found all necessary info to build nexthop */
577 nh = vertex_nexthop_new ();
578 nh->oi = oi;
579 nh->router = l2->link_data;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000580 ospf_spf_add_parent (v, w, nh, l);
581 return 1;
pauleb3da6d2005-10-18 04:20:33 +0000582 }
583 else
Paul Jakma9c27ef92006-05-04 07:32:57 +0000584 zlog_info("ospf_nexthop_calculation(): "
585 "could not determine nexthop for link");
pauleb3da6d2005-10-18 04:20:33 +0000586 } /* end point-to-point link from V to W */
Paul Jakma9c27ef92006-05-04 07:32:57 +0000587 else if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK)
588 {
589 struct ospf_vl_data *vl_data;
590
591 /* VLink implementation limitations:
592 * a) vl_data can only reference one nexthop, so no ECMP
593 * to backbone through VLinks. Though transit-area
594 * summaries may be considered, and those can be ECMP.
595 * b) We can only use /one/ VLink, even if multiple ones
596 * exist this router through multiple transit-areas.
597 */
598 vl_data = ospf_vl_lookup (area->ospf, NULL, l->link_id);
599
600 if (vl_data
601 && CHECK_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED))
602 {
603 nh = vertex_nexthop_new ();
604 nh->oi = vl_data->nexthop.oi;
605 nh->router = vl_data->nexthop.router;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000606 ospf_spf_add_parent (v, w, nh, l);
607 return 1;
Paul Jakma9c27ef92006-05-04 07:32:57 +0000608 }
609 else
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000610 zlog_info("ospf_nexthop_calculation(): "
611 "vl_data for VL link not found");
Paul Jakma9c27ef92006-05-04 07:32:57 +0000612 } /* end virtual-link from V to W */
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000613 return 0;
gdt630e4802004-08-31 17:28:41 +0000614 } /* end W is a Router vertex */
paul718e3742002-12-13 20:15:29 +0000615 else
paul0c0f9cd2003-06-06 23:27:04 +0000616 {
pauleb3da6d2005-10-18 04:20:33 +0000617 assert(w->type == OSPF_VERTEX_NETWORK);
618 oi = ospf_if_is_configured (area->ospf, &(l->link_data));
619 if (oi)
paul0c0f9cd2003-06-06 23:27:04 +0000620 {
pauleb3da6d2005-10-18 04:20:33 +0000621 nh = vertex_nexthop_new ();
622 nh->oi = oi;
623 nh->router.s_addr = 0;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000624 ospf_spf_add_parent (v, w, nh, l);
625 return 1;
paul0c0f9cd2003-06-06 23:27:04 +0000626 }
627 }
Paul Jakma9c27ef92006-05-04 07:32:57 +0000628 zlog_info("ospf_nexthop_calculation(): "
629 "Unknown attached link");
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000630 return 0;
gdt630e4802004-08-31 17:28:41 +0000631 } /* end V is the root */
gdt630e4802004-08-31 17:28:41 +0000632 /* Check if W's parent is a network connected to root. */
paul718e3742002-12-13 20:15:29 +0000633 else if (v->type == OSPF_VERTEX_NETWORK)
634 {
gdt630e4802004-08-31 17:28:41 +0000635 /* See if any of V's parents are the root. */
pauleb3da6d2005-10-18 04:20:33 +0000636 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
paul718e3742002-12-13 20:15:29 +0000637 {
pauleb3da6d2005-10-18 04:20:33 +0000638 if (vp->parent == area->spf) /* connects to root? */
gdt630e4802004-08-31 17:28:41 +0000639 {
640 /* 16.1.1 para 5. ...the parent vertex is a network that
641 * directly connects the calculating router to the destination
642 * router. The list of next hops is then determined by
643 * examining the destination's router-LSA...
644 */
645
646 assert(w->type == OSPF_VERTEX_ROUTER);
paul0c0f9cd2003-06-06 23:27:04 +0000647 while ((l = ospf_get_next_link (w, v, l)))
648 {
gdt630e4802004-08-31 17:28:41 +0000649 /* ...For each link in the router-LSA that points back to the
650 * parent network, the link's Link Data field provides the IP
651 * address of a next hop router. The outgoing interface to
652 * use can then be derived from the next hop IP address (or
653 * it can be inherited from the parent network).
654 */
pauleb3da6d2005-10-18 04:20:33 +0000655 nh = vertex_nexthop_new ();
656 nh->oi = vp->nexthop->oi;
657 nh->router = l->link_data;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000658 added = 1;
659 ospf_spf_add_parent (v, w, nh, l);
paul0c0f9cd2003-06-06 23:27:04 +0000660 }
paul0c0f9cd2003-06-06 23:27:04 +0000661 }
paul718e3742002-12-13 20:15:29 +0000662 }
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000663 return added;
paul718e3742002-12-13 20:15:29 +0000664 }
665
gdt630e4802004-08-31 17:28:41 +0000666 /* 16.1.1 para 4. If there is at least one intervening router in the
667 * current shortest path between the destination and the root, the
668 * destination simply inherits the set of next hops from the
669 * parent.
670 */
pauleb3da6d2005-10-18 04:20:33 +0000671 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000672 {
673 added = 1;
674 ospf_spf_add_parent (v, w, vp->nexthop, l);
675 }
Paul Jakma9c27ef92006-05-04 07:32:57 +0000676
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000677 return added;
paul718e3742002-12-13 20:15:29 +0000678}
679
gdt630e4802004-08-31 17:28:41 +0000680/* RFC2328 Section 16.1 (2).
681 * v is on the SPF tree. Examine the links in v's LSA. Update the list
682 * of candidates with any vertices not already on the list. If a lower-cost
683 * path is found to a vertex already on the candidate list, store the new cost.
684 */
paul4dadc292005-05-06 21:37:42 +0000685static void
paul718e3742002-12-13 20:15:29 +0000686ospf_spf_next (struct vertex *v, struct ospf_area *area,
hasso462f20d2005-02-23 11:29:02 +0000687 struct pqueue * candidate)
paul718e3742002-12-13 20:15:29 +0000688{
689 struct ospf_lsa *w_lsa = NULL;
paul718e3742002-12-13 20:15:29 +0000690 u_char *p;
691 u_char *lim;
692 struct router_lsa_link *l = NULL;
693 struct in_addr *r;
paul718e3742002-12-13 20:15:29 +0000694 int type = 0;
695
696 /* If this is a router-LSA, and bit V of the router-LSA (see Section
697 A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE. */
698 if (v->type == OSPF_VERTEX_ROUTER)
699 {
700 if (IS_ROUTER_LSA_VIRTUAL ((struct router_lsa *) v->lsa))
701 area->transit = OSPF_TRANSIT_TRUE;
702 }
703
704 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul0c0f9cd2003-06-06 23:27:04 +0000705 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
706
paul718e3742002-12-13 20:15:29 +0000707 while (p < lim)
708 {
pauleb3da6d2005-10-18 04:20:33 +0000709 struct vertex *w;
710 unsigned int distance;
pauld355bfa2004-04-08 07:43:45 +0000711
paul718e3742002-12-13 20:15:29 +0000712 /* In case of V is Router-LSA. */
713 if (v->lsa->type == OSPF_ROUTER_LSA)
714 {
715 l = (struct router_lsa_link *) p;
716
paul0c0f9cd2003-06-06 23:27:04 +0000717 p += (ROUTER_LSA_MIN_SIZE +
paul718e3742002-12-13 20:15:29 +0000718 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
719
720 /* (a) If this is a link to a stub network, examine the next
721 link in V's LSA. Links to stub networks will be
722 considered in the second stage of the shortest path
723 calculation. */
724 if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB)
725 continue;
726
727 /* (b) Otherwise, W is a transit vertex (router or transit
728 network). Look up the vertex W's LSA (router-LSA or
729 network-LSA) in Area A's link state database. */
730 switch (type)
731 {
732 case LSA_LINK_TYPE_POINTOPOINT:
733 case LSA_LINK_TYPE_VIRTUALLINK:
734 if (type == LSA_LINK_TYPE_VIRTUALLINK)
paul0c0f9cd2003-06-06 23:27:04 +0000735 {
736 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000737 zlog_debug ("looking up LSA through VL: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000738 inet_ntoa (l->link_id));
739 }
paul718e3742002-12-13 20:15:29 +0000740
741 w_lsa = ospf_lsa_lookup (area, OSPF_ROUTER_LSA, l->link_id,
742 l->link_id);
743 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000744 {
745 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000746 zlog_debug ("found Router LSA %s", inet_ntoa (l->link_id));
paul0c0f9cd2003-06-06 23:27:04 +0000747 }
paul718e3742002-12-13 20:15:29 +0000748 break;
749 case LSA_LINK_TYPE_TRANSIT:
paul0c0f9cd2003-06-06 23:27:04 +0000750 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000751 zlog_debug ("Looking up Network LSA, ID: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000752 inet_ntoa (l->link_id));
paul718e3742002-12-13 20:15:29 +0000753 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_NETWORK_LSA,
paul0c0f9cd2003-06-06 23:27:04 +0000754 l->link_id);
paul718e3742002-12-13 20:15:29 +0000755 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000756 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000757 zlog_debug ("found the LSA");
paul718e3742002-12-13 20:15:29 +0000758 break;
759 default:
paul0c0f9cd2003-06-06 23:27:04 +0000760 zlog_warn ("Invalid LSA link type %d", type);
paul718e3742002-12-13 20:15:29 +0000761 continue;
762 }
763 }
764 else
765 {
766 /* In case of V is Network-LSA. */
paul0c0f9cd2003-06-06 23:27:04 +0000767 r = (struct in_addr *) p;
paul718e3742002-12-13 20:15:29 +0000768 p += sizeof (struct in_addr);
769
770 /* Lookup the vertex W's LSA. */
771 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_ROUTER_LSA, *r);
772 }
773
774 /* (b cont.) If the LSA does not exist, or its LS age is equal
775 to MaxAge, or it does not have a link back to vertex V,
776 examine the next link in V's LSA.[23] */
777 if (w_lsa == NULL)
778 continue;
779
780 if (IS_LSA_MAXAGE (w_lsa))
781 continue;
782
pauleb3da6d2005-10-18 04:20:33 +0000783 if (ospf_lsa_has_link (w_lsa->data, v->lsa) < 0 )
paul718e3742002-12-13 20:15:29 +0000784 {
paul0c0f9cd2003-06-06 23:27:04 +0000785 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000786 zlog_debug ("The LSA doesn't have a link back");
paul718e3742002-12-13 20:15:29 +0000787 continue;
788 }
789
790 /* (c) If vertex W is already on the shortest-path tree, examine
791 the next link in the LSA. */
hasso462f20d2005-02-23 11:29:02 +0000792 if (w_lsa->stat == LSA_SPF_IN_SPFTREE)
793 {
794 if (IS_DEBUG_OSPF_EVENT)
795 zlog_debug ("The LSA is already in SPF");
796 continue;
797 }
paul718e3742002-12-13 20:15:29 +0000798
799 /* (d) Calculate the link state cost D of the resulting path
800 from the root to vertex W. D is equal to the sum of the link
801 state cost of the (already calculated) shortest path to
802 vertex V and the advertised cost of the link between vertices
803 V and W. If D is: */
804
paul718e3742002-12-13 20:15:29 +0000805 /* calculate link cost D. */
806 if (v->lsa->type == OSPF_ROUTER_LSA)
pauleb3da6d2005-10-18 04:20:33 +0000807 distance = v->distance + ntohs (l->m[0].metric);
gdt630e4802004-08-31 17:28:41 +0000808 else /* v is not a Router-LSA */
pauleb3da6d2005-10-18 04:20:33 +0000809 distance = v->distance;
paul718e3742002-12-13 20:15:29 +0000810
811 /* Is there already vertex W in candidate list? */
hasso462f20d2005-02-23 11:29:02 +0000812 if (w_lsa->stat == LSA_SPF_NOT_EXPLORED)
813 {
pauleb3da6d2005-10-18 04:20:33 +0000814 /* prepare vertex W. */
815 w = ospf_vertex_new (w_lsa);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000816 w->distance = distance;
pauleb3da6d2005-10-18 04:20:33 +0000817
hasso462f20d2005-02-23 11:29:02 +0000818 /* Calculate nexthop to W. */
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000819 if (ospf_nexthop_calculation (area, v, w, l))
820 pqueue_enqueue (w, candidate);
hasso462f20d2005-02-23 11:29:02 +0000821 }
822 else if (w_lsa->stat >= 0)
823 {
824 /* Get the vertex from candidates. */
pauleb3da6d2005-10-18 04:20:33 +0000825 w = candidate->array[w_lsa->stat];
paul718e3742002-12-13 20:15:29 +0000826
hasso462f20d2005-02-23 11:29:02 +0000827 /* if D is greater than. */
pauleb3da6d2005-10-18 04:20:33 +0000828 if (w->distance < distance)
paul718e3742002-12-13 20:15:29 +0000829 {
paul718e3742002-12-13 20:15:29 +0000830 continue;
831 }
hasso462f20d2005-02-23 11:29:02 +0000832 /* equal to. */
pauleb3da6d2005-10-18 04:20:33 +0000833 else if (w->distance == distance)
paul718e3742002-12-13 20:15:29 +0000834 {
pauleb3da6d2005-10-18 04:20:33 +0000835 /* Found an equal-cost path to W.
836 * Calculate nexthop of to W from V. */
837 ospf_nexthop_calculation (area, v, w, l);
paul718e3742002-12-13 20:15:29 +0000838 }
hasso462f20d2005-02-23 11:29:02 +0000839 /* less than. */
840 else
paul718e3742002-12-13 20:15:29 +0000841 {
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000842 /* Found a lower-cost path to W.
843 * nexthop_calculation is conditional, if it finds
844 * valid nexthop it will call spf_add_parents, which
845 * will flush the old parents
846 */
847 if (ospf_nexthop_calculation (area, v, w, l))
848 /* Decrease the key of the node in the heap,
849 * re-sort the heap. */
850 trickle_down (w_lsa->stat, candidate);
paul718e3742002-12-13 20:15:29 +0000851 }
gdt630e4802004-08-31 17:28:41 +0000852 } /* end W is already on the candidate list */
853 } /* end loop over the links in V's LSA */
paul718e3742002-12-13 20:15:29 +0000854}
855
paul4dadc292005-05-06 21:37:42 +0000856static void
paul718e3742002-12-13 20:15:29 +0000857ospf_spf_dump (struct vertex *v, int i)
858{
hasso52dc7ee2004-09-23 19:18:23 +0000859 struct listnode *cnode;
860 struct listnode *nnode;
pauleb3da6d2005-10-18 04:20:33 +0000861 struct vertex_parent *parent;
paul718e3742002-12-13 20:15:29 +0000862
863 if (v->type == OSPF_VERTEX_ROUTER)
864 {
865 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000866 zlog_debug ("SPF Result: %d [R] %s", i, inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000867 }
868 else
869 {
870 struct network_lsa *lsa = (struct network_lsa *) v->lsa;
871 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000872 zlog_debug ("SPF Result: %d [N] %s/%d", i, inet_ntoa (v->lsa->id),
paul0c0f9cd2003-06-06 23:27:04 +0000873 ip_masklen (lsa->mask));
gdt630e4802004-08-31 17:28:41 +0000874 }
paul718e3742002-12-13 20:15:29 +0000875
paul1eb8ef22005-04-07 07:30:20 +0000876 if (IS_DEBUG_OSPF_EVENT)
pauleb3da6d2005-10-18 04:20:33 +0000877 for (ALL_LIST_ELEMENTS_RO (v->parents, nnode, parent))
878 {
879 zlog_debug (" nexthop %p %s %s",
880 parent->nexthop,
881 inet_ntoa (parent->nexthop->router),
882 parent->nexthop->oi ? IF_NAME(parent->nexthop->oi)
883 : "NULL");
884 }
paul718e3742002-12-13 20:15:29 +0000885
886 i++;
887
pauleb3da6d2005-10-18 04:20:33 +0000888 for (ALL_LIST_ELEMENTS_RO (v->children, cnode, v))
paul1eb8ef22005-04-07 07:30:20 +0000889 ospf_spf_dump (v, i);
paul718e3742002-12-13 20:15:29 +0000890}
891
892/* Second stage of SPF calculation. */
paul4dadc292005-05-06 21:37:42 +0000893static void
paul0c0f9cd2003-06-06 23:27:04 +0000894ospf_spf_process_stubs (struct ospf_area *area, struct vertex *v,
paul718e3742002-12-13 20:15:29 +0000895 struct route_table *rt)
896{
paul1eb8ef22005-04-07 07:30:20 +0000897 struct listnode *cnode, *cnnode;
paul718e3742002-12-13 20:15:29 +0000898 struct vertex *child;
899
900 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000901 zlog_debug ("ospf_process_stub():processing stubs for area %s",
paul0c0f9cd2003-06-06 23:27:04 +0000902 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +0000903 if (v->type == OSPF_VERTEX_ROUTER)
904 {
905 u_char *p;
906 u_char *lim;
907 struct router_lsa_link *l;
908 struct router_lsa *rlsa;
909
paul0c0f9cd2003-06-06 23:27:04 +0000910 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000911 zlog_debug ("ospf_process_stubs():processing router LSA, id: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000912 inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000913 rlsa = (struct router_lsa *) v->lsa;
914
915
paul0c0f9cd2003-06-06 23:27:04 +0000916 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000917 zlog_debug ("ospf_process_stubs(): we have %d links to process",
paul0c0f9cd2003-06-06 23:27:04 +0000918 ntohs (rlsa->links));
gdt630e4802004-08-31 17:28:41 +0000919 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +0000920 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
921
922 while (p < lim)
923 {
924 l = (struct router_lsa_link *) p;
925
926 p += (ROUTER_LSA_MIN_SIZE +
927 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
928
929 if (l->m[0].type == LSA_LINK_TYPE_STUB)
930 ospf_intra_add_stub (rt, l, v, area);
931 }
932 }
933
gdt630e4802004-08-31 17:28:41 +0000934 ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1, 1);
paul718e3742002-12-13 20:15:29 +0000935
pauleb3da6d2005-10-18 04:20:33 +0000936 for (ALL_LIST_ELEMENTS (v->children, cnode, cnnode, child))
paul718e3742002-12-13 20:15:29 +0000937 {
paul718e3742002-12-13 20:15:29 +0000938 if (CHECK_FLAG (child->flags, OSPF_VERTEX_PROCESSED))
paul0c0f9cd2003-06-06 23:27:04 +0000939 continue;
paul718e3742002-12-13 20:15:29 +0000940
941 ospf_spf_process_stubs (area, child, rt);
942
943 SET_FLAG (child->flags, OSPF_VERTEX_PROCESSED);
944 }
945}
946
947void
948ospf_rtrs_free (struct route_table *rtrs)
949{
950 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +0000951 struct list *or_list;
paul1eb8ef22005-04-07 07:30:20 +0000952 struct ospf_route *or;
953 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000954
955 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000956 zlog_debug ("Route: Router Routing Table free");
paul718e3742002-12-13 20:15:29 +0000957
958 for (rn = route_top (rtrs); rn; rn = route_next (rn))
959 if ((or_list = rn->info) != NULL)
960 {
paul1eb8ef22005-04-07 07:30:20 +0000961 for (ALL_LIST_ELEMENTS (or_list, node, nnode, or))
962 ospf_route_free (or);
paul718e3742002-12-13 20:15:29 +0000963
paul0c0f9cd2003-06-06 23:27:04 +0000964 list_delete (or_list);
paul718e3742002-12-13 20:15:29 +0000965
paul0c0f9cd2003-06-06 23:27:04 +0000966 /* Unlock the node. */
967 rn->info = NULL;
968 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +0000969 }
970 route_table_finish (rtrs);
971}
972
paul4dadc292005-05-06 21:37:42 +0000973static void
paul718e3742002-12-13 20:15:29 +0000974ospf_rtrs_print (struct route_table *rtrs)
975{
976 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +0000977 struct list *or_list;
978 struct listnode *ln;
979 struct listnode *pnode;
paul718e3742002-12-13 20:15:29 +0000980 struct ospf_route *or;
981 struct ospf_path *path;
982 char buf1[BUFSIZ];
983 char buf2[BUFSIZ];
984
985 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000986 zlog_debug ("ospf_rtrs_print() start");
paul718e3742002-12-13 20:15:29 +0000987
988 for (rn = route_top (rtrs); rn; rn = route_next (rn))
989 if ((or_list = rn->info) != NULL)
paul1eb8ef22005-04-07 07:30:20 +0000990 for (ALL_LIST_ELEMENTS_RO (or_list, ln, or))
paul718e3742002-12-13 20:15:29 +0000991 {
paul718e3742002-12-13 20:15:29 +0000992 switch (or->path_type)
993 {
994 case OSPF_PATH_INTRA_AREA:
paul0c0f9cd2003-06-06 23:27:04 +0000995 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000996 zlog_debug ("%s [%d] area: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000997 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
998 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
999 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +00001000 break;
1001 case OSPF_PATH_INTER_AREA:
paul0c0f9cd2003-06-06 23:27:04 +00001002 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001003 zlog_debug ("%s IA [%d] area: %s",
paul0c0f9cd2003-06-06 23:27:04 +00001004 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1005 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1006 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +00001007 break;
1008 default:
1009 break;
1010 }
1011
paul1eb8ef22005-04-07 07:30:20 +00001012 for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path))
paul718e3742002-12-13 20:15:29 +00001013 {
paul718e3742002-12-13 20:15:29 +00001014 if (path->nexthop.s_addr == 0)
paul0c0f9cd2003-06-06 23:27:04 +00001015 {
1016 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001017 zlog_debug (" directly attached to %s\r\n",
paul0c0f9cd2003-06-06 23:27:04 +00001018 IF_NAME (path->oi));
1019 }
1020 else
1021 {
1022 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001023 zlog_debug (" via %s, %s\r\n",
paul0c0f9cd2003-06-06 23:27:04 +00001024 inet_ntoa (path->nexthop), IF_NAME (path->oi));
1025 }
paul718e3742002-12-13 20:15:29 +00001026 }
1027 }
1028
ajs2a42e282004-12-08 18:43:03 +00001029 zlog_debug ("ospf_rtrs_print() end");
paul718e3742002-12-13 20:15:29 +00001030}
1031
1032/* Calculating the shortest-path tree for an area. */
paul4dadc292005-05-06 21:37:42 +00001033static void
paul0c0f9cd2003-06-06 23:27:04 +00001034ospf_spf_calculate (struct ospf_area *area, struct route_table *new_table,
paul718e3742002-12-13 20:15:29 +00001035 struct route_table *new_rtrs)
1036{
hasso462f20d2005-02-23 11:29:02 +00001037 struct pqueue *candidate;
paul718e3742002-12-13 20:15:29 +00001038 struct vertex *v;
pauleb3da6d2005-10-18 04:20:33 +00001039
paul718e3742002-12-13 20:15:29 +00001040 if (IS_DEBUG_OSPF_EVENT)
1041 {
ajs2a42e282004-12-08 18:43:03 +00001042 zlog_debug ("ospf_spf_calculate: Start");
1043 zlog_debug ("ospf_spf_calculate: running Dijkstra for area %s",
paul0c0f9cd2003-06-06 23:27:04 +00001044 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001045 }
1046
1047 /* Check router-lsa-self. If self-router-lsa is not yet allocated,
1048 return this area's calculation. */
paul0c0f9cd2003-06-06 23:27:04 +00001049 if (!area->router_lsa_self)
paul718e3742002-12-13 20:15:29 +00001050 {
1051 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001052 zlog_debug ("ospf_spf_calculate: "
paul0c0f9cd2003-06-06 23:27:04 +00001053 "Skip area %s's calculation due to empty router_lsa_self",
1054 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001055 return;
1056 }
1057
1058 /* RFC2328 16.1. (1). */
paul0c0f9cd2003-06-06 23:27:04 +00001059 /* Initialize the algorithm's data structures. */
hasso462f20d2005-02-23 11:29:02 +00001060
1061 /* This function scans all the LSA database and set the stat field to
1062 * LSA_SPF_NOT_EXPLORED. */
1063 ospf_lsdb_clean_stat (area->lsdb);
1064 /* Create a new heap for the candidates. */
1065 candidate = pqueue_create();
1066 candidate->cmp = cmp;
1067 candidate->update = update_stat;
paul718e3742002-12-13 20:15:29 +00001068
1069 /* Initialize the shortest-path tree to only the root (which is the
1070 router doing the calculation). */
1071 ospf_spf_init (area);
1072 v = area->spf;
hasso462f20d2005-02-23 11:29:02 +00001073 /* Set LSA position to LSA_SPF_IN_SPFTREE. This vertex is the root of the
1074 * spanning tree. */
1075 *(v->stat) = LSA_SPF_IN_SPFTREE;
paul718e3742002-12-13 20:15:29 +00001076
1077 /* Set Area A's TransitCapability to FALSE. */
1078 area->transit = OSPF_TRANSIT_FALSE;
1079 area->shortcut_capability = 1;
pauleb3da6d2005-10-18 04:20:33 +00001080
paul718e3742002-12-13 20:15:29 +00001081 for (;;)
1082 {
1083 /* RFC2328 16.1. (2). */
hasso462f20d2005-02-23 11:29:02 +00001084 ospf_spf_next (v, area, candidate);
paul718e3742002-12-13 20:15:29 +00001085
1086 /* RFC2328 16.1. (3). */
1087 /* If at this step the candidate list is empty, the shortest-
1088 path tree (of transit vertices) has been completely built and
1089 this stage of the procedure terminates. */
hasso462f20d2005-02-23 11:29:02 +00001090 if (candidate->size == 0)
paul718e3742002-12-13 20:15:29 +00001091 break;
1092
1093 /* Otherwise, choose the vertex belonging to the candidate list
1094 that is closest to the root, and add it to the shortest-path
1095 tree (removing it from the candidate list in the
paul0c0f9cd2003-06-06 23:27:04 +00001096 process). */
hasso462f20d2005-02-23 11:29:02 +00001097 /* Extract from the candidates the node with the lower key. */
1098 v = (struct vertex *) pqueue_dequeue (candidate);
1099 /* Update stat field in vertex. */
1100 *(v->stat) = LSA_SPF_IN_SPFTREE;
pauleb3da6d2005-10-18 04:20:33 +00001101
paul718e3742002-12-13 20:15:29 +00001102 ospf_vertex_add_parent (v);
1103
paul718e3742002-12-13 20:15:29 +00001104 /* Note that when there is a choice of vertices closest to the
1105 root, network vertices must be chosen before router vertices
1106 in order to necessarily find all equal-cost paths. */
1107 /* We don't do this at this moment, we should add the treatment
1108 above codes. -- kunihiro. */
1109
1110 /* RFC2328 16.1. (4). */
1111 if (v->type == OSPF_VERTEX_ROUTER)
1112 ospf_intra_add_router (new_rtrs, v, area);
paul0c0f9cd2003-06-06 23:27:04 +00001113 else
paul718e3742002-12-13 20:15:29 +00001114 ospf_intra_add_transit (new_table, v, area);
1115
1116 /* RFC2328 16.1. (5). */
1117 /* Iterate the algorithm by returning to Step 2. */
gdt630e4802004-08-31 17:28:41 +00001118
1119 } /* end loop until no more candidate vertices */
paul718e3742002-12-13 20:15:29 +00001120
1121 if (IS_DEBUG_OSPF_EVENT)
1122 {
1123 ospf_spf_dump (area->spf, 0);
1124 ospf_route_table_dump (new_table);
1125 }
1126
1127 /* Second stage of SPF calculation procedure's */
1128 ospf_spf_process_stubs (area, area->spf, new_table);
1129
pauleb3da6d2005-10-18 04:20:33 +00001130 /* Free candidate queue. */
hasso462f20d2005-02-23 11:29:02 +00001131 pqueue_delete (candidate);
pauleb3da6d2005-10-18 04:20:33 +00001132
1133 ospf_vertex_dump (__func__, area->spf, 0, 1);
1134 /* Free nexthop information, canonical versions of which are attached
1135 * the first level of router vertices attached to the root vertex, see
1136 * ospf_nexthop_calculation.
1137 */
1138 ospf_canonical_nexthops_free (area->spf);
1139
Paul Jakma9c27ef92006-05-04 07:32:57 +00001140 /* Free SPF vertices, but not the list. List has ospf_vertex_free
1141 * as deconstructor.
1142 */
1143 list_delete_all_node (&vertex_list);
pauleb3da6d2005-10-18 04:20:33 +00001144
paul718e3742002-12-13 20:15:29 +00001145 /* Increment SPF Calculation Counter. */
1146 area->spf_calculation++;
1147
Paul Jakma2518efd2006-08-27 06:49:29 +00001148 quagga_gettime (QUAGGA_CLK_MONOTONIC, &area->ospf->ts_spf);
paul718e3742002-12-13 20:15:29 +00001149
1150 if (IS_DEBUG_OSPF_EVENT)
Paul Jakma9c27ef92006-05-04 07:32:57 +00001151 zlog_debug ("ospf_spf_calculate: Stop. %ld vertices",
1152 mtype_stats_alloc(MTYPE_OSPF_VERTEX));
paul718e3742002-12-13 20:15:29 +00001153}
1154
1155/* Timer for SPF calculation. */
paul4dadc292005-05-06 21:37:42 +00001156static int
paul68980082003-03-25 05:07:42 +00001157ospf_spf_calculate_timer (struct thread *thread)
paul718e3742002-12-13 20:15:29 +00001158{
paul68980082003-03-25 05:07:42 +00001159 struct ospf *ospf = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +00001160 struct route_table *new_table, *new_rtrs;
paul1eb8ef22005-04-07 07:30:20 +00001161 struct ospf_area *area;
1162 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001163
1164 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001165 zlog_debug ("SPF: Timer (SPF calculation expire)");
paul0c0f9cd2003-06-06 23:27:04 +00001166
paul718e3742002-12-13 20:15:29 +00001167 ospf->t_spf_calc = NULL;
1168
1169 /* Allocate new table tree. */
1170 new_table = route_table_init ();
paul0c0f9cd2003-06-06 23:27:04 +00001171 new_rtrs = route_table_init ();
paul718e3742002-12-13 20:15:29 +00001172
paul68980082003-03-25 05:07:42 +00001173 ospf_vl_unapprove (ospf);
paul718e3742002-12-13 20:15:29 +00001174
1175 /* Calculate SPF for each area. */
paul1eb8ef22005-04-07 07:30:20 +00001176 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
Paul Jakma9c27ef92006-05-04 07:32:57 +00001177 {
1178 /* Do backbone last, so as to first discover intra-area paths
1179 * for any back-bone virtual-links
1180 */
1181 if (ospf->backbone && ospf->backbone == area)
1182 continue;
1183
1184 ospf_spf_calculate (area, new_table, new_rtrs);
1185 }
1186
1187 /* SPF for backbone, if required */
1188 if (ospf->backbone)
1189 ospf_spf_calculate (ospf->backbone, new_table, new_rtrs);
1190
paul68980082003-03-25 05:07:42 +00001191 ospf_vl_shut_unapproved (ospf);
paul718e3742002-12-13 20:15:29 +00001192
paul68980082003-03-25 05:07:42 +00001193 ospf_ia_routing (ospf, new_table, new_rtrs);
paul718e3742002-12-13 20:15:29 +00001194
1195 ospf_prune_unreachable_networks (new_table);
1196 ospf_prune_unreachable_routers (new_rtrs);
1197
1198 /* AS-external-LSA calculation should not be performed here. */
1199
1200 /* If new Router Route is installed,
1201 then schedule re-calculate External routes. */
1202 if (1)
paul68980082003-03-25 05:07:42 +00001203 ospf_ase_calculate_schedule (ospf);
paul718e3742002-12-13 20:15:29 +00001204
paul68980082003-03-25 05:07:42 +00001205 ospf_ase_calculate_timer_add (ospf);
paul718e3742002-12-13 20:15:29 +00001206
1207 /* Update routing table. */
paul68980082003-03-25 05:07:42 +00001208 ospf_route_install (ospf, new_table);
paul718e3742002-12-13 20:15:29 +00001209
1210 /* Update ABR/ASBR routing table */
paul68980082003-03-25 05:07:42 +00001211 if (ospf->old_rtrs)
paul718e3742002-12-13 20:15:29 +00001212 {
1213 /* old_rtrs's node holds linked list of ospf_route. --kunihiro. */
paul68980082003-03-25 05:07:42 +00001214 /* ospf_route_delete (ospf->old_rtrs); */
1215 ospf_rtrs_free (ospf->old_rtrs);
paul718e3742002-12-13 20:15:29 +00001216 }
1217
paul68980082003-03-25 05:07:42 +00001218 ospf->old_rtrs = ospf->new_rtrs;
1219 ospf->new_rtrs = new_rtrs;
paul718e3742002-12-13 20:15:29 +00001220
paul0c0f9cd2003-06-06 23:27:04 +00001221 if (IS_OSPF_ABR (ospf))
paul68980082003-03-25 05:07:42 +00001222 ospf_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001223
1224 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001225 zlog_debug ("SPF: calculation complete");
paul718e3742002-12-13 20:15:29 +00001226
1227 return 0;
1228}
1229
1230/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
1231 set timer for SPF calc. */
1232void
paul68980082003-03-25 05:07:42 +00001233ospf_spf_calculate_schedule (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00001234{
pauld24f6e22005-10-21 09:23:12 +00001235 unsigned long delay, elapsed, ht;
1236 struct timeval result;
paul718e3742002-12-13 20:15:29 +00001237
1238 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001239 zlog_debug ("SPF: calculation timer scheduled");
paul718e3742002-12-13 20:15:29 +00001240
1241 /* OSPF instance does not exist. */
paul68980082003-03-25 05:07:42 +00001242 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001243 return;
pauld24f6e22005-10-21 09:23:12 +00001244
paul718e3742002-12-13 20:15:29 +00001245 /* SPF calculation timer is already scheduled. */
paul68980082003-03-25 05:07:42 +00001246 if (ospf->t_spf_calc)
paul718e3742002-12-13 20:15:29 +00001247 {
1248 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001249 zlog_debug ("SPF: calculation timer is already scheduled: %p",
paul0c0f9cd2003-06-06 23:27:04 +00001250 ospf->t_spf_calc);
paul718e3742002-12-13 20:15:29 +00001251 return;
1252 }
pauld24f6e22005-10-21 09:23:12 +00001253
1254 /* XXX Monotic timers: we only care about relative time here. */
Paul Jakma2518efd2006-08-27 06:49:29 +00001255 result = tv_sub (recent_relative_time (), ospf->ts_spf);
pauld24f6e22005-10-21 09:23:12 +00001256
1257 elapsed = (result.tv_sec * 1000) + (result.tv_usec / 1000);
1258 ht = ospf->spf_holdtime * ospf->spf_hold_multiplier;
1259
1260 if (ht > ospf->spf_max_holdtime)
1261 ht = ospf->spf_max_holdtime;
1262
paul718e3742002-12-13 20:15:29 +00001263 /* Get SPF calculation delay time. */
pauld24f6e22005-10-21 09:23:12 +00001264 if (elapsed < ht)
paul718e3742002-12-13 20:15:29 +00001265 {
pauld24f6e22005-10-21 09:23:12 +00001266 /* Got an event within the hold time of last SPF. We need to
1267 * increase the hold_multiplier, if it's not already at/past
1268 * maximum value, and wasn't already increased..
1269 */
1270 if (ht < ospf->spf_max_holdtime)
1271 ospf->spf_hold_multiplier++;
1272
1273 /* always honour the SPF initial delay */
1274 if ( (ht - elapsed) < ospf->spf_delay)
paul0c0f9cd2003-06-06 23:27:04 +00001275 delay = ospf->spf_delay;
paul718e3742002-12-13 20:15:29 +00001276 else
pauld24f6e22005-10-21 09:23:12 +00001277 delay = ht - elapsed;
paul718e3742002-12-13 20:15:29 +00001278 }
1279 else
pauld24f6e22005-10-21 09:23:12 +00001280 {
1281 /* Event is past required hold-time of last SPF */
1282 delay = ospf->spf_delay;
1283 ospf->spf_hold_multiplier = 1;
1284 }
1285
paul718e3742002-12-13 20:15:29 +00001286 if (IS_DEBUG_OSPF_EVENT)
pauld24f6e22005-10-21 09:23:12 +00001287 zlog_debug ("SPF: calculation timer delay = %ld", delay);
1288
paul68980082003-03-25 05:07:42 +00001289 ospf->t_spf_calc =
pauld24f6e22005-10-21 09:23:12 +00001290 thread_add_timer_msec (master, ospf_spf_calculate_timer, ospf, delay);
paul718e3742002-12-13 20:15:29 +00001291}