blob: cd5ebb1631ba07169e486c95a05605615a40067d [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
Paul Jakma9c27ef92006-05-04 07:32:57 +000049static void ospf_vertex_free (void *);
50/* List of allocated vertices, to simplify cleanup of SPF.
51 * Not thread-safe obviously. If it ever needs to be, it'd have to be
52 * dynamically allocated at begin of ospf_spf_calculate
53 */
54static struct list vertex_list = { .del = ospf_vertex_free };
55
hasso462f20d2005-02-23 11:29:02 +000056/* Heap related functions, for the managment of the candidates, to
57 * be used with pqueue. */
58static int
59cmp (void * node1 , void * node2)
60{
61 struct vertex * v1 = (struct vertex *) node1;
62 struct vertex * v2 = (struct vertex *) node2;
63 if (v1 != NULL && v2 != NULL )
Paul Jakma9c27ef92006-05-04 07:32:57 +000064 {
65 /* network vertices must be chosen before router vertices of same
66 * cost in order to find all shortest paths
67 */
68 if ( ((v1->distance - v2->distance) == 0)
69 && (v1->type != v2->type))
70 {
71 switch (v1->type)
72 {
73 case OSPF_VERTEX_NETWORK:
74 return -1;
75 case OSPF_VERTEX_ROUTER:
76 return 1;
77 }
78 }
79 else
80 return (v1->distance - v2->distance);
81 }
82 return 0;
hasso462f20d2005-02-23 11:29:02 +000083}
84
85static void
pauleb3da6d2005-10-18 04:20:33 +000086update_stat (void *node , int position)
hasso462f20d2005-02-23 11:29:02 +000087{
pauleb3da6d2005-10-18 04:20:33 +000088 struct vertex *v = node;
89
hasso462f20d2005-02-23 11:29:02 +000090 /* Set the status of the vertex, when its position changes. */
91 *(v->stat) = position;
92}
pauleb3da6d2005-10-18 04:20:33 +000093
paul4dadc292005-05-06 21:37:42 +000094static struct vertex_nexthop *
pauleb3da6d2005-10-18 04:20:33 +000095vertex_nexthop_new (void)
paul718e3742002-12-13 20:15:29 +000096{
pauleb3da6d2005-10-18 04:20:33 +000097 return XCALLOC (MTYPE_OSPF_NEXTHOP, sizeof (struct vertex_nexthop));
paul718e3742002-12-13 20:15:29 +000098}
99
paul4dadc292005-05-06 21:37:42 +0000100static void
paul718e3742002-12-13 20:15:29 +0000101vertex_nexthop_free (struct vertex_nexthop *nh)
102{
103 XFREE (MTYPE_OSPF_NEXTHOP, nh);
104}
105
pauleb3da6d2005-10-18 04:20:33 +0000106/* Free the canonical nexthop objects for an area, ie the nexthop objects
Paul Jakma9c27ef92006-05-04 07:32:57 +0000107 * attached to the first-hop router vertices, and any intervening network
108 * vertices.
pauleb3da6d2005-10-18 04:20:33 +0000109 */
110static void
111ospf_canonical_nexthops_free (struct vertex *root)
paul718e3742002-12-13 20:15:29 +0000112{
pauleb3da6d2005-10-18 04:20:33 +0000113 struct listnode *node, *nnode;
114 struct vertex *child;
115
116 for (ALL_LIST_ELEMENTS (root->children, node, nnode, child))
117 {
118 struct listnode *n2, *nn2;
119 struct vertex_parent *vp;
120
paul58e1bef2005-11-11 12:10:03 +0000121 /* router vertices through an attached network each
122 * have a distinct (canonical / not inherited) nexthop
123 * which must be freed.
124 *
125 * A network vertex can only have router vertices as its
126 * children, so only one level of recursion is possible.
127 */
pauleb3da6d2005-10-18 04:20:33 +0000128 if (child->type == OSPF_VERTEX_NETWORK)
129 ospf_canonical_nexthops_free (child);
130
paul58e1bef2005-11-11 12:10:03 +0000131 /* Free child nexthops pointing back to this root vertex */
pauleb3da6d2005-10-18 04:20:33 +0000132 for (ALL_LIST_ELEMENTS (child->parents, n2, nn2, vp))
Paul Jakma9c27ef92006-05-04 07:32:57 +0000133 if (vp->parent == root && vp->nexthop)
paul58e1bef2005-11-11 12:10:03 +0000134 vertex_nexthop_free (vp->nexthop);
pauleb3da6d2005-10-18 04:20:33 +0000135 }
136}
137
Paul Jakma9c27ef92006-05-04 07:32:57 +0000138/* TODO: Parent list should be excised, in favour of maintaining only
139 * vertex_nexthop, with refcounts.
140 */
pauleb3da6d2005-10-18 04:20:33 +0000141static struct vertex_parent *
142vertex_parent_new (struct vertex *v, int backlink, struct vertex_nexthop *hop)
143{
144 struct vertex_parent *new;
145
146 new = XMALLOC (MTYPE_OSPF_VERTEX_PARENT, sizeof (struct vertex_parent));
147
148 if (new == NULL)
149 return NULL;
150
151 new->parent = v;
152 new->backlink = backlink;
153 new->nexthop = hop;
paul718e3742002-12-13 20:15:29 +0000154 return new;
155}
paul0c0f9cd2003-06-06 23:27:04 +0000156
pauleb3da6d2005-10-18 04:20:33 +0000157static void
Paul Jakma9c27ef92006-05-04 07:32:57 +0000158vertex_parent_free (void *p)
pauleb3da6d2005-10-18 04:20:33 +0000159{
160 XFREE (MTYPE_OSPF_VERTEX_PARENT, p);
161}
162
paul4dadc292005-05-06 21:37:42 +0000163static struct vertex *
paul718e3742002-12-13 20:15:29 +0000164ospf_vertex_new (struct ospf_lsa *lsa)
165{
166 struct vertex *new;
167
pauleb3da6d2005-10-18 04:20:33 +0000168 new = XCALLOC (MTYPE_OSPF_VERTEX, sizeof (struct vertex));
paul718e3742002-12-13 20:15:29 +0000169
170 new->flags = 0;
hasso462f20d2005-02-23 11:29:02 +0000171 new->stat = &(lsa->stat);
paul718e3742002-12-13 20:15:29 +0000172 new->type = lsa->data->type;
173 new->id = lsa->data->id;
174 new->lsa = lsa->data;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000175 new->distance = OSPF_OUTPUT_COST_INFINITE;
pauleb3da6d2005-10-18 04:20:33 +0000176 new->children = list_new ();
177 new->parents = list_new ();
Paul Jakma9c27ef92006-05-04 07:32:57 +0000178 new->parents->del = vertex_parent_free;
pauleb3da6d2005-10-18 04:20:33 +0000179
Paul Jakma9c27ef92006-05-04 07:32:57 +0000180 listnode_add (&vertex_list, new);
181
182 if (IS_DEBUG_OSPF_EVENT)
183 zlog_debug ("%s: Created %s vertex %s", __func__,
184 new->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
185 inet_ntoa (new->lsa->id));
paul718e3742002-12-13 20:15:29 +0000186 return new;
187}
188
paul4dadc292005-05-06 21:37:42 +0000189static void
Paul Jakma9c27ef92006-05-04 07:32:57 +0000190ospf_vertex_free (void *data)
paul718e3742002-12-13 20:15:29 +0000191{
Paul Jakma9c27ef92006-05-04 07:32:57 +0000192 struct vertex *v = data;
paul7461d452005-06-13 13:57:16 +0000193
Paul Jakma9c27ef92006-05-04 07:32:57 +0000194 if (IS_DEBUG_OSPF_EVENT)
195 zlog_debug ("%s: Free %s vertex %s", __func__,
196 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
197 inet_ntoa (v->lsa->id));
pauleb3da6d2005-10-18 04:20:33 +0000198
Paul Jakma9c27ef92006-05-04 07:32:57 +0000199 /* There should be no parents potentially holding references to this vertex
200 * Children however may still be there, but presumably referenced by other
201 * vertices
pauleb3da6d2005-10-18 04:20:33 +0000202 */
Paul Jakma9c27ef92006-05-04 07:32:57 +0000203 //assert (listcount (v->parents) == 0);
pauleb3da6d2005-10-18 04:20:33 +0000204
Paul Jakma9c27ef92006-05-04 07:32:57 +0000205 if (v->children)
206 list_delete (v->children);
207 v->children = NULL;
208
209 if (v->parents)
210 list_delete (v->parents);
pauleb3da6d2005-10-18 04:20:33 +0000211 v->parents = NULL;
212
213 v->lsa = NULL;
paul7461d452005-06-13 13:57:16 +0000214
paul718e3742002-12-13 20:15:29 +0000215 XFREE (MTYPE_OSPF_VERTEX, v);
216}
217
paul4dadc292005-05-06 21:37:42 +0000218static void
hassoeb1ce602004-10-08 08:17:22 +0000219ospf_vertex_dump(const char *msg, struct vertex *v,
pauleb3da6d2005-10-18 04:20:33 +0000220 int print_parents, int print_children)
gdt630e4802004-08-31 17:28:41 +0000221{
222 if ( ! IS_DEBUG_OSPF_EVENT)
223 return;
224
pauleb3da6d2005-10-18 04:20:33 +0000225 zlog_debug("%s %s vertex %s distance %u flags %u",
gdt630e4802004-08-31 17:28:41 +0000226 msg,
227 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
228 inet_ntoa(v->lsa->id),
229 v->distance,
gdt630e4802004-08-31 17:28:41 +0000230 (unsigned int)v->flags);
231
pauleb3da6d2005-10-18 04:20:33 +0000232 if (print_parents)
gdt630e4802004-08-31 17:28:41 +0000233 {
paul1eb8ef22005-04-07 07:30:20 +0000234 struct listnode *node;
pauleb3da6d2005-10-18 04:20:33 +0000235 struct vertex_parent *vp;
paul1eb8ef22005-04-07 07:30:20 +0000236
pauleb3da6d2005-10-18 04:20:33 +0000237 for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
gdt630e4802004-08-31 17:28:41 +0000238 {
239 char buf1[BUFSIZ];
pauleb3da6d2005-10-18 04:20:33 +0000240
241 if (vp)
gdt630e4802004-08-31 17:28:41 +0000242 {
pauleb3da6d2005-10-18 04:20:33 +0000243 zlog_debug ("parent %s backlink %d nexthop %s interface %s",
244 inet_ntoa(vp->parent->lsa->id), vp->backlink,
245 inet_ntop(AF_INET, &vp->nexthop->router, buf1, BUFSIZ),
246 vp->nexthop->oi ? IF_NAME(vp->nexthop->oi) : "NULL");
gdt630e4802004-08-31 17:28:41 +0000247 }
248 }
249 }
250
251 if (print_children)
252 {
hasso52dc7ee2004-09-23 19:18:23 +0000253 struct listnode *cnode;
paul1eb8ef22005-04-07 07:30:20 +0000254 struct vertex *cv;
255
pauleb3da6d2005-10-18 04:20:33 +0000256 for (ALL_LIST_ELEMENTS_RO (v->children, cnode, cv))
paul1eb8ef22005-04-07 07:30:20 +0000257 ospf_vertex_dump(" child:", cv, 0, 0);
gdt630e4802004-08-31 17:28:41 +0000258 }
259}
260
261
262/* Add a vertex to the list of children in each of its parents. */
paul4dadc292005-05-06 21:37:42 +0000263static void
paul718e3742002-12-13 20:15:29 +0000264ospf_vertex_add_parent (struct vertex *v)
265{
pauleb3da6d2005-10-18 04:20:33 +0000266 struct vertex_parent *vp;
hasso52dc7ee2004-09-23 19:18:23 +0000267 struct listnode *node;
paul7461d452005-06-13 13:57:16 +0000268
Paul Jakma9c27ef92006-05-04 07:32:57 +0000269 assert (v && v->parents);
paul7461d452005-06-13 13:57:16 +0000270
pauleb3da6d2005-10-18 04:20:33 +0000271 for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
paul718e3742002-12-13 20:15:29 +0000272 {
pauleb3da6d2005-10-18 04:20:33 +0000273 assert (vp->parent && vp->parent->children);
paul7461d452005-06-13 13:57:16 +0000274
paul718e3742002-12-13 20:15:29 +0000275 /* No need to add two links from the same parent. */
pauleb3da6d2005-10-18 04:20:33 +0000276 if (listnode_lookup (vp->parent->children, v) == NULL)
277 listnode_add (vp->parent->children, v);
paul718e3742002-12-13 20:15:29 +0000278 }
279}
280
paul4dadc292005-05-06 21:37:42 +0000281static void
paul718e3742002-12-13 20:15:29 +0000282ospf_spf_init (struct ospf_area *area)
283{
284 struct vertex *v;
Paul Jakma9c27ef92006-05-04 07:32:57 +0000285
paul718e3742002-12-13 20:15:29 +0000286 /* Create root node. */
287 v = ospf_vertex_new (area->router_lsa_self);
Paul Jakmabd34fb32007-02-26 17:14:48 +0000288 v->distance = 0;
289
paul718e3742002-12-13 20:15:29 +0000290 area->spf = v;
291
292 /* Reset ABR and ASBR router counts. */
293 area->abr_count = 0;
294 area->asbr_count = 0;
295}
296
pauld355bfa2004-04-08 07:43:45 +0000297/* return index of link back to V from W, or -1 if no link found */
paul4dadc292005-05-06 21:37:42 +0000298static int
paul718e3742002-12-13 20:15:29 +0000299ospf_lsa_has_link (struct lsa_header *w, struct lsa_header *v)
300{
hassoeb1ce602004-10-08 08:17:22 +0000301 unsigned int i, length;
paul718e3742002-12-13 20:15:29 +0000302 struct router_lsa *rl;
303 struct network_lsa *nl;
304
305 /* In case of W is Network LSA. */
306 if (w->type == OSPF_NETWORK_LSA)
307 {
308 if (v->type == OSPF_NETWORK_LSA)
pauld355bfa2004-04-08 07:43:45 +0000309 return -1;
paul718e3742002-12-13 20:15:29 +0000310
311 nl = (struct network_lsa *) w;
312 length = (ntohs (w->length) - OSPF_LSA_HEADER_SIZE - 4) / 4;
paul0c0f9cd2003-06-06 23:27:04 +0000313
paul718e3742002-12-13 20:15:29 +0000314 for (i = 0; i < length; i++)
315 if (IPV4_ADDR_SAME (&nl->routers[i], &v->id))
pauld355bfa2004-04-08 07:43:45 +0000316 return i;
317 return -1;
paul718e3742002-12-13 20:15:29 +0000318 }
319
320 /* In case of W is Router LSA. */
321 if (w->type == OSPF_ROUTER_LSA)
322 {
323 rl = (struct router_lsa *) w;
324
325 length = ntohs (w->length);
326
327 for (i = 0;
paul0c0f9cd2003-06-06 23:27:04 +0000328 i < ntohs (rl->links) && length >= sizeof (struct router_lsa);
329 i++, length -= 12)
paul718e3742002-12-13 20:15:29 +0000330 {
331 switch (rl->link[i].type)
332 {
333 case LSA_LINK_TYPE_POINTOPOINT:
334 case LSA_LINK_TYPE_VIRTUALLINK:
335 /* Router LSA ID. */
336 if (v->type == OSPF_ROUTER_LSA &&
337 IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
338 {
pauld355bfa2004-04-08 07:43:45 +0000339 return i;
paul718e3742002-12-13 20:15:29 +0000340 }
341 break;
342 case LSA_LINK_TYPE_TRANSIT:
343 /* Network LSA ID. */
344 if (v->type == OSPF_NETWORK_LSA &&
345 IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
346 {
pauld355bfa2004-04-08 07:43:45 +0000347 return i;
paul0c0f9cd2003-06-06 23:27:04 +0000348 }
paul718e3742002-12-13 20:15:29 +0000349 break;
350 case LSA_LINK_TYPE_STUB:
pauleb3da6d2005-10-18 04:20:33 +0000351 /* Stub can't lead anywhere, carry on */
paul718e3742002-12-13 20:15:29 +0000352 continue;
353 default:
354 break;
355 }
356 }
357 }
pauld355bfa2004-04-08 07:43:45 +0000358 return -1;
paul718e3742002-12-13 20:15:29 +0000359}
360
paul718e3742002-12-13 20:15:29 +0000361#define ROUTER_LSA_MIN_SIZE 12
362#define ROUTER_LSA_TOS_SIZE 4
363
gdt630e4802004-08-31 17:28:41 +0000364/* Find the next link after prev_link from v to w. If prev_link is
365 * NULL, return the first link from v to w. Ignore stub and virtual links;
366 * these link types will never be returned.
367 */
paul4dadc292005-05-06 21:37:42 +0000368static struct router_lsa_link *
paul718e3742002-12-13 20:15:29 +0000369ospf_get_next_link (struct vertex *v, struct vertex *w,
paul0c0f9cd2003-06-06 23:27:04 +0000370 struct router_lsa_link *prev_link)
paul718e3742002-12-13 20:15:29 +0000371{
372 u_char *p;
373 u_char *lim;
374 struct router_lsa_link *l;
375
376 if (prev_link == NULL)
gdt630e4802004-08-31 17:28:41 +0000377 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +0000378 else
379 {
paul0c0f9cd2003-06-06 23:27:04 +0000380 p = (u_char *) prev_link;
paul718e3742002-12-13 20:15:29 +0000381 p += (ROUTER_LSA_MIN_SIZE +
382 (prev_link->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
383 }
paul0c0f9cd2003-06-06 23:27:04 +0000384
paul718e3742002-12-13 20:15:29 +0000385 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
386
387 while (p < lim)
388 {
389 l = (struct router_lsa_link *) p;
390
paul0c0f9cd2003-06-06 23:27:04 +0000391 p += (ROUTER_LSA_MIN_SIZE + (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
paul718e3742002-12-13 20:15:29 +0000392
393 if (l->m[0].type == LSA_LINK_TYPE_STUB)
394 continue;
395
396 /* Defer NH calculation via VLs until summaries from
397 transit areas area confidered */
398
399 if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK)
paul0c0f9cd2003-06-06 23:27:04 +0000400 continue;
paul718e3742002-12-13 20:15:29 +0000401
402 if (IPV4_ADDR_SAME (&l->link_id, &w->id))
paul0c0f9cd2003-06-06 23:27:04 +0000403 return l;
paul718e3742002-12-13 20:15:29 +0000404 }
405
406 return NULL;
407}
408
pauleb3da6d2005-10-18 04:20:33 +0000409static void
410ospf_spf_flush_parents (struct vertex *w)
411{
412 struct vertex_parent *vp;
413 struct listnode *ln, *nn;
414
415 /* delete the existing nexthops */
416 for (ALL_LIST_ELEMENTS (w->parents, ln, nn, vp))
417 {
418 list_delete_node (w->parents, ln);
419 vertex_parent_free (vp);
420 }
421}
422
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000423/*
424 * Consider supplied next-hop for inclusion to the supplied list of
425 * equal-cost next-hops, adjust list as neccessary.
426 */
427static void
428ospf_spf_add_parent (struct vertex *v, struct vertex *w,
429 struct vertex_nexthop *newhop,
Paul Jakmabd34fb32007-02-26 17:14:48 +0000430 unsigned int distance)
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000431{
432 struct vertex_parent *vp;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000433
434 /* we must have a newhop.. */
Paul Jakmabd34fb32007-02-26 17:14:48 +0000435 assert (v && w && newhop);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000436
437 /* We shouldn't get here unless callers have determined V(l)->W is
438 * shortest / equal-shortest path.
439 */
Paul Jakmabd34fb32007-02-26 17:14:48 +0000440 assert (distance <= w->distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000441
442 /* Adding parent for a new, better path: flush existing parents from W. */
Paul Jakmabd34fb32007-02-26 17:14:48 +0000443 if (distance < w->distance)
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000444 {
445 ospf_spf_flush_parents (w);
Paul Jakmabd34fb32007-02-26 17:14:48 +0000446 w->distance = distance;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000447 }
448
449 /* new parent is <= existing parents, add it to parent list */
450 vp = vertex_parent_new (v, ospf_lsa_has_link (w->lsa, v->lsa), newhop);
451 listnode_add (w->parents, vp);
452
453 return;
454}
455
gdt630e4802004-08-31 17:28:41 +0000456/* 16.1.1. Calculate nexthop from root through V (parent) to
Paul Jakmabd34fb32007-02-26 17:14:48 +0000457 * vertex W (destination), with given distance from root->W.
pauleb3da6d2005-10-18 04:20:33 +0000458 *
459 * The link must be supplied if V is the root vertex. In all other cases
460 * it may be NULL.
Paul Jakmabd34fb32007-02-26 17:14:48 +0000461 *
462 * Note that this function may fail, hence the state of the destination
463 * vertex, W, should /not/ be modified in a dependent manner until
464 * this function returns. This function will update the W vertex with the
465 * provided distance as appropriate.
gdt630e4802004-08-31 17:28:41 +0000466 */
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000467static unsigned int
pauleb3da6d2005-10-18 04:20:33 +0000468ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v,
Paul Jakmabd34fb32007-02-26 17:14:48 +0000469 struct vertex *w, struct router_lsa_link *l,
470 unsigned int distance)
paul718e3742002-12-13 20:15:29 +0000471{
paul1eb8ef22005-04-07 07:30:20 +0000472 struct listnode *node, *nnode;
pauleb3da6d2005-10-18 04:20:33 +0000473 struct vertex_nexthop *nh;
474 struct vertex_parent *vp;
paul718e3742002-12-13 20:15:29 +0000475 struct ospf_interface *oi = NULL;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000476 unsigned int added = 0;
paul0c0f9cd2003-06-06 23:27:04 +0000477
paul718e3742002-12-13 20:15:29 +0000478 if (IS_DEBUG_OSPF_EVENT)
gdt630e4802004-08-31 17:28:41 +0000479 {
ajs2a42e282004-12-08 18:43:03 +0000480 zlog_debug ("ospf_nexthop_calculation(): Start");
gdt630e4802004-08-31 17:28:41 +0000481 ospf_vertex_dump("V (parent):", v, 1, 1);
482 ospf_vertex_dump("W (dest) :", w, 1, 1);
Paul Jakmabd34fb32007-02-26 17:14:48 +0000483 zlog_debug ("V->W distance: %d", distance);
gdt630e4802004-08-31 17:28:41 +0000484 }
paul718e3742002-12-13 20:15:29 +0000485
paul718e3742002-12-13 20:15:29 +0000486 if (v == area->spf)
Paul Jakma9c27ef92006-05-04 07:32:57 +0000487 {
gdt630e4802004-08-31 17:28:41 +0000488 /* 16.1.1 para 4. In the first case, the parent vertex (V) is the
489 root (the calculating router itself). This means that the
490 destination is either a directly connected network or directly
491 connected router. The outgoing interface in this case is simply
492 the OSPF interface connecting to the destination network/router.
493 */
494
paul718e3742002-12-13 20:15:29 +0000495 if (w->type == OSPF_VERTEX_ROUTER)
paul0c0f9cd2003-06-06 23:27:04 +0000496 {
pauleb3da6d2005-10-18 04:20:33 +0000497 /* l is a link from v to w
498 * l2 will be link from w to v
499 */
500 struct router_lsa_link *l2 = NULL;
501
502 /* we *must* be supplied with the link data */
503 assert (l != NULL);
504
505 if (IS_DEBUG_OSPF_EVENT)
paul0c0f9cd2003-06-06 23:27:04 +0000506 {
pauleb3da6d2005-10-18 04:20:33 +0000507 char buf1[BUFSIZ];
508 char buf2[BUFSIZ];
509
510 zlog_debug("ospf_nexthop_calculation(): considering link "
511 "type %d link_id %s link_data %s",
512 l->m[0].type,
513 inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ),
514 inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ));
515 }
paul0c0f9cd2003-06-06 23:27:04 +0000516
pauleb3da6d2005-10-18 04:20:33 +0000517 if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT)
518 {
519 /* If the destination is a router which connects to
520 the calculating router via a Point-to-MultiPoint
521 network, the destination's next hop IP address(es)
522 can be determined by examining the destination's
523 router-LSA: each link pointing back to the
524 calculating router and having a Link Data field
525 belonging to the Point-to-MultiPoint network
526 provides an IP address of the next hop router.
gdt630e4802004-08-31 17:28:41 +0000527
pauleb3da6d2005-10-18 04:20:33 +0000528 At this point l is a link from V to W, and V is the
529 root ("us"). Find the local interface associated
530 with l (its address is in l->link_data). If it
531 is a point-to-multipoint interface, then look through
532 the links in the opposite direction (W to V). If
533 any of them have an address that lands within the
534 subnet declared by the PtMP link, then that link
535 is a constituent of the PtMP link, and its address is
536 a nexthop address for V.
537 */
538 oi = ospf_if_is_configured (area->ospf, &l->link_data);
539 if (oi && oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
paul0c0f9cd2003-06-06 23:27:04 +0000540 {
pauleb3da6d2005-10-18 04:20:33 +0000541 struct prefix_ipv4 la;
gdt630e4802004-08-31 17:28:41 +0000542
pauleb3da6d2005-10-18 04:20:33 +0000543 la.family = AF_INET;
544 la.prefixlen = oi->address->prefixlen;
545
546 /* V links to W on PtMP interface
547 - find the interface address on W */
548 while ((l2 = ospf_get_next_link (w, v, l2)))
paul0c0f9cd2003-06-06 23:27:04 +0000549 {
pauleb3da6d2005-10-18 04:20:33 +0000550 la.prefix = l2->link_data;
gdt630e4802004-08-31 17:28:41 +0000551
pauleb3da6d2005-10-18 04:20:33 +0000552 if (prefix_cmp ((struct prefix *) &la,
553 oi->address) == 0)
554 /* link_data is on our PtMP network */
555 break;
paul0c0f9cd2003-06-06 23:27:04 +0000556 }
pauleb3da6d2005-10-18 04:20:33 +0000557 } /* end l is on point-to-multipoint link */
558 else
559 {
560 /* l is a regular point-to-point link.
561 Look for a link from W to V.
562 */
563 while ((l2 = ospf_get_next_link (w, v, l2)))
paul0c0f9cd2003-06-06 23:27:04 +0000564 {
pauleb3da6d2005-10-18 04:20:33 +0000565 oi = ospf_if_is_configured (area->ospf,
566 &(l2->link_data));
567
568 if (oi == NULL)
569 continue;
570
571 if (!IPV4_ADDR_SAME (&oi->address->u.prefix4,
572 &l->link_data))
573 continue;
574
575 break;
paul0c0f9cd2003-06-06 23:27:04 +0000576 }
pauleb3da6d2005-10-18 04:20:33 +0000577 }
578
579 if (oi && l2)
580 {
581 /* found all necessary info to build nexthop */
582 nh = vertex_nexthop_new ();
583 nh->oi = oi;
584 nh->router = l2->link_data;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000585 ospf_spf_add_parent (v, w, nh, distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000586 return 1;
pauleb3da6d2005-10-18 04:20:33 +0000587 }
588 else
Paul Jakma9c27ef92006-05-04 07:32:57 +0000589 zlog_info("ospf_nexthop_calculation(): "
590 "could not determine nexthop for link");
pauleb3da6d2005-10-18 04:20:33 +0000591 } /* end point-to-point link from V to W */
Paul Jakma9c27ef92006-05-04 07:32:57 +0000592 else if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK)
593 {
594 struct ospf_vl_data *vl_data;
595
596 /* VLink implementation limitations:
597 * a) vl_data can only reference one nexthop, so no ECMP
598 * to backbone through VLinks. Though transit-area
599 * summaries may be considered, and those can be ECMP.
600 * b) We can only use /one/ VLink, even if multiple ones
601 * exist this router through multiple transit-areas.
602 */
603 vl_data = ospf_vl_lookup (area->ospf, NULL, l->link_id);
604
605 if (vl_data
606 && CHECK_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED))
607 {
608 nh = vertex_nexthop_new ();
609 nh->oi = vl_data->nexthop.oi;
610 nh->router = vl_data->nexthop.router;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000611 ospf_spf_add_parent (v, w, nh, distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000612 return 1;
Paul Jakma9c27ef92006-05-04 07:32:57 +0000613 }
614 else
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000615 zlog_info("ospf_nexthop_calculation(): "
616 "vl_data for VL link not found");
Paul Jakma9c27ef92006-05-04 07:32:57 +0000617 } /* end virtual-link from V to W */
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000618 return 0;
gdt630e4802004-08-31 17:28:41 +0000619 } /* end W is a Router vertex */
paul718e3742002-12-13 20:15:29 +0000620 else
paul0c0f9cd2003-06-06 23:27:04 +0000621 {
pauleb3da6d2005-10-18 04:20:33 +0000622 assert(w->type == OSPF_VERTEX_NETWORK);
623 oi = ospf_if_is_configured (area->ospf, &(l->link_data));
624 if (oi)
paul0c0f9cd2003-06-06 23:27:04 +0000625 {
pauleb3da6d2005-10-18 04:20:33 +0000626 nh = vertex_nexthop_new ();
627 nh->oi = oi;
628 nh->router.s_addr = 0;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000629 ospf_spf_add_parent (v, w, nh, distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000630 return 1;
paul0c0f9cd2003-06-06 23:27:04 +0000631 }
632 }
Paul Jakma9c27ef92006-05-04 07:32:57 +0000633 zlog_info("ospf_nexthop_calculation(): "
634 "Unknown attached link");
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000635 return 0;
gdt630e4802004-08-31 17:28:41 +0000636 } /* end V is the root */
gdt630e4802004-08-31 17:28:41 +0000637 /* Check if W's parent is a network connected to root. */
paul718e3742002-12-13 20:15:29 +0000638 else if (v->type == OSPF_VERTEX_NETWORK)
639 {
gdt630e4802004-08-31 17:28:41 +0000640 /* See if any of V's parents are the root. */
pauleb3da6d2005-10-18 04:20:33 +0000641 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
paul718e3742002-12-13 20:15:29 +0000642 {
pauleb3da6d2005-10-18 04:20:33 +0000643 if (vp->parent == area->spf) /* connects to root? */
gdt630e4802004-08-31 17:28:41 +0000644 {
645 /* 16.1.1 para 5. ...the parent vertex is a network that
646 * directly connects the calculating router to the destination
647 * router. The list of next hops is then determined by
648 * examining the destination's router-LSA...
649 */
650
651 assert(w->type == OSPF_VERTEX_ROUTER);
paul0c0f9cd2003-06-06 23:27:04 +0000652 while ((l = ospf_get_next_link (w, v, l)))
653 {
gdt630e4802004-08-31 17:28:41 +0000654 /* ...For each link in the router-LSA that points back to the
655 * parent network, the link's Link Data field provides the IP
656 * address of a next hop router. The outgoing interface to
657 * use can then be derived from the next hop IP address (or
658 * it can be inherited from the parent network).
659 */
pauleb3da6d2005-10-18 04:20:33 +0000660 nh = vertex_nexthop_new ();
661 nh->oi = vp->nexthop->oi;
662 nh->router = l->link_data;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000663 added = 1;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000664 ospf_spf_add_parent (v, w, nh, distance);
paul0c0f9cd2003-06-06 23:27:04 +0000665 }
paul0c0f9cd2003-06-06 23:27:04 +0000666 }
paul718e3742002-12-13 20:15:29 +0000667 }
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000668 return added;
paul718e3742002-12-13 20:15:29 +0000669 }
670
gdt630e4802004-08-31 17:28:41 +0000671 /* 16.1.1 para 4. If there is at least one intervening router in the
672 * current shortest path between the destination and the root, the
673 * destination simply inherits the set of next hops from the
674 * parent.
675 */
pauleb3da6d2005-10-18 04:20:33 +0000676 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000677 {
678 added = 1;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000679 ospf_spf_add_parent (v, w, vp->nexthop, distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000680 }
Paul Jakma9c27ef92006-05-04 07:32:57 +0000681
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000682 return added;
paul718e3742002-12-13 20:15:29 +0000683}
684
gdt630e4802004-08-31 17:28:41 +0000685/* RFC2328 Section 16.1 (2).
686 * v is on the SPF tree. Examine the links in v's LSA. Update the list
687 * of candidates with any vertices not already on the list. If a lower-cost
688 * path is found to a vertex already on the candidate list, store the new cost.
689 */
paul4dadc292005-05-06 21:37:42 +0000690static void
paul718e3742002-12-13 20:15:29 +0000691ospf_spf_next (struct vertex *v, struct ospf_area *area,
hasso462f20d2005-02-23 11:29:02 +0000692 struct pqueue * candidate)
paul718e3742002-12-13 20:15:29 +0000693{
694 struct ospf_lsa *w_lsa = NULL;
paul718e3742002-12-13 20:15:29 +0000695 u_char *p;
696 u_char *lim;
697 struct router_lsa_link *l = NULL;
698 struct in_addr *r;
paul718e3742002-12-13 20:15:29 +0000699 int type = 0;
700
701 /* If this is a router-LSA, and bit V of the router-LSA (see Section
702 A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE. */
703 if (v->type == OSPF_VERTEX_ROUTER)
704 {
705 if (IS_ROUTER_LSA_VIRTUAL ((struct router_lsa *) v->lsa))
706 area->transit = OSPF_TRANSIT_TRUE;
707 }
708
709 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul0c0f9cd2003-06-06 23:27:04 +0000710 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
711
paul718e3742002-12-13 20:15:29 +0000712 while (p < lim)
713 {
pauleb3da6d2005-10-18 04:20:33 +0000714 struct vertex *w;
715 unsigned int distance;
pauld355bfa2004-04-08 07:43:45 +0000716
paul718e3742002-12-13 20:15:29 +0000717 /* In case of V is Router-LSA. */
718 if (v->lsa->type == OSPF_ROUTER_LSA)
719 {
720 l = (struct router_lsa_link *) p;
721
paul0c0f9cd2003-06-06 23:27:04 +0000722 p += (ROUTER_LSA_MIN_SIZE +
paul718e3742002-12-13 20:15:29 +0000723 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
724
725 /* (a) If this is a link to a stub network, examine the next
726 link in V's LSA. Links to stub networks will be
727 considered in the second stage of the shortest path
728 calculation. */
729 if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB)
730 continue;
731
732 /* (b) Otherwise, W is a transit vertex (router or transit
733 network). Look up the vertex W's LSA (router-LSA or
734 network-LSA) in Area A's link state database. */
735 switch (type)
736 {
737 case LSA_LINK_TYPE_POINTOPOINT:
738 case LSA_LINK_TYPE_VIRTUALLINK:
739 if (type == LSA_LINK_TYPE_VIRTUALLINK)
paul0c0f9cd2003-06-06 23:27:04 +0000740 {
741 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000742 zlog_debug ("looking up LSA through VL: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000743 inet_ntoa (l->link_id));
744 }
paul718e3742002-12-13 20:15:29 +0000745
746 w_lsa = ospf_lsa_lookup (area, OSPF_ROUTER_LSA, l->link_id,
747 l->link_id);
748 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000749 {
750 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000751 zlog_debug ("found Router LSA %s", inet_ntoa (l->link_id));
paul0c0f9cd2003-06-06 23:27:04 +0000752 }
paul718e3742002-12-13 20:15:29 +0000753 break;
754 case LSA_LINK_TYPE_TRANSIT:
paul0c0f9cd2003-06-06 23:27:04 +0000755 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000756 zlog_debug ("Looking up Network LSA, ID: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000757 inet_ntoa (l->link_id));
paul718e3742002-12-13 20:15:29 +0000758 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_NETWORK_LSA,
paul0c0f9cd2003-06-06 23:27:04 +0000759 l->link_id);
paul718e3742002-12-13 20:15:29 +0000760 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000761 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000762 zlog_debug ("found the LSA");
paul718e3742002-12-13 20:15:29 +0000763 break;
764 default:
paul0c0f9cd2003-06-06 23:27:04 +0000765 zlog_warn ("Invalid LSA link type %d", type);
paul718e3742002-12-13 20:15:29 +0000766 continue;
767 }
768 }
769 else
770 {
771 /* In case of V is Network-LSA. */
paul0c0f9cd2003-06-06 23:27:04 +0000772 r = (struct in_addr *) p;
paul718e3742002-12-13 20:15:29 +0000773 p += sizeof (struct in_addr);
774
775 /* Lookup the vertex W's LSA. */
776 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_ROUTER_LSA, *r);
777 }
778
779 /* (b cont.) If the LSA does not exist, or its LS age is equal
780 to MaxAge, or it does not have a link back to vertex V,
781 examine the next link in V's LSA.[23] */
782 if (w_lsa == NULL)
783 continue;
784
785 if (IS_LSA_MAXAGE (w_lsa))
786 continue;
787
pauleb3da6d2005-10-18 04:20:33 +0000788 if (ospf_lsa_has_link (w_lsa->data, v->lsa) < 0 )
paul718e3742002-12-13 20:15:29 +0000789 {
paul0c0f9cd2003-06-06 23:27:04 +0000790 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000791 zlog_debug ("The LSA doesn't have a link back");
paul718e3742002-12-13 20:15:29 +0000792 continue;
793 }
794
795 /* (c) If vertex W is already on the shortest-path tree, examine
796 the next link in the LSA. */
hasso462f20d2005-02-23 11:29:02 +0000797 if (w_lsa->stat == LSA_SPF_IN_SPFTREE)
798 {
799 if (IS_DEBUG_OSPF_EVENT)
800 zlog_debug ("The LSA is already in SPF");
801 continue;
802 }
paul718e3742002-12-13 20:15:29 +0000803
804 /* (d) Calculate the link state cost D of the resulting path
805 from the root to vertex W. D is equal to the sum of the link
806 state cost of the (already calculated) shortest path to
807 vertex V and the advertised cost of the link between vertices
808 V and W. If D is: */
809
paul718e3742002-12-13 20:15:29 +0000810 /* calculate link cost D. */
811 if (v->lsa->type == OSPF_ROUTER_LSA)
pauleb3da6d2005-10-18 04:20:33 +0000812 distance = v->distance + ntohs (l->m[0].metric);
gdt630e4802004-08-31 17:28:41 +0000813 else /* v is not a Router-LSA */
pauleb3da6d2005-10-18 04:20:33 +0000814 distance = v->distance;
paul718e3742002-12-13 20:15:29 +0000815
816 /* Is there already vertex W in candidate list? */
hasso462f20d2005-02-23 11:29:02 +0000817 if (w_lsa->stat == LSA_SPF_NOT_EXPLORED)
818 {
pauleb3da6d2005-10-18 04:20:33 +0000819 /* prepare vertex W. */
820 w = ospf_vertex_new (w_lsa);
821
hasso462f20d2005-02-23 11:29:02 +0000822 /* Calculate nexthop to W. */
Paul Jakmabd34fb32007-02-26 17:14:48 +0000823 if (ospf_nexthop_calculation (area, v, w, l, distance))
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000824 pqueue_enqueue (w, candidate);
hasso462f20d2005-02-23 11:29:02 +0000825 }
826 else if (w_lsa->stat >= 0)
827 {
828 /* Get the vertex from candidates. */
pauleb3da6d2005-10-18 04:20:33 +0000829 w = candidate->array[w_lsa->stat];
paul718e3742002-12-13 20:15:29 +0000830
hasso462f20d2005-02-23 11:29:02 +0000831 /* if D is greater than. */
pauleb3da6d2005-10-18 04:20:33 +0000832 if (w->distance < distance)
paul718e3742002-12-13 20:15:29 +0000833 {
paul718e3742002-12-13 20:15:29 +0000834 continue;
835 }
hasso462f20d2005-02-23 11:29:02 +0000836 /* equal to. */
pauleb3da6d2005-10-18 04:20:33 +0000837 else if (w->distance == distance)
paul718e3742002-12-13 20:15:29 +0000838 {
pauleb3da6d2005-10-18 04:20:33 +0000839 /* Found an equal-cost path to W.
840 * Calculate nexthop of to W from V. */
Paul Jakmabd34fb32007-02-26 17:14:48 +0000841 ospf_nexthop_calculation (area, v, w, l, distance);
paul718e3742002-12-13 20:15:29 +0000842 }
hasso462f20d2005-02-23 11:29:02 +0000843 /* less than. */
844 else
paul718e3742002-12-13 20:15:29 +0000845 {
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000846 /* Found a lower-cost path to W.
847 * nexthop_calculation is conditional, if it finds
848 * valid nexthop it will call spf_add_parents, which
849 * will flush the old parents
850 */
Paul Jakmabd34fb32007-02-26 17:14:48 +0000851 if (ospf_nexthop_calculation (area, v, w, l, distance))
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000852 /* Decrease the key of the node in the heap,
853 * re-sort the heap. */
854 trickle_down (w_lsa->stat, candidate);
paul718e3742002-12-13 20:15:29 +0000855 }
gdt630e4802004-08-31 17:28:41 +0000856 } /* end W is already on the candidate list */
857 } /* end loop over the links in V's LSA */
paul718e3742002-12-13 20:15:29 +0000858}
859
paul4dadc292005-05-06 21:37:42 +0000860static void
paul718e3742002-12-13 20:15:29 +0000861ospf_spf_dump (struct vertex *v, int i)
862{
hasso52dc7ee2004-09-23 19:18:23 +0000863 struct listnode *cnode;
864 struct listnode *nnode;
pauleb3da6d2005-10-18 04:20:33 +0000865 struct vertex_parent *parent;
paul718e3742002-12-13 20:15:29 +0000866
867 if (v->type == OSPF_VERTEX_ROUTER)
868 {
869 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000870 zlog_debug ("SPF Result: %d [R] %s", i, inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000871 }
872 else
873 {
874 struct network_lsa *lsa = (struct network_lsa *) v->lsa;
875 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000876 zlog_debug ("SPF Result: %d [N] %s/%d", i, inet_ntoa (v->lsa->id),
paul0c0f9cd2003-06-06 23:27:04 +0000877 ip_masklen (lsa->mask));
gdt630e4802004-08-31 17:28:41 +0000878 }
paul718e3742002-12-13 20:15:29 +0000879
paul1eb8ef22005-04-07 07:30:20 +0000880 if (IS_DEBUG_OSPF_EVENT)
pauleb3da6d2005-10-18 04:20:33 +0000881 for (ALL_LIST_ELEMENTS_RO (v->parents, nnode, parent))
882 {
883 zlog_debug (" nexthop %p %s %s",
884 parent->nexthop,
885 inet_ntoa (parent->nexthop->router),
886 parent->nexthop->oi ? IF_NAME(parent->nexthop->oi)
887 : "NULL");
888 }
paul718e3742002-12-13 20:15:29 +0000889
890 i++;
891
pauleb3da6d2005-10-18 04:20:33 +0000892 for (ALL_LIST_ELEMENTS_RO (v->children, cnode, v))
paul1eb8ef22005-04-07 07:30:20 +0000893 ospf_spf_dump (v, i);
paul718e3742002-12-13 20:15:29 +0000894}
895
896/* Second stage of SPF calculation. */
paul4dadc292005-05-06 21:37:42 +0000897static void
paul0c0f9cd2003-06-06 23:27:04 +0000898ospf_spf_process_stubs (struct ospf_area *area, struct vertex *v,
paul718e3742002-12-13 20:15:29 +0000899 struct route_table *rt)
900{
paul1eb8ef22005-04-07 07:30:20 +0000901 struct listnode *cnode, *cnnode;
paul718e3742002-12-13 20:15:29 +0000902 struct vertex *child;
903
904 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000905 zlog_debug ("ospf_process_stub():processing stubs for area %s",
paul0c0f9cd2003-06-06 23:27:04 +0000906 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +0000907 if (v->type == OSPF_VERTEX_ROUTER)
908 {
909 u_char *p;
910 u_char *lim;
911 struct router_lsa_link *l;
912 struct router_lsa *rlsa;
913
paul0c0f9cd2003-06-06 23:27:04 +0000914 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000915 zlog_debug ("ospf_process_stubs():processing router LSA, id: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000916 inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000917 rlsa = (struct router_lsa *) v->lsa;
918
919
paul0c0f9cd2003-06-06 23:27:04 +0000920 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000921 zlog_debug ("ospf_process_stubs(): we have %d links to process",
paul0c0f9cd2003-06-06 23:27:04 +0000922 ntohs (rlsa->links));
gdt630e4802004-08-31 17:28:41 +0000923 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +0000924 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
925
926 while (p < lim)
927 {
928 l = (struct router_lsa_link *) p;
929
930 p += (ROUTER_LSA_MIN_SIZE +
931 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
932
933 if (l->m[0].type == LSA_LINK_TYPE_STUB)
934 ospf_intra_add_stub (rt, l, v, area);
935 }
936 }
937
gdt630e4802004-08-31 17:28:41 +0000938 ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1, 1);
paul718e3742002-12-13 20:15:29 +0000939
pauleb3da6d2005-10-18 04:20:33 +0000940 for (ALL_LIST_ELEMENTS (v->children, cnode, cnnode, child))
paul718e3742002-12-13 20:15:29 +0000941 {
paul718e3742002-12-13 20:15:29 +0000942 if (CHECK_FLAG (child->flags, OSPF_VERTEX_PROCESSED))
paul0c0f9cd2003-06-06 23:27:04 +0000943 continue;
paul718e3742002-12-13 20:15:29 +0000944
945 ospf_spf_process_stubs (area, child, rt);
946
947 SET_FLAG (child->flags, OSPF_VERTEX_PROCESSED);
948 }
949}
950
951void
952ospf_rtrs_free (struct route_table *rtrs)
953{
954 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +0000955 struct list *or_list;
paul1eb8ef22005-04-07 07:30:20 +0000956 struct ospf_route *or;
957 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000958
959 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000960 zlog_debug ("Route: Router Routing Table free");
paul718e3742002-12-13 20:15:29 +0000961
962 for (rn = route_top (rtrs); rn; rn = route_next (rn))
963 if ((or_list = rn->info) != NULL)
964 {
paul1eb8ef22005-04-07 07:30:20 +0000965 for (ALL_LIST_ELEMENTS (or_list, node, nnode, or))
966 ospf_route_free (or);
paul718e3742002-12-13 20:15:29 +0000967
paul0c0f9cd2003-06-06 23:27:04 +0000968 list_delete (or_list);
paul718e3742002-12-13 20:15:29 +0000969
paul0c0f9cd2003-06-06 23:27:04 +0000970 /* Unlock the node. */
971 rn->info = NULL;
972 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +0000973 }
974 route_table_finish (rtrs);
975}
976
paul4dadc292005-05-06 21:37:42 +0000977static void
paul718e3742002-12-13 20:15:29 +0000978ospf_rtrs_print (struct route_table *rtrs)
979{
980 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +0000981 struct list *or_list;
982 struct listnode *ln;
983 struct listnode *pnode;
paul718e3742002-12-13 20:15:29 +0000984 struct ospf_route *or;
985 struct ospf_path *path;
986 char buf1[BUFSIZ];
987 char buf2[BUFSIZ];
988
989 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000990 zlog_debug ("ospf_rtrs_print() start");
paul718e3742002-12-13 20:15:29 +0000991
992 for (rn = route_top (rtrs); rn; rn = route_next (rn))
993 if ((or_list = rn->info) != NULL)
paul1eb8ef22005-04-07 07:30:20 +0000994 for (ALL_LIST_ELEMENTS_RO (or_list, ln, or))
paul718e3742002-12-13 20:15:29 +0000995 {
paul718e3742002-12-13 20:15:29 +0000996 switch (or->path_type)
997 {
998 case OSPF_PATH_INTRA_AREA:
paul0c0f9cd2003-06-06 23:27:04 +0000999 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001000 zlog_debug ("%s [%d] area: %s",
paul0c0f9cd2003-06-06 23:27:04 +00001001 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1002 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1003 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +00001004 break;
1005 case OSPF_PATH_INTER_AREA:
paul0c0f9cd2003-06-06 23:27:04 +00001006 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001007 zlog_debug ("%s IA [%d] area: %s",
paul0c0f9cd2003-06-06 23:27:04 +00001008 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1009 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1010 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +00001011 break;
1012 default:
1013 break;
1014 }
1015
paul1eb8ef22005-04-07 07:30:20 +00001016 for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path))
paul718e3742002-12-13 20:15:29 +00001017 {
paul718e3742002-12-13 20:15:29 +00001018 if (path->nexthop.s_addr == 0)
paul0c0f9cd2003-06-06 23:27:04 +00001019 {
1020 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001021 zlog_debug (" directly attached to %s\r\n",
paul0c0f9cd2003-06-06 23:27:04 +00001022 IF_NAME (path->oi));
1023 }
1024 else
1025 {
1026 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001027 zlog_debug (" via %s, %s\r\n",
paul0c0f9cd2003-06-06 23:27:04 +00001028 inet_ntoa (path->nexthop), IF_NAME (path->oi));
1029 }
paul718e3742002-12-13 20:15:29 +00001030 }
1031 }
1032
ajs2a42e282004-12-08 18:43:03 +00001033 zlog_debug ("ospf_rtrs_print() end");
paul718e3742002-12-13 20:15:29 +00001034}
1035
1036/* Calculating the shortest-path tree for an area. */
paul4dadc292005-05-06 21:37:42 +00001037static void
paul0c0f9cd2003-06-06 23:27:04 +00001038ospf_spf_calculate (struct ospf_area *area, struct route_table *new_table,
paul718e3742002-12-13 20:15:29 +00001039 struct route_table *new_rtrs)
1040{
hasso462f20d2005-02-23 11:29:02 +00001041 struct pqueue *candidate;
paul718e3742002-12-13 20:15:29 +00001042 struct vertex *v;
pauleb3da6d2005-10-18 04:20:33 +00001043
paul718e3742002-12-13 20:15:29 +00001044 if (IS_DEBUG_OSPF_EVENT)
1045 {
ajs2a42e282004-12-08 18:43:03 +00001046 zlog_debug ("ospf_spf_calculate: Start");
1047 zlog_debug ("ospf_spf_calculate: running Dijkstra for area %s",
paul0c0f9cd2003-06-06 23:27:04 +00001048 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001049 }
1050
1051 /* Check router-lsa-self. If self-router-lsa is not yet allocated,
1052 return this area's calculation. */
paul0c0f9cd2003-06-06 23:27:04 +00001053 if (!area->router_lsa_self)
paul718e3742002-12-13 20:15:29 +00001054 {
1055 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001056 zlog_debug ("ospf_spf_calculate: "
paul0c0f9cd2003-06-06 23:27:04 +00001057 "Skip area %s's calculation due to empty router_lsa_self",
1058 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001059 return;
1060 }
1061
1062 /* RFC2328 16.1. (1). */
paul0c0f9cd2003-06-06 23:27:04 +00001063 /* Initialize the algorithm's data structures. */
hasso462f20d2005-02-23 11:29:02 +00001064
1065 /* This function scans all the LSA database and set the stat field to
1066 * LSA_SPF_NOT_EXPLORED. */
1067 ospf_lsdb_clean_stat (area->lsdb);
1068 /* Create a new heap for the candidates. */
1069 candidate = pqueue_create();
1070 candidate->cmp = cmp;
1071 candidate->update = update_stat;
paul718e3742002-12-13 20:15:29 +00001072
1073 /* Initialize the shortest-path tree to only the root (which is the
1074 router doing the calculation). */
1075 ospf_spf_init (area);
1076 v = area->spf;
hasso462f20d2005-02-23 11:29:02 +00001077 /* Set LSA position to LSA_SPF_IN_SPFTREE. This vertex is the root of the
1078 * spanning tree. */
1079 *(v->stat) = LSA_SPF_IN_SPFTREE;
paul718e3742002-12-13 20:15:29 +00001080
1081 /* Set Area A's TransitCapability to FALSE. */
1082 area->transit = OSPF_TRANSIT_FALSE;
1083 area->shortcut_capability = 1;
pauleb3da6d2005-10-18 04:20:33 +00001084
paul718e3742002-12-13 20:15:29 +00001085 for (;;)
1086 {
1087 /* RFC2328 16.1. (2). */
hasso462f20d2005-02-23 11:29:02 +00001088 ospf_spf_next (v, area, candidate);
paul718e3742002-12-13 20:15:29 +00001089
1090 /* RFC2328 16.1. (3). */
1091 /* If at this step the candidate list is empty, the shortest-
1092 path tree (of transit vertices) has been completely built and
1093 this stage of the procedure terminates. */
hasso462f20d2005-02-23 11:29:02 +00001094 if (candidate->size == 0)
paul718e3742002-12-13 20:15:29 +00001095 break;
1096
1097 /* Otherwise, choose the vertex belonging to the candidate list
1098 that is closest to the root, and add it to the shortest-path
1099 tree (removing it from the candidate list in the
paul0c0f9cd2003-06-06 23:27:04 +00001100 process). */
hasso462f20d2005-02-23 11:29:02 +00001101 /* Extract from the candidates the node with the lower key. */
1102 v = (struct vertex *) pqueue_dequeue (candidate);
1103 /* Update stat field in vertex. */
1104 *(v->stat) = LSA_SPF_IN_SPFTREE;
pauleb3da6d2005-10-18 04:20:33 +00001105
paul718e3742002-12-13 20:15:29 +00001106 ospf_vertex_add_parent (v);
1107
paul718e3742002-12-13 20:15:29 +00001108 /* Note that when there is a choice of vertices closest to the
1109 root, network vertices must be chosen before router vertices
1110 in order to necessarily find all equal-cost paths. */
1111 /* We don't do this at this moment, we should add the treatment
1112 above codes. -- kunihiro. */
1113
1114 /* RFC2328 16.1. (4). */
1115 if (v->type == OSPF_VERTEX_ROUTER)
1116 ospf_intra_add_router (new_rtrs, v, area);
paul0c0f9cd2003-06-06 23:27:04 +00001117 else
paul718e3742002-12-13 20:15:29 +00001118 ospf_intra_add_transit (new_table, v, area);
1119
1120 /* RFC2328 16.1. (5). */
1121 /* Iterate the algorithm by returning to Step 2. */
gdt630e4802004-08-31 17:28:41 +00001122
1123 } /* end loop until no more candidate vertices */
paul718e3742002-12-13 20:15:29 +00001124
1125 if (IS_DEBUG_OSPF_EVENT)
1126 {
1127 ospf_spf_dump (area->spf, 0);
1128 ospf_route_table_dump (new_table);
1129 }
1130
1131 /* Second stage of SPF calculation procedure's */
1132 ospf_spf_process_stubs (area, area->spf, new_table);
1133
pauleb3da6d2005-10-18 04:20:33 +00001134 /* Free candidate queue. */
hasso462f20d2005-02-23 11:29:02 +00001135 pqueue_delete (candidate);
pauleb3da6d2005-10-18 04:20:33 +00001136
1137 ospf_vertex_dump (__func__, area->spf, 0, 1);
1138 /* Free nexthop information, canonical versions of which are attached
1139 * the first level of router vertices attached to the root vertex, see
1140 * ospf_nexthop_calculation.
1141 */
1142 ospf_canonical_nexthops_free (area->spf);
1143
Paul Jakma9c27ef92006-05-04 07:32:57 +00001144 /* Free SPF vertices, but not the list. List has ospf_vertex_free
1145 * as deconstructor.
1146 */
1147 list_delete_all_node (&vertex_list);
pauleb3da6d2005-10-18 04:20:33 +00001148
paul718e3742002-12-13 20:15:29 +00001149 /* Increment SPF Calculation Counter. */
1150 area->spf_calculation++;
1151
Paul Jakma2518efd2006-08-27 06:49:29 +00001152 quagga_gettime (QUAGGA_CLK_MONOTONIC, &area->ospf->ts_spf);
paul718e3742002-12-13 20:15:29 +00001153
1154 if (IS_DEBUG_OSPF_EVENT)
Paul Jakma9c27ef92006-05-04 07:32:57 +00001155 zlog_debug ("ospf_spf_calculate: Stop. %ld vertices",
1156 mtype_stats_alloc(MTYPE_OSPF_VERTEX));
paul718e3742002-12-13 20:15:29 +00001157}
1158
1159/* Timer for SPF calculation. */
paul4dadc292005-05-06 21:37:42 +00001160static int
paul68980082003-03-25 05:07:42 +00001161ospf_spf_calculate_timer (struct thread *thread)
paul718e3742002-12-13 20:15:29 +00001162{
paul68980082003-03-25 05:07:42 +00001163 struct ospf *ospf = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +00001164 struct route_table *new_table, *new_rtrs;
paul1eb8ef22005-04-07 07:30:20 +00001165 struct ospf_area *area;
1166 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001167
1168 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001169 zlog_debug ("SPF: Timer (SPF calculation expire)");
paul0c0f9cd2003-06-06 23:27:04 +00001170
paul718e3742002-12-13 20:15:29 +00001171 ospf->t_spf_calc = NULL;
1172
1173 /* Allocate new table tree. */
1174 new_table = route_table_init ();
paul0c0f9cd2003-06-06 23:27:04 +00001175 new_rtrs = route_table_init ();
paul718e3742002-12-13 20:15:29 +00001176
paul68980082003-03-25 05:07:42 +00001177 ospf_vl_unapprove (ospf);
paul718e3742002-12-13 20:15:29 +00001178
1179 /* Calculate SPF for each area. */
paul1eb8ef22005-04-07 07:30:20 +00001180 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
Paul Jakma9c27ef92006-05-04 07:32:57 +00001181 {
1182 /* Do backbone last, so as to first discover intra-area paths
1183 * for any back-bone virtual-links
1184 */
1185 if (ospf->backbone && ospf->backbone == area)
1186 continue;
1187
1188 ospf_spf_calculate (area, new_table, new_rtrs);
1189 }
1190
1191 /* SPF for backbone, if required */
1192 if (ospf->backbone)
1193 ospf_spf_calculate (ospf->backbone, new_table, new_rtrs);
1194
paul68980082003-03-25 05:07:42 +00001195 ospf_vl_shut_unapproved (ospf);
paul718e3742002-12-13 20:15:29 +00001196
paul68980082003-03-25 05:07:42 +00001197 ospf_ia_routing (ospf, new_table, new_rtrs);
paul718e3742002-12-13 20:15:29 +00001198
1199 ospf_prune_unreachable_networks (new_table);
1200 ospf_prune_unreachable_routers (new_rtrs);
1201
1202 /* AS-external-LSA calculation should not be performed here. */
1203
1204 /* If new Router Route is installed,
1205 then schedule re-calculate External routes. */
1206 if (1)
paul68980082003-03-25 05:07:42 +00001207 ospf_ase_calculate_schedule (ospf);
paul718e3742002-12-13 20:15:29 +00001208
paul68980082003-03-25 05:07:42 +00001209 ospf_ase_calculate_timer_add (ospf);
paul718e3742002-12-13 20:15:29 +00001210
1211 /* Update routing table. */
paul68980082003-03-25 05:07:42 +00001212 ospf_route_install (ospf, new_table);
paul718e3742002-12-13 20:15:29 +00001213
1214 /* Update ABR/ASBR routing table */
paul68980082003-03-25 05:07:42 +00001215 if (ospf->old_rtrs)
paul718e3742002-12-13 20:15:29 +00001216 {
1217 /* old_rtrs's node holds linked list of ospf_route. --kunihiro. */
paul68980082003-03-25 05:07:42 +00001218 /* ospf_route_delete (ospf->old_rtrs); */
1219 ospf_rtrs_free (ospf->old_rtrs);
paul718e3742002-12-13 20:15:29 +00001220 }
1221
paul68980082003-03-25 05:07:42 +00001222 ospf->old_rtrs = ospf->new_rtrs;
1223 ospf->new_rtrs = new_rtrs;
paul718e3742002-12-13 20:15:29 +00001224
paul0c0f9cd2003-06-06 23:27:04 +00001225 if (IS_OSPF_ABR (ospf))
paul68980082003-03-25 05:07:42 +00001226 ospf_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001227
1228 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001229 zlog_debug ("SPF: calculation complete");
paul718e3742002-12-13 20:15:29 +00001230
1231 return 0;
1232}
1233
1234/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
1235 set timer for SPF calc. */
1236void
paul68980082003-03-25 05:07:42 +00001237ospf_spf_calculate_schedule (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00001238{
pauld24f6e22005-10-21 09:23:12 +00001239 unsigned long delay, elapsed, ht;
1240 struct timeval result;
paul718e3742002-12-13 20:15:29 +00001241
1242 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001243 zlog_debug ("SPF: calculation timer scheduled");
paul718e3742002-12-13 20:15:29 +00001244
1245 /* OSPF instance does not exist. */
paul68980082003-03-25 05:07:42 +00001246 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001247 return;
pauld24f6e22005-10-21 09:23:12 +00001248
paul718e3742002-12-13 20:15:29 +00001249 /* SPF calculation timer is already scheduled. */
paul68980082003-03-25 05:07:42 +00001250 if (ospf->t_spf_calc)
paul718e3742002-12-13 20:15:29 +00001251 {
1252 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001253 zlog_debug ("SPF: calculation timer is already scheduled: %p",
paul0c0f9cd2003-06-06 23:27:04 +00001254 ospf->t_spf_calc);
paul718e3742002-12-13 20:15:29 +00001255 return;
1256 }
pauld24f6e22005-10-21 09:23:12 +00001257
1258 /* XXX Monotic timers: we only care about relative time here. */
Paul Jakma2518efd2006-08-27 06:49:29 +00001259 result = tv_sub (recent_relative_time (), ospf->ts_spf);
pauld24f6e22005-10-21 09:23:12 +00001260
1261 elapsed = (result.tv_sec * 1000) + (result.tv_usec / 1000);
1262 ht = ospf->spf_holdtime * ospf->spf_hold_multiplier;
1263
1264 if (ht > ospf->spf_max_holdtime)
1265 ht = ospf->spf_max_holdtime;
1266
paul718e3742002-12-13 20:15:29 +00001267 /* Get SPF calculation delay time. */
pauld24f6e22005-10-21 09:23:12 +00001268 if (elapsed < ht)
paul718e3742002-12-13 20:15:29 +00001269 {
pauld24f6e22005-10-21 09:23:12 +00001270 /* Got an event within the hold time of last SPF. We need to
1271 * increase the hold_multiplier, if it's not already at/past
1272 * maximum value, and wasn't already increased..
1273 */
1274 if (ht < ospf->spf_max_holdtime)
1275 ospf->spf_hold_multiplier++;
1276
1277 /* always honour the SPF initial delay */
1278 if ( (ht - elapsed) < ospf->spf_delay)
paul0c0f9cd2003-06-06 23:27:04 +00001279 delay = ospf->spf_delay;
paul718e3742002-12-13 20:15:29 +00001280 else
pauld24f6e22005-10-21 09:23:12 +00001281 delay = ht - elapsed;
paul718e3742002-12-13 20:15:29 +00001282 }
1283 else
pauld24f6e22005-10-21 09:23:12 +00001284 {
1285 /* Event is past required hold-time of last SPF */
1286 delay = ospf->spf_delay;
1287 ospf->spf_hold_multiplier = 1;
1288 }
1289
paul718e3742002-12-13 20:15:29 +00001290 if (IS_DEBUG_OSPF_EVENT)
pauld24f6e22005-10-21 09:23:12 +00001291 zlog_debug ("SPF: calculation timer delay = %ld", delay);
1292
paul68980082003-03-25 05:07:42 +00001293 ospf->t_spf_calc =
pauld24f6e22005-10-21 09:23:12 +00001294 thread_add_timer_msec (master, ospf_spf_calculate_timer, ospf, delay);
paul718e3742002-12-13 20:15:29 +00001295}