blob: 9a4e8ffa2c98fc90337589b670571ae2e04d7bd5 [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
49#define DEBUG
50
hasso462f20d2005-02-23 11:29:02 +000051/* Heap related functions, for the managment of the candidates, to
52 * be used with pqueue. */
53static int
54cmp (void * node1 , void * node2)
55{
56 struct vertex * v1 = (struct vertex *) node1;
57 struct vertex * v2 = (struct vertex *) node2;
58 if (v1 != NULL && v2 != NULL )
59 return (v1->distance - v2->distance);
60 else
61 return 0;
62}
63
64static void
65update_stat (void * node , int position)
66{
67 struct vertex * v = (struct vertex *) node;
68 /* Set the status of the vertex, when its position changes. */
69 *(v->stat) = position;
70}
71/* End of the heap related functions. */
72
paul718e3742002-12-13 20:15:29 +000073struct vertex_nexthop *
74vertex_nexthop_new (struct vertex *parent)
75{
76 struct vertex_nexthop *new;
77
78 new = XCALLOC (MTYPE_OSPF_NEXTHOP, sizeof (struct vertex_nexthop));
79 new->parent = parent;
80
81 return new;
82}
83
84void
85vertex_nexthop_free (struct vertex_nexthop *nh)
86{
87 XFREE (MTYPE_OSPF_NEXTHOP, nh);
88}
89
90struct vertex_nexthop *
91vertex_nexthop_dup (struct vertex_nexthop *nh)
92{
93 struct vertex_nexthop *new;
94
95 new = vertex_nexthop_new (nh->parent);
96
97 new->oi = nh->oi;
98 new->router = nh->router;
99
100 return new;
101}
paul718e3742002-12-13 20:15:29 +0000102
paul0c0f9cd2003-06-06 23:27:04 +0000103
paul718e3742002-12-13 20:15:29 +0000104struct vertex *
105ospf_vertex_new (struct ospf_lsa *lsa)
106{
107 struct vertex *new;
108
109 new = XMALLOC (MTYPE_OSPF_VERTEX, sizeof (struct vertex));
110 memset (new, 0, sizeof (struct vertex));
111
112 new->flags = 0;
hasso462f20d2005-02-23 11:29:02 +0000113 new->stat = &(lsa->stat);
paul718e3742002-12-13 20:15:29 +0000114 new->type = lsa->data->type;
115 new->id = lsa->data->id;
116 new->lsa = lsa->data;
117 new->distance = 0;
118 new->child = list_new ();
119 new->nexthop = list_new ();
pauld355bfa2004-04-08 07:43:45 +0000120 new->backlink = -1;
paul718e3742002-12-13 20:15:29 +0000121
122 return new;
123}
124
125void
126ospf_vertex_free (struct vertex *v)
127{
hasso52dc7ee2004-09-23 19:18:23 +0000128 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000129
130 list_delete (v->child);
131
132 if (listcount (v->nexthop) > 0)
133 for (node = listhead (v->nexthop); node; nextnode (node))
134 vertex_nexthop_free (node->data);
135
136 list_delete (v->nexthop);
137
138 XFREE (MTYPE_OSPF_VERTEX, v);
139}
140
141void
hassoeb1ce602004-10-08 08:17:22 +0000142ospf_vertex_dump(const char *msg, struct vertex *v,
gdt630e4802004-08-31 17:28:41 +0000143 int print_nexthops, int print_children)
144{
145 if ( ! IS_DEBUG_OSPF_EVENT)
146 return;
147
ajs2a42e282004-12-08 18:43:03 +0000148 zlog_debug("%s %s vertex %s distance %u backlink %d flags %u",
gdt630e4802004-08-31 17:28:41 +0000149 msg,
150 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
151 inet_ntoa(v->lsa->id),
152 v->distance,
153 v->backlink,
154 (unsigned int)v->flags);
155
156 if (print_nexthops)
157 {
hasso52dc7ee2004-09-23 19:18:23 +0000158 struct listnode *nnode;
gdt630e4802004-08-31 17:28:41 +0000159 for (nnode = listhead (v->nexthop); nnode; nextnode (nnode))
160 {
161 char buf1[BUFSIZ];
162 char buf2[BUFSIZ];
163 struct vertex_nexthop *nexthop;
164
165 nexthop = getdata (nnode);
166 if (nexthop)
167 {
ajs2a42e282004-12-08 18:43:03 +0000168 zlog_debug (" nexthop %s interface %s parent %s",
gdt630e4802004-08-31 17:28:41 +0000169 inet_ntop(AF_INET, &nexthop->router, buf1, BUFSIZ),
170 nexthop->oi ? IF_NAME(nexthop->oi) : "NULL",
171 nexthop->parent ? inet_ntop(AF_INET,
172 &nexthop->parent->id,
173 buf2, BUFSIZ)
174 : "NULL");
175 }
176 }
177 }
178
179 if (print_children)
180 {
hasso52dc7ee2004-09-23 19:18:23 +0000181 struct listnode *cnode;
gdt630e4802004-08-31 17:28:41 +0000182 for (cnode = listhead (v->child); cnode; nextnode (cnode))
183 {
184 struct vertex *cv = getdata (cnode);
185 if (cv)
186 ospf_vertex_dump(" child:", cv, 0, 0);
187 }
188 }
189}
190
191
192/* Add a vertex to the list of children in each of its parents. */
193void
paul718e3742002-12-13 20:15:29 +0000194ospf_vertex_add_parent (struct vertex *v)
195{
196 struct vertex_nexthop *nh;
hasso52dc7ee2004-09-23 19:18:23 +0000197 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000198
199 for (node = listhead (v->nexthop); node; nextnode (node))
200 {
201 nh = (struct vertex_nexthop *) getdata (node);
202
203 /* No need to add two links from the same parent. */
204 if (listnode_lookup (nh->parent->child, v) == NULL)
paul0c0f9cd2003-06-06 23:27:04 +0000205 listnode_add (nh->parent->child, v);
paul718e3742002-12-13 20:15:29 +0000206 }
207}
208
209void
210ospf_spf_init (struct ospf_area *area)
211{
212 struct vertex *v;
213
214 /* Create root node. */
215 v = ospf_vertex_new (area->router_lsa_self);
216
217 area->spf = v;
218
219 /* Reset ABR and ASBR router counts. */
220 area->abr_count = 0;
221 area->asbr_count = 0;
222}
223
pauld355bfa2004-04-08 07:43:45 +0000224/* return index of link back to V from W, or -1 if no link found */
paul718e3742002-12-13 20:15:29 +0000225int
226ospf_lsa_has_link (struct lsa_header *w, struct lsa_header *v)
227{
hassoeb1ce602004-10-08 08:17:22 +0000228 unsigned int i, length;
paul718e3742002-12-13 20:15:29 +0000229 struct router_lsa *rl;
230 struct network_lsa *nl;
231
232 /* In case of W is Network LSA. */
233 if (w->type == OSPF_NETWORK_LSA)
234 {
235 if (v->type == OSPF_NETWORK_LSA)
pauld355bfa2004-04-08 07:43:45 +0000236 return -1;
paul718e3742002-12-13 20:15:29 +0000237
238 nl = (struct network_lsa *) w;
239 length = (ntohs (w->length) - OSPF_LSA_HEADER_SIZE - 4) / 4;
paul0c0f9cd2003-06-06 23:27:04 +0000240
paul718e3742002-12-13 20:15:29 +0000241 for (i = 0; i < length; i++)
242 if (IPV4_ADDR_SAME (&nl->routers[i], &v->id))
pauld355bfa2004-04-08 07:43:45 +0000243 return i;
244 return -1;
paul718e3742002-12-13 20:15:29 +0000245 }
246
247 /* In case of W is Router LSA. */
248 if (w->type == OSPF_ROUTER_LSA)
249 {
250 rl = (struct router_lsa *) w;
251
252 length = ntohs (w->length);
253
254 for (i = 0;
paul0c0f9cd2003-06-06 23:27:04 +0000255 i < ntohs (rl->links) && length >= sizeof (struct router_lsa);
256 i++, length -= 12)
paul718e3742002-12-13 20:15:29 +0000257 {
258 switch (rl->link[i].type)
259 {
260 case LSA_LINK_TYPE_POINTOPOINT:
261 case LSA_LINK_TYPE_VIRTUALLINK:
262 /* Router LSA ID. */
263 if (v->type == OSPF_ROUTER_LSA &&
264 IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
265 {
pauld355bfa2004-04-08 07:43:45 +0000266 return i;
paul718e3742002-12-13 20:15:29 +0000267 }
268 break;
269 case LSA_LINK_TYPE_TRANSIT:
270 /* Network LSA ID. */
271 if (v->type == OSPF_NETWORK_LSA &&
272 IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
273 {
pauld355bfa2004-04-08 07:43:45 +0000274 return i;
paul0c0f9cd2003-06-06 23:27:04 +0000275 }
paul718e3742002-12-13 20:15:29 +0000276 break;
277 case LSA_LINK_TYPE_STUB:
278 /* Not take into count? */
279 continue;
280 default:
281 break;
282 }
283 }
284 }
pauld355bfa2004-04-08 07:43:45 +0000285 return -1;
paul718e3742002-12-13 20:15:29 +0000286}
287
288/* Add the nexthop to the list, only if it is unique.
289 * If it's not unique, free the nexthop entry.
290 */
291void
hasso52dc7ee2004-09-23 19:18:23 +0000292ospf_nexthop_add_unique (struct vertex_nexthop *new, struct list *nexthop)
paul718e3742002-12-13 20:15:29 +0000293{
294 struct vertex_nexthop *nh;
hasso52dc7ee2004-09-23 19:18:23 +0000295 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000296 int match;
297
298 match = 0;
299 for (node = listhead (nexthop); node; nextnode (node))
300 {
301 nh = node->data;
302
303 /* Compare the two entries. */
304 /* XXX
305 * Comparing the parent preserves the shortest path tree
306 * structure even when the nexthops are identical.
307 */
308 if (nh->oi == new->oi &&
paul0c0f9cd2003-06-06 23:27:04 +0000309 IPV4_ADDR_SAME (&nh->router, &new->router) &&
310 nh->parent == new->parent)
311 {
312 match = 1;
313 break;
314 }
paul718e3742002-12-13 20:15:29 +0000315 }
316
317 if (!match)
318 listnode_add (nexthop, new);
319 else
320 vertex_nexthop_free (new);
321}
322
323/* Merge entries in list b into list a. */
324void
hasso52dc7ee2004-09-23 19:18:23 +0000325ospf_nexthop_merge (struct list *a, struct list *b)
paul718e3742002-12-13 20:15:29 +0000326{
327 struct listnode *n;
328
329 for (n = listhead (b); n; nextnode (n))
330 {
331 ospf_nexthop_add_unique (n->data, a);
332 }
333}
334
335#define ROUTER_LSA_MIN_SIZE 12
336#define ROUTER_LSA_TOS_SIZE 4
337
gdt630e4802004-08-31 17:28:41 +0000338/* Find the next link after prev_link from v to w. If prev_link is
339 * NULL, return the first link from v to w. Ignore stub and virtual links;
340 * these link types will never be returned.
341 */
paul718e3742002-12-13 20:15:29 +0000342struct router_lsa_link *
343ospf_get_next_link (struct vertex *v, struct vertex *w,
paul0c0f9cd2003-06-06 23:27:04 +0000344 struct router_lsa_link *prev_link)
paul718e3742002-12-13 20:15:29 +0000345{
346 u_char *p;
347 u_char *lim;
348 struct router_lsa_link *l;
349
350 if (prev_link == NULL)
gdt630e4802004-08-31 17:28:41 +0000351 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +0000352 else
353 {
paul0c0f9cd2003-06-06 23:27:04 +0000354 p = (u_char *) prev_link;
paul718e3742002-12-13 20:15:29 +0000355 p += (ROUTER_LSA_MIN_SIZE +
356 (prev_link->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
357 }
paul0c0f9cd2003-06-06 23:27:04 +0000358
paul718e3742002-12-13 20:15:29 +0000359 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
360
361 while (p < lim)
362 {
363 l = (struct router_lsa_link *) p;
364
paul0c0f9cd2003-06-06 23:27:04 +0000365 p += (ROUTER_LSA_MIN_SIZE + (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
paul718e3742002-12-13 20:15:29 +0000366
367 if (l->m[0].type == LSA_LINK_TYPE_STUB)
368 continue;
369
370 /* Defer NH calculation via VLs until summaries from
371 transit areas area confidered */
372
373 if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK)
paul0c0f9cd2003-06-06 23:27:04 +0000374 continue;
paul718e3742002-12-13 20:15:29 +0000375
376 if (IPV4_ADDR_SAME (&l->link_id, &w->id))
paul0c0f9cd2003-06-06 23:27:04 +0000377 return l;
paul718e3742002-12-13 20:15:29 +0000378 }
379
380 return NULL;
381}
382
paul75ee0b82004-08-05 09:10:31 +0000383/*
384 * Consider supplied next-hop for inclusion to the supplied list of
385 * equal-cost next-hops, adjust list as neccessary.
386 *
387 * (Discussed on GNU Zebra list 27 May 2003, [zebra 19184])
388 *
389 * Note that below is a bit of a hack, and limits ECMP to paths that go to
390 * same nexthop. Where as paths via inequal output_cost interfaces could
391 * still quite easily be ECMP due to remote cost differences.
392 *
393 * TODO: It really should be done by way of recording currently valid
394 * backlinks and determining the appropriate nexthops from the list of
395 * backlinks, or even simpler, just flushing nexthop list if we find a lower
396 * cost path to a candidate vertex in SPF, maybe.
paulbf9392c2003-06-06 23:23:36 +0000397 */
paul0c0f9cd2003-06-06 23:27:04 +0000398void
399ospf_spf_consider_nexthop (struct list *nexthops,
400 struct vertex_nexthop *newhop)
paulbf9392c2003-06-06 23:23:36 +0000401{
paulbf9392c2003-06-06 23:23:36 +0000402 struct vertex_nexthop *hop;
paul75ee0b82004-08-05 09:10:31 +0000403 struct listnode *ln, *nn;
paul0c0f9cd2003-06-06 23:27:04 +0000404
paul75ee0b82004-08-05 09:10:31 +0000405 /* nexthop list should contain only the set of nexthops that have the lowest
406 * equal cost
407 */
408 if (nexthops->head != NULL)
409 {
410 hop = getdata (nexthops->head);
411
412 /* weed out hops with higher cost than the newhop */
413 if (hop->oi->output_cost > newhop->oi->output_cost)
414 {
415 /* delete the existing nexthops */
416 for (ln = nexthops->head; ln; ln = nn)
417 {
418 nn = ln->next;
419 hop = getdata (ln);
420
421 listnode_delete (nexthops, hop);
422 vertex_nexthop_free (hop);
423 }
424 }
425 else if (hop->oi->output_cost < newhop->oi->output_cost)
paul0c0f9cd2003-06-06 23:27:04 +0000426 return;
paul75ee0b82004-08-05 09:10:31 +0000427 }
paul0c0f9cd2003-06-06 23:27:04 +0000428
paulbf9392c2003-06-06 23:23:36 +0000429 /* new hop is <= existing hops, add it */
paul0c0f9cd2003-06-06 23:27:04 +0000430 listnode_add (nexthops, newhop);
paulbf9392c2003-06-06 23:23:36 +0000431
432 return;
433}
434
gdt630e4802004-08-31 17:28:41 +0000435/* 16.1.1. Calculate nexthop from root through V (parent) to
436 * vertex W (destination).
437 */
paul718e3742002-12-13 20:15:29 +0000438void
439ospf_nexthop_calculation (struct ospf_area *area,
440 struct vertex *v, struct vertex *w)
441{
hasso52dc7ee2004-09-23 19:18:23 +0000442 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000443 struct vertex_nexthop *nh, *x;
444 struct ospf_interface *oi = NULL;
445 struct router_lsa_link *l = NULL;
paul0c0f9cd2003-06-06 23:27:04 +0000446
447
paul718e3742002-12-13 20:15:29 +0000448 if (IS_DEBUG_OSPF_EVENT)
gdt630e4802004-08-31 17:28:41 +0000449 {
ajs2a42e282004-12-08 18:43:03 +0000450 zlog_debug ("ospf_nexthop_calculation(): Start");
gdt630e4802004-08-31 17:28:41 +0000451 ospf_vertex_dump("V (parent):", v, 1, 1);
452 ospf_vertex_dump("W (dest) :", w, 1, 1);
453 }
paul718e3742002-12-13 20:15:29 +0000454
paul718e3742002-12-13 20:15:29 +0000455 if (v == area->spf)
456 {
gdt630e4802004-08-31 17:28:41 +0000457 /* 16.1.1 para 4. In the first case, the parent vertex (V) is the
458 root (the calculating router itself). This means that the
459 destination is either a directly connected network or directly
460 connected router. The outgoing interface in this case is simply
461 the OSPF interface connecting to the destination network/router.
462 */
463
paul718e3742002-12-13 20:15:29 +0000464 if (w->type == OSPF_VERTEX_ROUTER)
paul0c0f9cd2003-06-06 23:27:04 +0000465 {
466 while ((l = ospf_get_next_link (v, w, l)))
467 {
gdt630e4802004-08-31 17:28:41 +0000468 /* l is a link from v to w
469 * l2 will be link from w to v
470 */
paul0c0f9cd2003-06-06 23:27:04 +0000471 struct router_lsa_link *l2 = NULL;
472
gdt630e4802004-08-31 17:28:41 +0000473 if (IS_DEBUG_OSPF_EVENT)
474 {
475 char buf1[BUFSIZ];
ajs2a42e282004-12-08 18:43:03 +0000476 zlog_debug("ospf_nexthop_calculation(): considering link "
gdt630e4802004-08-31 17:28:41 +0000477 "type %d link_id %s link_data %s",
478 l->m[0].type,
479 inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ),
480 inet_ntop (AF_INET, &l->link_data, buf1, BUFSIZ));
481 }
482
paul0c0f9cd2003-06-06 23:27:04 +0000483 if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT)
484 {
gdt630e4802004-08-31 17:28:41 +0000485 /* If the destination is a router which connects to
486 the calculating router via a Point-to-MultiPoint
487 network, the destination's next hop IP address(es)
488 can be determined by examining the destination's
489 router-LSA: each link pointing back to the
490 calculating router and having a Link Data field
491 belonging to the Point-to-MultiPoint network
492 provides an IP address of the next hop router.
493
494 At this point l is a link from V to W, and V is the
495 root ("us"). Find the local interface associated
496 with l (its address is in l->link_data). If it
497 is a point-to-multipoint interface, then look through
498 the links in the opposite direction (W to V). If
499 any of them have an address that lands within the
500 subnet declared by the PtMP link, then that link
501 is a constituent of the PtMP link, and its address is
502 a nexthop address for V.
503 */
paul68980082003-03-25 05:07:42 +0000504 oi = ospf_if_is_configured (area->ospf, &l->link_data);
paul7afa08d2002-12-13 20:59:45 +0000505 if (oi && oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
paul0c0f9cd2003-06-06 23:27:04 +0000506 {
507 struct prefix_ipv4 la;
gdt630e4802004-08-31 17:28:41 +0000508
509 la.family = AF_INET;
paul0c0f9cd2003-06-06 23:27:04 +0000510 la.prefixlen = oi->address->prefixlen;
gdt630e4802004-08-31 17:28:41 +0000511
512 /* V links to W on PtMP interface
513 - find the interface address on W */
paul0c0f9cd2003-06-06 23:27:04 +0000514 while ((l2 = ospf_get_next_link (w, v, l2)))
515 {
516 la.prefix = l2->link_data;
517
518 if (prefix_cmp ((struct prefix *) &la,
519 oi->address) == 0)
520 /* link_data is on our PtMP network */
521 break;
522 }
gdt630e4802004-08-31 17:28:41 +0000523 } /* end l is on point-to-multipoint link */
paul0c0f9cd2003-06-06 23:27:04 +0000524 else
525 {
gdt630e4802004-08-31 17:28:41 +0000526 /* l is a regular point-to-point link.
527 Look for a link from W to V.
528 */
paul0c0f9cd2003-06-06 23:27:04 +0000529 while ((l2 = ospf_get_next_link (w, v, l2)))
530 {
531 oi = ospf_if_is_configured (area->ospf,
532 &(l2->link_data));
533
534 if (oi == NULL)
535 continue;
536
537 if (!IPV4_ADDR_SAME (&oi->address->u.prefix4,
538 &l->link_data))
539 continue;
540
541 break;
542 }
543 }
544
545 if (oi && l2)
546 {
gdt630e4802004-08-31 17:28:41 +0000547 /* found all necessary info to build nexthop */
paul0c0f9cd2003-06-06 23:27:04 +0000548 nh = vertex_nexthop_new (v);
549 nh->oi = oi;
550 nh->router = l2->link_data;
551 ospf_spf_consider_nexthop (w->nexthop, nh);
552 }
gdt630e4802004-08-31 17:28:41 +0000553 else
554 {
555 zlog_info("ospf_nexthop_calculation(): "
556 "could not determine nexthop for link");
557 }
558 } /* end point-to-point link from V to W */
559 } /* end iterate over links in W */
560 } /* end W is a Router vertex */
paul718e3742002-12-13 20:15:29 +0000561 else
paul0c0f9cd2003-06-06 23:27:04 +0000562 {
gdt630e4802004-08-31 17:28:41 +0000563 assert(w->type == OSPF_VERTEX_NETWORK);
paul0c0f9cd2003-06-06 23:27:04 +0000564 while ((l = ospf_get_next_link (v, w, l)))
565 {
566 oi = ospf_if_is_configured (area->ospf, &(l->link_data));
567 if (oi)
568 {
569 nh = vertex_nexthop_new (v);
570 nh->oi = oi;
571 nh->router.s_addr = 0;
paul75ee0b82004-08-05 09:10:31 +0000572 ospf_spf_consider_nexthop (w->nexthop, nh);
paul0c0f9cd2003-06-06 23:27:04 +0000573 }
574 }
575 }
paul718e3742002-12-13 20:15:29 +0000576 return;
gdt630e4802004-08-31 17:28:41 +0000577 } /* end V is the root */
578
579 /* 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. */
paul718e3742002-12-13 20:15:29 +0000583 for (node = listhead (v->nexthop); node; nextnode (node))
584 {
gdt630e4802004-08-31 17:28:41 +0000585 x = (struct vertex_nexthop *) getdata (node);
586 if (x->parent == area->spf) /* connects to root? */
587 {
588 /* 16.1.1 para 5. ...the parent vertex is a network that
589 * directly connects the calculating router to the destination
590 * router. The list of next hops is then determined by
591 * examining the destination's router-LSA...
592 */
593
594 assert(w->type == OSPF_VERTEX_ROUTER);
paul0c0f9cd2003-06-06 23:27:04 +0000595 while ((l = ospf_get_next_link (w, v, l)))
596 {
gdt630e4802004-08-31 17:28:41 +0000597 /* ...For each link in the router-LSA that points back to the
598 * parent network, the link's Link Data field provides the IP
599 * address of a next hop router. The outgoing interface to
600 * use can then be derived from the next hop IP address (or
601 * it can be inherited from the parent network).
602 */
paul0c0f9cd2003-06-06 23:27:04 +0000603 nh = vertex_nexthop_new (v);
604 nh->oi = x->oi;
605 nh->router = l->link_data;
paul75ee0b82004-08-05 09:10:31 +0000606 ospf_spf_consider_nexthop (w->nexthop, nh);
paul0c0f9cd2003-06-06 23:27:04 +0000607 }
608 return;
609 }
paul718e3742002-12-13 20:15:29 +0000610 }
611 }
612
gdt630e4802004-08-31 17:28:41 +0000613 /* 16.1.1 para 4. If there is at least one intervening router in the
614 * current shortest path between the destination and the root, the
615 * destination simply inherits the set of next hops from the
616 * parent.
617 */
paul718e3742002-12-13 20:15:29 +0000618 for (node = listhead (v->nexthop); node; nextnode (node))
619 {
620 nh = vertex_nexthop_dup (node->data);
621 nh->parent = v;
622 ospf_nexthop_add_unique (nh, w->nexthop);
623 }
624}
625
gdt630e4802004-08-31 17:28:41 +0000626/* RFC2328 Section 16.1 (2).
627 * v is on the SPF tree. Examine the links in v's LSA. Update the list
628 * of candidates with any vertices not already on the list. If a lower-cost
629 * path is found to a vertex already on the candidate list, store the new cost.
630 */
paul718e3742002-12-13 20:15:29 +0000631void
632ospf_spf_next (struct vertex *v, struct ospf_area *area,
hasso462f20d2005-02-23 11:29:02 +0000633 struct pqueue * candidate)
paul718e3742002-12-13 20:15:29 +0000634{
635 struct ospf_lsa *w_lsa = NULL;
636 struct vertex *w, *cw;
637 u_char *p;
638 u_char *lim;
639 struct router_lsa_link *l = NULL;
640 struct in_addr *r;
paul718e3742002-12-13 20:15:29 +0000641 int type = 0;
642
643 /* If this is a router-LSA, and bit V of the router-LSA (see Section
644 A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE. */
645 if (v->type == OSPF_VERTEX_ROUTER)
646 {
647 if (IS_ROUTER_LSA_VIRTUAL ((struct router_lsa *) v->lsa))
648 area->transit = OSPF_TRANSIT_TRUE;
649 }
650
651 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul0c0f9cd2003-06-06 23:27:04 +0000652 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
653
paul718e3742002-12-13 20:15:29 +0000654 while (p < lim)
655 {
pauld355bfa2004-04-08 07:43:45 +0000656 int link = -1; /* link index for w's back link */
657
paul718e3742002-12-13 20:15:29 +0000658 /* In case of V is Router-LSA. */
659 if (v->lsa->type == OSPF_ROUTER_LSA)
660 {
661 l = (struct router_lsa_link *) p;
662
paul0c0f9cd2003-06-06 23:27:04 +0000663 p += (ROUTER_LSA_MIN_SIZE +
paul718e3742002-12-13 20:15:29 +0000664 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
665
666 /* (a) If this is a link to a stub network, examine the next
667 link in V's LSA. Links to stub networks will be
668 considered in the second stage of the shortest path
669 calculation. */
670 if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB)
671 continue;
672
673 /* (b) Otherwise, W is a transit vertex (router or transit
674 network). Look up the vertex W's LSA (router-LSA or
675 network-LSA) in Area A's link state database. */
676 switch (type)
677 {
678 case LSA_LINK_TYPE_POINTOPOINT:
679 case LSA_LINK_TYPE_VIRTUALLINK:
680 if (type == LSA_LINK_TYPE_VIRTUALLINK)
paul0c0f9cd2003-06-06 23:27:04 +0000681 {
682 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000683 zlog_debug ("looking up LSA through VL: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000684 inet_ntoa (l->link_id));
685 }
paul718e3742002-12-13 20:15:29 +0000686
687 w_lsa = ospf_lsa_lookup (area, OSPF_ROUTER_LSA, l->link_id,
688 l->link_id);
689 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000690 {
691 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000692 zlog_debug ("found Router LSA %s", inet_ntoa (l->link_id));
paul0c0f9cd2003-06-06 23:27:04 +0000693 }
paul718e3742002-12-13 20:15:29 +0000694 break;
695 case LSA_LINK_TYPE_TRANSIT:
paul0c0f9cd2003-06-06 23:27:04 +0000696 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000697 zlog_debug ("Looking up Network LSA, ID: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000698 inet_ntoa (l->link_id));
paul718e3742002-12-13 20:15:29 +0000699 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_NETWORK_LSA,
paul0c0f9cd2003-06-06 23:27:04 +0000700 l->link_id);
paul718e3742002-12-13 20:15:29 +0000701 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000702 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000703 zlog_debug ("found the LSA");
paul718e3742002-12-13 20:15:29 +0000704 break;
705 default:
paul0c0f9cd2003-06-06 23:27:04 +0000706 zlog_warn ("Invalid LSA link type %d", type);
paul718e3742002-12-13 20:15:29 +0000707 continue;
708 }
709 }
710 else
711 {
712 /* In case of V is Network-LSA. */
paul0c0f9cd2003-06-06 23:27:04 +0000713 r = (struct in_addr *) p;
paul718e3742002-12-13 20:15:29 +0000714 p += sizeof (struct in_addr);
715
716 /* Lookup the vertex W's LSA. */
717 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_ROUTER_LSA, *r);
718 }
719
720 /* (b cont.) If the LSA does not exist, or its LS age is equal
721 to MaxAge, or it does not have a link back to vertex V,
722 examine the next link in V's LSA.[23] */
723 if (w_lsa == NULL)
724 continue;
725
726 if (IS_LSA_MAXAGE (w_lsa))
727 continue;
728
pauld355bfa2004-04-08 07:43:45 +0000729 if ( (link = ospf_lsa_has_link (w_lsa->data, v->lsa)) < 0 )
paul718e3742002-12-13 20:15:29 +0000730 {
paul0c0f9cd2003-06-06 23:27:04 +0000731 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000732 zlog_debug ("The LSA doesn't have a link back");
paul718e3742002-12-13 20:15:29 +0000733 continue;
734 }
735
736 /* (c) If vertex W is already on the shortest-path tree, examine
737 the next link in the LSA. */
hasso462f20d2005-02-23 11:29:02 +0000738 if (w_lsa->stat == LSA_SPF_IN_SPFTREE)
739 {
740 if (IS_DEBUG_OSPF_EVENT)
741 zlog_debug ("The LSA is already in SPF");
742 continue;
743 }
paul718e3742002-12-13 20:15:29 +0000744
745 /* (d) Calculate the link state cost D of the resulting path
746 from the root to vertex W. D is equal to the sum of the link
747 state cost of the (already calculated) shortest path to
748 vertex V and the advertised cost of the link between vertices
749 V and W. If D is: */
750
751 /* prepare vertex W. */
752 w = ospf_vertex_new (w_lsa);
753
pauld355bfa2004-04-08 07:43:45 +0000754 /* Save W's back link index number, for use by virtual links */
755 w->backlink = link;
756
paul718e3742002-12-13 20:15:29 +0000757 /* calculate link cost D. */
758 if (v->lsa->type == OSPF_ROUTER_LSA)
gdt630e4802004-08-31 17:28:41 +0000759 w->distance = v->distance + ntohs (l->m[0].metric);
760 else /* v is not a Router-LSA */
761 w->distance = v->distance;
paul718e3742002-12-13 20:15:29 +0000762
763 /* Is there already vertex W in candidate list? */
hasso462f20d2005-02-23 11:29:02 +0000764 if (w_lsa->stat == LSA_SPF_NOT_EXPLORED)
765 {
766 /* Calculate nexthop to W. */
767 ospf_nexthop_calculation (area, v, w);
768 pqueue_enqueue (w, candidate);
769 }
770 else if (w_lsa->stat >= 0)
771 {
772 /* Get the vertex from candidates. */
773 cw = (struct vertex *) candidate->array[w_lsa->stat];
paul718e3742002-12-13 20:15:29 +0000774
hasso462f20d2005-02-23 11:29:02 +0000775 /* if D is greater than. */
776 if (cw->distance < w->distance)
paul718e3742002-12-13 20:15:29 +0000777 {
778 ospf_vertex_free (w);
779 continue;
780 }
hasso462f20d2005-02-23 11:29:02 +0000781 /* equal to. */
782 else if (cw->distance == w->distance)
paul718e3742002-12-13 20:15:29 +0000783 {
gdt630e4802004-08-31 17:28:41 +0000784 /* Found an equal-cost path to W. Calculate nexthop to W. */
paul718e3742002-12-13 20:15:29 +0000785 ospf_nexthop_calculation (area, v, w);
786 ospf_nexthop_merge (cw->nexthop, w->nexthop);
787 list_delete_all_node (w->nexthop);
788 ospf_vertex_free (w);
789 }
hasso462f20d2005-02-23 11:29:02 +0000790 /* less than. */
791 else
paul718e3742002-12-13 20:15:29 +0000792 {
gdt630e4802004-08-31 17:28:41 +0000793 /* Found a lower-cost path to W. Calculate nexthop to W. */
paul718e3742002-12-13 20:15:29 +0000794 ospf_nexthop_calculation (area, v, w);
795
796 /* Remove old vertex from candidate list. */
797 ospf_vertex_free (cw);
hasso462f20d2005-02-23 11:29:02 +0000798 candidate->array[w_lsa->stat] = w;
799 /* Decrease the key of the node in the heap, re-sort the heap. */
800 trickle_down (w_lsa->stat, candidate);
paul718e3742002-12-13 20:15:29 +0000801 }
gdt630e4802004-08-31 17:28:41 +0000802 } /* end W is already on the candidate list */
803 } /* end loop over the links in V's LSA */
paul718e3742002-12-13 20:15:29 +0000804}
805
paul718e3742002-12-13 20:15:29 +0000806void
807ospf_spf_route_free (struct route_table *table)
808{
809 struct route_node *rn;
810 struct vertex *v;
811
812 for (rn = route_top (table); rn; rn = route_next (rn))
813 {
814 if ((v = rn->info))
paul0c0f9cd2003-06-06 23:27:04 +0000815 {
816 ospf_vertex_free (v);
817 rn->info = NULL;
818 }
paul718e3742002-12-13 20:15:29 +0000819
820 route_unlock_node (rn);
821 }
822
823 route_table_finish (table);
824}
825
826void
827ospf_spf_dump (struct vertex *v, int i)
828{
hasso52dc7ee2004-09-23 19:18:23 +0000829 struct listnode *cnode;
830 struct listnode *nnode;
paul718e3742002-12-13 20:15:29 +0000831 struct vertex_nexthop *nexthop;
832
833 if (v->type == OSPF_VERTEX_ROUTER)
834 {
835 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000836 zlog_debug ("SPF Result: %d [R] %s", i, inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000837 }
838 else
839 {
840 struct network_lsa *lsa = (struct network_lsa *) v->lsa;
841 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000842 zlog_debug ("SPF Result: %d [N] %s/%d", i, inet_ntoa (v->lsa->id),
paul0c0f9cd2003-06-06 23:27:04 +0000843 ip_masklen (lsa->mask));
gdt630e4802004-08-31 17:28:41 +0000844 }
paul718e3742002-12-13 20:15:29 +0000845
gdt630e4802004-08-31 17:28:41 +0000846 for (nnode = listhead (v->nexthop); nnode; nextnode (nnode))
847 {
848 nexthop = getdata (nnode);
849 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000850 zlog_debug (" nexthop %s", inet_ntoa (nexthop->router));
paul718e3742002-12-13 20:15:29 +0000851 }
852
853 i++;
854
855 for (cnode = listhead (v->child); cnode; nextnode (cnode))
856 {
857 v = getdata (cnode);
858 ospf_spf_dump (v, i);
859 }
860}
861
862/* Second stage of SPF calculation. */
863void
paul0c0f9cd2003-06-06 23:27:04 +0000864ospf_spf_process_stubs (struct ospf_area *area, struct vertex *v,
paul718e3742002-12-13 20:15:29 +0000865 struct route_table *rt)
866{
hasso52dc7ee2004-09-23 19:18:23 +0000867 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000868 struct vertex *child;
869
870 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000871 zlog_debug ("ospf_process_stub():processing stubs for area %s",
paul0c0f9cd2003-06-06 23:27:04 +0000872 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +0000873 if (v->type == OSPF_VERTEX_ROUTER)
874 {
875 u_char *p;
876 u_char *lim;
877 struct router_lsa_link *l;
878 struct router_lsa *rlsa;
879
paul0c0f9cd2003-06-06 23:27:04 +0000880 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000881 zlog_debug ("ospf_process_stubs():processing router LSA, id: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000882 inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000883 rlsa = (struct router_lsa *) v->lsa;
884
885
paul0c0f9cd2003-06-06 23:27:04 +0000886 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000887 zlog_debug ("ospf_process_stubs(): we have %d links to process",
paul0c0f9cd2003-06-06 23:27:04 +0000888 ntohs (rlsa->links));
gdt630e4802004-08-31 17:28:41 +0000889 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +0000890 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
891
892 while (p < lim)
893 {
894 l = (struct router_lsa_link *) p;
895
896 p += (ROUTER_LSA_MIN_SIZE +
897 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
898
899 if (l->m[0].type == LSA_LINK_TYPE_STUB)
900 ospf_intra_add_stub (rt, l, v, area);
901 }
902 }
903
gdt630e4802004-08-31 17:28:41 +0000904 ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1, 1);
paul718e3742002-12-13 20:15:29 +0000905
906 for (cnode = listhead (v->child); cnode; nextnode (cnode))
907 {
908 child = getdata (cnode);
909
910 if (CHECK_FLAG (child->flags, OSPF_VERTEX_PROCESSED))
paul0c0f9cd2003-06-06 23:27:04 +0000911 continue;
paul718e3742002-12-13 20:15:29 +0000912
913 ospf_spf_process_stubs (area, child, rt);
914
915 SET_FLAG (child->flags, OSPF_VERTEX_PROCESSED);
916 }
917}
918
919void
920ospf_rtrs_free (struct route_table *rtrs)
921{
922 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +0000923 struct list *or_list;
924 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000925
926 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000927 zlog_debug ("Route: Router Routing Table free");
paul718e3742002-12-13 20:15:29 +0000928
929 for (rn = route_top (rtrs); rn; rn = route_next (rn))
930 if ((or_list = rn->info) != NULL)
931 {
paul0c0f9cd2003-06-06 23:27:04 +0000932 for (node = listhead (or_list); node; nextnode (node))
933 ospf_route_free (node->data);
paul718e3742002-12-13 20:15:29 +0000934
paul0c0f9cd2003-06-06 23:27:04 +0000935 list_delete (or_list);
paul718e3742002-12-13 20:15:29 +0000936
paul0c0f9cd2003-06-06 23:27:04 +0000937 /* Unlock the node. */
938 rn->info = NULL;
939 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +0000940 }
941 route_table_finish (rtrs);
942}
943
944void
945ospf_rtrs_print (struct route_table *rtrs)
946{
947 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +0000948 struct list *or_list;
949 struct listnode *ln;
950 struct listnode *pnode;
paul718e3742002-12-13 20:15:29 +0000951 struct ospf_route *or;
952 struct ospf_path *path;
953 char buf1[BUFSIZ];
954 char buf2[BUFSIZ];
955
956 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000957 zlog_debug ("ospf_rtrs_print() start");
paul718e3742002-12-13 20:15:29 +0000958
959 for (rn = route_top (rtrs); rn; rn = route_next (rn))
960 if ((or_list = rn->info) != NULL)
961 for (ln = listhead (or_list); ln; nextnode (ln))
962 {
963 or = getdata (ln);
964
965 switch (or->path_type)
966 {
967 case OSPF_PATH_INTRA_AREA:
paul0c0f9cd2003-06-06 23:27:04 +0000968 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000969 zlog_debug ("%s [%d] area: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000970 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
971 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
972 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +0000973 break;
974 case OSPF_PATH_INTER_AREA:
paul0c0f9cd2003-06-06 23:27:04 +0000975 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000976 zlog_debug ("%s IA [%d] area: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000977 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
978 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
979 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +0000980 break;
981 default:
982 break;
983 }
984
paul96735ee2003-08-10 02:51:22 +0000985 for (pnode = listhead (or->paths); pnode; nextnode (pnode))
paul718e3742002-12-13 20:15:29 +0000986 {
987 path = getdata (pnode);
988 if (path->nexthop.s_addr == 0)
paul0c0f9cd2003-06-06 23:27:04 +0000989 {
990 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000991 zlog_debug (" directly attached to %s\r\n",
paul0c0f9cd2003-06-06 23:27:04 +0000992 IF_NAME (path->oi));
993 }
994 else
995 {
996 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000997 zlog_debug (" via %s, %s\r\n",
paul0c0f9cd2003-06-06 23:27:04 +0000998 inet_ntoa (path->nexthop), IF_NAME (path->oi));
999 }
paul718e3742002-12-13 20:15:29 +00001000 }
1001 }
1002
ajs2a42e282004-12-08 18:43:03 +00001003 zlog_debug ("ospf_rtrs_print() end");
paul718e3742002-12-13 20:15:29 +00001004}
1005
1006/* Calculating the shortest-path tree for an area. */
1007void
paul0c0f9cd2003-06-06 23:27:04 +00001008ospf_spf_calculate (struct ospf_area *area, struct route_table *new_table,
paul718e3742002-12-13 20:15:29 +00001009 struct route_table *new_rtrs)
1010{
hasso462f20d2005-02-23 11:29:02 +00001011 struct pqueue *candidate;
paul718e3742002-12-13 20:15:29 +00001012 struct vertex *v;
paul718e3742002-12-13 20:15:29 +00001013
1014 if (IS_DEBUG_OSPF_EVENT)
1015 {
ajs2a42e282004-12-08 18:43:03 +00001016 zlog_debug ("ospf_spf_calculate: Start");
1017 zlog_debug ("ospf_spf_calculate: running Dijkstra for area %s",
paul0c0f9cd2003-06-06 23:27:04 +00001018 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001019 }
1020
1021 /* Check router-lsa-self. If self-router-lsa is not yet allocated,
1022 return this area's calculation. */
paul0c0f9cd2003-06-06 23:27:04 +00001023 if (!area->router_lsa_self)
paul718e3742002-12-13 20:15:29 +00001024 {
1025 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001026 zlog_debug ("ospf_spf_calculate: "
paul0c0f9cd2003-06-06 23:27:04 +00001027 "Skip area %s's calculation due to empty router_lsa_self",
1028 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001029 return;
1030 }
1031
1032 /* RFC2328 16.1. (1). */
paul0c0f9cd2003-06-06 23:27:04 +00001033 /* Initialize the algorithm's data structures. */
hasso462f20d2005-02-23 11:29:02 +00001034
1035 /* This function scans all the LSA database and set the stat field to
1036 * LSA_SPF_NOT_EXPLORED. */
1037 ospf_lsdb_clean_stat (area->lsdb);
1038 /* Create a new heap for the candidates. */
1039 candidate = pqueue_create();
1040 candidate->cmp = cmp;
1041 candidate->update = update_stat;
paul718e3742002-12-13 20:15:29 +00001042
1043 /* Initialize the shortest-path tree to only the root (which is the
1044 router doing the calculation). */
1045 ospf_spf_init (area);
1046 v = area->spf;
hasso462f20d2005-02-23 11:29:02 +00001047 /* Set LSA position to LSA_SPF_IN_SPFTREE. This vertex is the root of the
1048 * spanning tree. */
1049 *(v->stat) = LSA_SPF_IN_SPFTREE;
paul718e3742002-12-13 20:15:29 +00001050
1051 /* Set Area A's TransitCapability to FALSE. */
1052 area->transit = OSPF_TRANSIT_FALSE;
1053 area->shortcut_capability = 1;
1054
1055 for (;;)
1056 {
1057 /* RFC2328 16.1. (2). */
hasso462f20d2005-02-23 11:29:02 +00001058 ospf_spf_next (v, area, candidate);
paul718e3742002-12-13 20:15:29 +00001059
1060 /* RFC2328 16.1. (3). */
1061 /* If at this step the candidate list is empty, the shortest-
1062 path tree (of transit vertices) has been completely built and
1063 this stage of the procedure terminates. */
hasso462f20d2005-02-23 11:29:02 +00001064 if (candidate->size == 0)
paul718e3742002-12-13 20:15:29 +00001065 break;
1066
1067 /* Otherwise, choose the vertex belonging to the candidate list
1068 that is closest to the root, and add it to the shortest-path
1069 tree (removing it from the candidate list in the
paul0c0f9cd2003-06-06 23:27:04 +00001070 process). */
hasso462f20d2005-02-23 11:29:02 +00001071 /* Extract from the candidates the node with the lower key. */
1072 v = (struct vertex *) pqueue_dequeue (candidate);
1073 /* Update stat field in vertex. */
1074 *(v->stat) = LSA_SPF_IN_SPFTREE;
paul718e3742002-12-13 20:15:29 +00001075 ospf_vertex_add_parent (v);
1076
paul718e3742002-12-13 20:15:29 +00001077 /* Note that when there is a choice of vertices closest to the
1078 root, network vertices must be chosen before router vertices
1079 in order to necessarily find all equal-cost paths. */
1080 /* We don't do this at this moment, we should add the treatment
1081 above codes. -- kunihiro. */
1082
1083 /* RFC2328 16.1. (4). */
1084 if (v->type == OSPF_VERTEX_ROUTER)
1085 ospf_intra_add_router (new_rtrs, v, area);
paul0c0f9cd2003-06-06 23:27:04 +00001086 else
paul718e3742002-12-13 20:15:29 +00001087 ospf_intra_add_transit (new_table, v, area);
1088
1089 /* RFC2328 16.1. (5). */
1090 /* Iterate the algorithm by returning to Step 2. */
gdt630e4802004-08-31 17:28:41 +00001091
1092 } /* end loop until no more candidate vertices */
paul718e3742002-12-13 20:15:29 +00001093
1094 if (IS_DEBUG_OSPF_EVENT)
1095 {
1096 ospf_spf_dump (area->spf, 0);
1097 ospf_route_table_dump (new_table);
1098 }
1099
1100 /* Second stage of SPF calculation procedure's */
1101 ospf_spf_process_stubs (area, area->spf, new_table);
1102
hasso462f20d2005-02-23 11:29:02 +00001103 /* Free candidates. */
1104 pqueue_delete (candidate);
paul718e3742002-12-13 20:15:29 +00001105
1106 /* Increment SPF Calculation Counter. */
1107 area->spf_calculation++;
1108
paul68980082003-03-25 05:07:42 +00001109 area->ospf->ts_spf = time (NULL);
paul718e3742002-12-13 20:15:29 +00001110
1111 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001112 zlog_debug ("ospf_spf_calculate: Stop");
paul718e3742002-12-13 20:15:29 +00001113}
1114
1115/* Timer for SPF calculation. */
1116int
paul68980082003-03-25 05:07:42 +00001117ospf_spf_calculate_timer (struct thread *thread)
paul718e3742002-12-13 20:15:29 +00001118{
paul68980082003-03-25 05:07:42 +00001119 struct ospf *ospf = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +00001120 struct route_table *new_table, *new_rtrs;
hasso52dc7ee2004-09-23 19:18:23 +00001121 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001122
1123 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001124 zlog_debug ("SPF: Timer (SPF calculation expire)");
paul0c0f9cd2003-06-06 23:27:04 +00001125
paul718e3742002-12-13 20:15:29 +00001126 ospf->t_spf_calc = NULL;
1127
1128 /* Allocate new table tree. */
1129 new_table = route_table_init ();
paul0c0f9cd2003-06-06 23:27:04 +00001130 new_rtrs = route_table_init ();
paul718e3742002-12-13 20:15:29 +00001131
paul68980082003-03-25 05:07:42 +00001132 ospf_vl_unapprove (ospf);
paul718e3742002-12-13 20:15:29 +00001133
1134 /* Calculate SPF for each area. */
1135 for (node = listhead (ospf->areas); node; node = nextnode (node))
1136 ospf_spf_calculate (node->data, new_table, new_rtrs);
1137
paul68980082003-03-25 05:07:42 +00001138 ospf_vl_shut_unapproved (ospf);
paul718e3742002-12-13 20:15:29 +00001139
paul68980082003-03-25 05:07:42 +00001140 ospf_ia_routing (ospf, new_table, new_rtrs);
paul718e3742002-12-13 20:15:29 +00001141
1142 ospf_prune_unreachable_networks (new_table);
1143 ospf_prune_unreachable_routers (new_rtrs);
1144
1145 /* AS-external-LSA calculation should not be performed here. */
1146
1147 /* If new Router Route is installed,
1148 then schedule re-calculate External routes. */
1149 if (1)
paul68980082003-03-25 05:07:42 +00001150 ospf_ase_calculate_schedule (ospf);
paul718e3742002-12-13 20:15:29 +00001151
paul68980082003-03-25 05:07:42 +00001152 ospf_ase_calculate_timer_add (ospf);
paul718e3742002-12-13 20:15:29 +00001153
1154 /* Update routing table. */
paul68980082003-03-25 05:07:42 +00001155 ospf_route_install (ospf, new_table);
paul718e3742002-12-13 20:15:29 +00001156
1157 /* Update ABR/ASBR routing table */
paul68980082003-03-25 05:07:42 +00001158 if (ospf->old_rtrs)
paul718e3742002-12-13 20:15:29 +00001159 {
1160 /* old_rtrs's node holds linked list of ospf_route. --kunihiro. */
paul68980082003-03-25 05:07:42 +00001161 /* ospf_route_delete (ospf->old_rtrs); */
1162 ospf_rtrs_free (ospf->old_rtrs);
paul718e3742002-12-13 20:15:29 +00001163 }
1164
paul68980082003-03-25 05:07:42 +00001165 ospf->old_rtrs = ospf->new_rtrs;
1166 ospf->new_rtrs = new_rtrs;
paul718e3742002-12-13 20:15:29 +00001167
paul0c0f9cd2003-06-06 23:27:04 +00001168 if (IS_OSPF_ABR (ospf))
paul68980082003-03-25 05:07:42 +00001169 ospf_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001170
1171 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001172 zlog_debug ("SPF: calculation complete");
paul718e3742002-12-13 20:15:29 +00001173
1174 return 0;
1175}
1176
1177/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
1178 set timer for SPF calc. */
1179void
paul68980082003-03-25 05:07:42 +00001180ospf_spf_calculate_schedule (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00001181{
1182 time_t ht, delay;
1183
1184 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001185 zlog_debug ("SPF: calculation timer scheduled");
paul718e3742002-12-13 20:15:29 +00001186
1187 /* OSPF instance does not exist. */
paul68980082003-03-25 05:07:42 +00001188 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001189 return;
1190
1191 /* SPF calculation timer is already scheduled. */
paul68980082003-03-25 05:07:42 +00001192 if (ospf->t_spf_calc)
paul718e3742002-12-13 20:15:29 +00001193 {
1194 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001195 zlog_debug ("SPF: calculation timer is already scheduled: %p",
paul0c0f9cd2003-06-06 23:27:04 +00001196 ospf->t_spf_calc);
paul718e3742002-12-13 20:15:29 +00001197 return;
1198 }
1199
paul68980082003-03-25 05:07:42 +00001200 ht = time (NULL) - ospf->ts_spf;
paul718e3742002-12-13 20:15:29 +00001201
1202 /* Get SPF calculation delay time. */
paul68980082003-03-25 05:07:42 +00001203 if (ht < ospf->spf_holdtime)
paul718e3742002-12-13 20:15:29 +00001204 {
paul68980082003-03-25 05:07:42 +00001205 if (ospf->spf_holdtime - ht < ospf->spf_delay)
paul0c0f9cd2003-06-06 23:27:04 +00001206 delay = ospf->spf_delay;
paul718e3742002-12-13 20:15:29 +00001207 else
paul0c0f9cd2003-06-06 23:27:04 +00001208 delay = ospf->spf_holdtime - ht;
paul718e3742002-12-13 20:15:29 +00001209 }
1210 else
paul68980082003-03-25 05:07:42 +00001211 delay = ospf->spf_delay;
paul718e3742002-12-13 20:15:29 +00001212
1213 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001214 zlog_debug ("SPF: calculation timer delay = %ld", (long)delay);
paul68980082003-03-25 05:07:42 +00001215 ospf->t_spf_calc =
1216 thread_add_timer (master, ospf_spf_calculate_timer, ospf, delay);
paul718e3742002-12-13 20:15:29 +00001217}