blob: 5288531f582ce9030471ef25b816008f15e5fe43 [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{
104 listnode node;
105
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
gdt630e4802004-08-31 17:28:41 +0000118ospf_vertex_dump(char *msg, struct vertex *v,
119 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 {
134 listnode nnode;
135 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 {
157 listnode cnode;
158 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;
173 listnode node;
174
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 */
paul718e3742002-12-13 20:15:29 +0000228listnode
229ospf_vertex_lookup (list vlist, struct in_addr id, int type)
230{
231 listnode node;
232 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{
248 int i;
249 int length;
250 struct router_lsa *rl;
251 struct network_lsa *nl;
252
253 /* In case of W is Network LSA. */
254 if (w->type == OSPF_NETWORK_LSA)
255 {
256 if (v->type == OSPF_NETWORK_LSA)
pauld355bfa2004-04-08 07:43:45 +0000257 return -1;
paul718e3742002-12-13 20:15:29 +0000258
259 nl = (struct network_lsa *) w;
260 length = (ntohs (w->length) - OSPF_LSA_HEADER_SIZE - 4) / 4;
paul0c0f9cd2003-06-06 23:27:04 +0000261
paul718e3742002-12-13 20:15:29 +0000262 for (i = 0; i < length; i++)
263 if (IPV4_ADDR_SAME (&nl->routers[i], &v->id))
pauld355bfa2004-04-08 07:43:45 +0000264 return i;
265 return -1;
paul718e3742002-12-13 20:15:29 +0000266 }
267
268 /* In case of W is Router LSA. */
269 if (w->type == OSPF_ROUTER_LSA)
270 {
271 rl = (struct router_lsa *) w;
272
273 length = ntohs (w->length);
274
275 for (i = 0;
paul0c0f9cd2003-06-06 23:27:04 +0000276 i < ntohs (rl->links) && length >= sizeof (struct router_lsa);
277 i++, length -= 12)
paul718e3742002-12-13 20:15:29 +0000278 {
279 switch (rl->link[i].type)
280 {
281 case LSA_LINK_TYPE_POINTOPOINT:
282 case LSA_LINK_TYPE_VIRTUALLINK:
283 /* Router LSA ID. */
284 if (v->type == OSPF_ROUTER_LSA &&
285 IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
286 {
pauld355bfa2004-04-08 07:43:45 +0000287 return i;
paul718e3742002-12-13 20:15:29 +0000288 }
289 break;
290 case LSA_LINK_TYPE_TRANSIT:
291 /* Network LSA ID. */
292 if (v->type == OSPF_NETWORK_LSA &&
293 IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
294 {
pauld355bfa2004-04-08 07:43:45 +0000295 return i;
paul0c0f9cd2003-06-06 23:27:04 +0000296 }
paul718e3742002-12-13 20:15:29 +0000297 break;
298 case LSA_LINK_TYPE_STUB:
299 /* Not take into count? */
300 continue;
301 default:
302 break;
303 }
304 }
305 }
pauld355bfa2004-04-08 07:43:45 +0000306 return -1;
paul718e3742002-12-13 20:15:29 +0000307}
308
309/* Add the nexthop to the list, only if it is unique.
310 * If it's not unique, free the nexthop entry.
311 */
312void
313ospf_nexthop_add_unique (struct vertex_nexthop *new, list nexthop)
314{
315 struct vertex_nexthop *nh;
316 listnode node;
317 int match;
318
319 match = 0;
320 for (node = listhead (nexthop); node; nextnode (node))
321 {
322 nh = node->data;
323
324 /* Compare the two entries. */
325 /* XXX
326 * Comparing the parent preserves the shortest path tree
327 * structure even when the nexthops are identical.
328 */
329 if (nh->oi == new->oi &&
paul0c0f9cd2003-06-06 23:27:04 +0000330 IPV4_ADDR_SAME (&nh->router, &new->router) &&
331 nh->parent == new->parent)
332 {
333 match = 1;
334 break;
335 }
paul718e3742002-12-13 20:15:29 +0000336 }
337
338 if (!match)
339 listnode_add (nexthop, new);
340 else
341 vertex_nexthop_free (new);
342}
343
344/* Merge entries in list b into list a. */
345void
346ospf_nexthop_merge (list a, list b)
347{
348 struct listnode *n;
349
350 for (n = listhead (b); n; nextnode (n))
351 {
352 ospf_nexthop_add_unique (n->data, a);
353 }
354}
355
356#define ROUTER_LSA_MIN_SIZE 12
357#define ROUTER_LSA_TOS_SIZE 4
358
gdt630e4802004-08-31 17:28:41 +0000359/* Find the next link after prev_link from v to w. If prev_link is
360 * NULL, return the first link from v to w. Ignore stub and virtual links;
361 * these link types will never be returned.
362 */
paul718e3742002-12-13 20:15:29 +0000363struct router_lsa_link *
364ospf_get_next_link (struct vertex *v, struct vertex *w,
paul0c0f9cd2003-06-06 23:27:04 +0000365 struct router_lsa_link *prev_link)
paul718e3742002-12-13 20:15:29 +0000366{
367 u_char *p;
368 u_char *lim;
369 struct router_lsa_link *l;
370
371 if (prev_link == NULL)
gdt630e4802004-08-31 17:28:41 +0000372 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +0000373 else
374 {
paul0c0f9cd2003-06-06 23:27:04 +0000375 p = (u_char *) prev_link;
paul718e3742002-12-13 20:15:29 +0000376 p += (ROUTER_LSA_MIN_SIZE +
377 (prev_link->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
378 }
paul0c0f9cd2003-06-06 23:27:04 +0000379
paul718e3742002-12-13 20:15:29 +0000380 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
381
382 while (p < lim)
383 {
384 l = (struct router_lsa_link *) p;
385
paul0c0f9cd2003-06-06 23:27:04 +0000386 p += (ROUTER_LSA_MIN_SIZE + (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
paul718e3742002-12-13 20:15:29 +0000387
388 if (l->m[0].type == LSA_LINK_TYPE_STUB)
389 continue;
390
391 /* Defer NH calculation via VLs until summaries from
392 transit areas area confidered */
393
394 if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK)
paul0c0f9cd2003-06-06 23:27:04 +0000395 continue;
paul718e3742002-12-13 20:15:29 +0000396
397 if (IPV4_ADDR_SAME (&l->link_id, &w->id))
paul0c0f9cd2003-06-06 23:27:04 +0000398 return l;
paul718e3742002-12-13 20:15:29 +0000399 }
400
401 return NULL;
402}
403
paul75ee0b82004-08-05 09:10:31 +0000404/*
405 * Consider supplied next-hop for inclusion to the supplied list of
406 * equal-cost next-hops, adjust list as neccessary.
407 *
408 * (Discussed on GNU Zebra list 27 May 2003, [zebra 19184])
409 *
410 * Note that below is a bit of a hack, and limits ECMP to paths that go to
411 * same nexthop. Where as paths via inequal output_cost interfaces could
412 * still quite easily be ECMP due to remote cost differences.
413 *
414 * TODO: It really should be done by way of recording currently valid
415 * backlinks and determining the appropriate nexthops from the list of
416 * backlinks, or even simpler, just flushing nexthop list if we find a lower
417 * cost path to a candidate vertex in SPF, maybe.
paulbf9392c2003-06-06 23:23:36 +0000418 */
paul0c0f9cd2003-06-06 23:27:04 +0000419void
420ospf_spf_consider_nexthop (struct list *nexthops,
421 struct vertex_nexthop *newhop)
paulbf9392c2003-06-06 23:23:36 +0000422{
paulbf9392c2003-06-06 23:23:36 +0000423 struct vertex_nexthop *hop;
paul75ee0b82004-08-05 09:10:31 +0000424 struct listnode *ln, *nn;
paul0c0f9cd2003-06-06 23:27:04 +0000425
paul75ee0b82004-08-05 09:10:31 +0000426 /* nexthop list should contain only the set of nexthops that have the lowest
427 * equal cost
428 */
429 if (nexthops->head != NULL)
430 {
431 hop = getdata (nexthops->head);
432
433 /* weed out hops with higher cost than the newhop */
434 if (hop->oi->output_cost > newhop->oi->output_cost)
435 {
436 /* delete the existing nexthops */
437 for (ln = nexthops->head; ln; ln = nn)
438 {
439 nn = ln->next;
440 hop = getdata (ln);
441
442 listnode_delete (nexthops, hop);
443 vertex_nexthop_free (hop);
444 }
445 }
446 else if (hop->oi->output_cost < newhop->oi->output_cost)
paul0c0f9cd2003-06-06 23:27:04 +0000447 return;
paul75ee0b82004-08-05 09:10:31 +0000448 }
paul0c0f9cd2003-06-06 23:27:04 +0000449
paulbf9392c2003-06-06 23:23:36 +0000450 /* new hop is <= existing hops, add it */
paul0c0f9cd2003-06-06 23:27:04 +0000451 listnode_add (nexthops, newhop);
paulbf9392c2003-06-06 23:23:36 +0000452
453 return;
454}
455
gdt630e4802004-08-31 17:28:41 +0000456/* 16.1.1. Calculate nexthop from root through V (parent) to
457 * vertex W (destination).
458 */
paul718e3742002-12-13 20:15:29 +0000459void
460ospf_nexthop_calculation (struct ospf_area *area,
461 struct vertex *v, struct vertex *w)
462{
463 listnode node;
464 struct vertex_nexthop *nh, *x;
465 struct ospf_interface *oi = NULL;
466 struct router_lsa_link *l = NULL;
paul0c0f9cd2003-06-06 23:27:04 +0000467
468
paul718e3742002-12-13 20:15:29 +0000469 if (IS_DEBUG_OSPF_EVENT)
gdt630e4802004-08-31 17:28:41 +0000470 {
471 zlog_info ("ospf_nexthop_calculation(): Start");
472 ospf_vertex_dump("V (parent):", v, 1, 1);
473 ospf_vertex_dump("W (dest) :", w, 1, 1);
474 }
paul718e3742002-12-13 20:15:29 +0000475
paul718e3742002-12-13 20:15:29 +0000476 if (v == area->spf)
477 {
gdt630e4802004-08-31 17:28:41 +0000478 /* 16.1.1 para 4. In the first case, the parent vertex (V) is the
479 root (the calculating router itself). This means that the
480 destination is either a directly connected network or directly
481 connected router. The outgoing interface in this case is simply
482 the OSPF interface connecting to the destination network/router.
483 */
484
paul718e3742002-12-13 20:15:29 +0000485 if (w->type == OSPF_VERTEX_ROUTER)
paul0c0f9cd2003-06-06 23:27:04 +0000486 {
487 while ((l = ospf_get_next_link (v, w, l)))
488 {
gdt630e4802004-08-31 17:28:41 +0000489 /* l is a link from v to w
490 * l2 will be link from w to v
491 */
paul0c0f9cd2003-06-06 23:27:04 +0000492 struct router_lsa_link *l2 = NULL;
493
gdt630e4802004-08-31 17:28:41 +0000494 if (IS_DEBUG_OSPF_EVENT)
495 {
496 char buf1[BUFSIZ];
497 char buf2[BUFSIZ];
498 zlog_info("ospf_nexthop_calculation(): considering link "
499 "type %d link_id %s link_data %s",
500 l->m[0].type,
501 inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ),
502 inet_ntop (AF_INET, &l->link_data, buf1, BUFSIZ));
503 }
504
paul0c0f9cd2003-06-06 23:27:04 +0000505 if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT)
506 {
gdt630e4802004-08-31 17:28:41 +0000507 /* If the destination is a router which connects to
508 the calculating router via a Point-to-MultiPoint
509 network, the destination's next hop IP address(es)
510 can be determined by examining the destination's
511 router-LSA: each link pointing back to the
512 calculating router and having a Link Data field
513 belonging to the Point-to-MultiPoint network
514 provides an IP address of the next hop router.
515
516 At this point l is a link from V to W, and V is the
517 root ("us"). Find the local interface associated
518 with l (its address is in l->link_data). If it
519 is a point-to-multipoint interface, then look through
520 the links in the opposite direction (W to V). If
521 any of them have an address that lands within the
522 subnet declared by the PtMP link, then that link
523 is a constituent of the PtMP link, and its address is
524 a nexthop address for V.
525 */
paul68980082003-03-25 05:07:42 +0000526 oi = ospf_if_is_configured (area->ospf, &l->link_data);
paul7afa08d2002-12-13 20:59:45 +0000527 if (oi && oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
paul0c0f9cd2003-06-06 23:27:04 +0000528 {
529 struct prefix_ipv4 la;
gdt630e4802004-08-31 17:28:41 +0000530
531 la.family = AF_INET;
paul0c0f9cd2003-06-06 23:27:04 +0000532 la.prefixlen = oi->address->prefixlen;
gdt630e4802004-08-31 17:28:41 +0000533
534 /* V links to W on PtMP interface
535 - find the interface address on W */
paul0c0f9cd2003-06-06 23:27:04 +0000536 while ((l2 = ospf_get_next_link (w, v, l2)))
537 {
538 la.prefix = l2->link_data;
539
540 if (prefix_cmp ((struct prefix *) &la,
541 oi->address) == 0)
542 /* link_data is on our PtMP network */
543 break;
544 }
gdt630e4802004-08-31 17:28:41 +0000545 } /* end l is on point-to-multipoint link */
paul0c0f9cd2003-06-06 23:27:04 +0000546 else
547 {
gdt630e4802004-08-31 17:28:41 +0000548 /* l is a regular point-to-point link.
549 Look for a link from W to V.
550 */
paul0c0f9cd2003-06-06 23:27:04 +0000551 while ((l2 = ospf_get_next_link (w, v, l2)))
552 {
553 oi = ospf_if_is_configured (area->ospf,
554 &(l2->link_data));
555
556 if (oi == NULL)
557 continue;
558
559 if (!IPV4_ADDR_SAME (&oi->address->u.prefix4,
560 &l->link_data))
561 continue;
562
563 break;
564 }
565 }
566
567 if (oi && l2)
568 {
gdt630e4802004-08-31 17:28:41 +0000569 /* found all necessary info to build nexthop */
paul0c0f9cd2003-06-06 23:27:04 +0000570 nh = vertex_nexthop_new (v);
571 nh->oi = oi;
572 nh->router = l2->link_data;
573 ospf_spf_consider_nexthop (w->nexthop, nh);
574 }
gdt630e4802004-08-31 17:28:41 +0000575 else
576 {
577 zlog_info("ospf_nexthop_calculation(): "
578 "could not determine nexthop for link");
579 }
580 } /* end point-to-point link from V to W */
581 } /* end iterate over links in W */
582 } /* end W is a Router vertex */
paul718e3742002-12-13 20:15:29 +0000583 else
paul0c0f9cd2003-06-06 23:27:04 +0000584 {
gdt630e4802004-08-31 17:28:41 +0000585 assert(w->type == OSPF_VERTEX_NETWORK);
paul0c0f9cd2003-06-06 23:27:04 +0000586 while ((l = ospf_get_next_link (v, w, l)))
587 {
588 oi = ospf_if_is_configured (area->ospf, &(l->link_data));
589 if (oi)
590 {
591 nh = vertex_nexthop_new (v);
592 nh->oi = oi;
593 nh->router.s_addr = 0;
paul75ee0b82004-08-05 09:10:31 +0000594 ospf_spf_consider_nexthop (w->nexthop, nh);
paul0c0f9cd2003-06-06 23:27:04 +0000595 }
596 }
597 }
paul718e3742002-12-13 20:15:29 +0000598 return;
gdt630e4802004-08-31 17:28:41 +0000599 } /* end V is the root */
600
601 /* Check if W's parent is a network connected to root. */
paul718e3742002-12-13 20:15:29 +0000602 else if (v->type == OSPF_VERTEX_NETWORK)
603 {
gdt630e4802004-08-31 17:28:41 +0000604 /* See if any of V's parents are the root. */
paul718e3742002-12-13 20:15:29 +0000605 for (node = listhead (v->nexthop); node; nextnode (node))
606 {
gdt630e4802004-08-31 17:28:41 +0000607 x = (struct vertex_nexthop *) getdata (node);
608 if (x->parent == area->spf) /* connects to root? */
609 {
610 /* 16.1.1 para 5. ...the parent vertex is a network that
611 * directly connects the calculating router to the destination
612 * router. The list of next hops is then determined by
613 * examining the destination's router-LSA...
614 */
615
616 assert(w->type == OSPF_VERTEX_ROUTER);
paul0c0f9cd2003-06-06 23:27:04 +0000617 while ((l = ospf_get_next_link (w, v, l)))
618 {
gdt630e4802004-08-31 17:28:41 +0000619 /* ...For each link in the router-LSA that points back to the
620 * parent network, the link's Link Data field provides the IP
621 * address of a next hop router. The outgoing interface to
622 * use can then be derived from the next hop IP address (or
623 * it can be inherited from the parent network).
624 */
paul0c0f9cd2003-06-06 23:27:04 +0000625 nh = vertex_nexthop_new (v);
626 nh->oi = x->oi;
627 nh->router = l->link_data;
paul75ee0b82004-08-05 09:10:31 +0000628 ospf_spf_consider_nexthop (w->nexthop, nh);
paul0c0f9cd2003-06-06 23:27:04 +0000629 }
630 return;
631 }
paul718e3742002-12-13 20:15:29 +0000632 }
633 }
634
gdt630e4802004-08-31 17:28:41 +0000635 /* 16.1.1 para 4. If there is at least one intervening router in the
636 * current shortest path between the destination and the root, the
637 * destination simply inherits the set of next hops from the
638 * parent.
639 */
paul718e3742002-12-13 20:15:29 +0000640 for (node = listhead (v->nexthop); node; nextnode (node))
641 {
642 nh = vertex_nexthop_dup (node->data);
643 nh->parent = v;
644 ospf_nexthop_add_unique (nh, w->nexthop);
645 }
646}
647
gdt630e4802004-08-31 17:28:41 +0000648/* Add a vertex to the SPF candidate list. */
paul718e3742002-12-13 20:15:29 +0000649void
650ospf_install_candidate (list candidate, struct vertex *w)
651{
652 listnode node;
653 struct vertex *cw;
654
gdt630e4802004-08-31 17:28:41 +0000655 ospf_vertex_dump("ospf_install_candidate(): add to candidate list", w, 1, 1);
656
paul718e3742002-12-13 20:15:29 +0000657 if (list_isempty (candidate))
658 {
659 listnode_add (candidate, w);
660 return;
661 }
662
663 /* Install vertex with sorting by distance. */
664 for (node = listhead (candidate); node; nextnode (node))
665 {
666 cw = (struct vertex *) getdata (node);
667 if (cw->distance > w->distance)
668 {
669 list_add_node_prev (candidate, node, w);
670 break;
671 }
672 else if (node->next == NULL)
673 {
674 list_add_node_next (candidate, node, w);
675 break;
676 }
677 }
gdt630e4802004-08-31 17:28:41 +0000678
679 if (IS_DEBUG_OSPF_EVENT)
680 {
681 zlog_info("ospf_install_candidate(): candidate list now contains:");
682 for (node = listhead (candidate); node; nextnode (node))
683 {
684 cw = (struct vertex *) getdata (node);
685 ospf_vertex_dump(" candidate:", cw, 0, 0);
686 }
687 }
paul718e3742002-12-13 20:15:29 +0000688}
689
gdt630e4802004-08-31 17:28:41 +0000690/* RFC2328 Section 16.1 (2).
691 * v is on the SPF tree. Examine the links in v's LSA. Update the list
692 * of candidates with any vertices not already on the list. If a lower-cost
693 * path is found to a vertex already on the candidate list, store the new cost.
694 */
paul718e3742002-12-13 20:15:29 +0000695void
696ospf_spf_next (struct vertex *v, struct ospf_area *area,
paul0c0f9cd2003-06-06 23:27:04 +0000697 list candidate, struct route_table *rv, struct route_table *nv)
paul718e3742002-12-13 20:15:29 +0000698{
699 struct ospf_lsa *w_lsa = NULL;
700 struct vertex *w, *cw;
701 u_char *p;
702 u_char *lim;
703 struct router_lsa_link *l = NULL;
704 struct in_addr *r;
705 listnode node;
706 int type = 0;
707
708 /* If this is a router-LSA, and bit V of the router-LSA (see Section
709 A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE. */
710 if (v->type == OSPF_VERTEX_ROUTER)
711 {
712 if (IS_ROUTER_LSA_VIRTUAL ((struct router_lsa *) v->lsa))
713 area->transit = OSPF_TRANSIT_TRUE;
714 }
715
716 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul0c0f9cd2003-06-06 23:27:04 +0000717 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
718
paul718e3742002-12-13 20:15:29 +0000719 while (p < lim)
720 {
pauld355bfa2004-04-08 07:43:45 +0000721 int link = -1; /* link index for w's back link */
722
paul718e3742002-12-13 20:15:29 +0000723 /* In case of V is Router-LSA. */
724 if (v->lsa->type == OSPF_ROUTER_LSA)
725 {
726 l = (struct router_lsa_link *) p;
727
paul0c0f9cd2003-06-06 23:27:04 +0000728 p += (ROUTER_LSA_MIN_SIZE +
paul718e3742002-12-13 20:15:29 +0000729 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
730
731 /* (a) If this is a link to a stub network, examine the next
732 link in V's LSA. Links to stub networks will be
733 considered in the second stage of the shortest path
734 calculation. */
735 if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB)
736 continue;
737
738 /* (b) Otherwise, W is a transit vertex (router or transit
739 network). Look up the vertex W's LSA (router-LSA or
740 network-LSA) in Area A's link state database. */
741 switch (type)
742 {
743 case LSA_LINK_TYPE_POINTOPOINT:
744 case LSA_LINK_TYPE_VIRTUALLINK:
745 if (type == LSA_LINK_TYPE_VIRTUALLINK)
paul0c0f9cd2003-06-06 23:27:04 +0000746 {
747 if (IS_DEBUG_OSPF_EVENT)
748 zlog_info ("looking up LSA through VL: %s",
749 inet_ntoa (l->link_id));
750 }
paul718e3742002-12-13 20:15:29 +0000751
752 w_lsa = ospf_lsa_lookup (area, OSPF_ROUTER_LSA, l->link_id,
753 l->link_id);
754 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000755 {
756 if (IS_DEBUG_OSPF_EVENT)
gdt630e4802004-08-31 17:28:41 +0000757 zlog_info ("found Router LSA %s", inet_ntoa (l->link_id));
paul0c0f9cd2003-06-06 23:27:04 +0000758 }
paul718e3742002-12-13 20:15:29 +0000759 break;
760 case LSA_LINK_TYPE_TRANSIT:
paul0c0f9cd2003-06-06 23:27:04 +0000761 if (IS_DEBUG_OSPF_EVENT)
paul718e3742002-12-13 20:15:29 +0000762
paul0c0f9cd2003-06-06 23:27:04 +0000763 zlog_info ("Looking up Network LSA, ID: %s",
764 inet_ntoa (l->link_id));
paul718e3742002-12-13 20:15:29 +0000765 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_NETWORK_LSA,
paul0c0f9cd2003-06-06 23:27:04 +0000766 l->link_id);
paul718e3742002-12-13 20:15:29 +0000767 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000768 if (IS_DEBUG_OSPF_EVENT)
769 zlog_info ("found the LSA");
paul718e3742002-12-13 20:15:29 +0000770 break;
771 default:
paul0c0f9cd2003-06-06 23:27:04 +0000772 zlog_warn ("Invalid LSA link type %d", type);
paul718e3742002-12-13 20:15:29 +0000773 continue;
774 }
775 }
776 else
777 {
778 /* In case of V is Network-LSA. */
paul0c0f9cd2003-06-06 23:27:04 +0000779 r = (struct in_addr *) p;
paul718e3742002-12-13 20:15:29 +0000780 p += sizeof (struct in_addr);
781
782 /* Lookup the vertex W's LSA. */
783 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_ROUTER_LSA, *r);
784 }
785
786 /* (b cont.) If the LSA does not exist, or its LS age is equal
787 to MaxAge, or it does not have a link back to vertex V,
788 examine the next link in V's LSA.[23] */
789 if (w_lsa == NULL)
790 continue;
791
792 if (IS_LSA_MAXAGE (w_lsa))
793 continue;
794
pauld355bfa2004-04-08 07:43:45 +0000795 if ( (link = ospf_lsa_has_link (w_lsa->data, v->lsa)) < 0 )
paul718e3742002-12-13 20:15:29 +0000796 {
paul0c0f9cd2003-06-06 23:27:04 +0000797 if (IS_DEBUG_OSPF_EVENT)
798 zlog_info ("The LSA doesn't have a link back");
paul718e3742002-12-13 20:15:29 +0000799 continue;
800 }
801
802 /* (c) If vertex W is already on the shortest-path tree, examine
803 the next link in the LSA. */
804 if (ospf_spf_has_vertex (rv, nv, w_lsa->data))
805 {
paul0c0f9cd2003-06-06 23:27:04 +0000806 if (IS_DEBUG_OSPF_EVENT)
807 zlog_info ("The LSA is already in SPF");
paul718e3742002-12-13 20:15:29 +0000808 continue;
809 }
810
811 /* (d) Calculate the link state cost D of the resulting path
812 from the root to vertex W. D is equal to the sum of the link
813 state cost of the (already calculated) shortest path to
814 vertex V and the advertised cost of the link between vertices
815 V and W. If D is: */
816
817 /* prepare vertex W. */
818 w = ospf_vertex_new (w_lsa);
819
pauld355bfa2004-04-08 07:43:45 +0000820 /* Save W's back link index number, for use by virtual links */
821 w->backlink = link;
822
paul718e3742002-12-13 20:15:29 +0000823 /* calculate link cost D. */
824 if (v->lsa->type == OSPF_ROUTER_LSA)
gdt630e4802004-08-31 17:28:41 +0000825 w->distance = v->distance + ntohs (l->m[0].metric);
826 else /* v is not a Router-LSA */
827 w->distance = v->distance;
paul718e3742002-12-13 20:15:29 +0000828
829 /* Is there already vertex W in candidate list? */
830 node = ospf_vertex_lookup (candidate, w->id, w->type);
831 if (node == NULL)
832 {
gdt630e4802004-08-31 17:28:41 +0000833 /* W is a new candidate. Calculate nexthop to W and add W
834 * to the candidate list.
835 */
paul718e3742002-12-13 20:15:29 +0000836 ospf_nexthop_calculation (area, v, w);
837
838 ospf_install_candidate (candidate, w);
839 }
840 else
841 {
gdt630e4802004-08-31 17:28:41 +0000842 /* W is already on the candidate list; call it cw.
843 * Compare the previously calculated cost (cw->distance)
844 * with the cost we just determined (w->distance) to see
845 * if we've found a shorter path.
846 */
paul718e3742002-12-13 20:15:29 +0000847 cw = (struct vertex *) getdata (node);
848
gdt630e4802004-08-31 17:28:41 +0000849 /* If the previous cost was lower, we didn't find a
850 * shorter path, so we're done with w.
851 */
paul718e3742002-12-13 20:15:29 +0000852 if (cw->distance < w->distance)
853 {
854 ospf_vertex_free (w);
855 continue;
856 }
paul718e3742002-12-13 20:15:29 +0000857 else if (cw->distance == w->distance)
858 {
gdt630e4802004-08-31 17:28:41 +0000859 /* Found an equal-cost path to W. Calculate nexthop to W. */
paul718e3742002-12-13 20:15:29 +0000860 ospf_nexthop_calculation (area, v, w);
861 ospf_nexthop_merge (cw->nexthop, w->nexthop);
862 list_delete_all_node (w->nexthop);
863 ospf_vertex_free (w);
864 }
paul718e3742002-12-13 20:15:29 +0000865 else
866 {
gdt630e4802004-08-31 17:28:41 +0000867 /* Found a lower-cost path to W. Calculate nexthop to W. */
paul718e3742002-12-13 20:15:29 +0000868 ospf_nexthop_calculation (area, v, w);
869
870 /* Remove old vertex from candidate list. */
871 ospf_vertex_free (cw);
872 listnode_delete (candidate, cw);
873
gdt630e4802004-08-31 17:28:41 +0000874 /* Install new W to candidate list. */
paul718e3742002-12-13 20:15:29 +0000875 ospf_install_candidate (candidate, w);
876 }
gdt630e4802004-08-31 17:28:41 +0000877 } /* end W is already on the candidate list */
878 } /* end loop over the links in V's LSA */
paul718e3742002-12-13 20:15:29 +0000879}
880
881/* Add vertex V to SPF tree. */
882void
883ospf_spf_register (struct vertex *v, struct route_table *rv,
paul0c0f9cd2003-06-06 23:27:04 +0000884 struct route_table *nv)
paul718e3742002-12-13 20:15:29 +0000885{
886 struct prefix p;
887 struct route_node *rn;
888
gdt630e4802004-08-31 17:28:41 +0000889 ospf_vertex_dump("ospf_spf_register(): adding to SPF tree:", v, 1, 1);
890
paul718e3742002-12-13 20:15:29 +0000891 p.family = AF_INET;
892 p.prefixlen = IPV4_MAX_BITLEN;
893 p.u.prefix4 = v->id;
894
895 if (v->type == OSPF_VERTEX_ROUTER)
896 rn = route_node_get (rv, &p);
897 else
898 rn = route_node_get (nv, &p);
899
900 rn->info = v;
901}
902
903void
904ospf_spf_route_free (struct route_table *table)
905{
906 struct route_node *rn;
907 struct vertex *v;
908
909 for (rn = route_top (table); rn; rn = route_next (rn))
910 {
911 if ((v = rn->info))
paul0c0f9cd2003-06-06 23:27:04 +0000912 {
913 ospf_vertex_free (v);
914 rn->info = NULL;
915 }
paul718e3742002-12-13 20:15:29 +0000916
917 route_unlock_node (rn);
918 }
919
920 route_table_finish (table);
921}
922
923void
924ospf_spf_dump (struct vertex *v, int i)
925{
926 listnode cnode;
927 listnode nnode;
928 struct vertex_nexthop *nexthop;
929
930 if (v->type == OSPF_VERTEX_ROUTER)
931 {
932 if (IS_DEBUG_OSPF_EVENT)
paul0c0f9cd2003-06-06 23:27:04 +0000933 zlog_info ("SPF Result: %d [R] %s", i, inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000934 }
935 else
936 {
937 struct network_lsa *lsa = (struct network_lsa *) v->lsa;
938 if (IS_DEBUG_OSPF_EVENT)
paul0c0f9cd2003-06-06 23:27:04 +0000939 zlog_info ("SPF Result: %d [N] %s/%d", i, inet_ntoa (v->lsa->id),
940 ip_masklen (lsa->mask));
gdt630e4802004-08-31 17:28:41 +0000941 }
paul718e3742002-12-13 20:15:29 +0000942
gdt630e4802004-08-31 17:28:41 +0000943 for (nnode = listhead (v->nexthop); nnode; nextnode (nnode))
944 {
945 nexthop = getdata (nnode);
946 if (IS_DEBUG_OSPF_EVENT)
947 zlog_info (" nexthop %s", inet_ntoa (nexthop->router));
paul718e3742002-12-13 20:15:29 +0000948 }
949
950 i++;
951
952 for (cnode = listhead (v->child); cnode; nextnode (cnode))
953 {
954 v = getdata (cnode);
955 ospf_spf_dump (v, i);
956 }
957}
958
959/* Second stage of SPF calculation. */
960void
paul0c0f9cd2003-06-06 23:27:04 +0000961ospf_spf_process_stubs (struct ospf_area *area, struct vertex *v,
paul718e3742002-12-13 20:15:29 +0000962 struct route_table *rt)
963{
964 listnode cnode;
965 struct vertex *child;
966
967 if (IS_DEBUG_OSPF_EVENT)
968 zlog_info ("ospf_process_stub():processing stubs for area %s",
paul0c0f9cd2003-06-06 23:27:04 +0000969 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +0000970 if (v->type == OSPF_VERTEX_ROUTER)
971 {
972 u_char *p;
973 u_char *lim;
974 struct router_lsa_link *l;
975 struct router_lsa *rlsa;
976
paul0c0f9cd2003-06-06 23:27:04 +0000977 if (IS_DEBUG_OSPF_EVENT)
gdt630e4802004-08-31 17:28:41 +0000978 zlog_info ("ospf_process_stubs():processing router LSA, id: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000979 inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000980 rlsa = (struct router_lsa *) v->lsa;
981
982
paul0c0f9cd2003-06-06 23:27:04 +0000983 if (IS_DEBUG_OSPF_EVENT)
gdt630e4802004-08-31 17:28:41 +0000984 zlog_info ("ospf_process_stubs(): we have %d links to process",
paul0c0f9cd2003-06-06 23:27:04 +0000985 ntohs (rlsa->links));
gdt630e4802004-08-31 17:28:41 +0000986 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +0000987 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
988
989 while (p < lim)
990 {
991 l = (struct router_lsa_link *) p;
992
993 p += (ROUTER_LSA_MIN_SIZE +
994 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
995
996 if (l->m[0].type == LSA_LINK_TYPE_STUB)
997 ospf_intra_add_stub (rt, l, v, area);
998 }
999 }
1000
gdt630e4802004-08-31 17:28:41 +00001001 ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1, 1);
paul718e3742002-12-13 20:15:29 +00001002
1003 for (cnode = listhead (v->child); cnode; nextnode (cnode))
1004 {
1005 child = getdata (cnode);
1006
1007 if (CHECK_FLAG (child->flags, OSPF_VERTEX_PROCESSED))
paul0c0f9cd2003-06-06 23:27:04 +00001008 continue;
paul718e3742002-12-13 20:15:29 +00001009
1010 ospf_spf_process_stubs (area, child, rt);
1011
1012 SET_FLAG (child->flags, OSPF_VERTEX_PROCESSED);
1013 }
1014}
1015
1016void
1017ospf_rtrs_free (struct route_table *rtrs)
1018{
1019 struct route_node *rn;
1020 list or_list;
1021 listnode node;
1022
1023 if (IS_DEBUG_OSPF_EVENT)
paul0c0f9cd2003-06-06 23:27:04 +00001024 zlog_info ("Route: Router Routing Table free");
paul718e3742002-12-13 20:15:29 +00001025
1026 for (rn = route_top (rtrs); rn; rn = route_next (rn))
1027 if ((or_list = rn->info) != NULL)
1028 {
paul0c0f9cd2003-06-06 23:27:04 +00001029 for (node = listhead (or_list); node; nextnode (node))
1030 ospf_route_free (node->data);
paul718e3742002-12-13 20:15:29 +00001031
paul0c0f9cd2003-06-06 23:27:04 +00001032 list_delete (or_list);
paul718e3742002-12-13 20:15:29 +00001033
paul0c0f9cd2003-06-06 23:27:04 +00001034 /* Unlock the node. */
1035 rn->info = NULL;
1036 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001037 }
1038 route_table_finish (rtrs);
1039}
1040
1041void
1042ospf_rtrs_print (struct route_table *rtrs)
1043{
1044 struct route_node *rn;
1045 list or_list;
1046 listnode ln;
1047 listnode pnode;
1048 struct ospf_route *or;
1049 struct ospf_path *path;
1050 char buf1[BUFSIZ];
1051 char buf2[BUFSIZ];
1052
1053 if (IS_DEBUG_OSPF_EVENT)
1054 zlog_info ("ospf_rtrs_print() start");
1055
1056 for (rn = route_top (rtrs); rn; rn = route_next (rn))
1057 if ((or_list = rn->info) != NULL)
1058 for (ln = listhead (or_list); ln; nextnode (ln))
1059 {
1060 or = getdata (ln);
1061
1062 switch (or->path_type)
1063 {
1064 case OSPF_PATH_INTRA_AREA:
paul0c0f9cd2003-06-06 23:27:04 +00001065 if (IS_DEBUG_OSPF_EVENT)
1066 zlog_info ("%s [%d] area: %s",
1067 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1068 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1069 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +00001070 break;
1071 case OSPF_PATH_INTER_AREA:
paul0c0f9cd2003-06-06 23:27:04 +00001072 if (IS_DEBUG_OSPF_EVENT)
1073 zlog_info ("%s IA [%d] area: %s",
1074 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1075 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1076 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +00001077 break;
1078 default:
1079 break;
1080 }
1081
paul96735ee2003-08-10 02:51:22 +00001082 for (pnode = listhead (or->paths); pnode; nextnode (pnode))
paul718e3742002-12-13 20:15:29 +00001083 {
1084 path = getdata (pnode);
1085 if (path->nexthop.s_addr == 0)
paul0c0f9cd2003-06-06 23:27:04 +00001086 {
1087 if (IS_DEBUG_OSPF_EVENT)
1088 zlog_info (" directly attached to %s\r\n",
1089 IF_NAME (path->oi));
1090 }
1091 else
1092 {
1093 if (IS_DEBUG_OSPF_EVENT)
1094 zlog_info (" via %s, %s\r\n",
1095 inet_ntoa (path->nexthop), IF_NAME (path->oi));
1096 }
paul718e3742002-12-13 20:15:29 +00001097 }
1098 }
1099
1100 zlog_info ("ospf_rtrs_print() end");
1101}
1102
1103/* Calculating the shortest-path tree for an area. */
1104void
paul0c0f9cd2003-06-06 23:27:04 +00001105ospf_spf_calculate (struct ospf_area *area, struct route_table *new_table,
paul718e3742002-12-13 20:15:29 +00001106 struct route_table *new_rtrs)
1107{
1108 list candidate;
1109 listnode node;
1110 struct vertex *v;
1111 struct route_table *rv;
1112 struct route_table *nv;
1113
1114 if (IS_DEBUG_OSPF_EVENT)
1115 {
1116 zlog_info ("ospf_spf_calculate: Start");
paul0c0f9cd2003-06-06 23:27:04 +00001117 zlog_info ("ospf_spf_calculate: running Dijkstra for area %s",
1118 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001119 }
1120
1121 /* Check router-lsa-self. If self-router-lsa is not yet allocated,
1122 return this area's calculation. */
paul0c0f9cd2003-06-06 23:27:04 +00001123 if (!area->router_lsa_self)
paul718e3742002-12-13 20:15:29 +00001124 {
1125 if (IS_DEBUG_OSPF_EVENT)
paul0c0f9cd2003-06-06 23:27:04 +00001126 zlog_info ("ospf_spf_calculate: "
1127 "Skip area %s's calculation due to empty router_lsa_self",
1128 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001129 return;
1130 }
1131
1132 /* RFC2328 16.1. (1). */
paul0c0f9cd2003-06-06 23:27:04 +00001133 /* Initialize the algorithm's data structures. */
paul718e3742002-12-13 20:15:29 +00001134 rv = route_table_init ();
1135 nv = route_table_init ();
1136
paul0c0f9cd2003-06-06 23:27:04 +00001137 /* Clear the list of candidate vertices. */
paul718e3742002-12-13 20:15:29 +00001138 candidate = list_new ();
1139
1140 /* Initialize the shortest-path tree to only the root (which is the
1141 router doing the calculation). */
1142 ospf_spf_init (area);
1143 v = area->spf;
1144 ospf_spf_register (v, rv, nv);
1145
1146 /* Set Area A's TransitCapability to FALSE. */
1147 area->transit = OSPF_TRANSIT_FALSE;
1148 area->shortcut_capability = 1;
1149
1150 for (;;)
1151 {
1152 /* RFC2328 16.1. (2). */
1153 ospf_spf_next (v, area, candidate, rv, nv);
1154
1155 /* RFC2328 16.1. (3). */
1156 /* If at this step the candidate list is empty, the shortest-
1157 path tree (of transit vertices) has been completely built and
1158 this stage of the procedure terminates. */
1159 if (listcount (candidate) == 0)
1160 break;
1161
1162 /* Otherwise, choose the vertex belonging to the candidate list
1163 that is closest to the root, and add it to the shortest-path
1164 tree (removing it from the candidate list in the
paul0c0f9cd2003-06-06 23:27:04 +00001165 process). */
paul718e3742002-12-13 20:15:29 +00001166 node = listhead (candidate);
1167 v = getdata (node);
1168 ospf_vertex_add_parent (v);
1169
gdt630e4802004-08-31 17:28:41 +00001170 /* Remove from the candidate list. */
paul718e3742002-12-13 20:15:29 +00001171 listnode_delete (candidate, v);
1172
1173 /* Add to SPF tree. */
1174 ospf_spf_register (v, rv, nv);
1175
1176 /* Note that when there is a choice of vertices closest to the
1177 root, network vertices must be chosen before router vertices
1178 in order to necessarily find all equal-cost paths. */
1179 /* We don't do this at this moment, we should add the treatment
1180 above codes. -- kunihiro. */
1181
1182 /* RFC2328 16.1. (4). */
1183 if (v->type == OSPF_VERTEX_ROUTER)
1184 ospf_intra_add_router (new_rtrs, v, area);
paul0c0f9cd2003-06-06 23:27:04 +00001185 else
paul718e3742002-12-13 20:15:29 +00001186 ospf_intra_add_transit (new_table, v, area);
1187
1188 /* RFC2328 16.1. (5). */
1189 /* Iterate the algorithm by returning to Step 2. */
gdt630e4802004-08-31 17:28:41 +00001190
1191 } /* end loop until no more candidate vertices */
paul718e3742002-12-13 20:15:29 +00001192
1193 if (IS_DEBUG_OSPF_EVENT)
1194 {
1195 ospf_spf_dump (area->spf, 0);
1196 ospf_route_table_dump (new_table);
1197 }
1198
1199 /* Second stage of SPF calculation procedure's */
1200 ospf_spf_process_stubs (area, area->spf, new_table);
1201
1202 /* Free all vertices which allocated for SPF calculation */
1203 ospf_spf_route_free (rv);
1204 ospf_spf_route_free (nv);
1205
1206 /* Free candidate list */
1207 list_free (candidate);
1208
1209 /* Increment SPF Calculation Counter. */
1210 area->spf_calculation++;
1211
paul68980082003-03-25 05:07:42 +00001212 area->ospf->ts_spf = time (NULL);
paul718e3742002-12-13 20:15:29 +00001213
1214 if (IS_DEBUG_OSPF_EVENT)
1215 zlog_info ("ospf_spf_calculate: Stop");
1216}
1217
1218/* Timer for SPF calculation. */
1219int
paul68980082003-03-25 05:07:42 +00001220ospf_spf_calculate_timer (struct thread *thread)
paul718e3742002-12-13 20:15:29 +00001221{
paul68980082003-03-25 05:07:42 +00001222 struct ospf *ospf = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +00001223 struct route_table *new_table, *new_rtrs;
paul718e3742002-12-13 20:15:29 +00001224 listnode node;
1225
1226 if (IS_DEBUG_OSPF_EVENT)
1227 zlog_info ("SPF: Timer (SPF calculation expire)");
paul0c0f9cd2003-06-06 23:27:04 +00001228
paul718e3742002-12-13 20:15:29 +00001229 ospf->t_spf_calc = NULL;
1230
1231 /* Allocate new table tree. */
1232 new_table = route_table_init ();
paul0c0f9cd2003-06-06 23:27:04 +00001233 new_rtrs = route_table_init ();
paul718e3742002-12-13 20:15:29 +00001234
paul68980082003-03-25 05:07:42 +00001235 ospf_vl_unapprove (ospf);
paul718e3742002-12-13 20:15:29 +00001236
1237 /* Calculate SPF for each area. */
1238 for (node = listhead (ospf->areas); node; node = nextnode (node))
1239 ospf_spf_calculate (node->data, new_table, new_rtrs);
1240
paul68980082003-03-25 05:07:42 +00001241 ospf_vl_shut_unapproved (ospf);
paul718e3742002-12-13 20:15:29 +00001242
paul68980082003-03-25 05:07:42 +00001243 ospf_ia_routing (ospf, new_table, new_rtrs);
paul718e3742002-12-13 20:15:29 +00001244
1245 ospf_prune_unreachable_networks (new_table);
1246 ospf_prune_unreachable_routers (new_rtrs);
1247
1248 /* AS-external-LSA calculation should not be performed here. */
1249
1250 /* If new Router Route is installed,
1251 then schedule re-calculate External routes. */
1252 if (1)
paul68980082003-03-25 05:07:42 +00001253 ospf_ase_calculate_schedule (ospf);
paul718e3742002-12-13 20:15:29 +00001254
paul68980082003-03-25 05:07:42 +00001255 ospf_ase_calculate_timer_add (ospf);
paul718e3742002-12-13 20:15:29 +00001256
1257 /* Update routing table. */
paul68980082003-03-25 05:07:42 +00001258 ospf_route_install (ospf, new_table);
paul718e3742002-12-13 20:15:29 +00001259
1260 /* Update ABR/ASBR routing table */
paul68980082003-03-25 05:07:42 +00001261 if (ospf->old_rtrs)
paul718e3742002-12-13 20:15:29 +00001262 {
1263 /* old_rtrs's node holds linked list of ospf_route. --kunihiro. */
paul68980082003-03-25 05:07:42 +00001264 /* ospf_route_delete (ospf->old_rtrs); */
1265 ospf_rtrs_free (ospf->old_rtrs);
paul718e3742002-12-13 20:15:29 +00001266 }
1267
paul68980082003-03-25 05:07:42 +00001268 ospf->old_rtrs = ospf->new_rtrs;
1269 ospf->new_rtrs = new_rtrs;
paul718e3742002-12-13 20:15:29 +00001270
paul0c0f9cd2003-06-06 23:27:04 +00001271 if (IS_OSPF_ABR (ospf))
paul68980082003-03-25 05:07:42 +00001272 ospf_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001273
1274 if (IS_DEBUG_OSPF_EVENT)
1275 zlog_info ("SPF: calculation complete");
1276
1277 return 0;
1278}
1279
1280/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
1281 set timer for SPF calc. */
1282void
paul68980082003-03-25 05:07:42 +00001283ospf_spf_calculate_schedule (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00001284{
1285 time_t ht, delay;
1286
1287 if (IS_DEBUG_OSPF_EVENT)
1288 zlog_info ("SPF: calculation timer scheduled");
1289
1290 /* OSPF instance does not exist. */
paul68980082003-03-25 05:07:42 +00001291 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001292 return;
1293
1294 /* SPF calculation timer is already scheduled. */
paul68980082003-03-25 05:07:42 +00001295 if (ospf->t_spf_calc)
paul718e3742002-12-13 20:15:29 +00001296 {
1297 if (IS_DEBUG_OSPF_EVENT)
paul0c0f9cd2003-06-06 23:27:04 +00001298 zlog_info ("SPF: calculation timer is already scheduled: %p",
1299 ospf->t_spf_calc);
paul718e3742002-12-13 20:15:29 +00001300 return;
1301 }
1302
paul68980082003-03-25 05:07:42 +00001303 ht = time (NULL) - ospf->ts_spf;
paul718e3742002-12-13 20:15:29 +00001304
1305 /* Get SPF calculation delay time. */
paul68980082003-03-25 05:07:42 +00001306 if (ht < ospf->spf_holdtime)
paul718e3742002-12-13 20:15:29 +00001307 {
paul68980082003-03-25 05:07:42 +00001308 if (ospf->spf_holdtime - ht < ospf->spf_delay)
paul0c0f9cd2003-06-06 23:27:04 +00001309 delay = ospf->spf_delay;
paul718e3742002-12-13 20:15:29 +00001310 else
paul0c0f9cd2003-06-06 23:27:04 +00001311 delay = ospf->spf_holdtime - ht;
paul718e3742002-12-13 20:15:29 +00001312 }
1313 else
paul68980082003-03-25 05:07:42 +00001314 delay = ospf->spf_delay;
paul718e3742002-12-13 20:15:29 +00001315
1316 if (IS_DEBUG_OSPF_EVENT)
hassofa2b17e2004-03-04 17:45:00 +00001317 zlog_info ("SPF: calculation timer delay = %ld", (long)delay);
paul68980082003-03-25 05:07:42 +00001318 ospf->t_spf_calc =
1319 thread_add_timer (master, ospf_spf_calculate_timer, ospf, delay);
paul718e3742002-12-13 20:15:29 +00001320}