blob: a133d5f87d5b66b5019a351489b6ea5005d7738e [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
paul75ee0b82004-08-05 09:10:31 +0000408/*
409 * Consider supplied next-hop for inclusion to the supplied list of
410 * equal-cost next-hops, adjust list as neccessary.
411 *
412 * (Discussed on GNU Zebra list 27 May 2003, [zebra 19184])
413 *
414 * Note that below is a bit of a hack, and limits ECMP to paths that go to
415 * same nexthop. Where as paths via inequal output_cost interfaces could
416 * still quite easily be ECMP due to remote cost differences.
417 *
418 * TODO: It really should be done by way of recording currently valid
419 * backlinks and determining the appropriate nexthops from the list of
420 * backlinks, or even simpler, just flushing nexthop list if we find a lower
421 * cost path to a candidate vertex in SPF, maybe.
paulbf9392c2003-06-06 23:23:36 +0000422 */
paul4dadc292005-05-06 21:37:42 +0000423static void
pauleb3da6d2005-10-18 04:20:33 +0000424ospf_spf_add_parent (struct vertex *v, struct vertex *w,
425 struct vertex_nexthop *newhop)
paulbf9392c2003-06-06 23:23:36 +0000426{
pauleb3da6d2005-10-18 04:20:33 +0000427 struct vertex_parent *vp;
428
429 /* we must have a newhop.. */
430 assert (v && w && newhop);
431
432 /* new parent is <= existing parents, add it */
433 vp = vertex_parent_new (v, ospf_lsa_has_link (w->lsa, v->lsa), newhop);
434 listnode_add (w->parents, vp);
paulbf9392c2003-06-06 23:23:36 +0000435
436 return;
437}
438
pauleb3da6d2005-10-18 04:20:33 +0000439static void
440ospf_spf_flush_parents (struct vertex *w)
441{
442 struct vertex_parent *vp;
443 struct listnode *ln, *nn;
444
445 /* delete the existing nexthops */
446 for (ALL_LIST_ELEMENTS (w->parents, ln, nn, vp))
447 {
448 list_delete_node (w->parents, ln);
449 vertex_parent_free (vp);
450 }
451}
452
gdt630e4802004-08-31 17:28:41 +0000453/* 16.1.1. Calculate nexthop from root through V (parent) to
454 * vertex W (destination).
pauleb3da6d2005-10-18 04:20:33 +0000455 *
456 * The link must be supplied if V is the root vertex. In all other cases
457 * it may be NULL.
gdt630e4802004-08-31 17:28:41 +0000458 */
paul4dadc292005-05-06 21:37:42 +0000459static void
pauleb3da6d2005-10-18 04:20:33 +0000460ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v,
461 struct vertex *w, struct router_lsa_link *l)
paul718e3742002-12-13 20:15:29 +0000462{
paul1eb8ef22005-04-07 07:30:20 +0000463 struct listnode *node, *nnode;
pauleb3da6d2005-10-18 04:20:33 +0000464 struct vertex_nexthop *nh;
465 struct vertex_parent *vp;
paul718e3742002-12-13 20:15:29 +0000466 struct ospf_interface *oi = NULL;
paul0c0f9cd2003-06-06 23:27:04 +0000467
paul718e3742002-12-13 20:15:29 +0000468 if (IS_DEBUG_OSPF_EVENT)
gdt630e4802004-08-31 17:28:41 +0000469 {
ajs2a42e282004-12-08 18:43:03 +0000470 zlog_debug ("ospf_nexthop_calculation(): Start");
gdt630e4802004-08-31 17:28:41 +0000471 ospf_vertex_dump("V (parent):", v, 1, 1);
472 ospf_vertex_dump("W (dest) :", w, 1, 1);
473 }
paul718e3742002-12-13 20:15:29 +0000474
paul718e3742002-12-13 20:15:29 +0000475 if (v == area->spf)
Paul Jakma9c27ef92006-05-04 07:32:57 +0000476 {
gdt630e4802004-08-31 17:28:41 +0000477 /* 16.1.1 para 4. In the first case, the parent vertex (V) is the
478 root (the calculating router itself). This means that the
479 destination is either a directly connected network or directly
480 connected router. The outgoing interface in this case is simply
481 the OSPF interface connecting to the destination network/router.
482 */
483
paul718e3742002-12-13 20:15:29 +0000484 if (w->type == OSPF_VERTEX_ROUTER)
paul0c0f9cd2003-06-06 23:27:04 +0000485 {
pauleb3da6d2005-10-18 04:20:33 +0000486 /* l is a link from v to w
487 * l2 will be link from w to v
488 */
489 struct router_lsa_link *l2 = NULL;
490
491 /* we *must* be supplied with the link data */
492 assert (l != NULL);
493
494 if (IS_DEBUG_OSPF_EVENT)
paul0c0f9cd2003-06-06 23:27:04 +0000495 {
pauleb3da6d2005-10-18 04:20:33 +0000496 char buf1[BUFSIZ];
497 char buf2[BUFSIZ];
498
499 zlog_debug("ospf_nexthop_calculation(): considering link "
500 "type %d link_id %s link_data %s",
501 l->m[0].type,
502 inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ),
503 inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ));
504 }
paul0c0f9cd2003-06-06 23:27:04 +0000505
pauleb3da6d2005-10-18 04:20:33 +0000506 if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT)
507 {
508 /* If the destination is a router which connects to
509 the calculating router via a Point-to-MultiPoint
510 network, the destination's next hop IP address(es)
511 can be determined by examining the destination's
512 router-LSA: each link pointing back to the
513 calculating router and having a Link Data field
514 belonging to the Point-to-MultiPoint network
515 provides an IP address of the next hop router.
gdt630e4802004-08-31 17:28:41 +0000516
pauleb3da6d2005-10-18 04:20:33 +0000517 At this point l is a link from V to W, and V is the
518 root ("us"). Find the local interface associated
519 with l (its address is in l->link_data). If it
520 is a point-to-multipoint interface, then look through
521 the links in the opposite direction (W to V). If
522 any of them have an address that lands within the
523 subnet declared by the PtMP link, then that link
524 is a constituent of the PtMP link, and its address is
525 a nexthop address for V.
526 */
527 oi = ospf_if_is_configured (area->ospf, &l->link_data);
528 if (oi && oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
paul0c0f9cd2003-06-06 23:27:04 +0000529 {
pauleb3da6d2005-10-18 04:20:33 +0000530 struct prefix_ipv4 la;
gdt630e4802004-08-31 17:28:41 +0000531
pauleb3da6d2005-10-18 04:20:33 +0000532 la.family = AF_INET;
533 la.prefixlen = oi->address->prefixlen;
534
535 /* V links to W on PtMP interface
536 - find the interface address on W */
537 while ((l2 = ospf_get_next_link (w, v, l2)))
paul0c0f9cd2003-06-06 23:27:04 +0000538 {
pauleb3da6d2005-10-18 04:20:33 +0000539 la.prefix = l2->link_data;
gdt630e4802004-08-31 17:28:41 +0000540
pauleb3da6d2005-10-18 04:20:33 +0000541 if (prefix_cmp ((struct prefix *) &la,
542 oi->address) == 0)
543 /* link_data is on our PtMP network */
544 break;
paul0c0f9cd2003-06-06 23:27:04 +0000545 }
pauleb3da6d2005-10-18 04:20:33 +0000546 } /* end l is on point-to-multipoint link */
547 else
548 {
549 /* l is a regular point-to-point link.
550 Look for a link from W to V.
551 */
552 while ((l2 = ospf_get_next_link (w, v, l2)))
paul0c0f9cd2003-06-06 23:27:04 +0000553 {
pauleb3da6d2005-10-18 04:20:33 +0000554 oi = ospf_if_is_configured (area->ospf,
555 &(l2->link_data));
556
557 if (oi == NULL)
558 continue;
559
560 if (!IPV4_ADDR_SAME (&oi->address->u.prefix4,
561 &l->link_data))
562 continue;
563
564 break;
paul0c0f9cd2003-06-06 23:27:04 +0000565 }
pauleb3da6d2005-10-18 04:20:33 +0000566 }
567
568 if (oi && l2)
569 {
570 /* found all necessary info to build nexthop */
571 nh = vertex_nexthop_new ();
572 nh->oi = oi;
573 nh->router = l2->link_data;
574 ospf_spf_add_parent (v, w, nh);
575 }
576 else
Paul Jakma9c27ef92006-05-04 07:32:57 +0000577 zlog_info("ospf_nexthop_calculation(): "
578 "could not determine nexthop for link");
pauleb3da6d2005-10-18 04:20:33 +0000579 } /* end point-to-point link from V to W */
Paul Jakma9c27ef92006-05-04 07:32:57 +0000580 else if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK)
581 {
582 struct ospf_vl_data *vl_data;
583
584 /* VLink implementation limitations:
585 * a) vl_data can only reference one nexthop, so no ECMP
586 * to backbone through VLinks. Though transit-area
587 * summaries may be considered, and those can be ECMP.
588 * b) We can only use /one/ VLink, even if multiple ones
589 * exist this router through multiple transit-areas.
590 */
591 vl_data = ospf_vl_lookup (area->ospf, NULL, l->link_id);
592
593 if (vl_data
594 && CHECK_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED))
595 {
596 nh = vertex_nexthop_new ();
597 nh->oi = vl_data->nexthop.oi;
598 nh->router = vl_data->nexthop.router;
599 ospf_spf_add_parent (v, w, nh);
600 }
601 else
602 zlog_info("ospf_nexthop_calculation(): "
603 "vl_data for VL link not found");
604 } /* end virtual-link from V to W */
605 return;
gdt630e4802004-08-31 17:28:41 +0000606 } /* end W is a Router vertex */
paul718e3742002-12-13 20:15:29 +0000607 else
paul0c0f9cd2003-06-06 23:27:04 +0000608 {
pauleb3da6d2005-10-18 04:20:33 +0000609 assert(w->type == OSPF_VERTEX_NETWORK);
610 oi = ospf_if_is_configured (area->ospf, &(l->link_data));
611 if (oi)
paul0c0f9cd2003-06-06 23:27:04 +0000612 {
pauleb3da6d2005-10-18 04:20:33 +0000613 nh = vertex_nexthop_new ();
614 nh->oi = oi;
615 nh->router.s_addr = 0;
616 ospf_spf_add_parent (v, w, nh);
Paul Jakma9c27ef92006-05-04 07:32:57 +0000617 return;
paul0c0f9cd2003-06-06 23:27:04 +0000618 }
619 }
Paul Jakma9c27ef92006-05-04 07:32:57 +0000620 zlog_info("ospf_nexthop_calculation(): "
621 "Unknown attached link");
paul718e3742002-12-13 20:15:29 +0000622 return;
gdt630e4802004-08-31 17:28:41 +0000623 } /* end V is the root */
gdt630e4802004-08-31 17:28:41 +0000624 /* Check if W's parent is a network connected to root. */
paul718e3742002-12-13 20:15:29 +0000625 else if (v->type == OSPF_VERTEX_NETWORK)
626 {
gdt630e4802004-08-31 17:28:41 +0000627 /* See if any of V's parents are the root. */
pauleb3da6d2005-10-18 04:20:33 +0000628 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
paul718e3742002-12-13 20:15:29 +0000629 {
pauleb3da6d2005-10-18 04:20:33 +0000630 if (vp->parent == area->spf) /* connects to root? */
gdt630e4802004-08-31 17:28:41 +0000631 {
632 /* 16.1.1 para 5. ...the parent vertex is a network that
633 * directly connects the calculating router to the destination
634 * router. The list of next hops is then determined by
635 * examining the destination's router-LSA...
636 */
637
638 assert(w->type == OSPF_VERTEX_ROUTER);
paul0c0f9cd2003-06-06 23:27:04 +0000639 while ((l = ospf_get_next_link (w, v, l)))
640 {
gdt630e4802004-08-31 17:28:41 +0000641 /* ...For each link in the router-LSA that points back to the
642 * parent network, the link's Link Data field provides the IP
643 * address of a next hop router. The outgoing interface to
644 * use can then be derived from the next hop IP address (or
645 * it can be inherited from the parent network).
646 */
pauleb3da6d2005-10-18 04:20:33 +0000647 nh = vertex_nexthop_new ();
648 nh->oi = vp->nexthop->oi;
649 nh->router = l->link_data;
650 ospf_spf_add_parent (v, w, nh);
paul0c0f9cd2003-06-06 23:27:04 +0000651 }
652 return;
653 }
paul718e3742002-12-13 20:15:29 +0000654 }
655 }
656
gdt630e4802004-08-31 17:28:41 +0000657 /* 16.1.1 para 4. If there is at least one intervening router in the
658 * current shortest path between the destination and the root, the
659 * destination simply inherits the set of next hops from the
660 * parent.
661 */
pauleb3da6d2005-10-18 04:20:33 +0000662 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
663 ospf_spf_add_parent (v, w, vp->nexthop);
Paul Jakma9c27ef92006-05-04 07:32:57 +0000664
665 return;
paul718e3742002-12-13 20:15:29 +0000666}
667
gdt630e4802004-08-31 17:28:41 +0000668/* RFC2328 Section 16.1 (2).
669 * v is on the SPF tree. Examine the links in v's LSA. Update the list
670 * of candidates with any vertices not already on the list. If a lower-cost
671 * path is found to a vertex already on the candidate list, store the new cost.
672 */
paul4dadc292005-05-06 21:37:42 +0000673static void
paul718e3742002-12-13 20:15:29 +0000674ospf_spf_next (struct vertex *v, struct ospf_area *area,
hasso462f20d2005-02-23 11:29:02 +0000675 struct pqueue * candidate)
paul718e3742002-12-13 20:15:29 +0000676{
677 struct ospf_lsa *w_lsa = NULL;
paul718e3742002-12-13 20:15:29 +0000678 u_char *p;
679 u_char *lim;
680 struct router_lsa_link *l = NULL;
681 struct in_addr *r;
paul718e3742002-12-13 20:15:29 +0000682 int type = 0;
683
684 /* If this is a router-LSA, and bit V of the router-LSA (see Section
685 A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE. */
686 if (v->type == OSPF_VERTEX_ROUTER)
687 {
688 if (IS_ROUTER_LSA_VIRTUAL ((struct router_lsa *) v->lsa))
689 area->transit = OSPF_TRANSIT_TRUE;
690 }
691
692 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul0c0f9cd2003-06-06 23:27:04 +0000693 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
694
paul718e3742002-12-13 20:15:29 +0000695 while (p < lim)
696 {
pauleb3da6d2005-10-18 04:20:33 +0000697 struct vertex *w;
698 unsigned int distance;
pauld355bfa2004-04-08 07:43:45 +0000699
paul718e3742002-12-13 20:15:29 +0000700 /* In case of V is Router-LSA. */
701 if (v->lsa->type == OSPF_ROUTER_LSA)
702 {
703 l = (struct router_lsa_link *) p;
704
paul0c0f9cd2003-06-06 23:27:04 +0000705 p += (ROUTER_LSA_MIN_SIZE +
paul718e3742002-12-13 20:15:29 +0000706 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
707
708 /* (a) If this is a link to a stub network, examine the next
709 link in V's LSA. Links to stub networks will be
710 considered in the second stage of the shortest path
711 calculation. */
712 if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB)
713 continue;
714
715 /* (b) Otherwise, W is a transit vertex (router or transit
716 network). Look up the vertex W's LSA (router-LSA or
717 network-LSA) in Area A's link state database. */
718 switch (type)
719 {
720 case LSA_LINK_TYPE_POINTOPOINT:
721 case LSA_LINK_TYPE_VIRTUALLINK:
722 if (type == LSA_LINK_TYPE_VIRTUALLINK)
paul0c0f9cd2003-06-06 23:27:04 +0000723 {
724 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000725 zlog_debug ("looking up LSA through VL: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000726 inet_ntoa (l->link_id));
727 }
paul718e3742002-12-13 20:15:29 +0000728
729 w_lsa = ospf_lsa_lookup (area, OSPF_ROUTER_LSA, l->link_id,
730 l->link_id);
731 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000732 {
733 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000734 zlog_debug ("found Router LSA %s", inet_ntoa (l->link_id));
paul0c0f9cd2003-06-06 23:27:04 +0000735 }
paul718e3742002-12-13 20:15:29 +0000736 break;
737 case LSA_LINK_TYPE_TRANSIT:
paul0c0f9cd2003-06-06 23:27:04 +0000738 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000739 zlog_debug ("Looking up Network LSA, ID: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000740 inet_ntoa (l->link_id));
paul718e3742002-12-13 20:15:29 +0000741 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_NETWORK_LSA,
paul0c0f9cd2003-06-06 23:27:04 +0000742 l->link_id);
paul718e3742002-12-13 20:15:29 +0000743 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000744 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000745 zlog_debug ("found the LSA");
paul718e3742002-12-13 20:15:29 +0000746 break;
747 default:
paul0c0f9cd2003-06-06 23:27:04 +0000748 zlog_warn ("Invalid LSA link type %d", type);
paul718e3742002-12-13 20:15:29 +0000749 continue;
750 }
751 }
752 else
753 {
754 /* In case of V is Network-LSA. */
paul0c0f9cd2003-06-06 23:27:04 +0000755 r = (struct in_addr *) p;
paul718e3742002-12-13 20:15:29 +0000756 p += sizeof (struct in_addr);
757
758 /* Lookup the vertex W's LSA. */
759 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_ROUTER_LSA, *r);
760 }
761
762 /* (b cont.) If the LSA does not exist, or its LS age is equal
763 to MaxAge, or it does not have a link back to vertex V,
764 examine the next link in V's LSA.[23] */
765 if (w_lsa == NULL)
766 continue;
767
768 if (IS_LSA_MAXAGE (w_lsa))
769 continue;
770
pauleb3da6d2005-10-18 04:20:33 +0000771 if (ospf_lsa_has_link (w_lsa->data, v->lsa) < 0 )
paul718e3742002-12-13 20:15:29 +0000772 {
paul0c0f9cd2003-06-06 23:27:04 +0000773 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000774 zlog_debug ("The LSA doesn't have a link back");
paul718e3742002-12-13 20:15:29 +0000775 continue;
776 }
777
778 /* (c) If vertex W is already on the shortest-path tree, examine
779 the next link in the LSA. */
hasso462f20d2005-02-23 11:29:02 +0000780 if (w_lsa->stat == LSA_SPF_IN_SPFTREE)
781 {
782 if (IS_DEBUG_OSPF_EVENT)
783 zlog_debug ("The LSA is already in SPF");
784 continue;
785 }
paul718e3742002-12-13 20:15:29 +0000786
787 /* (d) Calculate the link state cost D of the resulting path
788 from the root to vertex W. D is equal to the sum of the link
789 state cost of the (already calculated) shortest path to
790 vertex V and the advertised cost of the link between vertices
791 V and W. If D is: */
792
paul718e3742002-12-13 20:15:29 +0000793 /* calculate link cost D. */
794 if (v->lsa->type == OSPF_ROUTER_LSA)
pauleb3da6d2005-10-18 04:20:33 +0000795 distance = v->distance + ntohs (l->m[0].metric);
gdt630e4802004-08-31 17:28:41 +0000796 else /* v is not a Router-LSA */
pauleb3da6d2005-10-18 04:20:33 +0000797 distance = v->distance;
paul718e3742002-12-13 20:15:29 +0000798
799 /* Is there already vertex W in candidate list? */
hasso462f20d2005-02-23 11:29:02 +0000800 if (w_lsa->stat == LSA_SPF_NOT_EXPLORED)
801 {
pauleb3da6d2005-10-18 04:20:33 +0000802 /* prepare vertex W. */
803 w = ospf_vertex_new (w_lsa);
804
hasso462f20d2005-02-23 11:29:02 +0000805 /* Calculate nexthop to W. */
pauleb3da6d2005-10-18 04:20:33 +0000806 w->distance = distance;
Paul Jakma9c27ef92006-05-04 07:32:57 +0000807
808 ospf_nexthop_calculation (area, v, w, l);
809 pqueue_enqueue (w, candidate);
hasso462f20d2005-02-23 11:29:02 +0000810 }
811 else if (w_lsa->stat >= 0)
812 {
813 /* Get the vertex from candidates. */
pauleb3da6d2005-10-18 04:20:33 +0000814 w = candidate->array[w_lsa->stat];
paul718e3742002-12-13 20:15:29 +0000815
hasso462f20d2005-02-23 11:29:02 +0000816 /* if D is greater than. */
pauleb3da6d2005-10-18 04:20:33 +0000817 if (w->distance < distance)
paul718e3742002-12-13 20:15:29 +0000818 {
paul718e3742002-12-13 20:15:29 +0000819 continue;
820 }
hasso462f20d2005-02-23 11:29:02 +0000821 /* equal to. */
pauleb3da6d2005-10-18 04:20:33 +0000822 else if (w->distance == distance)
paul718e3742002-12-13 20:15:29 +0000823 {
pauleb3da6d2005-10-18 04:20:33 +0000824 /* Found an equal-cost path to W.
825 * Calculate nexthop of to W from V. */
826 ospf_nexthop_calculation (area, v, w, l);
paul718e3742002-12-13 20:15:29 +0000827 }
hasso462f20d2005-02-23 11:29:02 +0000828 /* less than. */
829 else
paul718e3742002-12-13 20:15:29 +0000830 {
pauleb3da6d2005-10-18 04:20:33 +0000831 /* Found a lower-cost path to W. */
832 w->distance = distance;
833
834 /* Flush existing parent list from W */
835 ospf_spf_flush_parents (w);
836
837 /* Calculate new nexthop(s) to W. */
838 ospf_nexthop_calculation (area, v, w, l);
paul718e3742002-12-13 20:15:29 +0000839
hasso462f20d2005-02-23 11:29:02 +0000840 /* Decrease the key of the node in the heap, re-sort the heap. */
841 trickle_down (w_lsa->stat, candidate);
paul718e3742002-12-13 20:15:29 +0000842 }
gdt630e4802004-08-31 17:28:41 +0000843 } /* end W is already on the candidate list */
844 } /* end loop over the links in V's LSA */
paul718e3742002-12-13 20:15:29 +0000845}
846
paul4dadc292005-05-06 21:37:42 +0000847static void
paul718e3742002-12-13 20:15:29 +0000848ospf_spf_dump (struct vertex *v, int i)
849{
hasso52dc7ee2004-09-23 19:18:23 +0000850 struct listnode *cnode;
851 struct listnode *nnode;
pauleb3da6d2005-10-18 04:20:33 +0000852 struct vertex_parent *parent;
paul718e3742002-12-13 20:15:29 +0000853
854 if (v->type == OSPF_VERTEX_ROUTER)
855 {
856 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000857 zlog_debug ("SPF Result: %d [R] %s", i, inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000858 }
859 else
860 {
861 struct network_lsa *lsa = (struct network_lsa *) v->lsa;
862 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000863 zlog_debug ("SPF Result: %d [N] %s/%d", i, inet_ntoa (v->lsa->id),
paul0c0f9cd2003-06-06 23:27:04 +0000864 ip_masklen (lsa->mask));
gdt630e4802004-08-31 17:28:41 +0000865 }
paul718e3742002-12-13 20:15:29 +0000866
paul1eb8ef22005-04-07 07:30:20 +0000867 if (IS_DEBUG_OSPF_EVENT)
pauleb3da6d2005-10-18 04:20:33 +0000868 for (ALL_LIST_ELEMENTS_RO (v->parents, nnode, parent))
869 {
870 zlog_debug (" nexthop %p %s %s",
871 parent->nexthop,
872 inet_ntoa (parent->nexthop->router),
873 parent->nexthop->oi ? IF_NAME(parent->nexthop->oi)
874 : "NULL");
875 }
paul718e3742002-12-13 20:15:29 +0000876
877 i++;
878
pauleb3da6d2005-10-18 04:20:33 +0000879 for (ALL_LIST_ELEMENTS_RO (v->children, cnode, v))
paul1eb8ef22005-04-07 07:30:20 +0000880 ospf_spf_dump (v, i);
paul718e3742002-12-13 20:15:29 +0000881}
882
883/* Second stage of SPF calculation. */
paul4dadc292005-05-06 21:37:42 +0000884static void
paul0c0f9cd2003-06-06 23:27:04 +0000885ospf_spf_process_stubs (struct ospf_area *area, struct vertex *v,
paul718e3742002-12-13 20:15:29 +0000886 struct route_table *rt)
887{
paul1eb8ef22005-04-07 07:30:20 +0000888 struct listnode *cnode, *cnnode;
paul718e3742002-12-13 20:15:29 +0000889 struct vertex *child;
890
891 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000892 zlog_debug ("ospf_process_stub():processing stubs for area %s",
paul0c0f9cd2003-06-06 23:27:04 +0000893 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +0000894 if (v->type == OSPF_VERTEX_ROUTER)
895 {
896 u_char *p;
897 u_char *lim;
898 struct router_lsa_link *l;
899 struct router_lsa *rlsa;
900
paul0c0f9cd2003-06-06 23:27:04 +0000901 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000902 zlog_debug ("ospf_process_stubs():processing router LSA, id: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000903 inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000904 rlsa = (struct router_lsa *) v->lsa;
905
906
paul0c0f9cd2003-06-06 23:27:04 +0000907 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000908 zlog_debug ("ospf_process_stubs(): we have %d links to process",
paul0c0f9cd2003-06-06 23:27:04 +0000909 ntohs (rlsa->links));
gdt630e4802004-08-31 17:28:41 +0000910 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +0000911 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
912
913 while (p < lim)
914 {
915 l = (struct router_lsa_link *) p;
916
917 p += (ROUTER_LSA_MIN_SIZE +
918 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
919
920 if (l->m[0].type == LSA_LINK_TYPE_STUB)
921 ospf_intra_add_stub (rt, l, v, area);
922 }
923 }
924
gdt630e4802004-08-31 17:28:41 +0000925 ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1, 1);
paul718e3742002-12-13 20:15:29 +0000926
pauleb3da6d2005-10-18 04:20:33 +0000927 for (ALL_LIST_ELEMENTS (v->children, cnode, cnnode, child))
paul718e3742002-12-13 20:15:29 +0000928 {
paul718e3742002-12-13 20:15:29 +0000929 if (CHECK_FLAG (child->flags, OSPF_VERTEX_PROCESSED))
paul0c0f9cd2003-06-06 23:27:04 +0000930 continue;
paul718e3742002-12-13 20:15:29 +0000931
932 ospf_spf_process_stubs (area, child, rt);
933
934 SET_FLAG (child->flags, OSPF_VERTEX_PROCESSED);
935 }
936}
937
938void
939ospf_rtrs_free (struct route_table *rtrs)
940{
941 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +0000942 struct list *or_list;
paul1eb8ef22005-04-07 07:30:20 +0000943 struct ospf_route *or;
944 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000945
946 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000947 zlog_debug ("Route: Router Routing Table free");
paul718e3742002-12-13 20:15:29 +0000948
949 for (rn = route_top (rtrs); rn; rn = route_next (rn))
950 if ((or_list = rn->info) != NULL)
951 {
paul1eb8ef22005-04-07 07:30:20 +0000952 for (ALL_LIST_ELEMENTS (or_list, node, nnode, or))
953 ospf_route_free (or);
paul718e3742002-12-13 20:15:29 +0000954
paul0c0f9cd2003-06-06 23:27:04 +0000955 list_delete (or_list);
paul718e3742002-12-13 20:15:29 +0000956
paul0c0f9cd2003-06-06 23:27:04 +0000957 /* Unlock the node. */
958 rn->info = NULL;
959 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +0000960 }
961 route_table_finish (rtrs);
962}
963
paul4dadc292005-05-06 21:37:42 +0000964static void
paul718e3742002-12-13 20:15:29 +0000965ospf_rtrs_print (struct route_table *rtrs)
966{
967 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +0000968 struct list *or_list;
969 struct listnode *ln;
970 struct listnode *pnode;
paul718e3742002-12-13 20:15:29 +0000971 struct ospf_route *or;
972 struct ospf_path *path;
973 char buf1[BUFSIZ];
974 char buf2[BUFSIZ];
975
976 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000977 zlog_debug ("ospf_rtrs_print() start");
paul718e3742002-12-13 20:15:29 +0000978
979 for (rn = route_top (rtrs); rn; rn = route_next (rn))
980 if ((or_list = rn->info) != NULL)
paul1eb8ef22005-04-07 07:30:20 +0000981 for (ALL_LIST_ELEMENTS_RO (or_list, ln, or))
paul718e3742002-12-13 20:15:29 +0000982 {
paul718e3742002-12-13 20:15:29 +0000983 switch (or->path_type)
984 {
985 case OSPF_PATH_INTRA_AREA:
paul0c0f9cd2003-06-06 23:27:04 +0000986 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000987 zlog_debug ("%s [%d] area: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000988 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
989 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
990 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +0000991 break;
992 case OSPF_PATH_INTER_AREA:
paul0c0f9cd2003-06-06 23:27:04 +0000993 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000994 zlog_debug ("%s IA [%d] area: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000995 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
996 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
997 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +0000998 break;
999 default:
1000 break;
1001 }
1002
paul1eb8ef22005-04-07 07:30:20 +00001003 for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path))
paul718e3742002-12-13 20:15:29 +00001004 {
paul718e3742002-12-13 20:15:29 +00001005 if (path->nexthop.s_addr == 0)
paul0c0f9cd2003-06-06 23:27:04 +00001006 {
1007 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001008 zlog_debug (" directly attached to %s\r\n",
paul0c0f9cd2003-06-06 23:27:04 +00001009 IF_NAME (path->oi));
1010 }
1011 else
1012 {
1013 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001014 zlog_debug (" via %s, %s\r\n",
paul0c0f9cd2003-06-06 23:27:04 +00001015 inet_ntoa (path->nexthop), IF_NAME (path->oi));
1016 }
paul718e3742002-12-13 20:15:29 +00001017 }
1018 }
1019
ajs2a42e282004-12-08 18:43:03 +00001020 zlog_debug ("ospf_rtrs_print() end");
paul718e3742002-12-13 20:15:29 +00001021}
1022
1023/* Calculating the shortest-path tree for an area. */
paul4dadc292005-05-06 21:37:42 +00001024static void
paul0c0f9cd2003-06-06 23:27:04 +00001025ospf_spf_calculate (struct ospf_area *area, struct route_table *new_table,
paul718e3742002-12-13 20:15:29 +00001026 struct route_table *new_rtrs)
1027{
hasso462f20d2005-02-23 11:29:02 +00001028 struct pqueue *candidate;
paul718e3742002-12-13 20:15:29 +00001029 struct vertex *v;
pauleb3da6d2005-10-18 04:20:33 +00001030
paul718e3742002-12-13 20:15:29 +00001031 if (IS_DEBUG_OSPF_EVENT)
1032 {
ajs2a42e282004-12-08 18:43:03 +00001033 zlog_debug ("ospf_spf_calculate: Start");
1034 zlog_debug ("ospf_spf_calculate: running Dijkstra for area %s",
paul0c0f9cd2003-06-06 23:27:04 +00001035 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001036 }
1037
1038 /* Check router-lsa-self. If self-router-lsa is not yet allocated,
1039 return this area's calculation. */
paul0c0f9cd2003-06-06 23:27:04 +00001040 if (!area->router_lsa_self)
paul718e3742002-12-13 20:15:29 +00001041 {
1042 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001043 zlog_debug ("ospf_spf_calculate: "
paul0c0f9cd2003-06-06 23:27:04 +00001044 "Skip area %s's calculation due to empty router_lsa_self",
1045 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001046 return;
1047 }
1048
1049 /* RFC2328 16.1. (1). */
paul0c0f9cd2003-06-06 23:27:04 +00001050 /* Initialize the algorithm's data structures. */
hasso462f20d2005-02-23 11:29:02 +00001051
1052 /* This function scans all the LSA database and set the stat field to
1053 * LSA_SPF_NOT_EXPLORED. */
1054 ospf_lsdb_clean_stat (area->lsdb);
1055 /* Create a new heap for the candidates. */
1056 candidate = pqueue_create();
1057 candidate->cmp = cmp;
1058 candidate->update = update_stat;
paul718e3742002-12-13 20:15:29 +00001059
1060 /* Initialize the shortest-path tree to only the root (which is the
1061 router doing the calculation). */
1062 ospf_spf_init (area);
1063 v = area->spf;
hasso462f20d2005-02-23 11:29:02 +00001064 /* Set LSA position to LSA_SPF_IN_SPFTREE. This vertex is the root of the
1065 * spanning tree. */
1066 *(v->stat) = LSA_SPF_IN_SPFTREE;
paul718e3742002-12-13 20:15:29 +00001067
1068 /* Set Area A's TransitCapability to FALSE. */
1069 area->transit = OSPF_TRANSIT_FALSE;
1070 area->shortcut_capability = 1;
pauleb3da6d2005-10-18 04:20:33 +00001071
paul718e3742002-12-13 20:15:29 +00001072 for (;;)
1073 {
1074 /* RFC2328 16.1. (2). */
hasso462f20d2005-02-23 11:29:02 +00001075 ospf_spf_next (v, area, candidate);
paul718e3742002-12-13 20:15:29 +00001076
1077 /* RFC2328 16.1. (3). */
1078 /* If at this step the candidate list is empty, the shortest-
1079 path tree (of transit vertices) has been completely built and
1080 this stage of the procedure terminates. */
hasso462f20d2005-02-23 11:29:02 +00001081 if (candidate->size == 0)
paul718e3742002-12-13 20:15:29 +00001082 break;
1083
1084 /* Otherwise, choose the vertex belonging to the candidate list
1085 that is closest to the root, and add it to the shortest-path
1086 tree (removing it from the candidate list in the
paul0c0f9cd2003-06-06 23:27:04 +00001087 process). */
hasso462f20d2005-02-23 11:29:02 +00001088 /* Extract from the candidates the node with the lower key. */
1089 v = (struct vertex *) pqueue_dequeue (candidate);
1090 /* Update stat field in vertex. */
1091 *(v->stat) = LSA_SPF_IN_SPFTREE;
pauleb3da6d2005-10-18 04:20:33 +00001092
paul718e3742002-12-13 20:15:29 +00001093 ospf_vertex_add_parent (v);
1094
paul718e3742002-12-13 20:15:29 +00001095 /* Note that when there is a choice of vertices closest to the
1096 root, network vertices must be chosen before router vertices
1097 in order to necessarily find all equal-cost paths. */
1098 /* We don't do this at this moment, we should add the treatment
1099 above codes. -- kunihiro. */
1100
1101 /* RFC2328 16.1. (4). */
1102 if (v->type == OSPF_VERTEX_ROUTER)
1103 ospf_intra_add_router (new_rtrs, v, area);
paul0c0f9cd2003-06-06 23:27:04 +00001104 else
paul718e3742002-12-13 20:15:29 +00001105 ospf_intra_add_transit (new_table, v, area);
1106
1107 /* RFC2328 16.1. (5). */
1108 /* Iterate the algorithm by returning to Step 2. */
gdt630e4802004-08-31 17:28:41 +00001109
1110 } /* end loop until no more candidate vertices */
paul718e3742002-12-13 20:15:29 +00001111
1112 if (IS_DEBUG_OSPF_EVENT)
1113 {
1114 ospf_spf_dump (area->spf, 0);
1115 ospf_route_table_dump (new_table);
1116 }
1117
1118 /* Second stage of SPF calculation procedure's */
1119 ospf_spf_process_stubs (area, area->spf, new_table);
1120
pauleb3da6d2005-10-18 04:20:33 +00001121 /* Free candidate queue. */
hasso462f20d2005-02-23 11:29:02 +00001122 pqueue_delete (candidate);
pauleb3da6d2005-10-18 04:20:33 +00001123
1124 ospf_vertex_dump (__func__, area->spf, 0, 1);
1125 /* Free nexthop information, canonical versions of which are attached
1126 * the first level of router vertices attached to the root vertex, see
1127 * ospf_nexthop_calculation.
1128 */
1129 ospf_canonical_nexthops_free (area->spf);
1130
Paul Jakma9c27ef92006-05-04 07:32:57 +00001131 /* Free SPF vertices, but not the list. List has ospf_vertex_free
1132 * as deconstructor.
1133 */
1134 list_delete_all_node (&vertex_list);
pauleb3da6d2005-10-18 04:20:33 +00001135
paul718e3742002-12-13 20:15:29 +00001136 /* Increment SPF Calculation Counter. */
1137 area->spf_calculation++;
1138
Paul Jakma2518efd2006-08-27 06:49:29 +00001139 quagga_gettime (QUAGGA_CLK_MONOTONIC, &area->ospf->ts_spf);
paul718e3742002-12-13 20:15:29 +00001140
1141 if (IS_DEBUG_OSPF_EVENT)
Paul Jakma9c27ef92006-05-04 07:32:57 +00001142 zlog_debug ("ospf_spf_calculate: Stop. %ld vertices",
1143 mtype_stats_alloc(MTYPE_OSPF_VERTEX));
paul718e3742002-12-13 20:15:29 +00001144}
1145
1146/* Timer for SPF calculation. */
paul4dadc292005-05-06 21:37:42 +00001147static int
paul68980082003-03-25 05:07:42 +00001148ospf_spf_calculate_timer (struct thread *thread)
paul718e3742002-12-13 20:15:29 +00001149{
paul68980082003-03-25 05:07:42 +00001150 struct ospf *ospf = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +00001151 struct route_table *new_table, *new_rtrs;
paul1eb8ef22005-04-07 07:30:20 +00001152 struct ospf_area *area;
1153 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001154
1155 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001156 zlog_debug ("SPF: Timer (SPF calculation expire)");
paul0c0f9cd2003-06-06 23:27:04 +00001157
paul718e3742002-12-13 20:15:29 +00001158 ospf->t_spf_calc = NULL;
1159
1160 /* Allocate new table tree. */
1161 new_table = route_table_init ();
paul0c0f9cd2003-06-06 23:27:04 +00001162 new_rtrs = route_table_init ();
paul718e3742002-12-13 20:15:29 +00001163
paul68980082003-03-25 05:07:42 +00001164 ospf_vl_unapprove (ospf);
paul718e3742002-12-13 20:15:29 +00001165
1166 /* Calculate SPF for each area. */
paul1eb8ef22005-04-07 07:30:20 +00001167 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
Paul Jakma9c27ef92006-05-04 07:32:57 +00001168 {
1169 /* Do backbone last, so as to first discover intra-area paths
1170 * for any back-bone virtual-links
1171 */
1172 if (ospf->backbone && ospf->backbone == area)
1173 continue;
1174
1175 ospf_spf_calculate (area, new_table, new_rtrs);
1176 }
1177
1178 /* SPF for backbone, if required */
1179 if (ospf->backbone)
1180 ospf_spf_calculate (ospf->backbone, new_table, new_rtrs);
1181
paul68980082003-03-25 05:07:42 +00001182 ospf_vl_shut_unapproved (ospf);
paul718e3742002-12-13 20:15:29 +00001183
paul68980082003-03-25 05:07:42 +00001184 ospf_ia_routing (ospf, new_table, new_rtrs);
paul718e3742002-12-13 20:15:29 +00001185
1186 ospf_prune_unreachable_networks (new_table);
1187 ospf_prune_unreachable_routers (new_rtrs);
1188
1189 /* AS-external-LSA calculation should not be performed here. */
1190
1191 /* If new Router Route is installed,
1192 then schedule re-calculate External routes. */
1193 if (1)
paul68980082003-03-25 05:07:42 +00001194 ospf_ase_calculate_schedule (ospf);
paul718e3742002-12-13 20:15:29 +00001195
paul68980082003-03-25 05:07:42 +00001196 ospf_ase_calculate_timer_add (ospf);
paul718e3742002-12-13 20:15:29 +00001197
1198 /* Update routing table. */
paul68980082003-03-25 05:07:42 +00001199 ospf_route_install (ospf, new_table);
paul718e3742002-12-13 20:15:29 +00001200
1201 /* Update ABR/ASBR routing table */
paul68980082003-03-25 05:07:42 +00001202 if (ospf->old_rtrs)
paul718e3742002-12-13 20:15:29 +00001203 {
1204 /* old_rtrs's node holds linked list of ospf_route. --kunihiro. */
paul68980082003-03-25 05:07:42 +00001205 /* ospf_route_delete (ospf->old_rtrs); */
1206 ospf_rtrs_free (ospf->old_rtrs);
paul718e3742002-12-13 20:15:29 +00001207 }
1208
paul68980082003-03-25 05:07:42 +00001209 ospf->old_rtrs = ospf->new_rtrs;
1210 ospf->new_rtrs = new_rtrs;
paul718e3742002-12-13 20:15:29 +00001211
paul0c0f9cd2003-06-06 23:27:04 +00001212 if (IS_OSPF_ABR (ospf))
paul68980082003-03-25 05:07:42 +00001213 ospf_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001214
1215 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001216 zlog_debug ("SPF: calculation complete");
paul718e3742002-12-13 20:15:29 +00001217
1218 return 0;
1219}
1220
1221/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
1222 set timer for SPF calc. */
1223void
paul68980082003-03-25 05:07:42 +00001224ospf_spf_calculate_schedule (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00001225{
pauld24f6e22005-10-21 09:23:12 +00001226 unsigned long delay, elapsed, ht;
1227 struct timeval result;
paul718e3742002-12-13 20:15:29 +00001228
1229 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001230 zlog_debug ("SPF: calculation timer scheduled");
paul718e3742002-12-13 20:15:29 +00001231
1232 /* OSPF instance does not exist. */
paul68980082003-03-25 05:07:42 +00001233 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001234 return;
pauld24f6e22005-10-21 09:23:12 +00001235
paul718e3742002-12-13 20:15:29 +00001236 /* SPF calculation timer is already scheduled. */
paul68980082003-03-25 05:07:42 +00001237 if (ospf->t_spf_calc)
paul718e3742002-12-13 20:15:29 +00001238 {
1239 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001240 zlog_debug ("SPF: calculation timer is already scheduled: %p",
paul0c0f9cd2003-06-06 23:27:04 +00001241 ospf->t_spf_calc);
paul718e3742002-12-13 20:15:29 +00001242 return;
1243 }
pauld24f6e22005-10-21 09:23:12 +00001244
1245 /* XXX Monotic timers: we only care about relative time here. */
Paul Jakma2518efd2006-08-27 06:49:29 +00001246 result = tv_sub (recent_relative_time (), ospf->ts_spf);
pauld24f6e22005-10-21 09:23:12 +00001247
1248 elapsed = (result.tv_sec * 1000) + (result.tv_usec / 1000);
1249 ht = ospf->spf_holdtime * ospf->spf_hold_multiplier;
1250
1251 if (ht > ospf->spf_max_holdtime)
1252 ht = ospf->spf_max_holdtime;
1253
paul718e3742002-12-13 20:15:29 +00001254 /* Get SPF calculation delay time. */
pauld24f6e22005-10-21 09:23:12 +00001255 if (elapsed < ht)
paul718e3742002-12-13 20:15:29 +00001256 {
pauld24f6e22005-10-21 09:23:12 +00001257 /* Got an event within the hold time of last SPF. We need to
1258 * increase the hold_multiplier, if it's not already at/past
1259 * maximum value, and wasn't already increased..
1260 */
1261 if (ht < ospf->spf_max_holdtime)
1262 ospf->spf_hold_multiplier++;
1263
1264 /* always honour the SPF initial delay */
1265 if ( (ht - elapsed) < ospf->spf_delay)
paul0c0f9cd2003-06-06 23:27:04 +00001266 delay = ospf->spf_delay;
paul718e3742002-12-13 20:15:29 +00001267 else
pauld24f6e22005-10-21 09:23:12 +00001268 delay = ht - elapsed;
paul718e3742002-12-13 20:15:29 +00001269 }
1270 else
pauld24f6e22005-10-21 09:23:12 +00001271 {
1272 /* Event is past required hold-time of last SPF */
1273 delay = ospf->spf_delay;
1274 ospf->spf_hold_multiplier = 1;
1275 }
1276
paul718e3742002-12-13 20:15:29 +00001277 if (IS_DEBUG_OSPF_EVENT)
pauld24f6e22005-10-21 09:23:12 +00001278 zlog_debug ("SPF: calculation timer delay = %ld", delay);
1279
paul68980082003-03-25 05:07:42 +00001280 ospf->t_spf_calc =
pauld24f6e22005-10-21 09:23:12 +00001281 thread_add_timer_msec (master, ospf_spf_calculate_timer, ospf, delay);
paul718e3742002-12-13 20:15:29 +00001282}