blob: 0fd39fa17888527ffb245384cc2c796452cf53e6 [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
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 {
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{
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
hasso52dc7ee2004-09-23 19:18:23 +0000313ospf_nexthop_add_unique (struct vertex_nexthop *new, struct list *nexthop)
paul718e3742002-12-13 20:15:29 +0000314{
315 struct vertex_nexthop *nh;
hasso52dc7ee2004-09-23 19:18:23 +0000316 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000317 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
hasso52dc7ee2004-09-23 19:18:23 +0000346ospf_nexthop_merge (struct list *a, struct list *b)
paul718e3742002-12-13 20:15:29 +0000347{
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{
hasso52dc7ee2004-09-23 19:18:23 +0000463 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000464 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
hasso52dc7ee2004-09-23 19:18:23 +0000650ospf_install_candidate (struct list *candidate, struct vertex *w)
paul718e3742002-12-13 20:15:29 +0000651{
hasso52dc7ee2004-09-23 19:18:23 +0000652 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000653 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,
hasso52dc7ee2004-09-23 19:18:23 +0000697 struct list *candidate, struct route_table *rv,
698 struct route_table *nv)
paul718e3742002-12-13 20:15:29 +0000699{
700 struct ospf_lsa *w_lsa = NULL;
701 struct vertex *w, *cw;
702 u_char *p;
703 u_char *lim;
704 struct router_lsa_link *l = NULL;
705 struct in_addr *r;
hasso52dc7ee2004-09-23 19:18:23 +0000706 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000707 int type = 0;
708
709 /* If this is a router-LSA, and bit V of the router-LSA (see Section
710 A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE. */
711 if (v->type == OSPF_VERTEX_ROUTER)
712 {
713 if (IS_ROUTER_LSA_VIRTUAL ((struct router_lsa *) v->lsa))
714 area->transit = OSPF_TRANSIT_TRUE;
715 }
716
717 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul0c0f9cd2003-06-06 23:27:04 +0000718 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
719
paul718e3742002-12-13 20:15:29 +0000720 while (p < lim)
721 {
pauld355bfa2004-04-08 07:43:45 +0000722 int link = -1; /* link index for w's back link */
723
paul718e3742002-12-13 20:15:29 +0000724 /* In case of V is Router-LSA. */
725 if (v->lsa->type == OSPF_ROUTER_LSA)
726 {
727 l = (struct router_lsa_link *) p;
728
paul0c0f9cd2003-06-06 23:27:04 +0000729 p += (ROUTER_LSA_MIN_SIZE +
paul718e3742002-12-13 20:15:29 +0000730 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
731
732 /* (a) If this is a link to a stub network, examine the next
733 link in V's LSA. Links to stub networks will be
734 considered in the second stage of the shortest path
735 calculation. */
736 if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB)
737 continue;
738
739 /* (b) Otherwise, W is a transit vertex (router or transit
740 network). Look up the vertex W's LSA (router-LSA or
741 network-LSA) in Area A's link state database. */
742 switch (type)
743 {
744 case LSA_LINK_TYPE_POINTOPOINT:
745 case LSA_LINK_TYPE_VIRTUALLINK:
746 if (type == LSA_LINK_TYPE_VIRTUALLINK)
paul0c0f9cd2003-06-06 23:27:04 +0000747 {
748 if (IS_DEBUG_OSPF_EVENT)
749 zlog_info ("looking up LSA through VL: %s",
750 inet_ntoa (l->link_id));
751 }
paul718e3742002-12-13 20:15:29 +0000752
753 w_lsa = ospf_lsa_lookup (area, OSPF_ROUTER_LSA, l->link_id,
754 l->link_id);
755 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000756 {
757 if (IS_DEBUG_OSPF_EVENT)
gdt630e4802004-08-31 17:28:41 +0000758 zlog_info ("found Router LSA %s", inet_ntoa (l->link_id));
paul0c0f9cd2003-06-06 23:27:04 +0000759 }
paul718e3742002-12-13 20:15:29 +0000760 break;
761 case LSA_LINK_TYPE_TRANSIT:
paul0c0f9cd2003-06-06 23:27:04 +0000762 if (IS_DEBUG_OSPF_EVENT)
paul718e3742002-12-13 20:15:29 +0000763
paul0c0f9cd2003-06-06 23:27:04 +0000764 zlog_info ("Looking up Network LSA, ID: %s",
765 inet_ntoa (l->link_id));
paul718e3742002-12-13 20:15:29 +0000766 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_NETWORK_LSA,
paul0c0f9cd2003-06-06 23:27:04 +0000767 l->link_id);
paul718e3742002-12-13 20:15:29 +0000768 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000769 if (IS_DEBUG_OSPF_EVENT)
770 zlog_info ("found the LSA");
paul718e3742002-12-13 20:15:29 +0000771 break;
772 default:
paul0c0f9cd2003-06-06 23:27:04 +0000773 zlog_warn ("Invalid LSA link type %d", type);
paul718e3742002-12-13 20:15:29 +0000774 continue;
775 }
776 }
777 else
778 {
779 /* In case of V is Network-LSA. */
paul0c0f9cd2003-06-06 23:27:04 +0000780 r = (struct in_addr *) p;
paul718e3742002-12-13 20:15:29 +0000781 p += sizeof (struct in_addr);
782
783 /* Lookup the vertex W's LSA. */
784 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_ROUTER_LSA, *r);
785 }
786
787 /* (b cont.) If the LSA does not exist, or its LS age is equal
788 to MaxAge, or it does not have a link back to vertex V,
789 examine the next link in V's LSA.[23] */
790 if (w_lsa == NULL)
791 continue;
792
793 if (IS_LSA_MAXAGE (w_lsa))
794 continue;
795
pauld355bfa2004-04-08 07:43:45 +0000796 if ( (link = ospf_lsa_has_link (w_lsa->data, v->lsa)) < 0 )
paul718e3742002-12-13 20:15:29 +0000797 {
paul0c0f9cd2003-06-06 23:27:04 +0000798 if (IS_DEBUG_OSPF_EVENT)
799 zlog_info ("The LSA doesn't have a link back");
paul718e3742002-12-13 20:15:29 +0000800 continue;
801 }
802
803 /* (c) If vertex W is already on the shortest-path tree, examine
804 the next link in the LSA. */
805 if (ospf_spf_has_vertex (rv, nv, w_lsa->data))
806 {
paul0c0f9cd2003-06-06 23:27:04 +0000807 if (IS_DEBUG_OSPF_EVENT)
808 zlog_info ("The LSA is already in SPF");
paul718e3742002-12-13 20:15:29 +0000809 continue;
810 }
811
812 /* (d) Calculate the link state cost D of the resulting path
813 from the root to vertex W. D is equal to the sum of the link
814 state cost of the (already calculated) shortest path to
815 vertex V and the advertised cost of the link between vertices
816 V and W. If D is: */
817
818 /* prepare vertex W. */
819 w = ospf_vertex_new (w_lsa);
820
pauld355bfa2004-04-08 07:43:45 +0000821 /* Save W's back link index number, for use by virtual links */
822 w->backlink = link;
823
paul718e3742002-12-13 20:15:29 +0000824 /* calculate link cost D. */
825 if (v->lsa->type == OSPF_ROUTER_LSA)
gdt630e4802004-08-31 17:28:41 +0000826 w->distance = v->distance + ntohs (l->m[0].metric);
827 else /* v is not a Router-LSA */
828 w->distance = v->distance;
paul718e3742002-12-13 20:15:29 +0000829
830 /* Is there already vertex W in candidate list? */
831 node = ospf_vertex_lookup (candidate, w->id, w->type);
832 if (node == NULL)
833 {
gdt630e4802004-08-31 17:28:41 +0000834 /* W is a new candidate. Calculate nexthop to W and add W
835 * to the candidate list.
836 */
paul718e3742002-12-13 20:15:29 +0000837 ospf_nexthop_calculation (area, v, w);
838
839 ospf_install_candidate (candidate, w);
840 }
841 else
842 {
gdt630e4802004-08-31 17:28:41 +0000843 /* W is already on the candidate list; call it cw.
844 * Compare the previously calculated cost (cw->distance)
845 * with the cost we just determined (w->distance) to see
846 * if we've found a shorter path.
847 */
paul718e3742002-12-13 20:15:29 +0000848 cw = (struct vertex *) getdata (node);
849
gdt630e4802004-08-31 17:28:41 +0000850 /* If the previous cost was lower, we didn't find a
851 * shorter path, so we're done with w.
852 */
paul718e3742002-12-13 20:15:29 +0000853 if (cw->distance < w->distance)
854 {
855 ospf_vertex_free (w);
856 continue;
857 }
paul718e3742002-12-13 20:15:29 +0000858 else if (cw->distance == w->distance)
859 {
gdt630e4802004-08-31 17:28:41 +0000860 /* Found an equal-cost path to W. Calculate nexthop to W. */
paul718e3742002-12-13 20:15:29 +0000861 ospf_nexthop_calculation (area, v, w);
862 ospf_nexthop_merge (cw->nexthop, w->nexthop);
863 list_delete_all_node (w->nexthop);
864 ospf_vertex_free (w);
865 }
paul718e3742002-12-13 20:15:29 +0000866 else
867 {
gdt630e4802004-08-31 17:28:41 +0000868 /* Found a lower-cost path to W. Calculate nexthop to W. */
paul718e3742002-12-13 20:15:29 +0000869 ospf_nexthop_calculation (area, v, w);
870
871 /* Remove old vertex from candidate list. */
872 ospf_vertex_free (cw);
873 listnode_delete (candidate, cw);
874
gdt630e4802004-08-31 17:28:41 +0000875 /* Install new W to candidate list. */
paul718e3742002-12-13 20:15:29 +0000876 ospf_install_candidate (candidate, w);
877 }
gdt630e4802004-08-31 17:28:41 +0000878 } /* end W is already on the candidate list */
879 } /* end loop over the links in V's LSA */
paul718e3742002-12-13 20:15:29 +0000880}
881
882/* Add vertex V to SPF tree. */
883void
884ospf_spf_register (struct vertex *v, struct route_table *rv,
paul0c0f9cd2003-06-06 23:27:04 +0000885 struct route_table *nv)
paul718e3742002-12-13 20:15:29 +0000886{
887 struct prefix p;
888 struct route_node *rn;
889
gdt630e4802004-08-31 17:28:41 +0000890 ospf_vertex_dump("ospf_spf_register(): adding to SPF tree:", v, 1, 1);
891
paul718e3742002-12-13 20:15:29 +0000892 p.family = AF_INET;
893 p.prefixlen = IPV4_MAX_BITLEN;
894 p.u.prefix4 = v->id;
895
896 if (v->type == OSPF_VERTEX_ROUTER)
897 rn = route_node_get (rv, &p);
898 else
899 rn = route_node_get (nv, &p);
900
901 rn->info = v;
902}
903
904void
905ospf_spf_route_free (struct route_table *table)
906{
907 struct route_node *rn;
908 struct vertex *v;
909
910 for (rn = route_top (table); rn; rn = route_next (rn))
911 {
912 if ((v = rn->info))
paul0c0f9cd2003-06-06 23:27:04 +0000913 {
914 ospf_vertex_free (v);
915 rn->info = NULL;
916 }
paul718e3742002-12-13 20:15:29 +0000917
918 route_unlock_node (rn);
919 }
920
921 route_table_finish (table);
922}
923
924void
925ospf_spf_dump (struct vertex *v, int i)
926{
hasso52dc7ee2004-09-23 19:18:23 +0000927 struct listnode *cnode;
928 struct listnode *nnode;
paul718e3742002-12-13 20:15:29 +0000929 struct vertex_nexthop *nexthop;
930
931 if (v->type == OSPF_VERTEX_ROUTER)
932 {
933 if (IS_DEBUG_OSPF_EVENT)
paul0c0f9cd2003-06-06 23:27:04 +0000934 zlog_info ("SPF Result: %d [R] %s", i, inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000935 }
936 else
937 {
938 struct network_lsa *lsa = (struct network_lsa *) v->lsa;
939 if (IS_DEBUG_OSPF_EVENT)
paul0c0f9cd2003-06-06 23:27:04 +0000940 zlog_info ("SPF Result: %d [N] %s/%d", i, inet_ntoa (v->lsa->id),
941 ip_masklen (lsa->mask));
gdt630e4802004-08-31 17:28:41 +0000942 }
paul718e3742002-12-13 20:15:29 +0000943
gdt630e4802004-08-31 17:28:41 +0000944 for (nnode = listhead (v->nexthop); nnode; nextnode (nnode))
945 {
946 nexthop = getdata (nnode);
947 if (IS_DEBUG_OSPF_EVENT)
948 zlog_info (" nexthop %s", inet_ntoa (nexthop->router));
paul718e3742002-12-13 20:15:29 +0000949 }
950
951 i++;
952
953 for (cnode = listhead (v->child); cnode; nextnode (cnode))
954 {
955 v = getdata (cnode);
956 ospf_spf_dump (v, i);
957 }
958}
959
960/* Second stage of SPF calculation. */
961void
paul0c0f9cd2003-06-06 23:27:04 +0000962ospf_spf_process_stubs (struct ospf_area *area, struct vertex *v,
paul718e3742002-12-13 20:15:29 +0000963 struct route_table *rt)
964{
hasso52dc7ee2004-09-23 19:18:23 +0000965 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000966 struct vertex *child;
967
968 if (IS_DEBUG_OSPF_EVENT)
969 zlog_info ("ospf_process_stub():processing stubs for area %s",
paul0c0f9cd2003-06-06 23:27:04 +0000970 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +0000971 if (v->type == OSPF_VERTEX_ROUTER)
972 {
973 u_char *p;
974 u_char *lim;
975 struct router_lsa_link *l;
976 struct router_lsa *rlsa;
977
paul0c0f9cd2003-06-06 23:27:04 +0000978 if (IS_DEBUG_OSPF_EVENT)
gdt630e4802004-08-31 17:28:41 +0000979 zlog_info ("ospf_process_stubs():processing router LSA, id: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000980 inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000981 rlsa = (struct router_lsa *) v->lsa;
982
983
paul0c0f9cd2003-06-06 23:27:04 +0000984 if (IS_DEBUG_OSPF_EVENT)
gdt630e4802004-08-31 17:28:41 +0000985 zlog_info ("ospf_process_stubs(): we have %d links to process",
paul0c0f9cd2003-06-06 23:27:04 +0000986 ntohs (rlsa->links));
gdt630e4802004-08-31 17:28:41 +0000987 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +0000988 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
989
990 while (p < lim)
991 {
992 l = (struct router_lsa_link *) p;
993
994 p += (ROUTER_LSA_MIN_SIZE +
995 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
996
997 if (l->m[0].type == LSA_LINK_TYPE_STUB)
998 ospf_intra_add_stub (rt, l, v, area);
999 }
1000 }
1001
gdt630e4802004-08-31 17:28:41 +00001002 ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1, 1);
paul718e3742002-12-13 20:15:29 +00001003
1004 for (cnode = listhead (v->child); cnode; nextnode (cnode))
1005 {
1006 child = getdata (cnode);
1007
1008 if (CHECK_FLAG (child->flags, OSPF_VERTEX_PROCESSED))
paul0c0f9cd2003-06-06 23:27:04 +00001009 continue;
paul718e3742002-12-13 20:15:29 +00001010
1011 ospf_spf_process_stubs (area, child, rt);
1012
1013 SET_FLAG (child->flags, OSPF_VERTEX_PROCESSED);
1014 }
1015}
1016
1017void
1018ospf_rtrs_free (struct route_table *rtrs)
1019{
1020 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001021 struct list *or_list;
1022 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001023
1024 if (IS_DEBUG_OSPF_EVENT)
paul0c0f9cd2003-06-06 23:27:04 +00001025 zlog_info ("Route: Router Routing Table free");
paul718e3742002-12-13 20:15:29 +00001026
1027 for (rn = route_top (rtrs); rn; rn = route_next (rn))
1028 if ((or_list = rn->info) != NULL)
1029 {
paul0c0f9cd2003-06-06 23:27:04 +00001030 for (node = listhead (or_list); node; nextnode (node))
1031 ospf_route_free (node->data);
paul718e3742002-12-13 20:15:29 +00001032
paul0c0f9cd2003-06-06 23:27:04 +00001033 list_delete (or_list);
paul718e3742002-12-13 20:15:29 +00001034
paul0c0f9cd2003-06-06 23:27:04 +00001035 /* Unlock the node. */
1036 rn->info = NULL;
1037 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001038 }
1039 route_table_finish (rtrs);
1040}
1041
1042void
1043ospf_rtrs_print (struct route_table *rtrs)
1044{
1045 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001046 struct list *or_list;
1047 struct listnode *ln;
1048 struct listnode *pnode;
paul718e3742002-12-13 20:15:29 +00001049 struct ospf_route *or;
1050 struct ospf_path *path;
1051 char buf1[BUFSIZ];
1052 char buf2[BUFSIZ];
1053
1054 if (IS_DEBUG_OSPF_EVENT)
1055 zlog_info ("ospf_rtrs_print() start");
1056
1057 for (rn = route_top (rtrs); rn; rn = route_next (rn))
1058 if ((or_list = rn->info) != NULL)
1059 for (ln = listhead (or_list); ln; nextnode (ln))
1060 {
1061 or = getdata (ln);
1062
1063 switch (or->path_type)
1064 {
1065 case OSPF_PATH_INTRA_AREA:
paul0c0f9cd2003-06-06 23:27:04 +00001066 if (IS_DEBUG_OSPF_EVENT)
1067 zlog_info ("%s [%d] area: %s",
1068 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1069 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1070 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +00001071 break;
1072 case OSPF_PATH_INTER_AREA:
paul0c0f9cd2003-06-06 23:27:04 +00001073 if (IS_DEBUG_OSPF_EVENT)
1074 zlog_info ("%s IA [%d] area: %s",
1075 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1076 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1077 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +00001078 break;
1079 default:
1080 break;
1081 }
1082
paul96735ee2003-08-10 02:51:22 +00001083 for (pnode = listhead (or->paths); pnode; nextnode (pnode))
paul718e3742002-12-13 20:15:29 +00001084 {
1085 path = getdata (pnode);
1086 if (path->nexthop.s_addr == 0)
paul0c0f9cd2003-06-06 23:27:04 +00001087 {
1088 if (IS_DEBUG_OSPF_EVENT)
1089 zlog_info (" directly attached to %s\r\n",
1090 IF_NAME (path->oi));
1091 }
1092 else
1093 {
1094 if (IS_DEBUG_OSPF_EVENT)
1095 zlog_info (" via %s, %s\r\n",
1096 inet_ntoa (path->nexthop), IF_NAME (path->oi));
1097 }
paul718e3742002-12-13 20:15:29 +00001098 }
1099 }
1100
1101 zlog_info ("ospf_rtrs_print() end");
1102}
1103
1104/* Calculating the shortest-path tree for an area. */
1105void
paul0c0f9cd2003-06-06 23:27:04 +00001106ospf_spf_calculate (struct ospf_area *area, struct route_table *new_table,
paul718e3742002-12-13 20:15:29 +00001107 struct route_table *new_rtrs)
1108{
hasso52dc7ee2004-09-23 19:18:23 +00001109 struct list *candidate;
1110 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001111 struct vertex *v;
1112 struct route_table *rv;
1113 struct route_table *nv;
1114
1115 if (IS_DEBUG_OSPF_EVENT)
1116 {
1117 zlog_info ("ospf_spf_calculate: Start");
paul0c0f9cd2003-06-06 23:27:04 +00001118 zlog_info ("ospf_spf_calculate: running Dijkstra for area %s",
1119 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001120 }
1121
1122 /* Check router-lsa-self. If self-router-lsa is not yet allocated,
1123 return this area's calculation. */
paul0c0f9cd2003-06-06 23:27:04 +00001124 if (!area->router_lsa_self)
paul718e3742002-12-13 20:15:29 +00001125 {
1126 if (IS_DEBUG_OSPF_EVENT)
paul0c0f9cd2003-06-06 23:27:04 +00001127 zlog_info ("ospf_spf_calculate: "
1128 "Skip area %s's calculation due to empty router_lsa_self",
1129 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001130 return;
1131 }
1132
1133 /* RFC2328 16.1. (1). */
paul0c0f9cd2003-06-06 23:27:04 +00001134 /* Initialize the algorithm's data structures. */
paul718e3742002-12-13 20:15:29 +00001135 rv = route_table_init ();
1136 nv = route_table_init ();
1137
paul0c0f9cd2003-06-06 23:27:04 +00001138 /* Clear the list of candidate vertices. */
paul718e3742002-12-13 20:15:29 +00001139 candidate = list_new ();
1140
1141 /* Initialize the shortest-path tree to only the root (which is the
1142 router doing the calculation). */
1143 ospf_spf_init (area);
1144 v = area->spf;
1145 ospf_spf_register (v, rv, nv);
1146
1147 /* Set Area A's TransitCapability to FALSE. */
1148 area->transit = OSPF_TRANSIT_FALSE;
1149 area->shortcut_capability = 1;
1150
1151 for (;;)
1152 {
1153 /* RFC2328 16.1. (2). */
1154 ospf_spf_next (v, area, candidate, rv, nv);
1155
1156 /* RFC2328 16.1. (3). */
1157 /* If at this step the candidate list is empty, the shortest-
1158 path tree (of transit vertices) has been completely built and
1159 this stage of the procedure terminates. */
1160 if (listcount (candidate) == 0)
1161 break;
1162
1163 /* Otherwise, choose the vertex belonging to the candidate list
1164 that is closest to the root, and add it to the shortest-path
1165 tree (removing it from the candidate list in the
paul0c0f9cd2003-06-06 23:27:04 +00001166 process). */
paul718e3742002-12-13 20:15:29 +00001167 node = listhead (candidate);
1168 v = getdata (node);
1169 ospf_vertex_add_parent (v);
1170
gdt630e4802004-08-31 17:28:41 +00001171 /* Remove from the candidate list. */
paul718e3742002-12-13 20:15:29 +00001172 listnode_delete (candidate, v);
1173
1174 /* Add to SPF tree. */
1175 ospf_spf_register (v, rv, nv);
1176
1177 /* Note that when there is a choice of vertices closest to the
1178 root, network vertices must be chosen before router vertices
1179 in order to necessarily find all equal-cost paths. */
1180 /* We don't do this at this moment, we should add the treatment
1181 above codes. -- kunihiro. */
1182
1183 /* RFC2328 16.1. (4). */
1184 if (v->type == OSPF_VERTEX_ROUTER)
1185 ospf_intra_add_router (new_rtrs, v, area);
paul0c0f9cd2003-06-06 23:27:04 +00001186 else
paul718e3742002-12-13 20:15:29 +00001187 ospf_intra_add_transit (new_table, v, area);
1188
1189 /* RFC2328 16.1. (5). */
1190 /* Iterate the algorithm by returning to Step 2. */
gdt630e4802004-08-31 17:28:41 +00001191
1192 } /* end loop until no more candidate vertices */
paul718e3742002-12-13 20:15:29 +00001193
1194 if (IS_DEBUG_OSPF_EVENT)
1195 {
1196 ospf_spf_dump (area->spf, 0);
1197 ospf_route_table_dump (new_table);
1198 }
1199
1200 /* Second stage of SPF calculation procedure's */
1201 ospf_spf_process_stubs (area, area->spf, new_table);
1202
1203 /* Free all vertices which allocated for SPF calculation */
1204 ospf_spf_route_free (rv);
1205 ospf_spf_route_free (nv);
1206
1207 /* Free candidate list */
1208 list_free (candidate);
1209
1210 /* Increment SPF Calculation Counter. */
1211 area->spf_calculation++;
1212
paul68980082003-03-25 05:07:42 +00001213 area->ospf->ts_spf = time (NULL);
paul718e3742002-12-13 20:15:29 +00001214
1215 if (IS_DEBUG_OSPF_EVENT)
1216 zlog_info ("ospf_spf_calculate: Stop");
1217}
1218
1219/* Timer for SPF calculation. */
1220int
paul68980082003-03-25 05:07:42 +00001221ospf_spf_calculate_timer (struct thread *thread)
paul718e3742002-12-13 20:15:29 +00001222{
paul68980082003-03-25 05:07:42 +00001223 struct ospf *ospf = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +00001224 struct route_table *new_table, *new_rtrs;
hasso52dc7ee2004-09-23 19:18:23 +00001225 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001226
1227 if (IS_DEBUG_OSPF_EVENT)
1228 zlog_info ("SPF: Timer (SPF calculation expire)");
paul0c0f9cd2003-06-06 23:27:04 +00001229
paul718e3742002-12-13 20:15:29 +00001230 ospf->t_spf_calc = NULL;
1231
1232 /* Allocate new table tree. */
1233 new_table = route_table_init ();
paul0c0f9cd2003-06-06 23:27:04 +00001234 new_rtrs = route_table_init ();
paul718e3742002-12-13 20:15:29 +00001235
paul68980082003-03-25 05:07:42 +00001236 ospf_vl_unapprove (ospf);
paul718e3742002-12-13 20:15:29 +00001237
1238 /* Calculate SPF for each area. */
1239 for (node = listhead (ospf->areas); node; node = nextnode (node))
1240 ospf_spf_calculate (node->data, new_table, new_rtrs);
1241
paul68980082003-03-25 05:07:42 +00001242 ospf_vl_shut_unapproved (ospf);
paul718e3742002-12-13 20:15:29 +00001243
paul68980082003-03-25 05:07:42 +00001244 ospf_ia_routing (ospf, new_table, new_rtrs);
paul718e3742002-12-13 20:15:29 +00001245
1246 ospf_prune_unreachable_networks (new_table);
1247 ospf_prune_unreachable_routers (new_rtrs);
1248
1249 /* AS-external-LSA calculation should not be performed here. */
1250
1251 /* If new Router Route is installed,
1252 then schedule re-calculate External routes. */
1253 if (1)
paul68980082003-03-25 05:07:42 +00001254 ospf_ase_calculate_schedule (ospf);
paul718e3742002-12-13 20:15:29 +00001255
paul68980082003-03-25 05:07:42 +00001256 ospf_ase_calculate_timer_add (ospf);
paul718e3742002-12-13 20:15:29 +00001257
1258 /* Update routing table. */
paul68980082003-03-25 05:07:42 +00001259 ospf_route_install (ospf, new_table);
paul718e3742002-12-13 20:15:29 +00001260
1261 /* Update ABR/ASBR routing table */
paul68980082003-03-25 05:07:42 +00001262 if (ospf->old_rtrs)
paul718e3742002-12-13 20:15:29 +00001263 {
1264 /* old_rtrs's node holds linked list of ospf_route. --kunihiro. */
paul68980082003-03-25 05:07:42 +00001265 /* ospf_route_delete (ospf->old_rtrs); */
1266 ospf_rtrs_free (ospf->old_rtrs);
paul718e3742002-12-13 20:15:29 +00001267 }
1268
paul68980082003-03-25 05:07:42 +00001269 ospf->old_rtrs = ospf->new_rtrs;
1270 ospf->new_rtrs = new_rtrs;
paul718e3742002-12-13 20:15:29 +00001271
paul0c0f9cd2003-06-06 23:27:04 +00001272 if (IS_OSPF_ABR (ospf))
paul68980082003-03-25 05:07:42 +00001273 ospf_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001274
1275 if (IS_DEBUG_OSPF_EVENT)
1276 zlog_info ("SPF: calculation complete");
1277
1278 return 0;
1279}
1280
1281/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
1282 set timer for SPF calc. */
1283void
paul68980082003-03-25 05:07:42 +00001284ospf_spf_calculate_schedule (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00001285{
1286 time_t ht, delay;
1287
1288 if (IS_DEBUG_OSPF_EVENT)
1289 zlog_info ("SPF: calculation timer scheduled");
1290
1291 /* OSPF instance does not exist. */
paul68980082003-03-25 05:07:42 +00001292 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001293 return;
1294
1295 /* SPF calculation timer is already scheduled. */
paul68980082003-03-25 05:07:42 +00001296 if (ospf->t_spf_calc)
paul718e3742002-12-13 20:15:29 +00001297 {
1298 if (IS_DEBUG_OSPF_EVENT)
paul0c0f9cd2003-06-06 23:27:04 +00001299 zlog_info ("SPF: calculation timer is already scheduled: %p",
1300 ospf->t_spf_calc);
paul718e3742002-12-13 20:15:29 +00001301 return;
1302 }
1303
paul68980082003-03-25 05:07:42 +00001304 ht = time (NULL) - ospf->ts_spf;
paul718e3742002-12-13 20:15:29 +00001305
1306 /* Get SPF calculation delay time. */
paul68980082003-03-25 05:07:42 +00001307 if (ht < ospf->spf_holdtime)
paul718e3742002-12-13 20:15:29 +00001308 {
paul68980082003-03-25 05:07:42 +00001309 if (ospf->spf_holdtime - ht < ospf->spf_delay)
paul0c0f9cd2003-06-06 23:27:04 +00001310 delay = ospf->spf_delay;
paul718e3742002-12-13 20:15:29 +00001311 else
paul0c0f9cd2003-06-06 23:27:04 +00001312 delay = ospf->spf_holdtime - ht;
paul718e3742002-12-13 20:15:29 +00001313 }
1314 else
paul68980082003-03-25 05:07:42 +00001315 delay = ospf->spf_delay;
paul718e3742002-12-13 20:15:29 +00001316
1317 if (IS_DEBUG_OSPF_EVENT)
hassofa2b17e2004-03-04 17:45:00 +00001318 zlog_info ("SPF: calculation timer delay = %ld", (long)delay);
paul68980082003-03-25 05:07:42 +00001319 ospf->t_spf_calc =
1320 thread_add_timer (master, ospf_spf_calculate_timer, ospf, delay);
paul718e3742002-12-13 20:15:29 +00001321}