blob: 206a2e7c3cf2097bd5ff1408b205a3d05f042a34 [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
49#define DEBUG
50
hasso462f20d2005-02-23 11:29:02 +000051/* Heap related functions, for the managment of the candidates, to
52 * be used with pqueue. */
53static int
54cmp (void * node1 , void * node2)
55{
56 struct vertex * v1 = (struct vertex *) node1;
57 struct vertex * v2 = (struct vertex *) node2;
58 if (v1 != NULL && v2 != NULL )
59 return (v1->distance - v2->distance);
60 else
61 return 0;
62}
63
64static void
65update_stat (void * node , int position)
66{
67 struct vertex * v = (struct vertex *) node;
68 /* Set the status of the vertex, when its position changes. */
69 *(v->stat) = position;
70}
71/* End of the heap related functions. */
72
paul4dadc292005-05-06 21:37:42 +000073static struct vertex_nexthop *
paul718e3742002-12-13 20:15:29 +000074vertex_nexthop_new (struct vertex *parent)
75{
76 struct vertex_nexthop *new;
77
78 new = XCALLOC (MTYPE_OSPF_NEXTHOP, sizeof (struct vertex_nexthop));
79 new->parent = parent;
80
81 return new;
82}
83
paul4dadc292005-05-06 21:37:42 +000084static void
paul718e3742002-12-13 20:15:29 +000085vertex_nexthop_free (struct vertex_nexthop *nh)
86{
87 XFREE (MTYPE_OSPF_NEXTHOP, nh);
88}
89
paul4dadc292005-05-06 21:37:42 +000090static struct vertex_nexthop *
paul718e3742002-12-13 20:15:29 +000091vertex_nexthop_dup (struct vertex_nexthop *nh)
92{
93 struct vertex_nexthop *new;
94
95 new = vertex_nexthop_new (nh->parent);
96
97 new->oi = nh->oi;
98 new->router = nh->router;
99
100 return new;
101}
paul718e3742002-12-13 20:15:29 +0000102
paul0c0f9cd2003-06-06 23:27:04 +0000103
paul4dadc292005-05-06 21:37:42 +0000104static struct vertex *
paul718e3742002-12-13 20:15:29 +0000105ospf_vertex_new (struct ospf_lsa *lsa)
106{
107 struct vertex *new;
108
109 new = XMALLOC (MTYPE_OSPF_VERTEX, sizeof (struct vertex));
110 memset (new, 0, sizeof (struct vertex));
111
112 new->flags = 0;
hasso462f20d2005-02-23 11:29:02 +0000113 new->stat = &(lsa->stat);
paul718e3742002-12-13 20:15:29 +0000114 new->type = lsa->data->type;
115 new->id = lsa->data->id;
116 new->lsa = lsa->data;
117 new->distance = 0;
118 new->child = list_new ();
119 new->nexthop = list_new ();
pauld355bfa2004-04-08 07:43:45 +0000120 new->backlink = -1;
paul718e3742002-12-13 20:15:29 +0000121
122 return new;
123}
124
paul4dadc292005-05-06 21:37:42 +0000125static void
paul718e3742002-12-13 20:15:29 +0000126ospf_vertex_free (struct vertex *v)
127{
paul1eb8ef22005-04-07 07:30:20 +0000128 struct listnode *node, *nnode;
129 struct vertex_nexthop *nh;
paul718e3742002-12-13 20:15:29 +0000130
131 list_delete (v->child);
paul7461d452005-06-13 13:57:16 +0000132 v->child = NULL;
133
paul718e3742002-12-13 20:15:29 +0000134 if (listcount (v->nexthop) > 0)
paul1eb8ef22005-04-07 07:30:20 +0000135 for (ALL_LIST_ELEMENTS (v->nexthop, node, nnode, nh))
136 vertex_nexthop_free (nh);
paul718e3742002-12-13 20:15:29 +0000137
138 list_delete (v->nexthop);
paul7461d452005-06-13 13:57:16 +0000139 v->nexthop = NULL;
140
paul718e3742002-12-13 20:15:29 +0000141 XFREE (MTYPE_OSPF_VERTEX, v);
142}
143
paul4dadc292005-05-06 21:37:42 +0000144static void
hassoeb1ce602004-10-08 08:17:22 +0000145ospf_vertex_dump(const char *msg, struct vertex *v,
gdt630e4802004-08-31 17:28:41 +0000146 int print_nexthops, int print_children)
147{
148 if ( ! IS_DEBUG_OSPF_EVENT)
149 return;
150
ajs2a42e282004-12-08 18:43:03 +0000151 zlog_debug("%s %s vertex %s distance %u backlink %d flags %u",
gdt630e4802004-08-31 17:28:41 +0000152 msg,
153 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
154 inet_ntoa(v->lsa->id),
155 v->distance,
156 v->backlink,
157 (unsigned int)v->flags);
158
159 if (print_nexthops)
160 {
paul1eb8ef22005-04-07 07:30:20 +0000161 struct listnode *node;
162 struct vertex_nexthop *nexthop;
163
164 for (ALL_LIST_ELEMENTS_RO (v->nexthop, node, nexthop))
gdt630e4802004-08-31 17:28:41 +0000165 {
166 char buf1[BUFSIZ];
167 char buf2[BUFSIZ];
gdt630e4802004-08-31 17:28:41 +0000168
gdt630e4802004-08-31 17:28:41 +0000169 if (nexthop)
170 {
ajs2a42e282004-12-08 18:43:03 +0000171 zlog_debug (" nexthop %s interface %s parent %s",
gdt630e4802004-08-31 17:28:41 +0000172 inet_ntop(AF_INET, &nexthop->router, buf1, BUFSIZ),
173 nexthop->oi ? IF_NAME(nexthop->oi) : "NULL",
174 nexthop->parent ? inet_ntop(AF_INET,
175 &nexthop->parent->id,
176 buf2, BUFSIZ)
177 : "NULL");
178 }
179 }
180 }
181
182 if (print_children)
183 {
hasso52dc7ee2004-09-23 19:18:23 +0000184 struct listnode *cnode;
paul1eb8ef22005-04-07 07:30:20 +0000185 struct vertex *cv;
186
187 for (ALL_LIST_ELEMENTS_RO (v->child, cnode, cv))
188 ospf_vertex_dump(" child:", cv, 0, 0);
gdt630e4802004-08-31 17:28:41 +0000189 }
190}
191
192
193/* Add a vertex to the list of children in each of its parents. */
paul4dadc292005-05-06 21:37:42 +0000194static void
paul718e3742002-12-13 20:15:29 +0000195ospf_vertex_add_parent (struct vertex *v)
196{
197 struct vertex_nexthop *nh;
hasso52dc7ee2004-09-23 19:18:23 +0000198 struct listnode *node;
paul7461d452005-06-13 13:57:16 +0000199
200 assert (v->nexthop && v->child);
201
paul1eb8ef22005-04-07 07:30:20 +0000202 for (ALL_LIST_ELEMENTS_RO (v->nexthop, node, nh))
paul718e3742002-12-13 20:15:29 +0000203 {
paul7461d452005-06-13 13:57:16 +0000204 assert (nh->parent && nh->parent->child);
205
paul718e3742002-12-13 20:15:29 +0000206 /* No need to add two links from the same parent. */
207 if (listnode_lookup (nh->parent->child, v) == NULL)
paul0c0f9cd2003-06-06 23:27:04 +0000208 listnode_add (nh->parent->child, v);
paul718e3742002-12-13 20:15:29 +0000209 }
210}
211
paul4dadc292005-05-06 21:37:42 +0000212static void
paul718e3742002-12-13 20:15:29 +0000213ospf_spf_init (struct ospf_area *area)
214{
215 struct vertex *v;
216
217 /* Create root node. */
218 v = ospf_vertex_new (area->router_lsa_self);
219
220 area->spf = v;
221
222 /* Reset ABR and ASBR router counts. */
223 area->abr_count = 0;
224 area->asbr_count = 0;
225}
226
pauld355bfa2004-04-08 07:43:45 +0000227/* return index of link back to V from W, or -1 if no link found */
paul4dadc292005-05-06 21:37:42 +0000228static int
paul718e3742002-12-13 20:15:29 +0000229ospf_lsa_has_link (struct lsa_header *w, struct lsa_header *v)
230{
hassoeb1ce602004-10-08 08:17:22 +0000231 unsigned int i, length;
paul718e3742002-12-13 20:15:29 +0000232 struct router_lsa *rl;
233 struct network_lsa *nl;
234
235 /* In case of W is Network LSA. */
236 if (w->type == OSPF_NETWORK_LSA)
237 {
238 if (v->type == OSPF_NETWORK_LSA)
pauld355bfa2004-04-08 07:43:45 +0000239 return -1;
paul718e3742002-12-13 20:15:29 +0000240
241 nl = (struct network_lsa *) w;
242 length = (ntohs (w->length) - OSPF_LSA_HEADER_SIZE - 4) / 4;
paul0c0f9cd2003-06-06 23:27:04 +0000243
paul718e3742002-12-13 20:15:29 +0000244 for (i = 0; i < length; i++)
245 if (IPV4_ADDR_SAME (&nl->routers[i], &v->id))
pauld355bfa2004-04-08 07:43:45 +0000246 return i;
247 return -1;
paul718e3742002-12-13 20:15:29 +0000248 }
249
250 /* In case of W is Router LSA. */
251 if (w->type == OSPF_ROUTER_LSA)
252 {
253 rl = (struct router_lsa *) w;
254
255 length = ntohs (w->length);
256
257 for (i = 0;
paul0c0f9cd2003-06-06 23:27:04 +0000258 i < ntohs (rl->links) && length >= sizeof (struct router_lsa);
259 i++, length -= 12)
paul718e3742002-12-13 20:15:29 +0000260 {
261 switch (rl->link[i].type)
262 {
263 case LSA_LINK_TYPE_POINTOPOINT:
264 case LSA_LINK_TYPE_VIRTUALLINK:
265 /* Router LSA ID. */
266 if (v->type == OSPF_ROUTER_LSA &&
267 IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
268 {
pauld355bfa2004-04-08 07:43:45 +0000269 return i;
paul718e3742002-12-13 20:15:29 +0000270 }
271 break;
272 case LSA_LINK_TYPE_TRANSIT:
273 /* Network LSA ID. */
274 if (v->type == OSPF_NETWORK_LSA &&
275 IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
276 {
pauld355bfa2004-04-08 07:43:45 +0000277 return i;
paul0c0f9cd2003-06-06 23:27:04 +0000278 }
paul718e3742002-12-13 20:15:29 +0000279 break;
280 case LSA_LINK_TYPE_STUB:
281 /* Not take into count? */
282 continue;
283 default:
284 break;
285 }
286 }
287 }
pauld355bfa2004-04-08 07:43:45 +0000288 return -1;
paul718e3742002-12-13 20:15:29 +0000289}
290
291/* Add the nexthop to the list, only if it is unique.
292 * If it's not unique, free the nexthop entry.
293 */
paul4dadc292005-05-06 21:37:42 +0000294static void
hasso52dc7ee2004-09-23 19:18:23 +0000295ospf_nexthop_add_unique (struct vertex_nexthop *new, struct list *nexthop)
paul718e3742002-12-13 20:15:29 +0000296{
297 struct vertex_nexthop *nh;
hasso52dc7ee2004-09-23 19:18:23 +0000298 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000299 int match;
300
301 match = 0;
paul718e3742002-12-13 20:15:29 +0000302
paul1eb8ef22005-04-07 07:30:20 +0000303 for (ALL_LIST_ELEMENTS_RO (nexthop, node, nh))
304 {
paul718e3742002-12-13 20:15:29 +0000305 /* Compare the two entries. */
306 /* XXX
307 * Comparing the parent preserves the shortest path tree
308 * structure even when the nexthops are identical.
309 */
310 if (nh->oi == new->oi &&
paul0c0f9cd2003-06-06 23:27:04 +0000311 IPV4_ADDR_SAME (&nh->router, &new->router) &&
312 nh->parent == new->parent)
313 {
314 match = 1;
315 break;
316 }
paul718e3742002-12-13 20:15:29 +0000317 }
318
319 if (!match)
320 listnode_add (nexthop, new);
321 else
322 vertex_nexthop_free (new);
323}
324
325/* Merge entries in list b into list a. */
paul4dadc292005-05-06 21:37:42 +0000326static void
hasso52dc7ee2004-09-23 19:18:23 +0000327ospf_nexthop_merge (struct list *a, struct list *b)
paul718e3742002-12-13 20:15:29 +0000328{
paul1eb8ef22005-04-07 07:30:20 +0000329 struct listnode *node, *nnode;
330 struct vertex_nexthop *nh;
paul718e3742002-12-13 20:15:29 +0000331
paul1eb8ef22005-04-07 07:30:20 +0000332 for (ALL_LIST_ELEMENTS (b, node, nnode, nh))
333 ospf_nexthop_add_unique (nh, a);
paul718e3742002-12-13 20:15:29 +0000334}
335
336#define ROUTER_LSA_MIN_SIZE 12
337#define ROUTER_LSA_TOS_SIZE 4
338
gdt630e4802004-08-31 17:28:41 +0000339/* Find the next link after prev_link from v to w. If prev_link is
340 * NULL, return the first link from v to w. Ignore stub and virtual links;
341 * these link types will never be returned.
342 */
paul4dadc292005-05-06 21:37:42 +0000343static struct router_lsa_link *
paul718e3742002-12-13 20:15:29 +0000344ospf_get_next_link (struct vertex *v, struct vertex *w,
paul0c0f9cd2003-06-06 23:27:04 +0000345 struct router_lsa_link *prev_link)
paul718e3742002-12-13 20:15:29 +0000346{
347 u_char *p;
348 u_char *lim;
349 struct router_lsa_link *l;
350
351 if (prev_link == NULL)
gdt630e4802004-08-31 17:28:41 +0000352 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +0000353 else
354 {
paul0c0f9cd2003-06-06 23:27:04 +0000355 p = (u_char *) prev_link;
paul718e3742002-12-13 20:15:29 +0000356 p += (ROUTER_LSA_MIN_SIZE +
357 (prev_link->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
358 }
paul0c0f9cd2003-06-06 23:27:04 +0000359
paul718e3742002-12-13 20:15:29 +0000360 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
361
362 while (p < lim)
363 {
364 l = (struct router_lsa_link *) p;
365
paul0c0f9cd2003-06-06 23:27:04 +0000366 p += (ROUTER_LSA_MIN_SIZE + (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
paul718e3742002-12-13 20:15:29 +0000367
368 if (l->m[0].type == LSA_LINK_TYPE_STUB)
369 continue;
370
371 /* Defer NH calculation via VLs until summaries from
372 transit areas area confidered */
373
374 if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK)
paul0c0f9cd2003-06-06 23:27:04 +0000375 continue;
paul718e3742002-12-13 20:15:29 +0000376
377 if (IPV4_ADDR_SAME (&l->link_id, &w->id))
paul0c0f9cd2003-06-06 23:27:04 +0000378 return l;
paul718e3742002-12-13 20:15:29 +0000379 }
380
381 return NULL;
382}
383
paul75ee0b82004-08-05 09:10:31 +0000384/*
385 * Consider supplied next-hop for inclusion to the supplied list of
386 * equal-cost next-hops, adjust list as neccessary.
387 *
388 * (Discussed on GNU Zebra list 27 May 2003, [zebra 19184])
389 *
390 * Note that below is a bit of a hack, and limits ECMP to paths that go to
391 * same nexthop. Where as paths via inequal output_cost interfaces could
392 * still quite easily be ECMP due to remote cost differences.
393 *
394 * TODO: It really should be done by way of recording currently valid
395 * backlinks and determining the appropriate nexthops from the list of
396 * backlinks, or even simpler, just flushing nexthop list if we find a lower
397 * cost path to a candidate vertex in SPF, maybe.
paulbf9392c2003-06-06 23:23:36 +0000398 */
paul4dadc292005-05-06 21:37:42 +0000399static void
paul0c0f9cd2003-06-06 23:27:04 +0000400ospf_spf_consider_nexthop (struct list *nexthops,
401 struct vertex_nexthop *newhop)
paulbf9392c2003-06-06 23:23:36 +0000402{
paulbf9392c2003-06-06 23:23:36 +0000403 struct vertex_nexthop *hop;
paul75ee0b82004-08-05 09:10:31 +0000404 struct listnode *ln, *nn;
paul0c0f9cd2003-06-06 23:27:04 +0000405
paul75ee0b82004-08-05 09:10:31 +0000406 /* nexthop list should contain only the set of nexthops that have the lowest
407 * equal cost
408 */
409 if (nexthops->head != NULL)
410 {
paul1eb8ef22005-04-07 07:30:20 +0000411 hop = listgetdata (nexthops->head);
paul75ee0b82004-08-05 09:10:31 +0000412
413 /* weed out hops with higher cost than the newhop */
414 if (hop->oi->output_cost > newhop->oi->output_cost)
415 {
416 /* delete the existing nexthops */
paul1eb8ef22005-04-07 07:30:20 +0000417 for (ALL_LIST_ELEMENTS (nexthops, ln, nn, hop))
paul75ee0b82004-08-05 09:10:31 +0000418 {
paul75ee0b82004-08-05 09:10:31 +0000419 listnode_delete (nexthops, hop);
420 vertex_nexthop_free (hop);
421 }
422 }
423 else if (hop->oi->output_cost < newhop->oi->output_cost)
paul0c0f9cd2003-06-06 23:27:04 +0000424 return;
paul75ee0b82004-08-05 09:10:31 +0000425 }
paul0c0f9cd2003-06-06 23:27:04 +0000426
paulbf9392c2003-06-06 23:23:36 +0000427 /* new hop is <= existing hops, add it */
paul0c0f9cd2003-06-06 23:27:04 +0000428 listnode_add (nexthops, newhop);
paulbf9392c2003-06-06 23:23:36 +0000429
430 return;
431}
432
gdt630e4802004-08-31 17:28:41 +0000433/* 16.1.1. Calculate nexthop from root through V (parent) to
434 * vertex W (destination).
435 */
paul4dadc292005-05-06 21:37:42 +0000436static void
paul718e3742002-12-13 20:15:29 +0000437ospf_nexthop_calculation (struct ospf_area *area,
438 struct vertex *v, struct vertex *w)
439{
paul1eb8ef22005-04-07 07:30:20 +0000440 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000441 struct vertex_nexthop *nh, *x;
442 struct ospf_interface *oi = NULL;
443 struct router_lsa_link *l = NULL;
paul0c0f9cd2003-06-06 23:27:04 +0000444
445
paul718e3742002-12-13 20:15:29 +0000446 if (IS_DEBUG_OSPF_EVENT)
gdt630e4802004-08-31 17:28:41 +0000447 {
ajs2a42e282004-12-08 18:43:03 +0000448 zlog_debug ("ospf_nexthop_calculation(): Start");
gdt630e4802004-08-31 17:28:41 +0000449 ospf_vertex_dump("V (parent):", v, 1, 1);
450 ospf_vertex_dump("W (dest) :", w, 1, 1);
451 }
paul718e3742002-12-13 20:15:29 +0000452
paul718e3742002-12-13 20:15:29 +0000453 if (v == area->spf)
454 {
gdt630e4802004-08-31 17:28:41 +0000455 /* 16.1.1 para 4. In the first case, the parent vertex (V) is the
456 root (the calculating router itself). This means that the
457 destination is either a directly connected network or directly
458 connected router. The outgoing interface in this case is simply
459 the OSPF interface connecting to the destination network/router.
460 */
461
paul718e3742002-12-13 20:15:29 +0000462 if (w->type == OSPF_VERTEX_ROUTER)
paul0c0f9cd2003-06-06 23:27:04 +0000463 {
464 while ((l = ospf_get_next_link (v, w, l)))
465 {
gdt630e4802004-08-31 17:28:41 +0000466 /* l is a link from v to w
467 * l2 will be link from w to v
468 */
paul0c0f9cd2003-06-06 23:27:04 +0000469 struct router_lsa_link *l2 = NULL;
470
gdt630e4802004-08-31 17:28:41 +0000471 if (IS_DEBUG_OSPF_EVENT)
472 {
473 char buf1[BUFSIZ];
paul1eb8ef22005-04-07 07:30:20 +0000474 char buf2[BUFSIZ];
475
ajs2a42e282004-12-08 18:43:03 +0000476 zlog_debug("ospf_nexthop_calculation(): considering link "
gdt630e4802004-08-31 17:28:41 +0000477 "type %d link_id %s link_data %s",
478 l->m[0].type,
479 inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ),
paul1eb8ef22005-04-07 07:30:20 +0000480 inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ));
gdt630e4802004-08-31 17:28:41 +0000481 }
482
paul0c0f9cd2003-06-06 23:27:04 +0000483 if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT)
484 {
gdt630e4802004-08-31 17:28:41 +0000485 /* If the destination is a router which connects to
486 the calculating router via a Point-to-MultiPoint
487 network, the destination's next hop IP address(es)
488 can be determined by examining the destination's
489 router-LSA: each link pointing back to the
490 calculating router and having a Link Data field
491 belonging to the Point-to-MultiPoint network
492 provides an IP address of the next hop router.
493
494 At this point l is a link from V to W, and V is the
495 root ("us"). Find the local interface associated
496 with l (its address is in l->link_data). If it
497 is a point-to-multipoint interface, then look through
498 the links in the opposite direction (W to V). If
499 any of them have an address that lands within the
500 subnet declared by the PtMP link, then that link
501 is a constituent of the PtMP link, and its address is
502 a nexthop address for V.
503 */
paul68980082003-03-25 05:07:42 +0000504 oi = ospf_if_is_configured (area->ospf, &l->link_data);
paul7afa08d2002-12-13 20:59:45 +0000505 if (oi && oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
paul0c0f9cd2003-06-06 23:27:04 +0000506 {
507 struct prefix_ipv4 la;
gdt630e4802004-08-31 17:28:41 +0000508
509 la.family = AF_INET;
paul0c0f9cd2003-06-06 23:27:04 +0000510 la.prefixlen = oi->address->prefixlen;
gdt630e4802004-08-31 17:28:41 +0000511
512 /* V links to W on PtMP interface
513 - find the interface address on W */
paul0c0f9cd2003-06-06 23:27:04 +0000514 while ((l2 = ospf_get_next_link (w, v, l2)))
515 {
516 la.prefix = l2->link_data;
517
518 if (prefix_cmp ((struct prefix *) &la,
519 oi->address) == 0)
520 /* link_data is on our PtMP network */
521 break;
522 }
gdt630e4802004-08-31 17:28:41 +0000523 } /* end l is on point-to-multipoint link */
paul0c0f9cd2003-06-06 23:27:04 +0000524 else
525 {
gdt630e4802004-08-31 17:28:41 +0000526 /* l is a regular point-to-point link.
527 Look for a link from W to V.
528 */
paul0c0f9cd2003-06-06 23:27:04 +0000529 while ((l2 = ospf_get_next_link (w, v, l2)))
530 {
531 oi = ospf_if_is_configured (area->ospf,
532 &(l2->link_data));
533
534 if (oi == NULL)
535 continue;
536
537 if (!IPV4_ADDR_SAME (&oi->address->u.prefix4,
538 &l->link_data))
539 continue;
540
541 break;
542 }
543 }
544
545 if (oi && l2)
546 {
gdt630e4802004-08-31 17:28:41 +0000547 /* found all necessary info to build nexthop */
paul0c0f9cd2003-06-06 23:27:04 +0000548 nh = vertex_nexthop_new (v);
549 nh->oi = oi;
550 nh->router = l2->link_data;
551 ospf_spf_consider_nexthop (w->nexthop, nh);
552 }
gdt630e4802004-08-31 17:28:41 +0000553 else
554 {
555 zlog_info("ospf_nexthop_calculation(): "
556 "could not determine nexthop for link");
557 }
558 } /* end point-to-point link from V to W */
559 } /* end iterate over links in W */
560 } /* end W is a Router vertex */
paul718e3742002-12-13 20:15:29 +0000561 else
paul0c0f9cd2003-06-06 23:27:04 +0000562 {
gdt630e4802004-08-31 17:28:41 +0000563 assert(w->type == OSPF_VERTEX_NETWORK);
paul0c0f9cd2003-06-06 23:27:04 +0000564 while ((l = ospf_get_next_link (v, w, l)))
565 {
566 oi = ospf_if_is_configured (area->ospf, &(l->link_data));
567 if (oi)
568 {
569 nh = vertex_nexthop_new (v);
570 nh->oi = oi;
571 nh->router.s_addr = 0;
paul75ee0b82004-08-05 09:10:31 +0000572 ospf_spf_consider_nexthop (w->nexthop, nh);
paul0c0f9cd2003-06-06 23:27:04 +0000573 }
574 }
575 }
paul718e3742002-12-13 20:15:29 +0000576 return;
gdt630e4802004-08-31 17:28:41 +0000577 } /* end V is the root */
578
579 /* Check if W's parent is a network connected to root. */
paul718e3742002-12-13 20:15:29 +0000580 else if (v->type == OSPF_VERTEX_NETWORK)
581 {
gdt630e4802004-08-31 17:28:41 +0000582 /* See if any of V's parents are the root. */
paul1eb8ef22005-04-07 07:30:20 +0000583 for (ALL_LIST_ELEMENTS (v->nexthop, node, nnode, x))
paul718e3742002-12-13 20:15:29 +0000584 {
gdt630e4802004-08-31 17:28:41 +0000585 if (x->parent == area->spf) /* connects to root? */
586 {
587 /* 16.1.1 para 5. ...the parent vertex is a network that
588 * directly connects the calculating router to the destination
589 * router. The list of next hops is then determined by
590 * examining the destination's router-LSA...
591 */
592
593 assert(w->type == OSPF_VERTEX_ROUTER);
paul0c0f9cd2003-06-06 23:27:04 +0000594 while ((l = ospf_get_next_link (w, v, l)))
595 {
gdt630e4802004-08-31 17:28:41 +0000596 /* ...For each link in the router-LSA that points back to the
597 * parent network, the link's Link Data field provides the IP
598 * address of a next hop router. The outgoing interface to
599 * use can then be derived from the next hop IP address (or
600 * it can be inherited from the parent network).
601 */
paul0c0f9cd2003-06-06 23:27:04 +0000602 nh = vertex_nexthop_new (v);
603 nh->oi = x->oi;
604 nh->router = l->link_data;
paul75ee0b82004-08-05 09:10:31 +0000605 ospf_spf_consider_nexthop (w->nexthop, nh);
paul0c0f9cd2003-06-06 23:27:04 +0000606 }
607 return;
608 }
paul718e3742002-12-13 20:15:29 +0000609 }
610 }
611
gdt630e4802004-08-31 17:28:41 +0000612 /* 16.1.1 para 4. If there is at least one intervening router in the
613 * current shortest path between the destination and the root, the
614 * destination simply inherits the set of next hops from the
615 * parent.
616 */
paul1eb8ef22005-04-07 07:30:20 +0000617 for (ALL_LIST_ELEMENTS (v->nexthop, node, nnode, nh))
paul718e3742002-12-13 20:15:29 +0000618 {
paul718e3742002-12-13 20:15:29 +0000619 nh->parent = v;
620 ospf_nexthop_add_unique (nh, w->nexthop);
621 }
622}
623
gdt630e4802004-08-31 17:28:41 +0000624/* RFC2328 Section 16.1 (2).
625 * v is on the SPF tree. Examine the links in v's LSA. Update the list
626 * of candidates with any vertices not already on the list. If a lower-cost
627 * path is found to a vertex already on the candidate list, store the new cost.
628 */
paul4dadc292005-05-06 21:37:42 +0000629static void
paul718e3742002-12-13 20:15:29 +0000630ospf_spf_next (struct vertex *v, struct ospf_area *area,
hasso462f20d2005-02-23 11:29:02 +0000631 struct pqueue * candidate)
paul718e3742002-12-13 20:15:29 +0000632{
633 struct ospf_lsa *w_lsa = NULL;
paul718e3742002-12-13 20:15:29 +0000634 u_char *p;
635 u_char *lim;
636 struct router_lsa_link *l = NULL;
637 struct in_addr *r;
paul718e3742002-12-13 20:15:29 +0000638 int type = 0;
639
640 /* If this is a router-LSA, and bit V of the router-LSA (see Section
641 A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE. */
642 if (v->type == OSPF_VERTEX_ROUTER)
643 {
644 if (IS_ROUTER_LSA_VIRTUAL ((struct router_lsa *) v->lsa))
645 area->transit = OSPF_TRANSIT_TRUE;
646 }
647
648 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul0c0f9cd2003-06-06 23:27:04 +0000649 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
650
paul718e3742002-12-13 20:15:29 +0000651 while (p < lim)
652 {
paul7461d452005-06-13 13:57:16 +0000653 struct vertex *w, *cw;
654
pauld355bfa2004-04-08 07:43:45 +0000655 int link = -1; /* link index for w's back link */
656
paul718e3742002-12-13 20:15:29 +0000657 /* In case of V is Router-LSA. */
658 if (v->lsa->type == OSPF_ROUTER_LSA)
659 {
660 l = (struct router_lsa_link *) p;
661
paul0c0f9cd2003-06-06 23:27:04 +0000662 p += (ROUTER_LSA_MIN_SIZE +
paul718e3742002-12-13 20:15:29 +0000663 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
664
665 /* (a) If this is a link to a stub network, examine the next
666 link in V's LSA. Links to stub networks will be
667 considered in the second stage of the shortest path
668 calculation. */
669 if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB)
670 continue;
671
672 /* (b) Otherwise, W is a transit vertex (router or transit
673 network). Look up the vertex W's LSA (router-LSA or
674 network-LSA) in Area A's link state database. */
675 switch (type)
676 {
677 case LSA_LINK_TYPE_POINTOPOINT:
678 case LSA_LINK_TYPE_VIRTUALLINK:
679 if (type == LSA_LINK_TYPE_VIRTUALLINK)
paul0c0f9cd2003-06-06 23:27:04 +0000680 {
681 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000682 zlog_debug ("looking up LSA through VL: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000683 inet_ntoa (l->link_id));
684 }
paul718e3742002-12-13 20:15:29 +0000685
686 w_lsa = ospf_lsa_lookup (area, OSPF_ROUTER_LSA, l->link_id,
687 l->link_id);
688 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000689 {
690 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000691 zlog_debug ("found Router LSA %s", inet_ntoa (l->link_id));
paul0c0f9cd2003-06-06 23:27:04 +0000692 }
paul718e3742002-12-13 20:15:29 +0000693 break;
694 case LSA_LINK_TYPE_TRANSIT:
paul0c0f9cd2003-06-06 23:27:04 +0000695 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000696 zlog_debug ("Looking up Network LSA, ID: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000697 inet_ntoa (l->link_id));
paul718e3742002-12-13 20:15:29 +0000698 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_NETWORK_LSA,
paul0c0f9cd2003-06-06 23:27:04 +0000699 l->link_id);
paul718e3742002-12-13 20:15:29 +0000700 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000701 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000702 zlog_debug ("found the LSA");
paul718e3742002-12-13 20:15:29 +0000703 break;
704 default:
paul0c0f9cd2003-06-06 23:27:04 +0000705 zlog_warn ("Invalid LSA link type %d", type);
paul718e3742002-12-13 20:15:29 +0000706 continue;
707 }
708 }
709 else
710 {
711 /* In case of V is Network-LSA. */
paul0c0f9cd2003-06-06 23:27:04 +0000712 r = (struct in_addr *) p;
paul718e3742002-12-13 20:15:29 +0000713 p += sizeof (struct in_addr);
714
715 /* Lookup the vertex W's LSA. */
716 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_ROUTER_LSA, *r);
717 }
718
719 /* (b cont.) If the LSA does not exist, or its LS age is equal
720 to MaxAge, or it does not have a link back to vertex V,
721 examine the next link in V's LSA.[23] */
722 if (w_lsa == NULL)
723 continue;
724
725 if (IS_LSA_MAXAGE (w_lsa))
726 continue;
727
pauld355bfa2004-04-08 07:43:45 +0000728 if ( (link = ospf_lsa_has_link (w_lsa->data, v->lsa)) < 0 )
paul718e3742002-12-13 20:15:29 +0000729 {
paul0c0f9cd2003-06-06 23:27:04 +0000730 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000731 zlog_debug ("The LSA doesn't have a link back");
paul718e3742002-12-13 20:15:29 +0000732 continue;
733 }
734
735 /* (c) If vertex W is already on the shortest-path tree, examine
736 the next link in the LSA. */
hasso462f20d2005-02-23 11:29:02 +0000737 if (w_lsa->stat == LSA_SPF_IN_SPFTREE)
738 {
739 if (IS_DEBUG_OSPF_EVENT)
740 zlog_debug ("The LSA is already in SPF");
741 continue;
742 }
paul718e3742002-12-13 20:15:29 +0000743
744 /* (d) Calculate the link state cost D of the resulting path
745 from the root to vertex W. D is equal to the sum of the link
746 state cost of the (already calculated) shortest path to
747 vertex V and the advertised cost of the link between vertices
748 V and W. If D is: */
749
750 /* prepare vertex W. */
751 w = ospf_vertex_new (w_lsa);
752
pauld355bfa2004-04-08 07:43:45 +0000753 /* Save W's back link index number, for use by virtual links */
754 w->backlink = link;
755
paul718e3742002-12-13 20:15:29 +0000756 /* calculate link cost D. */
757 if (v->lsa->type == OSPF_ROUTER_LSA)
gdt630e4802004-08-31 17:28:41 +0000758 w->distance = v->distance + ntohs (l->m[0].metric);
759 else /* v is not a Router-LSA */
760 w->distance = v->distance;
paul718e3742002-12-13 20:15:29 +0000761
762 /* Is there already vertex W in candidate list? */
hasso462f20d2005-02-23 11:29:02 +0000763 if (w_lsa->stat == LSA_SPF_NOT_EXPLORED)
764 {
765 /* Calculate nexthop to W. */
766 ospf_nexthop_calculation (area, v, w);
767 pqueue_enqueue (w, candidate);
768 }
769 else if (w_lsa->stat >= 0)
770 {
771 /* Get the vertex from candidates. */
772 cw = (struct vertex *) candidate->array[w_lsa->stat];
paul718e3742002-12-13 20:15:29 +0000773
hasso462f20d2005-02-23 11:29:02 +0000774 /* if D is greater than. */
775 if (cw->distance < w->distance)
paul718e3742002-12-13 20:15:29 +0000776 {
777 ospf_vertex_free (w);
778 continue;
779 }
hasso462f20d2005-02-23 11:29:02 +0000780 /* equal to. */
781 else if (cw->distance == w->distance)
paul718e3742002-12-13 20:15:29 +0000782 {
gdt630e4802004-08-31 17:28:41 +0000783 /* Found an equal-cost path to W. Calculate nexthop to W. */
paul718e3742002-12-13 20:15:29 +0000784 ospf_nexthop_calculation (area, v, w);
785 ospf_nexthop_merge (cw->nexthop, w->nexthop);
786 list_delete_all_node (w->nexthop);
787 ospf_vertex_free (w);
788 }
hasso462f20d2005-02-23 11:29:02 +0000789 /* less than. */
790 else
paul718e3742002-12-13 20:15:29 +0000791 {
gdt630e4802004-08-31 17:28:41 +0000792 /* Found a lower-cost path to W. Calculate nexthop to W. */
paul718e3742002-12-13 20:15:29 +0000793 ospf_nexthop_calculation (area, v, w);
794
795 /* Remove old vertex from candidate list. */
796 ospf_vertex_free (cw);
hasso462f20d2005-02-23 11:29:02 +0000797 candidate->array[w_lsa->stat] = w;
798 /* Decrease the key of the node in the heap, re-sort the heap. */
799 trickle_down (w_lsa->stat, candidate);
paul718e3742002-12-13 20:15:29 +0000800 }
gdt630e4802004-08-31 17:28:41 +0000801 } /* end W is already on the candidate list */
802 } /* end loop over the links in V's LSA */
paul718e3742002-12-13 20:15:29 +0000803}
804
paul4dadc292005-05-06 21:37:42 +0000805static void
paul718e3742002-12-13 20:15:29 +0000806ospf_spf_route_free (struct route_table *table)
807{
808 struct route_node *rn;
809 struct vertex *v;
810
811 for (rn = route_top (table); rn; rn = route_next (rn))
812 {
813 if ((v = rn->info))
paul0c0f9cd2003-06-06 23:27:04 +0000814 {
815 ospf_vertex_free (v);
816 rn->info = NULL;
817 }
paul718e3742002-12-13 20:15:29 +0000818
819 route_unlock_node (rn);
820 }
821
822 route_table_finish (table);
823}
824
paul4dadc292005-05-06 21:37:42 +0000825static void
paul718e3742002-12-13 20:15:29 +0000826ospf_spf_dump (struct vertex *v, int i)
827{
hasso52dc7ee2004-09-23 19:18:23 +0000828 struct listnode *cnode;
829 struct listnode *nnode;
paul718e3742002-12-13 20:15:29 +0000830 struct vertex_nexthop *nexthop;
831
832 if (v->type == OSPF_VERTEX_ROUTER)
833 {
834 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000835 zlog_debug ("SPF Result: %d [R] %s", i, inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000836 }
837 else
838 {
839 struct network_lsa *lsa = (struct network_lsa *) v->lsa;
840 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000841 zlog_debug ("SPF Result: %d [N] %s/%d", i, inet_ntoa (v->lsa->id),
paul0c0f9cd2003-06-06 23:27:04 +0000842 ip_masklen (lsa->mask));
gdt630e4802004-08-31 17:28:41 +0000843 }
paul718e3742002-12-13 20:15:29 +0000844
paul1eb8ef22005-04-07 07:30:20 +0000845 if (IS_DEBUG_OSPF_EVENT)
846 for (ALL_LIST_ELEMENTS_RO (v->nexthop, nnode, nexthop))
847 zlog_debug (" nexthop %s", inet_ntoa (nexthop->router));
paul718e3742002-12-13 20:15:29 +0000848
849 i++;
850
paul1eb8ef22005-04-07 07:30:20 +0000851 for (ALL_LIST_ELEMENTS_RO (v->child, cnode, v))
852 ospf_spf_dump (v, i);
paul718e3742002-12-13 20:15:29 +0000853}
854
855/* Second stage of SPF calculation. */
paul4dadc292005-05-06 21:37:42 +0000856static void
paul0c0f9cd2003-06-06 23:27:04 +0000857ospf_spf_process_stubs (struct ospf_area *area, struct vertex *v,
paul718e3742002-12-13 20:15:29 +0000858 struct route_table *rt)
859{
paul1eb8ef22005-04-07 07:30:20 +0000860 struct listnode *cnode, *cnnode;
paul718e3742002-12-13 20:15:29 +0000861 struct vertex *child;
862
863 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000864 zlog_debug ("ospf_process_stub():processing stubs for area %s",
paul0c0f9cd2003-06-06 23:27:04 +0000865 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +0000866 if (v->type == OSPF_VERTEX_ROUTER)
867 {
868 u_char *p;
869 u_char *lim;
870 struct router_lsa_link *l;
871 struct router_lsa *rlsa;
872
paul0c0f9cd2003-06-06 23:27:04 +0000873 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000874 zlog_debug ("ospf_process_stubs():processing router LSA, id: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000875 inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000876 rlsa = (struct router_lsa *) v->lsa;
877
878
paul0c0f9cd2003-06-06 23:27:04 +0000879 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000880 zlog_debug ("ospf_process_stubs(): we have %d links to process",
paul0c0f9cd2003-06-06 23:27:04 +0000881 ntohs (rlsa->links));
gdt630e4802004-08-31 17:28:41 +0000882 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +0000883 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
884
885 while (p < lim)
886 {
887 l = (struct router_lsa_link *) p;
888
889 p += (ROUTER_LSA_MIN_SIZE +
890 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
891
892 if (l->m[0].type == LSA_LINK_TYPE_STUB)
893 ospf_intra_add_stub (rt, l, v, area);
894 }
895 }
896
gdt630e4802004-08-31 17:28:41 +0000897 ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1, 1);
paul718e3742002-12-13 20:15:29 +0000898
paul1eb8ef22005-04-07 07:30:20 +0000899 for (ALL_LIST_ELEMENTS (v->child, cnode, cnnode, child))
paul718e3742002-12-13 20:15:29 +0000900 {
paul718e3742002-12-13 20:15:29 +0000901 if (CHECK_FLAG (child->flags, OSPF_VERTEX_PROCESSED))
paul0c0f9cd2003-06-06 23:27:04 +0000902 continue;
paul718e3742002-12-13 20:15:29 +0000903
904 ospf_spf_process_stubs (area, child, rt);
905
906 SET_FLAG (child->flags, OSPF_VERTEX_PROCESSED);
907 }
908}
909
910void
911ospf_rtrs_free (struct route_table *rtrs)
912{
913 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +0000914 struct list *or_list;
paul1eb8ef22005-04-07 07:30:20 +0000915 struct ospf_route *or;
916 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000917
918 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000919 zlog_debug ("Route: Router Routing Table free");
paul718e3742002-12-13 20:15:29 +0000920
921 for (rn = route_top (rtrs); rn; rn = route_next (rn))
922 if ((or_list = rn->info) != NULL)
923 {
paul1eb8ef22005-04-07 07:30:20 +0000924 for (ALL_LIST_ELEMENTS (or_list, node, nnode, or))
925 ospf_route_free (or);
paul718e3742002-12-13 20:15:29 +0000926
paul0c0f9cd2003-06-06 23:27:04 +0000927 list_delete (or_list);
paul718e3742002-12-13 20:15:29 +0000928
paul0c0f9cd2003-06-06 23:27:04 +0000929 /* Unlock the node. */
930 rn->info = NULL;
931 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +0000932 }
933 route_table_finish (rtrs);
934}
935
paul4dadc292005-05-06 21:37:42 +0000936static void
paul718e3742002-12-13 20:15:29 +0000937ospf_rtrs_print (struct route_table *rtrs)
938{
939 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +0000940 struct list *or_list;
941 struct listnode *ln;
942 struct listnode *pnode;
paul718e3742002-12-13 20:15:29 +0000943 struct ospf_route *or;
944 struct ospf_path *path;
945 char buf1[BUFSIZ];
946 char buf2[BUFSIZ];
947
948 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000949 zlog_debug ("ospf_rtrs_print() start");
paul718e3742002-12-13 20:15:29 +0000950
951 for (rn = route_top (rtrs); rn; rn = route_next (rn))
952 if ((or_list = rn->info) != NULL)
paul1eb8ef22005-04-07 07:30:20 +0000953 for (ALL_LIST_ELEMENTS_RO (or_list, ln, or))
paul718e3742002-12-13 20:15:29 +0000954 {
paul718e3742002-12-13 20:15:29 +0000955 switch (or->path_type)
956 {
957 case OSPF_PATH_INTRA_AREA:
paul0c0f9cd2003-06-06 23:27:04 +0000958 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000959 zlog_debug ("%s [%d] area: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000960 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
961 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
962 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +0000963 break;
964 case OSPF_PATH_INTER_AREA:
paul0c0f9cd2003-06-06 23:27:04 +0000965 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000966 zlog_debug ("%s IA [%d] area: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000967 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
968 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
969 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +0000970 break;
971 default:
972 break;
973 }
974
paul1eb8ef22005-04-07 07:30:20 +0000975 for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path))
paul718e3742002-12-13 20:15:29 +0000976 {
paul718e3742002-12-13 20:15:29 +0000977 if (path->nexthop.s_addr == 0)
paul0c0f9cd2003-06-06 23:27:04 +0000978 {
979 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000980 zlog_debug (" directly attached to %s\r\n",
paul0c0f9cd2003-06-06 23:27:04 +0000981 IF_NAME (path->oi));
982 }
983 else
984 {
985 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000986 zlog_debug (" via %s, %s\r\n",
paul0c0f9cd2003-06-06 23:27:04 +0000987 inet_ntoa (path->nexthop), IF_NAME (path->oi));
988 }
paul718e3742002-12-13 20:15:29 +0000989 }
990 }
991
ajs2a42e282004-12-08 18:43:03 +0000992 zlog_debug ("ospf_rtrs_print() end");
paul718e3742002-12-13 20:15:29 +0000993}
994
995/* Calculating the shortest-path tree for an area. */
paul4dadc292005-05-06 21:37:42 +0000996static void
paul0c0f9cd2003-06-06 23:27:04 +0000997ospf_spf_calculate (struct ospf_area *area, struct route_table *new_table,
paul718e3742002-12-13 20:15:29 +0000998 struct route_table *new_rtrs)
999{
hasso462f20d2005-02-23 11:29:02 +00001000 struct pqueue *candidate;
paul718e3742002-12-13 20:15:29 +00001001 struct vertex *v;
paul718e3742002-12-13 20:15:29 +00001002
1003 if (IS_DEBUG_OSPF_EVENT)
1004 {
ajs2a42e282004-12-08 18:43:03 +00001005 zlog_debug ("ospf_spf_calculate: Start");
1006 zlog_debug ("ospf_spf_calculate: running Dijkstra for area %s",
paul0c0f9cd2003-06-06 23:27:04 +00001007 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001008 }
1009
1010 /* Check router-lsa-self. If self-router-lsa is not yet allocated,
1011 return this area's calculation. */
paul0c0f9cd2003-06-06 23:27:04 +00001012 if (!area->router_lsa_self)
paul718e3742002-12-13 20:15:29 +00001013 {
1014 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001015 zlog_debug ("ospf_spf_calculate: "
paul0c0f9cd2003-06-06 23:27:04 +00001016 "Skip area %s's calculation due to empty router_lsa_self",
1017 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001018 return;
1019 }
1020
1021 /* RFC2328 16.1. (1). */
paul0c0f9cd2003-06-06 23:27:04 +00001022 /* Initialize the algorithm's data structures. */
hasso462f20d2005-02-23 11:29:02 +00001023
1024 /* This function scans all the LSA database and set the stat field to
1025 * LSA_SPF_NOT_EXPLORED. */
1026 ospf_lsdb_clean_stat (area->lsdb);
1027 /* Create a new heap for the candidates. */
1028 candidate = pqueue_create();
1029 candidate->cmp = cmp;
1030 candidate->update = update_stat;
paul718e3742002-12-13 20:15:29 +00001031
1032 /* Initialize the shortest-path tree to only the root (which is the
1033 router doing the calculation). */
1034 ospf_spf_init (area);
1035 v = area->spf;
hasso462f20d2005-02-23 11:29:02 +00001036 /* Set LSA position to LSA_SPF_IN_SPFTREE. This vertex is the root of the
1037 * spanning tree. */
1038 *(v->stat) = LSA_SPF_IN_SPFTREE;
paul718e3742002-12-13 20:15:29 +00001039
1040 /* Set Area A's TransitCapability to FALSE. */
1041 area->transit = OSPF_TRANSIT_FALSE;
1042 area->shortcut_capability = 1;
1043
1044 for (;;)
1045 {
1046 /* RFC2328 16.1. (2). */
hasso462f20d2005-02-23 11:29:02 +00001047 ospf_spf_next (v, area, candidate);
paul718e3742002-12-13 20:15:29 +00001048
1049 /* RFC2328 16.1. (3). */
1050 /* If at this step the candidate list is empty, the shortest-
1051 path tree (of transit vertices) has been completely built and
1052 this stage of the procedure terminates. */
hasso462f20d2005-02-23 11:29:02 +00001053 if (candidate->size == 0)
paul718e3742002-12-13 20:15:29 +00001054 break;
1055
1056 /* Otherwise, choose the vertex belonging to the candidate list
1057 that is closest to the root, and add it to the shortest-path
1058 tree (removing it from the candidate list in the
paul0c0f9cd2003-06-06 23:27:04 +00001059 process). */
hasso462f20d2005-02-23 11:29:02 +00001060 /* Extract from the candidates the node with the lower key. */
1061 v = (struct vertex *) pqueue_dequeue (candidate);
1062 /* Update stat field in vertex. */
1063 *(v->stat) = LSA_SPF_IN_SPFTREE;
paul718e3742002-12-13 20:15:29 +00001064 ospf_vertex_add_parent (v);
1065
paul718e3742002-12-13 20:15:29 +00001066 /* Note that when there is a choice of vertices closest to the
1067 root, network vertices must be chosen before router vertices
1068 in order to necessarily find all equal-cost paths. */
1069 /* We don't do this at this moment, we should add the treatment
1070 above codes. -- kunihiro. */
1071
1072 /* RFC2328 16.1. (4). */
1073 if (v->type == OSPF_VERTEX_ROUTER)
1074 ospf_intra_add_router (new_rtrs, v, area);
paul0c0f9cd2003-06-06 23:27:04 +00001075 else
paul718e3742002-12-13 20:15:29 +00001076 ospf_intra_add_transit (new_table, v, area);
1077
1078 /* RFC2328 16.1. (5). */
1079 /* Iterate the algorithm by returning to Step 2. */
gdt630e4802004-08-31 17:28:41 +00001080
1081 } /* end loop until no more candidate vertices */
paul718e3742002-12-13 20:15:29 +00001082
1083 if (IS_DEBUG_OSPF_EVENT)
1084 {
1085 ospf_spf_dump (area->spf, 0);
1086 ospf_route_table_dump (new_table);
1087 }
1088
1089 /* Second stage of SPF calculation procedure's */
1090 ospf_spf_process_stubs (area, area->spf, new_table);
1091
hasso462f20d2005-02-23 11:29:02 +00001092 /* Free candidates. */
1093 pqueue_delete (candidate);
paul718e3742002-12-13 20:15:29 +00001094
1095 /* Increment SPF Calculation Counter. */
1096 area->spf_calculation++;
1097
paul68980082003-03-25 05:07:42 +00001098 area->ospf->ts_spf = time (NULL);
paul718e3742002-12-13 20:15:29 +00001099
1100 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001101 zlog_debug ("ospf_spf_calculate: Stop");
paul718e3742002-12-13 20:15:29 +00001102}
1103
1104/* Timer for SPF calculation. */
paul4dadc292005-05-06 21:37:42 +00001105static int
paul68980082003-03-25 05:07:42 +00001106ospf_spf_calculate_timer (struct thread *thread)
paul718e3742002-12-13 20:15:29 +00001107{
paul68980082003-03-25 05:07:42 +00001108 struct ospf *ospf = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +00001109 struct route_table *new_table, *new_rtrs;
paul1eb8ef22005-04-07 07:30:20 +00001110 struct ospf_area *area;
1111 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001112
1113 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001114 zlog_debug ("SPF: Timer (SPF calculation expire)");
paul0c0f9cd2003-06-06 23:27:04 +00001115
paul718e3742002-12-13 20:15:29 +00001116 ospf->t_spf_calc = NULL;
1117
1118 /* Allocate new table tree. */
1119 new_table = route_table_init ();
paul0c0f9cd2003-06-06 23:27:04 +00001120 new_rtrs = route_table_init ();
paul718e3742002-12-13 20:15:29 +00001121
paul68980082003-03-25 05:07:42 +00001122 ospf_vl_unapprove (ospf);
paul718e3742002-12-13 20:15:29 +00001123
1124 /* Calculate SPF for each area. */
paul1eb8ef22005-04-07 07:30:20 +00001125 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
1126 ospf_spf_calculate (area, new_table, new_rtrs);
paul718e3742002-12-13 20:15:29 +00001127
paul68980082003-03-25 05:07:42 +00001128 ospf_vl_shut_unapproved (ospf);
paul718e3742002-12-13 20:15:29 +00001129
paul68980082003-03-25 05:07:42 +00001130 ospf_ia_routing (ospf, new_table, new_rtrs);
paul718e3742002-12-13 20:15:29 +00001131
1132 ospf_prune_unreachable_networks (new_table);
1133 ospf_prune_unreachable_routers (new_rtrs);
1134
1135 /* AS-external-LSA calculation should not be performed here. */
1136
1137 /* If new Router Route is installed,
1138 then schedule re-calculate External routes. */
1139 if (1)
paul68980082003-03-25 05:07:42 +00001140 ospf_ase_calculate_schedule (ospf);
paul718e3742002-12-13 20:15:29 +00001141
paul68980082003-03-25 05:07:42 +00001142 ospf_ase_calculate_timer_add (ospf);
paul718e3742002-12-13 20:15:29 +00001143
1144 /* Update routing table. */
paul68980082003-03-25 05:07:42 +00001145 ospf_route_install (ospf, new_table);
paul718e3742002-12-13 20:15:29 +00001146
1147 /* Update ABR/ASBR routing table */
paul68980082003-03-25 05:07:42 +00001148 if (ospf->old_rtrs)
paul718e3742002-12-13 20:15:29 +00001149 {
1150 /* old_rtrs's node holds linked list of ospf_route. --kunihiro. */
paul68980082003-03-25 05:07:42 +00001151 /* ospf_route_delete (ospf->old_rtrs); */
1152 ospf_rtrs_free (ospf->old_rtrs);
paul718e3742002-12-13 20:15:29 +00001153 }
1154
paul68980082003-03-25 05:07:42 +00001155 ospf->old_rtrs = ospf->new_rtrs;
1156 ospf->new_rtrs = new_rtrs;
paul718e3742002-12-13 20:15:29 +00001157
paul0c0f9cd2003-06-06 23:27:04 +00001158 if (IS_OSPF_ABR (ospf))
paul68980082003-03-25 05:07:42 +00001159 ospf_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001160
1161 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001162 zlog_debug ("SPF: calculation complete");
paul718e3742002-12-13 20:15:29 +00001163
1164 return 0;
1165}
1166
1167/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
1168 set timer for SPF calc. */
1169void
paul68980082003-03-25 05:07:42 +00001170ospf_spf_calculate_schedule (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00001171{
1172 time_t ht, delay;
1173
1174 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001175 zlog_debug ("SPF: calculation timer scheduled");
paul718e3742002-12-13 20:15:29 +00001176
1177 /* OSPF instance does not exist. */
paul68980082003-03-25 05:07:42 +00001178 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001179 return;
1180
1181 /* SPF calculation timer is already scheduled. */
paul68980082003-03-25 05:07:42 +00001182 if (ospf->t_spf_calc)
paul718e3742002-12-13 20:15:29 +00001183 {
1184 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001185 zlog_debug ("SPF: calculation timer is already scheduled: %p",
paul0c0f9cd2003-06-06 23:27:04 +00001186 ospf->t_spf_calc);
paul718e3742002-12-13 20:15:29 +00001187 return;
1188 }
1189
paul68980082003-03-25 05:07:42 +00001190 ht = time (NULL) - ospf->ts_spf;
paul718e3742002-12-13 20:15:29 +00001191
1192 /* Get SPF calculation delay time. */
paul68980082003-03-25 05:07:42 +00001193 if (ht < ospf->spf_holdtime)
paul718e3742002-12-13 20:15:29 +00001194 {
paul68980082003-03-25 05:07:42 +00001195 if (ospf->spf_holdtime - ht < ospf->spf_delay)
paul0c0f9cd2003-06-06 23:27:04 +00001196 delay = ospf->spf_delay;
paul718e3742002-12-13 20:15:29 +00001197 else
paul0c0f9cd2003-06-06 23:27:04 +00001198 delay = ospf->spf_holdtime - ht;
paul718e3742002-12-13 20:15:29 +00001199 }
1200 else
paul68980082003-03-25 05:07:42 +00001201 delay = ospf->spf_delay;
paul718e3742002-12-13 20:15:29 +00001202
1203 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001204 zlog_debug ("SPF: calculation timer delay = %ld", (long)delay);
paul68980082003-03-25 05:07:42 +00001205 ospf->t_spf_calc =
1206 thread_add_timer (master, ospf_spf_calculate_timer, ospf, delay);
paul718e3742002-12-13 20:15:29 +00001207}