blob: 1298ebe8c4deb7c8fe1faaa8ff2c02a2e8dea3df [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* OSPF SPF calculation.
2 Copyright (C) 1999, 2000 Kunihiro Ishiguro, Toshiaki Takada
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22
23#include "thread.h"
24#include "memory.h"
25#include "hash.h"
26#include "linklist.h"
27#include "prefix.h"
28#include "if.h"
29#include "table.h"
30#include "log.h"
31#include "sockunion.h" /* for inet_ntop () */
32
33#include "ospfd/ospfd.h"
34#include "ospfd/ospf_interface.h"
35#include "ospfd/ospf_ism.h"
36#include "ospfd/ospf_asbr.h"
37#include "ospfd/ospf_lsa.h"
38#include "ospfd/ospf_lsdb.h"
39#include "ospfd/ospf_neighbor.h"
40#include "ospfd/ospf_nsm.h"
41#include "ospfd/ospf_spf.h"
42#include "ospfd/ospf_route.h"
43#include "ospfd/ospf_ia.h"
44#include "ospfd/ospf_ase.h"
45#include "ospfd/ospf_abr.h"
46#include "ospfd/ospf_dump.h"
47
48#define DEBUG
49
50struct vertex_nexthop *
51vertex_nexthop_new (struct vertex *parent)
52{
53 struct vertex_nexthop *new;
54
55 new = XCALLOC (MTYPE_OSPF_NEXTHOP, sizeof (struct vertex_nexthop));
56 new->parent = parent;
57
58 return new;
59}
60
61void
62vertex_nexthop_free (struct vertex_nexthop *nh)
63{
64 XFREE (MTYPE_OSPF_NEXTHOP, nh);
65}
66
67struct vertex_nexthop *
68vertex_nexthop_dup (struct vertex_nexthop *nh)
69{
70 struct vertex_nexthop *new;
71
72 new = vertex_nexthop_new (nh->parent);
73
74 new->oi = nh->oi;
75 new->router = nh->router;
76
77 return new;
78}
paul718e3742002-12-13 20:15:29 +000079
paul0c0f9cd2003-06-06 23:27:04 +000080
paul718e3742002-12-13 20:15:29 +000081struct vertex *
82ospf_vertex_new (struct ospf_lsa *lsa)
83{
84 struct vertex *new;
85
86 new = XMALLOC (MTYPE_OSPF_VERTEX, sizeof (struct vertex));
87 memset (new, 0, sizeof (struct vertex));
88
89 new->flags = 0;
90 new->type = lsa->data->type;
91 new->id = lsa->data->id;
92 new->lsa = lsa->data;
93 new->distance = 0;
94 new->child = list_new ();
95 new->nexthop = list_new ();
pauld355bfa2004-04-08 07:43:45 +000096 new->backlink = -1;
paul718e3742002-12-13 20:15:29 +000097
98 return new;
99}
100
101void
102ospf_vertex_free (struct vertex *v)
103{
hasso52dc7ee2004-09-23 19:18:23 +0000104 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000105
106 list_delete (v->child);
107
108 if (listcount (v->nexthop) > 0)
109 for (node = listhead (v->nexthop); node; nextnode (node))
110 vertex_nexthop_free (node->data);
111
112 list_delete (v->nexthop);
113
114 XFREE (MTYPE_OSPF_VERTEX, v);
115}
116
117void
hassoeb1ce602004-10-08 08:17:22 +0000118ospf_vertex_dump(const char *msg, struct vertex *v,
gdt630e4802004-08-31 17:28:41 +0000119 int print_nexthops, int print_children)
120{
121 if ( ! IS_DEBUG_OSPF_EVENT)
122 return;
123
ajs2a42e282004-12-08 18:43:03 +0000124 zlog_debug("%s %s vertex %s distance %u backlink %d flags %u",
gdt630e4802004-08-31 17:28:41 +0000125 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 {
ajs2a42e282004-12-08 18:43:03 +0000144 zlog_debug (" nexthop %s interface %s parent %s",
gdt630e4802004-08-31 17:28:41 +0000145 inet_ntop(AF_INET, &nexthop->router, buf1, BUFSIZ),
146 nexthop->oi ? IF_NAME(nexthop->oi) : "NULL",
147 nexthop->parent ? inet_ntop(AF_INET,
148 &nexthop->parent->id,
149 buf2, BUFSIZ)
150 : "NULL");
151 }
152 }
153 }
154
155 if (print_children)
156 {
hasso52dc7ee2004-09-23 19:18:23 +0000157 struct listnode *cnode;
gdt630e4802004-08-31 17:28:41 +0000158 for (cnode = listhead (v->child); cnode; nextnode (cnode))
159 {
160 struct vertex *cv = getdata (cnode);
161 if (cv)
162 ospf_vertex_dump(" child:", cv, 0, 0);
163 }
164 }
165}
166
167
168/* Add a vertex to the list of children in each of its parents. */
169void
paul718e3742002-12-13 20:15:29 +0000170ospf_vertex_add_parent (struct vertex *v)
171{
172 struct vertex_nexthop *nh;
hasso52dc7ee2004-09-23 19:18:23 +0000173 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000174
175 for (node = listhead (v->nexthop); node; nextnode (node))
176 {
177 nh = (struct vertex_nexthop *) getdata (node);
178
179 /* No need to add two links from the same parent. */
180 if (listnode_lookup (nh->parent->child, v) == NULL)
paul0c0f9cd2003-06-06 23:27:04 +0000181 listnode_add (nh->parent->child, v);
paul718e3742002-12-13 20:15:29 +0000182 }
183}
184
185void
186ospf_spf_init (struct ospf_area *area)
187{
188 struct vertex *v;
189
190 /* Create root node. */
191 v = ospf_vertex_new (area->router_lsa_self);
192
193 area->spf = v;
194
195 /* Reset ABR and ASBR router counts. */
196 area->abr_count = 0;
197 area->asbr_count = 0;
198}
199
gdt630e4802004-08-31 17:28:41 +0000200/* Check if the vertex represented by lsa is on the SPF tree. */
paul718e3742002-12-13 20:15:29 +0000201int
202ospf_spf_has_vertex (struct route_table *rv, struct route_table *nv,
203 struct lsa_header *lsa)
204{
205 struct prefix p;
206 struct route_node *rn;
207
208 p.family = AF_INET;
209 p.prefixlen = IPV4_MAX_BITLEN;
210 p.u.prefix4 = lsa->id;
211
212 if (lsa->type == OSPF_ROUTER_LSA)
213 rn = route_node_get (rv, &p);
214 else
215 rn = route_node_get (nv, &p);
216
217 if (rn->info != NULL)
218 {
219 route_unlock_node (rn);
220 return 1;
221 }
222 return 0;
223}
224
gdt630e4802004-08-31 17:28:41 +0000225/* Find the vertex specified by the given id and LSA type
226 * in vlist (the candidate list).
227 */
hasso52dc7ee2004-09-23 19:18:23 +0000228struct listnode *
229ospf_vertex_lookup (struct list *vlist, struct in_addr id, int type)
paul718e3742002-12-13 20:15:29 +0000230{
hasso52dc7ee2004-09-23 19:18:23 +0000231 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000232 struct vertex *v;
233
234 for (node = listhead (vlist); node; nextnode (node))
235 {
236 v = (struct vertex *) getdata (node);
237 if (IPV4_ADDR_SAME (&id, &v->id) && type == v->type)
238 return node;
239 }
240
241 return NULL;
242}
243
pauld355bfa2004-04-08 07:43:45 +0000244/* return index of link back to V from W, or -1 if no link found */
paul718e3742002-12-13 20:15:29 +0000245int
246ospf_lsa_has_link (struct lsa_header *w, struct lsa_header *v)
247{
hassoeb1ce602004-10-08 08:17:22 +0000248 unsigned int i, length;
paul718e3742002-12-13 20:15:29 +0000249 struct router_lsa *rl;
250 struct network_lsa *nl;
251
252 /* In case of W is Network LSA. */
253 if (w->type == OSPF_NETWORK_LSA)
254 {
255 if (v->type == OSPF_NETWORK_LSA)
pauld355bfa2004-04-08 07:43:45 +0000256 return -1;
paul718e3742002-12-13 20:15:29 +0000257
258 nl = (struct network_lsa *) w;
259 length = (ntohs (w->length) - OSPF_LSA_HEADER_SIZE - 4) / 4;
paul0c0f9cd2003-06-06 23:27:04 +0000260
paul718e3742002-12-13 20:15:29 +0000261 for (i = 0; i < length; i++)
262 if (IPV4_ADDR_SAME (&nl->routers[i], &v->id))
pauld355bfa2004-04-08 07:43:45 +0000263 return i;
264 return -1;
paul718e3742002-12-13 20:15:29 +0000265 }
266
267 /* In case of W is Router LSA. */
268 if (w->type == OSPF_ROUTER_LSA)
269 {
270 rl = (struct router_lsa *) w;
271
272 length = ntohs (w->length);
273
274 for (i = 0;
paul0c0f9cd2003-06-06 23:27:04 +0000275 i < ntohs (rl->links) && length >= sizeof (struct router_lsa);
276 i++, length -= 12)
paul718e3742002-12-13 20:15:29 +0000277 {
278 switch (rl->link[i].type)
279 {
280 case LSA_LINK_TYPE_POINTOPOINT:
281 case LSA_LINK_TYPE_VIRTUALLINK:
282 /* Router LSA ID. */
283 if (v->type == OSPF_ROUTER_LSA &&
284 IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
285 {
pauld355bfa2004-04-08 07:43:45 +0000286 return i;
paul718e3742002-12-13 20:15:29 +0000287 }
288 break;
289 case LSA_LINK_TYPE_TRANSIT:
290 /* Network LSA ID. */
291 if (v->type == OSPF_NETWORK_LSA &&
292 IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
293 {
pauld355bfa2004-04-08 07:43:45 +0000294 return i;
paul0c0f9cd2003-06-06 23:27:04 +0000295 }
paul718e3742002-12-13 20:15:29 +0000296 break;
297 case LSA_LINK_TYPE_STUB:
298 /* Not take into count? */
299 continue;
300 default:
301 break;
302 }
303 }
304 }
pauld355bfa2004-04-08 07:43:45 +0000305 return -1;
paul718e3742002-12-13 20:15:29 +0000306}
307
308/* Add the nexthop to the list, only if it is unique.
309 * If it's not unique, free the nexthop entry.
310 */
311void
hasso52dc7ee2004-09-23 19:18:23 +0000312ospf_nexthop_add_unique (struct vertex_nexthop *new, struct list *nexthop)
paul718e3742002-12-13 20:15:29 +0000313{
314 struct vertex_nexthop *nh;
hasso52dc7ee2004-09-23 19:18:23 +0000315 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000316 int match;
317
318 match = 0;
319 for (node = listhead (nexthop); node; nextnode (node))
320 {
321 nh = node->data;
322
323 /* Compare the two entries. */
324 /* XXX
325 * Comparing the parent preserves the shortest path tree
326 * structure even when the nexthops are identical.
327 */
328 if (nh->oi == new->oi &&
paul0c0f9cd2003-06-06 23:27:04 +0000329 IPV4_ADDR_SAME (&nh->router, &new->router) &&
330 nh->parent == new->parent)
331 {
332 match = 1;
333 break;
334 }
paul718e3742002-12-13 20:15:29 +0000335 }
336
337 if (!match)
338 listnode_add (nexthop, new);
339 else
340 vertex_nexthop_free (new);
341}
342
343/* Merge entries in list b into list a. */
344void
hasso52dc7ee2004-09-23 19:18:23 +0000345ospf_nexthop_merge (struct list *a, struct list *b)
paul718e3742002-12-13 20:15:29 +0000346{
347 struct listnode *n;
348
349 for (n = listhead (b); n; nextnode (n))
350 {
351 ospf_nexthop_add_unique (n->data, a);
352 }
353}
354
355#define ROUTER_LSA_MIN_SIZE 12
356#define ROUTER_LSA_TOS_SIZE 4
357
gdt630e4802004-08-31 17:28:41 +0000358/* Find the next link after prev_link from v to w. If prev_link is
359 * NULL, return the first link from v to w. Ignore stub and virtual links;
360 * these link types will never be returned.
361 */
paul718e3742002-12-13 20:15:29 +0000362struct router_lsa_link *
363ospf_get_next_link (struct vertex *v, struct vertex *w,
paul0c0f9cd2003-06-06 23:27:04 +0000364 struct router_lsa_link *prev_link)
paul718e3742002-12-13 20:15:29 +0000365{
366 u_char *p;
367 u_char *lim;
368 struct router_lsa_link *l;
369
370 if (prev_link == NULL)
gdt630e4802004-08-31 17:28:41 +0000371 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +0000372 else
373 {
paul0c0f9cd2003-06-06 23:27:04 +0000374 p = (u_char *) prev_link;
paul718e3742002-12-13 20:15:29 +0000375 p += (ROUTER_LSA_MIN_SIZE +
376 (prev_link->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
377 }
paul0c0f9cd2003-06-06 23:27:04 +0000378
paul718e3742002-12-13 20:15:29 +0000379 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
380
381 while (p < lim)
382 {
383 l = (struct router_lsa_link *) p;
384
paul0c0f9cd2003-06-06 23:27:04 +0000385 p += (ROUTER_LSA_MIN_SIZE + (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
paul718e3742002-12-13 20:15:29 +0000386
387 if (l->m[0].type == LSA_LINK_TYPE_STUB)
388 continue;
389
390 /* Defer NH calculation via VLs until summaries from
391 transit areas area confidered */
392
393 if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK)
paul0c0f9cd2003-06-06 23:27:04 +0000394 continue;
paul718e3742002-12-13 20:15:29 +0000395
396 if (IPV4_ADDR_SAME (&l->link_id, &w->id))
paul0c0f9cd2003-06-06 23:27:04 +0000397 return l;
paul718e3742002-12-13 20:15:29 +0000398 }
399
400 return NULL;
401}
402
paul75ee0b82004-08-05 09:10:31 +0000403/*
404 * Consider supplied next-hop for inclusion to the supplied list of
405 * equal-cost next-hops, adjust list as neccessary.
406 *
407 * (Discussed on GNU Zebra list 27 May 2003, [zebra 19184])
408 *
409 * Note that below is a bit of a hack, and limits ECMP to paths that go to
410 * same nexthop. Where as paths via inequal output_cost interfaces could
411 * still quite easily be ECMP due to remote cost differences.
412 *
413 * TODO: It really should be done by way of recording currently valid
414 * backlinks and determining the appropriate nexthops from the list of
415 * backlinks, or even simpler, just flushing nexthop list if we find a lower
416 * cost path to a candidate vertex in SPF, maybe.
paulbf9392c2003-06-06 23:23:36 +0000417 */
paul0c0f9cd2003-06-06 23:27:04 +0000418void
419ospf_spf_consider_nexthop (struct list *nexthops,
420 struct vertex_nexthop *newhop)
paulbf9392c2003-06-06 23:23:36 +0000421{
paulbf9392c2003-06-06 23:23:36 +0000422 struct vertex_nexthop *hop;
paul75ee0b82004-08-05 09:10:31 +0000423 struct listnode *ln, *nn;
paul0c0f9cd2003-06-06 23:27:04 +0000424
paul75ee0b82004-08-05 09:10:31 +0000425 /* nexthop list should contain only the set of nexthops that have the lowest
426 * equal cost
427 */
428 if (nexthops->head != NULL)
429 {
430 hop = getdata (nexthops->head);
431
432 /* weed out hops with higher cost than the newhop */
433 if (hop->oi->output_cost > newhop->oi->output_cost)
434 {
435 /* delete the existing nexthops */
436 for (ln = nexthops->head; ln; ln = nn)
437 {
438 nn = ln->next;
439 hop = getdata (ln);
440
441 listnode_delete (nexthops, hop);
442 vertex_nexthop_free (hop);
443 }
444 }
445 else if (hop->oi->output_cost < newhop->oi->output_cost)
paul0c0f9cd2003-06-06 23:27:04 +0000446 return;
paul75ee0b82004-08-05 09:10:31 +0000447 }
paul0c0f9cd2003-06-06 23:27:04 +0000448
paulbf9392c2003-06-06 23:23:36 +0000449 /* new hop is <= existing hops, add it */
paul0c0f9cd2003-06-06 23:27:04 +0000450 listnode_add (nexthops, newhop);
paulbf9392c2003-06-06 23:23:36 +0000451
452 return;
453}
454
gdt630e4802004-08-31 17:28:41 +0000455/* 16.1.1. Calculate nexthop from root through V (parent) to
456 * vertex W (destination).
457 */
paul718e3742002-12-13 20:15:29 +0000458void
459ospf_nexthop_calculation (struct ospf_area *area,
460 struct vertex *v, struct vertex *w)
461{
hasso52dc7ee2004-09-23 19:18:23 +0000462 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000463 struct vertex_nexthop *nh, *x;
464 struct ospf_interface *oi = NULL;
465 struct router_lsa_link *l = NULL;
paul0c0f9cd2003-06-06 23:27:04 +0000466
467
paul718e3742002-12-13 20:15:29 +0000468 if (IS_DEBUG_OSPF_EVENT)
gdt630e4802004-08-31 17:28:41 +0000469 {
ajs2a42e282004-12-08 18:43:03 +0000470 zlog_debug ("ospf_nexthop_calculation(): Start");
gdt630e4802004-08-31 17:28:41 +0000471 ospf_vertex_dump("V (parent):", v, 1, 1);
472 ospf_vertex_dump("W (dest) :", w, 1, 1);
473 }
paul718e3742002-12-13 20:15:29 +0000474
paul718e3742002-12-13 20:15:29 +0000475 if (v == area->spf)
476 {
gdt630e4802004-08-31 17:28:41 +0000477 /* 16.1.1 para 4. In the first case, the parent vertex (V) is the
478 root (the calculating router itself). This means that the
479 destination is either a directly connected network or directly
480 connected router. The outgoing interface in this case is simply
481 the OSPF interface connecting to the destination network/router.
482 */
483
paul718e3742002-12-13 20:15:29 +0000484 if (w->type == OSPF_VERTEX_ROUTER)
paul0c0f9cd2003-06-06 23:27:04 +0000485 {
486 while ((l = ospf_get_next_link (v, w, l)))
487 {
gdt630e4802004-08-31 17:28:41 +0000488 /* l is a link from v to w
489 * l2 will be link from w to v
490 */
paul0c0f9cd2003-06-06 23:27:04 +0000491 struct router_lsa_link *l2 = NULL;
492
gdt630e4802004-08-31 17:28:41 +0000493 if (IS_DEBUG_OSPF_EVENT)
494 {
495 char buf1[BUFSIZ];
ajs2a42e282004-12-08 18:43:03 +0000496 zlog_debug("ospf_nexthop_calculation(): considering link "
gdt630e4802004-08-31 17:28:41 +0000497 "type %d link_id %s link_data %s",
498 l->m[0].type,
499 inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ),
500 inet_ntop (AF_INET, &l->link_data, buf1, BUFSIZ));
501 }
502
paul0c0f9cd2003-06-06 23:27:04 +0000503 if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT)
504 {
gdt630e4802004-08-31 17:28:41 +0000505 /* If the destination is a router which connects to
506 the calculating router via a Point-to-MultiPoint
507 network, the destination's next hop IP address(es)
508 can be determined by examining the destination's
509 router-LSA: each link pointing back to the
510 calculating router and having a Link Data field
511 belonging to the Point-to-MultiPoint network
512 provides an IP address of the next hop router.
513
514 At this point l is a link from V to W, and V is the
515 root ("us"). Find the local interface associated
516 with l (its address is in l->link_data). If it
517 is a point-to-multipoint interface, then look through
518 the links in the opposite direction (W to V). If
519 any of them have an address that lands within the
520 subnet declared by the PtMP link, then that link
521 is a constituent of the PtMP link, and its address is
522 a nexthop address for V.
523 */
paul68980082003-03-25 05:07:42 +0000524 oi = ospf_if_is_configured (area->ospf, &l->link_data);
paul7afa08d2002-12-13 20:59:45 +0000525 if (oi && oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
paul0c0f9cd2003-06-06 23:27:04 +0000526 {
527 struct prefix_ipv4 la;
gdt630e4802004-08-31 17:28:41 +0000528
529 la.family = AF_INET;
paul0c0f9cd2003-06-06 23:27:04 +0000530 la.prefixlen = oi->address->prefixlen;
gdt630e4802004-08-31 17:28:41 +0000531
532 /* V links to W on PtMP interface
533 - find the interface address on W */
paul0c0f9cd2003-06-06 23:27:04 +0000534 while ((l2 = ospf_get_next_link (w, v, l2)))
535 {
536 la.prefix = l2->link_data;
537
538 if (prefix_cmp ((struct prefix *) &la,
539 oi->address) == 0)
540 /* link_data is on our PtMP network */
541 break;
542 }
gdt630e4802004-08-31 17:28:41 +0000543 } /* end l is on point-to-multipoint link */
paul0c0f9cd2003-06-06 23:27:04 +0000544 else
545 {
gdt630e4802004-08-31 17:28:41 +0000546 /* l is a regular point-to-point link.
547 Look for a link from W to V.
548 */
paul0c0f9cd2003-06-06 23:27:04 +0000549 while ((l2 = ospf_get_next_link (w, v, l2)))
550 {
551 oi = ospf_if_is_configured (area->ospf,
552 &(l2->link_data));
553
554 if (oi == NULL)
555 continue;
556
557 if (!IPV4_ADDR_SAME (&oi->address->u.prefix4,
558 &l->link_data))
559 continue;
560
561 break;
562 }
563 }
564
565 if (oi && l2)
566 {
gdt630e4802004-08-31 17:28:41 +0000567 /* found all necessary info to build nexthop */
paul0c0f9cd2003-06-06 23:27:04 +0000568 nh = vertex_nexthop_new (v);
569 nh->oi = oi;
570 nh->router = l2->link_data;
571 ospf_spf_consider_nexthop (w->nexthop, nh);
572 }
gdt630e4802004-08-31 17:28:41 +0000573 else
574 {
575 zlog_info("ospf_nexthop_calculation(): "
576 "could not determine nexthop for link");
577 }
578 } /* end point-to-point link from V to W */
579 } /* end iterate over links in W */
580 } /* end W is a Router vertex */
paul718e3742002-12-13 20:15:29 +0000581 else
paul0c0f9cd2003-06-06 23:27:04 +0000582 {
gdt630e4802004-08-31 17:28:41 +0000583 assert(w->type == OSPF_VERTEX_NETWORK);
paul0c0f9cd2003-06-06 23:27:04 +0000584 while ((l = ospf_get_next_link (v, w, l)))
585 {
586 oi = ospf_if_is_configured (area->ospf, &(l->link_data));
587 if (oi)
588 {
589 nh = vertex_nexthop_new (v);
590 nh->oi = oi;
591 nh->router.s_addr = 0;
paul75ee0b82004-08-05 09:10:31 +0000592 ospf_spf_consider_nexthop (w->nexthop, nh);
paul0c0f9cd2003-06-06 23:27:04 +0000593 }
594 }
595 }
paul718e3742002-12-13 20:15:29 +0000596 return;
gdt630e4802004-08-31 17:28:41 +0000597 } /* end V is the root */
598
599 /* Check if W's parent is a network connected to root. */
paul718e3742002-12-13 20:15:29 +0000600 else if (v->type == OSPF_VERTEX_NETWORK)
601 {
gdt630e4802004-08-31 17:28:41 +0000602 /* See if any of V's parents are the root. */
paul718e3742002-12-13 20:15:29 +0000603 for (node = listhead (v->nexthop); node; nextnode (node))
604 {
gdt630e4802004-08-31 17:28:41 +0000605 x = (struct vertex_nexthop *) getdata (node);
606 if (x->parent == area->spf) /* connects to root? */
607 {
608 /* 16.1.1 para 5. ...the parent vertex is a network that
609 * directly connects the calculating router to the destination
610 * router. The list of next hops is then determined by
611 * examining the destination's router-LSA...
612 */
613
614 assert(w->type == OSPF_VERTEX_ROUTER);
paul0c0f9cd2003-06-06 23:27:04 +0000615 while ((l = ospf_get_next_link (w, v, l)))
616 {
gdt630e4802004-08-31 17:28:41 +0000617 /* ...For each link in the router-LSA that points back to the
618 * parent network, the link's Link Data field provides the IP
619 * address of a next hop router. The outgoing interface to
620 * use can then be derived from the next hop IP address (or
621 * it can be inherited from the parent network).
622 */
paul0c0f9cd2003-06-06 23:27:04 +0000623 nh = vertex_nexthop_new (v);
624 nh->oi = x->oi;
625 nh->router = l->link_data;
paul75ee0b82004-08-05 09:10:31 +0000626 ospf_spf_consider_nexthop (w->nexthop, nh);
paul0c0f9cd2003-06-06 23:27:04 +0000627 }
628 return;
629 }
paul718e3742002-12-13 20:15:29 +0000630 }
631 }
632
gdt630e4802004-08-31 17:28:41 +0000633 /* 16.1.1 para 4. If there is at least one intervening router in the
634 * current shortest path between the destination and the root, the
635 * destination simply inherits the set of next hops from the
636 * parent.
637 */
paul718e3742002-12-13 20:15:29 +0000638 for (node = listhead (v->nexthop); node; nextnode (node))
639 {
640 nh = vertex_nexthop_dup (node->data);
641 nh->parent = v;
642 ospf_nexthop_add_unique (nh, w->nexthop);
643 }
644}
645
gdt630e4802004-08-31 17:28:41 +0000646/* Add a vertex to the SPF candidate list. */
paul718e3742002-12-13 20:15:29 +0000647void
hasso52dc7ee2004-09-23 19:18:23 +0000648ospf_install_candidate (struct list *candidate, struct vertex *w)
paul718e3742002-12-13 20:15:29 +0000649{
hasso52dc7ee2004-09-23 19:18:23 +0000650 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000651 struct vertex *cw;
652
gdt630e4802004-08-31 17:28:41 +0000653 ospf_vertex_dump("ospf_install_candidate(): add to candidate list", w, 1, 1);
654
paul718e3742002-12-13 20:15:29 +0000655 if (list_isempty (candidate))
656 {
657 listnode_add (candidate, w);
658 return;
659 }
660
661 /* Install vertex with sorting by distance. */
662 for (node = listhead (candidate); node; nextnode (node))
663 {
664 cw = (struct vertex *) getdata (node);
665 if (cw->distance > w->distance)
666 {
667 list_add_node_prev (candidate, node, w);
668 break;
669 }
670 else if (node->next == NULL)
671 {
672 list_add_node_next (candidate, node, w);
673 break;
674 }
675 }
gdt630e4802004-08-31 17:28:41 +0000676
677 if (IS_DEBUG_OSPF_EVENT)
678 {
ajs2a42e282004-12-08 18:43:03 +0000679 zlog_debug("ospf_install_candidate(): candidate list now contains:");
gdt630e4802004-08-31 17:28:41 +0000680 for (node = listhead (candidate); node; nextnode (node))
681 {
682 cw = (struct vertex *) getdata (node);
683 ospf_vertex_dump(" candidate:", cw, 0, 0);
684 }
685 }
paul718e3742002-12-13 20:15:29 +0000686}
687
gdt630e4802004-08-31 17:28:41 +0000688/* RFC2328 Section 16.1 (2).
689 * v is on the SPF tree. Examine the links in v's LSA. Update the list
690 * of candidates with any vertices not already on the list. If a lower-cost
691 * path is found to a vertex already on the candidate list, store the new cost.
692 */
paul718e3742002-12-13 20:15:29 +0000693void
694ospf_spf_next (struct vertex *v, struct ospf_area *area,
hasso52dc7ee2004-09-23 19:18:23 +0000695 struct list *candidate, struct route_table *rv,
696 struct route_table *nv)
paul718e3742002-12-13 20:15:29 +0000697{
698 struct ospf_lsa *w_lsa = NULL;
699 struct vertex *w, *cw;
700 u_char *p;
701 u_char *lim;
702 struct router_lsa_link *l = NULL;
703 struct in_addr *r;
hasso52dc7ee2004-09-23 19:18:23 +0000704 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000705 int type = 0;
706
707 /* If this is a router-LSA, and bit V of the router-LSA (see Section
708 A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE. */
709 if (v->type == OSPF_VERTEX_ROUTER)
710 {
711 if (IS_ROUTER_LSA_VIRTUAL ((struct router_lsa *) v->lsa))
712 area->transit = OSPF_TRANSIT_TRUE;
713 }
714
715 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul0c0f9cd2003-06-06 23:27:04 +0000716 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
717
paul718e3742002-12-13 20:15:29 +0000718 while (p < lim)
719 {
pauld355bfa2004-04-08 07:43:45 +0000720 int link = -1; /* link index for w's back link */
721
paul718e3742002-12-13 20:15:29 +0000722 /* In case of V is Router-LSA. */
723 if (v->lsa->type == OSPF_ROUTER_LSA)
724 {
725 l = (struct router_lsa_link *) p;
726
paul0c0f9cd2003-06-06 23:27:04 +0000727 p += (ROUTER_LSA_MIN_SIZE +
paul718e3742002-12-13 20:15:29 +0000728 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
729
730 /* (a) If this is a link to a stub network, examine the next
731 link in V's LSA. Links to stub networks will be
732 considered in the second stage of the shortest path
733 calculation. */
734 if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB)
735 continue;
736
737 /* (b) Otherwise, W is a transit vertex (router or transit
738 network). Look up the vertex W's LSA (router-LSA or
739 network-LSA) in Area A's link state database. */
740 switch (type)
741 {
742 case LSA_LINK_TYPE_POINTOPOINT:
743 case LSA_LINK_TYPE_VIRTUALLINK:
744 if (type == LSA_LINK_TYPE_VIRTUALLINK)
paul0c0f9cd2003-06-06 23:27:04 +0000745 {
746 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000747 zlog_debug ("looking up LSA through VL: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000748 inet_ntoa (l->link_id));
749 }
paul718e3742002-12-13 20:15:29 +0000750
751 w_lsa = ospf_lsa_lookup (area, OSPF_ROUTER_LSA, l->link_id,
752 l->link_id);
753 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000754 {
755 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000756 zlog_debug ("found Router LSA %s", inet_ntoa (l->link_id));
paul0c0f9cd2003-06-06 23:27:04 +0000757 }
paul718e3742002-12-13 20:15:29 +0000758 break;
759 case LSA_LINK_TYPE_TRANSIT:
paul0c0f9cd2003-06-06 23:27:04 +0000760 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000761 zlog_debug ("Looking up Network LSA, ID: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000762 inet_ntoa (l->link_id));
paul718e3742002-12-13 20:15:29 +0000763 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_NETWORK_LSA,
paul0c0f9cd2003-06-06 23:27:04 +0000764 l->link_id);
paul718e3742002-12-13 20:15:29 +0000765 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000766 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000767 zlog_debug ("found the LSA");
paul718e3742002-12-13 20:15:29 +0000768 break;
769 default:
paul0c0f9cd2003-06-06 23:27:04 +0000770 zlog_warn ("Invalid LSA link type %d", type);
paul718e3742002-12-13 20:15:29 +0000771 continue;
772 }
773 }
774 else
775 {
776 /* In case of V is Network-LSA. */
paul0c0f9cd2003-06-06 23:27:04 +0000777 r = (struct in_addr *) p;
paul718e3742002-12-13 20:15:29 +0000778 p += sizeof (struct in_addr);
779
780 /* Lookup the vertex W's LSA. */
781 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_ROUTER_LSA, *r);
782 }
783
784 /* (b cont.) If the LSA does not exist, or its LS age is equal
785 to MaxAge, or it does not have a link back to vertex V,
786 examine the next link in V's LSA.[23] */
787 if (w_lsa == NULL)
788 continue;
789
790 if (IS_LSA_MAXAGE (w_lsa))
791 continue;
792
pauld355bfa2004-04-08 07:43:45 +0000793 if ( (link = ospf_lsa_has_link (w_lsa->data, v->lsa)) < 0 )
paul718e3742002-12-13 20:15:29 +0000794 {
paul0c0f9cd2003-06-06 23:27:04 +0000795 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000796 zlog_debug ("The LSA doesn't have a link back");
paul718e3742002-12-13 20:15:29 +0000797 continue;
798 }
799
800 /* (c) If vertex W is already on the shortest-path tree, examine
801 the next link in the LSA. */
802 if (ospf_spf_has_vertex (rv, nv, w_lsa->data))
803 {
paul0c0f9cd2003-06-06 23:27:04 +0000804 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000805 zlog_debug ("The LSA is already in SPF");
paul718e3742002-12-13 20:15:29 +0000806 continue;
807 }
808
809 /* (d) Calculate the link state cost D of the resulting path
810 from the root to vertex W. D is equal to the sum of the link
811 state cost of the (already calculated) shortest path to
812 vertex V and the advertised cost of the link between vertices
813 V and W. If D is: */
814
815 /* prepare vertex W. */
816 w = ospf_vertex_new (w_lsa);
817
pauld355bfa2004-04-08 07:43:45 +0000818 /* Save W's back link index number, for use by virtual links */
819 w->backlink = link;
820
paul718e3742002-12-13 20:15:29 +0000821 /* calculate link cost D. */
822 if (v->lsa->type == OSPF_ROUTER_LSA)
gdt630e4802004-08-31 17:28:41 +0000823 w->distance = v->distance + ntohs (l->m[0].metric);
824 else /* v is not a Router-LSA */
825 w->distance = v->distance;
paul718e3742002-12-13 20:15:29 +0000826
827 /* Is there already vertex W in candidate list? */
828 node = ospf_vertex_lookup (candidate, w->id, w->type);
829 if (node == NULL)
830 {
gdt630e4802004-08-31 17:28:41 +0000831 /* W is a new candidate. Calculate nexthop to W and add W
832 * to the candidate list.
833 */
paul718e3742002-12-13 20:15:29 +0000834 ospf_nexthop_calculation (area, v, w);
835
836 ospf_install_candidate (candidate, w);
837 }
838 else
839 {
gdt630e4802004-08-31 17:28:41 +0000840 /* W is already on the candidate list; call it cw.
841 * Compare the previously calculated cost (cw->distance)
842 * with the cost we just determined (w->distance) to see
843 * if we've found a shorter path.
844 */
paul718e3742002-12-13 20:15:29 +0000845 cw = (struct vertex *) getdata (node);
846
gdt630e4802004-08-31 17:28:41 +0000847 /* If the previous cost was lower, we didn't find a
848 * shorter path, so we're done with w.
849 */
paul718e3742002-12-13 20:15:29 +0000850 if (cw->distance < w->distance)
851 {
852 ospf_vertex_free (w);
853 continue;
854 }
paul718e3742002-12-13 20:15:29 +0000855 else if (cw->distance == w->distance)
856 {
gdt630e4802004-08-31 17:28:41 +0000857 /* Found an equal-cost path to W. Calculate nexthop to W. */
paul718e3742002-12-13 20:15:29 +0000858 ospf_nexthop_calculation (area, v, w);
859 ospf_nexthop_merge (cw->nexthop, w->nexthop);
860 list_delete_all_node (w->nexthop);
861 ospf_vertex_free (w);
862 }
paul718e3742002-12-13 20:15:29 +0000863 else
864 {
gdt630e4802004-08-31 17:28:41 +0000865 /* Found a lower-cost path to W. Calculate nexthop to W. */
paul718e3742002-12-13 20:15:29 +0000866 ospf_nexthop_calculation (area, v, w);
867
868 /* Remove old vertex from candidate list. */
869 ospf_vertex_free (cw);
870 listnode_delete (candidate, cw);
871
gdt630e4802004-08-31 17:28:41 +0000872 /* Install new W to candidate list. */
paul718e3742002-12-13 20:15:29 +0000873 ospf_install_candidate (candidate, w);
874 }
gdt630e4802004-08-31 17:28:41 +0000875 } /* end W is already on the candidate list */
876 } /* end loop over the links in V's LSA */
paul718e3742002-12-13 20:15:29 +0000877}
878
879/* Add vertex V to SPF tree. */
880void
881ospf_spf_register (struct vertex *v, struct route_table *rv,
paul0c0f9cd2003-06-06 23:27:04 +0000882 struct route_table *nv)
paul718e3742002-12-13 20:15:29 +0000883{
884 struct prefix p;
885 struct route_node *rn;
886
gdt630e4802004-08-31 17:28:41 +0000887 ospf_vertex_dump("ospf_spf_register(): adding to SPF tree:", v, 1, 1);
888
paul718e3742002-12-13 20:15:29 +0000889 p.family = AF_INET;
890 p.prefixlen = IPV4_MAX_BITLEN;
891 p.u.prefix4 = v->id;
892
893 if (v->type == OSPF_VERTEX_ROUTER)
894 rn = route_node_get (rv, &p);
895 else
896 rn = route_node_get (nv, &p);
897
898 rn->info = v;
899}
900
901void
902ospf_spf_route_free (struct route_table *table)
903{
904 struct route_node *rn;
905 struct vertex *v;
906
907 for (rn = route_top (table); rn; rn = route_next (rn))
908 {
909 if ((v = rn->info))
paul0c0f9cd2003-06-06 23:27:04 +0000910 {
911 ospf_vertex_free (v);
912 rn->info = NULL;
913 }
paul718e3742002-12-13 20:15:29 +0000914
915 route_unlock_node (rn);
916 }
917
918 route_table_finish (table);
919}
920
921void
922ospf_spf_dump (struct vertex *v, int i)
923{
hasso52dc7ee2004-09-23 19:18:23 +0000924 struct listnode *cnode;
925 struct listnode *nnode;
paul718e3742002-12-13 20:15:29 +0000926 struct vertex_nexthop *nexthop;
927
928 if (v->type == OSPF_VERTEX_ROUTER)
929 {
930 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000931 zlog_debug ("SPF Result: %d [R] %s", i, inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000932 }
933 else
934 {
935 struct network_lsa *lsa = (struct network_lsa *) v->lsa;
936 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000937 zlog_debug ("SPF Result: %d [N] %s/%d", i, inet_ntoa (v->lsa->id),
paul0c0f9cd2003-06-06 23:27:04 +0000938 ip_masklen (lsa->mask));
gdt630e4802004-08-31 17:28:41 +0000939 }
paul718e3742002-12-13 20:15:29 +0000940
gdt630e4802004-08-31 17:28:41 +0000941 for (nnode = listhead (v->nexthop); nnode; nextnode (nnode))
942 {
943 nexthop = getdata (nnode);
944 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000945 zlog_debug (" nexthop %s", inet_ntoa (nexthop->router));
paul718e3742002-12-13 20:15:29 +0000946 }
947
948 i++;
949
950 for (cnode = listhead (v->child); cnode; nextnode (cnode))
951 {
952 v = getdata (cnode);
953 ospf_spf_dump (v, i);
954 }
955}
956
957/* Second stage of SPF calculation. */
958void
paul0c0f9cd2003-06-06 23:27:04 +0000959ospf_spf_process_stubs (struct ospf_area *area, struct vertex *v,
paul718e3742002-12-13 20:15:29 +0000960 struct route_table *rt)
961{
hasso52dc7ee2004-09-23 19:18:23 +0000962 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000963 struct vertex *child;
964
965 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000966 zlog_debug ("ospf_process_stub():processing stubs for area %s",
paul0c0f9cd2003-06-06 23:27:04 +0000967 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +0000968 if (v->type == OSPF_VERTEX_ROUTER)
969 {
970 u_char *p;
971 u_char *lim;
972 struct router_lsa_link *l;
973 struct router_lsa *rlsa;
974
paul0c0f9cd2003-06-06 23:27:04 +0000975 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000976 zlog_debug ("ospf_process_stubs():processing router LSA, id: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000977 inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000978 rlsa = (struct router_lsa *) v->lsa;
979
980
paul0c0f9cd2003-06-06 23:27:04 +0000981 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000982 zlog_debug ("ospf_process_stubs(): we have %d links to process",
paul0c0f9cd2003-06-06 23:27:04 +0000983 ntohs (rlsa->links));
gdt630e4802004-08-31 17:28:41 +0000984 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +0000985 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
986
987 while (p < lim)
988 {
989 l = (struct router_lsa_link *) p;
990
991 p += (ROUTER_LSA_MIN_SIZE +
992 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
993
994 if (l->m[0].type == LSA_LINK_TYPE_STUB)
995 ospf_intra_add_stub (rt, l, v, area);
996 }
997 }
998
gdt630e4802004-08-31 17:28:41 +0000999 ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1, 1);
paul718e3742002-12-13 20:15:29 +00001000
1001 for (cnode = listhead (v->child); cnode; nextnode (cnode))
1002 {
1003 child = getdata (cnode);
1004
1005 if (CHECK_FLAG (child->flags, OSPF_VERTEX_PROCESSED))
paul0c0f9cd2003-06-06 23:27:04 +00001006 continue;
paul718e3742002-12-13 20:15:29 +00001007
1008 ospf_spf_process_stubs (area, child, rt);
1009
1010 SET_FLAG (child->flags, OSPF_VERTEX_PROCESSED);
1011 }
1012}
1013
1014void
1015ospf_rtrs_free (struct route_table *rtrs)
1016{
1017 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001018 struct list *or_list;
1019 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001020
1021 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001022 zlog_debug ("Route: Router Routing Table free");
paul718e3742002-12-13 20:15:29 +00001023
1024 for (rn = route_top (rtrs); rn; rn = route_next (rn))
1025 if ((or_list = rn->info) != NULL)
1026 {
paul0c0f9cd2003-06-06 23:27:04 +00001027 for (node = listhead (or_list); node; nextnode (node))
1028 ospf_route_free (node->data);
paul718e3742002-12-13 20:15:29 +00001029
paul0c0f9cd2003-06-06 23:27:04 +00001030 list_delete (or_list);
paul718e3742002-12-13 20:15:29 +00001031
paul0c0f9cd2003-06-06 23:27:04 +00001032 /* Unlock the node. */
1033 rn->info = NULL;
1034 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001035 }
1036 route_table_finish (rtrs);
1037}
1038
1039void
1040ospf_rtrs_print (struct route_table *rtrs)
1041{
1042 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001043 struct list *or_list;
1044 struct listnode *ln;
1045 struct listnode *pnode;
paul718e3742002-12-13 20:15:29 +00001046 struct ospf_route *or;
1047 struct ospf_path *path;
1048 char buf1[BUFSIZ];
1049 char buf2[BUFSIZ];
1050
1051 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001052 zlog_debug ("ospf_rtrs_print() start");
paul718e3742002-12-13 20:15:29 +00001053
1054 for (rn = route_top (rtrs); rn; rn = route_next (rn))
1055 if ((or_list = rn->info) != NULL)
1056 for (ln = listhead (or_list); ln; nextnode (ln))
1057 {
1058 or = getdata (ln);
1059
1060 switch (or->path_type)
1061 {
1062 case OSPF_PATH_INTRA_AREA:
paul0c0f9cd2003-06-06 23:27:04 +00001063 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001064 zlog_debug ("%s [%d] area: %s",
paul0c0f9cd2003-06-06 23:27:04 +00001065 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1066 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1067 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +00001068 break;
1069 case OSPF_PATH_INTER_AREA:
paul0c0f9cd2003-06-06 23:27:04 +00001070 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001071 zlog_debug ("%s IA [%d] area: %s",
paul0c0f9cd2003-06-06 23:27:04 +00001072 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1073 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1074 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +00001075 break;
1076 default:
1077 break;
1078 }
1079
paul96735ee2003-08-10 02:51:22 +00001080 for (pnode = listhead (or->paths); pnode; nextnode (pnode))
paul718e3742002-12-13 20:15:29 +00001081 {
1082 path = getdata (pnode);
1083 if (path->nexthop.s_addr == 0)
paul0c0f9cd2003-06-06 23:27:04 +00001084 {
1085 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001086 zlog_debug (" directly attached to %s\r\n",
paul0c0f9cd2003-06-06 23:27:04 +00001087 IF_NAME (path->oi));
1088 }
1089 else
1090 {
1091 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001092 zlog_debug (" via %s, %s\r\n",
paul0c0f9cd2003-06-06 23:27:04 +00001093 inet_ntoa (path->nexthop), IF_NAME (path->oi));
1094 }
paul718e3742002-12-13 20:15:29 +00001095 }
1096 }
1097
ajs2a42e282004-12-08 18:43:03 +00001098 zlog_debug ("ospf_rtrs_print() end");
paul718e3742002-12-13 20:15:29 +00001099}
1100
1101/* Calculating the shortest-path tree for an area. */
1102void
paul0c0f9cd2003-06-06 23:27:04 +00001103ospf_spf_calculate (struct ospf_area *area, struct route_table *new_table,
paul718e3742002-12-13 20:15:29 +00001104 struct route_table *new_rtrs)
1105{
hasso52dc7ee2004-09-23 19:18:23 +00001106 struct list *candidate;
1107 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001108 struct vertex *v;
1109 struct route_table *rv;
1110 struct route_table *nv;
1111
1112 if (IS_DEBUG_OSPF_EVENT)
1113 {
ajs2a42e282004-12-08 18:43:03 +00001114 zlog_debug ("ospf_spf_calculate: Start");
1115 zlog_debug ("ospf_spf_calculate: running Dijkstra for area %s",
paul0c0f9cd2003-06-06 23:27:04 +00001116 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001117 }
1118
1119 /* Check router-lsa-self. If self-router-lsa is not yet allocated,
1120 return this area's calculation. */
paul0c0f9cd2003-06-06 23:27:04 +00001121 if (!area->router_lsa_self)
paul718e3742002-12-13 20:15:29 +00001122 {
1123 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001124 zlog_debug ("ospf_spf_calculate: "
paul0c0f9cd2003-06-06 23:27:04 +00001125 "Skip area %s's calculation due to empty router_lsa_self",
1126 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001127 return;
1128 }
1129
1130 /* RFC2328 16.1. (1). */
paul0c0f9cd2003-06-06 23:27:04 +00001131 /* Initialize the algorithm's data structures. */
paul718e3742002-12-13 20:15:29 +00001132 rv = route_table_init ();
1133 nv = route_table_init ();
1134
paul0c0f9cd2003-06-06 23:27:04 +00001135 /* Clear the list of candidate vertices. */
paul718e3742002-12-13 20:15:29 +00001136 candidate = list_new ();
1137
1138 /* Initialize the shortest-path tree to only the root (which is the
1139 router doing the calculation). */
1140 ospf_spf_init (area);
1141 v = area->spf;
1142 ospf_spf_register (v, rv, nv);
1143
1144 /* Set Area A's TransitCapability to FALSE. */
1145 area->transit = OSPF_TRANSIT_FALSE;
1146 area->shortcut_capability = 1;
1147
1148 for (;;)
1149 {
1150 /* RFC2328 16.1. (2). */
1151 ospf_spf_next (v, area, candidate, rv, nv);
1152
1153 /* RFC2328 16.1. (3). */
1154 /* If at this step the candidate list is empty, the shortest-
1155 path tree (of transit vertices) has been completely built and
1156 this stage of the procedure terminates. */
1157 if (listcount (candidate) == 0)
1158 break;
1159
1160 /* Otherwise, choose the vertex belonging to the candidate list
1161 that is closest to the root, and add it to the shortest-path
1162 tree (removing it from the candidate list in the
paul0c0f9cd2003-06-06 23:27:04 +00001163 process). */
paul718e3742002-12-13 20:15:29 +00001164 node = listhead (candidate);
1165 v = getdata (node);
1166 ospf_vertex_add_parent (v);
1167
gdt630e4802004-08-31 17:28:41 +00001168 /* Remove from the candidate list. */
paul718e3742002-12-13 20:15:29 +00001169 listnode_delete (candidate, v);
1170
1171 /* Add to SPF tree. */
1172 ospf_spf_register (v, rv, nv);
1173
1174 /* Note that when there is a choice of vertices closest to the
1175 root, network vertices must be chosen before router vertices
1176 in order to necessarily find all equal-cost paths. */
1177 /* We don't do this at this moment, we should add the treatment
1178 above codes. -- kunihiro. */
1179
1180 /* RFC2328 16.1. (4). */
1181 if (v->type == OSPF_VERTEX_ROUTER)
1182 ospf_intra_add_router (new_rtrs, v, area);
paul0c0f9cd2003-06-06 23:27:04 +00001183 else
paul718e3742002-12-13 20:15:29 +00001184 ospf_intra_add_transit (new_table, v, area);
1185
1186 /* RFC2328 16.1. (5). */
1187 /* Iterate the algorithm by returning to Step 2. */
gdt630e4802004-08-31 17:28:41 +00001188
1189 } /* end loop until no more candidate vertices */
paul718e3742002-12-13 20:15:29 +00001190
1191 if (IS_DEBUG_OSPF_EVENT)
1192 {
1193 ospf_spf_dump (area->spf, 0);
1194 ospf_route_table_dump (new_table);
1195 }
1196
1197 /* Second stage of SPF calculation procedure's */
1198 ospf_spf_process_stubs (area, area->spf, new_table);
1199
1200 /* Free all vertices which allocated for SPF calculation */
1201 ospf_spf_route_free (rv);
1202 ospf_spf_route_free (nv);
1203
1204 /* Free candidate list */
1205 list_free (candidate);
1206
1207 /* Increment SPF Calculation Counter. */
1208 area->spf_calculation++;
1209
paul68980082003-03-25 05:07:42 +00001210 area->ospf->ts_spf = time (NULL);
paul718e3742002-12-13 20:15:29 +00001211
1212 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001213 zlog_debug ("ospf_spf_calculate: Stop");
paul718e3742002-12-13 20:15:29 +00001214}
1215
1216/* Timer for SPF calculation. */
1217int
paul68980082003-03-25 05:07:42 +00001218ospf_spf_calculate_timer (struct thread *thread)
paul718e3742002-12-13 20:15:29 +00001219{
paul68980082003-03-25 05:07:42 +00001220 struct ospf *ospf = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +00001221 struct route_table *new_table, *new_rtrs;
hasso52dc7ee2004-09-23 19:18:23 +00001222 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001223
1224 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001225 zlog_debug ("SPF: Timer (SPF calculation expire)");
paul0c0f9cd2003-06-06 23:27:04 +00001226
paul718e3742002-12-13 20:15:29 +00001227 ospf->t_spf_calc = NULL;
1228
1229 /* Allocate new table tree. */
1230 new_table = route_table_init ();
paul0c0f9cd2003-06-06 23:27:04 +00001231 new_rtrs = route_table_init ();
paul718e3742002-12-13 20:15:29 +00001232
paul68980082003-03-25 05:07:42 +00001233 ospf_vl_unapprove (ospf);
paul718e3742002-12-13 20:15:29 +00001234
1235 /* Calculate SPF for each area. */
1236 for (node = listhead (ospf->areas); node; node = nextnode (node))
1237 ospf_spf_calculate (node->data, new_table, new_rtrs);
1238
paul68980082003-03-25 05:07:42 +00001239 ospf_vl_shut_unapproved (ospf);
paul718e3742002-12-13 20:15:29 +00001240
paul68980082003-03-25 05:07:42 +00001241 ospf_ia_routing (ospf, new_table, new_rtrs);
paul718e3742002-12-13 20:15:29 +00001242
1243 ospf_prune_unreachable_networks (new_table);
1244 ospf_prune_unreachable_routers (new_rtrs);
1245
1246 /* AS-external-LSA calculation should not be performed here. */
1247
1248 /* If new Router Route is installed,
1249 then schedule re-calculate External routes. */
1250 if (1)
paul68980082003-03-25 05:07:42 +00001251 ospf_ase_calculate_schedule (ospf);
paul718e3742002-12-13 20:15:29 +00001252
paul68980082003-03-25 05:07:42 +00001253 ospf_ase_calculate_timer_add (ospf);
paul718e3742002-12-13 20:15:29 +00001254
1255 /* Update routing table. */
paul68980082003-03-25 05:07:42 +00001256 ospf_route_install (ospf, new_table);
paul718e3742002-12-13 20:15:29 +00001257
1258 /* Update ABR/ASBR routing table */
paul68980082003-03-25 05:07:42 +00001259 if (ospf->old_rtrs)
paul718e3742002-12-13 20:15:29 +00001260 {
1261 /* old_rtrs's node holds linked list of ospf_route. --kunihiro. */
paul68980082003-03-25 05:07:42 +00001262 /* ospf_route_delete (ospf->old_rtrs); */
1263 ospf_rtrs_free (ospf->old_rtrs);
paul718e3742002-12-13 20:15:29 +00001264 }
1265
paul68980082003-03-25 05:07:42 +00001266 ospf->old_rtrs = ospf->new_rtrs;
1267 ospf->new_rtrs = new_rtrs;
paul718e3742002-12-13 20:15:29 +00001268
paul0c0f9cd2003-06-06 23:27:04 +00001269 if (IS_OSPF_ABR (ospf))
paul68980082003-03-25 05:07:42 +00001270 ospf_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001271
1272 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001273 zlog_debug ("SPF: calculation complete");
paul718e3742002-12-13 20:15:29 +00001274
1275 return 0;
1276}
1277
1278/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
1279 set timer for SPF calc. */
1280void
paul68980082003-03-25 05:07:42 +00001281ospf_spf_calculate_schedule (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00001282{
1283 time_t ht, delay;
1284
1285 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001286 zlog_debug ("SPF: calculation timer scheduled");
paul718e3742002-12-13 20:15:29 +00001287
1288 /* OSPF instance does not exist. */
paul68980082003-03-25 05:07:42 +00001289 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001290 return;
1291
1292 /* SPF calculation timer is already scheduled. */
paul68980082003-03-25 05:07:42 +00001293 if (ospf->t_spf_calc)
paul718e3742002-12-13 20:15:29 +00001294 {
1295 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001296 zlog_debug ("SPF: calculation timer is already scheduled: %p",
paul0c0f9cd2003-06-06 23:27:04 +00001297 ospf->t_spf_calc);
paul718e3742002-12-13 20:15:29 +00001298 return;
1299 }
1300
paul68980082003-03-25 05:07:42 +00001301 ht = time (NULL) - ospf->ts_spf;
paul718e3742002-12-13 20:15:29 +00001302
1303 /* Get SPF calculation delay time. */
paul68980082003-03-25 05:07:42 +00001304 if (ht < ospf->spf_holdtime)
paul718e3742002-12-13 20:15:29 +00001305 {
paul68980082003-03-25 05:07:42 +00001306 if (ospf->spf_holdtime - ht < ospf->spf_delay)
paul0c0f9cd2003-06-06 23:27:04 +00001307 delay = ospf->spf_delay;
paul718e3742002-12-13 20:15:29 +00001308 else
paul0c0f9cd2003-06-06 23:27:04 +00001309 delay = ospf->spf_holdtime - ht;
paul718e3742002-12-13 20:15:29 +00001310 }
1311 else
paul68980082003-03-25 05:07:42 +00001312 delay = ospf->spf_delay;
paul718e3742002-12-13 20:15:29 +00001313
1314 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001315 zlog_debug ("SPF: calculation timer delay = %ld", (long)delay);
paul68980082003-03-25 05:07:42 +00001316 ospf->t_spf_calc =
1317 thread_add_timer (master, ospf_spf_calculate_timer, ospf, delay);
paul718e3742002-12-13 20:15:29 +00001318}