blob: c7c25f8d4eb5e78c90d0e205d535740c16ef9a07 [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 () */
32
33#include "ospfd/ospfd.h"
34#include "ospfd/ospf_interface.h"
35#include "ospfd/ospf_ism.h"
36#include "ospfd/ospf_asbr.h"
37#include "ospfd/ospf_lsa.h"
38#include "ospfd/ospf_lsdb.h"
39#include "ospfd/ospf_neighbor.h"
40#include "ospfd/ospf_nsm.h"
41#include "ospfd/ospf_spf.h"
42#include "ospfd/ospf_route.h"
43#include "ospfd/ospf_ia.h"
44#include "ospfd/ospf_ase.h"
45#include "ospfd/ospf_abr.h"
46#include "ospfd/ospf_dump.h"
47
48#define DEBUG
49
50struct vertex_nexthop *
51vertex_nexthop_new (struct vertex *parent)
52{
53 struct vertex_nexthop *new;
54
55 new = XCALLOC (MTYPE_OSPF_NEXTHOP, sizeof (struct vertex_nexthop));
56 new->parent = parent;
57
58 return new;
59}
60
61void
62vertex_nexthop_free (struct vertex_nexthop *nh)
63{
64 XFREE (MTYPE_OSPF_NEXTHOP, nh);
65}
66
67struct vertex_nexthop *
68vertex_nexthop_dup (struct vertex_nexthop *nh)
69{
70 struct vertex_nexthop *new;
71
72 new = vertex_nexthop_new (nh->parent);
73
74 new->oi = nh->oi;
75 new->router = nh->router;
76
77 return new;
78}
paul718e3742002-12-13 20:15:29 +000079
paul0c0f9cd2003-06-06 23:27:04 +000080
paul718e3742002-12-13 20:15:29 +000081struct vertex *
82ospf_vertex_new (struct ospf_lsa *lsa)
83{
84 struct vertex *new;
85
86 new = XMALLOC (MTYPE_OSPF_VERTEX, sizeof (struct vertex));
87 memset (new, 0, sizeof (struct vertex));
88
89 new->flags = 0;
90 new->type = lsa->data->type;
91 new->id = lsa->data->id;
92 new->lsa = lsa->data;
93 new->distance = 0;
94 new->child = list_new ();
95 new->nexthop = list_new ();
pauld355bfa2004-04-08 07:43:45 +000096 new->backlink = -1;
paul718e3742002-12-13 20:15:29 +000097
98 return new;
99}
100
101void
102ospf_vertex_free (struct vertex *v)
103{
hasso52dc7ee2004-09-23 19:18:23 +0000104 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000105
106 list_delete (v->child);
107
108 if (listcount (v->nexthop) > 0)
109 for (node = listhead (v->nexthop); node; nextnode (node))
110 vertex_nexthop_free (node->data);
111
112 list_delete (v->nexthop);
113
114 XFREE (MTYPE_OSPF_VERTEX, v);
115}
116
117void
hassoeb1ce602004-10-08 08:17:22 +0000118ospf_vertex_dump(const char *msg, struct vertex *v,
gdt630e4802004-08-31 17:28:41 +0000119 int print_nexthops, int print_children)
120{
121 if ( ! IS_DEBUG_OSPF_EVENT)
122 return;
123
124 zlog_info("%s %s vertex %s distance %u backlink %d flags %u",
125 msg,
126 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
127 inet_ntoa(v->lsa->id),
128 v->distance,
129 v->backlink,
130 (unsigned int)v->flags);
131
132 if (print_nexthops)
133 {
hasso52dc7ee2004-09-23 19:18:23 +0000134 struct listnode *nnode;
gdt630e4802004-08-31 17:28:41 +0000135 for (nnode = listhead (v->nexthop); nnode; nextnode (nnode))
136 {
137 char buf1[BUFSIZ];
138 char buf2[BUFSIZ];
139 struct vertex_nexthop *nexthop;
140
141 nexthop = getdata (nnode);
142 if (nexthop)
143 {
144 zlog_info (" nexthop %s interface %s parent %s",
145 inet_ntop(AF_INET, &nexthop->router, buf1, BUFSIZ),
146 nexthop->oi ? IF_NAME(nexthop->oi) : "NULL",
147 nexthop->parent ? inet_ntop(AF_INET,
148 &nexthop->parent->id,
149 buf2, BUFSIZ)
150 : "NULL");
151 }
152 }
153 }
154
155 if (print_children)
156 {
hasso52dc7ee2004-09-23 19:18:23 +0000157 struct listnode *cnode;
gdt630e4802004-08-31 17:28:41 +0000158 for (cnode = listhead (v->child); cnode; nextnode (cnode))
159 {
160 struct vertex *cv = getdata (cnode);
161 if (cv)
162 ospf_vertex_dump(" child:", cv, 0, 0);
163 }
164 }
165}
166
167
168/* Add a vertex to the list of children in each of its parents. */
169void
paul718e3742002-12-13 20:15:29 +0000170ospf_vertex_add_parent (struct vertex *v)
171{
172 struct vertex_nexthop *nh;
hasso52dc7ee2004-09-23 19:18:23 +0000173 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000174
175 for (node = listhead (v->nexthop); node; nextnode (node))
176 {
177 nh = (struct vertex_nexthop *) getdata (node);
178
179 /* No need to add two links from the same parent. */
180 if (listnode_lookup (nh->parent->child, v) == NULL)
paul0c0f9cd2003-06-06 23:27:04 +0000181 listnode_add (nh->parent->child, v);
paul718e3742002-12-13 20:15:29 +0000182 }
183}
184
185void
186ospf_spf_init (struct ospf_area *area)
187{
188 struct vertex *v;
189
190 /* Create root node. */
191 v = ospf_vertex_new (area->router_lsa_self);
192
193 area->spf = v;
194
195 /* Reset ABR and ASBR router counts. */
196 area->abr_count = 0;
197 area->asbr_count = 0;
198}
199
gdt630e4802004-08-31 17:28:41 +0000200/* Check if the vertex represented by lsa is on the SPF tree. */
paul718e3742002-12-13 20:15:29 +0000201int
202ospf_spf_has_vertex (struct route_table *rv, struct route_table *nv,
203 struct lsa_header *lsa)
204{
205 struct prefix p;
206 struct route_node *rn;
207
208 p.family = AF_INET;
209 p.prefixlen = IPV4_MAX_BITLEN;
210 p.u.prefix4 = lsa->id;
211
212 if (lsa->type == OSPF_ROUTER_LSA)
213 rn = route_node_get (rv, &p);
214 else
215 rn = route_node_get (nv, &p);
216
217 if (rn->info != NULL)
218 {
219 route_unlock_node (rn);
220 return 1;
221 }
222 return 0;
223}
224
gdt630e4802004-08-31 17:28:41 +0000225/* Find the vertex specified by the given id and LSA type
226 * in vlist (the candidate list).
227 */
hasso52dc7ee2004-09-23 19:18:23 +0000228struct listnode *
229ospf_vertex_lookup (struct list *vlist, struct in_addr id, int type)
paul718e3742002-12-13 20:15:29 +0000230{
hasso52dc7ee2004-09-23 19:18:23 +0000231 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000232 struct vertex *v;
233
234 for (node = listhead (vlist); node; nextnode (node))
235 {
236 v = (struct vertex *) getdata (node);
237 if (IPV4_ADDR_SAME (&id, &v->id) && type == v->type)
238 return node;
239 }
240
241 return NULL;
242}
243
pauld355bfa2004-04-08 07:43:45 +0000244/* return index of link back to V from W, or -1 if no link found */
paul718e3742002-12-13 20:15:29 +0000245int
246ospf_lsa_has_link (struct lsa_header *w, struct lsa_header *v)
247{
hassoeb1ce602004-10-08 08:17:22 +0000248 unsigned int i, length;
paul718e3742002-12-13 20:15:29 +0000249 struct router_lsa *rl;
250 struct network_lsa *nl;
251
252 /* In case of W is Network LSA. */
253 if (w->type == OSPF_NETWORK_LSA)
254 {
255 if (v->type == OSPF_NETWORK_LSA)
pauld355bfa2004-04-08 07:43:45 +0000256 return -1;
paul718e3742002-12-13 20:15:29 +0000257
258 nl = (struct network_lsa *) w;
259 length = (ntohs (w->length) - OSPF_LSA_HEADER_SIZE - 4) / 4;
paul0c0f9cd2003-06-06 23:27:04 +0000260
paul718e3742002-12-13 20:15:29 +0000261 for (i = 0; i < length; i++)
262 if (IPV4_ADDR_SAME (&nl->routers[i], &v->id))
pauld355bfa2004-04-08 07:43:45 +0000263 return i;
264 return -1;
paul718e3742002-12-13 20:15:29 +0000265 }
266
267 /* In case of W is Router LSA. */
268 if (w->type == OSPF_ROUTER_LSA)
269 {
270 rl = (struct router_lsa *) w;
271
272 length = ntohs (w->length);
273
274 for (i = 0;
paul0c0f9cd2003-06-06 23:27:04 +0000275 i < ntohs (rl->links) && length >= sizeof (struct router_lsa);
276 i++, length -= 12)
paul718e3742002-12-13 20:15:29 +0000277 {
278 switch (rl->link[i].type)
279 {
280 case LSA_LINK_TYPE_POINTOPOINT:
281 case LSA_LINK_TYPE_VIRTUALLINK:
282 /* Router LSA ID. */
283 if (v->type == OSPF_ROUTER_LSA &&
284 IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
285 {
pauld355bfa2004-04-08 07:43:45 +0000286 return i;
paul718e3742002-12-13 20:15:29 +0000287 }
288 break;
289 case LSA_LINK_TYPE_TRANSIT:
290 /* Network LSA ID. */
291 if (v->type == OSPF_NETWORK_LSA &&
292 IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
293 {
pauld355bfa2004-04-08 07:43:45 +0000294 return i;
paul0c0f9cd2003-06-06 23:27:04 +0000295 }
paul718e3742002-12-13 20:15:29 +0000296 break;
297 case LSA_LINK_TYPE_STUB:
298 /* Not take into count? */
299 continue;
300 default:
301 break;
302 }
303 }
304 }
pauld355bfa2004-04-08 07:43:45 +0000305 return -1;
paul718e3742002-12-13 20:15:29 +0000306}
307
308/* Add the nexthop to the list, only if it is unique.
309 * If it's not unique, free the nexthop entry.
310 */
311void
hasso52dc7ee2004-09-23 19:18:23 +0000312ospf_nexthop_add_unique (struct vertex_nexthop *new, struct list *nexthop)
paul718e3742002-12-13 20:15:29 +0000313{
314 struct vertex_nexthop *nh;
hasso52dc7ee2004-09-23 19:18:23 +0000315 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000316 int match;
317
318 match = 0;
319 for (node = listhead (nexthop); node; nextnode (node))
320 {
321 nh = node->data;
322
323 /* Compare the two entries. */
324 /* XXX
325 * Comparing the parent preserves the shortest path tree
326 * structure even when the nexthops are identical.
327 */
328 if (nh->oi == new->oi &&
paul0c0f9cd2003-06-06 23:27:04 +0000329 IPV4_ADDR_SAME (&nh->router, &new->router) &&
330 nh->parent == new->parent)
331 {
332 match = 1;
333 break;
334 }
paul718e3742002-12-13 20:15:29 +0000335 }
336
337 if (!match)
338 listnode_add (nexthop, new);
339 else
340 vertex_nexthop_free (new);
341}
342
343/* Merge entries in list b into list a. */
344void
hasso52dc7ee2004-09-23 19:18:23 +0000345ospf_nexthop_merge (struct list *a, struct list *b)
paul718e3742002-12-13 20:15:29 +0000346{
347 struct listnode *n;
348
349 for (n = listhead (b); n; nextnode (n))
350 {
351 ospf_nexthop_add_unique (n->data, a);
352 }
353}
354
355#define ROUTER_LSA_MIN_SIZE 12
356#define ROUTER_LSA_TOS_SIZE 4
357
gdt630e4802004-08-31 17:28:41 +0000358/* Find the next link after prev_link from v to w. If prev_link is
359 * NULL, return the first link from v to w. Ignore stub and virtual links;
360 * these link types will never be returned.
361 */
paul718e3742002-12-13 20:15:29 +0000362struct router_lsa_link *
363ospf_get_next_link (struct vertex *v, struct vertex *w,
paul0c0f9cd2003-06-06 23:27:04 +0000364 struct router_lsa_link *prev_link)
paul718e3742002-12-13 20:15:29 +0000365{
366 u_char *p;
367 u_char *lim;
368 struct router_lsa_link *l;
369
370 if (prev_link == NULL)
gdt630e4802004-08-31 17:28:41 +0000371 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +0000372 else
373 {
paul0c0f9cd2003-06-06 23:27:04 +0000374 p = (u_char *) prev_link;
paul718e3742002-12-13 20:15:29 +0000375 p += (ROUTER_LSA_MIN_SIZE +
376 (prev_link->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
377 }
paul0c0f9cd2003-06-06 23:27:04 +0000378
paul718e3742002-12-13 20:15:29 +0000379 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
380
381 while (p < lim)
382 {
383 l = (struct router_lsa_link *) p;
384
paul0c0f9cd2003-06-06 23:27:04 +0000385 p += (ROUTER_LSA_MIN_SIZE + (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
paul718e3742002-12-13 20:15:29 +0000386
387 if (l->m[0].type == LSA_LINK_TYPE_STUB)
388 continue;
389
390 /* Defer NH calculation via VLs until summaries from
391 transit areas area confidered */
392
393 if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK)
paul0c0f9cd2003-06-06 23:27:04 +0000394 continue;
paul718e3742002-12-13 20:15:29 +0000395
396 if (IPV4_ADDR_SAME (&l->link_id, &w->id))
paul0c0f9cd2003-06-06 23:27:04 +0000397 return l;
paul718e3742002-12-13 20:15:29 +0000398 }
399
400 return NULL;
401}
402
paul75ee0b82004-08-05 09:10:31 +0000403/*
404 * Consider supplied next-hop for inclusion to the supplied list of
405 * equal-cost next-hops, adjust list as neccessary.
406 *
407 * (Discussed on GNU Zebra list 27 May 2003, [zebra 19184])
408 *
409 * Note that below is a bit of a hack, and limits ECMP to paths that go to
410 * same nexthop. Where as paths via inequal output_cost interfaces could
411 * still quite easily be ECMP due to remote cost differences.
412 *
413 * TODO: It really should be done by way of recording currently valid
414 * backlinks and determining the appropriate nexthops from the list of
415 * backlinks, or even simpler, just flushing nexthop list if we find a lower
416 * cost path to a candidate vertex in SPF, maybe.
paulbf9392c2003-06-06 23:23:36 +0000417 */
paul0c0f9cd2003-06-06 23:27:04 +0000418void
419ospf_spf_consider_nexthop (struct list *nexthops,
420 struct vertex_nexthop *newhop)
paulbf9392c2003-06-06 23:23:36 +0000421{
paulbf9392c2003-06-06 23:23:36 +0000422 struct vertex_nexthop *hop;
paul75ee0b82004-08-05 09:10:31 +0000423 struct listnode *ln, *nn;
paul0c0f9cd2003-06-06 23:27:04 +0000424
paul75ee0b82004-08-05 09:10:31 +0000425 /* nexthop list should contain only the set of nexthops that have the lowest
426 * equal cost
427 */
428 if (nexthops->head != NULL)
429 {
430 hop = getdata (nexthops->head);
431
432 /* weed out hops with higher cost than the newhop */
433 if (hop->oi->output_cost > newhop->oi->output_cost)
434 {
435 /* delete the existing nexthops */
436 for (ln = nexthops->head; ln; ln = nn)
437 {
438 nn = ln->next;
439 hop = getdata (ln);
440
441 listnode_delete (nexthops, hop);
442 vertex_nexthop_free (hop);
443 }
444 }
445 else if (hop->oi->output_cost < newhop->oi->output_cost)
paul0c0f9cd2003-06-06 23:27:04 +0000446 return;
paul75ee0b82004-08-05 09:10:31 +0000447 }
paul0c0f9cd2003-06-06 23:27:04 +0000448
paulbf9392c2003-06-06 23:23:36 +0000449 /* new hop is <= existing hops, add it */
paul0c0f9cd2003-06-06 23:27:04 +0000450 listnode_add (nexthops, newhop);
paulbf9392c2003-06-06 23:23:36 +0000451
452 return;
453}
454
gdt630e4802004-08-31 17:28:41 +0000455/* 16.1.1. Calculate nexthop from root through V (parent) to
456 * vertex W (destination).
457 */
paul718e3742002-12-13 20:15:29 +0000458void
459ospf_nexthop_calculation (struct ospf_area *area,
460 struct vertex *v, struct vertex *w)
461{
hasso52dc7ee2004-09-23 19:18:23 +0000462 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000463 struct vertex_nexthop *nh, *x;
464 struct ospf_interface *oi = NULL;
465 struct router_lsa_link *l = NULL;
paul0c0f9cd2003-06-06 23:27:04 +0000466
467
paul718e3742002-12-13 20:15:29 +0000468 if (IS_DEBUG_OSPF_EVENT)
gdt630e4802004-08-31 17:28:41 +0000469 {
470 zlog_info ("ospf_nexthop_calculation(): Start");
471 ospf_vertex_dump("V (parent):", v, 1, 1);
472 ospf_vertex_dump("W (dest) :", w, 1, 1);
473 }
paul718e3742002-12-13 20:15:29 +0000474
paul718e3742002-12-13 20:15:29 +0000475 if (v == area->spf)
476 {
gdt630e4802004-08-31 17:28:41 +0000477 /* 16.1.1 para 4. In the first case, the parent vertex (V) is the
478 root (the calculating router itself). This means that the
479 destination is either a directly connected network or directly
480 connected router. The outgoing interface in this case is simply
481 the OSPF interface connecting to the destination network/router.
482 */
483
paul718e3742002-12-13 20:15:29 +0000484 if (w->type == OSPF_VERTEX_ROUTER)
paul0c0f9cd2003-06-06 23:27:04 +0000485 {
486 while ((l = ospf_get_next_link (v, w, l)))
487 {
gdt630e4802004-08-31 17:28:41 +0000488 /* l is a link from v to w
489 * l2 will be link from w to v
490 */
paul0c0f9cd2003-06-06 23:27:04 +0000491 struct router_lsa_link *l2 = NULL;
492
gdt630e4802004-08-31 17:28:41 +0000493 if (IS_DEBUG_OSPF_EVENT)
494 {
495 char buf1[BUFSIZ];
gdt630e4802004-08-31 17:28:41 +0000496 zlog_info("ospf_nexthop_calculation(): considering link "
497 "type %d link_id %s link_data %s",
498 l->m[0].type,
499 inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ),
500 inet_ntop (AF_INET, &l->link_data, buf1, BUFSIZ));
501 }
502
paul0c0f9cd2003-06-06 23:27:04 +0000503 if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT)
504 {
gdt630e4802004-08-31 17:28:41 +0000505 /* If the destination is a router which connects to
506 the calculating router via a Point-to-MultiPoint
507 network, the destination's next hop IP address(es)
508 can be determined by examining the destination's
509 router-LSA: each link pointing back to the
510 calculating router and having a Link Data field
511 belonging to the Point-to-MultiPoint network
512 provides an IP address of the next hop router.
513
514 At this point l is a link from V to W, and V is the
515 root ("us"). Find the local interface associated
516 with l (its address is in l->link_data). If it
517 is a point-to-multipoint interface, then look through
518 the links in the opposite direction (W to V). If
519 any of them have an address that lands within the
520 subnet declared by the PtMP link, then that link
521 is a constituent of the PtMP link, and its address is
522 a nexthop address for V.
523 */
paul68980082003-03-25 05:07:42 +0000524 oi = ospf_if_is_configured (area->ospf, &l->link_data);
paul7afa08d2002-12-13 20:59:45 +0000525 if (oi && oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
paul0c0f9cd2003-06-06 23:27:04 +0000526 {
527 struct prefix_ipv4 la;
gdt630e4802004-08-31 17:28:41 +0000528
529 la.family = AF_INET;
paul0c0f9cd2003-06-06 23:27:04 +0000530 la.prefixlen = oi->address->prefixlen;
gdt630e4802004-08-31 17:28:41 +0000531
532 /* V links to W on PtMP interface
533 - find the interface address on W */
paul0c0f9cd2003-06-06 23:27:04 +0000534 while ((l2 = ospf_get_next_link (w, v, l2)))
535 {
536 la.prefix = l2->link_data;
537
538 if (prefix_cmp ((struct prefix *) &la,
539 oi->address) == 0)
540 /* link_data is on our PtMP network */
541 break;
542 }
gdt630e4802004-08-31 17:28:41 +0000543 } /* end l is on point-to-multipoint link */
paul0c0f9cd2003-06-06 23:27:04 +0000544 else
545 {
gdt630e4802004-08-31 17:28:41 +0000546 /* l is a regular point-to-point link.
547 Look for a link from W to V.
548 */
paul0c0f9cd2003-06-06 23:27:04 +0000549 while ((l2 = ospf_get_next_link (w, v, l2)))
550 {
551 oi = ospf_if_is_configured (area->ospf,
552 &(l2->link_data));
553
554 if (oi == NULL)
555 continue;
556
557 if (!IPV4_ADDR_SAME (&oi->address->u.prefix4,
558 &l->link_data))
559 continue;
560
561 break;
562 }
563 }
564
565 if (oi && l2)
566 {
gdt630e4802004-08-31 17:28:41 +0000567 /* found all necessary info to build nexthop */
paul0c0f9cd2003-06-06 23:27:04 +0000568 nh = vertex_nexthop_new (v);
569 nh->oi = oi;
570 nh->router = l2->link_data;
571 ospf_spf_consider_nexthop (w->nexthop, nh);
572 }
gdt630e4802004-08-31 17:28:41 +0000573 else
574 {
575 zlog_info("ospf_nexthop_calculation(): "
576 "could not determine nexthop for link");
577 }
578 } /* end point-to-point link from V to W */
579 } /* end iterate over links in W */
580 } /* end W is a Router vertex */
paul718e3742002-12-13 20:15:29 +0000581 else
paul0c0f9cd2003-06-06 23:27:04 +0000582 {
gdt630e4802004-08-31 17:28:41 +0000583 assert(w->type == OSPF_VERTEX_NETWORK);
paul0c0f9cd2003-06-06 23:27:04 +0000584 while ((l = ospf_get_next_link (v, w, l)))
585 {
586 oi = ospf_if_is_configured (area->ospf, &(l->link_data));
587 if (oi)
588 {
589 nh = vertex_nexthop_new (v);
590 nh->oi = oi;
591 nh->router.s_addr = 0;
paul75ee0b82004-08-05 09:10:31 +0000592 ospf_spf_consider_nexthop (w->nexthop, nh);
paul0c0f9cd2003-06-06 23:27:04 +0000593 }
594 }
595 }
paul718e3742002-12-13 20:15:29 +0000596 return;
gdt630e4802004-08-31 17:28:41 +0000597 } /* end V is the root */
598
599 /* Check if W's parent is a network connected to root. */
paul718e3742002-12-13 20:15:29 +0000600 else if (v->type == OSPF_VERTEX_NETWORK)
601 {
gdt630e4802004-08-31 17:28:41 +0000602 /* See if any of V's parents are the root. */
paul718e3742002-12-13 20:15:29 +0000603 for (node = listhead (v->nexthop); node; nextnode (node))
604 {
gdt630e4802004-08-31 17:28:41 +0000605 x = (struct vertex_nexthop *) getdata (node);
606 if (x->parent == area->spf) /* connects to root? */
607 {
608 /* 16.1.1 para 5. ...the parent vertex is a network that
609 * directly connects the calculating router to the destination
610 * router. The list of next hops is then determined by
611 * examining the destination's router-LSA...
612 */
613
614 assert(w->type == OSPF_VERTEX_ROUTER);
paul0c0f9cd2003-06-06 23:27:04 +0000615 while ((l = ospf_get_next_link (w, v, l)))
616 {
gdt630e4802004-08-31 17:28:41 +0000617 /* ...For each link in the router-LSA that points back to the
618 * parent network, the link's Link Data field provides the IP
619 * address of a next hop router. The outgoing interface to
620 * use can then be derived from the next hop IP address (or
621 * it can be inherited from the parent network).
622 */
paul0c0f9cd2003-06-06 23:27:04 +0000623 nh = vertex_nexthop_new (v);
624 nh->oi = x->oi;
625 nh->router = l->link_data;
paul75ee0b82004-08-05 09:10:31 +0000626 ospf_spf_consider_nexthop (w->nexthop, nh);
paul0c0f9cd2003-06-06 23:27:04 +0000627 }
628 return;
629 }
paul718e3742002-12-13 20:15:29 +0000630 }
631 }
632
gdt630e4802004-08-31 17:28:41 +0000633 /* 16.1.1 para 4. If there is at least one intervening router in the
634 * current shortest path between the destination and the root, the
635 * destination simply inherits the set of next hops from the
636 * parent.
637 */
paul718e3742002-12-13 20:15:29 +0000638 for (node = listhead (v->nexthop); node; nextnode (node))
639 {
640 nh = vertex_nexthop_dup (node->data);
641 nh->parent = v;
642 ospf_nexthop_add_unique (nh, w->nexthop);
643 }
644}
645
gdt630e4802004-08-31 17:28:41 +0000646/* Add a vertex to the SPF candidate list. */
paul718e3742002-12-13 20:15:29 +0000647void
hasso52dc7ee2004-09-23 19:18:23 +0000648ospf_install_candidate (struct list *candidate, struct vertex *w)
paul718e3742002-12-13 20:15:29 +0000649{
hasso52dc7ee2004-09-23 19:18:23 +0000650 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000651 struct vertex *cw;
652
gdt630e4802004-08-31 17:28:41 +0000653 ospf_vertex_dump("ospf_install_candidate(): add to candidate list", w, 1, 1);
654
paul718e3742002-12-13 20:15:29 +0000655 if (list_isempty (candidate))
656 {
657 listnode_add (candidate, w);
658 return;
659 }
660
661 /* Install vertex with sorting by distance. */
662 for (node = listhead (candidate); node; nextnode (node))
663 {
664 cw = (struct vertex *) getdata (node);
665 if (cw->distance > w->distance)
666 {
667 list_add_node_prev (candidate, node, w);
668 break;
669 }
670 else if (node->next == NULL)
671 {
672 list_add_node_next (candidate, node, w);
673 break;
674 }
675 }
gdt630e4802004-08-31 17:28:41 +0000676
677 if (IS_DEBUG_OSPF_EVENT)
678 {
679 zlog_info("ospf_install_candidate(): candidate list now contains:");
680 for (node = listhead (candidate); node; nextnode (node))
681 {
682 cw = (struct vertex *) getdata (node);
683 ospf_vertex_dump(" candidate:", cw, 0, 0);
684 }
685 }
paul718e3742002-12-13 20:15:29 +0000686}
687
gdt630e4802004-08-31 17:28:41 +0000688/* RFC2328 Section 16.1 (2).
689 * v is on the SPF tree. Examine the links in v's LSA. Update the list
690 * of candidates with any vertices not already on the list. If a lower-cost
691 * path is found to a vertex already on the candidate list, store the new cost.
692 */
paul718e3742002-12-13 20:15:29 +0000693void
694ospf_spf_next (struct vertex *v, struct ospf_area *area,
hasso52dc7ee2004-09-23 19:18:23 +0000695 struct list *candidate, struct route_table *rv,
696 struct route_table *nv)
paul718e3742002-12-13 20:15:29 +0000697{
698 struct ospf_lsa *w_lsa = NULL;
699 struct vertex *w, *cw;
700 u_char *p;
701 u_char *lim;
702 struct router_lsa_link *l = NULL;
703 struct in_addr *r;
hasso52dc7ee2004-09-23 19:18:23 +0000704 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000705 int type = 0;
706
707 /* If this is a router-LSA, and bit V of the router-LSA (see Section
708 A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE. */
709 if (v->type == OSPF_VERTEX_ROUTER)
710 {
711 if (IS_ROUTER_LSA_VIRTUAL ((struct router_lsa *) v->lsa))
712 area->transit = OSPF_TRANSIT_TRUE;
713 }
714
715 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul0c0f9cd2003-06-06 23:27:04 +0000716 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
717
paul718e3742002-12-13 20:15:29 +0000718 while (p < lim)
719 {
pauld355bfa2004-04-08 07:43:45 +0000720 int link = -1; /* link index for w's back link */
721
paul718e3742002-12-13 20:15:29 +0000722 /* In case of V is Router-LSA. */
723 if (v->lsa->type == OSPF_ROUTER_LSA)
724 {
725 l = (struct router_lsa_link *) p;
726
paul0c0f9cd2003-06-06 23:27:04 +0000727 p += (ROUTER_LSA_MIN_SIZE +
paul718e3742002-12-13 20:15:29 +0000728 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
729
730 /* (a) If this is a link to a stub network, examine the next
731 link in V's LSA. Links to stub networks will be
732 considered in the second stage of the shortest path
733 calculation. */
734 if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB)
735 continue;
736
737 /* (b) Otherwise, W is a transit vertex (router or transit
738 network). Look up the vertex W's LSA (router-LSA or
739 network-LSA) in Area A's link state database. */
740 switch (type)
741 {
742 case LSA_LINK_TYPE_POINTOPOINT:
743 case LSA_LINK_TYPE_VIRTUALLINK:
744 if (type == LSA_LINK_TYPE_VIRTUALLINK)
paul0c0f9cd2003-06-06 23:27:04 +0000745 {
746 if (IS_DEBUG_OSPF_EVENT)
747 zlog_info ("looking up LSA through VL: %s",
748 inet_ntoa (l->link_id));
749 }
paul718e3742002-12-13 20:15:29 +0000750
751 w_lsa = ospf_lsa_lookup (area, OSPF_ROUTER_LSA, l->link_id,
752 l->link_id);
753 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000754 {
755 if (IS_DEBUG_OSPF_EVENT)
gdt630e4802004-08-31 17:28:41 +0000756 zlog_info ("found Router LSA %s", inet_ntoa (l->link_id));
paul0c0f9cd2003-06-06 23:27:04 +0000757 }
paul718e3742002-12-13 20:15:29 +0000758 break;
759 case LSA_LINK_TYPE_TRANSIT:
paul0c0f9cd2003-06-06 23:27:04 +0000760 if (IS_DEBUG_OSPF_EVENT)
paul718e3742002-12-13 20:15:29 +0000761
paul0c0f9cd2003-06-06 23:27:04 +0000762 zlog_info ("Looking up Network LSA, ID: %s",
763 inet_ntoa (l->link_id));
paul718e3742002-12-13 20:15:29 +0000764 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_NETWORK_LSA,
paul0c0f9cd2003-06-06 23:27:04 +0000765 l->link_id);
paul718e3742002-12-13 20:15:29 +0000766 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000767 if (IS_DEBUG_OSPF_EVENT)
768 zlog_info ("found the LSA");
paul718e3742002-12-13 20:15:29 +0000769 break;
770 default:
paul0c0f9cd2003-06-06 23:27:04 +0000771 zlog_warn ("Invalid LSA link type %d", type);
paul718e3742002-12-13 20:15:29 +0000772 continue;
773 }
774 }
775 else
776 {
777 /* In case of V is Network-LSA. */
paul0c0f9cd2003-06-06 23:27:04 +0000778 r = (struct in_addr *) p;
paul718e3742002-12-13 20:15:29 +0000779 p += sizeof (struct in_addr);
780
781 /* Lookup the vertex W's LSA. */
782 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_ROUTER_LSA, *r);
783 }
784
785 /* (b cont.) If the LSA does not exist, or its LS age is equal
786 to MaxAge, or it does not have a link back to vertex V,
787 examine the next link in V's LSA.[23] */
788 if (w_lsa == NULL)
789 continue;
790
791 if (IS_LSA_MAXAGE (w_lsa))
792 continue;
793
pauld355bfa2004-04-08 07:43:45 +0000794 if ( (link = ospf_lsa_has_link (w_lsa->data, v->lsa)) < 0 )
paul718e3742002-12-13 20:15:29 +0000795 {
paul0c0f9cd2003-06-06 23:27:04 +0000796 if (IS_DEBUG_OSPF_EVENT)
797 zlog_info ("The LSA doesn't have a link back");
paul718e3742002-12-13 20:15:29 +0000798 continue;
799 }
800
801 /* (c) If vertex W is already on the shortest-path tree, examine
802 the next link in the LSA. */
803 if (ospf_spf_has_vertex (rv, nv, w_lsa->data))
804 {
paul0c0f9cd2003-06-06 23:27:04 +0000805 if (IS_DEBUG_OSPF_EVENT)
806 zlog_info ("The LSA is already in SPF");
paul718e3742002-12-13 20:15:29 +0000807 continue;
808 }
809
810 /* (d) Calculate the link state cost D of the resulting path
811 from the root to vertex W. D is equal to the sum of the link
812 state cost of the (already calculated) shortest path to
813 vertex V and the advertised cost of the link between vertices
814 V and W. If D is: */
815
816 /* prepare vertex W. */
817 w = ospf_vertex_new (w_lsa);
818
pauld355bfa2004-04-08 07:43:45 +0000819 /* Save W's back link index number, for use by virtual links */
820 w->backlink = link;
821
paul718e3742002-12-13 20:15:29 +0000822 /* calculate link cost D. */
823 if (v->lsa->type == OSPF_ROUTER_LSA)
gdt630e4802004-08-31 17:28:41 +0000824 w->distance = v->distance + ntohs (l->m[0].metric);
825 else /* v is not a Router-LSA */
826 w->distance = v->distance;
paul718e3742002-12-13 20:15:29 +0000827
828 /* Is there already vertex W in candidate list? */
829 node = ospf_vertex_lookup (candidate, w->id, w->type);
830 if (node == NULL)
831 {
gdt630e4802004-08-31 17:28:41 +0000832 /* W is a new candidate. Calculate nexthop to W and add W
833 * to the candidate list.
834 */
paul718e3742002-12-13 20:15:29 +0000835 ospf_nexthop_calculation (area, v, w);
836
837 ospf_install_candidate (candidate, w);
838 }
839 else
840 {
gdt630e4802004-08-31 17:28:41 +0000841 /* W is already on the candidate list; call it cw.
842 * Compare the previously calculated cost (cw->distance)
843 * with the cost we just determined (w->distance) to see
844 * if we've found a shorter path.
845 */
paul718e3742002-12-13 20:15:29 +0000846 cw = (struct vertex *) getdata (node);
847
gdt630e4802004-08-31 17:28:41 +0000848 /* If the previous cost was lower, we didn't find a
849 * shorter path, so we're done with w.
850 */
paul718e3742002-12-13 20:15:29 +0000851 if (cw->distance < w->distance)
852 {
853 ospf_vertex_free (w);
854 continue;
855 }
paul718e3742002-12-13 20:15:29 +0000856 else if (cw->distance == w->distance)
857 {
gdt630e4802004-08-31 17:28:41 +0000858 /* Found an equal-cost path to W. Calculate nexthop to W. */
paul718e3742002-12-13 20:15:29 +0000859 ospf_nexthop_calculation (area, v, w);
860 ospf_nexthop_merge (cw->nexthop, w->nexthop);
861 list_delete_all_node (w->nexthop);
862 ospf_vertex_free (w);
863 }
paul718e3742002-12-13 20:15:29 +0000864 else
865 {
gdt630e4802004-08-31 17:28:41 +0000866 /* Found a lower-cost path to W. Calculate nexthop to W. */
paul718e3742002-12-13 20:15:29 +0000867 ospf_nexthop_calculation (area, v, w);
868
869 /* Remove old vertex from candidate list. */
870 ospf_vertex_free (cw);
871 listnode_delete (candidate, cw);
872
gdt630e4802004-08-31 17:28:41 +0000873 /* Install new W to candidate list. */
paul718e3742002-12-13 20:15:29 +0000874 ospf_install_candidate (candidate, w);
875 }
gdt630e4802004-08-31 17:28:41 +0000876 } /* end W is already on the candidate list */
877 } /* end loop over the links in V's LSA */
paul718e3742002-12-13 20:15:29 +0000878}
879
880/* Add vertex V to SPF tree. */
881void
882ospf_spf_register (struct vertex *v, struct route_table *rv,
paul0c0f9cd2003-06-06 23:27:04 +0000883 struct route_table *nv)
paul718e3742002-12-13 20:15:29 +0000884{
885 struct prefix p;
886 struct route_node *rn;
887
gdt630e4802004-08-31 17:28:41 +0000888 ospf_vertex_dump("ospf_spf_register(): adding to SPF tree:", v, 1, 1);
889
paul718e3742002-12-13 20:15:29 +0000890 p.family = AF_INET;
891 p.prefixlen = IPV4_MAX_BITLEN;
892 p.u.prefix4 = v->id;
893
894 if (v->type == OSPF_VERTEX_ROUTER)
895 rn = route_node_get (rv, &p);
896 else
897 rn = route_node_get (nv, &p);
898
899 rn->info = v;
900}
901
902void
903ospf_spf_route_free (struct route_table *table)
904{
905 struct route_node *rn;
906 struct vertex *v;
907
908 for (rn = route_top (table); rn; rn = route_next (rn))
909 {
910 if ((v = rn->info))
paul0c0f9cd2003-06-06 23:27:04 +0000911 {
912 ospf_vertex_free (v);
913 rn->info = NULL;
914 }
paul718e3742002-12-13 20:15:29 +0000915
916 route_unlock_node (rn);
917 }
918
919 route_table_finish (table);
920}
921
922void
923ospf_spf_dump (struct vertex *v, int i)
924{
hasso52dc7ee2004-09-23 19:18:23 +0000925 struct listnode *cnode;
926 struct listnode *nnode;
paul718e3742002-12-13 20:15:29 +0000927 struct vertex_nexthop *nexthop;
928
929 if (v->type == OSPF_VERTEX_ROUTER)
930 {
931 if (IS_DEBUG_OSPF_EVENT)
paul0c0f9cd2003-06-06 23:27:04 +0000932 zlog_info ("SPF Result: %d [R] %s", i, inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000933 }
934 else
935 {
936 struct network_lsa *lsa = (struct network_lsa *) v->lsa;
937 if (IS_DEBUG_OSPF_EVENT)
paul0c0f9cd2003-06-06 23:27:04 +0000938 zlog_info ("SPF Result: %d [N] %s/%d", i, inet_ntoa (v->lsa->id),
939 ip_masklen (lsa->mask));
gdt630e4802004-08-31 17:28:41 +0000940 }
paul718e3742002-12-13 20:15:29 +0000941
gdt630e4802004-08-31 17:28:41 +0000942 for (nnode = listhead (v->nexthop); nnode; nextnode (nnode))
943 {
944 nexthop = getdata (nnode);
945 if (IS_DEBUG_OSPF_EVENT)
946 zlog_info (" nexthop %s", inet_ntoa (nexthop->router));
paul718e3742002-12-13 20:15:29 +0000947 }
948
949 i++;
950
951 for (cnode = listhead (v->child); cnode; nextnode (cnode))
952 {
953 v = getdata (cnode);
954 ospf_spf_dump (v, i);
955 }
956}
957
958/* Second stage of SPF calculation. */
959void
paul0c0f9cd2003-06-06 23:27:04 +0000960ospf_spf_process_stubs (struct ospf_area *area, struct vertex *v,
paul718e3742002-12-13 20:15:29 +0000961 struct route_table *rt)
962{
hasso52dc7ee2004-09-23 19:18:23 +0000963 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000964 struct vertex *child;
965
966 if (IS_DEBUG_OSPF_EVENT)
967 zlog_info ("ospf_process_stub():processing stubs for area %s",
paul0c0f9cd2003-06-06 23:27:04 +0000968 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +0000969 if (v->type == OSPF_VERTEX_ROUTER)
970 {
971 u_char *p;
972 u_char *lim;
973 struct router_lsa_link *l;
974 struct router_lsa *rlsa;
975
paul0c0f9cd2003-06-06 23:27:04 +0000976 if (IS_DEBUG_OSPF_EVENT)
gdt630e4802004-08-31 17:28:41 +0000977 zlog_info ("ospf_process_stubs():processing router LSA, id: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000978 inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000979 rlsa = (struct router_lsa *) v->lsa;
980
981
paul0c0f9cd2003-06-06 23:27:04 +0000982 if (IS_DEBUG_OSPF_EVENT)
gdt630e4802004-08-31 17:28:41 +0000983 zlog_info ("ospf_process_stubs(): we have %d links to process",
paul0c0f9cd2003-06-06 23:27:04 +0000984 ntohs (rlsa->links));
gdt630e4802004-08-31 17:28:41 +0000985 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +0000986 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
987
988 while (p < lim)
989 {
990 l = (struct router_lsa_link *) p;
991
992 p += (ROUTER_LSA_MIN_SIZE +
993 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
994
995 if (l->m[0].type == LSA_LINK_TYPE_STUB)
996 ospf_intra_add_stub (rt, l, v, area);
997 }
998 }
999
gdt630e4802004-08-31 17:28:41 +00001000 ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1, 1);
paul718e3742002-12-13 20:15:29 +00001001
1002 for (cnode = listhead (v->child); cnode; nextnode (cnode))
1003 {
1004 child = getdata (cnode);
1005
1006 if (CHECK_FLAG (child->flags, OSPF_VERTEX_PROCESSED))
paul0c0f9cd2003-06-06 23:27:04 +00001007 continue;
paul718e3742002-12-13 20:15:29 +00001008
1009 ospf_spf_process_stubs (area, child, rt);
1010
1011 SET_FLAG (child->flags, OSPF_VERTEX_PROCESSED);
1012 }
1013}
1014
1015void
1016ospf_rtrs_free (struct route_table *rtrs)
1017{
1018 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001019 struct list *or_list;
1020 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001021
1022 if (IS_DEBUG_OSPF_EVENT)
paul0c0f9cd2003-06-06 23:27:04 +00001023 zlog_info ("Route: Router Routing Table free");
paul718e3742002-12-13 20:15:29 +00001024
1025 for (rn = route_top (rtrs); rn; rn = route_next (rn))
1026 if ((or_list = rn->info) != NULL)
1027 {
paul0c0f9cd2003-06-06 23:27:04 +00001028 for (node = listhead (or_list); node; nextnode (node))
1029 ospf_route_free (node->data);
paul718e3742002-12-13 20:15:29 +00001030
paul0c0f9cd2003-06-06 23:27:04 +00001031 list_delete (or_list);
paul718e3742002-12-13 20:15:29 +00001032
paul0c0f9cd2003-06-06 23:27:04 +00001033 /* Unlock the node. */
1034 rn->info = NULL;
1035 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001036 }
1037 route_table_finish (rtrs);
1038}
1039
1040void
1041ospf_rtrs_print (struct route_table *rtrs)
1042{
1043 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001044 struct list *or_list;
1045 struct listnode *ln;
1046 struct listnode *pnode;
paul718e3742002-12-13 20:15:29 +00001047 struct ospf_route *or;
1048 struct ospf_path *path;
1049 char buf1[BUFSIZ];
1050 char buf2[BUFSIZ];
1051
1052 if (IS_DEBUG_OSPF_EVENT)
1053 zlog_info ("ospf_rtrs_print() start");
1054
1055 for (rn = route_top (rtrs); rn; rn = route_next (rn))
1056 if ((or_list = rn->info) != NULL)
1057 for (ln = listhead (or_list); ln; nextnode (ln))
1058 {
1059 or = getdata (ln);
1060
1061 switch (or->path_type)
1062 {
1063 case OSPF_PATH_INTRA_AREA:
paul0c0f9cd2003-06-06 23:27:04 +00001064 if (IS_DEBUG_OSPF_EVENT)
1065 zlog_info ("%s [%d] area: %s",
1066 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1067 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1068 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +00001069 break;
1070 case OSPF_PATH_INTER_AREA:
paul0c0f9cd2003-06-06 23:27:04 +00001071 if (IS_DEBUG_OSPF_EVENT)
1072 zlog_info ("%s IA [%d] area: %s",
1073 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1074 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1075 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +00001076 break;
1077 default:
1078 break;
1079 }
1080
paul96735ee2003-08-10 02:51:22 +00001081 for (pnode = listhead (or->paths); pnode; nextnode (pnode))
paul718e3742002-12-13 20:15:29 +00001082 {
1083 path = getdata (pnode);
1084 if (path->nexthop.s_addr == 0)
paul0c0f9cd2003-06-06 23:27:04 +00001085 {
1086 if (IS_DEBUG_OSPF_EVENT)
1087 zlog_info (" directly attached to %s\r\n",
1088 IF_NAME (path->oi));
1089 }
1090 else
1091 {
1092 if (IS_DEBUG_OSPF_EVENT)
1093 zlog_info (" via %s, %s\r\n",
1094 inet_ntoa (path->nexthop), IF_NAME (path->oi));
1095 }
paul718e3742002-12-13 20:15:29 +00001096 }
1097 }
1098
1099 zlog_info ("ospf_rtrs_print() end");
1100}
1101
1102/* Calculating the shortest-path tree for an area. */
1103void
paul0c0f9cd2003-06-06 23:27:04 +00001104ospf_spf_calculate (struct ospf_area *area, struct route_table *new_table,
paul718e3742002-12-13 20:15:29 +00001105 struct route_table *new_rtrs)
1106{
hasso52dc7ee2004-09-23 19:18:23 +00001107 struct list *candidate;
1108 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001109 struct vertex *v;
1110 struct route_table *rv;
1111 struct route_table *nv;
1112
1113 if (IS_DEBUG_OSPF_EVENT)
1114 {
1115 zlog_info ("ospf_spf_calculate: Start");
paul0c0f9cd2003-06-06 23:27:04 +00001116 zlog_info ("ospf_spf_calculate: running Dijkstra for area %s",
1117 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001118 }
1119
1120 /* Check router-lsa-self. If self-router-lsa is not yet allocated,
1121 return this area's calculation. */
paul0c0f9cd2003-06-06 23:27:04 +00001122 if (!area->router_lsa_self)
paul718e3742002-12-13 20:15:29 +00001123 {
1124 if (IS_DEBUG_OSPF_EVENT)
paul0c0f9cd2003-06-06 23:27:04 +00001125 zlog_info ("ospf_spf_calculate: "
1126 "Skip area %s's calculation due to empty router_lsa_self",
1127 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001128 return;
1129 }
1130
1131 /* RFC2328 16.1. (1). */
paul0c0f9cd2003-06-06 23:27:04 +00001132 /* Initialize the algorithm's data structures. */
paul718e3742002-12-13 20:15:29 +00001133 rv = route_table_init ();
1134 nv = route_table_init ();
1135
paul0c0f9cd2003-06-06 23:27:04 +00001136 /* Clear the list of candidate vertices. */
paul718e3742002-12-13 20:15:29 +00001137 candidate = list_new ();
1138
1139 /* Initialize the shortest-path tree to only the root (which is the
1140 router doing the calculation). */
1141 ospf_spf_init (area);
1142 v = area->spf;
1143 ospf_spf_register (v, rv, nv);
1144
1145 /* Set Area A's TransitCapability to FALSE. */
1146 area->transit = OSPF_TRANSIT_FALSE;
1147 area->shortcut_capability = 1;
1148
1149 for (;;)
1150 {
1151 /* RFC2328 16.1. (2). */
1152 ospf_spf_next (v, area, candidate, rv, nv);
1153
1154 /* RFC2328 16.1. (3). */
1155 /* If at this step the candidate list is empty, the shortest-
1156 path tree (of transit vertices) has been completely built and
1157 this stage of the procedure terminates. */
1158 if (listcount (candidate) == 0)
1159 break;
1160
1161 /* Otherwise, choose the vertex belonging to the candidate list
1162 that is closest to the root, and add it to the shortest-path
1163 tree (removing it from the candidate list in the
paul0c0f9cd2003-06-06 23:27:04 +00001164 process). */
paul718e3742002-12-13 20:15:29 +00001165 node = listhead (candidate);
1166 v = getdata (node);
1167 ospf_vertex_add_parent (v);
1168
gdt630e4802004-08-31 17:28:41 +00001169 /* Remove from the candidate list. */
paul718e3742002-12-13 20:15:29 +00001170 listnode_delete (candidate, v);
1171
1172 /* Add to SPF tree. */
1173 ospf_spf_register (v, rv, nv);
1174
1175 /* Note that when there is a choice of vertices closest to the
1176 root, network vertices must be chosen before router vertices
1177 in order to necessarily find all equal-cost paths. */
1178 /* We don't do this at this moment, we should add the treatment
1179 above codes. -- kunihiro. */
1180
1181 /* RFC2328 16.1. (4). */
1182 if (v->type == OSPF_VERTEX_ROUTER)
1183 ospf_intra_add_router (new_rtrs, v, area);
paul0c0f9cd2003-06-06 23:27:04 +00001184 else
paul718e3742002-12-13 20:15:29 +00001185 ospf_intra_add_transit (new_table, v, area);
1186
1187 /* RFC2328 16.1. (5). */
1188 /* Iterate the algorithm by returning to Step 2. */
gdt630e4802004-08-31 17:28:41 +00001189
1190 } /* end loop until no more candidate vertices */
paul718e3742002-12-13 20:15:29 +00001191
1192 if (IS_DEBUG_OSPF_EVENT)
1193 {
1194 ospf_spf_dump (area->spf, 0);
1195 ospf_route_table_dump (new_table);
1196 }
1197
1198 /* Second stage of SPF calculation procedure's */
1199 ospf_spf_process_stubs (area, area->spf, new_table);
1200
1201 /* Free all vertices which allocated for SPF calculation */
1202 ospf_spf_route_free (rv);
1203 ospf_spf_route_free (nv);
1204
1205 /* Free candidate list */
1206 list_free (candidate);
1207
1208 /* Increment SPF Calculation Counter. */
1209 area->spf_calculation++;
1210
paul68980082003-03-25 05:07:42 +00001211 area->ospf->ts_spf = time (NULL);
paul718e3742002-12-13 20:15:29 +00001212
1213 if (IS_DEBUG_OSPF_EVENT)
1214 zlog_info ("ospf_spf_calculate: Stop");
1215}
1216
1217/* Timer for SPF calculation. */
1218int
paul68980082003-03-25 05:07:42 +00001219ospf_spf_calculate_timer (struct thread *thread)
paul718e3742002-12-13 20:15:29 +00001220{
paul68980082003-03-25 05:07:42 +00001221 struct ospf *ospf = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +00001222 struct route_table *new_table, *new_rtrs;
hasso52dc7ee2004-09-23 19:18:23 +00001223 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001224
1225 if (IS_DEBUG_OSPF_EVENT)
1226 zlog_info ("SPF: Timer (SPF calculation expire)");
paul0c0f9cd2003-06-06 23:27:04 +00001227
paul718e3742002-12-13 20:15:29 +00001228 ospf->t_spf_calc = NULL;
1229
1230 /* Allocate new table tree. */
1231 new_table = route_table_init ();
paul0c0f9cd2003-06-06 23:27:04 +00001232 new_rtrs = route_table_init ();
paul718e3742002-12-13 20:15:29 +00001233
paul68980082003-03-25 05:07:42 +00001234 ospf_vl_unapprove (ospf);
paul718e3742002-12-13 20:15:29 +00001235
1236 /* Calculate SPF for each area. */
1237 for (node = listhead (ospf->areas); node; node = nextnode (node))
1238 ospf_spf_calculate (node->data, new_table, new_rtrs);
1239
paul68980082003-03-25 05:07:42 +00001240 ospf_vl_shut_unapproved (ospf);
paul718e3742002-12-13 20:15:29 +00001241
paul68980082003-03-25 05:07:42 +00001242 ospf_ia_routing (ospf, new_table, new_rtrs);
paul718e3742002-12-13 20:15:29 +00001243
1244 ospf_prune_unreachable_networks (new_table);
1245 ospf_prune_unreachable_routers (new_rtrs);
1246
1247 /* AS-external-LSA calculation should not be performed here. */
1248
1249 /* If new Router Route is installed,
1250 then schedule re-calculate External routes. */
1251 if (1)
paul68980082003-03-25 05:07:42 +00001252 ospf_ase_calculate_schedule (ospf);
paul718e3742002-12-13 20:15:29 +00001253
paul68980082003-03-25 05:07:42 +00001254 ospf_ase_calculate_timer_add (ospf);
paul718e3742002-12-13 20:15:29 +00001255
1256 /* Update routing table. */
paul68980082003-03-25 05:07:42 +00001257 ospf_route_install (ospf, new_table);
paul718e3742002-12-13 20:15:29 +00001258
1259 /* Update ABR/ASBR routing table */
paul68980082003-03-25 05:07:42 +00001260 if (ospf->old_rtrs)
paul718e3742002-12-13 20:15:29 +00001261 {
1262 /* old_rtrs's node holds linked list of ospf_route. --kunihiro. */
paul68980082003-03-25 05:07:42 +00001263 /* ospf_route_delete (ospf->old_rtrs); */
1264 ospf_rtrs_free (ospf->old_rtrs);
paul718e3742002-12-13 20:15:29 +00001265 }
1266
paul68980082003-03-25 05:07:42 +00001267 ospf->old_rtrs = ospf->new_rtrs;
1268 ospf->new_rtrs = new_rtrs;
paul718e3742002-12-13 20:15:29 +00001269
paul0c0f9cd2003-06-06 23:27:04 +00001270 if (IS_OSPF_ABR (ospf))
paul68980082003-03-25 05:07:42 +00001271 ospf_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001272
1273 if (IS_DEBUG_OSPF_EVENT)
1274 zlog_info ("SPF: calculation complete");
1275
1276 return 0;
1277}
1278
1279/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
1280 set timer for SPF calc. */
1281void
paul68980082003-03-25 05:07:42 +00001282ospf_spf_calculate_schedule (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00001283{
1284 time_t ht, delay;
1285
1286 if (IS_DEBUG_OSPF_EVENT)
1287 zlog_info ("SPF: calculation timer scheduled");
1288
1289 /* OSPF instance does not exist. */
paul68980082003-03-25 05:07:42 +00001290 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001291 return;
1292
1293 /* SPF calculation timer is already scheduled. */
paul68980082003-03-25 05:07:42 +00001294 if (ospf->t_spf_calc)
paul718e3742002-12-13 20:15:29 +00001295 {
1296 if (IS_DEBUG_OSPF_EVENT)
paul0c0f9cd2003-06-06 23:27:04 +00001297 zlog_info ("SPF: calculation timer is already scheduled: %p",
1298 ospf->t_spf_calc);
paul718e3742002-12-13 20:15:29 +00001299 return;
1300 }
1301
paul68980082003-03-25 05:07:42 +00001302 ht = time (NULL) - ospf->ts_spf;
paul718e3742002-12-13 20:15:29 +00001303
1304 /* Get SPF calculation delay time. */
paul68980082003-03-25 05:07:42 +00001305 if (ht < ospf->spf_holdtime)
paul718e3742002-12-13 20:15:29 +00001306 {
paul68980082003-03-25 05:07:42 +00001307 if (ospf->spf_holdtime - ht < ospf->spf_delay)
paul0c0f9cd2003-06-06 23:27:04 +00001308 delay = ospf->spf_delay;
paul718e3742002-12-13 20:15:29 +00001309 else
paul0c0f9cd2003-06-06 23:27:04 +00001310 delay = ospf->spf_holdtime - ht;
paul718e3742002-12-13 20:15:29 +00001311 }
1312 else
paul68980082003-03-25 05:07:42 +00001313 delay = ospf->spf_delay;
paul718e3742002-12-13 20:15:29 +00001314
1315 if (IS_DEBUG_OSPF_EVENT)
hassofa2b17e2004-03-04 17:45:00 +00001316 zlog_info ("SPF: calculation timer delay = %ld", (long)delay);
paul68980082003-03-25 05:07:42 +00001317 ospf->t_spf_calc =
1318 thread_add_timer (master, ospf_spf_calculate_timer, ospf, delay);
paul718e3742002-12-13 20:15:29 +00001319}