blob: c40fc33ef76e2bea1705f4d9d31844c71cba5004 [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 };
David Lamparter6b0655a2014-06-04 06:53:35 +020055
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}
David Lamparter6b0655a2014-06-04 06:53:35 +020093
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}
David Lamparter6b0655a2014-06-04 06:53:35 +0200137
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}
David Lamparter6b0655a2014-06-04 06:53:35 +0200162
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}
David Lamparter6b0655a2014-06-04 06:53:35 +0200279
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,
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200493 unsigned int distance, int lsa_pos)
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;
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200500 char buf1[BUFSIZ];
501 char buf2[BUFSIZ];
paul0c0f9cd2003-06-06 23:27:04 +0000502
paul718e3742002-12-13 20:15:29 +0000503 if (IS_DEBUG_OSPF_EVENT)
gdt630e4802004-08-31 17:28:41 +0000504 {
ajs2a42e282004-12-08 18:43:03 +0000505 zlog_debug ("ospf_nexthop_calculation(): Start");
gdt630e4802004-08-31 17:28:41 +0000506 ospf_vertex_dump("V (parent):", v, 1, 1);
507 ospf_vertex_dump("W (dest) :", w, 1, 1);
Paul Jakmabd34fb32007-02-26 17:14:48 +0000508 zlog_debug ("V->W distance: %d", distance);
gdt630e4802004-08-31 17:28:41 +0000509 }
paul718e3742002-12-13 20:15:29 +0000510
paul718e3742002-12-13 20:15:29 +0000511 if (v == area->spf)
Paul Jakma9c27ef92006-05-04 07:32:57 +0000512 {
gdt630e4802004-08-31 17:28:41 +0000513 /* 16.1.1 para 4. In the first case, the parent vertex (V) is the
514 root (the calculating router itself). This means that the
515 destination is either a directly connected network or directly
516 connected router. The outgoing interface in this case is simply
517 the OSPF interface connecting to the destination network/router.
518 */
519
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200520 /* we *must* be supplied with the link data */
521 assert (l != NULL);
522 oi = ospf_if_lookup_by_lsa_pos (area, lsa_pos);
523 if (!oi)
524 {
525 zlog_debug("%s: OI not found in LSA: lsa_pos:%d link_id:%s link_data:%s",
526 __func__, lsa_pos,
527 inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ),
528 inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ));
529 return 0;
530 }
531
532 if (IS_DEBUG_OSPF_EVENT)
533 {
534 zlog_debug("%s: considering link:%s "
535 "type:%d link_id:%s link_data:%s",
536 __func__, oi->ifp->name, l->m[0].type,
537 inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ),
538 inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ));
539 }
540
paul718e3742002-12-13 20:15:29 +0000541 if (w->type == OSPF_VERTEX_ROUTER)
paul0c0f9cd2003-06-06 23:27:04 +0000542 {
pauleb3da6d2005-10-18 04:20:33 +0000543 /* l is a link from v to w
544 * l2 will be link from w to v
545 */
546 struct router_lsa_link *l2 = NULL;
paul0c0f9cd2003-06-06 23:27:04 +0000547
pauleb3da6d2005-10-18 04:20:33 +0000548 if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT)
549 {
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200550 struct in_addr nexthop;
551
pauleb3da6d2005-10-18 04:20:33 +0000552 /* If the destination is a router which connects to
553 the calculating router via a Point-to-MultiPoint
554 network, the destination's next hop IP address(es)
555 can be determined by examining the destination's
556 router-LSA: each link pointing back to the
557 calculating router and having a Link Data field
558 belonging to the Point-to-MultiPoint network
559 provides an IP address of the next hop router.
gdt630e4802004-08-31 17:28:41 +0000560
pauleb3da6d2005-10-18 04:20:33 +0000561 At this point l is a link from V to W, and V is the
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200562 root ("us"). If it is a point-to-multipoint interface,
563 then look through the links in the opposite direction (W to V).
564 If any of them have an address that lands within the
pauleb3da6d2005-10-18 04:20:33 +0000565 subnet declared by the PtMP link, then that link
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200566 is a constituent of the PtMP link, and its address is
pauleb3da6d2005-10-18 04:20:33 +0000567 a nexthop address for V.
568 */
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200569 if (oi->type == OSPF_IFTYPE_POINTOPOINT)
570 {
Christian Frankef2b53da2013-03-20 15:28:46 +0000571 /* Having nexthop = 0 is tempting, but NOT acceptable.
572 It breaks AS-External routes with a forwarding address,
573 since ospf_ase_complete_direct_routes() will mistakenly
574 assume we've reached the last hop and should place the
575 forwarding address as nexthop.
576 Also, users may configure multi-access links in p2p mode,
577 so we need the IP to ARP the nexthop.
578 */
579 struct ospf_neighbor *nbr_w;
580
581 nbr_w = ospf_nbr_lookup_by_routerid (oi->nbrs, &l->link_id);
582 if (nbr_w != NULL)
583 {
584 added = 1;
585 nexthop = nbr_w->src;
586 }
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200587 }
588 else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
589 {
590 struct prefix_ipv4 la;
gdt630e4802004-08-31 17:28:41 +0000591
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200592 la.family = AF_INET;
593 la.prefixlen = oi->address->prefixlen;
pauleb3da6d2005-10-18 04:20:33 +0000594
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200595 /* V links to W on PtMP interface
596 - find the interface address on W */
597 while ((l2 = ospf_get_next_link (w, v, l2)))
598 {
599 la.prefix = l2->link_data;
gdt630e4802004-08-31 17:28:41 +0000600
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200601 if (prefix_cmp ((struct prefix *) &la,
602 oi->address) != 0)
603 continue;
604 /* link_data is on our PtMP network */
605 added = 1;
606 nexthop = l2->link_data;
607 break;
608 }
609 }
pauleb3da6d2005-10-18 04:20:33 +0000610
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200611 if (added)
pauleb3da6d2005-10-18 04:20:33 +0000612 {
613 /* found all necessary info to build nexthop */
614 nh = vertex_nexthop_new ();
615 nh->oi = oi;
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200616 nh->router = nexthop;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000617 ospf_spf_add_parent (v, w, nh, distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000618 return 1;
pauleb3da6d2005-10-18 04:20:33 +0000619 }
620 else
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200621 zlog_info("%s: could not determine nexthop for link %s",
622 __func__, oi->ifp->name);
pauleb3da6d2005-10-18 04:20:33 +0000623 } /* end point-to-point link from V to W */
Paul Jakma9c27ef92006-05-04 07:32:57 +0000624 else if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK)
625 {
626 struct ospf_vl_data *vl_data;
627
628 /* VLink implementation limitations:
629 * a) vl_data can only reference one nexthop, so no ECMP
630 * to backbone through VLinks. Though transit-area
631 * summaries may be considered, and those can be ECMP.
632 * b) We can only use /one/ VLink, even if multiple ones
633 * exist this router through multiple transit-areas.
634 */
635 vl_data = ospf_vl_lookup (area->ospf, NULL, l->link_id);
636
637 if (vl_data
638 && CHECK_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED))
639 {
640 nh = vertex_nexthop_new ();
641 nh->oi = vl_data->nexthop.oi;
642 nh->router = vl_data->nexthop.router;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000643 ospf_spf_add_parent (v, w, nh, distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000644 return 1;
Paul Jakma9c27ef92006-05-04 07:32:57 +0000645 }
646 else
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000647 zlog_info("ospf_nexthop_calculation(): "
648 "vl_data for VL link not found");
Paul Jakma9c27ef92006-05-04 07:32:57 +0000649 } /* end virtual-link from V to W */
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000650 return 0;
gdt630e4802004-08-31 17:28:41 +0000651 } /* end W is a Router vertex */
paul718e3742002-12-13 20:15:29 +0000652 else
paul0c0f9cd2003-06-06 23:27:04 +0000653 {
pauleb3da6d2005-10-18 04:20:33 +0000654 assert(w->type == OSPF_VERTEX_NETWORK);
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200655
656 nh = vertex_nexthop_new ();
657 nh->oi = oi;
658 nh->router.s_addr = 0; /* Nexthop not required */
659 ospf_spf_add_parent (v, w, nh, distance);
660 return 1;
paul0c0f9cd2003-06-06 23:27:04 +0000661 }
gdt630e4802004-08-31 17:28:41 +0000662 } /* end V is the root */
gdt630e4802004-08-31 17:28:41 +0000663 /* Check if W's parent is a network connected to root. */
paul718e3742002-12-13 20:15:29 +0000664 else if (v->type == OSPF_VERTEX_NETWORK)
665 {
gdt630e4802004-08-31 17:28:41 +0000666 /* See if any of V's parents are the root. */
pauleb3da6d2005-10-18 04:20:33 +0000667 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
paul718e3742002-12-13 20:15:29 +0000668 {
pauleb3da6d2005-10-18 04:20:33 +0000669 if (vp->parent == area->spf) /* connects to root? */
gdt630e4802004-08-31 17:28:41 +0000670 {
671 /* 16.1.1 para 5. ...the parent vertex is a network that
672 * directly connects the calculating router to the destination
673 * router. The list of next hops is then determined by
674 * examining the destination's router-LSA...
675 */
676
677 assert(w->type == OSPF_VERTEX_ROUTER);
paul0c0f9cd2003-06-06 23:27:04 +0000678 while ((l = ospf_get_next_link (w, v, l)))
679 {
gdt630e4802004-08-31 17:28:41 +0000680 /* ...For each link in the router-LSA that points back to the
681 * parent network, the link's Link Data field provides the IP
682 * address of a next hop router. The outgoing interface to
683 * use can then be derived from the next hop IP address (or
684 * it can be inherited from the parent network).
685 */
pauleb3da6d2005-10-18 04:20:33 +0000686 nh = vertex_nexthop_new ();
687 nh->oi = vp->nexthop->oi;
688 nh->router = l->link_data;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000689 added = 1;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000690 ospf_spf_add_parent (v, w, nh, distance);
paul0c0f9cd2003-06-06 23:27:04 +0000691 }
Paul Jakma945ea292012-08-06 12:17:12 +0100692 /* Note lack of return is deliberate. See next comment. */
693 }
paul718e3742002-12-13 20:15:29 +0000694 }
Paul Jakma945ea292012-08-06 12:17:12 +0100695 /* NB: This code is non-trivial.
696 *
697 * E.g. it is not enough to know that V connects to the root. It is
698 * also important that the while above, looping through all links from
699 * W->V found at least one link, so that we know there is
700 * bi-directional connectivity between V and W (which need not be the
701 * case, e.g. when OSPF has not yet converged fully). Otherwise, if
702 * we /always/ return here, without having checked that root->V->-W
703 * actually resulted in a valid nexthop being created, then we we will
704 * prevent SPF from finding/using higher cost paths.
705 *
706 * It is important, if root->V->W has not been added, that we continue
707 * through to the intervening-router nexthop code below. So as to
708 * ensure other paths to V may be used. This avoids unnecessary
709 * blackholes while OSPF is convergening.
710 *
711 * I.e. we may have arrived at this function, examining V -> W, via
712 * workable paths other than root -> V, and it's important to avoid
713 * getting "confused" by non-working root->V->W path - it's important
714 * to *not* lose the working non-root paths, just because of a
715 * non-viable root->V->W.
716 *
717 * See also bug #330 (required reading!), and:
718 *
719 * http://blogs.oracle.com/paulj/entry/the_difference_a_line_makes
720 */
721 if (added)
722 return added;
paul718e3742002-12-13 20:15:29 +0000723 }
724
gdt630e4802004-08-31 17:28:41 +0000725 /* 16.1.1 para 4. If there is at least one intervening router in the
726 * current shortest path between the destination and the root, the
727 * destination simply inherits the set of next hops from the
728 * parent.
729 */
Paul Jakmab75ae992007-03-23 11:17:28 +0000730 if (IS_DEBUG_OSPF_EVENT)
731 zlog_debug ("%s: Intervening routers, adding parent(s)", __func__);
732
pauleb3da6d2005-10-18 04:20:33 +0000733 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000734 {
735 added = 1;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000736 ospf_spf_add_parent (v, w, vp->nexthop, distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000737 }
Paul Jakma9c27ef92006-05-04 07:32:57 +0000738
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000739 return added;
paul718e3742002-12-13 20:15:29 +0000740}
741
gdt630e4802004-08-31 17:28:41 +0000742/* RFC2328 Section 16.1 (2).
743 * v is on the SPF tree. Examine the links in v's LSA. Update the list
744 * of candidates with any vertices not already on the list. If a lower-cost
745 * path is found to a vertex already on the candidate list, store the new cost.
746 */
paul4dadc292005-05-06 21:37:42 +0000747static void
paul718e3742002-12-13 20:15:29 +0000748ospf_spf_next (struct vertex *v, struct ospf_area *area,
hasso462f20d2005-02-23 11:29:02 +0000749 struct pqueue * candidate)
paul718e3742002-12-13 20:15:29 +0000750{
751 struct ospf_lsa *w_lsa = NULL;
paul718e3742002-12-13 20:15:29 +0000752 u_char *p;
753 u_char *lim;
754 struct router_lsa_link *l = NULL;
755 struct in_addr *r;
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200756 int type = 0, lsa_pos=-1, lsa_pos_next=0;
paul718e3742002-12-13 20:15:29 +0000757
758 /* If this is a router-LSA, and bit V of the router-LSA (see Section
759 A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE. */
760 if (v->type == OSPF_VERTEX_ROUTER)
761 {
762 if (IS_ROUTER_LSA_VIRTUAL ((struct router_lsa *) v->lsa))
763 area->transit = OSPF_TRANSIT_TRUE;
764 }
Paul Jakmab75ae992007-03-23 11:17:28 +0000765
766 if (IS_DEBUG_OSPF_EVENT)
767 zlog_debug ("%s: Next vertex of %s vertex %s",
768 __func__,
769 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
770 inet_ntoa(v->lsa->id));
771
paul718e3742002-12-13 20:15:29 +0000772 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul0c0f9cd2003-06-06 23:27:04 +0000773 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
774
paul718e3742002-12-13 20:15:29 +0000775 while (p < lim)
776 {
pauleb3da6d2005-10-18 04:20:33 +0000777 struct vertex *w;
778 unsigned int distance;
pauld355bfa2004-04-08 07:43:45 +0000779
paul718e3742002-12-13 20:15:29 +0000780 /* In case of V is Router-LSA. */
781 if (v->lsa->type == OSPF_ROUTER_LSA)
782 {
783 l = (struct router_lsa_link *) p;
784
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200785 lsa_pos = lsa_pos_next; /* LSA link position */
786 lsa_pos_next++;
Denis Ovsienko05b77092011-08-23 11:36:27 +0400787 p += (OSPF_ROUTER_LSA_LINK_SIZE +
788 (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
paul718e3742002-12-13 20:15:29 +0000789
790 /* (a) If this is a link to a stub network, examine the next
791 link in V's LSA. Links to stub networks will be
792 considered in the second stage of the shortest path
793 calculation. */
794 if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB)
795 continue;
Paul Jakma08d3d5b2007-05-07 16:38:35 +0000796
797 /* Infinite distance links shouldn't be followed, except
798 * for local links (a stub-routed router still wants to
799 * calculate tree, so must follow its own links).
800 */
801 if ((v != area->spf) && l->m[0].metric >= OSPF_OUTPUT_COST_INFINITE)
802 continue;
paul718e3742002-12-13 20:15:29 +0000803
804 /* (b) Otherwise, W is a transit vertex (router or transit
805 network). Look up the vertex W's LSA (router-LSA or
806 network-LSA) in Area A's link state database. */
807 switch (type)
808 {
809 case LSA_LINK_TYPE_POINTOPOINT:
810 case LSA_LINK_TYPE_VIRTUALLINK:
811 if (type == LSA_LINK_TYPE_VIRTUALLINK)
paul0c0f9cd2003-06-06 23:27:04 +0000812 {
813 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000814 zlog_debug ("looking up LSA through VL: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000815 inet_ntoa (l->link_id));
816 }
paul718e3742002-12-13 20:15:29 +0000817
818 w_lsa = ospf_lsa_lookup (area, OSPF_ROUTER_LSA, l->link_id,
819 l->link_id);
820 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000821 {
822 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000823 zlog_debug ("found Router LSA %s", inet_ntoa (l->link_id));
paul0c0f9cd2003-06-06 23:27:04 +0000824 }
paul718e3742002-12-13 20:15:29 +0000825 break;
826 case LSA_LINK_TYPE_TRANSIT:
paul0c0f9cd2003-06-06 23:27:04 +0000827 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000828 zlog_debug ("Looking up Network LSA, ID: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000829 inet_ntoa (l->link_id));
paul718e3742002-12-13 20:15:29 +0000830 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_NETWORK_LSA,
paul0c0f9cd2003-06-06 23:27:04 +0000831 l->link_id);
paul718e3742002-12-13 20:15:29 +0000832 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000833 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000834 zlog_debug ("found the LSA");
paul718e3742002-12-13 20:15:29 +0000835 break;
836 default:
paul0c0f9cd2003-06-06 23:27:04 +0000837 zlog_warn ("Invalid LSA link type %d", type);
paul718e3742002-12-13 20:15:29 +0000838 continue;
839 }
840 }
841 else
842 {
843 /* In case of V is Network-LSA. */
paul0c0f9cd2003-06-06 23:27:04 +0000844 r = (struct in_addr *) p;
paul718e3742002-12-13 20:15:29 +0000845 p += sizeof (struct in_addr);
846
847 /* Lookup the vertex W's LSA. */
848 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_ROUTER_LSA, *r);
Paul Jakmab75ae992007-03-23 11:17:28 +0000849 if (w_lsa)
850 {
851 if (IS_DEBUG_OSPF_EVENT)
852 zlog_debug ("found Router LSA %s", inet_ntoa (w_lsa->data->id));
853 }
paul718e3742002-12-13 20:15:29 +0000854 }
855
856 /* (b cont.) If the LSA does not exist, or its LS age is equal
857 to MaxAge, or it does not have a link back to vertex V,
858 examine the next link in V's LSA.[23] */
859 if (w_lsa == NULL)
Paul Jakmab75ae992007-03-23 11:17:28 +0000860 {
861 if (IS_DEBUG_OSPF_EVENT)
862 zlog_debug ("No LSA found");
863 continue;
864 }
paul718e3742002-12-13 20:15:29 +0000865
866 if (IS_LSA_MAXAGE (w_lsa))
Paul Jakmab75ae992007-03-23 11:17:28 +0000867 {
868 if (IS_DEBUG_OSPF_EVENT)
869 zlog_debug ("LSA is MaxAge");
870 continue;
871 }
paul718e3742002-12-13 20:15:29 +0000872
pauleb3da6d2005-10-18 04:20:33 +0000873 if (ospf_lsa_has_link (w_lsa->data, v->lsa) < 0 )
paul718e3742002-12-13 20:15:29 +0000874 {
paul0c0f9cd2003-06-06 23:27:04 +0000875 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000876 zlog_debug ("The LSA doesn't have a link back");
paul718e3742002-12-13 20:15:29 +0000877 continue;
878 }
879
880 /* (c) If vertex W is already on the shortest-path tree, examine
881 the next link in the LSA. */
hasso462f20d2005-02-23 11:29:02 +0000882 if (w_lsa->stat == LSA_SPF_IN_SPFTREE)
883 {
884 if (IS_DEBUG_OSPF_EVENT)
885 zlog_debug ("The LSA is already in SPF");
886 continue;
887 }
paul718e3742002-12-13 20:15:29 +0000888
889 /* (d) Calculate the link state cost D of the resulting path
890 from the root to vertex W. D is equal to the sum of the link
891 state cost of the (already calculated) shortest path to
892 vertex V and the advertised cost of the link between vertices
893 V and W. If D is: */
894
paul718e3742002-12-13 20:15:29 +0000895 /* calculate link cost D. */
896 if (v->lsa->type == OSPF_ROUTER_LSA)
pauleb3da6d2005-10-18 04:20:33 +0000897 distance = v->distance + ntohs (l->m[0].metric);
gdt630e4802004-08-31 17:28:41 +0000898 else /* v is not a Router-LSA */
pauleb3da6d2005-10-18 04:20:33 +0000899 distance = v->distance;
paul718e3742002-12-13 20:15:29 +0000900
901 /* Is there already vertex W in candidate list? */
hasso462f20d2005-02-23 11:29:02 +0000902 if (w_lsa->stat == LSA_SPF_NOT_EXPLORED)
903 {
pauleb3da6d2005-10-18 04:20:33 +0000904 /* prepare vertex W. */
905 w = ospf_vertex_new (w_lsa);
906
hasso462f20d2005-02-23 11:29:02 +0000907 /* Calculate nexthop to W. */
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200908 if (ospf_nexthop_calculation (area, v, w, l, distance, lsa_pos))
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000909 pqueue_enqueue (w, candidate);
Paul Jakmab75ae992007-03-23 11:17:28 +0000910 else if (IS_DEBUG_OSPF_EVENT)
911 zlog_debug ("Nexthop Calc failed");
hasso462f20d2005-02-23 11:29:02 +0000912 }
913 else if (w_lsa->stat >= 0)
914 {
915 /* Get the vertex from candidates. */
pauleb3da6d2005-10-18 04:20:33 +0000916 w = candidate->array[w_lsa->stat];
paul718e3742002-12-13 20:15:29 +0000917
hasso462f20d2005-02-23 11:29:02 +0000918 /* if D is greater than. */
pauleb3da6d2005-10-18 04:20:33 +0000919 if (w->distance < distance)
paul718e3742002-12-13 20:15:29 +0000920 {
paul718e3742002-12-13 20:15:29 +0000921 continue;
922 }
hasso462f20d2005-02-23 11:29:02 +0000923 /* equal to. */
pauleb3da6d2005-10-18 04:20:33 +0000924 else if (w->distance == distance)
paul718e3742002-12-13 20:15:29 +0000925 {
pauleb3da6d2005-10-18 04:20:33 +0000926 /* Found an equal-cost path to W.
927 * Calculate nexthop of to W from V. */
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200928 ospf_nexthop_calculation (area, v, w, l, distance, lsa_pos);
paul718e3742002-12-13 20:15:29 +0000929 }
hasso462f20d2005-02-23 11:29:02 +0000930 /* less than. */
931 else
paul718e3742002-12-13 20:15:29 +0000932 {
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000933 /* Found a lower-cost path to W.
934 * nexthop_calculation is conditional, if it finds
935 * valid nexthop it will call spf_add_parents, which
936 * will flush the old parents
937 */
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200938 if (ospf_nexthop_calculation (area, v, w, l, distance, lsa_pos))
Paul Jakma7591d8b2007-08-06 18:52:45 +0000939 /* Decrease the key of the node in the heap.
940 * trickle-sort it up towards root, just in case this
941 * node should now be the new root due the cost change.
Paul Jakmae95537f2007-08-07 16:22:05 +0000942 * (next pqueu_{de,en}queue will fully re-heap the queue).
Paul Jakma7591d8b2007-08-06 18:52:45 +0000943 */
944 trickle_up (w_lsa->stat, candidate);
paul718e3742002-12-13 20:15:29 +0000945 }
gdt630e4802004-08-31 17:28:41 +0000946 } /* end W is already on the candidate list */
947 } /* end loop over the links in V's LSA */
paul718e3742002-12-13 20:15:29 +0000948}
949
paul4dadc292005-05-06 21:37:42 +0000950static void
paul718e3742002-12-13 20:15:29 +0000951ospf_spf_dump (struct vertex *v, int i)
952{
hasso52dc7ee2004-09-23 19:18:23 +0000953 struct listnode *cnode;
954 struct listnode *nnode;
pauleb3da6d2005-10-18 04:20:33 +0000955 struct vertex_parent *parent;
paul718e3742002-12-13 20:15:29 +0000956
957 if (v->type == OSPF_VERTEX_ROUTER)
958 {
959 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000960 zlog_debug ("SPF Result: %d [R] %s", i, inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +0000961 }
962 else
963 {
964 struct network_lsa *lsa = (struct network_lsa *) v->lsa;
965 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000966 zlog_debug ("SPF Result: %d [N] %s/%d", i, inet_ntoa (v->lsa->id),
paul0c0f9cd2003-06-06 23:27:04 +0000967 ip_masklen (lsa->mask));
gdt630e4802004-08-31 17:28:41 +0000968 }
paul718e3742002-12-13 20:15:29 +0000969
paul1eb8ef22005-04-07 07:30:20 +0000970 if (IS_DEBUG_OSPF_EVENT)
pauleb3da6d2005-10-18 04:20:33 +0000971 for (ALL_LIST_ELEMENTS_RO (v->parents, nnode, parent))
972 {
973 zlog_debug (" nexthop %p %s %s",
974 parent->nexthop,
975 inet_ntoa (parent->nexthop->router),
976 parent->nexthop->oi ? IF_NAME(parent->nexthop->oi)
977 : "NULL");
978 }
paul718e3742002-12-13 20:15:29 +0000979
980 i++;
981
pauleb3da6d2005-10-18 04:20:33 +0000982 for (ALL_LIST_ELEMENTS_RO (v->children, cnode, v))
paul1eb8ef22005-04-07 07:30:20 +0000983 ospf_spf_dump (v, i);
paul718e3742002-12-13 20:15:29 +0000984}
985
986/* Second stage of SPF calculation. */
paul4dadc292005-05-06 21:37:42 +0000987static void
paul0c0f9cd2003-06-06 23:27:04 +0000988ospf_spf_process_stubs (struct ospf_area *area, struct vertex *v,
Paul Jakmab3bc68e2008-09-04 13:52:07 +0100989 struct route_table *rt,
990 int parent_is_root)
paul718e3742002-12-13 20:15:29 +0000991{
paul1eb8ef22005-04-07 07:30:20 +0000992 struct listnode *cnode, *cnnode;
paul718e3742002-12-13 20:15:29 +0000993 struct vertex *child;
994
995 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000996 zlog_debug ("ospf_process_stub():processing stubs for area %s",
paul0c0f9cd2003-06-06 23:27:04 +0000997 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +0000998 if (v->type == OSPF_VERTEX_ROUTER)
999 {
1000 u_char *p;
1001 u_char *lim;
1002 struct router_lsa_link *l;
1003 struct router_lsa *rlsa;
Joakim Tjernlund57c639f2012-07-07 17:06:12 +02001004 int lsa_pos = 0;
paul718e3742002-12-13 20:15:29 +00001005
paul0c0f9cd2003-06-06 23:27:04 +00001006 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001007 zlog_debug ("ospf_process_stubs():processing router LSA, id: %s",
paul0c0f9cd2003-06-06 23:27:04 +00001008 inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +00001009 rlsa = (struct router_lsa *) v->lsa;
1010
1011
paul0c0f9cd2003-06-06 23:27:04 +00001012 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001013 zlog_debug ("ospf_process_stubs(): we have %d links to process",
paul0c0f9cd2003-06-06 23:27:04 +00001014 ntohs (rlsa->links));
gdt630e4802004-08-31 17:28:41 +00001015 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +00001016 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
1017
1018 while (p < lim)
1019 {
1020 l = (struct router_lsa_link *) p;
1021
Denis Ovsienko05b77092011-08-23 11:36:27 +04001022 p += (OSPF_ROUTER_LSA_LINK_SIZE +
1023 (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
paul718e3742002-12-13 20:15:29 +00001024
1025 if (l->m[0].type == LSA_LINK_TYPE_STUB)
Joakim Tjernlund57c639f2012-07-07 17:06:12 +02001026 ospf_intra_add_stub (rt, l, v, area, parent_is_root, lsa_pos);
1027 lsa_pos++;
paul718e3742002-12-13 20:15:29 +00001028 }
1029 }
1030
gdt630e4802004-08-31 17:28:41 +00001031 ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1, 1);
paul718e3742002-12-13 20:15:29 +00001032
pauleb3da6d2005-10-18 04:20:33 +00001033 for (ALL_LIST_ELEMENTS (v->children, cnode, cnnode, child))
paul718e3742002-12-13 20:15:29 +00001034 {
paul718e3742002-12-13 20:15:29 +00001035 if (CHECK_FLAG (child->flags, OSPF_VERTEX_PROCESSED))
paul0c0f9cd2003-06-06 23:27:04 +00001036 continue;
Paul Jakmab3bc68e2008-09-04 13:52:07 +01001037
1038 /* the first level of routers connected to the root
1039 * should have 'parent_is_root' set, including those
1040 * connected via a network vertex.
1041 */
1042 if (area->spf == v)
1043 parent_is_root = 1;
1044 else if (v->type == OSPF_VERTEX_ROUTER)
1045 parent_is_root = 0;
1046
1047 ospf_spf_process_stubs (area, child, rt, parent_is_root);
paul718e3742002-12-13 20:15:29 +00001048
1049 SET_FLAG (child->flags, OSPF_VERTEX_PROCESSED);
1050 }
1051}
1052
1053void
1054ospf_rtrs_free (struct route_table *rtrs)
1055{
1056 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001057 struct list *or_list;
paul1eb8ef22005-04-07 07:30:20 +00001058 struct ospf_route *or;
1059 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001060
1061 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001062 zlog_debug ("Route: Router Routing Table free");
paul718e3742002-12-13 20:15:29 +00001063
1064 for (rn = route_top (rtrs); rn; rn = route_next (rn))
1065 if ((or_list = rn->info) != NULL)
1066 {
paul1eb8ef22005-04-07 07:30:20 +00001067 for (ALL_LIST_ELEMENTS (or_list, node, nnode, or))
1068 ospf_route_free (or);
paul718e3742002-12-13 20:15:29 +00001069
paul0c0f9cd2003-06-06 23:27:04 +00001070 list_delete (or_list);
paul718e3742002-12-13 20:15:29 +00001071
paul0c0f9cd2003-06-06 23:27:04 +00001072 /* Unlock the node. */
1073 rn->info = NULL;
1074 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001075 }
1076 route_table_finish (rtrs);
1077}
1078
Stephen Hemminger075e12f2011-12-06 23:54:17 +04001079#if 0
paul4dadc292005-05-06 21:37:42 +00001080static void
paul718e3742002-12-13 20:15:29 +00001081ospf_rtrs_print (struct route_table *rtrs)
1082{
1083 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001084 struct list *or_list;
1085 struct listnode *ln;
1086 struct listnode *pnode;
paul718e3742002-12-13 20:15:29 +00001087 struct ospf_route *or;
1088 struct ospf_path *path;
1089 char buf1[BUFSIZ];
1090 char buf2[BUFSIZ];
1091
1092 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001093 zlog_debug ("ospf_rtrs_print() start");
paul718e3742002-12-13 20:15:29 +00001094
1095 for (rn = route_top (rtrs); rn; rn = route_next (rn))
1096 if ((or_list = rn->info) != NULL)
paul1eb8ef22005-04-07 07:30:20 +00001097 for (ALL_LIST_ELEMENTS_RO (or_list, ln, or))
paul718e3742002-12-13 20:15:29 +00001098 {
paul718e3742002-12-13 20:15:29 +00001099 switch (or->path_type)
1100 {
1101 case OSPF_PATH_INTRA_AREA:
paul0c0f9cd2003-06-06 23:27:04 +00001102 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001103 zlog_debug ("%s [%d] area: %s",
paul0c0f9cd2003-06-06 23:27:04 +00001104 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1105 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1106 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +00001107 break;
1108 case OSPF_PATH_INTER_AREA:
paul0c0f9cd2003-06-06 23:27:04 +00001109 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001110 zlog_debug ("%s IA [%d] area: %s",
paul0c0f9cd2003-06-06 23:27:04 +00001111 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1112 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1113 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +00001114 break;
1115 default:
1116 break;
1117 }
1118
paul1eb8ef22005-04-07 07:30:20 +00001119 for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path))
paul718e3742002-12-13 20:15:29 +00001120 {
paul718e3742002-12-13 20:15:29 +00001121 if (path->nexthop.s_addr == 0)
paul0c0f9cd2003-06-06 23:27:04 +00001122 {
1123 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001124 zlog_debug (" directly attached to %s\r\n",
Joakim Tjernlunda8ba8472009-07-27 12:42:34 +02001125 ifindex2ifname (path->ifindex));
paul0c0f9cd2003-06-06 23:27:04 +00001126 }
1127 else
1128 {
1129 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001130 zlog_debug (" via %s, %s\r\n",
Joakim Tjernlunda8ba8472009-07-27 12:42:34 +02001131 inet_ntoa (path->nexthop),
1132 ifindex2ifname (path->ifindex));
paul0c0f9cd2003-06-06 23:27:04 +00001133 }
paul718e3742002-12-13 20:15:29 +00001134 }
1135 }
1136
ajs2a42e282004-12-08 18:43:03 +00001137 zlog_debug ("ospf_rtrs_print() end");
paul718e3742002-12-13 20:15:29 +00001138}
Stephen Hemminger075e12f2011-12-06 23:54:17 +04001139#endif
paul718e3742002-12-13 20:15:29 +00001140
1141/* Calculating the shortest-path tree for an area. */
paul4dadc292005-05-06 21:37:42 +00001142static void
paul0c0f9cd2003-06-06 23:27:04 +00001143ospf_spf_calculate (struct ospf_area *area, struct route_table *new_table,
paul718e3742002-12-13 20:15:29 +00001144 struct route_table *new_rtrs)
1145{
hasso462f20d2005-02-23 11:29:02 +00001146 struct pqueue *candidate;
paul718e3742002-12-13 20:15:29 +00001147 struct vertex *v;
pauleb3da6d2005-10-18 04:20:33 +00001148
paul718e3742002-12-13 20:15:29 +00001149 if (IS_DEBUG_OSPF_EVENT)
1150 {
ajs2a42e282004-12-08 18:43:03 +00001151 zlog_debug ("ospf_spf_calculate: Start");
1152 zlog_debug ("ospf_spf_calculate: running Dijkstra for area %s",
paul0c0f9cd2003-06-06 23:27:04 +00001153 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001154 }
1155
1156 /* Check router-lsa-self. If self-router-lsa is not yet allocated,
1157 return this area's calculation. */
paul0c0f9cd2003-06-06 23:27:04 +00001158 if (!area->router_lsa_self)
paul718e3742002-12-13 20:15:29 +00001159 {
1160 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001161 zlog_debug ("ospf_spf_calculate: "
paul0c0f9cd2003-06-06 23:27:04 +00001162 "Skip area %s's calculation due to empty router_lsa_self",
1163 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001164 return;
1165 }
1166
1167 /* RFC2328 16.1. (1). */
paul0c0f9cd2003-06-06 23:27:04 +00001168 /* Initialize the algorithm's data structures. */
hasso462f20d2005-02-23 11:29:02 +00001169
1170 /* This function scans all the LSA database and set the stat field to
1171 * LSA_SPF_NOT_EXPLORED. */
1172 ospf_lsdb_clean_stat (area->lsdb);
1173 /* Create a new heap for the candidates. */
1174 candidate = pqueue_create();
1175 candidate->cmp = cmp;
1176 candidate->update = update_stat;
paul718e3742002-12-13 20:15:29 +00001177
1178 /* Initialize the shortest-path tree to only the root (which is the
1179 router doing the calculation). */
1180 ospf_spf_init (area);
1181 v = area->spf;
hasso462f20d2005-02-23 11:29:02 +00001182 /* Set LSA position to LSA_SPF_IN_SPFTREE. This vertex is the root of the
1183 * spanning tree. */
1184 *(v->stat) = LSA_SPF_IN_SPFTREE;
paul718e3742002-12-13 20:15:29 +00001185
1186 /* Set Area A's TransitCapability to FALSE. */
1187 area->transit = OSPF_TRANSIT_FALSE;
1188 area->shortcut_capability = 1;
pauleb3da6d2005-10-18 04:20:33 +00001189
paul718e3742002-12-13 20:15:29 +00001190 for (;;)
1191 {
1192 /* RFC2328 16.1. (2). */
hasso462f20d2005-02-23 11:29:02 +00001193 ospf_spf_next (v, area, candidate);
paul718e3742002-12-13 20:15:29 +00001194
1195 /* RFC2328 16.1. (3). */
1196 /* If at this step the candidate list is empty, the shortest-
1197 path tree (of transit vertices) has been completely built and
1198 this stage of the procedure terminates. */
hasso462f20d2005-02-23 11:29:02 +00001199 if (candidate->size == 0)
paul718e3742002-12-13 20:15:29 +00001200 break;
1201
1202 /* Otherwise, choose the vertex belonging to the candidate list
1203 that is closest to the root, and add it to the shortest-path
1204 tree (removing it from the candidate list in the
paul0c0f9cd2003-06-06 23:27:04 +00001205 process). */
hasso462f20d2005-02-23 11:29:02 +00001206 /* Extract from the candidates the node with the lower key. */
1207 v = (struct vertex *) pqueue_dequeue (candidate);
1208 /* Update stat field in vertex. */
1209 *(v->stat) = LSA_SPF_IN_SPFTREE;
pauleb3da6d2005-10-18 04:20:33 +00001210
paul718e3742002-12-13 20:15:29 +00001211 ospf_vertex_add_parent (v);
1212
paul718e3742002-12-13 20:15:29 +00001213 /* RFC2328 16.1. (4). */
1214 if (v->type == OSPF_VERTEX_ROUTER)
1215 ospf_intra_add_router (new_rtrs, v, area);
paul0c0f9cd2003-06-06 23:27:04 +00001216 else
paul718e3742002-12-13 20:15:29 +00001217 ospf_intra_add_transit (new_table, v, area);
1218
1219 /* RFC2328 16.1. (5). */
1220 /* Iterate the algorithm by returning to Step 2. */
gdt630e4802004-08-31 17:28:41 +00001221
1222 } /* end loop until no more candidate vertices */
paul718e3742002-12-13 20:15:29 +00001223
1224 if (IS_DEBUG_OSPF_EVENT)
1225 {
1226 ospf_spf_dump (area->spf, 0);
1227 ospf_route_table_dump (new_table);
1228 }
1229
1230 /* Second stage of SPF calculation procedure's */
Paul Jakmab3bc68e2008-09-04 13:52:07 +01001231 ospf_spf_process_stubs (area, area->spf, new_table, 0);
paul718e3742002-12-13 20:15:29 +00001232
pauleb3da6d2005-10-18 04:20:33 +00001233 /* Free candidate queue. */
hasso462f20d2005-02-23 11:29:02 +00001234 pqueue_delete (candidate);
pauleb3da6d2005-10-18 04:20:33 +00001235
1236 ospf_vertex_dump (__func__, area->spf, 0, 1);
1237 /* Free nexthop information, canonical versions of which are attached
1238 * the first level of router vertices attached to the root vertex, see
1239 * ospf_nexthop_calculation.
1240 */
1241 ospf_canonical_nexthops_free (area->spf);
1242
Paul Jakma9c27ef92006-05-04 07:32:57 +00001243 /* Free SPF vertices, but not the list. List has ospf_vertex_free
1244 * as deconstructor.
1245 */
1246 list_delete_all_node (&vertex_list);
pauleb3da6d2005-10-18 04:20:33 +00001247
paul718e3742002-12-13 20:15:29 +00001248 /* Increment SPF Calculation Counter. */
1249 area->spf_calculation++;
1250
Paul Jakma2518efd2006-08-27 06:49:29 +00001251 quagga_gettime (QUAGGA_CLK_MONOTONIC, &area->ospf->ts_spf);
paul718e3742002-12-13 20:15:29 +00001252
1253 if (IS_DEBUG_OSPF_EVENT)
Paul Jakma9c27ef92006-05-04 07:32:57 +00001254 zlog_debug ("ospf_spf_calculate: Stop. %ld vertices",
1255 mtype_stats_alloc(MTYPE_OSPF_VERTEX));
paul718e3742002-12-13 20:15:29 +00001256}
David Lamparter6b0655a2014-06-04 06:53:35 +02001257
paul718e3742002-12-13 20:15:29 +00001258/* Timer for SPF calculation. */
paul4dadc292005-05-06 21:37:42 +00001259static int
paul68980082003-03-25 05:07:42 +00001260ospf_spf_calculate_timer (struct thread *thread)
paul718e3742002-12-13 20:15:29 +00001261{
paul68980082003-03-25 05:07:42 +00001262 struct ospf *ospf = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +00001263 struct route_table *new_table, *new_rtrs;
paul1eb8ef22005-04-07 07:30:20 +00001264 struct ospf_area *area;
1265 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001266
1267 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001268 zlog_debug ("SPF: Timer (SPF calculation expire)");
paul0c0f9cd2003-06-06 23:27:04 +00001269
paul718e3742002-12-13 20:15:29 +00001270 ospf->t_spf_calc = NULL;
1271
1272 /* Allocate new table tree. */
1273 new_table = route_table_init ();
paul0c0f9cd2003-06-06 23:27:04 +00001274 new_rtrs = route_table_init ();
paul718e3742002-12-13 20:15:29 +00001275
paul68980082003-03-25 05:07:42 +00001276 ospf_vl_unapprove (ospf);
paul718e3742002-12-13 20:15:29 +00001277
1278 /* Calculate SPF for each area. */
paul1eb8ef22005-04-07 07:30:20 +00001279 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
Paul Jakma9c27ef92006-05-04 07:32:57 +00001280 {
1281 /* Do backbone last, so as to first discover intra-area paths
1282 * for any back-bone virtual-links
1283 */
1284 if (ospf->backbone && ospf->backbone == area)
1285 continue;
1286
1287 ospf_spf_calculate (area, new_table, new_rtrs);
1288 }
1289
1290 /* SPF for backbone, if required */
1291 if (ospf->backbone)
1292 ospf_spf_calculate (ospf->backbone, new_table, new_rtrs);
1293
paul68980082003-03-25 05:07:42 +00001294 ospf_vl_shut_unapproved (ospf);
paul718e3742002-12-13 20:15:29 +00001295
paul68980082003-03-25 05:07:42 +00001296 ospf_ia_routing (ospf, new_table, new_rtrs);
paul718e3742002-12-13 20:15:29 +00001297
1298 ospf_prune_unreachable_networks (new_table);
1299 ospf_prune_unreachable_routers (new_rtrs);
1300
1301 /* AS-external-LSA calculation should not be performed here. */
1302
1303 /* If new Router Route is installed,
1304 then schedule re-calculate External routes. */
1305 if (1)
paul68980082003-03-25 05:07:42 +00001306 ospf_ase_calculate_schedule (ospf);
paul718e3742002-12-13 20:15:29 +00001307
paul68980082003-03-25 05:07:42 +00001308 ospf_ase_calculate_timer_add (ospf);
paul718e3742002-12-13 20:15:29 +00001309
1310 /* Update routing table. */
paul68980082003-03-25 05:07:42 +00001311 ospf_route_install (ospf, new_table);
paul718e3742002-12-13 20:15:29 +00001312
1313 /* Update ABR/ASBR routing table */
paul68980082003-03-25 05:07:42 +00001314 if (ospf->old_rtrs)
paul718e3742002-12-13 20:15:29 +00001315 {
1316 /* old_rtrs's node holds linked list of ospf_route. --kunihiro. */
paul68980082003-03-25 05:07:42 +00001317 /* ospf_route_delete (ospf->old_rtrs); */
1318 ospf_rtrs_free (ospf->old_rtrs);
paul718e3742002-12-13 20:15:29 +00001319 }
1320
paul68980082003-03-25 05:07:42 +00001321 ospf->old_rtrs = ospf->new_rtrs;
1322 ospf->new_rtrs = new_rtrs;
paul718e3742002-12-13 20:15:29 +00001323
paul0c0f9cd2003-06-06 23:27:04 +00001324 if (IS_OSPF_ABR (ospf))
paul68980082003-03-25 05:07:42 +00001325 ospf_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001326
1327 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001328 zlog_debug ("SPF: calculation complete");
paul718e3742002-12-13 20:15:29 +00001329
1330 return 0;
1331}
1332
1333/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
1334 set timer for SPF calc. */
1335void
paul68980082003-03-25 05:07:42 +00001336ospf_spf_calculate_schedule (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00001337{
pauld24f6e22005-10-21 09:23:12 +00001338 unsigned long delay, elapsed, ht;
1339 struct timeval result;
paul718e3742002-12-13 20:15:29 +00001340
1341 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001342 zlog_debug ("SPF: calculation timer scheduled");
paul718e3742002-12-13 20:15:29 +00001343
1344 /* OSPF instance does not exist. */
paul68980082003-03-25 05:07:42 +00001345 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001346 return;
pauld24f6e22005-10-21 09:23:12 +00001347
paul718e3742002-12-13 20:15:29 +00001348 /* SPF calculation timer is already scheduled. */
paul68980082003-03-25 05:07:42 +00001349 if (ospf->t_spf_calc)
paul718e3742002-12-13 20:15:29 +00001350 {
1351 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001352 zlog_debug ("SPF: calculation timer is already scheduled: %p",
paul0c0f9cd2003-06-06 23:27:04 +00001353 ospf->t_spf_calc);
paul718e3742002-12-13 20:15:29 +00001354 return;
1355 }
pauld24f6e22005-10-21 09:23:12 +00001356
1357 /* XXX Monotic timers: we only care about relative time here. */
Paul Jakma2518efd2006-08-27 06:49:29 +00001358 result = tv_sub (recent_relative_time (), ospf->ts_spf);
pauld24f6e22005-10-21 09:23:12 +00001359
1360 elapsed = (result.tv_sec * 1000) + (result.tv_usec / 1000);
1361 ht = ospf->spf_holdtime * ospf->spf_hold_multiplier;
1362
1363 if (ht > ospf->spf_max_holdtime)
1364 ht = ospf->spf_max_holdtime;
1365
paul718e3742002-12-13 20:15:29 +00001366 /* Get SPF calculation delay time. */
pauld24f6e22005-10-21 09:23:12 +00001367 if (elapsed < ht)
paul718e3742002-12-13 20:15:29 +00001368 {
pauld24f6e22005-10-21 09:23:12 +00001369 /* Got an event within the hold time of last SPF. We need to
1370 * increase the hold_multiplier, if it's not already at/past
1371 * maximum value, and wasn't already increased..
1372 */
1373 if (ht < ospf->spf_max_holdtime)
1374 ospf->spf_hold_multiplier++;
1375
1376 /* always honour the SPF initial delay */
1377 if ( (ht - elapsed) < ospf->spf_delay)
paul0c0f9cd2003-06-06 23:27:04 +00001378 delay = ospf->spf_delay;
paul718e3742002-12-13 20:15:29 +00001379 else
pauld24f6e22005-10-21 09:23:12 +00001380 delay = ht - elapsed;
paul718e3742002-12-13 20:15:29 +00001381 }
1382 else
pauld24f6e22005-10-21 09:23:12 +00001383 {
1384 /* Event is past required hold-time of last SPF */
1385 delay = ospf->spf_delay;
1386 ospf->spf_hold_multiplier = 1;
1387 }
1388
paul718e3742002-12-13 20:15:29 +00001389 if (IS_DEBUG_OSPF_EVENT)
pauld24f6e22005-10-21 09:23:12 +00001390 zlog_debug ("SPF: calculation timer delay = %ld", delay);
1391
paul68980082003-03-25 05:07:42 +00001392 ospf->t_spf_calc =
pauld24f6e22005-10-21 09:23:12 +00001393 thread_add_timer_msec (master, ospf_spf_calculate_timer, ospf, delay);
paul718e3742002-12-13 20:15:29 +00001394}