blob: d7f9ba27d0060de4584205b37da4eda8c0a83c98 [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{
425 struct vertex_parent *vp;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000426
Paul Jakma08d3d5b2007-05-07 16:38:35 +0000427 /* we must have a newhop, and a distance */
Paul Jakmabd34fb32007-02-26 17:14:48 +0000428 assert (v && w && newhop);
Paul Jakma08d3d5b2007-05-07 16:38:35 +0000429 assert (distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000430
Paul Jakma08d3d5b2007-05-07 16:38:35 +0000431 /* IFF w has already been assigned a distance, then we shouldn't get here
432 * unless callers have determined V(l)->W is shortest / equal-shortest
433 * path (0 is a special case distance (no distance yet assigned)).
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000434 */
Paul Jakma08d3d5b2007-05-07 16:38:35 +0000435 if (w->distance)
436 assert (distance <= w->distance);
437 else
438 w->distance = distance;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000439
Paul Jakmab75ae992007-03-23 11:17:28 +0000440 if (IS_DEBUG_OSPF_EVENT)
441 {
442 char buf[2][INET_ADDRSTRLEN];
443 zlog_debug ("%s: Adding %s as parent of %s",
444 __func__,
445 inet_ntop(AF_INET, &v->lsa->id, buf[0], sizeof(buf[0])),
446 inet_ntop(AF_INET, &w->lsa->id, buf[1], sizeof(buf[1])));
447 }
448
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000449 /* Adding parent for a new, better path: flush existing parents from W. */
Paul Jakmabd34fb32007-02-26 17:14:48 +0000450 if (distance < w->distance)
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000451 {
Paul Jakmab75ae992007-03-23 11:17:28 +0000452 if (IS_DEBUG_OSPF_EVENT)
453 zlog_debug ("%s: distance %d better than %d, flushing existing parents",
454 __func__, distance, w->distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000455 ospf_spf_flush_parents (w);
Paul Jakmabd34fb32007-02-26 17:14:48 +0000456 w->distance = distance;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000457 }
458
459 /* new parent is <= existing parents, add it to parent list */
460 vp = vertex_parent_new (v, ospf_lsa_has_link (w->lsa, v->lsa), newhop);
461 listnode_add (w->parents, vp);
462
463 return;
464}
465
gdt630e4802004-08-31 17:28:41 +0000466/* 16.1.1. Calculate nexthop from root through V (parent) to
Paul Jakmabd34fb32007-02-26 17:14:48 +0000467 * vertex W (destination), with given distance from root->W.
pauleb3da6d2005-10-18 04:20:33 +0000468 *
469 * The link must be supplied if V is the root vertex. In all other cases
470 * it may be NULL.
Paul Jakmabd34fb32007-02-26 17:14:48 +0000471 *
472 * Note that this function may fail, hence the state of the destination
473 * vertex, W, should /not/ be modified in a dependent manner until
474 * this function returns. This function will update the W vertex with the
475 * provided distance as appropriate.
gdt630e4802004-08-31 17:28:41 +0000476 */
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000477static unsigned int
pauleb3da6d2005-10-18 04:20:33 +0000478ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v,
Paul Jakmabd34fb32007-02-26 17:14:48 +0000479 struct vertex *w, struct router_lsa_link *l,
480 unsigned int distance)
paul718e3742002-12-13 20:15:29 +0000481{
paul1eb8ef22005-04-07 07:30:20 +0000482 struct listnode *node, *nnode;
pauleb3da6d2005-10-18 04:20:33 +0000483 struct vertex_nexthop *nh;
484 struct vertex_parent *vp;
paul718e3742002-12-13 20:15:29 +0000485 struct ospf_interface *oi = NULL;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000486 unsigned int added = 0;
paul0c0f9cd2003-06-06 23:27:04 +0000487
paul718e3742002-12-13 20:15:29 +0000488 if (IS_DEBUG_OSPF_EVENT)
gdt630e4802004-08-31 17:28:41 +0000489 {
ajs2a42e282004-12-08 18:43:03 +0000490 zlog_debug ("ospf_nexthop_calculation(): Start");
gdt630e4802004-08-31 17:28:41 +0000491 ospf_vertex_dump("V (parent):", v, 1, 1);
492 ospf_vertex_dump("W (dest) :", w, 1, 1);
Paul Jakmabd34fb32007-02-26 17:14:48 +0000493 zlog_debug ("V->W distance: %d", distance);
gdt630e4802004-08-31 17:28:41 +0000494 }
paul718e3742002-12-13 20:15:29 +0000495
paul718e3742002-12-13 20:15:29 +0000496 if (v == area->spf)
Paul Jakma9c27ef92006-05-04 07:32:57 +0000497 {
gdt630e4802004-08-31 17:28:41 +0000498 /* 16.1.1 para 4. In the first case, the parent vertex (V) is the
499 root (the calculating router itself). This means that the
500 destination is either a directly connected network or directly
501 connected router. The outgoing interface in this case is simply
502 the OSPF interface connecting to the destination network/router.
503 */
504
paul718e3742002-12-13 20:15:29 +0000505 if (w->type == OSPF_VERTEX_ROUTER)
paul0c0f9cd2003-06-06 23:27:04 +0000506 {
pauleb3da6d2005-10-18 04:20:33 +0000507 /* l is a link from v to w
508 * l2 will be link from w to v
509 */
510 struct router_lsa_link *l2 = NULL;
511
512 /* we *must* be supplied with the link data */
513 assert (l != NULL);
514
515 if (IS_DEBUG_OSPF_EVENT)
paul0c0f9cd2003-06-06 23:27:04 +0000516 {
pauleb3da6d2005-10-18 04:20:33 +0000517 char buf1[BUFSIZ];
518 char buf2[BUFSIZ];
519
520 zlog_debug("ospf_nexthop_calculation(): considering link "
521 "type %d link_id %s link_data %s",
522 l->m[0].type,
523 inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ),
524 inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ));
525 }
paul0c0f9cd2003-06-06 23:27:04 +0000526
pauleb3da6d2005-10-18 04:20:33 +0000527 if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT)
528 {
529 /* If the destination is a router which connects to
530 the calculating router via a Point-to-MultiPoint
531 network, the destination's next hop IP address(es)
532 can be determined by examining the destination's
533 router-LSA: each link pointing back to the
534 calculating router and having a Link Data field
535 belonging to the Point-to-MultiPoint network
536 provides an IP address of the next hop router.
gdt630e4802004-08-31 17:28:41 +0000537
pauleb3da6d2005-10-18 04:20:33 +0000538 At this point l is a link from V to W, and V is the
539 root ("us"). Find the local interface associated
540 with l (its address is in l->link_data). If it
541 is a point-to-multipoint interface, then look through
542 the links in the opposite direction (W to V). If
543 any of them have an address that lands within the
544 subnet declared by the PtMP link, then that link
545 is a constituent of the PtMP link, and its address is
546 a nexthop address for V.
547 */
548 oi = ospf_if_is_configured (area->ospf, &l->link_data);
549 if (oi && oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
paul0c0f9cd2003-06-06 23:27:04 +0000550 {
pauleb3da6d2005-10-18 04:20:33 +0000551 struct prefix_ipv4 la;
gdt630e4802004-08-31 17:28:41 +0000552
pauleb3da6d2005-10-18 04:20:33 +0000553 la.family = AF_INET;
554 la.prefixlen = oi->address->prefixlen;
555
556 /* V links to W on PtMP interface
557 - find the interface address on W */
558 while ((l2 = ospf_get_next_link (w, v, l2)))
paul0c0f9cd2003-06-06 23:27:04 +0000559 {
pauleb3da6d2005-10-18 04:20:33 +0000560 la.prefix = l2->link_data;
gdt630e4802004-08-31 17:28:41 +0000561
pauleb3da6d2005-10-18 04:20:33 +0000562 if (prefix_cmp ((struct prefix *) &la,
563 oi->address) == 0)
564 /* link_data is on our PtMP network */
565 break;
paul0c0f9cd2003-06-06 23:27:04 +0000566 }
pauleb3da6d2005-10-18 04:20:33 +0000567 } /* end l is on point-to-multipoint link */
568 else
569 {
570 /* l is a regular point-to-point link.
571 Look for a link from W to V.
572 */
573 while ((l2 = ospf_get_next_link (w, v, l2)))
paul0c0f9cd2003-06-06 23:27:04 +0000574 {
pauleb3da6d2005-10-18 04:20:33 +0000575 oi = ospf_if_is_configured (area->ospf,
576 &(l2->link_data));
577
578 if (oi == NULL)
579 continue;
580
581 if (!IPV4_ADDR_SAME (&oi->address->u.prefix4,
582 &l->link_data))
583 continue;
584
585 break;
paul0c0f9cd2003-06-06 23:27:04 +0000586 }
pauleb3da6d2005-10-18 04:20:33 +0000587 }
588
589 if (oi && l2)
590 {
591 /* found all necessary info to build nexthop */
592 nh = vertex_nexthop_new ();
593 nh->oi = oi;
594 nh->router = l2->link_data;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000595 ospf_spf_add_parent (v, w, nh, distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000596 return 1;
pauleb3da6d2005-10-18 04:20:33 +0000597 }
598 else
Paul Jakma9c27ef92006-05-04 07:32:57 +0000599 zlog_info("ospf_nexthop_calculation(): "
600 "could not determine nexthop for link");
pauleb3da6d2005-10-18 04:20:33 +0000601 } /* end point-to-point link from V to W */
Paul Jakma9c27ef92006-05-04 07:32:57 +0000602 else if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK)
603 {
604 struct ospf_vl_data *vl_data;
605
606 /* VLink implementation limitations:
607 * a) vl_data can only reference one nexthop, so no ECMP
608 * to backbone through VLinks. Though transit-area
609 * summaries may be considered, and those can be ECMP.
610 * b) We can only use /one/ VLink, even if multiple ones
611 * exist this router through multiple transit-areas.
612 */
613 vl_data = ospf_vl_lookup (area->ospf, NULL, l->link_id);
614
615 if (vl_data
616 && CHECK_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED))
617 {
618 nh = vertex_nexthop_new ();
619 nh->oi = vl_data->nexthop.oi;
620 nh->router = vl_data->nexthop.router;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000621 ospf_spf_add_parent (v, w, nh, distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000622 return 1;
Paul Jakma9c27ef92006-05-04 07:32:57 +0000623 }
624 else
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000625 zlog_info("ospf_nexthop_calculation(): "
626 "vl_data for VL link not found");
Paul Jakma9c27ef92006-05-04 07:32:57 +0000627 } /* end virtual-link from V to W */
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000628 return 0;
gdt630e4802004-08-31 17:28:41 +0000629 } /* end W is a Router vertex */
paul718e3742002-12-13 20:15:29 +0000630 else
paul0c0f9cd2003-06-06 23:27:04 +0000631 {
pauleb3da6d2005-10-18 04:20:33 +0000632 assert(w->type == OSPF_VERTEX_NETWORK);
633 oi = ospf_if_is_configured (area->ospf, &(l->link_data));
634 if (oi)
paul0c0f9cd2003-06-06 23:27:04 +0000635 {
pauleb3da6d2005-10-18 04:20:33 +0000636 nh = vertex_nexthop_new ();
637 nh->oi = oi;
638 nh->router.s_addr = 0;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000639 ospf_spf_add_parent (v, w, nh, distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000640 return 1;
paul0c0f9cd2003-06-06 23:27:04 +0000641 }
642 }
Paul Jakma9c27ef92006-05-04 07:32:57 +0000643 zlog_info("ospf_nexthop_calculation(): "
644 "Unknown attached link");
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000645 return 0;
gdt630e4802004-08-31 17:28:41 +0000646 } /* end V is the root */
gdt630e4802004-08-31 17:28:41 +0000647 /* Check if W's parent is a network connected to root. */
paul718e3742002-12-13 20:15:29 +0000648 else if (v->type == OSPF_VERTEX_NETWORK)
649 {
gdt630e4802004-08-31 17:28:41 +0000650 /* See if any of V's parents are the root. */
pauleb3da6d2005-10-18 04:20:33 +0000651 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
paul718e3742002-12-13 20:15:29 +0000652 {
pauleb3da6d2005-10-18 04:20:33 +0000653 if (vp->parent == area->spf) /* connects to root? */
gdt630e4802004-08-31 17:28:41 +0000654 {
655 /* 16.1.1 para 5. ...the parent vertex is a network that
656 * directly connects the calculating router to the destination
657 * router. The list of next hops is then determined by
658 * examining the destination's router-LSA...
659 */
660
661 assert(w->type == OSPF_VERTEX_ROUTER);
paul0c0f9cd2003-06-06 23:27:04 +0000662 while ((l = ospf_get_next_link (w, v, l)))
663 {
gdt630e4802004-08-31 17:28:41 +0000664 /* ...For each link in the router-LSA that points back to the
665 * parent network, the link's Link Data field provides the IP
666 * address of a next hop router. The outgoing interface to
667 * use can then be derived from the next hop IP address (or
668 * it can be inherited from the parent network).
669 */
pauleb3da6d2005-10-18 04:20:33 +0000670 nh = vertex_nexthop_new ();
671 nh->oi = vp->nexthop->oi;
672 nh->router = l->link_data;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000673 added = 1;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000674 ospf_spf_add_parent (v, w, nh, distance);
paul0c0f9cd2003-06-06 23:27:04 +0000675 }
paul0c0f9cd2003-06-06 23:27:04 +0000676 }
paul718e3742002-12-13 20:15:29 +0000677 }
Paul Jakma4ca15d42009-08-03 15:16:41 +0100678 /* NB: This code is non-trivial.
679 *
680 * E.g. it is not enough to know that V connects to the root. It is
681 * also important that the while above, looping through all links from
682 * W->V found at least one link, so that we know there is
683 * bi-directional connectivity between V and W. Otherwise, if we
684 * /always/ return here, but don't check that W->V exists then we
685 * we will prevent SPF from finding/using higher cost paths..
686 *
687 * See also bug #330, and also:
688 *
689 * http://blogs.sun.com/paulj/entry/the_difference_a_line_makes
690 */
Paul Jakma85ef7842007-03-23 11:19:08 +0000691 if (added)
692 return added;
paul718e3742002-12-13 20:15:29 +0000693 }
694
gdt630e4802004-08-31 17:28:41 +0000695 /* 16.1.1 para 4. If there is at least one intervening router in the
696 * current shortest path between the destination and the root, the
697 * destination simply inherits the set of next hops from the
698 * parent.
699 */
Paul Jakmab75ae992007-03-23 11:17:28 +0000700 if (IS_DEBUG_OSPF_EVENT)
701 zlog_debug ("%s: Intervening routers, adding parent(s)", __func__);
702
pauleb3da6d2005-10-18 04:20:33 +0000703 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000704 {
705 added = 1;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000706 ospf_spf_add_parent (v, w, vp->nexthop, distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000707 }
Paul Jakma9c27ef92006-05-04 07:32:57 +0000708
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000709 return added;
paul718e3742002-12-13 20:15:29 +0000710}
711
gdt630e4802004-08-31 17:28:41 +0000712/* RFC2328 Section 16.1 (2).
713 * v is on the SPF tree. Examine the links in v's LSA. Update the list
714 * of candidates with any vertices not already on the list. If a lower-cost
715 * path is found to a vertex already on the candidate list, store the new cost.
716 */
paul4dadc292005-05-06 21:37:42 +0000717static void
paul718e3742002-12-13 20:15:29 +0000718ospf_spf_next (struct vertex *v, struct ospf_area *area,
hasso462f20d2005-02-23 11:29:02 +0000719 struct pqueue * candidate)
paul718e3742002-12-13 20:15:29 +0000720{
721 struct ospf_lsa *w_lsa = NULL;
paul718e3742002-12-13 20:15:29 +0000722 u_char *p;
723 u_char *lim;
724 struct router_lsa_link *l = NULL;
725 struct in_addr *r;
paul718e3742002-12-13 20:15:29 +0000726 int type = 0;
727
728 /* If this is a router-LSA, and bit V of the router-LSA (see Section
729 A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE. */
730 if (v->type == OSPF_VERTEX_ROUTER)
731 {
732 if (IS_ROUTER_LSA_VIRTUAL ((struct router_lsa *) v->lsa))
733 area->transit = OSPF_TRANSIT_TRUE;
734 }
Paul Jakmab75ae992007-03-23 11:17:28 +0000735
736 if (IS_DEBUG_OSPF_EVENT)
737 zlog_debug ("%s: Next vertex of %s vertex %s",
738 __func__,
739 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
740 inet_ntoa(v->lsa->id));
741
paul718e3742002-12-13 20:15:29 +0000742 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul0c0f9cd2003-06-06 23:27:04 +0000743 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
744
paul718e3742002-12-13 20:15:29 +0000745 while (p < lim)
746 {
pauleb3da6d2005-10-18 04:20:33 +0000747 struct vertex *w;
748 unsigned int distance;
pauld355bfa2004-04-08 07:43:45 +0000749
paul718e3742002-12-13 20:15:29 +0000750 /* In case of V is Router-LSA. */
751 if (v->lsa->type == OSPF_ROUTER_LSA)
752 {
753 l = (struct router_lsa_link *) p;
754
Denis Ovsienko05b77092011-08-23 11:36:27 +0400755 p += (OSPF_ROUTER_LSA_LINK_SIZE +
756 (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
paul718e3742002-12-13 20:15:29 +0000757
758 /* (a) If this is a link to a stub network, examine the next
759 link in V's LSA. Links to stub networks will be
760 considered in the second stage of the shortest path
761 calculation. */
762 if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB)
763 continue;
Paul Jakma08d3d5b2007-05-07 16:38:35 +0000764
765 /* Infinite distance links shouldn't be followed, except
766 * for local links (a stub-routed router still wants to
767 * calculate tree, so must follow its own links).
768 */
769 if ((v != area->spf) && l->m[0].metric >= OSPF_OUTPUT_COST_INFINITE)
770 continue;
paul718e3742002-12-13 20:15:29 +0000771
772 /* (b) Otherwise, W is a transit vertex (router or transit
773 network). Look up the vertex W's LSA (router-LSA or
774 network-LSA) in Area A's link state database. */
775 switch (type)
776 {
777 case LSA_LINK_TYPE_POINTOPOINT:
778 case LSA_LINK_TYPE_VIRTUALLINK:
779 if (type == LSA_LINK_TYPE_VIRTUALLINK)
paul0c0f9cd2003-06-06 23:27:04 +0000780 {
781 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000782 zlog_debug ("looking up LSA through VL: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000783 inet_ntoa (l->link_id));
784 }
paul718e3742002-12-13 20:15:29 +0000785
786 w_lsa = ospf_lsa_lookup (area, OSPF_ROUTER_LSA, l->link_id,
787 l->link_id);
788 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000789 {
790 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000791 zlog_debug ("found Router LSA %s", inet_ntoa (l->link_id));
paul0c0f9cd2003-06-06 23:27:04 +0000792 }
paul718e3742002-12-13 20:15:29 +0000793 break;
794 case LSA_LINK_TYPE_TRANSIT:
paul0c0f9cd2003-06-06 23:27:04 +0000795 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000796 zlog_debug ("Looking up Network LSA, ID: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000797 inet_ntoa (l->link_id));
paul718e3742002-12-13 20:15:29 +0000798 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_NETWORK_LSA,
paul0c0f9cd2003-06-06 23:27:04 +0000799 l->link_id);
paul718e3742002-12-13 20:15:29 +0000800 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000801 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000802 zlog_debug ("found the LSA");
paul718e3742002-12-13 20:15:29 +0000803 break;
804 default:
paul0c0f9cd2003-06-06 23:27:04 +0000805 zlog_warn ("Invalid LSA link type %d", type);
paul718e3742002-12-13 20:15:29 +0000806 continue;
807 }
808 }
809 else
810 {
811 /* In case of V is Network-LSA. */
paul0c0f9cd2003-06-06 23:27:04 +0000812 r = (struct in_addr *) p;
paul718e3742002-12-13 20:15:29 +0000813 p += sizeof (struct in_addr);
814
815 /* Lookup the vertex W's LSA. */
816 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_ROUTER_LSA, *r);
Paul Jakmab75ae992007-03-23 11:17:28 +0000817 if (w_lsa)
818 {
819 if (IS_DEBUG_OSPF_EVENT)
820 zlog_debug ("found Router LSA %s", inet_ntoa (w_lsa->data->id));
821 }
paul718e3742002-12-13 20:15:29 +0000822 }
823
824 /* (b cont.) If the LSA does not exist, or its LS age is equal
825 to MaxAge, or it does not have a link back to vertex V,
826 examine the next link in V's LSA.[23] */
827 if (w_lsa == NULL)
Paul Jakmab75ae992007-03-23 11:17:28 +0000828 {
829 if (IS_DEBUG_OSPF_EVENT)
830 zlog_debug ("No LSA found");
831 continue;
832 }
paul718e3742002-12-13 20:15:29 +0000833
834 if (IS_LSA_MAXAGE (w_lsa))
Paul Jakmab75ae992007-03-23 11:17:28 +0000835 {
836 if (IS_DEBUG_OSPF_EVENT)
837 zlog_debug ("LSA is MaxAge");
838 continue;
839 }
paul718e3742002-12-13 20:15:29 +0000840
pauleb3da6d2005-10-18 04:20:33 +0000841 if (ospf_lsa_has_link (w_lsa->data, v->lsa) < 0 )
paul718e3742002-12-13 20:15:29 +0000842 {
paul0c0f9cd2003-06-06 23:27:04 +0000843 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000844 zlog_debug ("The LSA doesn't have a link back");
paul718e3742002-12-13 20:15:29 +0000845 continue;
846 }
847
848 /* (c) If vertex W is already on the shortest-path tree, examine
849 the next link in the LSA. */
hasso462f20d2005-02-23 11:29:02 +0000850 if (w_lsa->stat == LSA_SPF_IN_SPFTREE)
851 {
852 if (IS_DEBUG_OSPF_EVENT)
853 zlog_debug ("The LSA is already in SPF");
854 continue;
855 }
paul718e3742002-12-13 20:15:29 +0000856
857 /* (d) Calculate the link state cost D of the resulting path
858 from the root to vertex W. D is equal to the sum of the link
859 state cost of the (already calculated) shortest path to
860 vertex V and the advertised cost of the link between vertices
861 V and W. If D is: */
862
paul718e3742002-12-13 20:15:29 +0000863 /* calculate link cost D. */
864 if (v->lsa->type == OSPF_ROUTER_LSA)
pauleb3da6d2005-10-18 04:20:33 +0000865 distance = v->distance + ntohs (l->m[0].metric);
gdt630e4802004-08-31 17:28:41 +0000866 else /* v is not a Router-LSA */
pauleb3da6d2005-10-18 04:20:33 +0000867 distance = v->distance;
paul718e3742002-12-13 20:15:29 +0000868
869 /* Is there already vertex W in candidate list? */
hasso462f20d2005-02-23 11:29:02 +0000870 if (w_lsa->stat == LSA_SPF_NOT_EXPLORED)
871 {
pauleb3da6d2005-10-18 04:20:33 +0000872 /* prepare vertex W. */
873 w = ospf_vertex_new (w_lsa);
874
hasso462f20d2005-02-23 11:29:02 +0000875 /* Calculate nexthop to W. */
Paul Jakmabd34fb32007-02-26 17:14:48 +0000876 if (ospf_nexthop_calculation (area, v, w, l, distance))
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000877 pqueue_enqueue (w, candidate);
Paul Jakmab75ae992007-03-23 11:17:28 +0000878 else if (IS_DEBUG_OSPF_EVENT)
879 zlog_debug ("Nexthop Calc failed");
hasso462f20d2005-02-23 11:29:02 +0000880 }
881 else if (w_lsa->stat >= 0)
882 {
883 /* Get the vertex from candidates. */
pauleb3da6d2005-10-18 04:20:33 +0000884 w = candidate->array[w_lsa->stat];
paul718e3742002-12-13 20:15:29 +0000885
hasso462f20d2005-02-23 11:29:02 +0000886 /* if D is greater than. */
pauleb3da6d2005-10-18 04:20:33 +0000887 if (w->distance < distance)
paul718e3742002-12-13 20:15:29 +0000888 {
paul718e3742002-12-13 20:15:29 +0000889 continue;
890 }
hasso462f20d2005-02-23 11:29:02 +0000891 /* equal to. */
pauleb3da6d2005-10-18 04:20:33 +0000892 else if (w->distance == distance)
paul718e3742002-12-13 20:15:29 +0000893 {
pauleb3da6d2005-10-18 04:20:33 +0000894 /* Found an equal-cost path to W.
895 * Calculate nexthop of to W from V. */
Paul Jakmabd34fb32007-02-26 17:14:48 +0000896 ospf_nexthop_calculation (area, v, w, l, distance);
paul718e3742002-12-13 20:15:29 +0000897 }
hasso462f20d2005-02-23 11:29:02 +0000898 /* less than. */
899 else
paul718e3742002-12-13 20:15:29 +0000900 {
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000901 /* Found a lower-cost path to W.
902 * nexthop_calculation is conditional, if it finds
903 * valid nexthop it will call spf_add_parents, which
904 * will flush the old parents
905 */
Paul Jakmabd34fb32007-02-26 17:14:48 +0000906 if (ospf_nexthop_calculation (area, v, w, l, distance))
Paul Jakma7591d8b2007-08-06 18:52:45 +0000907 /* Decrease the key of the node in the heap.
908 * trickle-sort it up towards root, just in case this
909 * node should now be the new root due the cost change.
Paul Jakmae95537f2007-08-07 16:22:05 +0000910 * (next pqueu_{de,en}queue will fully re-heap the queue).
Paul Jakma7591d8b2007-08-06 18:52:45 +0000911 */
912 trickle_up (w_lsa->stat, candidate);
paul718e3742002-12-13 20:15:29 +0000913 }
gdt630e4802004-08-31 17:28:41 +0000914 } /* end W is already on the candidate list */
915 } /* end loop over the links in V's LSA */
paul718e3742002-12-13 20:15:29 +0000916}
917
paul4dadc292005-05-06 21:37:42 +0000918static void
paul718e3742002-12-13 20:15:29 +0000919ospf_spf_dump (struct vertex *v, int i)
920{
hasso52dc7ee2004-09-23 19:18:23 +0000921 struct listnode *cnode;
922 struct listnode *nnode;
pauleb3da6d2005-10-18 04:20:33 +0000923 struct vertex_parent *parent;
paul718e3742002-12-13 20:15:29 +0000924
925 if (v->type == OSPF_VERTEX_ROUTER)
926 {
927 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000928 zlog_debug ("SPF Result: %d [R] %s", i, inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000929 }
930 else
931 {
932 struct network_lsa *lsa = (struct network_lsa *) v->lsa;
933 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000934 zlog_debug ("SPF Result: %d [N] %s/%d", i, inet_ntoa (v->lsa->id),
paul0c0f9cd2003-06-06 23:27:04 +0000935 ip_masklen (lsa->mask));
gdt630e4802004-08-31 17:28:41 +0000936 }
paul718e3742002-12-13 20:15:29 +0000937
paul1eb8ef22005-04-07 07:30:20 +0000938 if (IS_DEBUG_OSPF_EVENT)
pauleb3da6d2005-10-18 04:20:33 +0000939 for (ALL_LIST_ELEMENTS_RO (v->parents, nnode, parent))
940 {
941 zlog_debug (" nexthop %p %s %s",
942 parent->nexthop,
943 inet_ntoa (parent->nexthop->router),
944 parent->nexthop->oi ? IF_NAME(parent->nexthop->oi)
945 : "NULL");
946 }
paul718e3742002-12-13 20:15:29 +0000947
948 i++;
949
pauleb3da6d2005-10-18 04:20:33 +0000950 for (ALL_LIST_ELEMENTS_RO (v->children, cnode, v))
paul1eb8ef22005-04-07 07:30:20 +0000951 ospf_spf_dump (v, i);
paul718e3742002-12-13 20:15:29 +0000952}
953
954/* Second stage of SPF calculation. */
paul4dadc292005-05-06 21:37:42 +0000955static void
paul0c0f9cd2003-06-06 23:27:04 +0000956ospf_spf_process_stubs (struct ospf_area *area, struct vertex *v,
Paul Jakmab3bc68e2008-09-04 13:52:07 +0100957 struct route_table *rt,
958 int parent_is_root)
paul718e3742002-12-13 20:15:29 +0000959{
paul1eb8ef22005-04-07 07:30:20 +0000960 struct listnode *cnode, *cnnode;
paul718e3742002-12-13 20:15:29 +0000961 struct vertex *child;
962
963 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000964 zlog_debug ("ospf_process_stub():processing stubs for area %s",
paul0c0f9cd2003-06-06 23:27:04 +0000965 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +0000966 if (v->type == OSPF_VERTEX_ROUTER)
967 {
968 u_char *p;
969 u_char *lim;
970 struct router_lsa_link *l;
971 struct router_lsa *rlsa;
972
paul0c0f9cd2003-06-06 23:27:04 +0000973 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000974 zlog_debug ("ospf_process_stubs():processing router LSA, id: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000975 inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000976 rlsa = (struct router_lsa *) v->lsa;
977
978
paul0c0f9cd2003-06-06 23:27:04 +0000979 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000980 zlog_debug ("ospf_process_stubs(): we have %d links to process",
paul0c0f9cd2003-06-06 23:27:04 +0000981 ntohs (rlsa->links));
gdt630e4802004-08-31 17:28:41 +0000982 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +0000983 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
984
985 while (p < lim)
986 {
987 l = (struct router_lsa_link *) p;
988
Denis Ovsienko05b77092011-08-23 11:36:27 +0400989 p += (OSPF_ROUTER_LSA_LINK_SIZE +
990 (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
paul718e3742002-12-13 20:15:29 +0000991
992 if (l->m[0].type == LSA_LINK_TYPE_STUB)
Paul Jakmab3bc68e2008-09-04 13:52:07 +0100993 ospf_intra_add_stub (rt, l, v, area, parent_is_root);
paul718e3742002-12-13 20:15:29 +0000994 }
995 }
996
gdt630e4802004-08-31 17:28:41 +0000997 ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1, 1);
paul718e3742002-12-13 20:15:29 +0000998
pauleb3da6d2005-10-18 04:20:33 +0000999 for (ALL_LIST_ELEMENTS (v->children, cnode, cnnode, child))
paul718e3742002-12-13 20:15:29 +00001000 {
paul718e3742002-12-13 20:15:29 +00001001 if (CHECK_FLAG (child->flags, OSPF_VERTEX_PROCESSED))
paul0c0f9cd2003-06-06 23:27:04 +00001002 continue;
Paul Jakmab3bc68e2008-09-04 13:52:07 +01001003
1004 /* the first level of routers connected to the root
1005 * should have 'parent_is_root' set, including those
1006 * connected via a network vertex.
1007 */
1008 if (area->spf == v)
1009 parent_is_root = 1;
1010 else if (v->type == OSPF_VERTEX_ROUTER)
1011 parent_is_root = 0;
1012
1013 ospf_spf_process_stubs (area, child, rt, parent_is_root);
paul718e3742002-12-13 20:15:29 +00001014
1015 SET_FLAG (child->flags, OSPF_VERTEX_PROCESSED);
1016 }
1017}
1018
1019void
1020ospf_rtrs_free (struct route_table *rtrs)
1021{
1022 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001023 struct list *or_list;
paul1eb8ef22005-04-07 07:30:20 +00001024 struct ospf_route *or;
1025 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001026
1027 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001028 zlog_debug ("Route: Router Routing Table free");
paul718e3742002-12-13 20:15:29 +00001029
1030 for (rn = route_top (rtrs); rn; rn = route_next (rn))
1031 if ((or_list = rn->info) != NULL)
1032 {
paul1eb8ef22005-04-07 07:30:20 +00001033 for (ALL_LIST_ELEMENTS (or_list, node, nnode, or))
1034 ospf_route_free (or);
paul718e3742002-12-13 20:15:29 +00001035
paul0c0f9cd2003-06-06 23:27:04 +00001036 list_delete (or_list);
paul718e3742002-12-13 20:15:29 +00001037
paul0c0f9cd2003-06-06 23:27:04 +00001038 /* Unlock the node. */
1039 rn->info = NULL;
1040 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001041 }
1042 route_table_finish (rtrs);
1043}
1044
Stephen Hemminger075e12f2011-12-06 23:54:17 +04001045#if 0
paul4dadc292005-05-06 21:37:42 +00001046static void
paul718e3742002-12-13 20:15:29 +00001047ospf_rtrs_print (struct route_table *rtrs)
1048{
1049 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001050 struct list *or_list;
1051 struct listnode *ln;
1052 struct listnode *pnode;
paul718e3742002-12-13 20:15:29 +00001053 struct ospf_route *or;
1054 struct ospf_path *path;
1055 char buf1[BUFSIZ];
1056 char buf2[BUFSIZ];
1057
1058 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001059 zlog_debug ("ospf_rtrs_print() start");
paul718e3742002-12-13 20:15:29 +00001060
1061 for (rn = route_top (rtrs); rn; rn = route_next (rn))
1062 if ((or_list = rn->info) != NULL)
paul1eb8ef22005-04-07 07:30:20 +00001063 for (ALL_LIST_ELEMENTS_RO (or_list, ln, or))
paul718e3742002-12-13 20:15:29 +00001064 {
paul718e3742002-12-13 20:15:29 +00001065 switch (or->path_type)
1066 {
1067 case OSPF_PATH_INTRA_AREA:
paul0c0f9cd2003-06-06 23:27:04 +00001068 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001069 zlog_debug ("%s [%d] area: %s",
paul0c0f9cd2003-06-06 23:27:04 +00001070 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1071 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1072 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +00001073 break;
1074 case OSPF_PATH_INTER_AREA:
paul0c0f9cd2003-06-06 23:27:04 +00001075 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001076 zlog_debug ("%s IA [%d] area: %s",
paul0c0f9cd2003-06-06 23:27:04 +00001077 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1078 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1079 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +00001080 break;
1081 default:
1082 break;
1083 }
1084
paul1eb8ef22005-04-07 07:30:20 +00001085 for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path))
paul718e3742002-12-13 20:15:29 +00001086 {
paul718e3742002-12-13 20:15:29 +00001087 if (path->nexthop.s_addr == 0)
paul0c0f9cd2003-06-06 23:27:04 +00001088 {
1089 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001090 zlog_debug (" directly attached to %s\r\n",
Joakim Tjernlunda8ba8472009-07-27 12:42:34 +02001091 ifindex2ifname (path->ifindex));
paul0c0f9cd2003-06-06 23:27:04 +00001092 }
1093 else
1094 {
1095 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001096 zlog_debug (" via %s, %s\r\n",
Joakim Tjernlunda8ba8472009-07-27 12:42:34 +02001097 inet_ntoa (path->nexthop),
1098 ifindex2ifname (path->ifindex));
paul0c0f9cd2003-06-06 23:27:04 +00001099 }
paul718e3742002-12-13 20:15:29 +00001100 }
1101 }
1102
ajs2a42e282004-12-08 18:43:03 +00001103 zlog_debug ("ospf_rtrs_print() end");
paul718e3742002-12-13 20:15:29 +00001104}
Stephen Hemminger075e12f2011-12-06 23:54:17 +04001105#endif
paul718e3742002-12-13 20:15:29 +00001106
1107/* Calculating the shortest-path tree for an area. */
paul4dadc292005-05-06 21:37:42 +00001108static void
paul0c0f9cd2003-06-06 23:27:04 +00001109ospf_spf_calculate (struct ospf_area *area, struct route_table *new_table,
paul718e3742002-12-13 20:15:29 +00001110 struct route_table *new_rtrs)
1111{
hasso462f20d2005-02-23 11:29:02 +00001112 struct pqueue *candidate;
paul718e3742002-12-13 20:15:29 +00001113 struct vertex *v;
pauleb3da6d2005-10-18 04:20:33 +00001114
paul718e3742002-12-13 20:15:29 +00001115 if (IS_DEBUG_OSPF_EVENT)
1116 {
ajs2a42e282004-12-08 18:43:03 +00001117 zlog_debug ("ospf_spf_calculate: Start");
1118 zlog_debug ("ospf_spf_calculate: running Dijkstra for area %s",
paul0c0f9cd2003-06-06 23:27:04 +00001119 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001120 }
1121
1122 /* Check router-lsa-self. If self-router-lsa is not yet allocated,
1123 return this area's calculation. */
paul0c0f9cd2003-06-06 23:27:04 +00001124 if (!area->router_lsa_self)
paul718e3742002-12-13 20:15:29 +00001125 {
1126 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001127 zlog_debug ("ospf_spf_calculate: "
paul0c0f9cd2003-06-06 23:27:04 +00001128 "Skip area %s's calculation due to empty router_lsa_self",
1129 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001130 return;
1131 }
1132
1133 /* RFC2328 16.1. (1). */
paul0c0f9cd2003-06-06 23:27:04 +00001134 /* Initialize the algorithm's data structures. */
hasso462f20d2005-02-23 11:29:02 +00001135
1136 /* This function scans all the LSA database and set the stat field to
1137 * LSA_SPF_NOT_EXPLORED. */
1138 ospf_lsdb_clean_stat (area->lsdb);
1139 /* Create a new heap for the candidates. */
1140 candidate = pqueue_create();
1141 candidate->cmp = cmp;
1142 candidate->update = update_stat;
paul718e3742002-12-13 20:15:29 +00001143
1144 /* Initialize the shortest-path tree to only the root (which is the
1145 router doing the calculation). */
1146 ospf_spf_init (area);
1147 v = area->spf;
hasso462f20d2005-02-23 11:29:02 +00001148 /* Set LSA position to LSA_SPF_IN_SPFTREE. This vertex is the root of the
1149 * spanning tree. */
1150 *(v->stat) = LSA_SPF_IN_SPFTREE;
paul718e3742002-12-13 20:15:29 +00001151
1152 /* Set Area A's TransitCapability to FALSE. */
1153 area->transit = OSPF_TRANSIT_FALSE;
1154 area->shortcut_capability = 1;
pauleb3da6d2005-10-18 04:20:33 +00001155
paul718e3742002-12-13 20:15:29 +00001156 for (;;)
1157 {
1158 /* RFC2328 16.1. (2). */
hasso462f20d2005-02-23 11:29:02 +00001159 ospf_spf_next (v, area, candidate);
paul718e3742002-12-13 20:15:29 +00001160
1161 /* RFC2328 16.1. (3). */
1162 /* If at this step the candidate list is empty, the shortest-
1163 path tree (of transit vertices) has been completely built and
1164 this stage of the procedure terminates. */
hasso462f20d2005-02-23 11:29:02 +00001165 if (candidate->size == 0)
paul718e3742002-12-13 20:15:29 +00001166 break;
1167
1168 /* Otherwise, choose the vertex belonging to the candidate list
1169 that is closest to the root, and add it to the shortest-path
1170 tree (removing it from the candidate list in the
paul0c0f9cd2003-06-06 23:27:04 +00001171 process). */
hasso462f20d2005-02-23 11:29:02 +00001172 /* Extract from the candidates the node with the lower key. */
1173 v = (struct vertex *) pqueue_dequeue (candidate);
1174 /* Update stat field in vertex. */
1175 *(v->stat) = LSA_SPF_IN_SPFTREE;
pauleb3da6d2005-10-18 04:20:33 +00001176
paul718e3742002-12-13 20:15:29 +00001177 ospf_vertex_add_parent (v);
1178
paul718e3742002-12-13 20:15:29 +00001179 /* RFC2328 16.1. (4). */
1180 if (v->type == OSPF_VERTEX_ROUTER)
1181 ospf_intra_add_router (new_rtrs, v, area);
paul0c0f9cd2003-06-06 23:27:04 +00001182 else
paul718e3742002-12-13 20:15:29 +00001183 ospf_intra_add_transit (new_table, v, area);
1184
1185 /* RFC2328 16.1. (5). */
1186 /* Iterate the algorithm by returning to Step 2. */
gdt630e4802004-08-31 17:28:41 +00001187
1188 } /* end loop until no more candidate vertices */
paul718e3742002-12-13 20:15:29 +00001189
1190 if (IS_DEBUG_OSPF_EVENT)
1191 {
1192 ospf_spf_dump (area->spf, 0);
1193 ospf_route_table_dump (new_table);
1194 }
1195
1196 /* Second stage of SPF calculation procedure's */
Paul Jakmab3bc68e2008-09-04 13:52:07 +01001197 ospf_spf_process_stubs (area, area->spf, new_table, 0);
paul718e3742002-12-13 20:15:29 +00001198
pauleb3da6d2005-10-18 04:20:33 +00001199 /* Free candidate queue. */
hasso462f20d2005-02-23 11:29:02 +00001200 pqueue_delete (candidate);
pauleb3da6d2005-10-18 04:20:33 +00001201
1202 ospf_vertex_dump (__func__, area->spf, 0, 1);
1203 /* Free nexthop information, canonical versions of which are attached
1204 * the first level of router vertices attached to the root vertex, see
1205 * ospf_nexthop_calculation.
1206 */
1207 ospf_canonical_nexthops_free (area->spf);
1208
Paul Jakma9c27ef92006-05-04 07:32:57 +00001209 /* Free SPF vertices, but not the list. List has ospf_vertex_free
1210 * as deconstructor.
1211 */
1212 list_delete_all_node (&vertex_list);
pauleb3da6d2005-10-18 04:20:33 +00001213
paul718e3742002-12-13 20:15:29 +00001214 /* Increment SPF Calculation Counter. */
1215 area->spf_calculation++;
1216
Paul Jakma2518efd2006-08-27 06:49:29 +00001217 quagga_gettime (QUAGGA_CLK_MONOTONIC, &area->ospf->ts_spf);
paul718e3742002-12-13 20:15:29 +00001218
1219 if (IS_DEBUG_OSPF_EVENT)
Paul Jakma9c27ef92006-05-04 07:32:57 +00001220 zlog_debug ("ospf_spf_calculate: Stop. %ld vertices",
1221 mtype_stats_alloc(MTYPE_OSPF_VERTEX));
paul718e3742002-12-13 20:15:29 +00001222}
1223
1224/* Timer for SPF calculation. */
paul4dadc292005-05-06 21:37:42 +00001225static int
paul68980082003-03-25 05:07:42 +00001226ospf_spf_calculate_timer (struct thread *thread)
paul718e3742002-12-13 20:15:29 +00001227{
paul68980082003-03-25 05:07:42 +00001228 struct ospf *ospf = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +00001229 struct route_table *new_table, *new_rtrs;
paul1eb8ef22005-04-07 07:30:20 +00001230 struct ospf_area *area;
1231 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001232
1233 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001234 zlog_debug ("SPF: Timer (SPF calculation expire)");
paul0c0f9cd2003-06-06 23:27:04 +00001235
paul718e3742002-12-13 20:15:29 +00001236 ospf->t_spf_calc = NULL;
1237
1238 /* Allocate new table tree. */
1239 new_table = route_table_init ();
paul0c0f9cd2003-06-06 23:27:04 +00001240 new_rtrs = route_table_init ();
paul718e3742002-12-13 20:15:29 +00001241
paul68980082003-03-25 05:07:42 +00001242 ospf_vl_unapprove (ospf);
paul718e3742002-12-13 20:15:29 +00001243
1244 /* Calculate SPF for each area. */
paul1eb8ef22005-04-07 07:30:20 +00001245 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
Paul Jakma9c27ef92006-05-04 07:32:57 +00001246 {
1247 /* Do backbone last, so as to first discover intra-area paths
1248 * for any back-bone virtual-links
1249 */
1250 if (ospf->backbone && ospf->backbone == area)
1251 continue;
1252
1253 ospf_spf_calculate (area, new_table, new_rtrs);
1254 }
1255
1256 /* SPF for backbone, if required */
1257 if (ospf->backbone)
1258 ospf_spf_calculate (ospf->backbone, new_table, new_rtrs);
1259
paul68980082003-03-25 05:07:42 +00001260 ospf_vl_shut_unapproved (ospf);
paul718e3742002-12-13 20:15:29 +00001261
paul68980082003-03-25 05:07:42 +00001262 ospf_ia_routing (ospf, new_table, new_rtrs);
paul718e3742002-12-13 20:15:29 +00001263
1264 ospf_prune_unreachable_networks (new_table);
1265 ospf_prune_unreachable_routers (new_rtrs);
1266
1267 /* AS-external-LSA calculation should not be performed here. */
1268
1269 /* If new Router Route is installed,
1270 then schedule re-calculate External routes. */
1271 if (1)
paul68980082003-03-25 05:07:42 +00001272 ospf_ase_calculate_schedule (ospf);
paul718e3742002-12-13 20:15:29 +00001273
paul68980082003-03-25 05:07:42 +00001274 ospf_ase_calculate_timer_add (ospf);
paul718e3742002-12-13 20:15:29 +00001275
1276 /* Update routing table. */
paul68980082003-03-25 05:07:42 +00001277 ospf_route_install (ospf, new_table);
paul718e3742002-12-13 20:15:29 +00001278
1279 /* Update ABR/ASBR routing table */
paul68980082003-03-25 05:07:42 +00001280 if (ospf->old_rtrs)
paul718e3742002-12-13 20:15:29 +00001281 {
1282 /* old_rtrs's node holds linked list of ospf_route. --kunihiro. */
paul68980082003-03-25 05:07:42 +00001283 /* ospf_route_delete (ospf->old_rtrs); */
1284 ospf_rtrs_free (ospf->old_rtrs);
paul718e3742002-12-13 20:15:29 +00001285 }
1286
paul68980082003-03-25 05:07:42 +00001287 ospf->old_rtrs = ospf->new_rtrs;
1288 ospf->new_rtrs = new_rtrs;
paul718e3742002-12-13 20:15:29 +00001289
paul0c0f9cd2003-06-06 23:27:04 +00001290 if (IS_OSPF_ABR (ospf))
paul68980082003-03-25 05:07:42 +00001291 ospf_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001292
1293 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001294 zlog_debug ("SPF: calculation complete");
paul718e3742002-12-13 20:15:29 +00001295
1296 return 0;
1297}
1298
1299/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
1300 set timer for SPF calc. */
1301void
paul68980082003-03-25 05:07:42 +00001302ospf_spf_calculate_schedule (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00001303{
pauld24f6e22005-10-21 09:23:12 +00001304 unsigned long delay, elapsed, ht;
1305 struct timeval result;
paul718e3742002-12-13 20:15:29 +00001306
1307 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001308 zlog_debug ("SPF: calculation timer scheduled");
paul718e3742002-12-13 20:15:29 +00001309
1310 /* OSPF instance does not exist. */
paul68980082003-03-25 05:07:42 +00001311 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001312 return;
pauld24f6e22005-10-21 09:23:12 +00001313
paul718e3742002-12-13 20:15:29 +00001314 /* SPF calculation timer is already scheduled. */
paul68980082003-03-25 05:07:42 +00001315 if (ospf->t_spf_calc)
paul718e3742002-12-13 20:15:29 +00001316 {
1317 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001318 zlog_debug ("SPF: calculation timer is already scheduled: %p",
paul0c0f9cd2003-06-06 23:27:04 +00001319 ospf->t_spf_calc);
paul718e3742002-12-13 20:15:29 +00001320 return;
1321 }
pauld24f6e22005-10-21 09:23:12 +00001322
1323 /* XXX Monotic timers: we only care about relative time here. */
Paul Jakma2518efd2006-08-27 06:49:29 +00001324 result = tv_sub (recent_relative_time (), ospf->ts_spf);
pauld24f6e22005-10-21 09:23:12 +00001325
1326 elapsed = (result.tv_sec * 1000) + (result.tv_usec / 1000);
1327 ht = ospf->spf_holdtime * ospf->spf_hold_multiplier;
1328
1329 if (ht > ospf->spf_max_holdtime)
1330 ht = ospf->spf_max_holdtime;
1331
paul718e3742002-12-13 20:15:29 +00001332 /* Get SPF calculation delay time. */
pauld24f6e22005-10-21 09:23:12 +00001333 if (elapsed < ht)
paul718e3742002-12-13 20:15:29 +00001334 {
pauld24f6e22005-10-21 09:23:12 +00001335 /* Got an event within the hold time of last SPF. We need to
1336 * increase the hold_multiplier, if it's not already at/past
1337 * maximum value, and wasn't already increased..
1338 */
1339 if (ht < ospf->spf_max_holdtime)
1340 ospf->spf_hold_multiplier++;
1341
1342 /* always honour the SPF initial delay */
1343 if ( (ht - elapsed) < ospf->spf_delay)
paul0c0f9cd2003-06-06 23:27:04 +00001344 delay = ospf->spf_delay;
paul718e3742002-12-13 20:15:29 +00001345 else
pauld24f6e22005-10-21 09:23:12 +00001346 delay = ht - elapsed;
paul718e3742002-12-13 20:15:29 +00001347 }
1348 else
pauld24f6e22005-10-21 09:23:12 +00001349 {
1350 /* Event is past required hold-time of last SPF */
1351 delay = ospf->spf_delay;
1352 ospf->spf_hold_multiplier = 1;
1353 }
1354
paul718e3742002-12-13 20:15:29 +00001355 if (IS_DEBUG_OSPF_EVENT)
pauld24f6e22005-10-21 09:23:12 +00001356 zlog_debug ("SPF: calculation timer delay = %ld", delay);
1357
paul68980082003-03-25 05:07:42 +00001358 ospf->t_spf_calc =
pauld24f6e22005-10-21 09:23:12 +00001359 thread_add_timer_msec (master, ospf_spf_calculate_timer, ospf, delay);
paul718e3742002-12-13 20:15:29 +00001360}