blob: 1fe8ab4b49b58e34d902acf738ca14ca224506c0 [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
Dinesh G Dutt50f38b32014-09-30 12:53:28 -070049/* Variables to ensure a SPF scheduled log message is printed only once */
50
51static unsigned int spf_reason_flags = 0;
52
Paul Jakmab6eef002014-10-09 14:19:51 +010053static void
54ospf_clear_spf_reason_flags ()
Dinesh G Dutt50f38b32014-09-30 12:53:28 -070055{
56 spf_reason_flags = 0;
57}
58
Paul Jakmab6eef002014-10-09 14:19:51 +010059static void
60ospf_spf_set_reason (ospf_spf_reason_t reason)
Dinesh G Dutt50f38b32014-09-30 12:53:28 -070061{
Paul Jakmab6eef002014-10-09 14:19:51 +010062 spf_reason_flags |= 1 << reason;
Dinesh G Dutt50f38b32014-09-30 12:53:28 -070063}
64
65static void
66ospf_get_spf_reason_str (char *buf)
67{
Paul Jakmab6eef002014-10-09 14:19:51 +010068 if (!buf)
69 return;
70
71 buf[0] = '\0';
72 if (spf_reason_flags)
Dinesh G Dutt50f38b32014-09-30 12:53:28 -070073 {
Paul Jakmab6eef002014-10-09 14:19:51 +010074 if (spf_reason_flags & SPF_FLAG_ROUTER_LSA_INSTALL)
75 strcat (buf, "R, ");
76 if (spf_reason_flags & SPF_FLAG_NETWORK_LSA_INSTALL)
77 strcat (buf, "N, ");
78 if (spf_reason_flags & SPF_FLAG_SUMMARY_LSA_INSTALL)
79 strcat (buf, "S, ");
80 if (spf_reason_flags & SPF_FLAG_ASBR_SUMMARY_LSA_INSTALL)
81 strcat (buf, "AS, ");
82 if (spf_reason_flags & SPF_FLAG_ABR_STATUS_CHANGE)
83 strcat (buf, "ABR, ");
84 if (spf_reason_flags & SPF_FLAG_ASBR_STATUS_CHANGE)
85 strcat (buf, "ASBR, ");
86 if (spf_reason_flags & SPF_FLAG_MAXAGE)
87 strcat (buf, "M, ");
Dinesh G Dutt50f38b32014-09-30 12:53:28 -070088 buf[strlen(buf)-2] = '\0'; /* skip the last ", " */
89 }
90}
91
Paul Jakma9c27ef92006-05-04 07:32:57 +000092static void ospf_vertex_free (void *);
93/* List of allocated vertices, to simplify cleanup of SPF.
94 * Not thread-safe obviously. If it ever needs to be, it'd have to be
95 * dynamically allocated at begin of ospf_spf_calculate
96 */
97static struct list vertex_list = { .del = ospf_vertex_free };
David Lamparter6b0655a2014-06-04 06:53:35 +020098
hasso462f20d2005-02-23 11:29:02 +000099/* Heap related functions, for the managment of the candidates, to
100 * be used with pqueue. */
101static int
102cmp (void * node1 , void * node2)
103{
104 struct vertex * v1 = (struct vertex *) node1;
105 struct vertex * v2 = (struct vertex *) node2;
106 if (v1 != NULL && v2 != NULL )
Paul Jakma9c27ef92006-05-04 07:32:57 +0000107 {
108 /* network vertices must be chosen before router vertices of same
109 * cost in order to find all shortest paths
110 */
111 if ( ((v1->distance - v2->distance) == 0)
112 && (v1->type != v2->type))
113 {
114 switch (v1->type)
115 {
116 case OSPF_VERTEX_NETWORK:
117 return -1;
118 case OSPF_VERTEX_ROUTER:
119 return 1;
120 }
121 }
122 else
123 return (v1->distance - v2->distance);
124 }
125 return 0;
hasso462f20d2005-02-23 11:29:02 +0000126}
127
128static void
pauleb3da6d2005-10-18 04:20:33 +0000129update_stat (void *node , int position)
hasso462f20d2005-02-23 11:29:02 +0000130{
pauleb3da6d2005-10-18 04:20:33 +0000131 struct vertex *v = node;
132
hasso462f20d2005-02-23 11:29:02 +0000133 /* Set the status of the vertex, when its position changes. */
134 *(v->stat) = position;
135}
David Lamparter6b0655a2014-06-04 06:53:35 +0200136
paul4dadc292005-05-06 21:37:42 +0000137static struct vertex_nexthop *
pauleb3da6d2005-10-18 04:20:33 +0000138vertex_nexthop_new (void)
paul718e3742002-12-13 20:15:29 +0000139{
pauleb3da6d2005-10-18 04:20:33 +0000140 return XCALLOC (MTYPE_OSPF_NEXTHOP, sizeof (struct vertex_nexthop));
paul718e3742002-12-13 20:15:29 +0000141}
142
paul4dadc292005-05-06 21:37:42 +0000143static void
paul718e3742002-12-13 20:15:29 +0000144vertex_nexthop_free (struct vertex_nexthop *nh)
145{
146 XFREE (MTYPE_OSPF_NEXTHOP, nh);
147}
148
pauleb3da6d2005-10-18 04:20:33 +0000149/* Free the canonical nexthop objects for an area, ie the nexthop objects
Paul Jakma9c27ef92006-05-04 07:32:57 +0000150 * attached to the first-hop router vertices, and any intervening network
151 * vertices.
pauleb3da6d2005-10-18 04:20:33 +0000152 */
153static void
154ospf_canonical_nexthops_free (struct vertex *root)
paul718e3742002-12-13 20:15:29 +0000155{
pauleb3da6d2005-10-18 04:20:33 +0000156 struct listnode *node, *nnode;
157 struct vertex *child;
158
159 for (ALL_LIST_ELEMENTS (root->children, node, nnode, child))
160 {
161 struct listnode *n2, *nn2;
162 struct vertex_parent *vp;
163
paul58e1bef2005-11-11 12:10:03 +0000164 /* router vertices through an attached network each
165 * have a distinct (canonical / not inherited) nexthop
166 * which must be freed.
167 *
168 * A network vertex can only have router vertices as its
169 * children, so only one level of recursion is possible.
170 */
pauleb3da6d2005-10-18 04:20:33 +0000171 if (child->type == OSPF_VERTEX_NETWORK)
172 ospf_canonical_nexthops_free (child);
173
paul58e1bef2005-11-11 12:10:03 +0000174 /* Free child nexthops pointing back to this root vertex */
pauleb3da6d2005-10-18 04:20:33 +0000175 for (ALL_LIST_ELEMENTS (child->parents, n2, nn2, vp))
Paul Jakma9c27ef92006-05-04 07:32:57 +0000176 if (vp->parent == root && vp->nexthop)
paul58e1bef2005-11-11 12:10:03 +0000177 vertex_nexthop_free (vp->nexthop);
pauleb3da6d2005-10-18 04:20:33 +0000178 }
179}
David Lamparter6b0655a2014-06-04 06:53:35 +0200180
Paul Jakma9c27ef92006-05-04 07:32:57 +0000181/* TODO: Parent list should be excised, in favour of maintaining only
182 * vertex_nexthop, with refcounts.
183 */
pauleb3da6d2005-10-18 04:20:33 +0000184static struct vertex_parent *
185vertex_parent_new (struct vertex *v, int backlink, struct vertex_nexthop *hop)
186{
187 struct vertex_parent *new;
188
189 new = XMALLOC (MTYPE_OSPF_VERTEX_PARENT, sizeof (struct vertex_parent));
190
191 if (new == NULL)
192 return NULL;
193
194 new->parent = v;
195 new->backlink = backlink;
196 new->nexthop = hop;
paul718e3742002-12-13 20:15:29 +0000197 return new;
198}
paul0c0f9cd2003-06-06 23:27:04 +0000199
pauleb3da6d2005-10-18 04:20:33 +0000200static void
Paul Jakma9c27ef92006-05-04 07:32:57 +0000201vertex_parent_free (void *p)
pauleb3da6d2005-10-18 04:20:33 +0000202{
203 XFREE (MTYPE_OSPF_VERTEX_PARENT, p);
204}
David Lamparter6b0655a2014-06-04 06:53:35 +0200205
paul4dadc292005-05-06 21:37:42 +0000206static struct vertex *
paul718e3742002-12-13 20:15:29 +0000207ospf_vertex_new (struct ospf_lsa *lsa)
208{
209 struct vertex *new;
210
pauleb3da6d2005-10-18 04:20:33 +0000211 new = XCALLOC (MTYPE_OSPF_VERTEX, sizeof (struct vertex));
paul718e3742002-12-13 20:15:29 +0000212
213 new->flags = 0;
hasso462f20d2005-02-23 11:29:02 +0000214 new->stat = &(lsa->stat);
paul718e3742002-12-13 20:15:29 +0000215 new->type = lsa->data->type;
216 new->id = lsa->data->id;
217 new->lsa = lsa->data;
pauleb3da6d2005-10-18 04:20:33 +0000218 new->children = list_new ();
219 new->parents = list_new ();
Paul Jakma9c27ef92006-05-04 07:32:57 +0000220 new->parents->del = vertex_parent_free;
pauleb3da6d2005-10-18 04:20:33 +0000221
Paul Jakma9c27ef92006-05-04 07:32:57 +0000222 listnode_add (&vertex_list, new);
223
224 if (IS_DEBUG_OSPF_EVENT)
225 zlog_debug ("%s: Created %s vertex %s", __func__,
226 new->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
227 inet_ntoa (new->lsa->id));
paul718e3742002-12-13 20:15:29 +0000228 return new;
229}
230
paul4dadc292005-05-06 21:37:42 +0000231static void
Paul Jakma9c27ef92006-05-04 07:32:57 +0000232ospf_vertex_free (void *data)
paul718e3742002-12-13 20:15:29 +0000233{
Paul Jakma9c27ef92006-05-04 07:32:57 +0000234 struct vertex *v = data;
paul7461d452005-06-13 13:57:16 +0000235
Paul Jakma9c27ef92006-05-04 07:32:57 +0000236 if (IS_DEBUG_OSPF_EVENT)
237 zlog_debug ("%s: Free %s vertex %s", __func__,
238 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
239 inet_ntoa (v->lsa->id));
pauleb3da6d2005-10-18 04:20:33 +0000240
Paul Jakma9c27ef92006-05-04 07:32:57 +0000241 /* There should be no parents potentially holding references to this vertex
242 * Children however may still be there, but presumably referenced by other
243 * vertices
pauleb3da6d2005-10-18 04:20:33 +0000244 */
Paul Jakma9c27ef92006-05-04 07:32:57 +0000245 //assert (listcount (v->parents) == 0);
pauleb3da6d2005-10-18 04:20:33 +0000246
Paul Jakma9c27ef92006-05-04 07:32:57 +0000247 if (v->children)
248 list_delete (v->children);
249 v->children = NULL;
250
251 if (v->parents)
252 list_delete (v->parents);
pauleb3da6d2005-10-18 04:20:33 +0000253 v->parents = NULL;
254
255 v->lsa = NULL;
paul7461d452005-06-13 13:57:16 +0000256
paul718e3742002-12-13 20:15:29 +0000257 XFREE (MTYPE_OSPF_VERTEX, v);
258}
259
paul4dadc292005-05-06 21:37:42 +0000260static void
hassoeb1ce602004-10-08 08:17:22 +0000261ospf_vertex_dump(const char *msg, struct vertex *v,
pauleb3da6d2005-10-18 04:20:33 +0000262 int print_parents, int print_children)
gdt630e4802004-08-31 17:28:41 +0000263{
264 if ( ! IS_DEBUG_OSPF_EVENT)
265 return;
266
pauleb3da6d2005-10-18 04:20:33 +0000267 zlog_debug("%s %s vertex %s distance %u flags %u",
gdt630e4802004-08-31 17:28:41 +0000268 msg,
269 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
270 inet_ntoa(v->lsa->id),
271 v->distance,
gdt630e4802004-08-31 17:28:41 +0000272 (unsigned int)v->flags);
273
pauleb3da6d2005-10-18 04:20:33 +0000274 if (print_parents)
gdt630e4802004-08-31 17:28:41 +0000275 {
paul1eb8ef22005-04-07 07:30:20 +0000276 struct listnode *node;
pauleb3da6d2005-10-18 04:20:33 +0000277 struct vertex_parent *vp;
paul1eb8ef22005-04-07 07:30:20 +0000278
pauleb3da6d2005-10-18 04:20:33 +0000279 for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
gdt630e4802004-08-31 17:28:41 +0000280 {
281 char buf1[BUFSIZ];
pauleb3da6d2005-10-18 04:20:33 +0000282
283 if (vp)
gdt630e4802004-08-31 17:28:41 +0000284 {
pauleb3da6d2005-10-18 04:20:33 +0000285 zlog_debug ("parent %s backlink %d nexthop %s interface %s",
286 inet_ntoa(vp->parent->lsa->id), vp->backlink,
287 inet_ntop(AF_INET, &vp->nexthop->router, buf1, BUFSIZ),
288 vp->nexthop->oi ? IF_NAME(vp->nexthop->oi) : "NULL");
gdt630e4802004-08-31 17:28:41 +0000289 }
290 }
291 }
292
293 if (print_children)
294 {
hasso52dc7ee2004-09-23 19:18:23 +0000295 struct listnode *cnode;
paul1eb8ef22005-04-07 07:30:20 +0000296 struct vertex *cv;
297
pauleb3da6d2005-10-18 04:20:33 +0000298 for (ALL_LIST_ELEMENTS_RO (v->children, cnode, cv))
paul1eb8ef22005-04-07 07:30:20 +0000299 ospf_vertex_dump(" child:", cv, 0, 0);
gdt630e4802004-08-31 17:28:41 +0000300 }
301}
302
303
304/* Add a vertex to the list of children in each of its parents. */
paul4dadc292005-05-06 21:37:42 +0000305static void
paul718e3742002-12-13 20:15:29 +0000306ospf_vertex_add_parent (struct vertex *v)
307{
pauleb3da6d2005-10-18 04:20:33 +0000308 struct vertex_parent *vp;
hasso52dc7ee2004-09-23 19:18:23 +0000309 struct listnode *node;
paul7461d452005-06-13 13:57:16 +0000310
Paul Jakma9c27ef92006-05-04 07:32:57 +0000311 assert (v && v->parents);
paul7461d452005-06-13 13:57:16 +0000312
pauleb3da6d2005-10-18 04:20:33 +0000313 for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
paul718e3742002-12-13 20:15:29 +0000314 {
pauleb3da6d2005-10-18 04:20:33 +0000315 assert (vp->parent && vp->parent->children);
paul7461d452005-06-13 13:57:16 +0000316
paul718e3742002-12-13 20:15:29 +0000317 /* No need to add two links from the same parent. */
pauleb3da6d2005-10-18 04:20:33 +0000318 if (listnode_lookup (vp->parent->children, v) == NULL)
319 listnode_add (vp->parent->children, v);
paul718e3742002-12-13 20:15:29 +0000320 }
321}
David Lamparter6b0655a2014-06-04 06:53:35 +0200322
paul4dadc292005-05-06 21:37:42 +0000323static void
paul718e3742002-12-13 20:15:29 +0000324ospf_spf_init (struct ospf_area *area)
325{
326 struct vertex *v;
Paul Jakma9c27ef92006-05-04 07:32:57 +0000327
paul718e3742002-12-13 20:15:29 +0000328 /* Create root node. */
329 v = ospf_vertex_new (area->router_lsa_self);
Paul Jakmabd34fb32007-02-26 17:14:48 +0000330
paul718e3742002-12-13 20:15:29 +0000331 area->spf = v;
332
333 /* Reset ABR and ASBR router counts. */
334 area->abr_count = 0;
335 area->asbr_count = 0;
336}
337
pauld355bfa2004-04-08 07:43:45 +0000338/* return index of link back to V from W, or -1 if no link found */
paul4dadc292005-05-06 21:37:42 +0000339static int
paul718e3742002-12-13 20:15:29 +0000340ospf_lsa_has_link (struct lsa_header *w, struct lsa_header *v)
341{
hassoeb1ce602004-10-08 08:17:22 +0000342 unsigned int i, length;
paul718e3742002-12-13 20:15:29 +0000343 struct router_lsa *rl;
344 struct network_lsa *nl;
345
346 /* In case of W is Network LSA. */
347 if (w->type == OSPF_NETWORK_LSA)
348 {
349 if (v->type == OSPF_NETWORK_LSA)
pauld355bfa2004-04-08 07:43:45 +0000350 return -1;
paul718e3742002-12-13 20:15:29 +0000351
352 nl = (struct network_lsa *) w;
353 length = (ntohs (w->length) - OSPF_LSA_HEADER_SIZE - 4) / 4;
paul0c0f9cd2003-06-06 23:27:04 +0000354
paul718e3742002-12-13 20:15:29 +0000355 for (i = 0; i < length; i++)
356 if (IPV4_ADDR_SAME (&nl->routers[i], &v->id))
pauld355bfa2004-04-08 07:43:45 +0000357 return i;
358 return -1;
paul718e3742002-12-13 20:15:29 +0000359 }
360
361 /* In case of W is Router LSA. */
362 if (w->type == OSPF_ROUTER_LSA)
363 {
364 rl = (struct router_lsa *) w;
365
366 length = ntohs (w->length);
367
368 for (i = 0;
paul0c0f9cd2003-06-06 23:27:04 +0000369 i < ntohs (rl->links) && length >= sizeof (struct router_lsa);
370 i++, length -= 12)
paul718e3742002-12-13 20:15:29 +0000371 {
372 switch (rl->link[i].type)
373 {
374 case LSA_LINK_TYPE_POINTOPOINT:
375 case LSA_LINK_TYPE_VIRTUALLINK:
376 /* Router LSA ID. */
377 if (v->type == OSPF_ROUTER_LSA &&
378 IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
379 {
pauld355bfa2004-04-08 07:43:45 +0000380 return i;
paul718e3742002-12-13 20:15:29 +0000381 }
382 break;
383 case LSA_LINK_TYPE_TRANSIT:
384 /* Network LSA ID. */
385 if (v->type == OSPF_NETWORK_LSA &&
386 IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
387 {
pauld355bfa2004-04-08 07:43:45 +0000388 return i;
paul0c0f9cd2003-06-06 23:27:04 +0000389 }
paul718e3742002-12-13 20:15:29 +0000390 break;
391 case LSA_LINK_TYPE_STUB:
pauleb3da6d2005-10-18 04:20:33 +0000392 /* Stub can't lead anywhere, carry on */
paul718e3742002-12-13 20:15:29 +0000393 continue;
394 default:
395 break;
396 }
397 }
398 }
pauld355bfa2004-04-08 07:43:45 +0000399 return -1;
paul718e3742002-12-13 20:15:29 +0000400}
401
gdt630e4802004-08-31 17:28:41 +0000402/* Find the next link after prev_link from v to w. If prev_link is
403 * NULL, return the first link from v to w. Ignore stub and virtual links;
404 * these link types will never be returned.
405 */
paul4dadc292005-05-06 21:37:42 +0000406static struct router_lsa_link *
paul718e3742002-12-13 20:15:29 +0000407ospf_get_next_link (struct vertex *v, struct vertex *w,
paul0c0f9cd2003-06-06 23:27:04 +0000408 struct router_lsa_link *prev_link)
paul718e3742002-12-13 20:15:29 +0000409{
410 u_char *p;
411 u_char *lim;
Joakim Tjernlundbd540372009-07-27 12:42:31 +0200412 u_char lsa_type = LSA_LINK_TYPE_TRANSIT;
paul718e3742002-12-13 20:15:29 +0000413 struct router_lsa_link *l;
414
Joakim Tjernlundbd540372009-07-27 12:42:31 +0200415 if (w->type == OSPF_VERTEX_ROUTER)
416 lsa_type = LSA_LINK_TYPE_POINTOPOINT;
417
paul718e3742002-12-13 20:15:29 +0000418 if (prev_link == NULL)
gdt630e4802004-08-31 17:28:41 +0000419 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +0000420 else
421 {
paul0c0f9cd2003-06-06 23:27:04 +0000422 p = (u_char *) prev_link;
Denis Ovsienko05b77092011-08-23 11:36:27 +0400423 p += (OSPF_ROUTER_LSA_LINK_SIZE +
424 (prev_link->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
paul718e3742002-12-13 20:15:29 +0000425 }
paul0c0f9cd2003-06-06 23:27:04 +0000426
paul718e3742002-12-13 20:15:29 +0000427 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
428
429 while (p < lim)
430 {
431 l = (struct router_lsa_link *) p;
432
Denis Ovsienko05b77092011-08-23 11:36:27 +0400433 p += (OSPF_ROUTER_LSA_LINK_SIZE + (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
paul718e3742002-12-13 20:15:29 +0000434
Joakim Tjernlundbd540372009-07-27 12:42:31 +0200435 if (l->m[0].type != lsa_type)
paul0c0f9cd2003-06-06 23:27:04 +0000436 continue;
paul718e3742002-12-13 20:15:29 +0000437
438 if (IPV4_ADDR_SAME (&l->link_id, &w->id))
paul0c0f9cd2003-06-06 23:27:04 +0000439 return l;
paul718e3742002-12-13 20:15:29 +0000440 }
441
442 return NULL;
443}
444
pauleb3da6d2005-10-18 04:20:33 +0000445static void
446ospf_spf_flush_parents (struct vertex *w)
447{
448 struct vertex_parent *vp;
449 struct listnode *ln, *nn;
450
451 /* delete the existing nexthops */
452 for (ALL_LIST_ELEMENTS (w->parents, ln, nn, vp))
453 {
454 list_delete_node (w->parents, ln);
455 vertex_parent_free (vp);
456 }
457}
458
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000459/*
460 * Consider supplied next-hop for inclusion to the supplied list of
461 * equal-cost next-hops, adjust list as neccessary.
462 */
463static void
464ospf_spf_add_parent (struct vertex *v, struct vertex *w,
465 struct vertex_nexthop *newhop,
Paul Jakmabd34fb32007-02-26 17:14:48 +0000466 unsigned int distance)
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000467{
David Lamparter7b925892012-07-23 18:17:57 +0200468 struct vertex_parent *vp, *wp;
469 struct listnode *node;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000470
Paul Jakma08d3d5b2007-05-07 16:38:35 +0000471 /* we must have a newhop, and a distance */
Paul Jakmabd34fb32007-02-26 17:14:48 +0000472 assert (v && w && newhop);
Paul Jakma08d3d5b2007-05-07 16:38:35 +0000473 assert (distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000474
Paul Jakma08d3d5b2007-05-07 16:38:35 +0000475 /* IFF w has already been assigned a distance, then we shouldn't get here
476 * unless callers have determined V(l)->W is shortest / equal-shortest
477 * path (0 is a special case distance (no distance yet assigned)).
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000478 */
Paul Jakma08d3d5b2007-05-07 16:38:35 +0000479 if (w->distance)
480 assert (distance <= w->distance);
481 else
482 w->distance = distance;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000483
Paul Jakmab75ae992007-03-23 11:17:28 +0000484 if (IS_DEBUG_OSPF_EVENT)
485 {
486 char buf[2][INET_ADDRSTRLEN];
487 zlog_debug ("%s: Adding %s as parent of %s",
488 __func__,
489 inet_ntop(AF_INET, &v->lsa->id, buf[0], sizeof(buf[0])),
490 inet_ntop(AF_INET, &w->lsa->id, buf[1], sizeof(buf[1])));
491 }
492
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000493 /* Adding parent for a new, better path: flush existing parents from W. */
Paul Jakmabd34fb32007-02-26 17:14:48 +0000494 if (distance < w->distance)
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000495 {
Paul Jakmab75ae992007-03-23 11:17:28 +0000496 if (IS_DEBUG_OSPF_EVENT)
497 zlog_debug ("%s: distance %d better than %d, flushing existing parents",
498 __func__, distance, w->distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000499 ospf_spf_flush_parents (w);
Paul Jakmabd34fb32007-02-26 17:14:48 +0000500 w->distance = distance;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000501 }
502
David Lamparter7b925892012-07-23 18:17:57 +0200503 /* new parent is <= existing parents, add it to parent list (if nexthop
504 * not on parent list)
505 */
506 for (ALL_LIST_ELEMENTS_RO(w->parents, node, wp))
507 {
508 if (memcmp(newhop, wp->nexthop, sizeof(*newhop)) == 0)
509 {
510 if (IS_DEBUG_OSPF_EVENT)
511 zlog_debug ("%s: ... nexthop already on parent list, skipping add", __func__);
512 return;
513 }
514 }
515
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000516 vp = vertex_parent_new (v, ospf_lsa_has_link (w->lsa, v->lsa), newhop);
517 listnode_add (w->parents, vp);
518
519 return;
520}
521
gdt630e4802004-08-31 17:28:41 +0000522/* 16.1.1. Calculate nexthop from root through V (parent) to
Paul Jakmabd34fb32007-02-26 17:14:48 +0000523 * vertex W (destination), with given distance from root->W.
pauleb3da6d2005-10-18 04:20:33 +0000524 *
525 * The link must be supplied if V is the root vertex. In all other cases
526 * it may be NULL.
Paul Jakmabd34fb32007-02-26 17:14:48 +0000527 *
528 * Note that this function may fail, hence the state of the destination
529 * vertex, W, should /not/ be modified in a dependent manner until
530 * this function returns. This function will update the W vertex with the
531 * provided distance as appropriate.
gdt630e4802004-08-31 17:28:41 +0000532 */
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000533static unsigned int
pauleb3da6d2005-10-18 04:20:33 +0000534ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v,
Paul Jakmabd34fb32007-02-26 17:14:48 +0000535 struct vertex *w, struct router_lsa_link *l,
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200536 unsigned int distance, int lsa_pos)
paul718e3742002-12-13 20:15:29 +0000537{
paul1eb8ef22005-04-07 07:30:20 +0000538 struct listnode *node, *nnode;
pauleb3da6d2005-10-18 04:20:33 +0000539 struct vertex_nexthop *nh;
540 struct vertex_parent *vp;
paul718e3742002-12-13 20:15:29 +0000541 struct ospf_interface *oi = NULL;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000542 unsigned int added = 0;
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200543 char buf1[BUFSIZ];
544 char buf2[BUFSIZ];
paul0c0f9cd2003-06-06 23:27:04 +0000545
paul718e3742002-12-13 20:15:29 +0000546 if (IS_DEBUG_OSPF_EVENT)
gdt630e4802004-08-31 17:28:41 +0000547 {
ajs2a42e282004-12-08 18:43:03 +0000548 zlog_debug ("ospf_nexthop_calculation(): Start");
gdt630e4802004-08-31 17:28:41 +0000549 ospf_vertex_dump("V (parent):", v, 1, 1);
550 ospf_vertex_dump("W (dest) :", w, 1, 1);
Paul Jakmabd34fb32007-02-26 17:14:48 +0000551 zlog_debug ("V->W distance: %d", distance);
gdt630e4802004-08-31 17:28:41 +0000552 }
paul718e3742002-12-13 20:15:29 +0000553
paul718e3742002-12-13 20:15:29 +0000554 if (v == area->spf)
Paul Jakma9c27ef92006-05-04 07:32:57 +0000555 {
gdt630e4802004-08-31 17:28:41 +0000556 /* 16.1.1 para 4. In the first case, the parent vertex (V) is the
557 root (the calculating router itself). This means that the
558 destination is either a directly connected network or directly
559 connected router. The outgoing interface in this case is simply
560 the OSPF interface connecting to the destination network/router.
561 */
562
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200563 /* we *must* be supplied with the link data */
564 assert (l != NULL);
565 oi = ospf_if_lookup_by_lsa_pos (area, lsa_pos);
566 if (!oi)
567 {
568 zlog_debug("%s: OI not found in LSA: lsa_pos:%d link_id:%s link_data:%s",
569 __func__, lsa_pos,
570 inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ),
571 inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ));
572 return 0;
573 }
574
575 if (IS_DEBUG_OSPF_EVENT)
576 {
577 zlog_debug("%s: considering link:%s "
578 "type:%d link_id:%s link_data:%s",
579 __func__, oi->ifp->name, l->m[0].type,
580 inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ),
581 inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ));
582 }
583
paul718e3742002-12-13 20:15:29 +0000584 if (w->type == OSPF_VERTEX_ROUTER)
paul0c0f9cd2003-06-06 23:27:04 +0000585 {
pauleb3da6d2005-10-18 04:20:33 +0000586 /* l is a link from v to w
587 * l2 will be link from w to v
588 */
589 struct router_lsa_link *l2 = NULL;
paul0c0f9cd2003-06-06 23:27:04 +0000590
pauleb3da6d2005-10-18 04:20:33 +0000591 if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT)
592 {
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200593 struct in_addr nexthop;
594
pauleb3da6d2005-10-18 04:20:33 +0000595 /* If the destination is a router which connects to
596 the calculating router via a Point-to-MultiPoint
597 network, the destination's next hop IP address(es)
598 can be determined by examining the destination's
599 router-LSA: each link pointing back to the
600 calculating router and having a Link Data field
601 belonging to the Point-to-MultiPoint network
602 provides an IP address of the next hop router.
gdt630e4802004-08-31 17:28:41 +0000603
pauleb3da6d2005-10-18 04:20:33 +0000604 At this point l is a link from V to W, and V is the
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200605 root ("us"). If it is a point-to-multipoint interface,
606 then look through the links in the opposite direction (W to V).
607 If any of them have an address that lands within the
pauleb3da6d2005-10-18 04:20:33 +0000608 subnet declared by the PtMP link, then that link
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200609 is a constituent of the PtMP link, and its address is
pauleb3da6d2005-10-18 04:20:33 +0000610 a nexthop address for V.
611 */
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200612 if (oi->type == OSPF_IFTYPE_POINTOPOINT)
613 {
Christian Frankef2b53da2013-03-20 15:28:46 +0000614 /* Having nexthop = 0 is tempting, but NOT acceptable.
615 It breaks AS-External routes with a forwarding address,
616 since ospf_ase_complete_direct_routes() will mistakenly
617 assume we've reached the last hop and should place the
618 forwarding address as nexthop.
619 Also, users may configure multi-access links in p2p mode,
620 so we need the IP to ARP the nexthop.
621 */
622 struct ospf_neighbor *nbr_w;
623
624 nbr_w = ospf_nbr_lookup_by_routerid (oi->nbrs, &l->link_id);
625 if (nbr_w != NULL)
626 {
627 added = 1;
628 nexthop = nbr_w->src;
629 }
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200630 }
631 else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
632 {
633 struct prefix_ipv4 la;
gdt630e4802004-08-31 17:28:41 +0000634
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200635 la.family = AF_INET;
636 la.prefixlen = oi->address->prefixlen;
pauleb3da6d2005-10-18 04:20:33 +0000637
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200638 /* V links to W on PtMP interface
639 - find the interface address on W */
640 while ((l2 = ospf_get_next_link (w, v, l2)))
641 {
642 la.prefix = l2->link_data;
gdt630e4802004-08-31 17:28:41 +0000643
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200644 if (prefix_cmp ((struct prefix *) &la,
645 oi->address) != 0)
646 continue;
647 /* link_data is on our PtMP network */
648 added = 1;
649 nexthop = l2->link_data;
650 break;
651 }
652 }
pauleb3da6d2005-10-18 04:20:33 +0000653
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200654 if (added)
pauleb3da6d2005-10-18 04:20:33 +0000655 {
656 /* found all necessary info to build nexthop */
657 nh = vertex_nexthop_new ();
658 nh->oi = oi;
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200659 nh->router = nexthop;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000660 ospf_spf_add_parent (v, w, nh, distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000661 return 1;
pauleb3da6d2005-10-18 04:20:33 +0000662 }
663 else
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200664 zlog_info("%s: could not determine nexthop for link %s",
665 __func__, oi->ifp->name);
pauleb3da6d2005-10-18 04:20:33 +0000666 } /* end point-to-point link from V to W */
Paul Jakma9c27ef92006-05-04 07:32:57 +0000667 else if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK)
668 {
669 struct ospf_vl_data *vl_data;
670
671 /* VLink implementation limitations:
672 * a) vl_data can only reference one nexthop, so no ECMP
673 * to backbone through VLinks. Though transit-area
674 * summaries may be considered, and those can be ECMP.
675 * b) We can only use /one/ VLink, even if multiple ones
676 * exist this router through multiple transit-areas.
677 */
678 vl_data = ospf_vl_lookup (area->ospf, NULL, l->link_id);
679
680 if (vl_data
681 && CHECK_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED))
682 {
683 nh = vertex_nexthop_new ();
684 nh->oi = vl_data->nexthop.oi;
685 nh->router = vl_data->nexthop.router;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000686 ospf_spf_add_parent (v, w, nh, distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000687 return 1;
Paul Jakma9c27ef92006-05-04 07:32:57 +0000688 }
689 else
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000690 zlog_info("ospf_nexthop_calculation(): "
691 "vl_data for VL link not found");
Paul Jakma9c27ef92006-05-04 07:32:57 +0000692 } /* end virtual-link from V to W */
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000693 return 0;
gdt630e4802004-08-31 17:28:41 +0000694 } /* end W is a Router vertex */
paul718e3742002-12-13 20:15:29 +0000695 else
paul0c0f9cd2003-06-06 23:27:04 +0000696 {
pauleb3da6d2005-10-18 04:20:33 +0000697 assert(w->type == OSPF_VERTEX_NETWORK);
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200698
699 nh = vertex_nexthop_new ();
700 nh->oi = oi;
701 nh->router.s_addr = 0; /* Nexthop not required */
702 ospf_spf_add_parent (v, w, nh, distance);
703 return 1;
paul0c0f9cd2003-06-06 23:27:04 +0000704 }
gdt630e4802004-08-31 17:28:41 +0000705 } /* end V is the root */
gdt630e4802004-08-31 17:28:41 +0000706 /* Check if W's parent is a network connected to root. */
paul718e3742002-12-13 20:15:29 +0000707 else if (v->type == OSPF_VERTEX_NETWORK)
708 {
gdt630e4802004-08-31 17:28:41 +0000709 /* See if any of V's parents are the root. */
pauleb3da6d2005-10-18 04:20:33 +0000710 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
paul718e3742002-12-13 20:15:29 +0000711 {
pauleb3da6d2005-10-18 04:20:33 +0000712 if (vp->parent == area->spf) /* connects to root? */
gdt630e4802004-08-31 17:28:41 +0000713 {
714 /* 16.1.1 para 5. ...the parent vertex is a network that
715 * directly connects the calculating router to the destination
716 * router. The list of next hops is then determined by
717 * examining the destination's router-LSA...
718 */
719
720 assert(w->type == OSPF_VERTEX_ROUTER);
paul0c0f9cd2003-06-06 23:27:04 +0000721 while ((l = ospf_get_next_link (w, v, l)))
722 {
gdt630e4802004-08-31 17:28:41 +0000723 /* ...For each link in the router-LSA that points back to the
724 * parent network, the link's Link Data field provides the IP
725 * address of a next hop router. The outgoing interface to
726 * use can then be derived from the next hop IP address (or
727 * it can be inherited from the parent network).
728 */
pauleb3da6d2005-10-18 04:20:33 +0000729 nh = vertex_nexthop_new ();
730 nh->oi = vp->nexthop->oi;
731 nh->router = l->link_data;
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000732 added = 1;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000733 ospf_spf_add_parent (v, w, nh, distance);
paul0c0f9cd2003-06-06 23:27:04 +0000734 }
Paul Jakma945ea292012-08-06 12:17:12 +0100735 /* Note lack of return is deliberate. See next comment. */
736 }
paul718e3742002-12-13 20:15:29 +0000737 }
Paul Jakma945ea292012-08-06 12:17:12 +0100738 /* NB: This code is non-trivial.
739 *
740 * E.g. it is not enough to know that V connects to the root. It is
741 * also important that the while above, looping through all links from
742 * W->V found at least one link, so that we know there is
743 * bi-directional connectivity between V and W (which need not be the
744 * case, e.g. when OSPF has not yet converged fully). Otherwise, if
745 * we /always/ return here, without having checked that root->V->-W
746 * actually resulted in a valid nexthop being created, then we we will
747 * prevent SPF from finding/using higher cost paths.
748 *
749 * It is important, if root->V->W has not been added, that we continue
750 * through to the intervening-router nexthop code below. So as to
751 * ensure other paths to V may be used. This avoids unnecessary
752 * blackholes while OSPF is convergening.
753 *
754 * I.e. we may have arrived at this function, examining V -> W, via
755 * workable paths other than root -> V, and it's important to avoid
756 * getting "confused" by non-working root->V->W path - it's important
757 * to *not* lose the working non-root paths, just because of a
758 * non-viable root->V->W.
759 *
760 * See also bug #330 (required reading!), and:
761 *
762 * http://blogs.oracle.com/paulj/entry/the_difference_a_line_makes
763 */
764 if (added)
765 return added;
paul718e3742002-12-13 20:15:29 +0000766 }
767
gdt630e4802004-08-31 17:28:41 +0000768 /* 16.1.1 para 4. If there is at least one intervening router in the
769 * current shortest path between the destination and the root, the
770 * destination simply inherits the set of next hops from the
771 * parent.
772 */
Paul Jakmab75ae992007-03-23 11:17:28 +0000773 if (IS_DEBUG_OSPF_EVENT)
774 zlog_debug ("%s: Intervening routers, adding parent(s)", __func__);
775
pauleb3da6d2005-10-18 04:20:33 +0000776 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000777 {
778 added = 1;
Paul Jakmabd34fb32007-02-26 17:14:48 +0000779 ospf_spf_add_parent (v, w, vp->nexthop, distance);
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000780 }
Paul Jakma9c27ef92006-05-04 07:32:57 +0000781
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000782 return added;
paul718e3742002-12-13 20:15:29 +0000783}
784
gdt630e4802004-08-31 17:28:41 +0000785/* RFC2328 Section 16.1 (2).
786 * v is on the SPF tree. Examine the links in v's LSA. Update the list
787 * of candidates with any vertices not already on the list. If a lower-cost
788 * path is found to a vertex already on the candidate list, store the new cost.
789 */
paul4dadc292005-05-06 21:37:42 +0000790static void
paul718e3742002-12-13 20:15:29 +0000791ospf_spf_next (struct vertex *v, struct ospf_area *area,
hasso462f20d2005-02-23 11:29:02 +0000792 struct pqueue * candidate)
paul718e3742002-12-13 20:15:29 +0000793{
794 struct ospf_lsa *w_lsa = NULL;
paul718e3742002-12-13 20:15:29 +0000795 u_char *p;
796 u_char *lim;
797 struct router_lsa_link *l = NULL;
798 struct in_addr *r;
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200799 int type = 0, lsa_pos=-1, lsa_pos_next=0;
paul718e3742002-12-13 20:15:29 +0000800
801 /* If this is a router-LSA, and bit V of the router-LSA (see Section
802 A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE. */
803 if (v->type == OSPF_VERTEX_ROUTER)
804 {
805 if (IS_ROUTER_LSA_VIRTUAL ((struct router_lsa *) v->lsa))
806 area->transit = OSPF_TRANSIT_TRUE;
807 }
Paul Jakmab75ae992007-03-23 11:17:28 +0000808
809 if (IS_DEBUG_OSPF_EVENT)
810 zlog_debug ("%s: Next vertex of %s vertex %s",
811 __func__,
812 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
813 inet_ntoa(v->lsa->id));
814
paul718e3742002-12-13 20:15:29 +0000815 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul0c0f9cd2003-06-06 23:27:04 +0000816 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
817
paul718e3742002-12-13 20:15:29 +0000818 while (p < lim)
819 {
pauleb3da6d2005-10-18 04:20:33 +0000820 struct vertex *w;
821 unsigned int distance;
pauld355bfa2004-04-08 07:43:45 +0000822
paul718e3742002-12-13 20:15:29 +0000823 /* In case of V is Router-LSA. */
824 if (v->lsa->type == OSPF_ROUTER_LSA)
825 {
826 l = (struct router_lsa_link *) p;
827
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200828 lsa_pos = lsa_pos_next; /* LSA link position */
829 lsa_pos_next++;
Denis Ovsienko05b77092011-08-23 11:36:27 +0400830 p += (OSPF_ROUTER_LSA_LINK_SIZE +
831 (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
paul718e3742002-12-13 20:15:29 +0000832
833 /* (a) If this is a link to a stub network, examine the next
834 link in V's LSA. Links to stub networks will be
835 considered in the second stage of the shortest path
836 calculation. */
837 if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB)
838 continue;
Paul Jakma08d3d5b2007-05-07 16:38:35 +0000839
840 /* Infinite distance links shouldn't be followed, except
841 * for local links (a stub-routed router still wants to
842 * calculate tree, so must follow its own links).
843 */
844 if ((v != area->spf) && l->m[0].metric >= OSPF_OUTPUT_COST_INFINITE)
845 continue;
paul718e3742002-12-13 20:15:29 +0000846
847 /* (b) Otherwise, W is a transit vertex (router or transit
848 network). Look up the vertex W's LSA (router-LSA or
849 network-LSA) in Area A's link state database. */
850 switch (type)
851 {
852 case LSA_LINK_TYPE_POINTOPOINT:
853 case LSA_LINK_TYPE_VIRTUALLINK:
854 if (type == LSA_LINK_TYPE_VIRTUALLINK)
paul0c0f9cd2003-06-06 23:27:04 +0000855 {
856 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000857 zlog_debug ("looking up LSA through VL: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000858 inet_ntoa (l->link_id));
859 }
paul718e3742002-12-13 20:15:29 +0000860
861 w_lsa = ospf_lsa_lookup (area, OSPF_ROUTER_LSA, l->link_id,
862 l->link_id);
863 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000864 {
865 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000866 zlog_debug ("found Router LSA %s", inet_ntoa (l->link_id));
paul0c0f9cd2003-06-06 23:27:04 +0000867 }
paul718e3742002-12-13 20:15:29 +0000868 break;
869 case LSA_LINK_TYPE_TRANSIT:
paul0c0f9cd2003-06-06 23:27:04 +0000870 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000871 zlog_debug ("Looking up Network LSA, ID: %s",
paul0c0f9cd2003-06-06 23:27:04 +0000872 inet_ntoa (l->link_id));
paul718e3742002-12-13 20:15:29 +0000873 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_NETWORK_LSA,
paul0c0f9cd2003-06-06 23:27:04 +0000874 l->link_id);
paul718e3742002-12-13 20:15:29 +0000875 if (w_lsa)
paul0c0f9cd2003-06-06 23:27:04 +0000876 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000877 zlog_debug ("found the LSA");
paul718e3742002-12-13 20:15:29 +0000878 break;
879 default:
paul0c0f9cd2003-06-06 23:27:04 +0000880 zlog_warn ("Invalid LSA link type %d", type);
paul718e3742002-12-13 20:15:29 +0000881 continue;
882 }
883 }
884 else
885 {
886 /* In case of V is Network-LSA. */
paul0c0f9cd2003-06-06 23:27:04 +0000887 r = (struct in_addr *) p;
paul718e3742002-12-13 20:15:29 +0000888 p += sizeof (struct in_addr);
889
890 /* Lookup the vertex W's LSA. */
891 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_ROUTER_LSA, *r);
Paul Jakmab75ae992007-03-23 11:17:28 +0000892 if (w_lsa)
893 {
894 if (IS_DEBUG_OSPF_EVENT)
895 zlog_debug ("found Router LSA %s", inet_ntoa (w_lsa->data->id));
896 }
paul718e3742002-12-13 20:15:29 +0000897 }
898
899 /* (b cont.) If the LSA does not exist, or its LS age is equal
900 to MaxAge, or it does not have a link back to vertex V,
901 examine the next link in V's LSA.[23] */
902 if (w_lsa == NULL)
Paul Jakmab75ae992007-03-23 11:17:28 +0000903 {
904 if (IS_DEBUG_OSPF_EVENT)
905 zlog_debug ("No LSA found");
906 continue;
907 }
paul718e3742002-12-13 20:15:29 +0000908
909 if (IS_LSA_MAXAGE (w_lsa))
Paul Jakmab75ae992007-03-23 11:17:28 +0000910 {
911 if (IS_DEBUG_OSPF_EVENT)
912 zlog_debug ("LSA is MaxAge");
913 continue;
914 }
paul718e3742002-12-13 20:15:29 +0000915
pauleb3da6d2005-10-18 04:20:33 +0000916 if (ospf_lsa_has_link (w_lsa->data, v->lsa) < 0 )
paul718e3742002-12-13 20:15:29 +0000917 {
paul0c0f9cd2003-06-06 23:27:04 +0000918 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000919 zlog_debug ("The LSA doesn't have a link back");
paul718e3742002-12-13 20:15:29 +0000920 continue;
921 }
922
923 /* (c) If vertex W is already on the shortest-path tree, examine
924 the next link in the LSA. */
hasso462f20d2005-02-23 11:29:02 +0000925 if (w_lsa->stat == LSA_SPF_IN_SPFTREE)
926 {
927 if (IS_DEBUG_OSPF_EVENT)
928 zlog_debug ("The LSA is already in SPF");
929 continue;
930 }
paul718e3742002-12-13 20:15:29 +0000931
932 /* (d) Calculate the link state cost D of the resulting path
933 from the root to vertex W. D is equal to the sum of the link
934 state cost of the (already calculated) shortest path to
935 vertex V and the advertised cost of the link between vertices
936 V and W. If D is: */
937
paul718e3742002-12-13 20:15:29 +0000938 /* calculate link cost D. */
939 if (v->lsa->type == OSPF_ROUTER_LSA)
pauleb3da6d2005-10-18 04:20:33 +0000940 distance = v->distance + ntohs (l->m[0].metric);
gdt630e4802004-08-31 17:28:41 +0000941 else /* v is not a Router-LSA */
pauleb3da6d2005-10-18 04:20:33 +0000942 distance = v->distance;
paul718e3742002-12-13 20:15:29 +0000943
944 /* Is there already vertex W in candidate list? */
hasso462f20d2005-02-23 11:29:02 +0000945 if (w_lsa->stat == LSA_SPF_NOT_EXPLORED)
946 {
pauleb3da6d2005-10-18 04:20:33 +0000947 /* prepare vertex W. */
948 w = ospf_vertex_new (w_lsa);
949
hasso462f20d2005-02-23 11:29:02 +0000950 /* Calculate nexthop to W. */
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200951 if (ospf_nexthop_calculation (area, v, w, l, distance, lsa_pos))
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000952 pqueue_enqueue (w, candidate);
Paul Jakmab75ae992007-03-23 11:17:28 +0000953 else if (IS_DEBUG_OSPF_EVENT)
954 zlog_debug ("Nexthop Calc failed");
hasso462f20d2005-02-23 11:29:02 +0000955 }
956 else if (w_lsa->stat >= 0)
957 {
958 /* Get the vertex from candidates. */
pauleb3da6d2005-10-18 04:20:33 +0000959 w = candidate->array[w_lsa->stat];
paul718e3742002-12-13 20:15:29 +0000960
hasso462f20d2005-02-23 11:29:02 +0000961 /* if D is greater than. */
pauleb3da6d2005-10-18 04:20:33 +0000962 if (w->distance < distance)
paul718e3742002-12-13 20:15:29 +0000963 {
paul718e3742002-12-13 20:15:29 +0000964 continue;
965 }
hasso462f20d2005-02-23 11:29:02 +0000966 /* equal to. */
pauleb3da6d2005-10-18 04:20:33 +0000967 else if (w->distance == distance)
paul718e3742002-12-13 20:15:29 +0000968 {
pauleb3da6d2005-10-18 04:20:33 +0000969 /* Found an equal-cost path to W.
970 * Calculate nexthop of to W from V. */
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200971 ospf_nexthop_calculation (area, v, w, l, distance, lsa_pos);
paul718e3742002-12-13 20:15:29 +0000972 }
hasso462f20d2005-02-23 11:29:02 +0000973 /* less than. */
974 else
paul718e3742002-12-13 20:15:29 +0000975 {
Paul Jakmabc20c1a2007-01-24 14:51:51 +0000976 /* Found a lower-cost path to W.
977 * nexthop_calculation is conditional, if it finds
978 * valid nexthop it will call spf_add_parents, which
979 * will flush the old parents
980 */
Joakim Tjernlundc81ee5c2012-07-07 17:06:11 +0200981 if (ospf_nexthop_calculation (area, v, w, l, distance, lsa_pos))
Paul Jakma7591d8b2007-08-06 18:52:45 +0000982 /* Decrease the key of the node in the heap.
983 * trickle-sort it up towards root, just in case this
984 * node should now be the new root due the cost change.
Paul Jakmae95537f2007-08-07 16:22:05 +0000985 * (next pqueu_{de,en}queue will fully re-heap the queue).
Paul Jakma7591d8b2007-08-06 18:52:45 +0000986 */
987 trickle_up (w_lsa->stat, candidate);
paul718e3742002-12-13 20:15:29 +0000988 }
gdt630e4802004-08-31 17:28:41 +0000989 } /* end W is already on the candidate list */
990 } /* end loop over the links in V's LSA */
paul718e3742002-12-13 20:15:29 +0000991}
992
paul4dadc292005-05-06 21:37:42 +0000993static void
paul718e3742002-12-13 20:15:29 +0000994ospf_spf_dump (struct vertex *v, int i)
995{
hasso52dc7ee2004-09-23 19:18:23 +0000996 struct listnode *cnode;
997 struct listnode *nnode;
pauleb3da6d2005-10-18 04:20:33 +0000998 struct vertex_parent *parent;
paul718e3742002-12-13 20:15:29 +0000999
1000 if (v->type == OSPF_VERTEX_ROUTER)
1001 {
1002 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001003 zlog_debug ("SPF Result: %d [R] %s", i, inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +00001004 }
1005 else
1006 {
1007 struct network_lsa *lsa = (struct network_lsa *) v->lsa;
1008 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001009 zlog_debug ("SPF Result: %d [N] %s/%d", i, inet_ntoa (v->lsa->id),
paul0c0f9cd2003-06-06 23:27:04 +00001010 ip_masklen (lsa->mask));
gdt630e4802004-08-31 17:28:41 +00001011 }
paul718e3742002-12-13 20:15:29 +00001012
paul1eb8ef22005-04-07 07:30:20 +00001013 if (IS_DEBUG_OSPF_EVENT)
pauleb3da6d2005-10-18 04:20:33 +00001014 for (ALL_LIST_ELEMENTS_RO (v->parents, nnode, parent))
1015 {
1016 zlog_debug (" nexthop %p %s %s",
1017 parent->nexthop,
1018 inet_ntoa (parent->nexthop->router),
1019 parent->nexthop->oi ? IF_NAME(parent->nexthop->oi)
1020 : "NULL");
1021 }
paul718e3742002-12-13 20:15:29 +00001022
1023 i++;
1024
pauleb3da6d2005-10-18 04:20:33 +00001025 for (ALL_LIST_ELEMENTS_RO (v->children, cnode, v))
paul1eb8ef22005-04-07 07:30:20 +00001026 ospf_spf_dump (v, i);
paul718e3742002-12-13 20:15:29 +00001027}
1028
1029/* Second stage of SPF calculation. */
paul4dadc292005-05-06 21:37:42 +00001030static void
paul0c0f9cd2003-06-06 23:27:04 +00001031ospf_spf_process_stubs (struct ospf_area *area, struct vertex *v,
Paul Jakmab3bc68e2008-09-04 13:52:07 +01001032 struct route_table *rt,
1033 int parent_is_root)
paul718e3742002-12-13 20:15:29 +00001034{
paul1eb8ef22005-04-07 07:30:20 +00001035 struct listnode *cnode, *cnnode;
paul718e3742002-12-13 20:15:29 +00001036 struct vertex *child;
1037
1038 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001039 zlog_debug ("ospf_process_stub():processing stubs for area %s",
paul0c0f9cd2003-06-06 23:27:04 +00001040 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001041 if (v->type == OSPF_VERTEX_ROUTER)
1042 {
1043 u_char *p;
1044 u_char *lim;
1045 struct router_lsa_link *l;
1046 struct router_lsa *rlsa;
Joakim Tjernlund57c639f2012-07-07 17:06:12 +02001047 int lsa_pos = 0;
paul718e3742002-12-13 20:15:29 +00001048
paul0c0f9cd2003-06-06 23:27:04 +00001049 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001050 zlog_debug ("ospf_process_stubs():processing router LSA, id: %s",
paul0c0f9cd2003-06-06 23:27:04 +00001051 inet_ntoa (v->lsa->id));
paul718e3742002-12-13 20:15:29 +00001052 rlsa = (struct router_lsa *) v->lsa;
1053
1054
paul0c0f9cd2003-06-06 23:27:04 +00001055 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001056 zlog_debug ("ospf_process_stubs(): we have %d links to process",
paul0c0f9cd2003-06-06 23:27:04 +00001057 ntohs (rlsa->links));
gdt630e4802004-08-31 17:28:41 +00001058 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
paul718e3742002-12-13 20:15:29 +00001059 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
1060
1061 while (p < lim)
1062 {
1063 l = (struct router_lsa_link *) p;
1064
Denis Ovsienko05b77092011-08-23 11:36:27 +04001065 p += (OSPF_ROUTER_LSA_LINK_SIZE +
1066 (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
paul718e3742002-12-13 20:15:29 +00001067
1068 if (l->m[0].type == LSA_LINK_TYPE_STUB)
Joakim Tjernlund57c639f2012-07-07 17:06:12 +02001069 ospf_intra_add_stub (rt, l, v, area, parent_is_root, lsa_pos);
1070 lsa_pos++;
paul718e3742002-12-13 20:15:29 +00001071 }
1072 }
1073
gdt630e4802004-08-31 17:28:41 +00001074 ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1, 1);
paul718e3742002-12-13 20:15:29 +00001075
pauleb3da6d2005-10-18 04:20:33 +00001076 for (ALL_LIST_ELEMENTS (v->children, cnode, cnnode, child))
paul718e3742002-12-13 20:15:29 +00001077 {
paul718e3742002-12-13 20:15:29 +00001078 if (CHECK_FLAG (child->flags, OSPF_VERTEX_PROCESSED))
paul0c0f9cd2003-06-06 23:27:04 +00001079 continue;
Paul Jakmab3bc68e2008-09-04 13:52:07 +01001080
1081 /* the first level of routers connected to the root
1082 * should have 'parent_is_root' set, including those
1083 * connected via a network vertex.
1084 */
1085 if (area->spf == v)
1086 parent_is_root = 1;
1087 else if (v->type == OSPF_VERTEX_ROUTER)
1088 parent_is_root = 0;
1089
1090 ospf_spf_process_stubs (area, child, rt, parent_is_root);
paul718e3742002-12-13 20:15:29 +00001091
1092 SET_FLAG (child->flags, OSPF_VERTEX_PROCESSED);
1093 }
1094}
1095
1096void
1097ospf_rtrs_free (struct route_table *rtrs)
1098{
1099 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001100 struct list *or_list;
paul1eb8ef22005-04-07 07:30:20 +00001101 struct ospf_route *or;
1102 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001103
1104 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001105 zlog_debug ("Route: Router Routing Table free");
paul718e3742002-12-13 20:15:29 +00001106
1107 for (rn = route_top (rtrs); rn; rn = route_next (rn))
1108 if ((or_list = rn->info) != NULL)
1109 {
paul1eb8ef22005-04-07 07:30:20 +00001110 for (ALL_LIST_ELEMENTS (or_list, node, nnode, or))
1111 ospf_route_free (or);
paul718e3742002-12-13 20:15:29 +00001112
paul0c0f9cd2003-06-06 23:27:04 +00001113 list_delete (or_list);
paul718e3742002-12-13 20:15:29 +00001114
paul0c0f9cd2003-06-06 23:27:04 +00001115 /* Unlock the node. */
1116 rn->info = NULL;
1117 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001118 }
1119 route_table_finish (rtrs);
1120}
1121
Stephen Hemminger075e12f2011-12-06 23:54:17 +04001122#if 0
paul4dadc292005-05-06 21:37:42 +00001123static void
paul718e3742002-12-13 20:15:29 +00001124ospf_rtrs_print (struct route_table *rtrs)
1125{
1126 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001127 struct list *or_list;
1128 struct listnode *ln;
1129 struct listnode *pnode;
paul718e3742002-12-13 20:15:29 +00001130 struct ospf_route *or;
1131 struct ospf_path *path;
1132 char buf1[BUFSIZ];
1133 char buf2[BUFSIZ];
1134
1135 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001136 zlog_debug ("ospf_rtrs_print() start");
paul718e3742002-12-13 20:15:29 +00001137
1138 for (rn = route_top (rtrs); rn; rn = route_next (rn))
1139 if ((or_list = rn->info) != NULL)
paul1eb8ef22005-04-07 07:30:20 +00001140 for (ALL_LIST_ELEMENTS_RO (or_list, ln, or))
paul718e3742002-12-13 20:15:29 +00001141 {
paul718e3742002-12-13 20:15:29 +00001142 switch (or->path_type)
1143 {
1144 case OSPF_PATH_INTRA_AREA:
paul0c0f9cd2003-06-06 23:27:04 +00001145 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001146 zlog_debug ("%s [%d] area: %s",
paul0c0f9cd2003-06-06 23:27:04 +00001147 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1148 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1149 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +00001150 break;
1151 case OSPF_PATH_INTER_AREA:
paul0c0f9cd2003-06-06 23:27:04 +00001152 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001153 zlog_debug ("%s IA [%d] area: %s",
paul0c0f9cd2003-06-06 23:27:04 +00001154 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1155 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1156 buf2, BUFSIZ));
paul718e3742002-12-13 20:15:29 +00001157 break;
1158 default:
1159 break;
1160 }
1161
paul1eb8ef22005-04-07 07:30:20 +00001162 for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path))
paul718e3742002-12-13 20:15:29 +00001163 {
paul718e3742002-12-13 20:15:29 +00001164 if (path->nexthop.s_addr == 0)
paul0c0f9cd2003-06-06 23:27:04 +00001165 {
1166 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001167 zlog_debug (" directly attached to %s\r\n",
Joakim Tjernlunda8ba8472009-07-27 12:42:34 +02001168 ifindex2ifname (path->ifindex));
paul0c0f9cd2003-06-06 23:27:04 +00001169 }
1170 else
1171 {
1172 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001173 zlog_debug (" via %s, %s\r\n",
Joakim Tjernlunda8ba8472009-07-27 12:42:34 +02001174 inet_ntoa (path->nexthop),
1175 ifindex2ifname (path->ifindex));
paul0c0f9cd2003-06-06 23:27:04 +00001176 }
paul718e3742002-12-13 20:15:29 +00001177 }
1178 }
1179
ajs2a42e282004-12-08 18:43:03 +00001180 zlog_debug ("ospf_rtrs_print() end");
paul718e3742002-12-13 20:15:29 +00001181}
Stephen Hemminger075e12f2011-12-06 23:54:17 +04001182#endif
paul718e3742002-12-13 20:15:29 +00001183
1184/* Calculating the shortest-path tree for an area. */
paul4dadc292005-05-06 21:37:42 +00001185static void
paul0c0f9cd2003-06-06 23:27:04 +00001186ospf_spf_calculate (struct ospf_area *area, struct route_table *new_table,
paul718e3742002-12-13 20:15:29 +00001187 struct route_table *new_rtrs)
1188{
hasso462f20d2005-02-23 11:29:02 +00001189 struct pqueue *candidate;
paul718e3742002-12-13 20:15:29 +00001190 struct vertex *v;
pauleb3da6d2005-10-18 04:20:33 +00001191
paul718e3742002-12-13 20:15:29 +00001192 if (IS_DEBUG_OSPF_EVENT)
1193 {
ajs2a42e282004-12-08 18:43:03 +00001194 zlog_debug ("ospf_spf_calculate: Start");
1195 zlog_debug ("ospf_spf_calculate: running Dijkstra for area %s",
paul0c0f9cd2003-06-06 23:27:04 +00001196 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001197 }
1198
1199 /* Check router-lsa-self. If self-router-lsa is not yet allocated,
1200 return this area's calculation. */
paul0c0f9cd2003-06-06 23:27:04 +00001201 if (!area->router_lsa_self)
paul718e3742002-12-13 20:15:29 +00001202 {
1203 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001204 zlog_debug ("ospf_spf_calculate: "
paul0c0f9cd2003-06-06 23:27:04 +00001205 "Skip area %s's calculation due to empty router_lsa_self",
1206 inet_ntoa (area->area_id));
paul718e3742002-12-13 20:15:29 +00001207 return;
1208 }
1209
1210 /* RFC2328 16.1. (1). */
paul0c0f9cd2003-06-06 23:27:04 +00001211 /* Initialize the algorithm's data structures. */
hasso462f20d2005-02-23 11:29:02 +00001212
1213 /* This function scans all the LSA database and set the stat field to
1214 * LSA_SPF_NOT_EXPLORED. */
1215 ospf_lsdb_clean_stat (area->lsdb);
1216 /* Create a new heap for the candidates. */
1217 candidate = pqueue_create();
1218 candidate->cmp = cmp;
1219 candidate->update = update_stat;
paul718e3742002-12-13 20:15:29 +00001220
1221 /* Initialize the shortest-path tree to only the root (which is the
1222 router doing the calculation). */
1223 ospf_spf_init (area);
1224 v = area->spf;
hasso462f20d2005-02-23 11:29:02 +00001225 /* Set LSA position to LSA_SPF_IN_SPFTREE. This vertex is the root of the
1226 * spanning tree. */
1227 *(v->stat) = LSA_SPF_IN_SPFTREE;
paul718e3742002-12-13 20:15:29 +00001228
1229 /* Set Area A's TransitCapability to FALSE. */
1230 area->transit = OSPF_TRANSIT_FALSE;
1231 area->shortcut_capability = 1;
pauleb3da6d2005-10-18 04:20:33 +00001232
paul718e3742002-12-13 20:15:29 +00001233 for (;;)
1234 {
1235 /* RFC2328 16.1. (2). */
hasso462f20d2005-02-23 11:29:02 +00001236 ospf_spf_next (v, area, candidate);
paul718e3742002-12-13 20:15:29 +00001237
1238 /* RFC2328 16.1. (3). */
1239 /* If at this step the candidate list is empty, the shortest-
1240 path tree (of transit vertices) has been completely built and
1241 this stage of the procedure terminates. */
hasso462f20d2005-02-23 11:29:02 +00001242 if (candidate->size == 0)
paul718e3742002-12-13 20:15:29 +00001243 break;
1244
1245 /* Otherwise, choose the vertex belonging to the candidate list
1246 that is closest to the root, and add it to the shortest-path
1247 tree (removing it from the candidate list in the
paul0c0f9cd2003-06-06 23:27:04 +00001248 process). */
hasso462f20d2005-02-23 11:29:02 +00001249 /* Extract from the candidates the node with the lower key. */
1250 v = (struct vertex *) pqueue_dequeue (candidate);
1251 /* Update stat field in vertex. */
1252 *(v->stat) = LSA_SPF_IN_SPFTREE;
pauleb3da6d2005-10-18 04:20:33 +00001253
paul718e3742002-12-13 20:15:29 +00001254 ospf_vertex_add_parent (v);
1255
paul718e3742002-12-13 20:15:29 +00001256 /* RFC2328 16.1. (4). */
1257 if (v->type == OSPF_VERTEX_ROUTER)
1258 ospf_intra_add_router (new_rtrs, v, area);
paul0c0f9cd2003-06-06 23:27:04 +00001259 else
paul718e3742002-12-13 20:15:29 +00001260 ospf_intra_add_transit (new_table, v, area);
1261
1262 /* RFC2328 16.1. (5). */
1263 /* Iterate the algorithm by returning to Step 2. */
gdt630e4802004-08-31 17:28:41 +00001264
1265 } /* end loop until no more candidate vertices */
paul718e3742002-12-13 20:15:29 +00001266
1267 if (IS_DEBUG_OSPF_EVENT)
1268 {
1269 ospf_spf_dump (area->spf, 0);
1270 ospf_route_table_dump (new_table);
1271 }
1272
1273 /* Second stage of SPF calculation procedure's */
Paul Jakmab3bc68e2008-09-04 13:52:07 +01001274 ospf_spf_process_stubs (area, area->spf, new_table, 0);
paul718e3742002-12-13 20:15:29 +00001275
pauleb3da6d2005-10-18 04:20:33 +00001276 /* Free candidate queue. */
hasso462f20d2005-02-23 11:29:02 +00001277 pqueue_delete (candidate);
Dinesh G Dutt50f38b32014-09-30 12:53:28 -07001278
pauleb3da6d2005-10-18 04:20:33 +00001279 ospf_vertex_dump (__func__, area->spf, 0, 1);
1280 /* Free nexthop information, canonical versions of which are attached
1281 * the first level of router vertices attached to the root vertex, see
1282 * ospf_nexthop_calculation.
1283 */
1284 ospf_canonical_nexthops_free (area->spf);
Dinesh G Dutt50f38b32014-09-30 12:53:28 -07001285
paul718e3742002-12-13 20:15:29 +00001286 /* Increment SPF Calculation Counter. */
1287 area->spf_calculation++;
1288
Paul Jakma2518efd2006-08-27 06:49:29 +00001289 quagga_gettime (QUAGGA_CLK_MONOTONIC, &area->ospf->ts_spf);
Dinesh G Dutt50f38b32014-09-30 12:53:28 -07001290 area->ts_spf = area->ospf->ts_spf;
paul718e3742002-12-13 20:15:29 +00001291
1292 if (IS_DEBUG_OSPF_EVENT)
Paul Jakma9c27ef92006-05-04 07:32:57 +00001293 zlog_debug ("ospf_spf_calculate: Stop. %ld vertices",
1294 mtype_stats_alloc(MTYPE_OSPF_VERTEX));
Dinesh G Dutt50f38b32014-09-30 12:53:28 -07001295
1296 /* Free SPF vertices, but not the list. List has ospf_vertex_free
1297 * as deconstructor.
1298 */
1299 list_delete_all_node (&vertex_list);
paul718e3742002-12-13 20:15:29 +00001300}
David Lamparter6b0655a2014-06-04 06:53:35 +02001301
paul718e3742002-12-13 20:15:29 +00001302/* Timer for SPF calculation. */
paul4dadc292005-05-06 21:37:42 +00001303static int
paul68980082003-03-25 05:07:42 +00001304ospf_spf_calculate_timer (struct thread *thread)
paul718e3742002-12-13 20:15:29 +00001305{
paul68980082003-03-25 05:07:42 +00001306 struct ospf *ospf = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +00001307 struct route_table *new_table, *new_rtrs;
paul1eb8ef22005-04-07 07:30:20 +00001308 struct ospf_area *area;
1309 struct listnode *node, *nnode;
Dinesh G Dutt50f38b32014-09-30 12:53:28 -07001310 struct timeval start_time, stop_time, spf_start_time;
1311 int areas_processed = 0;
1312 unsigned long ia_time, prune_time, rt_time;
1313 unsigned long abr_time, total_spf_time, spf_time;
1314 char rbuf[32]; /* reason_buf */
Paul Jakmab6eef002014-10-09 14:19:51 +01001315
paul718e3742002-12-13 20:15:29 +00001316 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001317 zlog_debug ("SPF: Timer (SPF calculation expire)");
paul0c0f9cd2003-06-06 23:27:04 +00001318
paul718e3742002-12-13 20:15:29 +00001319 ospf->t_spf_calc = NULL;
1320
Dinesh G Dutt50f38b32014-09-30 12:53:28 -07001321 quagga_gettime (QUAGGA_CLK_MONOTONIC, &spf_start_time);
paul718e3742002-12-13 20:15:29 +00001322 /* Allocate new table tree. */
1323 new_table = route_table_init ();
paul0c0f9cd2003-06-06 23:27:04 +00001324 new_rtrs = route_table_init ();
paul718e3742002-12-13 20:15:29 +00001325
paul68980082003-03-25 05:07:42 +00001326 ospf_vl_unapprove (ospf);
paul718e3742002-12-13 20:15:29 +00001327
1328 /* Calculate SPF for each area. */
paul1eb8ef22005-04-07 07:30:20 +00001329 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
Paul Jakma9c27ef92006-05-04 07:32:57 +00001330 {
1331 /* Do backbone last, so as to first discover intra-area paths
1332 * for any back-bone virtual-links
1333 */
1334 if (ospf->backbone && ospf->backbone == area)
1335 continue;
Dinesh G Dutt50f38b32014-09-30 12:53:28 -07001336
Paul Jakma9c27ef92006-05-04 07:32:57 +00001337 ospf_spf_calculate (area, new_table, new_rtrs);
Dinesh G Dutt50f38b32014-09-30 12:53:28 -07001338 areas_processed++;
Paul Jakma9c27ef92006-05-04 07:32:57 +00001339 }
Dinesh G Dutt50f38b32014-09-30 12:53:28 -07001340
Paul Jakma9c27ef92006-05-04 07:32:57 +00001341 /* SPF for backbone, if required */
1342 if (ospf->backbone)
Dinesh G Dutt50f38b32014-09-30 12:53:28 -07001343 {
1344 ospf_spf_calculate (ospf->backbone, new_table, new_rtrs);
1345 areas_processed++;
1346 }
1347
1348 quagga_gettime (QUAGGA_CLK_MONOTONIC, &stop_time);
1349 spf_time = timeval_elapsed (stop_time, spf_start_time);
1350
paul68980082003-03-25 05:07:42 +00001351 ospf_vl_shut_unapproved (ospf);
paul718e3742002-12-13 20:15:29 +00001352
Dinesh G Dutt50f38b32014-09-30 12:53:28 -07001353 start_time = stop_time; /* saving a call */
1354
paul68980082003-03-25 05:07:42 +00001355 ospf_ia_routing (ospf, new_table, new_rtrs);
paul718e3742002-12-13 20:15:29 +00001356
Dinesh G Dutt50f38b32014-09-30 12:53:28 -07001357 quagga_gettime (QUAGGA_CLK_MONOTONIC, &stop_time);
1358 ia_time = timeval_elapsed (stop_time, start_time);
1359
1360 quagga_gettime (QUAGGA_CLK_MONOTONIC, &start_time);
paul718e3742002-12-13 20:15:29 +00001361 ospf_prune_unreachable_networks (new_table);
1362 ospf_prune_unreachable_routers (new_rtrs);
1363
Dinesh G Dutt50f38b32014-09-30 12:53:28 -07001364 quagga_gettime (QUAGGA_CLK_MONOTONIC, &stop_time);
1365 prune_time = timeval_elapsed (stop_time, start_time);
paul718e3742002-12-13 20:15:29 +00001366 /* AS-external-LSA calculation should not be performed here. */
1367
1368 /* If new Router Route is installed,
1369 then schedule re-calculate External routes. */
1370 if (1)
paul68980082003-03-25 05:07:42 +00001371 ospf_ase_calculate_schedule (ospf);
paul718e3742002-12-13 20:15:29 +00001372
paul68980082003-03-25 05:07:42 +00001373 ospf_ase_calculate_timer_add (ospf);
paul718e3742002-12-13 20:15:29 +00001374
Dinesh G Dutt50f38b32014-09-30 12:53:28 -07001375 quagga_gettime (QUAGGA_CLK_MONOTONIC, &start_time);
1376
paul718e3742002-12-13 20:15:29 +00001377 /* Update routing table. */
paul68980082003-03-25 05:07:42 +00001378 ospf_route_install (ospf, new_table);
paul718e3742002-12-13 20:15:29 +00001379
Dinesh G Dutt50f38b32014-09-30 12:53:28 -07001380 quagga_gettime (QUAGGA_CLK_MONOTONIC, &stop_time);
1381 rt_time = timeval_elapsed (stop_time, start_time);
paul718e3742002-12-13 20:15:29 +00001382 /* Update ABR/ASBR routing table */
paul68980082003-03-25 05:07:42 +00001383 if (ospf->old_rtrs)
paul718e3742002-12-13 20:15:29 +00001384 {
1385 /* old_rtrs's node holds linked list of ospf_route. --kunihiro. */
paul68980082003-03-25 05:07:42 +00001386 /* ospf_route_delete (ospf->old_rtrs); */
1387 ospf_rtrs_free (ospf->old_rtrs);
paul718e3742002-12-13 20:15:29 +00001388 }
1389
paul68980082003-03-25 05:07:42 +00001390 ospf->old_rtrs = ospf->new_rtrs;
1391 ospf->new_rtrs = new_rtrs;
paul718e3742002-12-13 20:15:29 +00001392
Dinesh G Dutt50f38b32014-09-30 12:53:28 -07001393 quagga_gettime (QUAGGA_CLK_MONOTONIC, &start_time);
paul0c0f9cd2003-06-06 23:27:04 +00001394 if (IS_OSPF_ABR (ospf))
paul68980082003-03-25 05:07:42 +00001395 ospf_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001396
Dinesh G Dutt50f38b32014-09-30 12:53:28 -07001397 quagga_gettime (QUAGGA_CLK_MONOTONIC, &stop_time);
1398 abr_time = timeval_elapsed (stop_time, start_time);
1399
1400 quagga_gettime (QUAGGA_CLK_MONOTONIC, &stop_time);
1401 total_spf_time = timeval_elapsed (stop_time, spf_start_time);
1402 ospf->ts_spf_duration.tv_sec = total_spf_time/1000000;
1403 ospf->ts_spf_duration.tv_usec = total_spf_time % 1000000;
1404
1405 ospf_get_spf_reason_str (rbuf);
1406
Paul Jakmab6eef002014-10-09 14:19:51 +01001407 if (IS_DEBUG_OSPF_EVENT)
1408 {
1409 zlog_info ("SPF Processing Time(usecs): %ld", total_spf_time);
1410 zlog_info ("\t SPF Time: %ld", spf_time);
1411 zlog_info ("\t InterArea: %ld", ia_time);
1412 zlog_info ("\t Prune: %ld", prune_time);
1413 zlog_info ("\tRouteInstall: %ld", rt_time);
1414 if (IS_OSPF_ABR (ospf))
1415 zlog_info ("\t ABR: %ld (%d areas)",
1416 abr_time, areas_processed);
1417 zlog_info ("Reason(s) for SPF: %s", rbuf);
1418 }
Dinesh G Dutt50f38b32014-09-30 12:53:28 -07001419
1420 ospf_clear_spf_reason_flags ();
paul718e3742002-12-13 20:15:29 +00001421
1422 return 0;
1423}
1424
1425/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
1426 set timer for SPF calc. */
1427void
Paul Jakmab6eef002014-10-09 14:19:51 +01001428ospf_spf_calculate_schedule (struct ospf *ospf, ospf_spf_reason_t reason)
paul718e3742002-12-13 20:15:29 +00001429{
pauld24f6e22005-10-21 09:23:12 +00001430 unsigned long delay, elapsed, ht;
1431 struct timeval result;
paul718e3742002-12-13 20:15:29 +00001432
1433 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001434 zlog_debug ("SPF: calculation timer scheduled");
paul718e3742002-12-13 20:15:29 +00001435
1436 /* OSPF instance does not exist. */
paul68980082003-03-25 05:07:42 +00001437 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001438 return;
pauld24f6e22005-10-21 09:23:12 +00001439
Paul Jakmab6eef002014-10-09 14:19:51 +01001440 ospf_spf_set_reason (reason);
1441
paul718e3742002-12-13 20:15:29 +00001442 /* SPF calculation timer is already scheduled. */
paul68980082003-03-25 05:07:42 +00001443 if (ospf->t_spf_calc)
paul718e3742002-12-13 20:15:29 +00001444 {
1445 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001446 zlog_debug ("SPF: calculation timer is already scheduled: %p",
paul0c0f9cd2003-06-06 23:27:04 +00001447 ospf->t_spf_calc);
paul718e3742002-12-13 20:15:29 +00001448 return;
1449 }
pauld24f6e22005-10-21 09:23:12 +00001450
1451 /* XXX Monotic timers: we only care about relative time here. */
Paul Jakma2518efd2006-08-27 06:49:29 +00001452 result = tv_sub (recent_relative_time (), ospf->ts_spf);
pauld24f6e22005-10-21 09:23:12 +00001453
1454 elapsed = (result.tv_sec * 1000) + (result.tv_usec / 1000);
1455 ht = ospf->spf_holdtime * ospf->spf_hold_multiplier;
1456
1457 if (ht > ospf->spf_max_holdtime)
1458 ht = ospf->spf_max_holdtime;
1459
paul718e3742002-12-13 20:15:29 +00001460 /* Get SPF calculation delay time. */
pauld24f6e22005-10-21 09:23:12 +00001461 if (elapsed < ht)
paul718e3742002-12-13 20:15:29 +00001462 {
pauld24f6e22005-10-21 09:23:12 +00001463 /* Got an event within the hold time of last SPF. We need to
1464 * increase the hold_multiplier, if it's not already at/past
1465 * maximum value, and wasn't already increased..
1466 */
1467 if (ht < ospf->spf_max_holdtime)
1468 ospf->spf_hold_multiplier++;
1469
1470 /* always honour the SPF initial delay */
1471 if ( (ht - elapsed) < ospf->spf_delay)
paul0c0f9cd2003-06-06 23:27:04 +00001472 delay = ospf->spf_delay;
paul718e3742002-12-13 20:15:29 +00001473 else
pauld24f6e22005-10-21 09:23:12 +00001474 delay = ht - elapsed;
paul718e3742002-12-13 20:15:29 +00001475 }
1476 else
pauld24f6e22005-10-21 09:23:12 +00001477 {
1478 /* Event is past required hold-time of last SPF */
1479 delay = ospf->spf_delay;
1480 ospf->spf_hold_multiplier = 1;
1481 }
1482
paul718e3742002-12-13 20:15:29 +00001483 if (IS_DEBUG_OSPF_EVENT)
pauld24f6e22005-10-21 09:23:12 +00001484 zlog_debug ("SPF: calculation timer delay = %ld", delay);
1485
Dinesh G Dutt50f38b32014-09-30 12:53:28 -07001486 zlog_info ("SPF: Scheduled in %ld msec", delay);
1487
paul68980082003-03-25 05:07:42 +00001488 ospf->t_spf_calc =
pauld24f6e22005-10-21 09:23:12 +00001489 thread_add_timer_msec (master, ospf_spf_calculate_timer, ospf, delay);
paul718e3742002-12-13 20:15:29 +00001490}