blob: 1aba5d979d358be62e0a4e69bef7166dd5fbe4cd [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* OSPF SPF calculation.
2 Copyright (C) 1999, 2000 Kunihiro Ishiguro, Toshiaki Takada
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22
23#include "thread.h"
24#include "memory.h"
25#include "hash.h"
26#include "linklist.h"
27#include "prefix.h"
28#include "if.h"
29#include "table.h"
30#include "log.h"
31#include "sockunion.h" /* for inet_ntop () */
hasso462f20d2005-02-23 11:29:02 +000032#include "pqueue.h"
paul718e3742002-12-13 20:15:29 +000033
34#include "ospfd/ospfd.h"
35#include "ospfd/ospf_interface.h"
36#include "ospfd/ospf_ism.h"
37#include "ospfd/ospf_asbr.h"
38#include "ospfd/ospf_lsa.h"
39#include "ospfd/ospf_lsdb.h"
40#include "ospfd/ospf_neighbor.h"
41#include "ospfd/ospf_nsm.h"
42#include "ospfd/ospf_spf.h"
43#include "ospfd/ospf_route.h"
44#include "ospfd/ospf_ia.h"
45#include "ospfd/ospf_ase.h"
46#include "ospfd/ospf_abr.h"
47#include "ospfd/ospf_dump.h"
48
hasso462f20d2005-02-23 11:29:02 +000049/* Heap related functions, for the managment of the candidates, to
50 * be used with pqueue. */
51static int
52cmp (void * node1 , void * node2)
53{
54 struct vertex * v1 = (struct vertex *) node1;
55 struct vertex * v2 = (struct vertex *) node2;
56 if (v1 != NULL && v2 != NULL )
57 return (v1->distance - v2->distance);
58 else
59 return 0;
60}
61
62static void
63update_stat (void * node , int position)
64{
65 struct vertex * v = (struct vertex *) node;
66 /* Set the status of the vertex, when its position changes. */
67 *(v->stat) = position;
68}
69/* End of the heap related functions. */
70
paul4dadc292005-05-06 21:37:42 +000071static struct vertex_nexthop *
paul718e3742002-12-13 20:15:29 +000072vertex_nexthop_new (struct vertex *parent)
73{
74 struct vertex_nexthop *new;
75
76 new = XCALLOC (MTYPE_OSPF_NEXTHOP, sizeof (struct vertex_nexthop));
77 new->parent = parent;
78
79 return new;
80}
81
paul4dadc292005-05-06 21:37:42 +000082static void
paul718e3742002-12-13 20:15:29 +000083vertex_nexthop_free (struct vertex_nexthop *nh)
84{
85 XFREE (MTYPE_OSPF_NEXTHOP, nh);
86}
87
paul4dadc292005-05-06 21:37:42 +000088static struct vertex_nexthop *
paul718e3742002-12-13 20:15:29 +000089vertex_nexthop_dup (struct vertex_nexthop *nh)
90{
91 struct vertex_nexthop *new;
92
93 new = vertex_nexthop_new (nh->parent);
94
95 new->oi = nh->oi;
96 new->router = nh->router;
97
98 return new;
99}
paul718e3742002-12-13 20:15:29 +0000100
paul0c0f9cd2003-06-06 23:27:04 +0000101
paul4dadc292005-05-06 21:37:42 +0000102static struct vertex *
paul718e3742002-12-13 20:15:29 +0000103ospf_vertex_new (struct ospf_lsa *lsa)
104{
105 struct vertex *new;
106
107 new = XMALLOC (MTYPE_OSPF_VERTEX, sizeof (struct vertex));
108 memset (new, 0, sizeof (struct vertex));
109
110 new->flags = 0;
hasso462f20d2005-02-23 11:29:02 +0000111 new->stat = &(lsa->stat);
paul718e3742002-12-13 20:15:29 +0000112 new->type = lsa->data->type;
113 new->id = lsa->data->id;
114 new->lsa = lsa->data;
115 new->distance = 0;
116 new->child = list_new ();
117 new->nexthop = list_new ();
pauld355bfa2004-04-08 07:43:45 +0000118 new->backlink = -1;
paul718e3742002-12-13 20:15:29 +0000119
120 return new;
121}
122
paul4dadc292005-05-06 21:37:42 +0000123static void
paul718e3742002-12-13 20:15:29 +0000124ospf_vertex_free (struct vertex *v)
125{
paul1eb8ef22005-04-07 07:30:20 +0000126 struct listnode *node, *nnode;
127 struct vertex_nexthop *nh;
paul718e3742002-12-13 20:15:29 +0000128
129 list_delete (v->child);
paul7461d452005-06-13 13:57:16 +0000130 v->child = NULL;
131
paul718e3742002-12-13 20:15:29 +0000132 if (listcount (v->nexthop) > 0)
paul1eb8ef22005-04-07 07:30:20 +0000133 for (ALL_LIST_ELEMENTS (v->nexthop, node, nnode, nh))
134 vertex_nexthop_free (nh);
paul718e3742002-12-13 20:15:29 +0000135
136 list_delete (v->nexthop);
paul7461d452005-06-13 13:57:16 +0000137 v->nexthop = NULL;
138
paul718e3742002-12-13 20:15:29 +0000139 XFREE (MTYPE_OSPF_VERTEX, v);
140}
141
paul4dadc292005-05-06 21:37:42 +0000142static void
hassoeb1ce602004-10-08 08:17:22 +0000143ospf_vertex_dump(const char *msg, struct vertex *v,
gdt630e4802004-08-31 17:28:41 +0000144 int print_nexthops, int print_children)
145{
146 if ( ! IS_DEBUG_OSPF_EVENT)
147 return;
148
ajs2a42e282004-12-08 18:43:03 +0000149 zlog_debug("%s %s vertex %s distance %u backlink %d flags %u",
gdt630e4802004-08-31 17:28:41 +0000150 msg,
151 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
152 inet_ntoa(v->lsa->id),
153 v->distance,
154 v->backlink,
155 (unsigned int)v->flags);
156
157 if (print_nexthops)
158 {
paul1eb8ef22005-04-07 07:30:20 +0000159 struct listnode *node;
160 struct vertex_nexthop *nexthop;
161
162 for (ALL_LIST_ELEMENTS_RO (v->nexthop, node, nexthop))
gdt630e4802004-08-31 17:28:41 +0000163 {
164 char buf1[BUFSIZ];
165 char buf2[BUFSIZ];
gdt630e4802004-08-31 17:28:41 +0000166
gdt630e4802004-08-31 17:28:41 +0000167 if (nexthop)
168 {
ajs2a42e282004-12-08 18:43:03 +0000169 zlog_debug (" nexthop %s interface %s parent %s",
gdt630e4802004-08-31 17:28:41 +0000170 inet_ntop(AF_INET, &nexthop->router, buf1, BUFSIZ),
171 nexthop->oi ? IF_NAME(nexthop->oi) : "NULL",
172 nexthop->parent ? inet_ntop(AF_INET,
173 &nexthop->parent->id,
174 buf2, BUFSIZ)
175 : "NULL");
176 }
177 }
178 }
179
180 if (print_children)
181 {
hasso52dc7ee2004-09-23 19:18:23 +0000182 struct listnode *cnode;
paul1eb8ef22005-04-07 07:30:20 +0000183 struct vertex *cv;
184
185 for (ALL_LIST_ELEMENTS_RO (v->child, cnode, cv))
186 ospf_vertex_dump(" child:", cv, 0, 0);
gdt630e4802004-08-31 17:28:41 +0000187 }
188}
189
190
191/* Add a vertex to the list of children in each of its parents. */
paul4dadc292005-05-06 21:37:42 +0000192static void
paul718e3742002-12-13 20:15:29 +0000193ospf_vertex_add_parent (struct vertex *v)
194{
195 struct vertex_nexthop *nh;
hasso52dc7ee2004-09-23 19:18:23 +0000196 struct listnode *node;
paul7461d452005-06-13 13:57:16 +0000197
198 assert (v->nexthop && v->child);
199
paul1eb8ef22005-04-07 07:30:20 +0000200 for (ALL_LIST_ELEMENTS_RO (v->nexthop, node, nh))
paul718e3742002-12-13 20:15:29 +0000201 {
paul7461d452005-06-13 13:57:16 +0000202 assert (nh->parent && nh->parent->child);
203
paul718e3742002-12-13 20:15:29 +0000204 /* No need to add two links from the same parent. */
205 if (listnode_lookup (nh->parent->child, v) == NULL)
paul0c0f9cd2003-06-06 23:27:04 +0000206 listnode_add (nh->parent->child, v);
paul718e3742002-12-13 20:15:29 +0000207 }
208}
209
paul4dadc292005-05-06 21:37:42 +0000210static void
paul718e3742002-12-13 20:15:29 +0000211ospf_spf_init (struct ospf_area *area)
212{
213 struct vertex *v;
214
215 /* Create root node. */
216 v = ospf_vertex_new (area->router_lsa_self);
217
218 area->spf = v;
219
220 /* Reset ABR and ASBR router counts. */
221 area->abr_count = 0;
222 area->asbr_count = 0;
223}
224
pauld355bfa2004-04-08 07:43:45 +0000225/* return index of link back to V from W, or -1 if no link found */
paul4dadc292005-05-06 21:37:42 +0000226static int
paul718e3742002-12-13 20:15:29 +0000227ospf_lsa_has_link (struct lsa_header *w, struct lsa_header *v)
228{
hassoeb1ce602004-10-08 08:17:22 +0000229 unsigned int i, length;
paul718e3742002-12-13 20:15:29 +0000230 struct router_lsa *rl;
231 struct network_lsa *nl;
232
233 /* In case of W is Network LSA. */
234 if (w->type == OSPF_NETWORK_LSA)
235 {
236 if (v->type == OSPF_NETWORK_LSA)
pauld355bfa2004-04-08 07:43:45 +0000237 return -1;
paul718e3742002-12-13 20:15:29 +0000238
239 nl = (struct network_lsa *) w;
240 length = (ntohs (w->length) - OSPF_LSA_HEADER_SIZE - 4) / 4;
paul0c0f9cd2003-06-06 23:27:04 +0000241
paul718e3742002-12-13 20:15:29 +0000242 for (i = 0; i < length; i++)
243 if (IPV4_ADDR_SAME (&nl->routers[i], &v->id))
pauld355bfa2004-04-08 07:43:45 +0000244 return i;
245 return -1;
paul718e3742002-12-13 20:15:29 +0000246 }
247
248 /* In case of W is Router LSA. */
249 if (w->type == OSPF_ROUTER_LSA)
250 {
251 rl = (struct router_lsa *) w;
252
253 length = ntohs (w->length);
254
255 for (i = 0;
paul0c0f9cd2003-06-06 23:27:04 +0000256 i < ntohs (rl->links) && length >= sizeof (struct router_lsa);
257 i++, length -= 12)
paul718e3742002-12-13 20:15:29 +0000258 {
259 switch (rl->link[i].type)
260 {
261 case LSA_LINK_TYPE_POINTOPOINT:
262 case LSA_LINK_TYPE_VIRTUALLINK:
263 /* Router LSA ID. */
264 if (v->type == OSPF_ROUTER_LSA &&
265 IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
266 {
pauld355bfa2004-04-08 07:43:45 +0000267 return i;
paul718e3742002-12-13 20:15:29 +0000268 }
269 break;
270 case LSA_LINK_TYPE_TRANSIT:
271 /* Network LSA ID. */
272 if (v->type == OSPF_NETWORK_LSA &&
273 IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
274 {
pauld355bfa2004-04-08 07:43:45 +0000275 return i;
paul0c0f9cd2003-06-06 23:27:04 +0000276 }
paul718e3742002-12-13 20:15:29 +0000277 break;
278 case LSA_LINK_TYPE_STUB:
279 /* Not take into count? */
280 continue;
281 default:
282 break;
283 }
284 }
285 }
pauld355bfa2004-04-08 07:43:45 +0000286 return -1;
paul718e3742002-12-13 20:15:29 +0000287}
288
289/* Add the nexthop to the list, only if it is unique.
290 * If it's not unique, free the nexthop entry.
291 */
paul4dadc292005-05-06 21:37:42 +0000292static void
hasso52dc7ee2004-09-23 19:18:23 +0000293ospf_nexthop_add_unique (struct vertex_nexthop *new, struct list *nexthop)
paul718e3742002-12-13 20:15:29 +0000294{
295 struct vertex_nexthop *nh;
hasso52dc7ee2004-09-23 19:18:23 +0000296 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000297 int match;
298
299 match = 0;
paul718e3742002-12-13 20:15:29 +0000300
paul1eb8ef22005-04-07 07:30:20 +0000301 for (ALL_LIST_ELEMENTS_RO (nexthop, node, nh))
302 {
paul718e3742002-12-13 20:15:29 +0000303 /* Compare the two entries. */
304 /* XXX
305 * Comparing the parent preserves the shortest path tree
306 * structure even when the nexthops are identical.
307 */
308 if (nh->oi == new->oi &&
paul0c0f9cd2003-06-06 23:27:04 +0000309 IPV4_ADDR_SAME (&nh->router, &new->router) &&
310 nh->parent == new->parent)
311 {
312 match = 1;
313 break;
314 }
paul718e3742002-12-13 20:15:29 +0000315 }
316
317 if (!match)
318 listnode_add (nexthop, new);
319 else
320 vertex_nexthop_free (new);
321}
322
323/* Merge entries in list b into list a. */
paul4dadc292005-05-06 21:37:42 +0000324static void
hasso52dc7ee2004-09-23 19:18:23 +0000325ospf_nexthop_merge (struct list *a, struct list *b)
paul718e3742002-12-13 20:15:29 +0000326{
paul1eb8ef22005-04-07 07:30:20 +0000327 struct listnode *node, *nnode;
328 struct vertex_nexthop *nh;
paul718e3742002-12-13 20:15:29 +0000329
paul1eb8ef22005-04-07 07:30:20 +0000330 for (ALL_LIST_ELEMENTS (b, node, nnode, nh))
331 ospf_nexthop_add_unique (nh, a);
paul718e3742002-12-13 20:15:29 +0000332}
333
334#define ROUTER_LSA_MIN_SIZE 12
335#define ROUTER_LSA_TOS_SIZE 4
336
gdt630e4802004-08-31 17:28:41 +0000337/* Find the next link after prev_link from v to w. If prev_link is
338 * NULL, return the first link from v to w. Ignore stub and virtual links;
339 * these link types will never be returned.
340 */
paul4dadc292005-05-06 21:37:42 +0000341static struct router_lsa_link *
paul718e3742002-12-13 20:15:29 +0000342ospf_get_next_link (struct vertex *v, struct vertex *w,
paul0c0f9cd2003-06-06 23:27:04 +0000343 struct router_lsa_link *prev_link)
paul718e3742002-12-13 20:15:29 +0000344{
345 u_char *p;
346 u_char *lim;
347 struct router_lsa_link *l;
348
349 if (prev_link == NULL)
gdt630e4802004-08-31 17:28:41 +0000350 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +0000351 else
352 {
paul0c0f9cd2003-06-06 23:27:04 +0000353 p = (u_char *) prev_link;
paul718e3742002-12-13 20:15:29 +0000354 p += (ROUTER_LSA_MIN_SIZE +
355 (prev_link->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
356 }
paul0c0f9cd2003-06-06 23:27:04 +0000357
paul718e3742002-12-13 20:15:29 +0000358 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
359
360 while (p < lim)
361 {
362 l = (struct router_lsa_link *) p;
363
paul0c0f9cd2003-06-06 23:27:04 +0000364 p += (ROUTER_LSA_MIN_SIZE + (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
paul718e3742002-12-13 20:15:29 +0000365
366 if (l->m[0].type == LSA_LINK_TYPE_STUB)
367 continue;
368
369 /* Defer NH calculation via VLs until summaries from
370 transit areas area confidered */
371
372 if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK)
paul0c0f9cd2003-06-06 23:27:04 +0000373 continue;
paul718e3742002-12-13 20:15:29 +0000374
375 if (IPV4_ADDR_SAME (&l->link_id, &w->id))
paul0c0f9cd2003-06-06 23:27:04 +0000376 return l;
paul718e3742002-12-13 20:15:29 +0000377 }
378
379 return NULL;
380}
381
paul75ee0b82004-08-05 09:10:31 +0000382/*
383 * Consider supplied next-hop for inclusion to the supplied list of
384 * equal-cost next-hops, adjust list as neccessary.
385 *
386 * (Discussed on GNU Zebra list 27 May 2003, [zebra 19184])
387 *
388 * Note that below is a bit of a hack, and limits ECMP to paths that go to
389 * same nexthop. Where as paths via inequal output_cost interfaces could
390 * still quite easily be ECMP due to remote cost differences.
391 *
392 * TODO: It really should be done by way of recording currently valid
393 * backlinks and determining the appropriate nexthops from the list of
394 * backlinks, or even simpler, just flushing nexthop list if we find a lower
395 * cost path to a candidate vertex in SPF, maybe.
paulbf9392c2003-06-06 23:23:36 +0000396 */
paul4dadc292005-05-06 21:37:42 +0000397static void
paul0c0f9cd2003-06-06 23:27:04 +0000398ospf_spf_consider_nexthop (struct list *nexthops,
399 struct vertex_nexthop *newhop)
paulbf9392c2003-06-06 23:23:36 +0000400{
paulbf9392c2003-06-06 23:23:36 +0000401 struct vertex_nexthop *hop;
paul75ee0b82004-08-05 09:10:31 +0000402 struct listnode *ln, *nn;
paul0c0f9cd2003-06-06 23:27:04 +0000403
paul75ee0b82004-08-05 09:10:31 +0000404 /* nexthop list should contain only the set of nexthops that have the lowest
405 * equal cost
406 */
407 if (nexthops->head != NULL)
408 {
paul1eb8ef22005-04-07 07:30:20 +0000409 hop = listgetdata (nexthops->head);
paul75ee0b82004-08-05 09:10:31 +0000410
411 /* weed out hops with higher cost than the newhop */
412 if (hop->oi->output_cost > newhop->oi->output_cost)
413 {
414 /* delete the existing nexthops */
paul1eb8ef22005-04-07 07:30:20 +0000415 for (ALL_LIST_ELEMENTS (nexthops, ln, nn, hop))
paul75ee0b82004-08-05 09:10:31 +0000416 {
paul75ee0b82004-08-05 09:10:31 +0000417 listnode_delete (nexthops, hop);
418 vertex_nexthop_free (hop);
419 }
420 }
421 else if (hop->oi->output_cost < newhop->oi->output_cost)
paul0c0f9cd2003-06-06 23:27:04 +0000422 return;
paul75ee0b82004-08-05 09:10:31 +0000423 }
paul0c0f9cd2003-06-06 23:27:04 +0000424
paulbf9392c2003-06-06 23:23:36 +0000425 /* new hop is <= existing hops, add it */
paul0c0f9cd2003-06-06 23:27:04 +0000426 listnode_add (nexthops, newhop);
paulbf9392c2003-06-06 23:23:36 +0000427
428 return;
429}
430
gdt630e4802004-08-31 17:28:41 +0000431/* 16.1.1. Calculate nexthop from root through V (parent) to
432 * vertex W (destination).
433 */
paul4dadc292005-05-06 21:37:42 +0000434static void
paul718e3742002-12-13 20:15:29 +0000435ospf_nexthop_calculation (struct ospf_area *area,
436 struct vertex *v, struct vertex *w)
437{
paul1eb8ef22005-04-07 07:30:20 +0000438 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000439 struct vertex_nexthop *nh, *x;
440 struct ospf_interface *oi = NULL;
441 struct router_lsa_link *l = NULL;
paul0c0f9cd2003-06-06 23:27:04 +0000442
443
paul718e3742002-12-13 20:15:29 +0000444 if (IS_DEBUG_OSPF_EVENT)
gdt630e4802004-08-31 17:28:41 +0000445 {
ajs2a42e282004-12-08 18:43:03 +0000446 zlog_debug ("ospf_nexthop_calculation(): Start");
gdt630e4802004-08-31 17:28:41 +0000447 ospf_vertex_dump("V (parent):", v, 1, 1);
448 ospf_vertex_dump("W (dest) :", w, 1, 1);
449 }
paul718e3742002-12-13 20:15:29 +0000450
paul718e3742002-12-13 20:15:29 +0000451 if (v == area->spf)
452 {
gdt630e4802004-08-31 17:28:41 +0000453 /* 16.1.1 para 4. In the first case, the parent vertex (V) is the
454 root (the calculating router itself). This means that the
455 destination is either a directly connected network or directly
456 connected router. The outgoing interface in this case is simply
457 the OSPF interface connecting to the destination network/router.
458 */
459
paul718e3742002-12-13 20:15:29 +0000460 if (w->type == OSPF_VERTEX_ROUTER)
paul0c0f9cd2003-06-06 23:27:04 +0000461 {
462 while ((l = ospf_get_next_link (v, w, l)))
463 {
gdt630e4802004-08-31 17:28:41 +0000464 /* l is a link from v to w
465 * l2 will be link from w to v
466 */
paul0c0f9cd2003-06-06 23:27:04 +0000467 struct router_lsa_link *l2 = NULL;
468
gdt630e4802004-08-31 17:28:41 +0000469 if (IS_DEBUG_OSPF_EVENT)
470 {
471 char buf1[BUFSIZ];
paul1eb8ef22005-04-07 07:30:20 +0000472 char buf2[BUFSIZ];
473
ajs2a42e282004-12-08 18:43:03 +0000474 zlog_debug("ospf_nexthop_calculation(): considering link "
gdt630e4802004-08-31 17:28:41 +0000475 "type %d link_id %s link_data %s",
476 l->m[0].type,
477 inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ),
paul1eb8ef22005-04-07 07:30:20 +0000478 inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ));
gdt630e4802004-08-31 17:28:41 +0000479 }
480
paul0c0f9cd2003-06-06 23:27:04 +0000481 if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT)
482 {
gdt630e4802004-08-31 17:28:41 +0000483 /* If the destination is a router which connects to
484 the calculating router via a Point-to-MultiPoint
485 network, the destination's next hop IP address(es)
486 can be determined by examining the destination's
487 router-LSA: each link pointing back to the
488 calculating router and having a Link Data field
489 belonging to the Point-to-MultiPoint network
490 provides an IP address of the next hop router.
491
492 At this point l is a link from V to W, and V is the
493 root ("us"). Find the local interface associated
494 with l (its address is in l->link_data). If it
495 is a point-to-multipoint interface, then look through
496 the links in the opposite direction (W to V). If
497 any of them have an address that lands within the
498 subnet declared by the PtMP link, then that link
499 is a constituent of the PtMP link, and its address is
500 a nexthop address for V.
501 */
paul68980082003-03-25 05:07:42 +0000502 oi = ospf_if_is_configured (area->ospf, &l->link_data);
paul7afa08d2002-12-13 20:59:45 +0000503 if (oi && oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
paul0c0f9cd2003-06-06 23:27:04 +0000504 {
505 struct prefix_ipv4 la;
gdt630e4802004-08-31 17:28:41 +0000506
507 la.family = AF_INET;
paul0c0f9cd2003-06-06 23:27:04 +0000508 la.prefixlen = oi->address->prefixlen;
gdt630e4802004-08-31 17:28:41 +0000509
510 /* V links to W on PtMP interface
511 - find the interface address on W */
paul0c0f9cd2003-06-06 23:27:04 +0000512 while ((l2 = ospf_get_next_link (w, v, l2)))
513 {
514 la.prefix = l2->link_data;
515
516 if (prefix_cmp ((struct prefix *) &la,
517 oi->address) == 0)
518 /* link_data is on our PtMP network */
519 break;
520 }
gdt630e4802004-08-31 17:28:41 +0000521 } /* end l is on point-to-multipoint link */
paul0c0f9cd2003-06-06 23:27:04 +0000522 else
523 {
gdt630e4802004-08-31 17:28:41 +0000524 /* l is a regular point-to-point link.
525 Look for a link from W to V.
526 */
paul0c0f9cd2003-06-06 23:27:04 +0000527 while ((l2 = ospf_get_next_link (w, v, l2)))
528 {
529 oi = ospf_if_is_configured (area->ospf,
530 &(l2->link_data));
531
532 if (oi == NULL)
533 continue;
534
535 if (!IPV4_ADDR_SAME (&oi->address->u.prefix4,
536 &l->link_data))
537 continue;
538
539 break;
540 }
541 }
542
543 if (oi && l2)
544 {
gdt630e4802004-08-31 17:28:41 +0000545 /* found all necessary info to build nexthop */
paul0c0f9cd2003-06-06 23:27:04 +0000546 nh = vertex_nexthop_new (v);
547 nh->oi = oi;
548 nh->router = l2->link_data;
549 ospf_spf_consider_nexthop (w->nexthop, nh);
550 }
gdt630e4802004-08-31 17:28:41 +0000551 else
552 {
553 zlog_info("ospf_nexthop_calculation(): "
554 "could not determine nexthop for link");
555 }
556 } /* end point-to-point link from V to W */
557 } /* end iterate over links in W */
558 } /* end W is a Router vertex */
paul718e3742002-12-13 20:15:29 +0000559 else
paul0c0f9cd2003-06-06 23:27:04 +0000560 {
gdt630e4802004-08-31 17:28:41 +0000561 assert(w->type == OSPF_VERTEX_NETWORK);
paul0c0f9cd2003-06-06 23:27:04 +0000562 while ((l = ospf_get_next_link (v, w, l)))
563 {
564 oi = ospf_if_is_configured (area->ospf, &(l->link_data));
565 if (oi)
566 {
567 nh = vertex_nexthop_new (v);
568 nh->oi = oi;
569 nh->router.s_addr = 0;
paul75ee0b82004-08-05 09:10:31 +0000570 ospf_spf_consider_nexthop (w->nexthop, nh);
paul0c0f9cd2003-06-06 23:27:04 +0000571 }
572 }
573 }
paul718e3742002-12-13 20:15:29 +0000574 return;
gdt630e4802004-08-31 17:28:41 +0000575 } /* end V is the root */
576
577 /* Check if W's parent is a network connected to root. */
paul718e3742002-12-13 20:15:29 +0000578 else if (v->type == OSPF_VERTEX_NETWORK)
579 {
gdt630e4802004-08-31 17:28:41 +0000580 /* See if any of V's parents are the root. */
paul1eb8ef22005-04-07 07:30:20 +0000581 for (ALL_LIST_ELEMENTS (v->nexthop, node, nnode, x))
paul718e3742002-12-13 20:15:29 +0000582 {
gdt630e4802004-08-31 17:28:41 +0000583 if (x->parent == area->spf) /* connects to root? */
584 {
585 /* 16.1.1 para 5. ...the parent vertex is a network that
586 * directly connects the calculating router to the destination
587 * router. The list of next hops is then determined by
588 * examining the destination's router-LSA...
589 */
590
591 assert(w->type == OSPF_VERTEX_ROUTER);
paul0c0f9cd2003-06-06 23:27:04 +0000592 while ((l = ospf_get_next_link (w, v, l)))
593 {
gdt630e4802004-08-31 17:28:41 +0000594 /* ...For each link in the router-LSA that points back to the
595 * parent network, the link's Link Data field provides the IP
596 * address of a next hop router. The outgoing interface to
597 * use can then be derived from the next hop IP address (or
598 * it can be inherited from the parent network).
599 */
paul0c0f9cd2003-06-06 23:27:04 +0000600 nh = vertex_nexthop_new (v);
601 nh->oi = x->oi;
602 nh->router = l->link_data;
paul75ee0b82004-08-05 09:10:31 +0000603 ospf_spf_consider_nexthop (w->nexthop, nh);
paul0c0f9cd2003-06-06 23:27:04 +0000604 }
605 return;
606 }
paul718e3742002-12-13 20:15:29 +0000607 }
608 }
609
gdt630e4802004-08-31 17:28:41 +0000610 /* 16.1.1 para 4. If there is at least one intervening router in the
611 * current shortest path between the destination and the root, the
612 * destination simply inherits the set of next hops from the
613 * parent.
614 */
paul1eb8ef22005-04-07 07:30:20 +0000615 for (ALL_LIST_ELEMENTS (v->nexthop, node, nnode, nh))
paul718e3742002-12-13 20:15:29 +0000616 {
paul718e3742002-12-13 20:15:29 +0000617 nh->parent = v;
618 ospf_nexthop_add_unique (nh, w->nexthop);
619 }
620}
621
gdt630e4802004-08-31 17:28:41 +0000622/* RFC2328 Section 16.1 (2).
623 * v is on the SPF tree. Examine the links in v's LSA. Update the list
624 * of candidates with any vertices not already on the list. If a lower-cost
625 * path is found to a vertex already on the candidate list, store the new cost.
626 */
paul4dadc292005-05-06 21:37:42 +0000627static void
paul718e3742002-12-13 20:15:29 +0000628ospf_spf_next (struct vertex *v, struct ospf_area *area,
hasso462f20d2005-02-23 11:29:02 +0000629 struct pqueue * candidate)
paul718e3742002-12-13 20:15:29 +0000630{
631 struct ospf_lsa *w_lsa = NULL;
paul718e3742002-12-13 20:15:29 +0000632 u_char *p;
633 u_char *lim;
634 struct router_lsa_link *l = NULL;
635 struct in_addr *r;
paul718e3742002-12-13 20:15:29 +0000636 int type = 0;
637
638 /* If this is a router-LSA, and bit V of the router-LSA (see Section
639 A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE. */
640 if (v->type == OSPF_VERTEX_ROUTER)
641 {
642 if (IS_ROUTER_LSA_VIRTUAL ((struct router_lsa *) v->lsa))
643 area->transit = OSPF_TRANSIT_TRUE;
644 }
645
646 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul0c0f9cd2003-06-06 23:27:04 +0000647 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
648
paul718e3742002-12-13 20:15:29 +0000649 while (p < lim)
650 {
paul7461d452005-06-13 13:57:16 +0000651 struct vertex *w, *cw;
652
pauld355bfa2004-04-08 07:43:45 +0000653 int link = -1; /* link index for w's back link */
654
paul718e3742002-12-13 20:15:29 +0000655 /* In case of V is Router-LSA. */
656 if (v->lsa->type == OSPF_ROUTER_LSA)
657 {
658 l = (struct router_lsa_link *) p;
659
paul0c0f9cd2003-06-06 23:27:04 +0000660 p += (ROUTER_LSA_MIN_SIZE +
paul718e3742002-12-13 20:15:29 +0000661 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
662
663 /* (a) If this is a link to a stub network, examine the next
664 link in V's LSA. Links to stub networks will be
665 considered in the second stage of the shortest path
666 calculation. */
667 if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB)
668 continue;
669
670 /* (b) Otherwise, W is a transit vertex (router or transit
671 network). Look up the vertex W's LSA (router-LSA or
672 network-LSA) in Area A's link state database. */
673 switch (type)
674 {
675 case LSA_LINK_TYPE_POINTOPOINT:
676 case LSA_LINK_TYPE_VIRTUALLINK:
677 if (type == LSA_LINK_TYPE_VIRTUALLINK)
paul0c0f9cd2003-06-06 23:27:04 +0000678 {
679 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000680 zlog_debug ("looking up LSA through VL: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000681 inet_ntoa (l->link_id));
682 }
paul718e3742002-12-13 20:15:29 +0000683
684 w_lsa = ospf_lsa_lookup (area, OSPF_ROUTER_LSA, l->link_id,
685 l->link_id);
686 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000687 {
688 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000689 zlog_debug ("found Router LSA %s", inet_ntoa (l->link_id));
paul0c0f9cd2003-06-06 23:27:04 +0000690 }
paul718e3742002-12-13 20:15:29 +0000691 break;
692 case LSA_LINK_TYPE_TRANSIT:
paul0c0f9cd2003-06-06 23:27:04 +0000693 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000694 zlog_debug ("Looking up Network LSA, ID: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000695 inet_ntoa (l->link_id));
paul718e3742002-12-13 20:15:29 +0000696 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_NETWORK_LSA,
paul0c0f9cd2003-06-06 23:27:04 +0000697 l->link_id);
paul718e3742002-12-13 20:15:29 +0000698 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000699 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000700 zlog_debug ("found the LSA");
paul718e3742002-12-13 20:15:29 +0000701 break;
702 default:
paul0c0f9cd2003-06-06 23:27:04 +0000703 zlog_warn ("Invalid LSA link type %d", type);
paul718e3742002-12-13 20:15:29 +0000704 continue;
705 }
706 }
707 else
708 {
709 /* In case of V is Network-LSA. */
paul0c0f9cd2003-06-06 23:27:04 +0000710 r = (struct in_addr *) p;
paul718e3742002-12-13 20:15:29 +0000711 p += sizeof (struct in_addr);
712
713 /* Lookup the vertex W's LSA. */
714 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_ROUTER_LSA, *r);
715 }
716
717 /* (b cont.) If the LSA does not exist, or its LS age is equal
718 to MaxAge, or it does not have a link back to vertex V,
719 examine the next link in V's LSA.[23] */
720 if (w_lsa == NULL)
721 continue;
722
723 if (IS_LSA_MAXAGE (w_lsa))
724 continue;
725
pauld355bfa2004-04-08 07:43:45 +0000726 if ( (link = ospf_lsa_has_link (w_lsa->data, v->lsa)) < 0 )
paul718e3742002-12-13 20:15:29 +0000727 {
paul0c0f9cd2003-06-06 23:27:04 +0000728 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000729 zlog_debug ("The LSA doesn't have a link back");
paul718e3742002-12-13 20:15:29 +0000730 continue;
731 }
732
733 /* (c) If vertex W is already on the shortest-path tree, examine
734 the next link in the LSA. */
hasso462f20d2005-02-23 11:29:02 +0000735 if (w_lsa->stat == LSA_SPF_IN_SPFTREE)
736 {
737 if (IS_DEBUG_OSPF_EVENT)
738 zlog_debug ("The LSA is already in SPF");
739 continue;
740 }
paul718e3742002-12-13 20:15:29 +0000741
742 /* (d) Calculate the link state cost D of the resulting path
743 from the root to vertex W. D is equal to the sum of the link
744 state cost of the (already calculated) shortest path to
745 vertex V and the advertised cost of the link between vertices
746 V and W. If D is: */
747
748 /* prepare vertex W. */
749 w = ospf_vertex_new (w_lsa);
750
pauld355bfa2004-04-08 07:43:45 +0000751 /* Save W's back link index number, for use by virtual links */
752 w->backlink = link;
753
paul718e3742002-12-13 20:15:29 +0000754 /* calculate link cost D. */
755 if (v->lsa->type == OSPF_ROUTER_LSA)
gdt630e4802004-08-31 17:28:41 +0000756 w->distance = v->distance + ntohs (l->m[0].metric);
757 else /* v is not a Router-LSA */
758 w->distance = v->distance;
paul718e3742002-12-13 20:15:29 +0000759
760 /* Is there already vertex W in candidate list? */
hasso462f20d2005-02-23 11:29:02 +0000761 if (w_lsa->stat == LSA_SPF_NOT_EXPLORED)
762 {
763 /* Calculate nexthop to W. */
764 ospf_nexthop_calculation (area, v, w);
765 pqueue_enqueue (w, candidate);
766 }
767 else if (w_lsa->stat >= 0)
768 {
769 /* Get the vertex from candidates. */
770 cw = (struct vertex *) candidate->array[w_lsa->stat];
paul718e3742002-12-13 20:15:29 +0000771
hasso462f20d2005-02-23 11:29:02 +0000772 /* if D is greater than. */
773 if (cw->distance < w->distance)
paul718e3742002-12-13 20:15:29 +0000774 {
775 ospf_vertex_free (w);
776 continue;
777 }
hasso462f20d2005-02-23 11:29:02 +0000778 /* equal to. */
779 else if (cw->distance == w->distance)
paul718e3742002-12-13 20:15:29 +0000780 {
gdt630e4802004-08-31 17:28:41 +0000781 /* Found an equal-cost path to W. Calculate nexthop to W. */
paul718e3742002-12-13 20:15:29 +0000782 ospf_nexthop_calculation (area, v, w);
783 ospf_nexthop_merge (cw->nexthop, w->nexthop);
784 list_delete_all_node (w->nexthop);
785 ospf_vertex_free (w);
786 }
hasso462f20d2005-02-23 11:29:02 +0000787 /* less than. */
788 else
paul718e3742002-12-13 20:15:29 +0000789 {
gdt630e4802004-08-31 17:28:41 +0000790 /* Found a lower-cost path to W. Calculate nexthop to W. */
paul718e3742002-12-13 20:15:29 +0000791 ospf_nexthop_calculation (area, v, w);
792
793 /* Remove old vertex from candidate list. */
794 ospf_vertex_free (cw);
hasso462f20d2005-02-23 11:29:02 +0000795 candidate->array[w_lsa->stat] = w;
796 /* Decrease the key of the node in the heap, re-sort the heap. */
797 trickle_down (w_lsa->stat, candidate);
paul718e3742002-12-13 20:15:29 +0000798 }
gdt630e4802004-08-31 17:28:41 +0000799 } /* end W is already on the candidate list */
800 } /* end loop over the links in V's LSA */
paul718e3742002-12-13 20:15:29 +0000801}
802
paul4dadc292005-05-06 21:37:42 +0000803static void
paul718e3742002-12-13 20:15:29 +0000804ospf_spf_route_free (struct route_table *table)
805{
806 struct route_node *rn;
807 struct vertex *v;
808
809 for (rn = route_top (table); rn; rn = route_next (rn))
810 {
811 if ((v = rn->info))
paul0c0f9cd2003-06-06 23:27:04 +0000812 {
813 ospf_vertex_free (v);
814 rn->info = NULL;
815 }
paul718e3742002-12-13 20:15:29 +0000816
817 route_unlock_node (rn);
818 }
819
820 route_table_finish (table);
821}
822
paul4dadc292005-05-06 21:37:42 +0000823static void
paul718e3742002-12-13 20:15:29 +0000824ospf_spf_dump (struct vertex *v, int i)
825{
hasso52dc7ee2004-09-23 19:18:23 +0000826 struct listnode *cnode;
827 struct listnode *nnode;
paul718e3742002-12-13 20:15:29 +0000828 struct vertex_nexthop *nexthop;
829
830 if (v->type == OSPF_VERTEX_ROUTER)
831 {
832 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000833 zlog_debug ("SPF Result: %d [R] %s", i, inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000834 }
835 else
836 {
837 struct network_lsa *lsa = (struct network_lsa *) v->lsa;
838 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000839 zlog_debug ("SPF Result: %d [N] %s/%d", i, inet_ntoa (v->lsa->id),
paul0c0f9cd2003-06-06 23:27:04 +0000840 ip_masklen (lsa->mask));
gdt630e4802004-08-31 17:28:41 +0000841 }
paul718e3742002-12-13 20:15:29 +0000842
paul1eb8ef22005-04-07 07:30:20 +0000843 if (IS_DEBUG_OSPF_EVENT)
844 for (ALL_LIST_ELEMENTS_RO (v->nexthop, nnode, nexthop))
845 zlog_debug (" nexthop %s", inet_ntoa (nexthop->router));
paul718e3742002-12-13 20:15:29 +0000846
847 i++;
848
paul1eb8ef22005-04-07 07:30:20 +0000849 for (ALL_LIST_ELEMENTS_RO (v->child, cnode, v))
850 ospf_spf_dump (v, i);
paul718e3742002-12-13 20:15:29 +0000851}
852
853/* Second stage of SPF calculation. */
paul4dadc292005-05-06 21:37:42 +0000854static void
paul0c0f9cd2003-06-06 23:27:04 +0000855ospf_spf_process_stubs (struct ospf_area *area, struct vertex *v,
paul718e3742002-12-13 20:15:29 +0000856 struct route_table *rt)
857{
paul1eb8ef22005-04-07 07:30:20 +0000858 struct listnode *cnode, *cnnode;
paul718e3742002-12-13 20:15:29 +0000859 struct vertex *child;
860
861 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000862 zlog_debug ("ospf_process_stub():processing stubs for area %s",
paul0c0f9cd2003-06-06 23:27:04 +0000863 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +0000864 if (v->type == OSPF_VERTEX_ROUTER)
865 {
866 u_char *p;
867 u_char *lim;
868 struct router_lsa_link *l;
869 struct router_lsa *rlsa;
870
paul0c0f9cd2003-06-06 23:27:04 +0000871 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000872 zlog_debug ("ospf_process_stubs():processing router LSA, id: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000873 inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000874 rlsa = (struct router_lsa *) v->lsa;
875
876
paul0c0f9cd2003-06-06 23:27:04 +0000877 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000878 zlog_debug ("ospf_process_stubs(): we have %d links to process",
paul0c0f9cd2003-06-06 23:27:04 +0000879 ntohs (rlsa->links));
gdt630e4802004-08-31 17:28:41 +0000880 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +0000881 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
882
883 while (p < lim)
884 {
885 l = (struct router_lsa_link *) p;
886
887 p += (ROUTER_LSA_MIN_SIZE +
888 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
889
890 if (l->m[0].type == LSA_LINK_TYPE_STUB)
891 ospf_intra_add_stub (rt, l, v, area);
892 }
893 }
894
gdt630e4802004-08-31 17:28:41 +0000895 ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1, 1);
paul718e3742002-12-13 20:15:29 +0000896
paul1eb8ef22005-04-07 07:30:20 +0000897 for (ALL_LIST_ELEMENTS (v->child, cnode, cnnode, child))
paul718e3742002-12-13 20:15:29 +0000898 {
paul718e3742002-12-13 20:15:29 +0000899 if (CHECK_FLAG (child->flags, OSPF_VERTEX_PROCESSED))
paul0c0f9cd2003-06-06 23:27:04 +0000900 continue;
paul718e3742002-12-13 20:15:29 +0000901
902 ospf_spf_process_stubs (area, child, rt);
903
904 SET_FLAG (child->flags, OSPF_VERTEX_PROCESSED);
905 }
906}
907
908void
909ospf_rtrs_free (struct route_table *rtrs)
910{
911 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +0000912 struct list *or_list;
paul1eb8ef22005-04-07 07:30:20 +0000913 struct ospf_route *or;
914 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000915
916 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000917 zlog_debug ("Route: Router Routing Table free");
paul718e3742002-12-13 20:15:29 +0000918
919 for (rn = route_top (rtrs); rn; rn = route_next (rn))
920 if ((or_list = rn->info) != NULL)
921 {
paul1eb8ef22005-04-07 07:30:20 +0000922 for (ALL_LIST_ELEMENTS (or_list, node, nnode, or))
923 ospf_route_free (or);
paul718e3742002-12-13 20:15:29 +0000924
paul0c0f9cd2003-06-06 23:27:04 +0000925 list_delete (or_list);
paul718e3742002-12-13 20:15:29 +0000926
paul0c0f9cd2003-06-06 23:27:04 +0000927 /* Unlock the node. */
928 rn->info = NULL;
929 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +0000930 }
931 route_table_finish (rtrs);
932}
933
paul4dadc292005-05-06 21:37:42 +0000934static void
paul718e3742002-12-13 20:15:29 +0000935ospf_rtrs_print (struct route_table *rtrs)
936{
937 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +0000938 struct list *or_list;
939 struct listnode *ln;
940 struct listnode *pnode;
paul718e3742002-12-13 20:15:29 +0000941 struct ospf_route *or;
942 struct ospf_path *path;
943 char buf1[BUFSIZ];
944 char buf2[BUFSIZ];
945
946 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000947 zlog_debug ("ospf_rtrs_print() start");
paul718e3742002-12-13 20:15:29 +0000948
949 for (rn = route_top (rtrs); rn; rn = route_next (rn))
950 if ((or_list = rn->info) != NULL)
paul1eb8ef22005-04-07 07:30:20 +0000951 for (ALL_LIST_ELEMENTS_RO (or_list, ln, or))
paul718e3742002-12-13 20:15:29 +0000952 {
paul718e3742002-12-13 20:15:29 +0000953 switch (or->path_type)
954 {
955 case OSPF_PATH_INTRA_AREA:
paul0c0f9cd2003-06-06 23:27:04 +0000956 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000957 zlog_debug ("%s [%d] area: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000958 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
959 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
960 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +0000961 break;
962 case OSPF_PATH_INTER_AREA:
paul0c0f9cd2003-06-06 23:27:04 +0000963 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000964 zlog_debug ("%s IA [%d] area: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000965 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
966 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
967 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +0000968 break;
969 default:
970 break;
971 }
972
paul1eb8ef22005-04-07 07:30:20 +0000973 for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path))
paul718e3742002-12-13 20:15:29 +0000974 {
paul718e3742002-12-13 20:15:29 +0000975 if (path->nexthop.s_addr == 0)
paul0c0f9cd2003-06-06 23:27:04 +0000976 {
977 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000978 zlog_debug (" directly attached to %s\r\n",
paul0c0f9cd2003-06-06 23:27:04 +0000979 IF_NAME (path->oi));
980 }
981 else
982 {
983 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000984 zlog_debug (" via %s, %s\r\n",
paul0c0f9cd2003-06-06 23:27:04 +0000985 inet_ntoa (path->nexthop), IF_NAME (path->oi));
986 }
paul718e3742002-12-13 20:15:29 +0000987 }
988 }
989
ajs2a42e282004-12-08 18:43:03 +0000990 zlog_debug ("ospf_rtrs_print() end");
paul718e3742002-12-13 20:15:29 +0000991}
992
993/* Calculating the shortest-path tree for an area. */
paul4dadc292005-05-06 21:37:42 +0000994static void
paul0c0f9cd2003-06-06 23:27:04 +0000995ospf_spf_calculate (struct ospf_area *area, struct route_table *new_table,
paul718e3742002-12-13 20:15:29 +0000996 struct route_table *new_rtrs)
997{
hasso462f20d2005-02-23 11:29:02 +0000998 struct pqueue *candidate;
paul718e3742002-12-13 20:15:29 +0000999 struct vertex *v;
paul718e3742002-12-13 20:15:29 +00001000
1001 if (IS_DEBUG_OSPF_EVENT)
1002 {
ajs2a42e282004-12-08 18:43:03 +00001003 zlog_debug ("ospf_spf_calculate: Start");
1004 zlog_debug ("ospf_spf_calculate: running Dijkstra for area %s",
paul0c0f9cd2003-06-06 23:27:04 +00001005 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001006 }
1007
1008 /* Check router-lsa-self. If self-router-lsa is not yet allocated,
1009 return this area's calculation. */
paul0c0f9cd2003-06-06 23:27:04 +00001010 if (!area->router_lsa_self)
paul718e3742002-12-13 20:15:29 +00001011 {
1012 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001013 zlog_debug ("ospf_spf_calculate: "
paul0c0f9cd2003-06-06 23:27:04 +00001014 "Skip area %s's calculation due to empty router_lsa_self",
1015 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001016 return;
1017 }
1018
1019 /* RFC2328 16.1. (1). */
paul0c0f9cd2003-06-06 23:27:04 +00001020 /* Initialize the algorithm's data structures. */
hasso462f20d2005-02-23 11:29:02 +00001021
1022 /* This function scans all the LSA database and set the stat field to
1023 * LSA_SPF_NOT_EXPLORED. */
1024 ospf_lsdb_clean_stat (area->lsdb);
1025 /* Create a new heap for the candidates. */
1026 candidate = pqueue_create();
1027 candidate->cmp = cmp;
1028 candidate->update = update_stat;
paul718e3742002-12-13 20:15:29 +00001029
1030 /* Initialize the shortest-path tree to only the root (which is the
1031 router doing the calculation). */
1032 ospf_spf_init (area);
1033 v = area->spf;
hasso462f20d2005-02-23 11:29:02 +00001034 /* Set LSA position to LSA_SPF_IN_SPFTREE. This vertex is the root of the
1035 * spanning tree. */
1036 *(v->stat) = LSA_SPF_IN_SPFTREE;
paul718e3742002-12-13 20:15:29 +00001037
1038 /* Set Area A's TransitCapability to FALSE. */
1039 area->transit = OSPF_TRANSIT_FALSE;
1040 area->shortcut_capability = 1;
1041
1042 for (;;)
1043 {
1044 /* RFC2328 16.1. (2). */
hasso462f20d2005-02-23 11:29:02 +00001045 ospf_spf_next (v, area, candidate);
paul718e3742002-12-13 20:15:29 +00001046
1047 /* RFC2328 16.1. (3). */
1048 /* If at this step the candidate list is empty, the shortest-
1049 path tree (of transit vertices) has been completely built and
1050 this stage of the procedure terminates. */
hasso462f20d2005-02-23 11:29:02 +00001051 if (candidate->size == 0)
paul718e3742002-12-13 20:15:29 +00001052 break;
1053
1054 /* Otherwise, choose the vertex belonging to the candidate list
1055 that is closest to the root, and add it to the shortest-path
1056 tree (removing it from the candidate list in the
paul0c0f9cd2003-06-06 23:27:04 +00001057 process). */
hasso462f20d2005-02-23 11:29:02 +00001058 /* Extract from the candidates the node with the lower key. */
1059 v = (struct vertex *) pqueue_dequeue (candidate);
1060 /* Update stat field in vertex. */
1061 *(v->stat) = LSA_SPF_IN_SPFTREE;
paul718e3742002-12-13 20:15:29 +00001062 ospf_vertex_add_parent (v);
1063
paul718e3742002-12-13 20:15:29 +00001064 /* Note that when there is a choice of vertices closest to the
1065 root, network vertices must be chosen before router vertices
1066 in order to necessarily find all equal-cost paths. */
1067 /* We don't do this at this moment, we should add the treatment
1068 above codes. -- kunihiro. */
1069
1070 /* RFC2328 16.1. (4). */
1071 if (v->type == OSPF_VERTEX_ROUTER)
1072 ospf_intra_add_router (new_rtrs, v, area);
paul0c0f9cd2003-06-06 23:27:04 +00001073 else
paul718e3742002-12-13 20:15:29 +00001074 ospf_intra_add_transit (new_table, v, area);
1075
1076 /* RFC2328 16.1. (5). */
1077 /* Iterate the algorithm by returning to Step 2. */
gdt630e4802004-08-31 17:28:41 +00001078
1079 } /* end loop until no more candidate vertices */
paul718e3742002-12-13 20:15:29 +00001080
1081 if (IS_DEBUG_OSPF_EVENT)
1082 {
1083 ospf_spf_dump (area->spf, 0);
1084 ospf_route_table_dump (new_table);
1085 }
1086
1087 /* Second stage of SPF calculation procedure's */
1088 ospf_spf_process_stubs (area, area->spf, new_table);
1089
hasso462f20d2005-02-23 11:29:02 +00001090 /* Free candidates. */
1091 pqueue_delete (candidate);
paul718e3742002-12-13 20:15:29 +00001092
1093 /* Increment SPF Calculation Counter. */
1094 area->spf_calculation++;
1095
paul68980082003-03-25 05:07:42 +00001096 area->ospf->ts_spf = time (NULL);
paul718e3742002-12-13 20:15:29 +00001097
1098 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001099 zlog_debug ("ospf_spf_calculate: Stop");
paul718e3742002-12-13 20:15:29 +00001100}
1101
1102/* Timer for SPF calculation. */
paul4dadc292005-05-06 21:37:42 +00001103static int
paul68980082003-03-25 05:07:42 +00001104ospf_spf_calculate_timer (struct thread *thread)
paul718e3742002-12-13 20:15:29 +00001105{
paul68980082003-03-25 05:07:42 +00001106 struct ospf *ospf = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +00001107 struct route_table *new_table, *new_rtrs;
paul1eb8ef22005-04-07 07:30:20 +00001108 struct ospf_area *area;
1109 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001110
1111 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001112 zlog_debug ("SPF: Timer (SPF calculation expire)");
paul0c0f9cd2003-06-06 23:27:04 +00001113
paul718e3742002-12-13 20:15:29 +00001114 ospf->t_spf_calc = NULL;
1115
1116 /* Allocate new table tree. */
1117 new_table = route_table_init ();
paul0c0f9cd2003-06-06 23:27:04 +00001118 new_rtrs = route_table_init ();
paul718e3742002-12-13 20:15:29 +00001119
paul68980082003-03-25 05:07:42 +00001120 ospf_vl_unapprove (ospf);
paul718e3742002-12-13 20:15:29 +00001121
1122 /* Calculate SPF for each area. */
paul1eb8ef22005-04-07 07:30:20 +00001123 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
1124 ospf_spf_calculate (area, new_table, new_rtrs);
paul718e3742002-12-13 20:15:29 +00001125
paul68980082003-03-25 05:07:42 +00001126 ospf_vl_shut_unapproved (ospf);
paul718e3742002-12-13 20:15:29 +00001127
paul68980082003-03-25 05:07:42 +00001128 ospf_ia_routing (ospf, new_table, new_rtrs);
paul718e3742002-12-13 20:15:29 +00001129
1130 ospf_prune_unreachable_networks (new_table);
1131 ospf_prune_unreachable_routers (new_rtrs);
1132
1133 /* AS-external-LSA calculation should not be performed here. */
1134
1135 /* If new Router Route is installed,
1136 then schedule re-calculate External routes. */
1137 if (1)
paul68980082003-03-25 05:07:42 +00001138 ospf_ase_calculate_schedule (ospf);
paul718e3742002-12-13 20:15:29 +00001139
paul68980082003-03-25 05:07:42 +00001140 ospf_ase_calculate_timer_add (ospf);
paul718e3742002-12-13 20:15:29 +00001141
1142 /* Update routing table. */
paul68980082003-03-25 05:07:42 +00001143 ospf_route_install (ospf, new_table);
paul718e3742002-12-13 20:15:29 +00001144
1145 /* Update ABR/ASBR routing table */
paul68980082003-03-25 05:07:42 +00001146 if (ospf->old_rtrs)
paul718e3742002-12-13 20:15:29 +00001147 {
1148 /* old_rtrs's node holds linked list of ospf_route. --kunihiro. */
paul68980082003-03-25 05:07:42 +00001149 /* ospf_route_delete (ospf->old_rtrs); */
1150 ospf_rtrs_free (ospf->old_rtrs);
paul718e3742002-12-13 20:15:29 +00001151 }
1152
paul68980082003-03-25 05:07:42 +00001153 ospf->old_rtrs = ospf->new_rtrs;
1154 ospf->new_rtrs = new_rtrs;
paul718e3742002-12-13 20:15:29 +00001155
paul0c0f9cd2003-06-06 23:27:04 +00001156 if (IS_OSPF_ABR (ospf))
paul68980082003-03-25 05:07:42 +00001157 ospf_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001158
1159 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001160 zlog_debug ("SPF: calculation complete");
paul718e3742002-12-13 20:15:29 +00001161
1162 return 0;
1163}
1164
1165/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
1166 set timer for SPF calc. */
1167void
paul68980082003-03-25 05:07:42 +00001168ospf_spf_calculate_schedule (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00001169{
1170 time_t ht, delay;
1171
1172 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001173 zlog_debug ("SPF: calculation timer scheduled");
paul718e3742002-12-13 20:15:29 +00001174
1175 /* OSPF instance does not exist. */
paul68980082003-03-25 05:07:42 +00001176 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001177 return;
1178
1179 /* SPF calculation timer is already scheduled. */
paul68980082003-03-25 05:07:42 +00001180 if (ospf->t_spf_calc)
paul718e3742002-12-13 20:15:29 +00001181 {
1182 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001183 zlog_debug ("SPF: calculation timer is already scheduled: %p",
paul0c0f9cd2003-06-06 23:27:04 +00001184 ospf->t_spf_calc);
paul718e3742002-12-13 20:15:29 +00001185 return;
1186 }
1187
paul68980082003-03-25 05:07:42 +00001188 ht = time (NULL) - ospf->ts_spf;
paul718e3742002-12-13 20:15:29 +00001189
1190 /* Get SPF calculation delay time. */
paul68980082003-03-25 05:07:42 +00001191 if (ht < ospf->spf_holdtime)
paul718e3742002-12-13 20:15:29 +00001192 {
paul68980082003-03-25 05:07:42 +00001193 if (ospf->spf_holdtime - ht < ospf->spf_delay)
paul0c0f9cd2003-06-06 23:27:04 +00001194 delay = ospf->spf_delay;
paul718e3742002-12-13 20:15:29 +00001195 else
paul0c0f9cd2003-06-06 23:27:04 +00001196 delay = ospf->spf_holdtime - ht;
paul718e3742002-12-13 20:15:29 +00001197 }
1198 else
paul68980082003-03-25 05:07:42 +00001199 delay = ospf->spf_delay;
paul718e3742002-12-13 20:15:29 +00001200
1201 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001202 zlog_debug ("SPF: calculation timer delay = %ld", (long)delay);
paul68980082003-03-25 05:07:42 +00001203 ospf->t_spf_calc =
1204 thread_add_timer (master, ospf_spf_calculate_timer, ospf, delay);
paul718e3742002-12-13 20:15:29 +00001205}