blob: f6260fbda3d9130b78ba286e3f0671fd3ae0954c [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
hasso462f20d2005-02-23 11:29:02 +000049/* Heap related functions, for the managment of the candidates, to
50 * be used with pqueue. */
51static int
52cmp (void * node1 , void * node2)
53{
54 struct vertex * v1 = (struct vertex *) node1;
55 struct vertex * v2 = (struct vertex *) node2;
56 if (v1 != NULL && v2 != NULL )
57 return (v1->distance - v2->distance);
58 else
59 return 0;
60}
61
62static void
pauleb3da6d2005-10-18 04:20:33 +000063update_stat (void *node , int position)
hasso462f20d2005-02-23 11:29:02 +000064{
pauleb3da6d2005-10-18 04:20:33 +000065 struct vertex *v = node;
66
hasso462f20d2005-02-23 11:29:02 +000067 /* Set the status of the vertex, when its position changes. */
68 *(v->stat) = position;
69}
pauleb3da6d2005-10-18 04:20:33 +000070
paul4dadc292005-05-06 21:37:42 +000071static struct vertex_nexthop *
pauleb3da6d2005-10-18 04:20:33 +000072vertex_nexthop_new (void)
paul718e3742002-12-13 20:15:29 +000073{
pauleb3da6d2005-10-18 04:20:33 +000074 return XCALLOC (MTYPE_OSPF_NEXTHOP, sizeof (struct vertex_nexthop));
paul718e3742002-12-13 20:15:29 +000075}
76
paul4dadc292005-05-06 21:37:42 +000077static void
paul718e3742002-12-13 20:15:29 +000078vertex_nexthop_free (struct vertex_nexthop *nh)
79{
80 XFREE (MTYPE_OSPF_NEXTHOP, nh);
81}
82
pauleb3da6d2005-10-18 04:20:33 +000083/* Free the canonical nexthop objects for an area, ie the nexthop objects
84 * attached to the first-hop router vertices.
85 */
86static void
87ospf_canonical_nexthops_free (struct vertex *root)
paul718e3742002-12-13 20:15:29 +000088{
pauleb3da6d2005-10-18 04:20:33 +000089 struct listnode *node, *nnode;
90 struct vertex *child;
91
92 for (ALL_LIST_ELEMENTS (root->children, node, nnode, child))
93 {
94 struct listnode *n2, *nn2;
95 struct vertex_parent *vp;
96
97 if (child->type == OSPF_VERTEX_NETWORK)
98 ospf_canonical_nexthops_free (child);
99
100 for (ALL_LIST_ELEMENTS (child->parents, n2, nn2, vp))
101 vertex_nexthop_free (vp->nexthop);
102 }
103}
104
105static struct vertex_parent *
106vertex_parent_new (struct vertex *v, int backlink, struct vertex_nexthop *hop)
107{
108 struct vertex_parent *new;
109
110 new = XMALLOC (MTYPE_OSPF_VERTEX_PARENT, sizeof (struct vertex_parent));
111
112 if (new == NULL)
113 return NULL;
114
115 new->parent = v;
116 new->backlink = backlink;
117 new->nexthop = hop;
paul718e3742002-12-13 20:15:29 +0000118 return new;
119}
paul0c0f9cd2003-06-06 23:27:04 +0000120
pauleb3da6d2005-10-18 04:20:33 +0000121static void
122vertex_parent_free (struct vertex_parent *p)
123{
124 XFREE (MTYPE_OSPF_VERTEX_PARENT, p);
125}
126
paul4dadc292005-05-06 21:37:42 +0000127static struct vertex *
paul718e3742002-12-13 20:15:29 +0000128ospf_vertex_new (struct ospf_lsa *lsa)
129{
130 struct vertex *new;
131
pauleb3da6d2005-10-18 04:20:33 +0000132 new = XCALLOC (MTYPE_OSPF_VERTEX, sizeof (struct vertex));
paul718e3742002-12-13 20:15:29 +0000133
134 new->flags = 0;
hasso462f20d2005-02-23 11:29:02 +0000135 new->stat = &(lsa->stat);
paul718e3742002-12-13 20:15:29 +0000136 new->type = lsa->data->type;
137 new->id = lsa->data->id;
138 new->lsa = lsa->data;
139 new->distance = 0;
pauleb3da6d2005-10-18 04:20:33 +0000140 new->children = list_new ();
141 new->parents = list_new ();
142
paul718e3742002-12-13 20:15:29 +0000143 return new;
144}
145
pauleb3da6d2005-10-18 04:20:33 +0000146/* Recursively free the given vertex and all its children
147 * and associated parent and nexthop information
148 * Parent should indicate which parent is trying to free this child,
149 * NULL parent is only valid for the root vertex.
150 */
paul4dadc292005-05-06 21:37:42 +0000151static void
pauleb3da6d2005-10-18 04:20:33 +0000152ospf_vertex_free (struct vertex *v, const struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +0000153{
paul1eb8ef22005-04-07 07:30:20 +0000154 struct listnode *node, *nnode;
pauleb3da6d2005-10-18 04:20:33 +0000155 struct vertex *vc;
paul7461d452005-06-13 13:57:16 +0000156
pauleb3da6d2005-10-18 04:20:33 +0000157 assert (*(v->stat) == LSA_SPF_IN_SPFTREE);
158
159 /* recurse down the tree, freeing furthest children first */
160 if (v->children)
161 {
162 for (ALL_LIST_ELEMENTS (v->children, node, nnode, vc))
163 ospf_vertex_free (vc, area);
164
165 list_delete (v->children);
166 v->children = NULL;
167 }
168
169 /* The vertex itself can only be freed when the last remaining parent
170 * with a reference to this vertex frees this vertex. Until then, we
171 * just cleanup /one/ parent association (doesnt matter which) -
172 * essentially using the parents list as a refcount.
173 */
174 if (listcount (v->parents) > 0)
175 {
176 vertex_parent_free (listgetdata (listhead (v->parents)));
177 list_delete_node (v->parents, listhead (v->parents));
paul718e3742002-12-13 20:15:29 +0000178
pauleb3da6d2005-10-18 04:20:33 +0000179 if (listcount (v->parents) > 0)
180 return; /* there are still parent references left */
181 }
182
183 list_delete (v->parents);
184 v->parents = NULL;
185
186 v->lsa = NULL;
paul7461d452005-06-13 13:57:16 +0000187
paul718e3742002-12-13 20:15:29 +0000188 XFREE (MTYPE_OSPF_VERTEX, v);
189}
190
paul4dadc292005-05-06 21:37:42 +0000191static void
hassoeb1ce602004-10-08 08:17:22 +0000192ospf_vertex_dump(const char *msg, struct vertex *v,
pauleb3da6d2005-10-18 04:20:33 +0000193 int print_parents, int print_children)
gdt630e4802004-08-31 17:28:41 +0000194{
195 if ( ! IS_DEBUG_OSPF_EVENT)
196 return;
197
pauleb3da6d2005-10-18 04:20:33 +0000198 zlog_debug("%s %s vertex %s distance %u flags %u",
gdt630e4802004-08-31 17:28:41 +0000199 msg,
200 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
201 inet_ntoa(v->lsa->id),
202 v->distance,
gdt630e4802004-08-31 17:28:41 +0000203 (unsigned int)v->flags);
204
pauleb3da6d2005-10-18 04:20:33 +0000205 if (print_parents)
gdt630e4802004-08-31 17:28:41 +0000206 {
paul1eb8ef22005-04-07 07:30:20 +0000207 struct listnode *node;
pauleb3da6d2005-10-18 04:20:33 +0000208 struct vertex_parent *vp;
paul1eb8ef22005-04-07 07:30:20 +0000209
pauleb3da6d2005-10-18 04:20:33 +0000210 for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
gdt630e4802004-08-31 17:28:41 +0000211 {
212 char buf1[BUFSIZ];
pauleb3da6d2005-10-18 04:20:33 +0000213
214 if (vp)
gdt630e4802004-08-31 17:28:41 +0000215 {
pauleb3da6d2005-10-18 04:20:33 +0000216 zlog_debug ("parent %s backlink %d nexthop %s interface %s",
217 inet_ntoa(vp->parent->lsa->id), vp->backlink,
218 inet_ntop(AF_INET, &vp->nexthop->router, buf1, BUFSIZ),
219 vp->nexthop->oi ? IF_NAME(vp->nexthop->oi) : "NULL");
gdt630e4802004-08-31 17:28:41 +0000220 }
221 }
222 }
223
224 if (print_children)
225 {
hasso52dc7ee2004-09-23 19:18:23 +0000226 struct listnode *cnode;
paul1eb8ef22005-04-07 07:30:20 +0000227 struct vertex *cv;
228
pauleb3da6d2005-10-18 04:20:33 +0000229 for (ALL_LIST_ELEMENTS_RO (v->children, cnode, cv))
paul1eb8ef22005-04-07 07:30:20 +0000230 ospf_vertex_dump(" child:", cv, 0, 0);
gdt630e4802004-08-31 17:28:41 +0000231 }
232}
233
234
235/* Add a vertex to the list of children in each of its parents. */
paul4dadc292005-05-06 21:37:42 +0000236static void
paul718e3742002-12-13 20:15:29 +0000237ospf_vertex_add_parent (struct vertex *v)
238{
pauleb3da6d2005-10-18 04:20:33 +0000239 struct vertex_parent *vp;
hasso52dc7ee2004-09-23 19:18:23 +0000240 struct listnode *node;
paul7461d452005-06-13 13:57:16 +0000241
pauleb3da6d2005-10-18 04:20:33 +0000242 assert (v && v->children);
paul7461d452005-06-13 13:57:16 +0000243
pauleb3da6d2005-10-18 04:20:33 +0000244 for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
paul718e3742002-12-13 20:15:29 +0000245 {
pauleb3da6d2005-10-18 04:20:33 +0000246 assert (vp->parent && vp->parent->children);
paul7461d452005-06-13 13:57:16 +0000247
paul718e3742002-12-13 20:15:29 +0000248 /* No need to add two links from the same parent. */
pauleb3da6d2005-10-18 04:20:33 +0000249 if (listnode_lookup (vp->parent->children, v) == NULL)
250 listnode_add (vp->parent->children, v);
paul718e3742002-12-13 20:15:29 +0000251 }
252}
253
paul4dadc292005-05-06 21:37:42 +0000254static void
paul718e3742002-12-13 20:15:29 +0000255ospf_spf_init (struct ospf_area *area)
256{
257 struct vertex *v;
258
259 /* Create root node. */
260 v = ospf_vertex_new (area->router_lsa_self);
261
262 area->spf = v;
263
264 /* Reset ABR and ASBR router counts. */
265 area->abr_count = 0;
266 area->asbr_count = 0;
267}
268
pauld355bfa2004-04-08 07:43:45 +0000269/* return index of link back to V from W, or -1 if no link found */
paul4dadc292005-05-06 21:37:42 +0000270static int
paul718e3742002-12-13 20:15:29 +0000271ospf_lsa_has_link (struct lsa_header *w, struct lsa_header *v)
272{
hassoeb1ce602004-10-08 08:17:22 +0000273 unsigned int i, length;
paul718e3742002-12-13 20:15:29 +0000274 struct router_lsa *rl;
275 struct network_lsa *nl;
276
277 /* In case of W is Network LSA. */
278 if (w->type == OSPF_NETWORK_LSA)
279 {
280 if (v->type == OSPF_NETWORK_LSA)
pauld355bfa2004-04-08 07:43:45 +0000281 return -1;
paul718e3742002-12-13 20:15:29 +0000282
283 nl = (struct network_lsa *) w;
284 length = (ntohs (w->length) - OSPF_LSA_HEADER_SIZE - 4) / 4;
paul0c0f9cd2003-06-06 23:27:04 +0000285
paul718e3742002-12-13 20:15:29 +0000286 for (i = 0; i < length; i++)
287 if (IPV4_ADDR_SAME (&nl->routers[i], &v->id))
pauld355bfa2004-04-08 07:43:45 +0000288 return i;
289 return -1;
paul718e3742002-12-13 20:15:29 +0000290 }
291
292 /* In case of W is Router LSA. */
293 if (w->type == OSPF_ROUTER_LSA)
294 {
295 rl = (struct router_lsa *) w;
296
297 length = ntohs (w->length);
298
299 for (i = 0;
paul0c0f9cd2003-06-06 23:27:04 +0000300 i < ntohs (rl->links) && length >= sizeof (struct router_lsa);
301 i++, length -= 12)
paul718e3742002-12-13 20:15:29 +0000302 {
303 switch (rl->link[i].type)
304 {
305 case LSA_LINK_TYPE_POINTOPOINT:
306 case LSA_LINK_TYPE_VIRTUALLINK:
307 /* Router LSA ID. */
308 if (v->type == OSPF_ROUTER_LSA &&
309 IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
310 {
pauld355bfa2004-04-08 07:43:45 +0000311 return i;
paul718e3742002-12-13 20:15:29 +0000312 }
313 break;
314 case LSA_LINK_TYPE_TRANSIT:
315 /* Network LSA ID. */
316 if (v->type == OSPF_NETWORK_LSA &&
317 IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
318 {
pauld355bfa2004-04-08 07:43:45 +0000319 return i;
paul0c0f9cd2003-06-06 23:27:04 +0000320 }
paul718e3742002-12-13 20:15:29 +0000321 break;
322 case LSA_LINK_TYPE_STUB:
pauleb3da6d2005-10-18 04:20:33 +0000323 /* Stub can't lead anywhere, carry on */
paul718e3742002-12-13 20:15:29 +0000324 continue;
325 default:
326 break;
327 }
328 }
329 }
pauld355bfa2004-04-08 07:43:45 +0000330 return -1;
paul718e3742002-12-13 20:15:29 +0000331}
332
paul718e3742002-12-13 20:15:29 +0000333#define ROUTER_LSA_MIN_SIZE 12
334#define ROUTER_LSA_TOS_SIZE 4
335
gdt630e4802004-08-31 17:28:41 +0000336/* Find the next link after prev_link from v to w. If prev_link is
337 * NULL, return the first link from v to w. Ignore stub and virtual links;
338 * these link types will never be returned.
339 */
paul4dadc292005-05-06 21:37:42 +0000340static struct router_lsa_link *
paul718e3742002-12-13 20:15:29 +0000341ospf_get_next_link (struct vertex *v, struct vertex *w,
paul0c0f9cd2003-06-06 23:27:04 +0000342 struct router_lsa_link *prev_link)
paul718e3742002-12-13 20:15:29 +0000343{
344 u_char *p;
345 u_char *lim;
346 struct router_lsa_link *l;
347
348 if (prev_link == NULL)
gdt630e4802004-08-31 17:28:41 +0000349 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +0000350 else
351 {
paul0c0f9cd2003-06-06 23:27:04 +0000352 p = (u_char *) prev_link;
paul718e3742002-12-13 20:15:29 +0000353 p += (ROUTER_LSA_MIN_SIZE +
354 (prev_link->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
355 }
paul0c0f9cd2003-06-06 23:27:04 +0000356
paul718e3742002-12-13 20:15:29 +0000357 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
358
359 while (p < lim)
360 {
361 l = (struct router_lsa_link *) p;
362
paul0c0f9cd2003-06-06 23:27:04 +0000363 p += (ROUTER_LSA_MIN_SIZE + (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
paul718e3742002-12-13 20:15:29 +0000364
365 if (l->m[0].type == LSA_LINK_TYPE_STUB)
366 continue;
367
368 /* Defer NH calculation via VLs until summaries from
369 transit areas area confidered */
370
371 if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK)
paul0c0f9cd2003-06-06 23:27:04 +0000372 continue;
paul718e3742002-12-13 20:15:29 +0000373
374 if (IPV4_ADDR_SAME (&l->link_id, &w->id))
paul0c0f9cd2003-06-06 23:27:04 +0000375 return l;
paul718e3742002-12-13 20:15:29 +0000376 }
377
378 return NULL;
379}
380
paul75ee0b82004-08-05 09:10:31 +0000381/*
382 * Consider supplied next-hop for inclusion to the supplied list of
383 * equal-cost next-hops, adjust list as neccessary.
384 *
385 * (Discussed on GNU Zebra list 27 May 2003, [zebra 19184])
386 *
387 * Note that below is a bit of a hack, and limits ECMP to paths that go to
388 * same nexthop. Where as paths via inequal output_cost interfaces could
389 * still quite easily be ECMP due to remote cost differences.
390 *
391 * TODO: It really should be done by way of recording currently valid
392 * backlinks and determining the appropriate nexthops from the list of
393 * backlinks, or even simpler, just flushing nexthop list if we find a lower
394 * cost path to a candidate vertex in SPF, maybe.
paulbf9392c2003-06-06 23:23:36 +0000395 */
paul4dadc292005-05-06 21:37:42 +0000396static void
pauleb3da6d2005-10-18 04:20:33 +0000397ospf_spf_add_parent (struct vertex *v, struct vertex *w,
398 struct vertex_nexthop *newhop)
paulbf9392c2003-06-06 23:23:36 +0000399{
pauleb3da6d2005-10-18 04:20:33 +0000400 struct vertex_parent *vp;
401
402 /* we must have a newhop.. */
403 assert (v && w && newhop);
404
405 /* new parent is <= existing parents, add it */
406 vp = vertex_parent_new (v, ospf_lsa_has_link (w->lsa, v->lsa), newhop);
407 listnode_add (w->parents, vp);
paulbf9392c2003-06-06 23:23:36 +0000408
409 return;
410}
411
pauleb3da6d2005-10-18 04:20:33 +0000412static void
413ospf_spf_flush_parents (struct vertex *w)
414{
415 struct vertex_parent *vp;
416 struct listnode *ln, *nn;
417
418 /* delete the existing nexthops */
419 for (ALL_LIST_ELEMENTS (w->parents, ln, nn, vp))
420 {
421 list_delete_node (w->parents, ln);
422 vertex_parent_free (vp);
423 }
424}
425
gdt630e4802004-08-31 17:28:41 +0000426/* 16.1.1. Calculate nexthop from root through V (parent) to
427 * vertex W (destination).
pauleb3da6d2005-10-18 04:20:33 +0000428 *
429 * The link must be supplied if V is the root vertex. In all other cases
430 * it may be NULL.
gdt630e4802004-08-31 17:28:41 +0000431 */
paul4dadc292005-05-06 21:37:42 +0000432static void
pauleb3da6d2005-10-18 04:20:33 +0000433ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v,
434 struct vertex *w, struct router_lsa_link *l)
paul718e3742002-12-13 20:15:29 +0000435{
paul1eb8ef22005-04-07 07:30:20 +0000436 struct listnode *node, *nnode;
pauleb3da6d2005-10-18 04:20:33 +0000437 struct vertex_nexthop *nh;
438 struct vertex_parent *vp;
paul718e3742002-12-13 20:15:29 +0000439 struct ospf_interface *oi = NULL;
paul0c0f9cd2003-06-06 23:27:04 +0000440
paul718e3742002-12-13 20:15:29 +0000441 if (IS_DEBUG_OSPF_EVENT)
gdt630e4802004-08-31 17:28:41 +0000442 {
ajs2a42e282004-12-08 18:43:03 +0000443 zlog_debug ("ospf_nexthop_calculation(): Start");
gdt630e4802004-08-31 17:28:41 +0000444 ospf_vertex_dump("V (parent):", v, 1, 1);
445 ospf_vertex_dump("W (dest) :", w, 1, 1);
446 }
paul718e3742002-12-13 20:15:29 +0000447
paul718e3742002-12-13 20:15:29 +0000448 if (v == area->spf)
449 {
gdt630e4802004-08-31 17:28:41 +0000450 /* 16.1.1 para 4. In the first case, the parent vertex (V) is the
451 root (the calculating router itself). This means that the
452 destination is either a directly connected network or directly
453 connected router. The outgoing interface in this case is simply
454 the OSPF interface connecting to the destination network/router.
455 */
456
paul718e3742002-12-13 20:15:29 +0000457 if (w->type == OSPF_VERTEX_ROUTER)
paul0c0f9cd2003-06-06 23:27:04 +0000458 {
pauleb3da6d2005-10-18 04:20:33 +0000459 /* l is a link from v to w
460 * l2 will be link from w to v
461 */
462 struct router_lsa_link *l2 = NULL;
463
464 /* we *must* be supplied with the link data */
465 assert (l != NULL);
466
467 if (IS_DEBUG_OSPF_EVENT)
paul0c0f9cd2003-06-06 23:27:04 +0000468 {
pauleb3da6d2005-10-18 04:20:33 +0000469 char buf1[BUFSIZ];
470 char buf2[BUFSIZ];
471
472 zlog_debug("ospf_nexthop_calculation(): considering link "
473 "type %d link_id %s link_data %s",
474 l->m[0].type,
475 inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ),
476 inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ));
477 }
paul0c0f9cd2003-06-06 23:27:04 +0000478
pauleb3da6d2005-10-18 04:20:33 +0000479 if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT)
480 {
481 /* If the destination is a router which connects to
482 the calculating router via a Point-to-MultiPoint
483 network, the destination's next hop IP address(es)
484 can be determined by examining the destination's
485 router-LSA: each link pointing back to the
486 calculating router and having a Link Data field
487 belonging to the Point-to-MultiPoint network
488 provides an IP address of the next hop router.
gdt630e4802004-08-31 17:28:41 +0000489
pauleb3da6d2005-10-18 04:20:33 +0000490 At this point l is a link from V to W, and V is the
491 root ("us"). Find the local interface associated
492 with l (its address is in l->link_data). If it
493 is a point-to-multipoint interface, then look through
494 the links in the opposite direction (W to V). If
495 any of them have an address that lands within the
496 subnet declared by the PtMP link, then that link
497 is a constituent of the PtMP link, and its address is
498 a nexthop address for V.
499 */
500 oi = ospf_if_is_configured (area->ospf, &l->link_data);
501 if (oi && oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
paul0c0f9cd2003-06-06 23:27:04 +0000502 {
pauleb3da6d2005-10-18 04:20:33 +0000503 struct prefix_ipv4 la;
gdt630e4802004-08-31 17:28:41 +0000504
pauleb3da6d2005-10-18 04:20:33 +0000505 la.family = AF_INET;
506 la.prefixlen = oi->address->prefixlen;
507
508 /* V links to W on PtMP interface
509 - find the interface address on W */
510 while ((l2 = ospf_get_next_link (w, v, l2)))
paul0c0f9cd2003-06-06 23:27:04 +0000511 {
pauleb3da6d2005-10-18 04:20:33 +0000512 la.prefix = l2->link_data;
gdt630e4802004-08-31 17:28:41 +0000513
pauleb3da6d2005-10-18 04:20:33 +0000514 if (prefix_cmp ((struct prefix *) &la,
515 oi->address) == 0)
516 /* link_data is on our PtMP network */
517 break;
paul0c0f9cd2003-06-06 23:27:04 +0000518 }
pauleb3da6d2005-10-18 04:20:33 +0000519 } /* end l is on point-to-multipoint link */
520 else
521 {
522 /* l is a regular point-to-point link.
523 Look for a link from W to V.
524 */
525 while ((l2 = ospf_get_next_link (w, v, l2)))
paul0c0f9cd2003-06-06 23:27:04 +0000526 {
pauleb3da6d2005-10-18 04:20:33 +0000527 oi = ospf_if_is_configured (area->ospf,
528 &(l2->link_data));
529
530 if (oi == NULL)
531 continue;
532
533 if (!IPV4_ADDR_SAME (&oi->address->u.prefix4,
534 &l->link_data))
535 continue;
536
537 break;
paul0c0f9cd2003-06-06 23:27:04 +0000538 }
pauleb3da6d2005-10-18 04:20:33 +0000539 }
540
541 if (oi && l2)
542 {
543 /* found all necessary info to build nexthop */
544 nh = vertex_nexthop_new ();
545 nh->oi = oi;
546 nh->router = l2->link_data;
547 ospf_spf_add_parent (v, w, nh);
548 }
549 else
550 {
551 zlog_info("ospf_nexthop_calculation(): "
552 "could not determine nexthop for link");
553 }
554 } /* end point-to-point link from V to W */
gdt630e4802004-08-31 17:28:41 +0000555 } /* end W is a Router vertex */
paul718e3742002-12-13 20:15:29 +0000556 else
paul0c0f9cd2003-06-06 23:27:04 +0000557 {
pauleb3da6d2005-10-18 04:20:33 +0000558 assert(w->type == OSPF_VERTEX_NETWORK);
559 oi = ospf_if_is_configured (area->ospf, &(l->link_data));
560 if (oi)
paul0c0f9cd2003-06-06 23:27:04 +0000561 {
pauleb3da6d2005-10-18 04:20:33 +0000562 nh = vertex_nexthop_new ();
563 nh->oi = oi;
564 nh->router.s_addr = 0;
565 ospf_spf_add_parent (v, w, nh);
paul0c0f9cd2003-06-06 23:27:04 +0000566 }
567 }
paul718e3742002-12-13 20:15:29 +0000568 return;
gdt630e4802004-08-31 17:28:41 +0000569 } /* end V is the root */
gdt630e4802004-08-31 17:28:41 +0000570 /* Check if W's parent is a network connected to root. */
paul718e3742002-12-13 20:15:29 +0000571 else if (v->type == OSPF_VERTEX_NETWORK)
572 {
gdt630e4802004-08-31 17:28:41 +0000573 /* See if any of V's parents are the root. */
pauleb3da6d2005-10-18 04:20:33 +0000574 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
paul718e3742002-12-13 20:15:29 +0000575 {
pauleb3da6d2005-10-18 04:20:33 +0000576 if (vp->parent == area->spf) /* connects to root? */
gdt630e4802004-08-31 17:28:41 +0000577 {
578 /* 16.1.1 para 5. ...the parent vertex is a network that
579 * directly connects the calculating router to the destination
580 * router. The list of next hops is then determined by
581 * examining the destination's router-LSA...
582 */
583
584 assert(w->type == OSPF_VERTEX_ROUTER);
paul0c0f9cd2003-06-06 23:27:04 +0000585 while ((l = ospf_get_next_link (w, v, l)))
586 {
gdt630e4802004-08-31 17:28:41 +0000587 /* ...For each link in the router-LSA that points back to the
588 * parent network, the link's Link Data field provides the IP
589 * address of a next hop router. The outgoing interface to
590 * use can then be derived from the next hop IP address (or
591 * it can be inherited from the parent network).
592 */
pauleb3da6d2005-10-18 04:20:33 +0000593 nh = vertex_nexthop_new ();
594 nh->oi = vp->nexthop->oi;
595 nh->router = l->link_data;
596 ospf_spf_add_parent (v, w, nh);
paul0c0f9cd2003-06-06 23:27:04 +0000597 }
598 return;
599 }
paul718e3742002-12-13 20:15:29 +0000600 }
601 }
602
gdt630e4802004-08-31 17:28:41 +0000603 /* 16.1.1 para 4. If there is at least one intervening router in the
604 * current shortest path between the destination and the root, the
605 * destination simply inherits the set of next hops from the
606 * parent.
607 */
pauleb3da6d2005-10-18 04:20:33 +0000608 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
609 ospf_spf_add_parent (v, w, vp->nexthop);
paul718e3742002-12-13 20:15:29 +0000610}
611
gdt630e4802004-08-31 17:28:41 +0000612/* RFC2328 Section 16.1 (2).
613 * v is on the SPF tree. Examine the links in v's LSA. Update the list
614 * of candidates with any vertices not already on the list. If a lower-cost
615 * path is found to a vertex already on the candidate list, store the new cost.
616 */
paul4dadc292005-05-06 21:37:42 +0000617static void
paul718e3742002-12-13 20:15:29 +0000618ospf_spf_next (struct vertex *v, struct ospf_area *area,
hasso462f20d2005-02-23 11:29:02 +0000619 struct pqueue * candidate)
paul718e3742002-12-13 20:15:29 +0000620{
621 struct ospf_lsa *w_lsa = NULL;
paul718e3742002-12-13 20:15:29 +0000622 u_char *p;
623 u_char *lim;
624 struct router_lsa_link *l = NULL;
625 struct in_addr *r;
paul718e3742002-12-13 20:15:29 +0000626 int type = 0;
627
628 /* If this is a router-LSA, and bit V of the router-LSA (see Section
629 A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE. */
630 if (v->type == OSPF_VERTEX_ROUTER)
631 {
632 if (IS_ROUTER_LSA_VIRTUAL ((struct router_lsa *) v->lsa))
633 area->transit = OSPF_TRANSIT_TRUE;
634 }
635
636 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul0c0f9cd2003-06-06 23:27:04 +0000637 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
638
paul718e3742002-12-13 20:15:29 +0000639 while (p < lim)
640 {
pauleb3da6d2005-10-18 04:20:33 +0000641 struct vertex *w;
642 unsigned int distance;
pauld355bfa2004-04-08 07:43:45 +0000643
paul718e3742002-12-13 20:15:29 +0000644 /* In case of V is Router-LSA. */
645 if (v->lsa->type == OSPF_ROUTER_LSA)
646 {
647 l = (struct router_lsa_link *) p;
648
paul0c0f9cd2003-06-06 23:27:04 +0000649 p += (ROUTER_LSA_MIN_SIZE +
paul718e3742002-12-13 20:15:29 +0000650 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
651
652 /* (a) If this is a link to a stub network, examine the next
653 link in V's LSA. Links to stub networks will be
654 considered in the second stage of the shortest path
655 calculation. */
656 if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB)
657 continue;
658
659 /* (b) Otherwise, W is a transit vertex (router or transit
660 network). Look up the vertex W's LSA (router-LSA or
661 network-LSA) in Area A's link state database. */
662 switch (type)
663 {
664 case LSA_LINK_TYPE_POINTOPOINT:
665 case LSA_LINK_TYPE_VIRTUALLINK:
666 if (type == LSA_LINK_TYPE_VIRTUALLINK)
paul0c0f9cd2003-06-06 23:27:04 +0000667 {
668 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000669 zlog_debug ("looking up LSA through VL: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000670 inet_ntoa (l->link_id));
671 }
paul718e3742002-12-13 20:15:29 +0000672
673 w_lsa = ospf_lsa_lookup (area, OSPF_ROUTER_LSA, l->link_id,
674 l->link_id);
675 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000676 {
677 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000678 zlog_debug ("found Router LSA %s", inet_ntoa (l->link_id));
paul0c0f9cd2003-06-06 23:27:04 +0000679 }
paul718e3742002-12-13 20:15:29 +0000680 break;
681 case LSA_LINK_TYPE_TRANSIT:
paul0c0f9cd2003-06-06 23:27:04 +0000682 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000683 zlog_debug ("Looking up Network LSA, ID: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000684 inet_ntoa (l->link_id));
paul718e3742002-12-13 20:15:29 +0000685 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_NETWORK_LSA,
paul0c0f9cd2003-06-06 23:27:04 +0000686 l->link_id);
paul718e3742002-12-13 20:15:29 +0000687 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000688 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000689 zlog_debug ("found the LSA");
paul718e3742002-12-13 20:15:29 +0000690 break;
691 default:
paul0c0f9cd2003-06-06 23:27:04 +0000692 zlog_warn ("Invalid LSA link type %d", type);
paul718e3742002-12-13 20:15:29 +0000693 continue;
694 }
695 }
696 else
697 {
698 /* In case of V is Network-LSA. */
paul0c0f9cd2003-06-06 23:27:04 +0000699 r = (struct in_addr *) p;
paul718e3742002-12-13 20:15:29 +0000700 p += sizeof (struct in_addr);
701
702 /* Lookup the vertex W's LSA. */
703 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_ROUTER_LSA, *r);
704 }
705
706 /* (b cont.) If the LSA does not exist, or its LS age is equal
707 to MaxAge, or it does not have a link back to vertex V,
708 examine the next link in V's LSA.[23] */
709 if (w_lsa == NULL)
710 continue;
711
712 if (IS_LSA_MAXAGE (w_lsa))
713 continue;
714
pauleb3da6d2005-10-18 04:20:33 +0000715 if (ospf_lsa_has_link (w_lsa->data, v->lsa) < 0 )
paul718e3742002-12-13 20:15:29 +0000716 {
paul0c0f9cd2003-06-06 23:27:04 +0000717 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000718 zlog_debug ("The LSA doesn't have a link back");
paul718e3742002-12-13 20:15:29 +0000719 continue;
720 }
721
722 /* (c) If vertex W is already on the shortest-path tree, examine
723 the next link in the LSA. */
hasso462f20d2005-02-23 11:29:02 +0000724 if (w_lsa->stat == LSA_SPF_IN_SPFTREE)
725 {
726 if (IS_DEBUG_OSPF_EVENT)
727 zlog_debug ("The LSA is already in SPF");
728 continue;
729 }
paul718e3742002-12-13 20:15:29 +0000730
731 /* (d) Calculate the link state cost D of the resulting path
732 from the root to vertex W. D is equal to the sum of the link
733 state cost of the (already calculated) shortest path to
734 vertex V and the advertised cost of the link between vertices
735 V and W. If D is: */
736
paul718e3742002-12-13 20:15:29 +0000737 /* calculate link cost D. */
738 if (v->lsa->type == OSPF_ROUTER_LSA)
pauleb3da6d2005-10-18 04:20:33 +0000739 distance = v->distance + ntohs (l->m[0].metric);
gdt630e4802004-08-31 17:28:41 +0000740 else /* v is not a Router-LSA */
pauleb3da6d2005-10-18 04:20:33 +0000741 distance = v->distance;
paul718e3742002-12-13 20:15:29 +0000742
743 /* Is there already vertex W in candidate list? */
hasso462f20d2005-02-23 11:29:02 +0000744 if (w_lsa->stat == LSA_SPF_NOT_EXPLORED)
745 {
pauleb3da6d2005-10-18 04:20:33 +0000746 /* prepare vertex W. */
747 w = ospf_vertex_new (w_lsa);
748
hasso462f20d2005-02-23 11:29:02 +0000749 /* Calculate nexthop to W. */
pauleb3da6d2005-10-18 04:20:33 +0000750 w->distance = distance;
751 ospf_nexthop_calculation (area, v, w, l);
hasso462f20d2005-02-23 11:29:02 +0000752 pqueue_enqueue (w, candidate);
753 }
754 else if (w_lsa->stat >= 0)
755 {
756 /* Get the vertex from candidates. */
pauleb3da6d2005-10-18 04:20:33 +0000757 w = candidate->array[w_lsa->stat];
paul718e3742002-12-13 20:15:29 +0000758
hasso462f20d2005-02-23 11:29:02 +0000759 /* if D is greater than. */
pauleb3da6d2005-10-18 04:20:33 +0000760 if (w->distance < distance)
paul718e3742002-12-13 20:15:29 +0000761 {
paul718e3742002-12-13 20:15:29 +0000762 continue;
763 }
hasso462f20d2005-02-23 11:29:02 +0000764 /* equal to. */
pauleb3da6d2005-10-18 04:20:33 +0000765 else if (w->distance == distance)
paul718e3742002-12-13 20:15:29 +0000766 {
pauleb3da6d2005-10-18 04:20:33 +0000767 /* Found an equal-cost path to W.
768 * Calculate nexthop of to W from V. */
769 ospf_nexthop_calculation (area, v, w, l);
paul718e3742002-12-13 20:15:29 +0000770 }
hasso462f20d2005-02-23 11:29:02 +0000771 /* less than. */
772 else
paul718e3742002-12-13 20:15:29 +0000773 {
pauleb3da6d2005-10-18 04:20:33 +0000774 /* Found a lower-cost path to W. */
775 w->distance = distance;
776
777 /* Flush existing parent list from W */
778 ospf_spf_flush_parents (w);
779
780 /* Calculate new nexthop(s) to W. */
781 ospf_nexthop_calculation (area, v, w, l);
paul718e3742002-12-13 20:15:29 +0000782
hasso462f20d2005-02-23 11:29:02 +0000783 /* Decrease the key of the node in the heap, re-sort the heap. */
784 trickle_down (w_lsa->stat, candidate);
paul718e3742002-12-13 20:15:29 +0000785 }
gdt630e4802004-08-31 17:28:41 +0000786 } /* end W is already on the candidate list */
787 } /* end loop over the links in V's LSA */
paul718e3742002-12-13 20:15:29 +0000788}
789
paul4dadc292005-05-06 21:37:42 +0000790static void
paul718e3742002-12-13 20:15:29 +0000791ospf_spf_dump (struct vertex *v, int i)
792{
hasso52dc7ee2004-09-23 19:18:23 +0000793 struct listnode *cnode;
794 struct listnode *nnode;
pauleb3da6d2005-10-18 04:20:33 +0000795 struct vertex_parent *parent;
paul718e3742002-12-13 20:15:29 +0000796
797 if (v->type == OSPF_VERTEX_ROUTER)
798 {
799 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000800 zlog_debug ("SPF Result: %d [R] %s", i, inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000801 }
802 else
803 {
804 struct network_lsa *lsa = (struct network_lsa *) v->lsa;
805 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000806 zlog_debug ("SPF Result: %d [N] %s/%d", i, inet_ntoa (v->lsa->id),
paul0c0f9cd2003-06-06 23:27:04 +0000807 ip_masklen (lsa->mask));
gdt630e4802004-08-31 17:28:41 +0000808 }
paul718e3742002-12-13 20:15:29 +0000809
paul1eb8ef22005-04-07 07:30:20 +0000810 if (IS_DEBUG_OSPF_EVENT)
pauleb3da6d2005-10-18 04:20:33 +0000811 for (ALL_LIST_ELEMENTS_RO (v->parents, nnode, parent))
812 {
813 zlog_debug (" nexthop %p %s %s",
814 parent->nexthop,
815 inet_ntoa (parent->nexthop->router),
816 parent->nexthop->oi ? IF_NAME(parent->nexthop->oi)
817 : "NULL");
818 }
paul718e3742002-12-13 20:15:29 +0000819
820 i++;
821
pauleb3da6d2005-10-18 04:20:33 +0000822 for (ALL_LIST_ELEMENTS_RO (v->children, cnode, v))
paul1eb8ef22005-04-07 07:30:20 +0000823 ospf_spf_dump (v, i);
paul718e3742002-12-13 20:15:29 +0000824}
825
826/* Second stage of SPF calculation. */
paul4dadc292005-05-06 21:37:42 +0000827static void
paul0c0f9cd2003-06-06 23:27:04 +0000828ospf_spf_process_stubs (struct ospf_area *area, struct vertex *v,
paul718e3742002-12-13 20:15:29 +0000829 struct route_table *rt)
830{
paul1eb8ef22005-04-07 07:30:20 +0000831 struct listnode *cnode, *cnnode;
paul718e3742002-12-13 20:15:29 +0000832 struct vertex *child;
833
834 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000835 zlog_debug ("ospf_process_stub():processing stubs for area %s",
paul0c0f9cd2003-06-06 23:27:04 +0000836 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +0000837 if (v->type == OSPF_VERTEX_ROUTER)
838 {
839 u_char *p;
840 u_char *lim;
841 struct router_lsa_link *l;
842 struct router_lsa *rlsa;
843
paul0c0f9cd2003-06-06 23:27:04 +0000844 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000845 zlog_debug ("ospf_process_stubs():processing router LSA, id: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000846 inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000847 rlsa = (struct router_lsa *) v->lsa;
848
849
paul0c0f9cd2003-06-06 23:27:04 +0000850 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000851 zlog_debug ("ospf_process_stubs(): we have %d links to process",
paul0c0f9cd2003-06-06 23:27:04 +0000852 ntohs (rlsa->links));
gdt630e4802004-08-31 17:28:41 +0000853 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +0000854 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
855
856 while (p < lim)
857 {
858 l = (struct router_lsa_link *) p;
859
860 p += (ROUTER_LSA_MIN_SIZE +
861 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
862
863 if (l->m[0].type == LSA_LINK_TYPE_STUB)
864 ospf_intra_add_stub (rt, l, v, area);
865 }
866 }
867
gdt630e4802004-08-31 17:28:41 +0000868 ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1, 1);
paul718e3742002-12-13 20:15:29 +0000869
pauleb3da6d2005-10-18 04:20:33 +0000870 for (ALL_LIST_ELEMENTS (v->children, cnode, cnnode, child))
paul718e3742002-12-13 20:15:29 +0000871 {
paul718e3742002-12-13 20:15:29 +0000872 if (CHECK_FLAG (child->flags, OSPF_VERTEX_PROCESSED))
paul0c0f9cd2003-06-06 23:27:04 +0000873 continue;
paul718e3742002-12-13 20:15:29 +0000874
875 ospf_spf_process_stubs (area, child, rt);
876
877 SET_FLAG (child->flags, OSPF_VERTEX_PROCESSED);
878 }
879}
880
881void
882ospf_rtrs_free (struct route_table *rtrs)
883{
884 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +0000885 struct list *or_list;
paul1eb8ef22005-04-07 07:30:20 +0000886 struct ospf_route *or;
887 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000888
889 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000890 zlog_debug ("Route: Router Routing Table free");
paul718e3742002-12-13 20:15:29 +0000891
892 for (rn = route_top (rtrs); rn; rn = route_next (rn))
893 if ((or_list = rn->info) != NULL)
894 {
paul1eb8ef22005-04-07 07:30:20 +0000895 for (ALL_LIST_ELEMENTS (or_list, node, nnode, or))
896 ospf_route_free (or);
paul718e3742002-12-13 20:15:29 +0000897
paul0c0f9cd2003-06-06 23:27:04 +0000898 list_delete (or_list);
paul718e3742002-12-13 20:15:29 +0000899
paul0c0f9cd2003-06-06 23:27:04 +0000900 /* Unlock the node. */
901 rn->info = NULL;
902 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +0000903 }
904 route_table_finish (rtrs);
905}
906
paul4dadc292005-05-06 21:37:42 +0000907static void
paul718e3742002-12-13 20:15:29 +0000908ospf_rtrs_print (struct route_table *rtrs)
909{
910 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +0000911 struct list *or_list;
912 struct listnode *ln;
913 struct listnode *pnode;
paul718e3742002-12-13 20:15:29 +0000914 struct ospf_route *or;
915 struct ospf_path *path;
916 char buf1[BUFSIZ];
917 char buf2[BUFSIZ];
918
919 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000920 zlog_debug ("ospf_rtrs_print() start");
paul718e3742002-12-13 20:15:29 +0000921
922 for (rn = route_top (rtrs); rn; rn = route_next (rn))
923 if ((or_list = rn->info) != NULL)
paul1eb8ef22005-04-07 07:30:20 +0000924 for (ALL_LIST_ELEMENTS_RO (or_list, ln, or))
paul718e3742002-12-13 20:15:29 +0000925 {
paul718e3742002-12-13 20:15:29 +0000926 switch (or->path_type)
927 {
928 case OSPF_PATH_INTRA_AREA:
paul0c0f9cd2003-06-06 23:27:04 +0000929 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000930 zlog_debug ("%s [%d] area: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000931 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
932 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
933 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +0000934 break;
935 case OSPF_PATH_INTER_AREA:
paul0c0f9cd2003-06-06 23:27:04 +0000936 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000937 zlog_debug ("%s IA [%d] area: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000938 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
939 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
940 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +0000941 break;
942 default:
943 break;
944 }
945
paul1eb8ef22005-04-07 07:30:20 +0000946 for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path))
paul718e3742002-12-13 20:15:29 +0000947 {
paul718e3742002-12-13 20:15:29 +0000948 if (path->nexthop.s_addr == 0)
paul0c0f9cd2003-06-06 23:27:04 +0000949 {
950 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000951 zlog_debug (" directly attached to %s\r\n",
paul0c0f9cd2003-06-06 23:27:04 +0000952 IF_NAME (path->oi));
953 }
954 else
955 {
956 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000957 zlog_debug (" via %s, %s\r\n",
paul0c0f9cd2003-06-06 23:27:04 +0000958 inet_ntoa (path->nexthop), IF_NAME (path->oi));
959 }
paul718e3742002-12-13 20:15:29 +0000960 }
961 }
962
ajs2a42e282004-12-08 18:43:03 +0000963 zlog_debug ("ospf_rtrs_print() end");
paul718e3742002-12-13 20:15:29 +0000964}
965
966/* Calculating the shortest-path tree for an area. */
paul4dadc292005-05-06 21:37:42 +0000967static void
paul0c0f9cd2003-06-06 23:27:04 +0000968ospf_spf_calculate (struct ospf_area *area, struct route_table *new_table,
paul718e3742002-12-13 20:15:29 +0000969 struct route_table *new_rtrs)
970{
hasso462f20d2005-02-23 11:29:02 +0000971 struct pqueue *candidate;
paul718e3742002-12-13 20:15:29 +0000972 struct vertex *v;
pauleb3da6d2005-10-18 04:20:33 +0000973
paul718e3742002-12-13 20:15:29 +0000974 if (IS_DEBUG_OSPF_EVENT)
975 {
ajs2a42e282004-12-08 18:43:03 +0000976 zlog_debug ("ospf_spf_calculate: Start");
977 zlog_debug ("ospf_spf_calculate: running Dijkstra for area %s",
paul0c0f9cd2003-06-06 23:27:04 +0000978 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +0000979 }
980
981 /* Check router-lsa-self. If self-router-lsa is not yet allocated,
982 return this area's calculation. */
paul0c0f9cd2003-06-06 23:27:04 +0000983 if (!area->router_lsa_self)
paul718e3742002-12-13 20:15:29 +0000984 {
985 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000986 zlog_debug ("ospf_spf_calculate: "
paul0c0f9cd2003-06-06 23:27:04 +0000987 "Skip area %s's calculation due to empty router_lsa_self",
988 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +0000989 return;
990 }
991
992 /* RFC2328 16.1. (1). */
paul0c0f9cd2003-06-06 23:27:04 +0000993 /* Initialize the algorithm's data structures. */
hasso462f20d2005-02-23 11:29:02 +0000994
995 /* This function scans all the LSA database and set the stat field to
996 * LSA_SPF_NOT_EXPLORED. */
997 ospf_lsdb_clean_stat (area->lsdb);
998 /* Create a new heap for the candidates. */
999 candidate = pqueue_create();
1000 candidate->cmp = cmp;
1001 candidate->update = update_stat;
paul718e3742002-12-13 20:15:29 +00001002
1003 /* Initialize the shortest-path tree to only the root (which is the
1004 router doing the calculation). */
1005 ospf_spf_init (area);
1006 v = area->spf;
hasso462f20d2005-02-23 11:29:02 +00001007 /* Set LSA position to LSA_SPF_IN_SPFTREE. This vertex is the root of the
1008 * spanning tree. */
1009 *(v->stat) = LSA_SPF_IN_SPFTREE;
paul718e3742002-12-13 20:15:29 +00001010
1011 /* Set Area A's TransitCapability to FALSE. */
1012 area->transit = OSPF_TRANSIT_FALSE;
1013 area->shortcut_capability = 1;
pauleb3da6d2005-10-18 04:20:33 +00001014
paul718e3742002-12-13 20:15:29 +00001015 for (;;)
1016 {
1017 /* RFC2328 16.1. (2). */
hasso462f20d2005-02-23 11:29:02 +00001018 ospf_spf_next (v, area, candidate);
paul718e3742002-12-13 20:15:29 +00001019
1020 /* RFC2328 16.1. (3). */
1021 /* If at this step the candidate list is empty, the shortest-
1022 path tree (of transit vertices) has been completely built and
1023 this stage of the procedure terminates. */
hasso462f20d2005-02-23 11:29:02 +00001024 if (candidate->size == 0)
paul718e3742002-12-13 20:15:29 +00001025 break;
1026
1027 /* Otherwise, choose the vertex belonging to the candidate list
1028 that is closest to the root, and add it to the shortest-path
1029 tree (removing it from the candidate list in the
paul0c0f9cd2003-06-06 23:27:04 +00001030 process). */
hasso462f20d2005-02-23 11:29:02 +00001031 /* Extract from the candidates the node with the lower key. */
1032 v = (struct vertex *) pqueue_dequeue (candidate);
1033 /* Update stat field in vertex. */
1034 *(v->stat) = LSA_SPF_IN_SPFTREE;
pauleb3da6d2005-10-18 04:20:33 +00001035
paul718e3742002-12-13 20:15:29 +00001036 ospf_vertex_add_parent (v);
1037
paul718e3742002-12-13 20:15:29 +00001038 /* Note that when there is a choice of vertices closest to the
1039 root, network vertices must be chosen before router vertices
1040 in order to necessarily find all equal-cost paths. */
1041 /* We don't do this at this moment, we should add the treatment
1042 above codes. -- kunihiro. */
1043
1044 /* RFC2328 16.1. (4). */
1045 if (v->type == OSPF_VERTEX_ROUTER)
1046 ospf_intra_add_router (new_rtrs, v, area);
paul0c0f9cd2003-06-06 23:27:04 +00001047 else
paul718e3742002-12-13 20:15:29 +00001048 ospf_intra_add_transit (new_table, v, area);
1049
1050 /* RFC2328 16.1. (5). */
1051 /* Iterate the algorithm by returning to Step 2. */
gdt630e4802004-08-31 17:28:41 +00001052
1053 } /* end loop until no more candidate vertices */
paul718e3742002-12-13 20:15:29 +00001054
1055 if (IS_DEBUG_OSPF_EVENT)
1056 {
1057 ospf_spf_dump (area->spf, 0);
1058 ospf_route_table_dump (new_table);
1059 }
1060
1061 /* Second stage of SPF calculation procedure's */
1062 ospf_spf_process_stubs (area, area->spf, new_table);
1063
pauleb3da6d2005-10-18 04:20:33 +00001064 /* Free candidate queue. */
hasso462f20d2005-02-23 11:29:02 +00001065 pqueue_delete (candidate);
pauleb3da6d2005-10-18 04:20:33 +00001066
1067 ospf_vertex_dump (__func__, area->spf, 0, 1);
1068 /* Free nexthop information, canonical versions of which are attached
1069 * the first level of router vertices attached to the root vertex, see
1070 * ospf_nexthop_calculation.
1071 */
1072 ospf_canonical_nexthops_free (area->spf);
1073
1074 /* Free SPF vertices */
1075 ospf_vertex_free (area->spf, area);
1076
paul718e3742002-12-13 20:15:29 +00001077 /* Increment SPF Calculation Counter. */
1078 area->spf_calculation++;
1079
pauld24f6e22005-10-21 09:23:12 +00001080 gettimeofday (&area->ospf->ts_spf, NULL);
paul718e3742002-12-13 20:15:29 +00001081
1082 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001083 zlog_debug ("ospf_spf_calculate: Stop");
paul718e3742002-12-13 20:15:29 +00001084}
1085
1086/* Timer for SPF calculation. */
paul4dadc292005-05-06 21:37:42 +00001087static int
paul68980082003-03-25 05:07:42 +00001088ospf_spf_calculate_timer (struct thread *thread)
paul718e3742002-12-13 20:15:29 +00001089{
paul68980082003-03-25 05:07:42 +00001090 struct ospf *ospf = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +00001091 struct route_table *new_table, *new_rtrs;
paul1eb8ef22005-04-07 07:30:20 +00001092 struct ospf_area *area;
1093 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001094
1095 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001096 zlog_debug ("SPF: Timer (SPF calculation expire)");
paul0c0f9cd2003-06-06 23:27:04 +00001097
paul718e3742002-12-13 20:15:29 +00001098 ospf->t_spf_calc = NULL;
1099
1100 /* Allocate new table tree. */
1101 new_table = route_table_init ();
paul0c0f9cd2003-06-06 23:27:04 +00001102 new_rtrs = route_table_init ();
paul718e3742002-12-13 20:15:29 +00001103
paul68980082003-03-25 05:07:42 +00001104 ospf_vl_unapprove (ospf);
paul718e3742002-12-13 20:15:29 +00001105
1106 /* Calculate SPF for each area. */
paul1eb8ef22005-04-07 07:30:20 +00001107 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
1108 ospf_spf_calculate (area, new_table, new_rtrs);
paul718e3742002-12-13 20:15:29 +00001109
paul68980082003-03-25 05:07:42 +00001110 ospf_vl_shut_unapproved (ospf);
paul718e3742002-12-13 20:15:29 +00001111
paul68980082003-03-25 05:07:42 +00001112 ospf_ia_routing (ospf, new_table, new_rtrs);
paul718e3742002-12-13 20:15:29 +00001113
1114 ospf_prune_unreachable_networks (new_table);
1115 ospf_prune_unreachable_routers (new_rtrs);
1116
1117 /* AS-external-LSA calculation should not be performed here. */
1118
1119 /* If new Router Route is installed,
1120 then schedule re-calculate External routes. */
1121 if (1)
paul68980082003-03-25 05:07:42 +00001122 ospf_ase_calculate_schedule (ospf);
paul718e3742002-12-13 20:15:29 +00001123
paul68980082003-03-25 05:07:42 +00001124 ospf_ase_calculate_timer_add (ospf);
paul718e3742002-12-13 20:15:29 +00001125
1126 /* Update routing table. */
paul68980082003-03-25 05:07:42 +00001127 ospf_route_install (ospf, new_table);
paul718e3742002-12-13 20:15:29 +00001128
1129 /* Update ABR/ASBR routing table */
paul68980082003-03-25 05:07:42 +00001130 if (ospf->old_rtrs)
paul718e3742002-12-13 20:15:29 +00001131 {
1132 /* old_rtrs's node holds linked list of ospf_route. --kunihiro. */
paul68980082003-03-25 05:07:42 +00001133 /* ospf_route_delete (ospf->old_rtrs); */
1134 ospf_rtrs_free (ospf->old_rtrs);
paul718e3742002-12-13 20:15:29 +00001135 }
1136
paul68980082003-03-25 05:07:42 +00001137 ospf->old_rtrs = ospf->new_rtrs;
1138 ospf->new_rtrs = new_rtrs;
paul718e3742002-12-13 20:15:29 +00001139
paul0c0f9cd2003-06-06 23:27:04 +00001140 if (IS_OSPF_ABR (ospf))
paul68980082003-03-25 05:07:42 +00001141 ospf_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001142
1143 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001144 zlog_debug ("SPF: calculation complete");
paul718e3742002-12-13 20:15:29 +00001145
1146 return 0;
1147}
1148
1149/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
1150 set timer for SPF calc. */
1151void
paul68980082003-03-25 05:07:42 +00001152ospf_spf_calculate_schedule (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00001153{
pauld24f6e22005-10-21 09:23:12 +00001154 unsigned long delay, elapsed, ht;
1155 struct timeval result;
paul718e3742002-12-13 20:15:29 +00001156
1157 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001158 zlog_debug ("SPF: calculation timer scheduled");
paul718e3742002-12-13 20:15:29 +00001159
1160 /* OSPF instance does not exist. */
paul68980082003-03-25 05:07:42 +00001161 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001162 return;
pauld24f6e22005-10-21 09:23:12 +00001163
paul718e3742002-12-13 20:15:29 +00001164 /* SPF calculation timer is already scheduled. */
paul68980082003-03-25 05:07:42 +00001165 if (ospf->t_spf_calc)
paul718e3742002-12-13 20:15:29 +00001166 {
1167 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001168 zlog_debug ("SPF: calculation timer is already scheduled: %p",
paul0c0f9cd2003-06-06 23:27:04 +00001169 ospf->t_spf_calc);
paul718e3742002-12-13 20:15:29 +00001170 return;
1171 }
pauld24f6e22005-10-21 09:23:12 +00001172
1173 /* XXX Monotic timers: we only care about relative time here. */
1174 timersub (&recent_time, &ospf->ts_spf, &result);
1175
1176 elapsed = (result.tv_sec * 1000) + (result.tv_usec / 1000);
1177 ht = ospf->spf_holdtime * ospf->spf_hold_multiplier;
1178
1179 if (ht > ospf->spf_max_holdtime)
1180 ht = ospf->spf_max_holdtime;
1181
paul718e3742002-12-13 20:15:29 +00001182 /* Get SPF calculation delay time. */
pauld24f6e22005-10-21 09:23:12 +00001183 if (elapsed < ht)
paul718e3742002-12-13 20:15:29 +00001184 {
pauld24f6e22005-10-21 09:23:12 +00001185 /* Got an event within the hold time of last SPF. We need to
1186 * increase the hold_multiplier, if it's not already at/past
1187 * maximum value, and wasn't already increased..
1188 */
1189 if (ht < ospf->spf_max_holdtime)
1190 ospf->spf_hold_multiplier++;
1191
1192 /* always honour the SPF initial delay */
1193 if ( (ht - elapsed) < ospf->spf_delay)
paul0c0f9cd2003-06-06 23:27:04 +00001194 delay = ospf->spf_delay;
paul718e3742002-12-13 20:15:29 +00001195 else
pauld24f6e22005-10-21 09:23:12 +00001196 delay = ht - elapsed;
paul718e3742002-12-13 20:15:29 +00001197 }
1198 else
pauld24f6e22005-10-21 09:23:12 +00001199 {
1200 /* Event is past required hold-time of last SPF */
1201 delay = ospf->spf_delay;
1202 ospf->spf_hold_multiplier = 1;
1203 }
1204
paul718e3742002-12-13 20:15:29 +00001205 if (IS_DEBUG_OSPF_EVENT)
pauld24f6e22005-10-21 09:23:12 +00001206 zlog_debug ("SPF: calculation timer delay = %ld", delay);
1207
paul68980082003-03-25 05:07:42 +00001208 ospf->t_spf_calc =
pauld24f6e22005-10-21 09:23:12 +00001209 thread_add_timer_msec (master, ospf_spf_calculate_timer, ospf, delay);
paul718e3742002-12-13 20:15:29 +00001210}