]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_spf.c
*: add missing includes
[mirror_frr.git] / ospfd / ospf_spf.c
CommitLineData
718e3744 1/* 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 () */
462f20d5 32#include "pqueue.h"
718e3744 33
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
cf744958
DS
49/* Variables to ensure a SPF scheduled log message is printed only once */
50
51static unsigned int spf_reason_flags = 0;
52
d3a9c768
PJ
53static void
54ospf_clear_spf_reason_flags (void)
cf744958
DS
55{
56 spf_reason_flags = 0;
57}
58
d3a9c768
PJ
59static void
60ospf_spf_set_reason (ospf_spf_reason_t reason)
cf744958 61{
d3a9c768 62 spf_reason_flags |= 1 << reason;
cf744958
DS
63}
64
65static void
66ospf_get_spf_reason_str (char *buf)
67{
d3a9c768
PJ
68 if (!buf)
69 return;
70
71 buf[0] = '\0';
72 if (spf_reason_flags)
cf744958 73 {
d3a9c768
PJ
74 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, ");
cf744958
DS
88 buf[strlen(buf)-2] = '\0'; /* skip the last ", " */
89 }
90}
91
9c27ef9b
PJ
92static 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 };
6b0655a2 98
462f20d5 99/* 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 )
9c27ef9b
PJ
107 {
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;
462f20d5 126}
127
128static void
eb3da6df 129update_stat (void *node , int position)
462f20d5 130{
eb3da6df 131 struct vertex *v = node;
132
462f20d5 133 /* Set the status of the vertex, when its position changes. */
134 *(v->stat) = position;
135}
6b0655a2 136
4dadc291 137static struct vertex_nexthop *
eb3da6df 138vertex_nexthop_new (void)
718e3744 139{
eb3da6df 140 return XCALLOC (MTYPE_OSPF_NEXTHOP, sizeof (struct vertex_nexthop));
718e3744 141}
142
4dadc291 143static void
718e3744 144vertex_nexthop_free (struct vertex_nexthop *nh)
145{
146 XFREE (MTYPE_OSPF_NEXTHOP, nh);
147}
148
eb3da6df 149/* Free the canonical nexthop objects for an area, ie the nexthop objects
9c27ef9b
PJ
150 * attached to the first-hop router vertices, and any intervening network
151 * vertices.
eb3da6df 152 */
153static void
154ospf_canonical_nexthops_free (struct vertex *root)
718e3744 155{
eb3da6df 156 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
58e1befe 164 /* 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 */
eb3da6df 171 if (child->type == OSPF_VERTEX_NETWORK)
172 ospf_canonical_nexthops_free (child);
173
58e1befe 174 /* Free child nexthops pointing back to this root vertex */
eb3da6df 175 for (ALL_LIST_ELEMENTS (child->parents, n2, nn2, vp))
9c27ef9b 176 if (vp->parent == root && vp->nexthop)
58e1befe 177 vertex_nexthop_free (vp->nexthop);
eb3da6df 178 }
179}
6b0655a2 180
9c27ef9b
PJ
181/* TODO: Parent list should be excised, in favour of maintaining only
182 * vertex_nexthop, with refcounts.
183 */
eb3da6df 184static 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;
718e3744 197 return new;
198}
0c0f9cd5 199
eb3da6df 200static void
9c27ef9b 201vertex_parent_free (void *p)
eb3da6df 202{
203 XFREE (MTYPE_OSPF_VERTEX_PARENT, p);
204}
6b0655a2 205
4dadc291 206static struct vertex *
718e3744 207ospf_vertex_new (struct ospf_lsa *lsa)
208{
209 struct vertex *new;
210
eb3da6df 211 new = XCALLOC (MTYPE_OSPF_VERTEX, sizeof (struct vertex));
718e3744 212
213 new->flags = 0;
462f20d5 214 new->stat = &(lsa->stat);
718e3744 215 new->type = lsa->data->type;
216 new->id = lsa->data->id;
217 new->lsa = lsa->data;
eb3da6df 218 new->children = list_new ();
219 new->parents = list_new ();
9c27ef9b
PJ
220 new->parents->del = vertex_parent_free;
221
222 listnode_add (&vertex_list, new);
eb3da6df 223
9c27ef9b
PJ
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));
718e3744 228 return new;
229}
230
4dadc291 231static void
9c27ef9b 232ospf_vertex_free (void *data)
718e3744 233{
9c27ef9b 234 struct vertex *v = data;
eb3da6df 235
9c27ef9b
PJ
236 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));
7461d459 240
9c27ef9b
PJ
241 /* 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
eb3da6df 244 */
9c27ef9b 245 //assert (listcount (v->parents) == 0);
eb3da6df 246
9c27ef9b
PJ
247 if (v->children)
248 list_delete (v->children);
249 v->children = NULL;
250
251 if (v->parents)
252 list_delete (v->parents);
eb3da6df 253 v->parents = NULL;
254
255 v->lsa = NULL;
7461d459 256
718e3744 257 XFREE (MTYPE_OSPF_VERTEX, v);
258}
259
4dadc291 260static void
eb1ce605 261ospf_vertex_dump(const char *msg, struct vertex *v,
eb3da6df 262 int print_parents, int print_children)
630e4807 263{
264 if ( ! IS_DEBUG_OSPF_EVENT)
265 return;
266
eb3da6df 267 zlog_debug("%s %s vertex %s distance %u flags %u",
630e4807 268 msg,
269 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
270 inet_ntoa(v->lsa->id),
271 v->distance,
630e4807 272 (unsigned int)v->flags);
273
eb3da6df 274 if (print_parents)
630e4807 275 {
1eb8ef25 276 struct listnode *node;
eb3da6df 277 struct vertex_parent *vp;
1eb8ef25 278
eb3da6df 279 for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
630e4807 280 {
281 char buf1[BUFSIZ];
eb3da6df 282
283 if (vp)
630e4807 284 {
eb3da6df 285 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");
630e4807 289 }
290 }
291 }
292
293 if (print_children)
294 {
52dc7ee6 295 struct listnode *cnode;
1eb8ef25 296 struct vertex *cv;
297
eb3da6df 298 for (ALL_LIST_ELEMENTS_RO (v->children, cnode, cv))
1eb8ef25 299 ospf_vertex_dump(" child:", cv, 0, 0);
630e4807 300 }
301}
302
303
304/* Add a vertex to the list of children in each of its parents. */
4dadc291 305static void
718e3744 306ospf_vertex_add_parent (struct vertex *v)
307{
eb3da6df 308 struct vertex_parent *vp;
52dc7ee6 309 struct listnode *node;
7461d459 310
9c27ef9b 311 assert (v && v->parents);
7461d459 312
eb3da6df 313 for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
718e3744 314 {
eb3da6df 315 assert (vp->parent && vp->parent->children);
7461d459 316
718e3744 317 /* No need to add two links from the same parent. */
eb3da6df 318 if (listnode_lookup (vp->parent->children, v) == NULL)
319 listnode_add (vp->parent->children, v);
718e3744 320 }
321}
6b0655a2 322
4dadc291 323static void
718e3744 324ospf_spf_init (struct ospf_area *area)
325{
326 struct vertex *v;
9c27ef9b 327
718e3744 328 /* Create root node. */
329 v = ospf_vertex_new (area->router_lsa_self);
bd34fb34 330
718e3744 331 area->spf = v;
332
333 /* Reset ABR and ASBR router counts. */
334 area->abr_count = 0;
335 area->asbr_count = 0;
336}
337
d355bfa7 338/* return index of link back to V from W, or -1 if no link found */
4dadc291 339static int
718e3744 340ospf_lsa_has_link (struct lsa_header *w, struct lsa_header *v)
341{
eb1ce605 342 unsigned int i, length;
718e3744 343 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)
d355bfa7 350 return -1;
718e3744 351
352 nl = (struct network_lsa *) w;
353 length = (ntohs (w->length) - OSPF_LSA_HEADER_SIZE - 4) / 4;
0c0f9cd5 354
718e3744 355 for (i = 0; i < length; i++)
356 if (IPV4_ADDR_SAME (&nl->routers[i], &v->id))
d355bfa7 357 return i;
358 return -1;
718e3744 359 }
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;
0c0f9cd5 369 i < ntohs (rl->links) && length >= sizeof (struct router_lsa);
370 i++, length -= 12)
718e3744 371 {
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 {
d355bfa7 380 return i;
718e3744 381 }
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 {
d355bfa7 388 return i;
0c0f9cd5 389 }
718e3744 390 break;
391 case LSA_LINK_TYPE_STUB:
eb3da6df 392 /* Stub can't lead anywhere, carry on */
718e3744 393 continue;
394 default:
395 break;
396 }
397 }
398 }
d355bfa7 399 return -1;
718e3744 400}
401
630e4807 402/* 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 */
4dadc291 406static struct router_lsa_link *
718e3744 407ospf_get_next_link (struct vertex *v, struct vertex *w,
0c0f9cd5 408 struct router_lsa_link *prev_link)
718e3744 409{
410 u_char *p;
411 u_char *lim;
bd540377 412 u_char lsa_type = LSA_LINK_TYPE_TRANSIT;
718e3744 413 struct router_lsa_link *l;
414
bd540377
JT
415 if (w->type == OSPF_VERTEX_ROUTER)
416 lsa_type = LSA_LINK_TYPE_POINTOPOINT;
417
718e3744 418 if (prev_link == NULL)
630e4807 419 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
718e3744 420 else
421 {
0c0f9cd5 422 p = (u_char *) prev_link;
05b7709d
DO
423 p += (OSPF_ROUTER_LSA_LINK_SIZE +
424 (prev_link->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
718e3744 425 }
0c0f9cd5 426
718e3744 427 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
428
429 while (p < lim)
430 {
431 l = (struct router_lsa_link *) p;
432
05b7709d 433 p += (OSPF_ROUTER_LSA_LINK_SIZE + (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
718e3744 434
bd540377 435 if (l->m[0].type != lsa_type)
0c0f9cd5 436 continue;
718e3744 437
438 if (IPV4_ADDR_SAME (&l->link_id, &w->id))
0c0f9cd5 439 return l;
718e3744 440 }
441
442 return NULL;
443}
444
bc20c1a4
PJ
445static 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
75ee0b8e 459/*
460 * Consider supplied next-hop for inclusion to the supplied list of
461 * equal-cost next-hops, adjust list as neccessary.
bf9392c6 462 */
4dadc291 463static void
eb3da6df 464ospf_spf_add_parent (struct vertex *v, struct vertex *w,
bc20c1a4 465 struct vertex_nexthop *newhop,
bd34fb34 466 unsigned int distance)
bf9392c6 467{
7b92589c
DL
468 struct vertex_parent *vp, *wp;
469 struct listnode *node;
eb3da6df 470
08d3d5b3 471 /* we must have a newhop, and a distance */
bd34fb34 472 assert (v && w && newhop);
08d3d5b3 473 assert (distance);
eb3da6df 474
08d3d5b3
PJ
475 /* 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)).
bc20c1a4 478 */
08d3d5b3
PJ
479 if (w->distance)
480 assert (distance <= w->distance);
481 else
482 w->distance = distance;
bc20c1a4 483
b75ae99e
PJ
484 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
bc20c1a4 493 /* Adding parent for a new, better path: flush existing parents from W. */
bd34fb34 494 if (distance < w->distance)
bc20c1a4 495 {
b75ae99e
PJ
496 if (IS_DEBUG_OSPF_EVENT)
497 zlog_debug ("%s: distance %d better than %d, flushing existing parents",
498 __func__, distance, w->distance);
bc20c1a4 499 ospf_spf_flush_parents (w);
bd34fb34 500 w->distance = distance;
bc20c1a4
PJ
501 }
502
7b92589c
DL
503 /* 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
eb3da6df 516 vp = vertex_parent_new (v, ospf_lsa_has_link (w->lsa, v->lsa), newhop);
517 listnode_add (w->parents, vp);
0c0f9cd5 518
eb3da6df 519 return;
520}
521
630e4807 522/* 16.1.1. Calculate nexthop from root through V (parent) to
bd34fb34 523 * vertex W (destination), with given distance from root->W.
eb3da6df 524 *
525 * The link must be supplied if V is the root vertex. In all other cases
526 * it may be NULL.
bd34fb34
PJ
527 *
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.
630e4807 532 */
bc20c1a4 533static unsigned int
eb3da6df 534ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v,
bd34fb34 535 struct vertex *w, struct router_lsa_link *l,
c81ee5c9 536 unsigned int distance, int lsa_pos)
718e3744 537{
1eb8ef25 538 struct listnode *node, *nnode;
eb3da6df 539 struct vertex_nexthop *nh;
540 struct vertex_parent *vp;
718e3744 541 struct ospf_interface *oi = NULL;
bc20c1a4 542 unsigned int added = 0;
c81ee5c9
JT
543 char buf1[BUFSIZ];
544 char buf2[BUFSIZ];
0c0f9cd5 545
718e3744 546 if (IS_DEBUG_OSPF_EVENT)
630e4807 547 {
2a42e285 548 zlog_debug ("ospf_nexthop_calculation(): Start");
630e4807 549 ospf_vertex_dump("V (parent):", v, 1, 1);
550 ospf_vertex_dump("W (dest) :", w, 1, 1);
bd34fb34 551 zlog_debug ("V->W distance: %d", distance);
630e4807 552 }
718e3744 553
718e3744 554 if (v == area->spf)
9c27ef9b 555 {
630e4807 556 /* 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
c81ee5c9
JT
563 /* 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
718e3744 584 if (w->type == OSPF_VERTEX_ROUTER)
0c0f9cd5 585 {
eb3da6df 586 /* 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;
eb3da6df 590
591 if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT)
592 {
c81ee5c9 593 struct in_addr nexthop;
ed2eb093 594 nexthop.s_addr = 0;
c81ee5c9 595
eb3da6df 596 /* If the destination is a router which connects to
597 the calculating router via a Point-to-MultiPoint
598 network, the destination's next hop IP address(es)
599 can be determined by examining the destination's
600 router-LSA: each link pointing back to the
601 calculating router and having a Link Data field
602 belonging to the Point-to-MultiPoint network
603 provides an IP address of the next hop router.
604
605 At this point l is a link from V to W, and V is the
c81ee5c9
JT
606 root ("us"). If it is a point-to-multipoint interface,
607 then look through the links in the opposite direction (W to V).
608 If any of them have an address that lands within the
eb3da6df 609 subnet declared by the PtMP link, then that link
c81ee5c9 610 is a constituent of the PtMP link, and its address is
eb3da6df 611 a nexthop address for V.
612 */
c81ee5c9
JT
613 if (oi->type == OSPF_IFTYPE_POINTOPOINT)
614 {
f2b53dac
CF
615 /* Having nexthop = 0 is tempting, but NOT acceptable.
616 It breaks AS-External routes with a forwarding address,
617 since ospf_ase_complete_direct_routes() will mistakenly
618 assume we've reached the last hop and should place the
619 forwarding address as nexthop.
620 Also, users may configure multi-access links in p2p mode,
621 so we need the IP to ARP the nexthop.
622 */
623 struct ospf_neighbor *nbr_w;
624
625 nbr_w = ospf_nbr_lookup_by_routerid (oi->nbrs, &l->link_id);
626 if (nbr_w != NULL)
627 {
628 added = 1;
629 nexthop = nbr_w->src;
630 }
c81ee5c9
JT
631 }
632 else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
633 {
634 struct prefix_ipv4 la;
635
636 la.family = AF_INET;
637 la.prefixlen = oi->address->prefixlen;
638
639 /* V links to W on PtMP interface
640 - find the interface address on W */
641 while ((l2 = ospf_get_next_link (w, v, l2)))
642 {
643 la.prefix = l2->link_data;
644
645 if (prefix_cmp ((struct prefix *) &la,
646 oi->address) != 0)
647 continue;
648 /* link_data is on our PtMP network */
649 added = 1;
650 nexthop = l2->link_data;
651 break;
652 }
653 }
654
655 if (added)
eb3da6df 656 {
657 /* found all necessary info to build nexthop */
658 nh = vertex_nexthop_new ();
659 nh->oi = oi;
c81ee5c9 660 nh->router = nexthop;
bd34fb34 661 ospf_spf_add_parent (v, w, nh, distance);
bc20c1a4 662 return 1;
eb3da6df 663 }
664 else
c81ee5c9
JT
665 zlog_info("%s: could not determine nexthop for link %s",
666 __func__, oi->ifp->name);
9c27ef9b
PJ
667 } /* end point-to-point link from V to W */
668 else if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK)
669 {
670 struct ospf_vl_data *vl_data;
671
672 /* VLink implementation limitations:
673 * a) vl_data can only reference one nexthop, so no ECMP
674 * to backbone through VLinks. Though transit-area
675 * summaries may be considered, and those can be ECMP.
676 * b) We can only use /one/ VLink, even if multiple ones
677 * exist this router through multiple transit-areas.
678 */
679 vl_data = ospf_vl_lookup (area->ospf, NULL, l->link_id);
680
681 if (vl_data
682 && CHECK_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED))
eb3da6df 683 {
9c27ef9b
PJ
684 nh = vertex_nexthop_new ();
685 nh->oi = vl_data->nexthop.oi;
686 nh->router = vl_data->nexthop.router;
bd34fb34 687 ospf_spf_add_parent (v, w, nh, distance);
bc20c1a4 688 return 1;
eb3da6df 689 }
9c27ef9b 690 else
bc20c1a4
PJ
691 zlog_info("ospf_nexthop_calculation(): "
692 "vl_data for VL link not found");
9c27ef9b 693 } /* end virtual-link from V to W */
bc20c1a4 694 return 0;
630e4807 695 } /* end W is a Router vertex */
718e3744 696 else
0c0f9cd5 697 {
eb3da6df 698 assert(w->type == OSPF_VERTEX_NETWORK);
c81ee5c9
JT
699
700 nh = vertex_nexthop_new ();
701 nh->oi = oi;
702 nh->router.s_addr = 0; /* Nexthop not required */
703 ospf_spf_add_parent (v, w, nh, distance);
704 return 1;
0c0f9cd5 705 }
630e4807 706 } /* end V is the root */
630e4807 707 /* Check if W's parent is a network connected to root. */
718e3744 708 else if (v->type == OSPF_VERTEX_NETWORK)
709 {
630e4807 710 /* See if any of V's parents are the root. */
eb3da6df 711 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
718e3744 712 {
eb3da6df 713 if (vp->parent == area->spf) /* connects to root? */
630e4807 714 {
715 /* 16.1.1 para 5. ...the parent vertex is a network that
716 * directly connects the calculating router to the destination
717 * router. The list of next hops is then determined by
718 * examining the destination's router-LSA...
719 */
720
721 assert(w->type == OSPF_VERTEX_ROUTER);
0c0f9cd5 722 while ((l = ospf_get_next_link (w, v, l)))
723 {
630e4807 724 /* ...For each link in the router-LSA that points back to the
725 * parent network, the link's Link Data field provides the IP
726 * address of a next hop router. The outgoing interface to
727 * use can then be derived from the next hop IP address (or
728 * it can be inherited from the parent network).
729 */
eb3da6df 730 nh = vertex_nexthop_new ();
731 nh->oi = vp->nexthop->oi;
732 nh->router = l->link_data;
bc20c1a4 733 added = 1;
bd34fb34 734 ospf_spf_add_parent (v, w, nh, distance);
0c0f9cd5 735 }
945ea293
PJ
736 /* Note lack of return is deliberate. See next comment. */
737 }
718e3744 738 }
945ea293
PJ
739 /* NB: This code is non-trivial.
740 *
741 * E.g. it is not enough to know that V connects to the root. It is
742 * also important that the while above, looping through all links from
743 * W->V found at least one link, so that we know there is
744 * bi-directional connectivity between V and W (which need not be the
745 * case, e.g. when OSPF has not yet converged fully). Otherwise, if
746 * we /always/ return here, without having checked that root->V->-W
747 * actually resulted in a valid nexthop being created, then we we will
748 * prevent SPF from finding/using higher cost paths.
749 *
750 * It is important, if root->V->W has not been added, that we continue
751 * through to the intervening-router nexthop code below. So as to
752 * ensure other paths to V may be used. This avoids unnecessary
753 * blackholes while OSPF is convergening.
754 *
755 * I.e. we may have arrived at this function, examining V -> W, via
756 * workable paths other than root -> V, and it's important to avoid
757 * getting "confused" by non-working root->V->W path - it's important
758 * to *not* lose the working non-root paths, just because of a
759 * non-viable root->V->W.
760 *
761 * See also bug #330 (required reading!), and:
762 *
763 * http://blogs.oracle.com/paulj/entry/the_difference_a_line_makes
764 */
765 if (added)
766 return added;
718e3744 767 }
768
630e4807 769 /* 16.1.1 para 4. If there is at least one intervening router in the
770 * current shortest path between the destination and the root, the
771 * destination simply inherits the set of next hops from the
772 * parent.
773 */
b75ae99e
PJ
774 if (IS_DEBUG_OSPF_EVENT)
775 zlog_debug ("%s: Intervening routers, adding parent(s)", __func__);
776
eb3da6df 777 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
bc20c1a4
PJ
778 {
779 added = 1;
bd34fb34 780 ospf_spf_add_parent (v, w, vp->nexthop, distance);
bc20c1a4 781 }
9c27ef9b 782
bc20c1a4 783 return added;
718e3744 784}
785
630e4807 786/* RFC2328 Section 16.1 (2).
787 * v is on the SPF tree. Examine the links in v's LSA. Update the list
788 * of candidates with any vertices not already on the list. If a lower-cost
789 * path is found to a vertex already on the candidate list, store the new cost.
790 */
4dadc291 791static void
718e3744 792ospf_spf_next (struct vertex *v, struct ospf_area *area,
462f20d5 793 struct pqueue * candidate)
718e3744 794{
795 struct ospf_lsa *w_lsa = NULL;
718e3744 796 u_char *p;
797 u_char *lim;
798 struct router_lsa_link *l = NULL;
799 struct in_addr *r;
c81ee5c9 800 int type = 0, lsa_pos=-1, lsa_pos_next=0;
718e3744 801
802 /* If this is a router-LSA, and bit V of the router-LSA (see Section
803 A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE. */
804 if (v->type == OSPF_VERTEX_ROUTER)
805 {
806 if (IS_ROUTER_LSA_VIRTUAL ((struct router_lsa *) v->lsa))
807 area->transit = OSPF_TRANSIT_TRUE;
808 }
b75ae99e
PJ
809
810 if (IS_DEBUG_OSPF_EVENT)
811 zlog_debug ("%s: Next vertex of %s vertex %s",
812 __func__,
813 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
814 inet_ntoa(v->lsa->id));
815
718e3744 816 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
0c0f9cd5 817 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
818
718e3744 819 while (p < lim)
820 {
eb3da6df 821 struct vertex *w;
822 unsigned int distance;
d355bfa7 823
718e3744 824 /* In case of V is Router-LSA. */
825 if (v->lsa->type == OSPF_ROUTER_LSA)
826 {
827 l = (struct router_lsa_link *) p;
828
c81ee5c9
JT
829 lsa_pos = lsa_pos_next; /* LSA link position */
830 lsa_pos_next++;
05b7709d
DO
831 p += (OSPF_ROUTER_LSA_LINK_SIZE +
832 (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
718e3744 833
834 /* (a) If this is a link to a stub network, examine the next
835 link in V's LSA. Links to stub networks will be
836 considered in the second stage of the shortest path
837 calculation. */
838 if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB)
839 continue;
08d3d5b3 840
718e3744 841 /* (b) Otherwise, W is a transit vertex (router or transit
842 network). Look up the vertex W's LSA (router-LSA or
843 network-LSA) in Area A's link state database. */
844 switch (type)
845 {
846 case LSA_LINK_TYPE_POINTOPOINT:
847 case LSA_LINK_TYPE_VIRTUALLINK:
848 if (type == LSA_LINK_TYPE_VIRTUALLINK)
0c0f9cd5 849 {
850 if (IS_DEBUG_OSPF_EVENT)
2a42e285 851 zlog_debug ("looking up LSA through VL: %s",
0c0f9cd5 852 inet_ntoa (l->link_id));
853 }
718e3744 854
855 w_lsa = ospf_lsa_lookup (area, OSPF_ROUTER_LSA, l->link_id,
856 l->link_id);
857 if (w_lsa)
0c0f9cd5 858 {
859 if (IS_DEBUG_OSPF_EVENT)
2a42e285 860 zlog_debug ("found Router LSA %s", inet_ntoa (l->link_id));
0c0f9cd5 861 }
718e3744 862 break;
863 case LSA_LINK_TYPE_TRANSIT:
0c0f9cd5 864 if (IS_DEBUG_OSPF_EVENT)
2a42e285 865 zlog_debug ("Looking up Network LSA, ID: %s",
0c0f9cd5 866 inet_ntoa (l->link_id));
718e3744 867 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_NETWORK_LSA,
0c0f9cd5 868 l->link_id);
718e3744 869 if (w_lsa)
0c0f9cd5 870 if (IS_DEBUG_OSPF_EVENT)
2a42e285 871 zlog_debug ("found the LSA");
718e3744 872 break;
873 default:
0c0f9cd5 874 zlog_warn ("Invalid LSA link type %d", type);
718e3744 875 continue;
876 }
877 }
878 else
879 {
880 /* In case of V is Network-LSA. */
0c0f9cd5 881 r = (struct in_addr *) p;
718e3744 882 p += sizeof (struct in_addr);
883
884 /* Lookup the vertex W's LSA. */
885 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_ROUTER_LSA, *r);
b75ae99e
PJ
886 if (w_lsa)
887 {
888 if (IS_DEBUG_OSPF_EVENT)
889 zlog_debug ("found Router LSA %s", inet_ntoa (w_lsa->data->id));
890 }
718e3744 891 }
892
893 /* (b cont.) If the LSA does not exist, or its LS age is equal
894 to MaxAge, or it does not have a link back to vertex V,
895 examine the next link in V's LSA.[23] */
896 if (w_lsa == NULL)
b75ae99e
PJ
897 {
898 if (IS_DEBUG_OSPF_EVENT)
899 zlog_debug ("No LSA found");
900 continue;
901 }
718e3744 902
903 if (IS_LSA_MAXAGE (w_lsa))
b75ae99e
PJ
904 {
905 if (IS_DEBUG_OSPF_EVENT)
906 zlog_debug ("LSA is MaxAge");
907 continue;
908 }
718e3744 909
eb3da6df 910 if (ospf_lsa_has_link (w_lsa->data, v->lsa) < 0 )
718e3744 911 {
0c0f9cd5 912 if (IS_DEBUG_OSPF_EVENT)
2a42e285 913 zlog_debug ("The LSA doesn't have a link back");
718e3744 914 continue;
915 }
916
917 /* (c) If vertex W is already on the shortest-path tree, examine
918 the next link in the LSA. */
462f20d5 919 if (w_lsa->stat == LSA_SPF_IN_SPFTREE)
920 {
921 if (IS_DEBUG_OSPF_EVENT)
922 zlog_debug ("The LSA is already in SPF");
923 continue;
924 }
718e3744 925
926 /* (d) Calculate the link state cost D of the resulting path
927 from the root to vertex W. D is equal to the sum of the link
928 state cost of the (already calculated) shortest path to
929 vertex V and the advertised cost of the link between vertices
930 V and W. If D is: */
931
718e3744 932 /* calculate link cost D. */
933 if (v->lsa->type == OSPF_ROUTER_LSA)
eb3da6df 934 distance = v->distance + ntohs (l->m[0].metric);
630e4807 935 else /* v is not a Router-LSA */
eb3da6df 936 distance = v->distance;
718e3744 937
938 /* Is there already vertex W in candidate list? */
462f20d5 939 if (w_lsa->stat == LSA_SPF_NOT_EXPLORED)
940 {
eb3da6df 941 /* prepare vertex W. */
942 w = ospf_vertex_new (w_lsa);
943
462f20d5 944 /* Calculate nexthop to W. */
c81ee5c9 945 if (ospf_nexthop_calculation (area, v, w, l, distance, lsa_pos))
bc20c1a4 946 pqueue_enqueue (w, candidate);
b75ae99e
PJ
947 else if (IS_DEBUG_OSPF_EVENT)
948 zlog_debug ("Nexthop Calc failed");
462f20d5 949 }
950 else if (w_lsa->stat >= 0)
951 {
952 /* Get the vertex from candidates. */
eb3da6df 953 w = candidate->array[w_lsa->stat];
718e3744 954
462f20d5 955 /* if D is greater than. */
eb3da6df 956 if (w->distance < distance)
718e3744 957 {
718e3744 958 continue;
959 }
462f20d5 960 /* equal to. */
eb3da6df 961 else if (w->distance == distance)
718e3744 962 {
eb3da6df 963 /* Found an equal-cost path to W.
964 * Calculate nexthop of to W from V. */
c81ee5c9 965 ospf_nexthop_calculation (area, v, w, l, distance, lsa_pos);
718e3744 966 }
462f20d5 967 /* less than. */
968 else
718e3744 969 {
bc20c1a4
PJ
970 /* Found a lower-cost path to W.
971 * nexthop_calculation is conditional, if it finds
972 * valid nexthop it will call spf_add_parents, which
973 * will flush the old parents
974 */
c81ee5c9 975 if (ospf_nexthop_calculation (area, v, w, l, distance, lsa_pos))
7591d8b8
PJ
976 /* Decrease the key of the node in the heap.
977 * trickle-sort it up towards root, just in case this
978 * node should now be the new root due the cost change.
e95537f0 979 * (next pqueu_{de,en}queue will fully re-heap the queue).
7591d8b8
PJ
980 */
981 trickle_up (w_lsa->stat, candidate);
718e3744 982 }
630e4807 983 } /* end W is already on the candidate list */
984 } /* end loop over the links in V's LSA */
718e3744 985}
986
4dadc291 987static void
718e3744 988ospf_spf_dump (struct vertex *v, int i)
989{
52dc7ee6 990 struct listnode *cnode;
991 struct listnode *nnode;
eb3da6df 992 struct vertex_parent *parent;
718e3744 993
994 if (v->type == OSPF_VERTEX_ROUTER)
995 {
996 if (IS_DEBUG_OSPF_EVENT)
2a42e285 997 zlog_debug ("SPF Result: %d [R] %s", i, inet_ntoa (v->lsa->id));
718e3744 998 }
999 else
1000 {
1001 struct network_lsa *lsa = (struct network_lsa *) v->lsa;
1002 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1003 zlog_debug ("SPF Result: %d [N] %s/%d", i, inet_ntoa (v->lsa->id),
0c0f9cd5 1004 ip_masklen (lsa->mask));
630e4807 1005 }
718e3744 1006
1eb8ef25 1007 if (IS_DEBUG_OSPF_EVENT)
eb3da6df 1008 for (ALL_LIST_ELEMENTS_RO (v->parents, nnode, parent))
1009 {
1010 zlog_debug (" nexthop %p %s %s",
6c4f4e6e 1011 (void *)parent->nexthop,
eb3da6df 1012 inet_ntoa (parent->nexthop->router),
1013 parent->nexthop->oi ? IF_NAME(parent->nexthop->oi)
1014 : "NULL");
1015 }
718e3744 1016
1017 i++;
1018
eb3da6df 1019 for (ALL_LIST_ELEMENTS_RO (v->children, cnode, v))
1eb8ef25 1020 ospf_spf_dump (v, i);
718e3744 1021}
1022
1023/* Second stage of SPF calculation. */
4dadc291 1024static void
0c0f9cd5 1025ospf_spf_process_stubs (struct ospf_area *area, struct vertex *v,
b3bc68e5
PJ
1026 struct route_table *rt,
1027 int parent_is_root)
718e3744 1028{
1eb8ef25 1029 struct listnode *cnode, *cnnode;
718e3744 1030 struct vertex *child;
1031
1032 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1033 zlog_debug ("ospf_process_stub():processing stubs for area %s",
0c0f9cd5 1034 inet_ntoa (area->area_id));
718e3744 1035 if (v->type == OSPF_VERTEX_ROUTER)
1036 {
1037 u_char *p;
1038 u_char *lim;
1039 struct router_lsa_link *l;
1040 struct router_lsa *rlsa;
57c639f0 1041 int lsa_pos = 0;
718e3744 1042
0c0f9cd5 1043 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1044 zlog_debug ("ospf_process_stubs():processing router LSA, id: %s",
0c0f9cd5 1045 inet_ntoa (v->lsa->id));
718e3744 1046 rlsa = (struct router_lsa *) v->lsa;
1047
1048
0c0f9cd5 1049 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1050 zlog_debug ("ospf_process_stubs(): we have %d links to process",
0c0f9cd5 1051 ntohs (rlsa->links));
630e4807 1052 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
718e3744 1053 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
1054
1055 while (p < lim)
1056 {
1057 l = (struct router_lsa_link *) p;
1058
05b7709d
DO
1059 p += (OSPF_ROUTER_LSA_LINK_SIZE +
1060 (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
718e3744 1061
1062 if (l->m[0].type == LSA_LINK_TYPE_STUB)
57c639f0
JT
1063 ospf_intra_add_stub (rt, l, v, area, parent_is_root, lsa_pos);
1064 lsa_pos++;
718e3744 1065 }
1066 }
1067
630e4807 1068 ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1, 1);
718e3744 1069
eb3da6df 1070 for (ALL_LIST_ELEMENTS (v->children, cnode, cnnode, child))
718e3744 1071 {
718e3744 1072 if (CHECK_FLAG (child->flags, OSPF_VERTEX_PROCESSED))
0c0f9cd5 1073 continue;
b3bc68e5
PJ
1074
1075 /* the first level of routers connected to the root
1076 * should have 'parent_is_root' set, including those
1077 * connected via a network vertex.
1078 */
1079 if (area->spf == v)
1080 parent_is_root = 1;
1081 else if (v->type == OSPF_VERTEX_ROUTER)
1082 parent_is_root = 0;
1083
1084 ospf_spf_process_stubs (area, child, rt, parent_is_root);
718e3744 1085
1086 SET_FLAG (child->flags, OSPF_VERTEX_PROCESSED);
1087 }
1088}
1089
1090void
1091ospf_rtrs_free (struct route_table *rtrs)
1092{
1093 struct route_node *rn;
52dc7ee6 1094 struct list *or_list;
1eb8ef25 1095 struct ospf_route *or;
1096 struct listnode *node, *nnode;
718e3744 1097
1098 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1099 zlog_debug ("Route: Router Routing Table free");
718e3744 1100
1101 for (rn = route_top (rtrs); rn; rn = route_next (rn))
1102 if ((or_list = rn->info) != NULL)
1103 {
1eb8ef25 1104 for (ALL_LIST_ELEMENTS (or_list, node, nnode, or))
1105 ospf_route_free (or);
718e3744 1106
0c0f9cd5 1107 list_delete (or_list);
718e3744 1108
0c0f9cd5 1109 /* Unlock the node. */
1110 rn->info = NULL;
1111 route_unlock_node (rn);
718e3744 1112 }
1113 route_table_finish (rtrs);
1114}
1115
075e12f5 1116#if 0
4dadc291 1117static void
718e3744 1118ospf_rtrs_print (struct route_table *rtrs)
1119{
1120 struct route_node *rn;
52dc7ee6 1121 struct list *or_list;
1122 struct listnode *ln;
1123 struct listnode *pnode;
718e3744 1124 struct ospf_route *or;
1125 struct ospf_path *path;
1126 char buf1[BUFSIZ];
1127 char buf2[BUFSIZ];
1128
1129 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1130 zlog_debug ("ospf_rtrs_print() start");
718e3744 1131
1132 for (rn = route_top (rtrs); rn; rn = route_next (rn))
1133 if ((or_list = rn->info) != NULL)
1eb8ef25 1134 for (ALL_LIST_ELEMENTS_RO (or_list, ln, or))
718e3744 1135 {
718e3744 1136 switch (or->path_type)
1137 {
1138 case OSPF_PATH_INTRA_AREA:
0c0f9cd5 1139 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1140 zlog_debug ("%s [%d] area: %s",
0c0f9cd5 1141 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1142 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1143 buf2, BUFSIZ));
718e3744 1144 break;
1145 case OSPF_PATH_INTER_AREA:
0c0f9cd5 1146 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1147 zlog_debug ("%s IA [%d] area: %s",
0c0f9cd5 1148 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1149 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1150 buf2, BUFSIZ));
718e3744 1151 break;
1152 default:
1153 break;
1154 }
1155
1eb8ef25 1156 for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path))
718e3744 1157 {
718e3744 1158 if (path->nexthop.s_addr == 0)
0c0f9cd5 1159 {
1160 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1161 zlog_debug (" directly attached to %s\r\n",
a8ba847f 1162 ifindex2ifname (path->ifindex));
0c0f9cd5 1163 }
1164 else
1165 {
1166 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1167 zlog_debug (" via %s, %s\r\n",
a8ba847f
JT
1168 inet_ntoa (path->nexthop),
1169 ifindex2ifname (path->ifindex));
0c0f9cd5 1170 }
718e3744 1171 }
1172 }
1173
2a42e285 1174 zlog_debug ("ospf_rtrs_print() end");
718e3744 1175}
075e12f5 1176#endif
718e3744 1177
1178/* Calculating the shortest-path tree for an area. */
4dadc291 1179static void
0c0f9cd5 1180ospf_spf_calculate (struct ospf_area *area, struct route_table *new_table,
718e3744 1181 struct route_table *new_rtrs)
1182{
462f20d5 1183 struct pqueue *candidate;
718e3744 1184 struct vertex *v;
eb3da6df 1185
718e3744 1186 if (IS_DEBUG_OSPF_EVENT)
1187 {
2a42e285 1188 zlog_debug ("ospf_spf_calculate: Start");
1189 zlog_debug ("ospf_spf_calculate: running Dijkstra for area %s",
0c0f9cd5 1190 inet_ntoa (area->area_id));
718e3744 1191 }
1192
1193 /* Check router-lsa-self. If self-router-lsa is not yet allocated,
1194 return this area's calculation. */
0c0f9cd5 1195 if (!area->router_lsa_self)
718e3744 1196 {
1197 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1198 zlog_debug ("ospf_spf_calculate: "
0c0f9cd5 1199 "Skip area %s's calculation due to empty router_lsa_self",
1200 inet_ntoa (area->area_id));
718e3744 1201 return;
1202 }
1203
1204 /* RFC2328 16.1. (1). */
0c0f9cd5 1205 /* Initialize the algorithm's data structures. */
462f20d5 1206
1207 /* This function scans all the LSA database and set the stat field to
1208 * LSA_SPF_NOT_EXPLORED. */
1209 ospf_lsdb_clean_stat (area->lsdb);
1210 /* Create a new heap for the candidates. */
1211 candidate = pqueue_create();
1212 candidate->cmp = cmp;
1213 candidate->update = update_stat;
718e3744 1214
1215 /* Initialize the shortest-path tree to only the root (which is the
1216 router doing the calculation). */
1217 ospf_spf_init (area);
1218 v = area->spf;
462f20d5 1219 /* Set LSA position to LSA_SPF_IN_SPFTREE. This vertex is the root of the
1220 * spanning tree. */
1221 *(v->stat) = LSA_SPF_IN_SPFTREE;
718e3744 1222
1223 /* Set Area A's TransitCapability to FALSE. */
1224 area->transit = OSPF_TRANSIT_FALSE;
1225 area->shortcut_capability = 1;
eb3da6df 1226
718e3744 1227 for (;;)
1228 {
1229 /* RFC2328 16.1. (2). */
462f20d5 1230 ospf_spf_next (v, area, candidate);
718e3744 1231
1232 /* RFC2328 16.1. (3). */
1233 /* If at this step the candidate list is empty, the shortest-
1234 path tree (of transit vertices) has been completely built and
1235 this stage of the procedure terminates. */
462f20d5 1236 if (candidate->size == 0)
718e3744 1237 break;
1238
1239 /* Otherwise, choose the vertex belonging to the candidate list
1240 that is closest to the root, and add it to the shortest-path
1241 tree (removing it from the candidate list in the
0c0f9cd5 1242 process). */
462f20d5 1243 /* Extract from the candidates the node with the lower key. */
1244 v = (struct vertex *) pqueue_dequeue (candidate);
1245 /* Update stat field in vertex. */
1246 *(v->stat) = LSA_SPF_IN_SPFTREE;
eb3da6df 1247
718e3744 1248 ospf_vertex_add_parent (v);
1249
718e3744 1250 /* RFC2328 16.1. (4). */
1251 if (v->type == OSPF_VERTEX_ROUTER)
1252 ospf_intra_add_router (new_rtrs, v, area);
0c0f9cd5 1253 else
718e3744 1254 ospf_intra_add_transit (new_table, v, area);
1255
1256 /* RFC2328 16.1. (5). */
1257 /* Iterate the algorithm by returning to Step 2. */
630e4807 1258
1259 } /* end loop until no more candidate vertices */
718e3744 1260
1261 if (IS_DEBUG_OSPF_EVENT)
1262 {
1263 ospf_spf_dump (area->spf, 0);
1264 ospf_route_table_dump (new_table);
1265 }
1266
1267 /* Second stage of SPF calculation procedure's */
b3bc68e5 1268 ospf_spf_process_stubs (area, area->spf, new_table, 0);
718e3744 1269
eb3da6df 1270 /* Free candidate queue. */
462f20d5 1271 pqueue_delete (candidate);
cf744958 1272
eb3da6df 1273 ospf_vertex_dump (__func__, area->spf, 0, 1);
1274 /* Free nexthop information, canonical versions of which are attached
1275 * the first level of router vertices attached to the root vertex, see
1276 * ospf_nexthop_calculation.
1277 */
1278 ospf_canonical_nexthops_free (area->spf);
cf744958 1279
718e3744 1280 /* Increment SPF Calculation Counter. */
1281 area->spf_calculation++;
1282
2518efd1 1283 quagga_gettime (QUAGGA_CLK_MONOTONIC, &area->ospf->ts_spf);
cf744958 1284 area->ts_spf = area->ospf->ts_spf;
718e3744 1285
1286 if (IS_DEBUG_OSPF_EVENT)
9c27ef9b
PJ
1287 zlog_debug ("ospf_spf_calculate: Stop. %ld vertices",
1288 mtype_stats_alloc(MTYPE_OSPF_VERTEX));
cf744958
DS
1289
1290 /* Free SPF vertices, but not the list. List has ospf_vertex_free
1291 * as deconstructor.
1292 */
1293 list_delete_all_node (&vertex_list);
718e3744 1294}
6b0655a2 1295
718e3744 1296/* Timer for SPF calculation. */
4dadc291 1297static int
68980084 1298ospf_spf_calculate_timer (struct thread *thread)
718e3744 1299{
68980084 1300 struct ospf *ospf = THREAD_ARG (thread);
718e3744 1301 struct route_table *new_table, *new_rtrs;
1eb8ef25 1302 struct ospf_area *area;
1303 struct listnode *node, *nnode;
cf744958
DS
1304 struct timeval start_time, stop_time, spf_start_time;
1305 int areas_processed = 0;
1306 unsigned long ia_time, prune_time, rt_time;
1307 unsigned long abr_time, total_spf_time, spf_time;
1308 char rbuf[32]; /* reason_buf */
d3a9c768 1309
718e3744 1310 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1311 zlog_debug ("SPF: Timer (SPF calculation expire)");
0c0f9cd5 1312
718e3744 1313 ospf->t_spf_calc = NULL;
1314
cf744958 1315 quagga_gettime (QUAGGA_CLK_MONOTONIC, &spf_start_time);
718e3744 1316 /* Allocate new table tree. */
1317 new_table = route_table_init ();
0c0f9cd5 1318 new_rtrs = route_table_init ();
718e3744 1319
68980084 1320 ospf_vl_unapprove (ospf);
718e3744 1321
1322 /* Calculate SPF for each area. */
1eb8ef25 1323 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
9c27ef9b
PJ
1324 {
1325 /* Do backbone last, so as to first discover intra-area paths
1326 * for any back-bone virtual-links
1327 */
1328 if (ospf->backbone && ospf->backbone == area)
1329 continue;
cf744958 1330
9c27ef9b 1331 ospf_spf_calculate (area, new_table, new_rtrs);
cf744958 1332 areas_processed++;
9c27ef9b 1333 }
cf744958 1334
9c27ef9b
PJ
1335 /* SPF for backbone, if required */
1336 if (ospf->backbone)
cf744958
DS
1337 {
1338 ospf_spf_calculate (ospf->backbone, new_table, new_rtrs);
1339 areas_processed++;
1340 }
1341
1342 quagga_gettime (QUAGGA_CLK_MONOTONIC, &stop_time);
1343 spf_time = timeval_elapsed (stop_time, spf_start_time);
1344
68980084 1345 ospf_vl_shut_unapproved (ospf);
718e3744 1346
cf744958
DS
1347 start_time = stop_time; /* saving a call */
1348
68980084 1349 ospf_ia_routing (ospf, new_table, new_rtrs);
718e3744 1350
cf744958
DS
1351 quagga_gettime (QUAGGA_CLK_MONOTONIC, &stop_time);
1352 ia_time = timeval_elapsed (stop_time, start_time);
1353
1354 quagga_gettime (QUAGGA_CLK_MONOTONIC, &start_time);
718e3744 1355 ospf_prune_unreachable_networks (new_table);
1356 ospf_prune_unreachable_routers (new_rtrs);
1357
cf744958
DS
1358 quagga_gettime (QUAGGA_CLK_MONOTONIC, &stop_time);
1359 prune_time = timeval_elapsed (stop_time, start_time);
718e3744 1360 /* AS-external-LSA calculation should not be performed here. */
1361
1362 /* If new Router Route is installed,
1363 then schedule re-calculate External routes. */
1364 if (1)
68980084 1365 ospf_ase_calculate_schedule (ospf);
718e3744 1366
68980084 1367 ospf_ase_calculate_timer_add (ospf);
718e3744 1368
cf744958
DS
1369 quagga_gettime (QUAGGA_CLK_MONOTONIC, &start_time);
1370
718e3744 1371 /* Update routing table. */
68980084 1372 ospf_route_install (ospf, new_table);
718e3744 1373
cf744958
DS
1374 quagga_gettime (QUAGGA_CLK_MONOTONIC, &stop_time);
1375 rt_time = timeval_elapsed (stop_time, start_time);
718e3744 1376 /* Update ABR/ASBR routing table */
68980084 1377 if (ospf->old_rtrs)
718e3744 1378 {
1379 /* old_rtrs's node holds linked list of ospf_route. --kunihiro. */
68980084 1380 /* ospf_route_delete (ospf->old_rtrs); */
1381 ospf_rtrs_free (ospf->old_rtrs);
718e3744 1382 }
1383
68980084 1384 ospf->old_rtrs = ospf->new_rtrs;
1385 ospf->new_rtrs = new_rtrs;
718e3744 1386
cf744958 1387 quagga_gettime (QUAGGA_CLK_MONOTONIC, &start_time);
0c0f9cd5 1388 if (IS_OSPF_ABR (ospf))
68980084 1389 ospf_abr_task (ospf);
718e3744 1390
cf744958
DS
1391 quagga_gettime (QUAGGA_CLK_MONOTONIC, &stop_time);
1392 abr_time = timeval_elapsed (stop_time, start_time);
1393
1394 quagga_gettime (QUAGGA_CLK_MONOTONIC, &stop_time);
1395 total_spf_time = timeval_elapsed (stop_time, spf_start_time);
1396 ospf->ts_spf_duration.tv_sec = total_spf_time/1000000;
1397 ospf->ts_spf_duration.tv_usec = total_spf_time % 1000000;
1398
1399 ospf_get_spf_reason_str (rbuf);
1400
d3a9c768
PJ
1401 if (IS_DEBUG_OSPF_EVENT)
1402 {
1403 zlog_info ("SPF Processing Time(usecs): %ld", total_spf_time);
1404 zlog_info ("\t SPF Time: %ld", spf_time);
1405 zlog_info ("\t InterArea: %ld", ia_time);
1406 zlog_info ("\t Prune: %ld", prune_time);
1407 zlog_info ("\tRouteInstall: %ld", rt_time);
1408 if (IS_OSPF_ABR (ospf))
1409 zlog_info ("\t ABR: %ld (%d areas)",
1410 abr_time, areas_processed);
1411 zlog_info ("Reason(s) for SPF: %s", rbuf);
1412 }
cf744958
DS
1413
1414 ospf_clear_spf_reason_flags ();
718e3744 1415
1416 return 0;
1417}
1418
1419/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
1420 set timer for SPF calc. */
1421void
d3a9c768 1422ospf_spf_calculate_schedule (struct ospf *ospf, ospf_spf_reason_t reason)
718e3744 1423{
d24f6e2a 1424 unsigned long delay, elapsed, ht;
1425 struct timeval result;
718e3744 1426
1427 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1428 zlog_debug ("SPF: calculation timer scheduled");
718e3744 1429
1430 /* OSPF instance does not exist. */
68980084 1431 if (ospf == NULL)
718e3744 1432 return;
d24f6e2a 1433
d3a9c768
PJ
1434 ospf_spf_set_reason (reason);
1435
718e3744 1436 /* SPF calculation timer is already scheduled. */
68980084 1437 if (ospf->t_spf_calc)
718e3744 1438 {
1439 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1440 zlog_debug ("SPF: calculation timer is already scheduled: %p",
6c4f4e6e 1441 (void *)ospf->t_spf_calc);
718e3744 1442 return;
1443 }
d24f6e2a 1444
1445 /* XXX Monotic timers: we only care about relative time here. */
2518efd1 1446 result = tv_sub (recent_relative_time (), ospf->ts_spf);
d24f6e2a 1447
1448 elapsed = (result.tv_sec * 1000) + (result.tv_usec / 1000);
1449 ht = ospf->spf_holdtime * ospf->spf_hold_multiplier;
1450
1451 if (ht > ospf->spf_max_holdtime)
1452 ht = ospf->spf_max_holdtime;
1453
718e3744 1454 /* Get SPF calculation delay time. */
d24f6e2a 1455 if (elapsed < ht)
718e3744 1456 {
d24f6e2a 1457 /* Got an event within the hold time of last SPF. We need to
1458 * increase the hold_multiplier, if it's not already at/past
1459 * maximum value, and wasn't already increased..
1460 */
1461 if (ht < ospf->spf_max_holdtime)
1462 ospf->spf_hold_multiplier++;
1463
1464 /* always honour the SPF initial delay */
1465 if ( (ht - elapsed) < ospf->spf_delay)
0c0f9cd5 1466 delay = ospf->spf_delay;
718e3744 1467 else
d24f6e2a 1468 delay = ht - elapsed;
718e3744 1469 }
1470 else
d24f6e2a 1471 {
1472 /* Event is past required hold-time of last SPF */
1473 delay = ospf->spf_delay;
1474 ospf->spf_hold_multiplier = 1;
1475 }
1476
718e3744 1477 if (IS_DEBUG_OSPF_EVENT)
d24f6e2a 1478 zlog_debug ("SPF: calculation timer delay = %ld", delay);
1479
cf744958
DS
1480 zlog_info ("SPF: Scheduled in %ld msec", delay);
1481
68980084 1482 ospf->t_spf_calc =
d24f6e2a 1483 thread_add_timer_msec (master, ospf_spf_calculate_timer, ospf, delay);
718e3744 1484}