blob: dbd06361285d4bcc4aa5c5078a02860c1f219086 [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
paul58e1bef2005-11-11 12:10:03 +000097 /* router vertices through an attached network each
98 * have a distinct (canonical / not inherited) nexthop
99 * which must be freed.
100 *
101 * A network vertex can only have router vertices as its
102 * children, so only one level of recursion is possible.
103 */
pauleb3da6d2005-10-18 04:20:33 +0000104 if (child->type == OSPF_VERTEX_NETWORK)
105 ospf_canonical_nexthops_free (child);
106
paul58e1bef2005-11-11 12:10:03 +0000107 /* Free child nexthops pointing back to this root vertex */
pauleb3da6d2005-10-18 04:20:33 +0000108 for (ALL_LIST_ELEMENTS (child->parents, n2, nn2, vp))
paul58e1bef2005-11-11 12:10:03 +0000109 if (vp->parent == root)
110 vertex_nexthop_free (vp->nexthop);
pauleb3da6d2005-10-18 04:20:33 +0000111 }
112}
113
114static struct vertex_parent *
115vertex_parent_new (struct vertex *v, int backlink, struct vertex_nexthop *hop)
116{
117 struct vertex_parent *new;
118
119 new = XMALLOC (MTYPE_OSPF_VERTEX_PARENT, sizeof (struct vertex_parent));
120
121 if (new == NULL)
122 return NULL;
123
124 new->parent = v;
125 new->backlink = backlink;
126 new->nexthop = hop;
paul718e3742002-12-13 20:15:29 +0000127 return new;
128}
paul0c0f9cd2003-06-06 23:27:04 +0000129
pauleb3da6d2005-10-18 04:20:33 +0000130static void
131vertex_parent_free (struct vertex_parent *p)
132{
133 XFREE (MTYPE_OSPF_VERTEX_PARENT, p);
134}
135
paul4dadc292005-05-06 21:37:42 +0000136static struct vertex *
paul718e3742002-12-13 20:15:29 +0000137ospf_vertex_new (struct ospf_lsa *lsa)
138{
139 struct vertex *new;
140
pauleb3da6d2005-10-18 04:20:33 +0000141 new = XCALLOC (MTYPE_OSPF_VERTEX, sizeof (struct vertex));
paul718e3742002-12-13 20:15:29 +0000142
143 new->flags = 0;
hasso462f20d2005-02-23 11:29:02 +0000144 new->stat = &(lsa->stat);
paul718e3742002-12-13 20:15:29 +0000145 new->type = lsa->data->type;
146 new->id = lsa->data->id;
147 new->lsa = lsa->data;
148 new->distance = 0;
pauleb3da6d2005-10-18 04:20:33 +0000149 new->children = list_new ();
150 new->parents = list_new ();
151
paul718e3742002-12-13 20:15:29 +0000152 return new;
153}
154
pauleb3da6d2005-10-18 04:20:33 +0000155/* Recursively free the given vertex and all its children
156 * and associated parent and nexthop information
157 * Parent should indicate which parent is trying to free this child,
158 * NULL parent is only valid for the root vertex.
159 */
paul4dadc292005-05-06 21:37:42 +0000160static void
pauleb3da6d2005-10-18 04:20:33 +0000161ospf_vertex_free (struct vertex *v, const struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +0000162{
paul1eb8ef22005-04-07 07:30:20 +0000163 struct listnode *node, *nnode;
pauleb3da6d2005-10-18 04:20:33 +0000164 struct vertex *vc;
paul7461d452005-06-13 13:57:16 +0000165
pauleb3da6d2005-10-18 04:20:33 +0000166 assert (*(v->stat) == LSA_SPF_IN_SPFTREE);
167
168 /* recurse down the tree, freeing furthest children first */
169 if (v->children)
170 {
171 for (ALL_LIST_ELEMENTS (v->children, node, nnode, vc))
172 ospf_vertex_free (vc, area);
173
174 list_delete (v->children);
175 v->children = NULL;
176 }
177
178 /* The vertex itself can only be freed when the last remaining parent
179 * with a reference to this vertex frees this vertex. Until then, we
180 * just cleanup /one/ parent association (doesnt matter which) -
181 * essentially using the parents list as a refcount.
182 */
183 if (listcount (v->parents) > 0)
184 {
185 vertex_parent_free (listgetdata (listhead (v->parents)));
186 list_delete_node (v->parents, listhead (v->parents));
paul718e3742002-12-13 20:15:29 +0000187
pauleb3da6d2005-10-18 04:20:33 +0000188 if (listcount (v->parents) > 0)
189 return; /* there are still parent references left */
190 }
191
192 list_delete (v->parents);
193 v->parents = NULL;
194
195 v->lsa = NULL;
paul7461d452005-06-13 13:57:16 +0000196
paul718e3742002-12-13 20:15:29 +0000197 XFREE (MTYPE_OSPF_VERTEX, v);
198}
199
paul4dadc292005-05-06 21:37:42 +0000200static void
hassoeb1ce602004-10-08 08:17:22 +0000201ospf_vertex_dump(const char *msg, struct vertex *v,
pauleb3da6d2005-10-18 04:20:33 +0000202 int print_parents, int print_children)
gdt630e4802004-08-31 17:28:41 +0000203{
204 if ( ! IS_DEBUG_OSPF_EVENT)
205 return;
206
pauleb3da6d2005-10-18 04:20:33 +0000207 zlog_debug("%s %s vertex %s distance %u flags %u",
gdt630e4802004-08-31 17:28:41 +0000208 msg,
209 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
210 inet_ntoa(v->lsa->id),
211 v->distance,
gdt630e4802004-08-31 17:28:41 +0000212 (unsigned int)v->flags);
213
pauleb3da6d2005-10-18 04:20:33 +0000214 if (print_parents)
gdt630e4802004-08-31 17:28:41 +0000215 {
paul1eb8ef22005-04-07 07:30:20 +0000216 struct listnode *node;
pauleb3da6d2005-10-18 04:20:33 +0000217 struct vertex_parent *vp;
paul1eb8ef22005-04-07 07:30:20 +0000218
pauleb3da6d2005-10-18 04:20:33 +0000219 for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
gdt630e4802004-08-31 17:28:41 +0000220 {
221 char buf1[BUFSIZ];
pauleb3da6d2005-10-18 04:20:33 +0000222
223 if (vp)
gdt630e4802004-08-31 17:28:41 +0000224 {
pauleb3da6d2005-10-18 04:20:33 +0000225 zlog_debug ("parent %s backlink %d nexthop %s interface %s",
226 inet_ntoa(vp->parent->lsa->id), vp->backlink,
227 inet_ntop(AF_INET, &vp->nexthop->router, buf1, BUFSIZ),
228 vp->nexthop->oi ? IF_NAME(vp->nexthop->oi) : "NULL");
gdt630e4802004-08-31 17:28:41 +0000229 }
230 }
231 }
232
233 if (print_children)
234 {
hasso52dc7ee2004-09-23 19:18:23 +0000235 struct listnode *cnode;
paul1eb8ef22005-04-07 07:30:20 +0000236 struct vertex *cv;
237
pauleb3da6d2005-10-18 04:20:33 +0000238 for (ALL_LIST_ELEMENTS_RO (v->children, cnode, cv))
paul1eb8ef22005-04-07 07:30:20 +0000239 ospf_vertex_dump(" child:", cv, 0, 0);
gdt630e4802004-08-31 17:28:41 +0000240 }
241}
242
243
244/* Add a vertex to the list of children in each of its parents. */
paul4dadc292005-05-06 21:37:42 +0000245static void
paul718e3742002-12-13 20:15:29 +0000246ospf_vertex_add_parent (struct vertex *v)
247{
pauleb3da6d2005-10-18 04:20:33 +0000248 struct vertex_parent *vp;
hasso52dc7ee2004-09-23 19:18:23 +0000249 struct listnode *node;
paul7461d452005-06-13 13:57:16 +0000250
pauleb3da6d2005-10-18 04:20:33 +0000251 assert (v && v->children);
paul7461d452005-06-13 13:57:16 +0000252
pauleb3da6d2005-10-18 04:20:33 +0000253 for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
paul718e3742002-12-13 20:15:29 +0000254 {
pauleb3da6d2005-10-18 04:20:33 +0000255 assert (vp->parent && vp->parent->children);
paul7461d452005-06-13 13:57:16 +0000256
paul718e3742002-12-13 20:15:29 +0000257 /* No need to add two links from the same parent. */
pauleb3da6d2005-10-18 04:20:33 +0000258 if (listnode_lookup (vp->parent->children, v) == NULL)
259 listnode_add (vp->parent->children, v);
paul718e3742002-12-13 20:15:29 +0000260 }
261}
262
paul4dadc292005-05-06 21:37:42 +0000263static void
paul718e3742002-12-13 20:15:29 +0000264ospf_spf_init (struct ospf_area *area)
265{
266 struct vertex *v;
267
268 /* Create root node. */
269 v = ospf_vertex_new (area->router_lsa_self);
270
271 area->spf = v;
272
273 /* Reset ABR and ASBR router counts. */
274 area->abr_count = 0;
275 area->asbr_count = 0;
276}
277
pauld355bfa2004-04-08 07:43:45 +0000278/* return index of link back to V from W, or -1 if no link found */
paul4dadc292005-05-06 21:37:42 +0000279static int
paul718e3742002-12-13 20:15:29 +0000280ospf_lsa_has_link (struct lsa_header *w, struct lsa_header *v)
281{
hassoeb1ce602004-10-08 08:17:22 +0000282 unsigned int i, length;
paul718e3742002-12-13 20:15:29 +0000283 struct router_lsa *rl;
284 struct network_lsa *nl;
285
286 /* In case of W is Network LSA. */
287 if (w->type == OSPF_NETWORK_LSA)
288 {
289 if (v->type == OSPF_NETWORK_LSA)
pauld355bfa2004-04-08 07:43:45 +0000290 return -1;
paul718e3742002-12-13 20:15:29 +0000291
292 nl = (struct network_lsa *) w;
293 length = (ntohs (w->length) - OSPF_LSA_HEADER_SIZE - 4) / 4;
paul0c0f9cd2003-06-06 23:27:04 +0000294
paul718e3742002-12-13 20:15:29 +0000295 for (i = 0; i < length; i++)
296 if (IPV4_ADDR_SAME (&nl->routers[i], &v->id))
pauld355bfa2004-04-08 07:43:45 +0000297 return i;
298 return -1;
paul718e3742002-12-13 20:15:29 +0000299 }
300
301 /* In case of W is Router LSA. */
302 if (w->type == OSPF_ROUTER_LSA)
303 {
304 rl = (struct router_lsa *) w;
305
306 length = ntohs (w->length);
307
308 for (i = 0;
paul0c0f9cd2003-06-06 23:27:04 +0000309 i < ntohs (rl->links) && length >= sizeof (struct router_lsa);
310 i++, length -= 12)
paul718e3742002-12-13 20:15:29 +0000311 {
312 switch (rl->link[i].type)
313 {
314 case LSA_LINK_TYPE_POINTOPOINT:
315 case LSA_LINK_TYPE_VIRTUALLINK:
316 /* Router LSA ID. */
317 if (v->type == OSPF_ROUTER_LSA &&
318 IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
319 {
pauld355bfa2004-04-08 07:43:45 +0000320 return i;
paul718e3742002-12-13 20:15:29 +0000321 }
322 break;
323 case LSA_LINK_TYPE_TRANSIT:
324 /* Network LSA ID. */
325 if (v->type == OSPF_NETWORK_LSA &&
326 IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
327 {
pauld355bfa2004-04-08 07:43:45 +0000328 return i;
paul0c0f9cd2003-06-06 23:27:04 +0000329 }
paul718e3742002-12-13 20:15:29 +0000330 break;
331 case LSA_LINK_TYPE_STUB:
pauleb3da6d2005-10-18 04:20:33 +0000332 /* Stub can't lead anywhere, carry on */
paul718e3742002-12-13 20:15:29 +0000333 continue;
334 default:
335 break;
336 }
337 }
338 }
pauld355bfa2004-04-08 07:43:45 +0000339 return -1;
paul718e3742002-12-13 20:15:29 +0000340}
341
paul718e3742002-12-13 20:15:29 +0000342#define ROUTER_LSA_MIN_SIZE 12
343#define ROUTER_LSA_TOS_SIZE 4
344
gdt630e4802004-08-31 17:28:41 +0000345/* Find the next link after prev_link from v to w. If prev_link is
346 * NULL, return the first link from v to w. Ignore stub and virtual links;
347 * these link types will never be returned.
348 */
paul4dadc292005-05-06 21:37:42 +0000349static struct router_lsa_link *
paul718e3742002-12-13 20:15:29 +0000350ospf_get_next_link (struct vertex *v, struct vertex *w,
paul0c0f9cd2003-06-06 23:27:04 +0000351 struct router_lsa_link *prev_link)
paul718e3742002-12-13 20:15:29 +0000352{
353 u_char *p;
354 u_char *lim;
355 struct router_lsa_link *l;
356
357 if (prev_link == NULL)
gdt630e4802004-08-31 17:28:41 +0000358 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +0000359 else
360 {
paul0c0f9cd2003-06-06 23:27:04 +0000361 p = (u_char *) prev_link;
paul718e3742002-12-13 20:15:29 +0000362 p += (ROUTER_LSA_MIN_SIZE +
363 (prev_link->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
364 }
paul0c0f9cd2003-06-06 23:27:04 +0000365
paul718e3742002-12-13 20:15:29 +0000366 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
367
368 while (p < lim)
369 {
370 l = (struct router_lsa_link *) p;
371
paul0c0f9cd2003-06-06 23:27:04 +0000372 p += (ROUTER_LSA_MIN_SIZE + (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
paul718e3742002-12-13 20:15:29 +0000373
374 if (l->m[0].type == LSA_LINK_TYPE_STUB)
375 continue;
376
377 /* Defer NH calculation via VLs until summaries from
378 transit areas area confidered */
379
380 if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK)
paul0c0f9cd2003-06-06 23:27:04 +0000381 continue;
paul718e3742002-12-13 20:15:29 +0000382
383 if (IPV4_ADDR_SAME (&l->link_id, &w->id))
paul0c0f9cd2003-06-06 23:27:04 +0000384 return l;
paul718e3742002-12-13 20:15:29 +0000385 }
386
387 return NULL;
388}
389
paul75ee0b82004-08-05 09:10:31 +0000390/*
391 * Consider supplied next-hop for inclusion to the supplied list of
392 * equal-cost next-hops, adjust list as neccessary.
393 *
394 * (Discussed on GNU Zebra list 27 May 2003, [zebra 19184])
395 *
396 * Note that below is a bit of a hack, and limits ECMP to paths that go to
397 * same nexthop. Where as paths via inequal output_cost interfaces could
398 * still quite easily be ECMP due to remote cost differences.
399 *
400 * TODO: It really should be done by way of recording currently valid
401 * backlinks and determining the appropriate nexthops from the list of
402 * backlinks, or even simpler, just flushing nexthop list if we find a lower
403 * cost path to a candidate vertex in SPF, maybe.
paulbf9392c2003-06-06 23:23:36 +0000404 */
paul4dadc292005-05-06 21:37:42 +0000405static void
pauleb3da6d2005-10-18 04:20:33 +0000406ospf_spf_add_parent (struct vertex *v, struct vertex *w,
407 struct vertex_nexthop *newhop)
paulbf9392c2003-06-06 23:23:36 +0000408{
pauleb3da6d2005-10-18 04:20:33 +0000409 struct vertex_parent *vp;
410
411 /* we must have a newhop.. */
412 assert (v && w && newhop);
413
414 /* new parent is <= existing parents, add it */
415 vp = vertex_parent_new (v, ospf_lsa_has_link (w->lsa, v->lsa), newhop);
416 listnode_add (w->parents, vp);
paulbf9392c2003-06-06 23:23:36 +0000417
418 return;
419}
420
pauleb3da6d2005-10-18 04:20:33 +0000421static void
422ospf_spf_flush_parents (struct vertex *w)
423{
424 struct vertex_parent *vp;
425 struct listnode *ln, *nn;
426
427 /* delete the existing nexthops */
428 for (ALL_LIST_ELEMENTS (w->parents, ln, nn, vp))
429 {
430 list_delete_node (w->parents, ln);
431 vertex_parent_free (vp);
432 }
433}
434
gdt630e4802004-08-31 17:28:41 +0000435/* 16.1.1. Calculate nexthop from root through V (parent) to
436 * vertex W (destination).
pauleb3da6d2005-10-18 04:20:33 +0000437 *
438 * The link must be supplied if V is the root vertex. In all other cases
439 * it may be NULL.
gdt630e4802004-08-31 17:28:41 +0000440 */
paul4dadc292005-05-06 21:37:42 +0000441static void
pauleb3da6d2005-10-18 04:20:33 +0000442ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v,
443 struct vertex *w, struct router_lsa_link *l)
paul718e3742002-12-13 20:15:29 +0000444{
paul1eb8ef22005-04-07 07:30:20 +0000445 struct listnode *node, *nnode;
pauleb3da6d2005-10-18 04:20:33 +0000446 struct vertex_nexthop *nh;
447 struct vertex_parent *vp;
paul718e3742002-12-13 20:15:29 +0000448 struct ospf_interface *oi = NULL;
paul0c0f9cd2003-06-06 23:27:04 +0000449
paul718e3742002-12-13 20:15:29 +0000450 if (IS_DEBUG_OSPF_EVENT)
gdt630e4802004-08-31 17:28:41 +0000451 {
ajs2a42e282004-12-08 18:43:03 +0000452 zlog_debug ("ospf_nexthop_calculation(): Start");
gdt630e4802004-08-31 17:28:41 +0000453 ospf_vertex_dump("V (parent):", v, 1, 1);
454 ospf_vertex_dump("W (dest) :", w, 1, 1);
455 }
paul718e3742002-12-13 20:15:29 +0000456
paul718e3742002-12-13 20:15:29 +0000457 if (v == area->spf)
458 {
gdt630e4802004-08-31 17:28:41 +0000459 /* 16.1.1 para 4. In the first case, the parent vertex (V) is the
460 root (the calculating router itself). This means that the
461 destination is either a directly connected network or directly
462 connected router. The outgoing interface in this case is simply
463 the OSPF interface connecting to the destination network/router.
464 */
465
paul718e3742002-12-13 20:15:29 +0000466 if (w->type == OSPF_VERTEX_ROUTER)
paul0c0f9cd2003-06-06 23:27:04 +0000467 {
pauleb3da6d2005-10-18 04:20:33 +0000468 /* l is a link from v to w
469 * l2 will be link from w to v
470 */
471 struct router_lsa_link *l2 = NULL;
472
473 /* we *must* be supplied with the link data */
474 assert (l != NULL);
475
476 if (IS_DEBUG_OSPF_EVENT)
paul0c0f9cd2003-06-06 23:27:04 +0000477 {
pauleb3da6d2005-10-18 04:20:33 +0000478 char buf1[BUFSIZ];
479 char buf2[BUFSIZ];
480
481 zlog_debug("ospf_nexthop_calculation(): considering link "
482 "type %d link_id %s link_data %s",
483 l->m[0].type,
484 inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ),
485 inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ));
486 }
paul0c0f9cd2003-06-06 23:27:04 +0000487
pauleb3da6d2005-10-18 04:20:33 +0000488 if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT)
489 {
490 /* If the destination is a router which connects to
491 the calculating router via a Point-to-MultiPoint
492 network, the destination's next hop IP address(es)
493 can be determined by examining the destination's
494 router-LSA: each link pointing back to the
495 calculating router and having a Link Data field
496 belonging to the Point-to-MultiPoint network
497 provides an IP address of the next hop router.
gdt630e4802004-08-31 17:28:41 +0000498
pauleb3da6d2005-10-18 04:20:33 +0000499 At this point l is a link from V to W, and V is the
500 root ("us"). Find the local interface associated
501 with l (its address is in l->link_data). If it
502 is a point-to-multipoint interface, then look through
503 the links in the opposite direction (W to V). If
504 any of them have an address that lands within the
505 subnet declared by the PtMP link, then that link
506 is a constituent of the PtMP link, and its address is
507 a nexthop address for V.
508 */
509 oi = ospf_if_is_configured (area->ospf, &l->link_data);
510 if (oi && oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
paul0c0f9cd2003-06-06 23:27:04 +0000511 {
pauleb3da6d2005-10-18 04:20:33 +0000512 struct prefix_ipv4 la;
gdt630e4802004-08-31 17:28:41 +0000513
pauleb3da6d2005-10-18 04:20:33 +0000514 la.family = AF_INET;
515 la.prefixlen = oi->address->prefixlen;
516
517 /* V links to W on PtMP interface
518 - find the interface address on W */
519 while ((l2 = ospf_get_next_link (w, v, l2)))
paul0c0f9cd2003-06-06 23:27:04 +0000520 {
pauleb3da6d2005-10-18 04:20:33 +0000521 la.prefix = l2->link_data;
gdt630e4802004-08-31 17:28:41 +0000522
pauleb3da6d2005-10-18 04:20:33 +0000523 if (prefix_cmp ((struct prefix *) &la,
524 oi->address) == 0)
525 /* link_data is on our PtMP network */
526 break;
paul0c0f9cd2003-06-06 23:27:04 +0000527 }
pauleb3da6d2005-10-18 04:20:33 +0000528 } /* end l is on point-to-multipoint link */
529 else
530 {
531 /* l is a regular point-to-point link.
532 Look for a link from W to V.
533 */
534 while ((l2 = ospf_get_next_link (w, v, l2)))
paul0c0f9cd2003-06-06 23:27:04 +0000535 {
pauleb3da6d2005-10-18 04:20:33 +0000536 oi = ospf_if_is_configured (area->ospf,
537 &(l2->link_data));
538
539 if (oi == NULL)
540 continue;
541
542 if (!IPV4_ADDR_SAME (&oi->address->u.prefix4,
543 &l->link_data))
544 continue;
545
546 break;
paul0c0f9cd2003-06-06 23:27:04 +0000547 }
pauleb3da6d2005-10-18 04:20:33 +0000548 }
549
550 if (oi && l2)
551 {
552 /* found all necessary info to build nexthop */
553 nh = vertex_nexthop_new ();
554 nh->oi = oi;
555 nh->router = l2->link_data;
556 ospf_spf_add_parent (v, w, nh);
557 }
558 else
559 {
560 zlog_info("ospf_nexthop_calculation(): "
561 "could not determine nexthop for link");
562 }
563 } /* end point-to-point link from V to W */
gdt630e4802004-08-31 17:28:41 +0000564 } /* end W is a Router vertex */
paul718e3742002-12-13 20:15:29 +0000565 else
paul0c0f9cd2003-06-06 23:27:04 +0000566 {
pauleb3da6d2005-10-18 04:20:33 +0000567 assert(w->type == OSPF_VERTEX_NETWORK);
568 oi = ospf_if_is_configured (area->ospf, &(l->link_data));
569 if (oi)
paul0c0f9cd2003-06-06 23:27:04 +0000570 {
pauleb3da6d2005-10-18 04:20:33 +0000571 nh = vertex_nexthop_new ();
572 nh->oi = oi;
573 nh->router.s_addr = 0;
574 ospf_spf_add_parent (v, w, nh);
paul0c0f9cd2003-06-06 23:27:04 +0000575 }
576 }
paul718e3742002-12-13 20:15:29 +0000577 return;
gdt630e4802004-08-31 17:28:41 +0000578 } /* end V is the root */
gdt630e4802004-08-31 17:28:41 +0000579 /* Check if W's parent is a network connected to root. */
paul718e3742002-12-13 20:15:29 +0000580 else if (v->type == OSPF_VERTEX_NETWORK)
581 {
gdt630e4802004-08-31 17:28:41 +0000582 /* See if any of V's parents are the root. */
pauleb3da6d2005-10-18 04:20:33 +0000583 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
paul718e3742002-12-13 20:15:29 +0000584 {
pauleb3da6d2005-10-18 04:20:33 +0000585 if (vp->parent == area->spf) /* connects to root? */
gdt630e4802004-08-31 17:28:41 +0000586 {
587 /* 16.1.1 para 5. ...the parent vertex is a network that
588 * directly connects the calculating router to the destination
589 * router. The list of next hops is then determined by
590 * examining the destination's router-LSA...
591 */
592
593 assert(w->type == OSPF_VERTEX_ROUTER);
paul0c0f9cd2003-06-06 23:27:04 +0000594 while ((l = ospf_get_next_link (w, v, l)))
595 {
gdt630e4802004-08-31 17:28:41 +0000596 /* ...For each link in the router-LSA that points back to the
597 * parent network, the link's Link Data field provides the IP
598 * address of a next hop router. The outgoing interface to
599 * use can then be derived from the next hop IP address (or
600 * it can be inherited from the parent network).
601 */
pauleb3da6d2005-10-18 04:20:33 +0000602 nh = vertex_nexthop_new ();
603 nh->oi = vp->nexthop->oi;
604 nh->router = l->link_data;
605 ospf_spf_add_parent (v, w, nh);
paul0c0f9cd2003-06-06 23:27:04 +0000606 }
607 return;
608 }
paul718e3742002-12-13 20:15:29 +0000609 }
610 }
611
gdt630e4802004-08-31 17:28:41 +0000612 /* 16.1.1 para 4. If there is at least one intervening router in the
613 * current shortest path between the destination and the root, the
614 * destination simply inherits the set of next hops from the
615 * parent.
616 */
pauleb3da6d2005-10-18 04:20:33 +0000617 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
618 ospf_spf_add_parent (v, w, vp->nexthop);
paul718e3742002-12-13 20:15:29 +0000619}
620
gdt630e4802004-08-31 17:28:41 +0000621/* RFC2328 Section 16.1 (2).
622 * v is on the SPF tree. Examine the links in v's LSA. Update the list
623 * of candidates with any vertices not already on the list. If a lower-cost
624 * path is found to a vertex already on the candidate list, store the new cost.
625 */
paul4dadc292005-05-06 21:37:42 +0000626static void
paul718e3742002-12-13 20:15:29 +0000627ospf_spf_next (struct vertex *v, struct ospf_area *area,
hasso462f20d2005-02-23 11:29:02 +0000628 struct pqueue * candidate)
paul718e3742002-12-13 20:15:29 +0000629{
630 struct ospf_lsa *w_lsa = NULL;
paul718e3742002-12-13 20:15:29 +0000631 u_char *p;
632 u_char *lim;
633 struct router_lsa_link *l = NULL;
634 struct in_addr *r;
paul718e3742002-12-13 20:15:29 +0000635 int type = 0;
636
637 /* If this is a router-LSA, and bit V of the router-LSA (see Section
638 A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE. */
639 if (v->type == OSPF_VERTEX_ROUTER)
640 {
641 if (IS_ROUTER_LSA_VIRTUAL ((struct router_lsa *) v->lsa))
642 area->transit = OSPF_TRANSIT_TRUE;
643 }
644
645 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul0c0f9cd2003-06-06 23:27:04 +0000646 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
647
paul718e3742002-12-13 20:15:29 +0000648 while (p < lim)
649 {
pauleb3da6d2005-10-18 04:20:33 +0000650 struct vertex *w;
651 unsigned int distance;
pauld355bfa2004-04-08 07:43:45 +0000652
paul718e3742002-12-13 20:15:29 +0000653 /* In case of V is Router-LSA. */
654 if (v->lsa->type == OSPF_ROUTER_LSA)
655 {
656 l = (struct router_lsa_link *) p;
657
paul0c0f9cd2003-06-06 23:27:04 +0000658 p += (ROUTER_LSA_MIN_SIZE +
paul718e3742002-12-13 20:15:29 +0000659 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
660
661 /* (a) If this is a link to a stub network, examine the next
662 link in V's LSA. Links to stub networks will be
663 considered in the second stage of the shortest path
664 calculation. */
665 if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB)
666 continue;
667
668 /* (b) Otherwise, W is a transit vertex (router or transit
669 network). Look up the vertex W's LSA (router-LSA or
670 network-LSA) in Area A's link state database. */
671 switch (type)
672 {
673 case LSA_LINK_TYPE_POINTOPOINT:
674 case LSA_LINK_TYPE_VIRTUALLINK:
675 if (type == LSA_LINK_TYPE_VIRTUALLINK)
paul0c0f9cd2003-06-06 23:27:04 +0000676 {
677 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000678 zlog_debug ("looking up LSA through VL: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000679 inet_ntoa (l->link_id));
680 }
paul718e3742002-12-13 20:15:29 +0000681
682 w_lsa = ospf_lsa_lookup (area, OSPF_ROUTER_LSA, l->link_id,
683 l->link_id);
684 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000685 {
686 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000687 zlog_debug ("found Router LSA %s", inet_ntoa (l->link_id));
paul0c0f9cd2003-06-06 23:27:04 +0000688 }
paul718e3742002-12-13 20:15:29 +0000689 break;
690 case LSA_LINK_TYPE_TRANSIT:
paul0c0f9cd2003-06-06 23:27:04 +0000691 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000692 zlog_debug ("Looking up Network LSA, ID: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000693 inet_ntoa (l->link_id));
paul718e3742002-12-13 20:15:29 +0000694 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_NETWORK_LSA,
paul0c0f9cd2003-06-06 23:27:04 +0000695 l->link_id);
paul718e3742002-12-13 20:15:29 +0000696 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000697 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000698 zlog_debug ("found the LSA");
paul718e3742002-12-13 20:15:29 +0000699 break;
700 default:
paul0c0f9cd2003-06-06 23:27:04 +0000701 zlog_warn ("Invalid LSA link type %d", type);
paul718e3742002-12-13 20:15:29 +0000702 continue;
703 }
704 }
705 else
706 {
707 /* In case of V is Network-LSA. */
paul0c0f9cd2003-06-06 23:27:04 +0000708 r = (struct in_addr *) p;
paul718e3742002-12-13 20:15:29 +0000709 p += sizeof (struct in_addr);
710
711 /* Lookup the vertex W's LSA. */
712 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_ROUTER_LSA, *r);
713 }
714
715 /* (b cont.) If the LSA does not exist, or its LS age is equal
716 to MaxAge, or it does not have a link back to vertex V,
717 examine the next link in V's LSA.[23] */
718 if (w_lsa == NULL)
719 continue;
720
721 if (IS_LSA_MAXAGE (w_lsa))
722 continue;
723
pauleb3da6d2005-10-18 04:20:33 +0000724 if (ospf_lsa_has_link (w_lsa->data, v->lsa) < 0 )
paul718e3742002-12-13 20:15:29 +0000725 {
paul0c0f9cd2003-06-06 23:27:04 +0000726 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000727 zlog_debug ("The LSA doesn't have a link back");
paul718e3742002-12-13 20:15:29 +0000728 continue;
729 }
730
731 /* (c) If vertex W is already on the shortest-path tree, examine
732 the next link in the LSA. */
hasso462f20d2005-02-23 11:29:02 +0000733 if (w_lsa->stat == LSA_SPF_IN_SPFTREE)
734 {
735 if (IS_DEBUG_OSPF_EVENT)
736 zlog_debug ("The LSA is already in SPF");
737 continue;
738 }
paul718e3742002-12-13 20:15:29 +0000739
740 /* (d) Calculate the link state cost D of the resulting path
741 from the root to vertex W. D is equal to the sum of the link
742 state cost of the (already calculated) shortest path to
743 vertex V and the advertised cost of the link between vertices
744 V and W. If D is: */
745
paul718e3742002-12-13 20:15:29 +0000746 /* calculate link cost D. */
747 if (v->lsa->type == OSPF_ROUTER_LSA)
pauleb3da6d2005-10-18 04:20:33 +0000748 distance = v->distance + ntohs (l->m[0].metric);
gdt630e4802004-08-31 17:28:41 +0000749 else /* v is not a Router-LSA */
pauleb3da6d2005-10-18 04:20:33 +0000750 distance = v->distance;
paul718e3742002-12-13 20:15:29 +0000751
752 /* Is there already vertex W in candidate list? */
hasso462f20d2005-02-23 11:29:02 +0000753 if (w_lsa->stat == LSA_SPF_NOT_EXPLORED)
754 {
pauleb3da6d2005-10-18 04:20:33 +0000755 /* prepare vertex W. */
756 w = ospf_vertex_new (w_lsa);
757
hasso462f20d2005-02-23 11:29:02 +0000758 /* Calculate nexthop to W. */
pauleb3da6d2005-10-18 04:20:33 +0000759 w->distance = distance;
760 ospf_nexthop_calculation (area, v, w, l);
hasso462f20d2005-02-23 11:29:02 +0000761 pqueue_enqueue (w, candidate);
762 }
763 else if (w_lsa->stat >= 0)
764 {
765 /* Get the vertex from candidates. */
pauleb3da6d2005-10-18 04:20:33 +0000766 w = candidate->array[w_lsa->stat];
paul718e3742002-12-13 20:15:29 +0000767
hasso462f20d2005-02-23 11:29:02 +0000768 /* if D is greater than. */
pauleb3da6d2005-10-18 04:20:33 +0000769 if (w->distance < distance)
paul718e3742002-12-13 20:15:29 +0000770 {
paul718e3742002-12-13 20:15:29 +0000771 continue;
772 }
hasso462f20d2005-02-23 11:29:02 +0000773 /* equal to. */
pauleb3da6d2005-10-18 04:20:33 +0000774 else if (w->distance == distance)
paul718e3742002-12-13 20:15:29 +0000775 {
pauleb3da6d2005-10-18 04:20:33 +0000776 /* Found an equal-cost path to W.
777 * Calculate nexthop of to W from V. */
778 ospf_nexthop_calculation (area, v, w, l);
paul718e3742002-12-13 20:15:29 +0000779 }
hasso462f20d2005-02-23 11:29:02 +0000780 /* less than. */
781 else
paul718e3742002-12-13 20:15:29 +0000782 {
pauleb3da6d2005-10-18 04:20:33 +0000783 /* Found a lower-cost path to W. */
784 w->distance = distance;
785
786 /* Flush existing parent list from W */
787 ospf_spf_flush_parents (w);
788
789 /* Calculate new nexthop(s) to W. */
790 ospf_nexthop_calculation (area, v, w, l);
paul718e3742002-12-13 20:15:29 +0000791
hasso462f20d2005-02-23 11:29:02 +0000792 /* Decrease the key of the node in the heap, re-sort the heap. */
793 trickle_down (w_lsa->stat, candidate);
paul718e3742002-12-13 20:15:29 +0000794 }
gdt630e4802004-08-31 17:28:41 +0000795 } /* end W is already on the candidate list */
796 } /* end loop over the links in V's LSA */
paul718e3742002-12-13 20:15:29 +0000797}
798
paul4dadc292005-05-06 21:37:42 +0000799static void
paul718e3742002-12-13 20:15:29 +0000800ospf_spf_dump (struct vertex *v, int i)
801{
hasso52dc7ee2004-09-23 19:18:23 +0000802 struct listnode *cnode;
803 struct listnode *nnode;
pauleb3da6d2005-10-18 04:20:33 +0000804 struct vertex_parent *parent;
paul718e3742002-12-13 20:15:29 +0000805
806 if (v->type == OSPF_VERTEX_ROUTER)
807 {
808 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000809 zlog_debug ("SPF Result: %d [R] %s", i, inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000810 }
811 else
812 {
813 struct network_lsa *lsa = (struct network_lsa *) v->lsa;
814 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000815 zlog_debug ("SPF Result: %d [N] %s/%d", i, inet_ntoa (v->lsa->id),
paul0c0f9cd2003-06-06 23:27:04 +0000816 ip_masklen (lsa->mask));
gdt630e4802004-08-31 17:28:41 +0000817 }
paul718e3742002-12-13 20:15:29 +0000818
paul1eb8ef22005-04-07 07:30:20 +0000819 if (IS_DEBUG_OSPF_EVENT)
pauleb3da6d2005-10-18 04:20:33 +0000820 for (ALL_LIST_ELEMENTS_RO (v->parents, nnode, parent))
821 {
822 zlog_debug (" nexthop %p %s %s",
823 parent->nexthop,
824 inet_ntoa (parent->nexthop->router),
825 parent->nexthop->oi ? IF_NAME(parent->nexthop->oi)
826 : "NULL");
827 }
paul718e3742002-12-13 20:15:29 +0000828
829 i++;
830
pauleb3da6d2005-10-18 04:20:33 +0000831 for (ALL_LIST_ELEMENTS_RO (v->children, cnode, v))
paul1eb8ef22005-04-07 07:30:20 +0000832 ospf_spf_dump (v, i);
paul718e3742002-12-13 20:15:29 +0000833}
834
835/* Second stage of SPF calculation. */
paul4dadc292005-05-06 21:37:42 +0000836static void
paul0c0f9cd2003-06-06 23:27:04 +0000837ospf_spf_process_stubs (struct ospf_area *area, struct vertex *v,
paul718e3742002-12-13 20:15:29 +0000838 struct route_table *rt)
839{
paul1eb8ef22005-04-07 07:30:20 +0000840 struct listnode *cnode, *cnnode;
paul718e3742002-12-13 20:15:29 +0000841 struct vertex *child;
842
843 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000844 zlog_debug ("ospf_process_stub():processing stubs for area %s",
paul0c0f9cd2003-06-06 23:27:04 +0000845 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +0000846 if (v->type == OSPF_VERTEX_ROUTER)
847 {
848 u_char *p;
849 u_char *lim;
850 struct router_lsa_link *l;
851 struct router_lsa *rlsa;
852
paul0c0f9cd2003-06-06 23:27:04 +0000853 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000854 zlog_debug ("ospf_process_stubs():processing router LSA, id: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000855 inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000856 rlsa = (struct router_lsa *) v->lsa;
857
858
paul0c0f9cd2003-06-06 23:27:04 +0000859 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000860 zlog_debug ("ospf_process_stubs(): we have %d links to process",
paul0c0f9cd2003-06-06 23:27:04 +0000861 ntohs (rlsa->links));
gdt630e4802004-08-31 17:28:41 +0000862 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +0000863 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
864
865 while (p < lim)
866 {
867 l = (struct router_lsa_link *) p;
868
869 p += (ROUTER_LSA_MIN_SIZE +
870 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
871
872 if (l->m[0].type == LSA_LINK_TYPE_STUB)
873 ospf_intra_add_stub (rt, l, v, area);
874 }
875 }
876
gdt630e4802004-08-31 17:28:41 +0000877 ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1, 1);
paul718e3742002-12-13 20:15:29 +0000878
pauleb3da6d2005-10-18 04:20:33 +0000879 for (ALL_LIST_ELEMENTS (v->children, cnode, cnnode, child))
paul718e3742002-12-13 20:15:29 +0000880 {
paul718e3742002-12-13 20:15:29 +0000881 if (CHECK_FLAG (child->flags, OSPF_VERTEX_PROCESSED))
paul0c0f9cd2003-06-06 23:27:04 +0000882 continue;
paul718e3742002-12-13 20:15:29 +0000883
884 ospf_spf_process_stubs (area, child, rt);
885
886 SET_FLAG (child->flags, OSPF_VERTEX_PROCESSED);
887 }
888}
889
890void
891ospf_rtrs_free (struct route_table *rtrs)
892{
893 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +0000894 struct list *or_list;
paul1eb8ef22005-04-07 07:30:20 +0000895 struct ospf_route *or;
896 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000897
898 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000899 zlog_debug ("Route: Router Routing Table free");
paul718e3742002-12-13 20:15:29 +0000900
901 for (rn = route_top (rtrs); rn; rn = route_next (rn))
902 if ((or_list = rn->info) != NULL)
903 {
paul1eb8ef22005-04-07 07:30:20 +0000904 for (ALL_LIST_ELEMENTS (or_list, node, nnode, or))
905 ospf_route_free (or);
paul718e3742002-12-13 20:15:29 +0000906
paul0c0f9cd2003-06-06 23:27:04 +0000907 list_delete (or_list);
paul718e3742002-12-13 20:15:29 +0000908
paul0c0f9cd2003-06-06 23:27:04 +0000909 /* Unlock the node. */
910 rn->info = NULL;
911 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +0000912 }
913 route_table_finish (rtrs);
914}
915
paul4dadc292005-05-06 21:37:42 +0000916static void
paul718e3742002-12-13 20:15:29 +0000917ospf_rtrs_print (struct route_table *rtrs)
918{
919 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +0000920 struct list *or_list;
921 struct listnode *ln;
922 struct listnode *pnode;
paul718e3742002-12-13 20:15:29 +0000923 struct ospf_route *or;
924 struct ospf_path *path;
925 char buf1[BUFSIZ];
926 char buf2[BUFSIZ];
927
928 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000929 zlog_debug ("ospf_rtrs_print() start");
paul718e3742002-12-13 20:15:29 +0000930
931 for (rn = route_top (rtrs); rn; rn = route_next (rn))
932 if ((or_list = rn->info) != NULL)
paul1eb8ef22005-04-07 07:30:20 +0000933 for (ALL_LIST_ELEMENTS_RO (or_list, ln, or))
paul718e3742002-12-13 20:15:29 +0000934 {
paul718e3742002-12-13 20:15:29 +0000935 switch (or->path_type)
936 {
937 case OSPF_PATH_INTRA_AREA:
paul0c0f9cd2003-06-06 23:27:04 +0000938 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000939 zlog_debug ("%s [%d] area: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000940 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
941 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
942 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +0000943 break;
944 case OSPF_PATH_INTER_AREA:
paul0c0f9cd2003-06-06 23:27:04 +0000945 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000946 zlog_debug ("%s IA [%d] area: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000947 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
948 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
949 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +0000950 break;
951 default:
952 break;
953 }
954
paul1eb8ef22005-04-07 07:30:20 +0000955 for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path))
paul718e3742002-12-13 20:15:29 +0000956 {
paul718e3742002-12-13 20:15:29 +0000957 if (path->nexthop.s_addr == 0)
paul0c0f9cd2003-06-06 23:27:04 +0000958 {
959 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000960 zlog_debug (" directly attached to %s\r\n",
paul0c0f9cd2003-06-06 23:27:04 +0000961 IF_NAME (path->oi));
962 }
963 else
964 {
965 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000966 zlog_debug (" via %s, %s\r\n",
paul0c0f9cd2003-06-06 23:27:04 +0000967 inet_ntoa (path->nexthop), IF_NAME (path->oi));
968 }
paul718e3742002-12-13 20:15:29 +0000969 }
970 }
971
ajs2a42e282004-12-08 18:43:03 +0000972 zlog_debug ("ospf_rtrs_print() end");
paul718e3742002-12-13 20:15:29 +0000973}
974
975/* Calculating the shortest-path tree for an area. */
paul4dadc292005-05-06 21:37:42 +0000976static void
paul0c0f9cd2003-06-06 23:27:04 +0000977ospf_spf_calculate (struct ospf_area *area, struct route_table *new_table,
paul718e3742002-12-13 20:15:29 +0000978 struct route_table *new_rtrs)
979{
hasso462f20d2005-02-23 11:29:02 +0000980 struct pqueue *candidate;
paul718e3742002-12-13 20:15:29 +0000981 struct vertex *v;
pauleb3da6d2005-10-18 04:20:33 +0000982
paul718e3742002-12-13 20:15:29 +0000983 if (IS_DEBUG_OSPF_EVENT)
984 {
ajs2a42e282004-12-08 18:43:03 +0000985 zlog_debug ("ospf_spf_calculate: Start");
986 zlog_debug ("ospf_spf_calculate: running Dijkstra for area %s",
paul0c0f9cd2003-06-06 23:27:04 +0000987 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +0000988 }
989
990 /* Check router-lsa-self. If self-router-lsa is not yet allocated,
991 return this area's calculation. */
paul0c0f9cd2003-06-06 23:27:04 +0000992 if (!area->router_lsa_self)
paul718e3742002-12-13 20:15:29 +0000993 {
994 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000995 zlog_debug ("ospf_spf_calculate: "
paul0c0f9cd2003-06-06 23:27:04 +0000996 "Skip area %s's calculation due to empty router_lsa_self",
997 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +0000998 return;
999 }
1000
1001 /* RFC2328 16.1. (1). */
paul0c0f9cd2003-06-06 23:27:04 +00001002 /* Initialize the algorithm's data structures. */
hasso462f20d2005-02-23 11:29:02 +00001003
1004 /* This function scans all the LSA database and set the stat field to
1005 * LSA_SPF_NOT_EXPLORED. */
1006 ospf_lsdb_clean_stat (area->lsdb);
1007 /* Create a new heap for the candidates. */
1008 candidate = pqueue_create();
1009 candidate->cmp = cmp;
1010 candidate->update = update_stat;
paul718e3742002-12-13 20:15:29 +00001011
1012 /* Initialize the shortest-path tree to only the root (which is the
1013 router doing the calculation). */
1014 ospf_spf_init (area);
1015 v = area->spf;
hasso462f20d2005-02-23 11:29:02 +00001016 /* Set LSA position to LSA_SPF_IN_SPFTREE. This vertex is the root of the
1017 * spanning tree. */
1018 *(v->stat) = LSA_SPF_IN_SPFTREE;
paul718e3742002-12-13 20:15:29 +00001019
1020 /* Set Area A's TransitCapability to FALSE. */
1021 area->transit = OSPF_TRANSIT_FALSE;
1022 area->shortcut_capability = 1;
pauleb3da6d2005-10-18 04:20:33 +00001023
paul718e3742002-12-13 20:15:29 +00001024 for (;;)
1025 {
1026 /* RFC2328 16.1. (2). */
hasso462f20d2005-02-23 11:29:02 +00001027 ospf_spf_next (v, area, candidate);
paul718e3742002-12-13 20:15:29 +00001028
1029 /* RFC2328 16.1. (3). */
1030 /* If at this step the candidate list is empty, the shortest-
1031 path tree (of transit vertices) has been completely built and
1032 this stage of the procedure terminates. */
hasso462f20d2005-02-23 11:29:02 +00001033 if (candidate->size == 0)
paul718e3742002-12-13 20:15:29 +00001034 break;
1035
1036 /* Otherwise, choose the vertex belonging to the candidate list
1037 that is closest to the root, and add it to the shortest-path
1038 tree (removing it from the candidate list in the
paul0c0f9cd2003-06-06 23:27:04 +00001039 process). */
hasso462f20d2005-02-23 11:29:02 +00001040 /* Extract from the candidates the node with the lower key. */
1041 v = (struct vertex *) pqueue_dequeue (candidate);
1042 /* Update stat field in vertex. */
1043 *(v->stat) = LSA_SPF_IN_SPFTREE;
pauleb3da6d2005-10-18 04:20:33 +00001044
paul718e3742002-12-13 20:15:29 +00001045 ospf_vertex_add_parent (v);
1046
paul718e3742002-12-13 20:15:29 +00001047 /* Note that when there is a choice of vertices closest to the
1048 root, network vertices must be chosen before router vertices
1049 in order to necessarily find all equal-cost paths. */
1050 /* We don't do this at this moment, we should add the treatment
1051 above codes. -- kunihiro. */
1052
1053 /* RFC2328 16.1. (4). */
1054 if (v->type == OSPF_VERTEX_ROUTER)
1055 ospf_intra_add_router (new_rtrs, v, area);
paul0c0f9cd2003-06-06 23:27:04 +00001056 else
paul718e3742002-12-13 20:15:29 +00001057 ospf_intra_add_transit (new_table, v, area);
1058
1059 /* RFC2328 16.1. (5). */
1060 /* Iterate the algorithm by returning to Step 2. */
gdt630e4802004-08-31 17:28:41 +00001061
1062 } /* end loop until no more candidate vertices */
paul718e3742002-12-13 20:15:29 +00001063
1064 if (IS_DEBUG_OSPF_EVENT)
1065 {
1066 ospf_spf_dump (area->spf, 0);
1067 ospf_route_table_dump (new_table);
1068 }
1069
1070 /* Second stage of SPF calculation procedure's */
1071 ospf_spf_process_stubs (area, area->spf, new_table);
1072
pauleb3da6d2005-10-18 04:20:33 +00001073 /* Free candidate queue. */
hasso462f20d2005-02-23 11:29:02 +00001074 pqueue_delete (candidate);
pauleb3da6d2005-10-18 04:20:33 +00001075
1076 ospf_vertex_dump (__func__, area->spf, 0, 1);
1077 /* Free nexthop information, canonical versions of which are attached
1078 * the first level of router vertices attached to the root vertex, see
1079 * ospf_nexthop_calculation.
1080 */
1081 ospf_canonical_nexthops_free (area->spf);
1082
1083 /* Free SPF vertices */
1084 ospf_vertex_free (area->spf, area);
1085
paul718e3742002-12-13 20:15:29 +00001086 /* Increment SPF Calculation Counter. */
1087 area->spf_calculation++;
1088
pauld24f6e22005-10-21 09:23:12 +00001089 gettimeofday (&area->ospf->ts_spf, NULL);
paul718e3742002-12-13 20:15:29 +00001090
1091 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001092 zlog_debug ("ospf_spf_calculate: Stop");
paul718e3742002-12-13 20:15:29 +00001093}
1094
1095/* Timer for SPF calculation. */
paul4dadc292005-05-06 21:37:42 +00001096static int
paul68980082003-03-25 05:07:42 +00001097ospf_spf_calculate_timer (struct thread *thread)
paul718e3742002-12-13 20:15:29 +00001098{
paul68980082003-03-25 05:07:42 +00001099 struct ospf *ospf = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +00001100 struct route_table *new_table, *new_rtrs;
paul1eb8ef22005-04-07 07:30:20 +00001101 struct ospf_area *area;
1102 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001103
1104 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001105 zlog_debug ("SPF: Timer (SPF calculation expire)");
paul0c0f9cd2003-06-06 23:27:04 +00001106
paul718e3742002-12-13 20:15:29 +00001107 ospf->t_spf_calc = NULL;
1108
1109 /* Allocate new table tree. */
1110 new_table = route_table_init ();
paul0c0f9cd2003-06-06 23:27:04 +00001111 new_rtrs = route_table_init ();
paul718e3742002-12-13 20:15:29 +00001112
paul68980082003-03-25 05:07:42 +00001113 ospf_vl_unapprove (ospf);
paul718e3742002-12-13 20:15:29 +00001114
1115 /* Calculate SPF for each area. */
paul1eb8ef22005-04-07 07:30:20 +00001116 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
1117 ospf_spf_calculate (area, new_table, new_rtrs);
paul718e3742002-12-13 20:15:29 +00001118
paul68980082003-03-25 05:07:42 +00001119 ospf_vl_shut_unapproved (ospf);
paul718e3742002-12-13 20:15:29 +00001120
paul68980082003-03-25 05:07:42 +00001121 ospf_ia_routing (ospf, new_table, new_rtrs);
paul718e3742002-12-13 20:15:29 +00001122
1123 ospf_prune_unreachable_networks (new_table);
1124 ospf_prune_unreachable_routers (new_rtrs);
1125
1126 /* AS-external-LSA calculation should not be performed here. */
1127
1128 /* If new Router Route is installed,
1129 then schedule re-calculate External routes. */
1130 if (1)
paul68980082003-03-25 05:07:42 +00001131 ospf_ase_calculate_schedule (ospf);
paul718e3742002-12-13 20:15:29 +00001132
paul68980082003-03-25 05:07:42 +00001133 ospf_ase_calculate_timer_add (ospf);
paul718e3742002-12-13 20:15:29 +00001134
1135 /* Update routing table. */
paul68980082003-03-25 05:07:42 +00001136 ospf_route_install (ospf, new_table);
paul718e3742002-12-13 20:15:29 +00001137
1138 /* Update ABR/ASBR routing table */
paul68980082003-03-25 05:07:42 +00001139 if (ospf->old_rtrs)
paul718e3742002-12-13 20:15:29 +00001140 {
1141 /* old_rtrs's node holds linked list of ospf_route. --kunihiro. */
paul68980082003-03-25 05:07:42 +00001142 /* ospf_route_delete (ospf->old_rtrs); */
1143 ospf_rtrs_free (ospf->old_rtrs);
paul718e3742002-12-13 20:15:29 +00001144 }
1145
paul68980082003-03-25 05:07:42 +00001146 ospf->old_rtrs = ospf->new_rtrs;
1147 ospf->new_rtrs = new_rtrs;
paul718e3742002-12-13 20:15:29 +00001148
paul0c0f9cd2003-06-06 23:27:04 +00001149 if (IS_OSPF_ABR (ospf))
paul68980082003-03-25 05:07:42 +00001150 ospf_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001151
1152 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001153 zlog_debug ("SPF: calculation complete");
paul718e3742002-12-13 20:15:29 +00001154
1155 return 0;
1156}
1157
1158/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
1159 set timer for SPF calc. */
1160void
paul68980082003-03-25 05:07:42 +00001161ospf_spf_calculate_schedule (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00001162{
pauld24f6e22005-10-21 09:23:12 +00001163 unsigned long delay, elapsed, ht;
1164 struct timeval result;
paul718e3742002-12-13 20:15:29 +00001165
1166 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001167 zlog_debug ("SPF: calculation timer scheduled");
paul718e3742002-12-13 20:15:29 +00001168
1169 /* OSPF instance does not exist. */
paul68980082003-03-25 05:07:42 +00001170 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001171 return;
pauld24f6e22005-10-21 09:23:12 +00001172
paul718e3742002-12-13 20:15:29 +00001173 /* SPF calculation timer is already scheduled. */
paul68980082003-03-25 05:07:42 +00001174 if (ospf->t_spf_calc)
paul718e3742002-12-13 20:15:29 +00001175 {
1176 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001177 zlog_debug ("SPF: calculation timer is already scheduled: %p",
paul0c0f9cd2003-06-06 23:27:04 +00001178 ospf->t_spf_calc);
paul718e3742002-12-13 20:15:29 +00001179 return;
1180 }
pauld24f6e22005-10-21 09:23:12 +00001181
1182 /* XXX Monotic timers: we only care about relative time here. */
paulc8c15212005-11-04 12:31:39 +00001183 result = tv_sub (recent_time, ospf->ts_spf);
pauld24f6e22005-10-21 09:23:12 +00001184
1185 elapsed = (result.tv_sec * 1000) + (result.tv_usec / 1000);
1186 ht = ospf->spf_holdtime * ospf->spf_hold_multiplier;
1187
1188 if (ht > ospf->spf_max_holdtime)
1189 ht = ospf->spf_max_holdtime;
1190
paul718e3742002-12-13 20:15:29 +00001191 /* Get SPF calculation delay time. */
pauld24f6e22005-10-21 09:23:12 +00001192 if (elapsed < ht)
paul718e3742002-12-13 20:15:29 +00001193 {
pauld24f6e22005-10-21 09:23:12 +00001194 /* Got an event within the hold time of last SPF. We need to
1195 * increase the hold_multiplier, if it's not already at/past
1196 * maximum value, and wasn't already increased..
1197 */
1198 if (ht < ospf->spf_max_holdtime)
1199 ospf->spf_hold_multiplier++;
1200
1201 /* always honour the SPF initial delay */
1202 if ( (ht - elapsed) < ospf->spf_delay)
paul0c0f9cd2003-06-06 23:27:04 +00001203 delay = ospf->spf_delay;
paul718e3742002-12-13 20:15:29 +00001204 else
pauld24f6e22005-10-21 09:23:12 +00001205 delay = ht - elapsed;
paul718e3742002-12-13 20:15:29 +00001206 }
1207 else
pauld24f6e22005-10-21 09:23:12 +00001208 {
1209 /* Event is past required hold-time of last SPF */
1210 delay = ospf->spf_delay;
1211 ospf->spf_hold_multiplier = 1;
1212 }
1213
paul718e3742002-12-13 20:15:29 +00001214 if (IS_DEBUG_OSPF_EVENT)
pauld24f6e22005-10-21 09:23:12 +00001215 zlog_debug ("SPF: calculation timer delay = %ld", delay);
1216
paul68980082003-03-25 05:07:42 +00001217 ospf->t_spf_calc =
pauld24f6e22005-10-21 09:23:12 +00001218 thread_add_timer_msec (master, ospf_spf_calculate_timer, ospf, delay);
paul718e3742002-12-13 20:15:29 +00001219}