blob: 974875ebcbb8de57facadf998e8d70efd2ff8130 [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;
pauleb3da6d2005-10-18 04:20:33 +0000175 new->children = list_new ();
176 new->parents = list_new ();
Paul Jakma9c27ef92006-05-04 07:32:57 +0000177 new->parents->del = vertex_parent_free;
pauleb3da6d2005-10-18 04:20:33 +0000178
Paul Jakma9c27ef92006-05-04 07:32:57 +0000179 listnode_add (&vertex_list, new);
180
181 if (IS_DEBUG_OSPF_EVENT)
182 zlog_debug ("%s: Created %s vertex %s", __func__,
183 new->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
184 inet_ntoa (new->lsa->id));
paul718e3742002-12-13 20:15:29 +0000185 return new;
186}
187
paul4dadc292005-05-06 21:37:42 +0000188static void
Paul Jakma9c27ef92006-05-04 07:32:57 +0000189ospf_vertex_free (void *data)
paul718e3742002-12-13 20:15:29 +0000190{
Paul Jakma9c27ef92006-05-04 07:32:57 +0000191 struct vertex *v = data;
paul7461d452005-06-13 13:57:16 +0000192
Paul Jakma9c27ef92006-05-04 07:32:57 +0000193 if (IS_DEBUG_OSPF_EVENT)
194 zlog_debug ("%s: Free %s vertex %s", __func__,
195 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
196 inet_ntoa (v->lsa->id));
pauleb3da6d2005-10-18 04:20:33 +0000197
Paul Jakma9c27ef92006-05-04 07:32:57 +0000198 /* There should be no parents potentially holding references to this vertex
199 * Children however may still be there, but presumably referenced by other
200 * vertices
pauleb3da6d2005-10-18 04:20:33 +0000201 */
Paul Jakma9c27ef92006-05-04 07:32:57 +0000202 //assert (listcount (v->parents) == 0);
pauleb3da6d2005-10-18 04:20:33 +0000203
Paul Jakma9c27ef92006-05-04 07:32:57 +0000204 if (v->children)
205 list_delete (v->children);
206 v->children = NULL;
207
208 if (v->parents)
209 list_delete (v->parents);
pauleb3da6d2005-10-18 04:20:33 +0000210 v->parents = NULL;
211
212 v->lsa = NULL;
paul7461d452005-06-13 13:57:16 +0000213
paul718e3742002-12-13 20:15:29 +0000214 XFREE (MTYPE_OSPF_VERTEX, v);
215}
216
paul4dadc292005-05-06 21:37:42 +0000217static void
hassoeb1ce602004-10-08 08:17:22 +0000218ospf_vertex_dump(const char *msg, struct vertex *v,
pauleb3da6d2005-10-18 04:20:33 +0000219 int print_parents, int print_children)
gdt630e4802004-08-31 17:28:41 +0000220{
221 if ( ! IS_DEBUG_OSPF_EVENT)
222 return;
223
pauleb3da6d2005-10-18 04:20:33 +0000224 zlog_debug("%s %s vertex %s distance %u flags %u",
gdt630e4802004-08-31 17:28:41 +0000225 msg,
226 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
227 inet_ntoa(v->lsa->id),
228 v->distance,
gdt630e4802004-08-31 17:28:41 +0000229 (unsigned int)v->flags);
230
pauleb3da6d2005-10-18 04:20:33 +0000231 if (print_parents)
gdt630e4802004-08-31 17:28:41 +0000232 {
paul1eb8ef22005-04-07 07:30:20 +0000233 struct listnode *node;
pauleb3da6d2005-10-18 04:20:33 +0000234 struct vertex_parent *vp;
paul1eb8ef22005-04-07 07:30:20 +0000235
pauleb3da6d2005-10-18 04:20:33 +0000236 for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
gdt630e4802004-08-31 17:28:41 +0000237 {
238 char buf1[BUFSIZ];
pauleb3da6d2005-10-18 04:20:33 +0000239
240 if (vp)
gdt630e4802004-08-31 17:28:41 +0000241 {
pauleb3da6d2005-10-18 04:20:33 +0000242 zlog_debug ("parent %s backlink %d nexthop %s interface %s",
243 inet_ntoa(vp->parent->lsa->id), vp->backlink,
244 inet_ntop(AF_INET, &vp->nexthop->router, buf1, BUFSIZ),
245 vp->nexthop->oi ? IF_NAME(vp->nexthop->oi) : "NULL");
gdt630e4802004-08-31 17:28:41 +0000246 }
247 }
248 }
249
250 if (print_children)
251 {
hasso52dc7ee2004-09-23 19:18:23 +0000252 struct listnode *cnode;
paul1eb8ef22005-04-07 07:30:20 +0000253 struct vertex *cv;
254
pauleb3da6d2005-10-18 04:20:33 +0000255 for (ALL_LIST_ELEMENTS_RO (v->children, cnode, cv))
paul1eb8ef22005-04-07 07:30:20 +0000256 ospf_vertex_dump(" child:", cv, 0, 0);
gdt630e4802004-08-31 17:28:41 +0000257 }
258}
259
260
261/* Add a vertex to the list of children in each of its parents. */
paul4dadc292005-05-06 21:37:42 +0000262static void
paul718e3742002-12-13 20:15:29 +0000263ospf_vertex_add_parent (struct vertex *v)
264{
pauleb3da6d2005-10-18 04:20:33 +0000265 struct vertex_parent *vp;
hasso52dc7ee2004-09-23 19:18:23 +0000266 struct listnode *node;
paul7461d452005-06-13 13:57:16 +0000267
Paul Jakma9c27ef92006-05-04 07:32:57 +0000268 assert (v && v->parents);
paul7461d452005-06-13 13:57:16 +0000269
pauleb3da6d2005-10-18 04:20:33 +0000270 for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
paul718e3742002-12-13 20:15:29 +0000271 {
pauleb3da6d2005-10-18 04:20:33 +0000272 assert (vp->parent && vp->parent->children);
paul7461d452005-06-13 13:57:16 +0000273
paul718e3742002-12-13 20:15:29 +0000274 /* No need to add two links from the same parent. */
pauleb3da6d2005-10-18 04:20:33 +0000275 if (listnode_lookup (vp->parent->children, v) == NULL)
276 listnode_add (vp->parent->children, v);
paul718e3742002-12-13 20:15:29 +0000277 }
278}
279
paul4dadc292005-05-06 21:37:42 +0000280static void
paul718e3742002-12-13 20:15:29 +0000281ospf_spf_init (struct ospf_area *area)
282{
283 struct vertex *v;
Paul Jakma9c27ef92006-05-04 07:32:57 +0000284
paul718e3742002-12-13 20:15:29 +0000285 /* Create root node. */
286 v = ospf_vertex_new (area->router_lsa_self);
Paul Jakmabd34fb32007-02-26 17:14:48 +0000287
paul718e3742002-12-13 20:15:29 +0000288 area->spf = v;
289
290 /* Reset ABR and ASBR router counts. */
291 area->abr_count = 0;
292 area->asbr_count = 0;
293}
294
pauld355bfa2004-04-08 07:43:45 +0000295/* return index of link back to V from W, or -1 if no link found */
paul4dadc292005-05-06 21:37:42 +0000296static int
paul718e3742002-12-13 20:15:29 +0000297ospf_lsa_has_link (struct lsa_header *w, struct lsa_header *v)
298{
hassoeb1ce602004-10-08 08:17:22 +0000299 unsigned int i, length;
paul718e3742002-12-13 20:15:29 +0000300 struct router_lsa *rl;
301 struct network_lsa *nl;
302
303 /* In case of W is Network LSA. */
304 if (w->type == OSPF_NETWORK_LSA)
305 {
306 if (v->type == OSPF_NETWORK_LSA)
pauld355bfa2004-04-08 07:43:45 +0000307 return -1;
paul718e3742002-12-13 20:15:29 +0000308
309 nl = (struct network_lsa *) w;
310 length = (ntohs (w->length) - OSPF_LSA_HEADER_SIZE - 4) / 4;
paul0c0f9cd2003-06-06 23:27:04 +0000311
paul718e3742002-12-13 20:15:29 +0000312 for (i = 0; i < length; i++)
313 if (IPV4_ADDR_SAME (&nl->routers[i], &v->id))
pauld355bfa2004-04-08 07:43:45 +0000314 return i;
315 return -1;
paul718e3742002-12-13 20:15:29 +0000316 }
317
318 /* In case of W is Router LSA. */
319 if (w->type == OSPF_ROUTER_LSA)
320 {
321 rl = (struct router_lsa *) w;
322
323 length = ntohs (w->length);
324
325 for (i = 0;
paul0c0f9cd2003-06-06 23:27:04 +0000326 i < ntohs (rl->links) && length >= sizeof (struct router_lsa);
327 i++, length -= 12)
paul718e3742002-12-13 20:15:29 +0000328 {
329 switch (rl->link[i].type)
330 {
331 case LSA_LINK_TYPE_POINTOPOINT:
332 case LSA_LINK_TYPE_VIRTUALLINK:
333 /* Router LSA ID. */
334 if (v->type == OSPF_ROUTER_LSA &&
335 IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
336 {
pauld355bfa2004-04-08 07:43:45 +0000337 return i;
paul718e3742002-12-13 20:15:29 +0000338 }
339 break;
340 case LSA_LINK_TYPE_TRANSIT:
341 /* Network LSA ID. */
342 if (v->type == OSPF_NETWORK_LSA &&
343 IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
344 {
pauld355bfa2004-04-08 07:43:45 +0000345 return i;
paul0c0f9cd2003-06-06 23:27:04 +0000346 }
paul718e3742002-12-13 20:15:29 +0000347 break;
348 case LSA_LINK_TYPE_STUB:
pauleb3da6d2005-10-18 04:20:33 +0000349 /* Stub can't lead anywhere, carry on */
paul718e3742002-12-13 20:15:29 +0000350 continue;
351 default:
352 break;
353 }
354 }
355 }
pauld355bfa2004-04-08 07:43:45 +0000356 return -1;
paul718e3742002-12-13 20:15:29 +0000357}
358
gdt630e4802004-08-31 17:28:41 +0000359/* Find the next link after prev_link from v to w. If prev_link is
360 * NULL, return the first link from v to w. Ignore stub and virtual links;
361 * these link types will never be returned.
362 */
paul4dadc292005-05-06 21:37:42 +0000363static struct router_lsa_link *
paul718e3742002-12-13 20:15:29 +0000364ospf_get_next_link (struct vertex *v, struct vertex *w,
paul0c0f9cd2003-06-06 23:27:04 +0000365 struct router_lsa_link *prev_link)
paul718e3742002-12-13 20:15:29 +0000366{
367 u_char *p;
368 u_char *lim;
Joakim Tjernlundbd540372009-07-27 12:42:31 +0200369 u_char lsa_type = LSA_LINK_TYPE_TRANSIT;
paul718e3742002-12-13 20:15:29 +0000370 struct router_lsa_link *l;
371
Joakim Tjernlundbd540372009-07-27 12:42:31 +0200372 if (w->type == OSPF_VERTEX_ROUTER)
373 lsa_type = LSA_LINK_TYPE_POINTOPOINT;
374
paul718e3742002-12-13 20:15:29 +0000375 if (prev_link == NULL)
gdt630e4802004-08-31 17:28:41 +0000376 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +0000377 else
378 {
paul0c0f9cd2003-06-06 23:27:04 +0000379 p = (u_char *) prev_link;
Denis Ovsienko05b77092011-08-23 11:36:27 +0400380 p += (OSPF_ROUTER_LSA_LINK_SIZE +
381 (prev_link->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
paul718e3742002-12-13 20:15:29 +0000382 }
paul0c0f9cd2003-06-06 23:27:04 +0000383
paul718e3742002-12-13 20:15:29 +0000384 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
385
386 while (p < lim)
387 {
388 l = (struct router_lsa_link *) p;
389
Denis Ovsienko05b77092011-08-23 11:36:27 +0400390 p += (OSPF_ROUTER_LSA_LINK_SIZE + (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
paul718e3742002-12-13 20:15:29 +0000391
Joakim Tjernlundbd540372009-07-27 12:42:31 +0200392 if (l->m[0].type != lsa_type)
paul0c0f9cd2003-06-06 23:27:04 +0000393 continue;
paul718e3742002-12-13 20:15:29 +0000394
395 if (IPV4_ADDR_SAME (&l->link_id, &w->id))
paul0c0f9cd2003-06-06 23:27:04 +0000396 return l;
paul718e3742002-12-13 20:15:29 +0000397 }
398
399 return NULL;
400}
401
pauleb3da6d2005-10-18 04:20:33 +0000402static void
403ospf_spf_flush_parents (struct vertex *w)
404{
405 struct vertex_parent *vp;
406 struct listnode *ln, *nn;
407
408 /* delete the existing nexthops */
409 for (ALL_LIST_ELEMENTS (w->parents, ln, nn, vp))
410 {
411 list_delete_node (w->parents, ln);
412 vertex_parent_free (vp);
413 }
414}
415
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000416/*
417 * Consider supplied next-hop for inclusion to the supplied list of
418 * equal-cost next-hops, adjust list as neccessary.
419 */
420static void
421ospf_spf_add_parent (struct vertex *v, struct vertex *w,
422 struct vertex_nexthop *newhop,
Paul Jakmabd34fb32007-02-26 17:14:48 +0000423 unsigned int distance)
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000424{
David Lamparter7b925892012-07-23 18:17:57 +0200425 struct vertex_parent *vp, *wp;
426 struct listnode *node;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000427
Paul Jakma08d3d5b2007-05-07 16:38:35 +0000428 /* we must have a newhop, and a distance */
Paul Jakmabd34fb32007-02-26 17:14:48 +0000429 assert (v && w && newhop);
Paul Jakma08d3d5b2007-05-07 16:38:35 +0000430 assert (distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000431
Paul Jakma08d3d5b2007-05-07 16:38:35 +0000432 /* IFF w has already been assigned a distance, then we shouldn't get here
433 * unless callers have determined V(l)->W is shortest / equal-shortest
434 * path (0 is a special case distance (no distance yet assigned)).
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000435 */
Paul Jakma08d3d5b2007-05-07 16:38:35 +0000436 if (w->distance)
437 assert (distance <= w->distance);
438 else
439 w->distance = distance;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000440
Paul Jakmab75ae992007-03-23 11:17:28 +0000441 if (IS_DEBUG_OSPF_EVENT)
442 {
443 char buf[2][INET_ADDRSTRLEN];
444 zlog_debug ("%s: Adding %s as parent of %s",
445 __func__,
446 inet_ntop(AF_INET, &v->lsa->id, buf[0], sizeof(buf[0])),
447 inet_ntop(AF_INET, &w->lsa->id, buf[1], sizeof(buf[1])));
448 }
449
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000450 /* Adding parent for a new, better path: flush existing parents from W. */
Paul Jakmabd34fb32007-02-26 17:14:48 +0000451 if (distance < w->distance)
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000452 {
Paul Jakmab75ae992007-03-23 11:17:28 +0000453 if (IS_DEBUG_OSPF_EVENT)
454 zlog_debug ("%s: distance %d better than %d, flushing existing parents",
455 __func__, distance, w->distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000456 ospf_spf_flush_parents (w);
Paul Jakmabd34fb32007-02-26 17:14:48 +0000457 w->distance = distance;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000458 }
459
David Lamparter7b925892012-07-23 18:17:57 +0200460 /* new parent is <= existing parents, add it to parent list (if nexthop
461 * not on parent list)
462 */
463 for (ALL_LIST_ELEMENTS_RO(w->parents, node, wp))
464 {
465 if (memcmp(newhop, wp->nexthop, sizeof(*newhop)) == 0)
466 {
467 if (IS_DEBUG_OSPF_EVENT)
468 zlog_debug ("%s: ... nexthop already on parent list, skipping add", __func__);
469 return;
470 }
471 }
472
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000473 vp = vertex_parent_new (v, ospf_lsa_has_link (w->lsa, v->lsa), newhop);
474 listnode_add (w->parents, vp);
475
476 return;
477}
478
gdt630e4802004-08-31 17:28:41 +0000479/* 16.1.1. Calculate nexthop from root through V (parent) to
Paul Jakmabd34fb32007-02-26 17:14:48 +0000480 * vertex W (destination), with given distance from root->W.
pauleb3da6d2005-10-18 04:20:33 +0000481 *
482 * The link must be supplied if V is the root vertex. In all other cases
483 * it may be NULL.
Paul Jakmabd34fb32007-02-26 17:14:48 +0000484 *
485 * Note that this function may fail, hence the state of the destination
486 * vertex, W, should /not/ be modified in a dependent manner until
487 * this function returns. This function will update the W vertex with the
488 * provided distance as appropriate.
gdt630e4802004-08-31 17:28:41 +0000489 */
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000490static unsigned int
pauleb3da6d2005-10-18 04:20:33 +0000491ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v,
Paul Jakmabd34fb32007-02-26 17:14:48 +0000492 struct vertex *w, struct router_lsa_link *l,
493 unsigned int distance)
paul718e3742002-12-13 20:15:29 +0000494{
paul1eb8ef22005-04-07 07:30:20 +0000495 struct listnode *node, *nnode;
pauleb3da6d2005-10-18 04:20:33 +0000496 struct vertex_nexthop *nh;
497 struct vertex_parent *vp;
paul718e3742002-12-13 20:15:29 +0000498 struct ospf_interface *oi = NULL;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000499 unsigned int added = 0;
paul0c0f9cd2003-06-06 23:27:04 +0000500
paul718e3742002-12-13 20:15:29 +0000501 if (IS_DEBUG_OSPF_EVENT)
gdt630e4802004-08-31 17:28:41 +0000502 {
ajs2a42e282004-12-08 18:43:03 +0000503 zlog_debug ("ospf_nexthop_calculation(): Start");
gdt630e4802004-08-31 17:28:41 +0000504 ospf_vertex_dump("V (parent):", v, 1, 1);
505 ospf_vertex_dump("W (dest) :", w, 1, 1);
Paul Jakmabd34fb32007-02-26 17:14:48 +0000506 zlog_debug ("V->W distance: %d", distance);
gdt630e4802004-08-31 17:28:41 +0000507 }
paul718e3742002-12-13 20:15:29 +0000508
paul718e3742002-12-13 20:15:29 +0000509 if (v == area->spf)
Paul Jakma9c27ef92006-05-04 07:32:57 +0000510 {
gdt630e4802004-08-31 17:28:41 +0000511 /* 16.1.1 para 4. In the first case, the parent vertex (V) is the
512 root (the calculating router itself). This means that the
513 destination is either a directly connected network or directly
514 connected router. The outgoing interface in this case is simply
515 the OSPF interface connecting to the destination network/router.
516 */
517
paul718e3742002-12-13 20:15:29 +0000518 if (w->type == OSPF_VERTEX_ROUTER)
paul0c0f9cd2003-06-06 23:27:04 +0000519 {
pauleb3da6d2005-10-18 04:20:33 +0000520 /* l is a link from v to w
521 * l2 will be link from w to v
522 */
523 struct router_lsa_link *l2 = NULL;
524
525 /* we *must* be supplied with the link data */
526 assert (l != NULL);
527
528 if (IS_DEBUG_OSPF_EVENT)
paul0c0f9cd2003-06-06 23:27:04 +0000529 {
pauleb3da6d2005-10-18 04:20:33 +0000530 char buf1[BUFSIZ];
531 char buf2[BUFSIZ];
532
533 zlog_debug("ospf_nexthop_calculation(): considering link "
534 "type %d link_id %s link_data %s",
535 l->m[0].type,
536 inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ),
537 inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ));
538 }
paul0c0f9cd2003-06-06 23:27:04 +0000539
pauleb3da6d2005-10-18 04:20:33 +0000540 if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT)
541 {
542 /* If the destination is a router which connects to
543 the calculating router via a Point-to-MultiPoint
544 network, the destination's next hop IP address(es)
545 can be determined by examining the destination's
546 router-LSA: each link pointing back to the
547 calculating router and having a Link Data field
548 belonging to the Point-to-MultiPoint network
549 provides an IP address of the next hop router.
gdt630e4802004-08-31 17:28:41 +0000550
pauleb3da6d2005-10-18 04:20:33 +0000551 At this point l is a link from V to W, and V is the
552 root ("us"). Find the local interface associated
553 with l (its address is in l->link_data). If it
554 is a point-to-multipoint interface, then look through
555 the links in the opposite direction (W to V). If
556 any of them have an address that lands within the
557 subnet declared by the PtMP link, then that link
558 is a constituent of the PtMP link, and its address is
559 a nexthop address for V.
560 */
561 oi = ospf_if_is_configured (area->ospf, &l->link_data);
562 if (oi && oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
paul0c0f9cd2003-06-06 23:27:04 +0000563 {
pauleb3da6d2005-10-18 04:20:33 +0000564 struct prefix_ipv4 la;
gdt630e4802004-08-31 17:28:41 +0000565
pauleb3da6d2005-10-18 04:20:33 +0000566 la.family = AF_INET;
567 la.prefixlen = oi->address->prefixlen;
568
569 /* V links to W on PtMP interface
570 - find the interface address on W */
571 while ((l2 = ospf_get_next_link (w, v, l2)))
paul0c0f9cd2003-06-06 23:27:04 +0000572 {
pauleb3da6d2005-10-18 04:20:33 +0000573 la.prefix = l2->link_data;
gdt630e4802004-08-31 17:28:41 +0000574
pauleb3da6d2005-10-18 04:20:33 +0000575 if (prefix_cmp ((struct prefix *) &la,
576 oi->address) == 0)
577 /* link_data is on our PtMP network */
578 break;
paul0c0f9cd2003-06-06 23:27:04 +0000579 }
pauleb3da6d2005-10-18 04:20:33 +0000580 } /* end l is on point-to-multipoint link */
581 else
582 {
583 /* l is a regular point-to-point link.
584 Look for a link from W to V.
585 */
586 while ((l2 = ospf_get_next_link (w, v, l2)))
paul0c0f9cd2003-06-06 23:27:04 +0000587 {
pauleb3da6d2005-10-18 04:20:33 +0000588 oi = ospf_if_is_configured (area->ospf,
589 &(l2->link_data));
590
591 if (oi == NULL)
592 continue;
593
594 if (!IPV4_ADDR_SAME (&oi->address->u.prefix4,
595 &l->link_data))
596 continue;
597
598 break;
paul0c0f9cd2003-06-06 23:27:04 +0000599 }
pauleb3da6d2005-10-18 04:20:33 +0000600 }
601
602 if (oi && l2)
603 {
604 /* found all necessary info to build nexthop */
605 nh = vertex_nexthop_new ();
606 nh->oi = oi;
607 nh->router = l2->link_data;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000608 ospf_spf_add_parent (v, w, nh, distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000609 return 1;
pauleb3da6d2005-10-18 04:20:33 +0000610 }
611 else
Paul Jakma9c27ef92006-05-04 07:32:57 +0000612 zlog_info("ospf_nexthop_calculation(): "
613 "could not determine nexthop for link");
pauleb3da6d2005-10-18 04:20:33 +0000614 } /* end point-to-point link from V to W */
Paul Jakma9c27ef92006-05-04 07:32:57 +0000615 else if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK)
616 {
617 struct ospf_vl_data *vl_data;
618
619 /* VLink implementation limitations:
620 * a) vl_data can only reference one nexthop, so no ECMP
621 * to backbone through VLinks. Though transit-area
622 * summaries may be considered, and those can be ECMP.
623 * b) We can only use /one/ VLink, even if multiple ones
624 * exist this router through multiple transit-areas.
625 */
626 vl_data = ospf_vl_lookup (area->ospf, NULL, l->link_id);
627
628 if (vl_data
629 && CHECK_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED))
630 {
631 nh = vertex_nexthop_new ();
632 nh->oi = vl_data->nexthop.oi;
633 nh->router = vl_data->nexthop.router;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000634 ospf_spf_add_parent (v, w, nh, distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000635 return 1;
Paul Jakma9c27ef92006-05-04 07:32:57 +0000636 }
637 else
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000638 zlog_info("ospf_nexthop_calculation(): "
639 "vl_data for VL link not found");
Paul Jakma9c27ef92006-05-04 07:32:57 +0000640 } /* end virtual-link from V to W */
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000641 return 0;
gdt630e4802004-08-31 17:28:41 +0000642 } /* end W is a Router vertex */
paul718e3742002-12-13 20:15:29 +0000643 else
paul0c0f9cd2003-06-06 23:27:04 +0000644 {
pauleb3da6d2005-10-18 04:20:33 +0000645 assert(w->type == OSPF_VERTEX_NETWORK);
646 oi = ospf_if_is_configured (area->ospf, &(l->link_data));
647 if (oi)
paul0c0f9cd2003-06-06 23:27:04 +0000648 {
pauleb3da6d2005-10-18 04:20:33 +0000649 nh = vertex_nexthop_new ();
650 nh->oi = oi;
651 nh->router.s_addr = 0;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000652 ospf_spf_add_parent (v, w, nh, distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000653 return 1;
paul0c0f9cd2003-06-06 23:27:04 +0000654 }
655 }
Paul Jakma9c27ef92006-05-04 07:32:57 +0000656 zlog_info("ospf_nexthop_calculation(): "
657 "Unknown attached link");
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000658 return 0;
gdt630e4802004-08-31 17:28:41 +0000659 } /* end V is the root */
gdt630e4802004-08-31 17:28:41 +0000660 /* Check if W's parent is a network connected to root. */
paul718e3742002-12-13 20:15:29 +0000661 else if (v->type == OSPF_VERTEX_NETWORK)
662 {
gdt630e4802004-08-31 17:28:41 +0000663 /* See if any of V's parents are the root. */
pauleb3da6d2005-10-18 04:20:33 +0000664 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
paul718e3742002-12-13 20:15:29 +0000665 {
pauleb3da6d2005-10-18 04:20:33 +0000666 if (vp->parent == area->spf) /* connects to root? */
gdt630e4802004-08-31 17:28:41 +0000667 {
668 /* 16.1.1 para 5. ...the parent vertex is a network that
669 * directly connects the calculating router to the destination
670 * router. The list of next hops is then determined by
671 * examining the destination's router-LSA...
672 */
673
674 assert(w->type == OSPF_VERTEX_ROUTER);
paul0c0f9cd2003-06-06 23:27:04 +0000675 while ((l = ospf_get_next_link (w, v, l)))
676 {
gdt630e4802004-08-31 17:28:41 +0000677 /* ...For each link in the router-LSA that points back to the
678 * parent network, the link's Link Data field provides the IP
679 * address of a next hop router. The outgoing interface to
680 * use can then be derived from the next hop IP address (or
681 * it can be inherited from the parent network).
682 */
pauleb3da6d2005-10-18 04:20:33 +0000683 nh = vertex_nexthop_new ();
684 nh->oi = vp->nexthop->oi;
685 nh->router = l->link_data;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000686 added = 1;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000687 ospf_spf_add_parent (v, w, nh, distance);
paul0c0f9cd2003-06-06 23:27:04 +0000688 }
paul0c0f9cd2003-06-06 23:27:04 +0000689 }
paul718e3742002-12-13 20:15:29 +0000690 }
Paul Jakma4ca15d42009-08-03 15:16:41 +0100691 /* NB: This code is non-trivial.
692 *
693 * E.g. it is not enough to know that V connects to the root. It is
694 * also important that the while above, looping through all links from
695 * W->V found at least one link, so that we know there is
696 * bi-directional connectivity between V and W. Otherwise, if we
697 * /always/ return here, but don't check that W->V exists then we
698 * we will prevent SPF from finding/using higher cost paths..
699 *
700 * See also bug #330, and also:
701 *
702 * http://blogs.sun.com/paulj/entry/the_difference_a_line_makes
703 */
Paul Jakma85ef7842007-03-23 11:19:08 +0000704 if (added)
705 return added;
paul718e3742002-12-13 20:15:29 +0000706 }
707
gdt630e4802004-08-31 17:28:41 +0000708 /* 16.1.1 para 4. If there is at least one intervening router in the
709 * current shortest path between the destination and the root, the
710 * destination simply inherits the set of next hops from the
711 * parent.
712 */
Paul Jakmab75ae992007-03-23 11:17:28 +0000713 if (IS_DEBUG_OSPF_EVENT)
714 zlog_debug ("%s: Intervening routers, adding parent(s)", __func__);
715
pauleb3da6d2005-10-18 04:20:33 +0000716 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000717 {
718 added = 1;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000719 ospf_spf_add_parent (v, w, vp->nexthop, distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000720 }
Paul Jakma9c27ef92006-05-04 07:32:57 +0000721
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000722 return added;
paul718e3742002-12-13 20:15:29 +0000723}
724
gdt630e4802004-08-31 17:28:41 +0000725/* RFC2328 Section 16.1 (2).
726 * v is on the SPF tree. Examine the links in v's LSA. Update the list
727 * of candidates with any vertices not already on the list. If a lower-cost
728 * path is found to a vertex already on the candidate list, store the new cost.
729 */
paul4dadc292005-05-06 21:37:42 +0000730static void
paul718e3742002-12-13 20:15:29 +0000731ospf_spf_next (struct vertex *v, struct ospf_area *area,
hasso462f20d2005-02-23 11:29:02 +0000732 struct pqueue * candidate)
paul718e3742002-12-13 20:15:29 +0000733{
734 struct ospf_lsa *w_lsa = NULL;
paul718e3742002-12-13 20:15:29 +0000735 u_char *p;
736 u_char *lim;
737 struct router_lsa_link *l = NULL;
738 struct in_addr *r;
paul718e3742002-12-13 20:15:29 +0000739 int type = 0;
740
741 /* If this is a router-LSA, and bit V of the router-LSA (see Section
742 A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE. */
743 if (v->type == OSPF_VERTEX_ROUTER)
744 {
745 if (IS_ROUTER_LSA_VIRTUAL ((struct router_lsa *) v->lsa))
746 area->transit = OSPF_TRANSIT_TRUE;
747 }
Paul Jakmab75ae992007-03-23 11:17:28 +0000748
749 if (IS_DEBUG_OSPF_EVENT)
750 zlog_debug ("%s: Next vertex of %s vertex %s",
751 __func__,
752 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
753 inet_ntoa(v->lsa->id));
754
paul718e3742002-12-13 20:15:29 +0000755 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul0c0f9cd2003-06-06 23:27:04 +0000756 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
757
paul718e3742002-12-13 20:15:29 +0000758 while (p < lim)
759 {
pauleb3da6d2005-10-18 04:20:33 +0000760 struct vertex *w;
761 unsigned int distance;
pauld355bfa2004-04-08 07:43:45 +0000762
paul718e3742002-12-13 20:15:29 +0000763 /* In case of V is Router-LSA. */
764 if (v->lsa->type == OSPF_ROUTER_LSA)
765 {
766 l = (struct router_lsa_link *) p;
767
Denis Ovsienko05b77092011-08-23 11:36:27 +0400768 p += (OSPF_ROUTER_LSA_LINK_SIZE +
769 (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
paul718e3742002-12-13 20:15:29 +0000770
771 /* (a) If this is a link to a stub network, examine the next
772 link in V's LSA. Links to stub networks will be
773 considered in the second stage of the shortest path
774 calculation. */
775 if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB)
776 continue;
Paul Jakma08d3d5b2007-05-07 16:38:35 +0000777
778 /* Infinite distance links shouldn't be followed, except
779 * for local links (a stub-routed router still wants to
780 * calculate tree, so must follow its own links).
781 */
782 if ((v != area->spf) && l->m[0].metric >= OSPF_OUTPUT_COST_INFINITE)
783 continue;
paul718e3742002-12-13 20:15:29 +0000784
785 /* (b) Otherwise, W is a transit vertex (router or transit
786 network). Look up the vertex W's LSA (router-LSA or
787 network-LSA) in Area A's link state database. */
788 switch (type)
789 {
790 case LSA_LINK_TYPE_POINTOPOINT:
791 case LSA_LINK_TYPE_VIRTUALLINK:
792 if (type == LSA_LINK_TYPE_VIRTUALLINK)
paul0c0f9cd2003-06-06 23:27:04 +0000793 {
794 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000795 zlog_debug ("looking up LSA through VL: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000796 inet_ntoa (l->link_id));
797 }
paul718e3742002-12-13 20:15:29 +0000798
799 w_lsa = ospf_lsa_lookup (area, OSPF_ROUTER_LSA, l->link_id,
800 l->link_id);
801 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000802 {
803 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000804 zlog_debug ("found Router LSA %s", inet_ntoa (l->link_id));
paul0c0f9cd2003-06-06 23:27:04 +0000805 }
paul718e3742002-12-13 20:15:29 +0000806 break;
807 case LSA_LINK_TYPE_TRANSIT:
paul0c0f9cd2003-06-06 23:27:04 +0000808 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000809 zlog_debug ("Looking up Network LSA, ID: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000810 inet_ntoa (l->link_id));
paul718e3742002-12-13 20:15:29 +0000811 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_NETWORK_LSA,
paul0c0f9cd2003-06-06 23:27:04 +0000812 l->link_id);
paul718e3742002-12-13 20:15:29 +0000813 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000814 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000815 zlog_debug ("found the LSA");
paul718e3742002-12-13 20:15:29 +0000816 break;
817 default:
paul0c0f9cd2003-06-06 23:27:04 +0000818 zlog_warn ("Invalid LSA link type %d", type);
paul718e3742002-12-13 20:15:29 +0000819 continue;
820 }
821 }
822 else
823 {
824 /* In case of V is Network-LSA. */
paul0c0f9cd2003-06-06 23:27:04 +0000825 r = (struct in_addr *) p;
paul718e3742002-12-13 20:15:29 +0000826 p += sizeof (struct in_addr);
827
828 /* Lookup the vertex W's LSA. */
829 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_ROUTER_LSA, *r);
Paul Jakmab75ae992007-03-23 11:17:28 +0000830 if (w_lsa)
831 {
832 if (IS_DEBUG_OSPF_EVENT)
833 zlog_debug ("found Router LSA %s", inet_ntoa (w_lsa->data->id));
834 }
paul718e3742002-12-13 20:15:29 +0000835 }
836
837 /* (b cont.) If the LSA does not exist, or its LS age is equal
838 to MaxAge, or it does not have a link back to vertex V,
839 examine the next link in V's LSA.[23] */
840 if (w_lsa == NULL)
Paul Jakmab75ae992007-03-23 11:17:28 +0000841 {
842 if (IS_DEBUG_OSPF_EVENT)
843 zlog_debug ("No LSA found");
844 continue;
845 }
paul718e3742002-12-13 20:15:29 +0000846
847 if (IS_LSA_MAXAGE (w_lsa))
Paul Jakmab75ae992007-03-23 11:17:28 +0000848 {
849 if (IS_DEBUG_OSPF_EVENT)
850 zlog_debug ("LSA is MaxAge");
851 continue;
852 }
paul718e3742002-12-13 20:15:29 +0000853
pauleb3da6d2005-10-18 04:20:33 +0000854 if (ospf_lsa_has_link (w_lsa->data, v->lsa) < 0 )
paul718e3742002-12-13 20:15:29 +0000855 {
paul0c0f9cd2003-06-06 23:27:04 +0000856 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000857 zlog_debug ("The LSA doesn't have a link back");
paul718e3742002-12-13 20:15:29 +0000858 continue;
859 }
860
861 /* (c) If vertex W is already on the shortest-path tree, examine
862 the next link in the LSA. */
hasso462f20d2005-02-23 11:29:02 +0000863 if (w_lsa->stat == LSA_SPF_IN_SPFTREE)
864 {
865 if (IS_DEBUG_OSPF_EVENT)
866 zlog_debug ("The LSA is already in SPF");
867 continue;
868 }
paul718e3742002-12-13 20:15:29 +0000869
870 /* (d) Calculate the link state cost D of the resulting path
871 from the root to vertex W. D is equal to the sum of the link
872 state cost of the (already calculated) shortest path to
873 vertex V and the advertised cost of the link between vertices
874 V and W. If D is: */
875
paul718e3742002-12-13 20:15:29 +0000876 /* calculate link cost D. */
877 if (v->lsa->type == OSPF_ROUTER_LSA)
pauleb3da6d2005-10-18 04:20:33 +0000878 distance = v->distance + ntohs (l->m[0].metric);
gdt630e4802004-08-31 17:28:41 +0000879 else /* v is not a Router-LSA */
pauleb3da6d2005-10-18 04:20:33 +0000880 distance = v->distance;
paul718e3742002-12-13 20:15:29 +0000881
882 /* Is there already vertex W in candidate list? */
hasso462f20d2005-02-23 11:29:02 +0000883 if (w_lsa->stat == LSA_SPF_NOT_EXPLORED)
884 {
pauleb3da6d2005-10-18 04:20:33 +0000885 /* prepare vertex W. */
886 w = ospf_vertex_new (w_lsa);
887
hasso462f20d2005-02-23 11:29:02 +0000888 /* Calculate nexthop to W. */
Paul Jakmabd34fb32007-02-26 17:14:48 +0000889 if (ospf_nexthop_calculation (area, v, w, l, distance))
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000890 pqueue_enqueue (w, candidate);
Paul Jakmab75ae992007-03-23 11:17:28 +0000891 else if (IS_DEBUG_OSPF_EVENT)
892 zlog_debug ("Nexthop Calc failed");
hasso462f20d2005-02-23 11:29:02 +0000893 }
894 else if (w_lsa->stat >= 0)
895 {
896 /* Get the vertex from candidates. */
pauleb3da6d2005-10-18 04:20:33 +0000897 w = candidate->array[w_lsa->stat];
paul718e3742002-12-13 20:15:29 +0000898
hasso462f20d2005-02-23 11:29:02 +0000899 /* if D is greater than. */
pauleb3da6d2005-10-18 04:20:33 +0000900 if (w->distance < distance)
paul718e3742002-12-13 20:15:29 +0000901 {
paul718e3742002-12-13 20:15:29 +0000902 continue;
903 }
hasso462f20d2005-02-23 11:29:02 +0000904 /* equal to. */
pauleb3da6d2005-10-18 04:20:33 +0000905 else if (w->distance == distance)
paul718e3742002-12-13 20:15:29 +0000906 {
pauleb3da6d2005-10-18 04:20:33 +0000907 /* Found an equal-cost path to W.
908 * Calculate nexthop of to W from V. */
Paul Jakmabd34fb32007-02-26 17:14:48 +0000909 ospf_nexthop_calculation (area, v, w, l, distance);
paul718e3742002-12-13 20:15:29 +0000910 }
hasso462f20d2005-02-23 11:29:02 +0000911 /* less than. */
912 else
paul718e3742002-12-13 20:15:29 +0000913 {
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000914 /* Found a lower-cost path to W.
915 * nexthop_calculation is conditional, if it finds
916 * valid nexthop it will call spf_add_parents, which
917 * will flush the old parents
918 */
Paul Jakmabd34fb32007-02-26 17:14:48 +0000919 if (ospf_nexthop_calculation (area, v, w, l, distance))
Paul Jakma7591d8b2007-08-06 18:52:45 +0000920 /* Decrease the key of the node in the heap.
921 * trickle-sort it up towards root, just in case this
922 * node should now be the new root due the cost change.
Paul Jakmae95537f2007-08-07 16:22:05 +0000923 * (next pqueu_{de,en}queue will fully re-heap the queue).
Paul Jakma7591d8b2007-08-06 18:52:45 +0000924 */
925 trickle_up (w_lsa->stat, candidate);
paul718e3742002-12-13 20:15:29 +0000926 }
gdt630e4802004-08-31 17:28:41 +0000927 } /* end W is already on the candidate list */
928 } /* end loop over the links in V's LSA */
paul718e3742002-12-13 20:15:29 +0000929}
930
paul4dadc292005-05-06 21:37:42 +0000931static void
paul718e3742002-12-13 20:15:29 +0000932ospf_spf_dump (struct vertex *v, int i)
933{
hasso52dc7ee2004-09-23 19:18:23 +0000934 struct listnode *cnode;
935 struct listnode *nnode;
pauleb3da6d2005-10-18 04:20:33 +0000936 struct vertex_parent *parent;
paul718e3742002-12-13 20:15:29 +0000937
938 if (v->type == OSPF_VERTEX_ROUTER)
939 {
940 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000941 zlog_debug ("SPF Result: %d [R] %s", i, inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000942 }
943 else
944 {
945 struct network_lsa *lsa = (struct network_lsa *) v->lsa;
946 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000947 zlog_debug ("SPF Result: %d [N] %s/%d", i, inet_ntoa (v->lsa->id),
paul0c0f9cd2003-06-06 23:27:04 +0000948 ip_masklen (lsa->mask));
gdt630e4802004-08-31 17:28:41 +0000949 }
paul718e3742002-12-13 20:15:29 +0000950
paul1eb8ef22005-04-07 07:30:20 +0000951 if (IS_DEBUG_OSPF_EVENT)
pauleb3da6d2005-10-18 04:20:33 +0000952 for (ALL_LIST_ELEMENTS_RO (v->parents, nnode, parent))
953 {
954 zlog_debug (" nexthop %p %s %s",
955 parent->nexthop,
956 inet_ntoa (parent->nexthop->router),
957 parent->nexthop->oi ? IF_NAME(parent->nexthop->oi)
958 : "NULL");
959 }
paul718e3742002-12-13 20:15:29 +0000960
961 i++;
962
pauleb3da6d2005-10-18 04:20:33 +0000963 for (ALL_LIST_ELEMENTS_RO (v->children, cnode, v))
paul1eb8ef22005-04-07 07:30:20 +0000964 ospf_spf_dump (v, i);
paul718e3742002-12-13 20:15:29 +0000965}
966
967/* Second stage of SPF calculation. */
paul4dadc292005-05-06 21:37:42 +0000968static void
paul0c0f9cd2003-06-06 23:27:04 +0000969ospf_spf_process_stubs (struct ospf_area *area, struct vertex *v,
Paul Jakmab3bc68e2008-09-04 13:52:07 +0100970 struct route_table *rt,
971 int parent_is_root)
paul718e3742002-12-13 20:15:29 +0000972{
paul1eb8ef22005-04-07 07:30:20 +0000973 struct listnode *cnode, *cnnode;
paul718e3742002-12-13 20:15:29 +0000974 struct vertex *child;
975
976 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000977 zlog_debug ("ospf_process_stub():processing stubs for area %s",
paul0c0f9cd2003-06-06 23:27:04 +0000978 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +0000979 if (v->type == OSPF_VERTEX_ROUTER)
980 {
981 u_char *p;
982 u_char *lim;
983 struct router_lsa_link *l;
984 struct router_lsa *rlsa;
985
paul0c0f9cd2003-06-06 23:27:04 +0000986 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000987 zlog_debug ("ospf_process_stubs():processing router LSA, id: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000988 inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000989 rlsa = (struct router_lsa *) v->lsa;
990
991
paul0c0f9cd2003-06-06 23:27:04 +0000992 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000993 zlog_debug ("ospf_process_stubs(): we have %d links to process",
paul0c0f9cd2003-06-06 23:27:04 +0000994 ntohs (rlsa->links));
gdt630e4802004-08-31 17:28:41 +0000995 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +0000996 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
997
998 while (p < lim)
999 {
1000 l = (struct router_lsa_link *) p;
1001
Denis Ovsienko05b77092011-08-23 11:36:27 +04001002 p += (OSPF_ROUTER_LSA_LINK_SIZE +
1003 (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
paul718e3742002-12-13 20:15:29 +00001004
1005 if (l->m[0].type == LSA_LINK_TYPE_STUB)
Paul Jakmab3bc68e2008-09-04 13:52:07 +01001006 ospf_intra_add_stub (rt, l, v, area, parent_is_root);
paul718e3742002-12-13 20:15:29 +00001007 }
1008 }
1009
gdt630e4802004-08-31 17:28:41 +00001010 ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1, 1);
paul718e3742002-12-13 20:15:29 +00001011
pauleb3da6d2005-10-18 04:20:33 +00001012 for (ALL_LIST_ELEMENTS (v->children, cnode, cnnode, child))
paul718e3742002-12-13 20:15:29 +00001013 {
paul718e3742002-12-13 20:15:29 +00001014 if (CHECK_FLAG (child->flags, OSPF_VERTEX_PROCESSED))
paul0c0f9cd2003-06-06 23:27:04 +00001015 continue;
Paul Jakmab3bc68e2008-09-04 13:52:07 +01001016
1017 /* the first level of routers connected to the root
1018 * should have 'parent_is_root' set, including those
1019 * connected via a network vertex.
1020 */
1021 if (area->spf == v)
1022 parent_is_root = 1;
1023 else if (v->type == OSPF_VERTEX_ROUTER)
1024 parent_is_root = 0;
1025
1026 ospf_spf_process_stubs (area, child, rt, parent_is_root);
paul718e3742002-12-13 20:15:29 +00001027
1028 SET_FLAG (child->flags, OSPF_VERTEX_PROCESSED);
1029 }
1030}
1031
1032void
1033ospf_rtrs_free (struct route_table *rtrs)
1034{
1035 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001036 struct list *or_list;
paul1eb8ef22005-04-07 07:30:20 +00001037 struct ospf_route *or;
1038 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001039
1040 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001041 zlog_debug ("Route: Router Routing Table free");
paul718e3742002-12-13 20:15:29 +00001042
1043 for (rn = route_top (rtrs); rn; rn = route_next (rn))
1044 if ((or_list = rn->info) != NULL)
1045 {
paul1eb8ef22005-04-07 07:30:20 +00001046 for (ALL_LIST_ELEMENTS (or_list, node, nnode, or))
1047 ospf_route_free (or);
paul718e3742002-12-13 20:15:29 +00001048
paul0c0f9cd2003-06-06 23:27:04 +00001049 list_delete (or_list);
paul718e3742002-12-13 20:15:29 +00001050
paul0c0f9cd2003-06-06 23:27:04 +00001051 /* Unlock the node. */
1052 rn->info = NULL;
1053 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001054 }
1055 route_table_finish (rtrs);
1056}
1057
Stephen Hemminger075e12f2011-12-06 23:54:17 +04001058#if 0
paul4dadc292005-05-06 21:37:42 +00001059static void
paul718e3742002-12-13 20:15:29 +00001060ospf_rtrs_print (struct route_table *rtrs)
1061{
1062 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001063 struct list *or_list;
1064 struct listnode *ln;
1065 struct listnode *pnode;
paul718e3742002-12-13 20:15:29 +00001066 struct ospf_route *or;
1067 struct ospf_path *path;
1068 char buf1[BUFSIZ];
1069 char buf2[BUFSIZ];
1070
1071 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001072 zlog_debug ("ospf_rtrs_print() start");
paul718e3742002-12-13 20:15:29 +00001073
1074 for (rn = route_top (rtrs); rn; rn = route_next (rn))
1075 if ((or_list = rn->info) != NULL)
paul1eb8ef22005-04-07 07:30:20 +00001076 for (ALL_LIST_ELEMENTS_RO (or_list, ln, or))
paul718e3742002-12-13 20:15:29 +00001077 {
paul718e3742002-12-13 20:15:29 +00001078 switch (or->path_type)
1079 {
1080 case OSPF_PATH_INTRA_AREA:
paul0c0f9cd2003-06-06 23:27:04 +00001081 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001082 zlog_debug ("%s [%d] area: %s",
paul0c0f9cd2003-06-06 23:27:04 +00001083 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1084 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1085 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +00001086 break;
1087 case OSPF_PATH_INTER_AREA:
paul0c0f9cd2003-06-06 23:27:04 +00001088 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001089 zlog_debug ("%s IA [%d] area: %s",
paul0c0f9cd2003-06-06 23:27:04 +00001090 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1091 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1092 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +00001093 break;
1094 default:
1095 break;
1096 }
1097
paul1eb8ef22005-04-07 07:30:20 +00001098 for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path))
paul718e3742002-12-13 20:15:29 +00001099 {
paul718e3742002-12-13 20:15:29 +00001100 if (path->nexthop.s_addr == 0)
paul0c0f9cd2003-06-06 23:27:04 +00001101 {
1102 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001103 zlog_debug (" directly attached to %s\r\n",
Joakim Tjernlunda8ba8472009-07-27 12:42:34 +02001104 ifindex2ifname (path->ifindex));
paul0c0f9cd2003-06-06 23:27:04 +00001105 }
1106 else
1107 {
1108 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001109 zlog_debug (" via %s, %s\r\n",
Joakim Tjernlunda8ba8472009-07-27 12:42:34 +02001110 inet_ntoa (path->nexthop),
1111 ifindex2ifname (path->ifindex));
paul0c0f9cd2003-06-06 23:27:04 +00001112 }
paul718e3742002-12-13 20:15:29 +00001113 }
1114 }
1115
ajs2a42e282004-12-08 18:43:03 +00001116 zlog_debug ("ospf_rtrs_print() end");
paul718e3742002-12-13 20:15:29 +00001117}
Stephen Hemminger075e12f2011-12-06 23:54:17 +04001118#endif
paul718e3742002-12-13 20:15:29 +00001119
1120/* Calculating the shortest-path tree for an area. */
paul4dadc292005-05-06 21:37:42 +00001121static void
paul0c0f9cd2003-06-06 23:27:04 +00001122ospf_spf_calculate (struct ospf_area *area, struct route_table *new_table,
paul718e3742002-12-13 20:15:29 +00001123 struct route_table *new_rtrs)
1124{
hasso462f20d2005-02-23 11:29:02 +00001125 struct pqueue *candidate;
paul718e3742002-12-13 20:15:29 +00001126 struct vertex *v;
pauleb3da6d2005-10-18 04:20:33 +00001127
paul718e3742002-12-13 20:15:29 +00001128 if (IS_DEBUG_OSPF_EVENT)
1129 {
ajs2a42e282004-12-08 18:43:03 +00001130 zlog_debug ("ospf_spf_calculate: Start");
1131 zlog_debug ("ospf_spf_calculate: running Dijkstra for area %s",
paul0c0f9cd2003-06-06 23:27:04 +00001132 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001133 }
1134
1135 /* Check router-lsa-self. If self-router-lsa is not yet allocated,
1136 return this area's calculation. */
paul0c0f9cd2003-06-06 23:27:04 +00001137 if (!area->router_lsa_self)
paul718e3742002-12-13 20:15:29 +00001138 {
1139 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001140 zlog_debug ("ospf_spf_calculate: "
paul0c0f9cd2003-06-06 23:27:04 +00001141 "Skip area %s's calculation due to empty router_lsa_self",
1142 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001143 return;
1144 }
1145
1146 /* RFC2328 16.1. (1). */
paul0c0f9cd2003-06-06 23:27:04 +00001147 /* Initialize the algorithm's data structures. */
hasso462f20d2005-02-23 11:29:02 +00001148
1149 /* This function scans all the LSA database and set the stat field to
1150 * LSA_SPF_NOT_EXPLORED. */
1151 ospf_lsdb_clean_stat (area->lsdb);
1152 /* Create a new heap for the candidates. */
1153 candidate = pqueue_create();
1154 candidate->cmp = cmp;
1155 candidate->update = update_stat;
paul718e3742002-12-13 20:15:29 +00001156
1157 /* Initialize the shortest-path tree to only the root (which is the
1158 router doing the calculation). */
1159 ospf_spf_init (area);
1160 v = area->spf;
hasso462f20d2005-02-23 11:29:02 +00001161 /* Set LSA position to LSA_SPF_IN_SPFTREE. This vertex is the root of the
1162 * spanning tree. */
1163 *(v->stat) = LSA_SPF_IN_SPFTREE;
paul718e3742002-12-13 20:15:29 +00001164
1165 /* Set Area A's TransitCapability to FALSE. */
1166 area->transit = OSPF_TRANSIT_FALSE;
1167 area->shortcut_capability = 1;
pauleb3da6d2005-10-18 04:20:33 +00001168
paul718e3742002-12-13 20:15:29 +00001169 for (;;)
1170 {
1171 /* RFC2328 16.1. (2). */
hasso462f20d2005-02-23 11:29:02 +00001172 ospf_spf_next (v, area, candidate);
paul718e3742002-12-13 20:15:29 +00001173
1174 /* RFC2328 16.1. (3). */
1175 /* If at this step the candidate list is empty, the shortest-
1176 path tree (of transit vertices) has been completely built and
1177 this stage of the procedure terminates. */
hasso462f20d2005-02-23 11:29:02 +00001178 if (candidate->size == 0)
paul718e3742002-12-13 20:15:29 +00001179 break;
1180
1181 /* Otherwise, choose the vertex belonging to the candidate list
1182 that is closest to the root, and add it to the shortest-path
1183 tree (removing it from the candidate list in the
paul0c0f9cd2003-06-06 23:27:04 +00001184 process). */
hasso462f20d2005-02-23 11:29:02 +00001185 /* Extract from the candidates the node with the lower key. */
1186 v = (struct vertex *) pqueue_dequeue (candidate);
1187 /* Update stat field in vertex. */
1188 *(v->stat) = LSA_SPF_IN_SPFTREE;
pauleb3da6d2005-10-18 04:20:33 +00001189
paul718e3742002-12-13 20:15:29 +00001190 ospf_vertex_add_parent (v);
1191
paul718e3742002-12-13 20:15:29 +00001192 /* RFC2328 16.1. (4). */
1193 if (v->type == OSPF_VERTEX_ROUTER)
1194 ospf_intra_add_router (new_rtrs, v, area);
paul0c0f9cd2003-06-06 23:27:04 +00001195 else
paul718e3742002-12-13 20:15:29 +00001196 ospf_intra_add_transit (new_table, v, area);
1197
1198 /* RFC2328 16.1. (5). */
1199 /* Iterate the algorithm by returning to Step 2. */
gdt630e4802004-08-31 17:28:41 +00001200
1201 } /* end loop until no more candidate vertices */
paul718e3742002-12-13 20:15:29 +00001202
1203 if (IS_DEBUG_OSPF_EVENT)
1204 {
1205 ospf_spf_dump (area->spf, 0);
1206 ospf_route_table_dump (new_table);
1207 }
1208
1209 /* Second stage of SPF calculation procedure's */
Paul Jakmab3bc68e2008-09-04 13:52:07 +01001210 ospf_spf_process_stubs (area, area->spf, new_table, 0);
paul718e3742002-12-13 20:15:29 +00001211
pauleb3da6d2005-10-18 04:20:33 +00001212 /* Free candidate queue. */
hasso462f20d2005-02-23 11:29:02 +00001213 pqueue_delete (candidate);
pauleb3da6d2005-10-18 04:20:33 +00001214
1215 ospf_vertex_dump (__func__, area->spf, 0, 1);
1216 /* Free nexthop information, canonical versions of which are attached
1217 * the first level of router vertices attached to the root vertex, see
1218 * ospf_nexthop_calculation.
1219 */
1220 ospf_canonical_nexthops_free (area->spf);
1221
Paul Jakma9c27ef92006-05-04 07:32:57 +00001222 /* Free SPF vertices, but not the list. List has ospf_vertex_free
1223 * as deconstructor.
1224 */
1225 list_delete_all_node (&vertex_list);
pauleb3da6d2005-10-18 04:20:33 +00001226
paul718e3742002-12-13 20:15:29 +00001227 /* Increment SPF Calculation Counter. */
1228 area->spf_calculation++;
1229
Paul Jakma2518efd2006-08-27 06:49:29 +00001230 quagga_gettime (QUAGGA_CLK_MONOTONIC, &area->ospf->ts_spf);
paul718e3742002-12-13 20:15:29 +00001231
1232 if (IS_DEBUG_OSPF_EVENT)
Paul Jakma9c27ef92006-05-04 07:32:57 +00001233 zlog_debug ("ospf_spf_calculate: Stop. %ld vertices",
1234 mtype_stats_alloc(MTYPE_OSPF_VERTEX));
paul718e3742002-12-13 20:15:29 +00001235}
1236
1237/* Timer for SPF calculation. */
paul4dadc292005-05-06 21:37:42 +00001238static int
paul68980082003-03-25 05:07:42 +00001239ospf_spf_calculate_timer (struct thread *thread)
paul718e3742002-12-13 20:15:29 +00001240{
paul68980082003-03-25 05:07:42 +00001241 struct ospf *ospf = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +00001242 struct route_table *new_table, *new_rtrs;
paul1eb8ef22005-04-07 07:30:20 +00001243 struct ospf_area *area;
1244 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001245
1246 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001247 zlog_debug ("SPF: Timer (SPF calculation expire)");
paul0c0f9cd2003-06-06 23:27:04 +00001248
paul718e3742002-12-13 20:15:29 +00001249 ospf->t_spf_calc = NULL;
1250
1251 /* Allocate new table tree. */
1252 new_table = route_table_init ();
paul0c0f9cd2003-06-06 23:27:04 +00001253 new_rtrs = route_table_init ();
paul718e3742002-12-13 20:15:29 +00001254
paul68980082003-03-25 05:07:42 +00001255 ospf_vl_unapprove (ospf);
paul718e3742002-12-13 20:15:29 +00001256
1257 /* Calculate SPF for each area. */
paul1eb8ef22005-04-07 07:30:20 +00001258 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
Paul Jakma9c27ef92006-05-04 07:32:57 +00001259 {
1260 /* Do backbone last, so as to first discover intra-area paths
1261 * for any back-bone virtual-links
1262 */
1263 if (ospf->backbone && ospf->backbone == area)
1264 continue;
1265
1266 ospf_spf_calculate (area, new_table, new_rtrs);
1267 }
1268
1269 /* SPF for backbone, if required */
1270 if (ospf->backbone)
1271 ospf_spf_calculate (ospf->backbone, new_table, new_rtrs);
1272
paul68980082003-03-25 05:07:42 +00001273 ospf_vl_shut_unapproved (ospf);
paul718e3742002-12-13 20:15:29 +00001274
paul68980082003-03-25 05:07:42 +00001275 ospf_ia_routing (ospf, new_table, new_rtrs);
paul718e3742002-12-13 20:15:29 +00001276
1277 ospf_prune_unreachable_networks (new_table);
1278 ospf_prune_unreachable_routers (new_rtrs);
1279
1280 /* AS-external-LSA calculation should not be performed here. */
1281
1282 /* If new Router Route is installed,
1283 then schedule re-calculate External routes. */
1284 if (1)
paul68980082003-03-25 05:07:42 +00001285 ospf_ase_calculate_schedule (ospf);
paul718e3742002-12-13 20:15:29 +00001286
paul68980082003-03-25 05:07:42 +00001287 ospf_ase_calculate_timer_add (ospf);
paul718e3742002-12-13 20:15:29 +00001288
1289 /* Update routing table. */
paul68980082003-03-25 05:07:42 +00001290 ospf_route_install (ospf, new_table);
paul718e3742002-12-13 20:15:29 +00001291
1292 /* Update ABR/ASBR routing table */
paul68980082003-03-25 05:07:42 +00001293 if (ospf->old_rtrs)
paul718e3742002-12-13 20:15:29 +00001294 {
1295 /* old_rtrs's node holds linked list of ospf_route. --kunihiro. */
paul68980082003-03-25 05:07:42 +00001296 /* ospf_route_delete (ospf->old_rtrs); */
1297 ospf_rtrs_free (ospf->old_rtrs);
paul718e3742002-12-13 20:15:29 +00001298 }
1299
paul68980082003-03-25 05:07:42 +00001300 ospf->old_rtrs = ospf->new_rtrs;
1301 ospf->new_rtrs = new_rtrs;
paul718e3742002-12-13 20:15:29 +00001302
paul0c0f9cd2003-06-06 23:27:04 +00001303 if (IS_OSPF_ABR (ospf))
paul68980082003-03-25 05:07:42 +00001304 ospf_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001305
1306 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001307 zlog_debug ("SPF: calculation complete");
paul718e3742002-12-13 20:15:29 +00001308
1309 return 0;
1310}
1311
1312/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
1313 set timer for SPF calc. */
1314void
paul68980082003-03-25 05:07:42 +00001315ospf_spf_calculate_schedule (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00001316{
pauld24f6e22005-10-21 09:23:12 +00001317 unsigned long delay, elapsed, ht;
1318 struct timeval result;
paul718e3742002-12-13 20:15:29 +00001319
1320 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001321 zlog_debug ("SPF: calculation timer scheduled");
paul718e3742002-12-13 20:15:29 +00001322
1323 /* OSPF instance does not exist. */
paul68980082003-03-25 05:07:42 +00001324 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001325 return;
pauld24f6e22005-10-21 09:23:12 +00001326
paul718e3742002-12-13 20:15:29 +00001327 /* SPF calculation timer is already scheduled. */
paul68980082003-03-25 05:07:42 +00001328 if (ospf->t_spf_calc)
paul718e3742002-12-13 20:15:29 +00001329 {
1330 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001331 zlog_debug ("SPF: calculation timer is already scheduled: %p",
paul0c0f9cd2003-06-06 23:27:04 +00001332 ospf->t_spf_calc);
paul718e3742002-12-13 20:15:29 +00001333 return;
1334 }
pauld24f6e22005-10-21 09:23:12 +00001335
1336 /* XXX Monotic timers: we only care about relative time here. */
Paul Jakma2518efd2006-08-27 06:49:29 +00001337 result = tv_sub (recent_relative_time (), ospf->ts_spf);
pauld24f6e22005-10-21 09:23:12 +00001338
1339 elapsed = (result.tv_sec * 1000) + (result.tv_usec / 1000);
1340 ht = ospf->spf_holdtime * ospf->spf_hold_multiplier;
1341
1342 if (ht > ospf->spf_max_holdtime)
1343 ht = ospf->spf_max_holdtime;
1344
paul718e3742002-12-13 20:15:29 +00001345 /* Get SPF calculation delay time. */
pauld24f6e22005-10-21 09:23:12 +00001346 if (elapsed < ht)
paul718e3742002-12-13 20:15:29 +00001347 {
pauld24f6e22005-10-21 09:23:12 +00001348 /* Got an event within the hold time of last SPF. We need to
1349 * increase the hold_multiplier, if it's not already at/past
1350 * maximum value, and wasn't already increased..
1351 */
1352 if (ht < ospf->spf_max_holdtime)
1353 ospf->spf_hold_multiplier++;
1354
1355 /* always honour the SPF initial delay */
1356 if ( (ht - elapsed) < ospf->spf_delay)
paul0c0f9cd2003-06-06 23:27:04 +00001357 delay = ospf->spf_delay;
paul718e3742002-12-13 20:15:29 +00001358 else
pauld24f6e22005-10-21 09:23:12 +00001359 delay = ht - elapsed;
paul718e3742002-12-13 20:15:29 +00001360 }
1361 else
pauld24f6e22005-10-21 09:23:12 +00001362 {
1363 /* Event is past required hold-time of last SPF */
1364 delay = ospf->spf_delay;
1365 ospf->spf_hold_multiplier = 1;
1366 }
1367
paul718e3742002-12-13 20:15:29 +00001368 if (IS_DEBUG_OSPF_EVENT)
pauld24f6e22005-10-21 09:23:12 +00001369 zlog_debug ("SPF: calculation timer delay = %ld", delay);
1370
paul68980082003-03-25 05:07:42 +00001371 ospf->t_spf_calc =
pauld24f6e22005-10-21 09:23:12 +00001372 thread_add_timer_msec (master, ospf_spf_calculate_timer, ospf, delay);
paul718e3742002-12-13 20:15:29 +00001373}