]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_spf.c
lib: time: add new monotime() helpers
[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 {
c5e0075f 593 struct in_addr nexthop = { .s_addr = 0 };
c81ee5c9 594
eb3da6df 595 /* 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.
603
604 At this point l is a link from V to W, and V is the
c81ee5c9
JT
605 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
eb3da6df 608 subnet declared by the PtMP link, then that link
c81ee5c9 609 is a constituent of the PtMP link, and its address is
eb3da6df 610 a nexthop address for V.
611 */
c81ee5c9
JT
612 if (oi->type == OSPF_IFTYPE_POINTOPOINT)
613 {
f2b53dac
CF
614 /* 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 }
c81ee5c9
JT
630 }
631 else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
632 {
633 struct prefix_ipv4 la;
634
635 la.family = AF_INET;
636 la.prefixlen = oi->address->prefixlen;
637
638 /* 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;
643
644 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 }
653
654 if (added)
eb3da6df 655 {
656 /* found all necessary info to build nexthop */
657 nh = vertex_nexthop_new ();
658 nh->oi = oi;
c81ee5c9 659 nh->router = nexthop;
bd34fb34 660 ospf_spf_add_parent (v, w, nh, distance);
bc20c1a4 661 return 1;
eb3da6df 662 }
663 else
c81ee5c9
JT
664 zlog_info("%s: could not determine nexthop for link %s",
665 __func__, oi->ifp->name);
9c27ef9b
PJ
666 } /* end point-to-point link from V to W */
667 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))
eb3da6df 682 {
9c27ef9b
PJ
683 nh = vertex_nexthop_new ();
684 nh->oi = vl_data->nexthop.oi;
685 nh->router = vl_data->nexthop.router;
bd34fb34 686 ospf_spf_add_parent (v, w, nh, distance);
bc20c1a4 687 return 1;
eb3da6df 688 }
9c27ef9b 689 else
bc20c1a4
PJ
690 zlog_info("ospf_nexthop_calculation(): "
691 "vl_data for VL link not found");
9c27ef9b 692 } /* end virtual-link from V to W */
bc20c1a4 693 return 0;
630e4807 694 } /* end W is a Router vertex */
718e3744 695 else
0c0f9cd5 696 {
eb3da6df 697 assert(w->type == OSPF_VERTEX_NETWORK);
c81ee5c9
JT
698
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;
0c0f9cd5 704 }
630e4807 705 } /* end V is the root */
630e4807 706 /* Check if W's parent is a network connected to root. */
718e3744 707 else if (v->type == OSPF_VERTEX_NETWORK)
708 {
630e4807 709 /* See if any of V's parents are the root. */
eb3da6df 710 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
718e3744 711 {
eb3da6df 712 if (vp->parent == area->spf) /* connects to root? */
630e4807 713 {
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);
0c0f9cd5 721 while ((l = ospf_get_next_link (w, v, l)))
722 {
630e4807 723 /* ...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 */
eb3da6df 729 nh = vertex_nexthop_new ();
730 nh->oi = vp->nexthop->oi;
731 nh->router = l->link_data;
bc20c1a4 732 added = 1;
bd34fb34 733 ospf_spf_add_parent (v, w, nh, distance);
0c0f9cd5 734 }
945ea293
PJ
735 /* Note lack of return is deliberate. See next comment. */
736 }
718e3744 737 }
945ea293
PJ
738 /* 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;
718e3744 766 }
767
630e4807 768 /* 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 */
b75ae99e
PJ
773 if (IS_DEBUG_OSPF_EVENT)
774 zlog_debug ("%s: Intervening routers, adding parent(s)", __func__);
775
eb3da6df 776 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
bc20c1a4
PJ
777 {
778 added = 1;
bd34fb34 779 ospf_spf_add_parent (v, w, vp->nexthop, distance);
bc20c1a4 780 }
9c27ef9b 781
bc20c1a4 782 return added;
718e3744 783}
784
630e4807 785/* 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 */
4dadc291 790static void
718e3744 791ospf_spf_next (struct vertex *v, struct ospf_area *area,
462f20d5 792 struct pqueue * candidate)
718e3744 793{
794 struct ospf_lsa *w_lsa = NULL;
718e3744 795 u_char *p;
796 u_char *lim;
797 struct router_lsa_link *l = NULL;
798 struct in_addr *r;
c81ee5c9 799 int type = 0, lsa_pos=-1, lsa_pos_next=0;
718e3744 800
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 }
b75ae99e
PJ
808
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
718e3744 815 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
0c0f9cd5 816 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
817
718e3744 818 while (p < lim)
819 {
eb3da6df 820 struct vertex *w;
821 unsigned int distance;
d355bfa7 822
718e3744 823 /* In case of V is Router-LSA. */
824 if (v->lsa->type == OSPF_ROUTER_LSA)
825 {
826 l = (struct router_lsa_link *) p;
827
c81ee5c9
JT
828 lsa_pos = lsa_pos_next; /* LSA link position */
829 lsa_pos_next++;
05b7709d
DO
830 p += (OSPF_ROUTER_LSA_LINK_SIZE +
831 (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
718e3744 832
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;
08d3d5b3 839
718e3744 840 /* (b) Otherwise, W is a transit vertex (router or transit
841 network). Look up the vertex W's LSA (router-LSA or
842 network-LSA) in Area A's link state database. */
843 switch (type)
844 {
845 case LSA_LINK_TYPE_POINTOPOINT:
846 case LSA_LINK_TYPE_VIRTUALLINK:
847 if (type == LSA_LINK_TYPE_VIRTUALLINK)
0c0f9cd5 848 {
849 if (IS_DEBUG_OSPF_EVENT)
2a42e285 850 zlog_debug ("looking up LSA through VL: %s",
0c0f9cd5 851 inet_ntoa (l->link_id));
852 }
718e3744 853
854 w_lsa = ospf_lsa_lookup (area, OSPF_ROUTER_LSA, l->link_id,
855 l->link_id);
856 if (w_lsa)
0c0f9cd5 857 {
858 if (IS_DEBUG_OSPF_EVENT)
2a42e285 859 zlog_debug ("found Router LSA %s", inet_ntoa (l->link_id));
0c0f9cd5 860 }
718e3744 861 break;
862 case LSA_LINK_TYPE_TRANSIT:
0c0f9cd5 863 if (IS_DEBUG_OSPF_EVENT)
2a42e285 864 zlog_debug ("Looking up Network LSA, ID: %s",
0c0f9cd5 865 inet_ntoa (l->link_id));
718e3744 866 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_NETWORK_LSA,
0c0f9cd5 867 l->link_id);
718e3744 868 if (w_lsa)
0c0f9cd5 869 if (IS_DEBUG_OSPF_EVENT)
2a42e285 870 zlog_debug ("found the LSA");
718e3744 871 break;
872 default:
0c0f9cd5 873 zlog_warn ("Invalid LSA link type %d", type);
718e3744 874 continue;
875 }
876 }
877 else
878 {
879 /* In case of V is Network-LSA. */
0c0f9cd5 880 r = (struct in_addr *) p;
718e3744 881 p += sizeof (struct in_addr);
882
883 /* Lookup the vertex W's LSA. */
884 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_ROUTER_LSA, *r);
b75ae99e
PJ
885 if (w_lsa)
886 {
887 if (IS_DEBUG_OSPF_EVENT)
888 zlog_debug ("found Router LSA %s", inet_ntoa (w_lsa->data->id));
889 }
718e3744 890 }
891
892 /* (b cont.) If the LSA does not exist, or its LS age is equal
893 to MaxAge, or it does not have a link back to vertex V,
894 examine the next link in V's LSA.[23] */
895 if (w_lsa == NULL)
b75ae99e
PJ
896 {
897 if (IS_DEBUG_OSPF_EVENT)
898 zlog_debug ("No LSA found");
899 continue;
900 }
718e3744 901
902 if (IS_LSA_MAXAGE (w_lsa))
b75ae99e
PJ
903 {
904 if (IS_DEBUG_OSPF_EVENT)
905 zlog_debug ("LSA is MaxAge");
906 continue;
907 }
718e3744 908
eb3da6df 909 if (ospf_lsa_has_link (w_lsa->data, v->lsa) < 0 )
718e3744 910 {
0c0f9cd5 911 if (IS_DEBUG_OSPF_EVENT)
2a42e285 912 zlog_debug ("The LSA doesn't have a link back");
718e3744 913 continue;
914 }
915
916 /* (c) If vertex W is already on the shortest-path tree, examine
917 the next link in the LSA. */
462f20d5 918 if (w_lsa->stat == LSA_SPF_IN_SPFTREE)
919 {
920 if (IS_DEBUG_OSPF_EVENT)
921 zlog_debug ("The LSA is already in SPF");
922 continue;
923 }
718e3744 924
925 /* (d) Calculate the link state cost D of the resulting path
926 from the root to vertex W. D is equal to the sum of the link
927 state cost of the (already calculated) shortest path to
928 vertex V and the advertised cost of the link between vertices
929 V and W. If D is: */
930
718e3744 931 /* calculate link cost D. */
932 if (v->lsa->type == OSPF_ROUTER_LSA)
eb3da6df 933 distance = v->distance + ntohs (l->m[0].metric);
630e4807 934 else /* v is not a Router-LSA */
eb3da6df 935 distance = v->distance;
718e3744 936
937 /* Is there already vertex W in candidate list? */
462f20d5 938 if (w_lsa->stat == LSA_SPF_NOT_EXPLORED)
939 {
eb3da6df 940 /* prepare vertex W. */
941 w = ospf_vertex_new (w_lsa);
942
462f20d5 943 /* Calculate nexthop to W. */
c81ee5c9 944 if (ospf_nexthop_calculation (area, v, w, l, distance, lsa_pos))
bc20c1a4 945 pqueue_enqueue (w, candidate);
b75ae99e
PJ
946 else if (IS_DEBUG_OSPF_EVENT)
947 zlog_debug ("Nexthop Calc failed");
462f20d5 948 }
949 else if (w_lsa->stat >= 0)
950 {
951 /* Get the vertex from candidates. */
eb3da6df 952 w = candidate->array[w_lsa->stat];
718e3744 953
462f20d5 954 /* if D is greater than. */
eb3da6df 955 if (w->distance < distance)
718e3744 956 {
718e3744 957 continue;
958 }
462f20d5 959 /* equal to. */
eb3da6df 960 else if (w->distance == distance)
718e3744 961 {
eb3da6df 962 /* Found an equal-cost path to W.
963 * Calculate nexthop of to W from V. */
c81ee5c9 964 ospf_nexthop_calculation (area, v, w, l, distance, lsa_pos);
718e3744 965 }
462f20d5 966 /* less than. */
967 else
718e3744 968 {
bc20c1a4
PJ
969 /* Found a lower-cost path to W.
970 * nexthop_calculation is conditional, if it finds
971 * valid nexthop it will call spf_add_parents, which
972 * will flush the old parents
973 */
c81ee5c9 974 if (ospf_nexthop_calculation (area, v, w, l, distance, lsa_pos))
7591d8b8
PJ
975 /* Decrease the key of the node in the heap.
976 * trickle-sort it up towards root, just in case this
977 * node should now be the new root due the cost change.
e95537f0 978 * (next pqueu_{de,en}queue will fully re-heap the queue).
7591d8b8
PJ
979 */
980 trickle_up (w_lsa->stat, candidate);
718e3744 981 }
630e4807 982 } /* end W is already on the candidate list */
983 } /* end loop over the links in V's LSA */
718e3744 984}
985
4dadc291 986static void
718e3744 987ospf_spf_dump (struct vertex *v, int i)
988{
52dc7ee6 989 struct listnode *cnode;
990 struct listnode *nnode;
eb3da6df 991 struct vertex_parent *parent;
718e3744 992
993 if (v->type == OSPF_VERTEX_ROUTER)
994 {
995 if (IS_DEBUG_OSPF_EVENT)
2a42e285 996 zlog_debug ("SPF Result: %d [R] %s", i, inet_ntoa (v->lsa->id));
718e3744 997 }
998 else
999 {
1000 struct network_lsa *lsa = (struct network_lsa *) v->lsa;
1001 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1002 zlog_debug ("SPF Result: %d [N] %s/%d", i, inet_ntoa (v->lsa->id),
0c0f9cd5 1003 ip_masklen (lsa->mask));
630e4807 1004 }
718e3744 1005
1eb8ef25 1006 if (IS_DEBUG_OSPF_EVENT)
eb3da6df 1007 for (ALL_LIST_ELEMENTS_RO (v->parents, nnode, parent))
1008 {
1009 zlog_debug (" nexthop %p %s %s",
6c4f4e6e 1010 (void *)parent->nexthop,
eb3da6df 1011 inet_ntoa (parent->nexthop->router),
1012 parent->nexthop->oi ? IF_NAME(parent->nexthop->oi)
1013 : "NULL");
1014 }
718e3744 1015
1016 i++;
1017
eb3da6df 1018 for (ALL_LIST_ELEMENTS_RO (v->children, cnode, v))
1eb8ef25 1019 ospf_spf_dump (v, i);
718e3744 1020}
1021
1022/* Second stage of SPF calculation. */
4dadc291 1023static void
0c0f9cd5 1024ospf_spf_process_stubs (struct ospf_area *area, struct vertex *v,
b3bc68e5
PJ
1025 struct route_table *rt,
1026 int parent_is_root)
718e3744 1027{
1eb8ef25 1028 struct listnode *cnode, *cnnode;
718e3744 1029 struct vertex *child;
1030
1031 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1032 zlog_debug ("ospf_process_stub():processing stubs for area %s",
0c0f9cd5 1033 inet_ntoa (area->area_id));
718e3744 1034 if (v->type == OSPF_VERTEX_ROUTER)
1035 {
1036 u_char *p;
1037 u_char *lim;
1038 struct router_lsa_link *l;
1039 struct router_lsa *rlsa;
57c639f0 1040 int lsa_pos = 0;
718e3744 1041
0c0f9cd5 1042 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1043 zlog_debug ("ospf_process_stubs():processing router LSA, id: %s",
0c0f9cd5 1044 inet_ntoa (v->lsa->id));
718e3744 1045 rlsa = (struct router_lsa *) v->lsa;
1046
1047
0c0f9cd5 1048 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1049 zlog_debug ("ospf_process_stubs(): we have %d links to process",
0c0f9cd5 1050 ntohs (rlsa->links));
630e4807 1051 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
718e3744 1052 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
1053
1054 while (p < lim)
1055 {
1056 l = (struct router_lsa_link *) p;
1057
05b7709d
DO
1058 p += (OSPF_ROUTER_LSA_LINK_SIZE +
1059 (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
718e3744 1060
1061 if (l->m[0].type == LSA_LINK_TYPE_STUB)
57c639f0
JT
1062 ospf_intra_add_stub (rt, l, v, area, parent_is_root, lsa_pos);
1063 lsa_pos++;
718e3744 1064 }
1065 }
1066
630e4807 1067 ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1, 1);
718e3744 1068
eb3da6df 1069 for (ALL_LIST_ELEMENTS (v->children, cnode, cnnode, child))
718e3744 1070 {
718e3744 1071 if (CHECK_FLAG (child->flags, OSPF_VERTEX_PROCESSED))
0c0f9cd5 1072 continue;
b3bc68e5
PJ
1073
1074 /* the first level of routers connected to the root
1075 * should have 'parent_is_root' set, including those
1076 * connected via a network vertex.
1077 */
1078 if (area->spf == v)
1079 parent_is_root = 1;
1080 else if (v->type == OSPF_VERTEX_ROUTER)
1081 parent_is_root = 0;
1082
1083 ospf_spf_process_stubs (area, child, rt, parent_is_root);
718e3744 1084
1085 SET_FLAG (child->flags, OSPF_VERTEX_PROCESSED);
1086 }
1087}
1088
1089void
1090ospf_rtrs_free (struct route_table *rtrs)
1091{
1092 struct route_node *rn;
52dc7ee6 1093 struct list *or_list;
1eb8ef25 1094 struct ospf_route *or;
1095 struct listnode *node, *nnode;
718e3744 1096
1097 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1098 zlog_debug ("Route: Router Routing Table free");
718e3744 1099
1100 for (rn = route_top (rtrs); rn; rn = route_next (rn))
1101 if ((or_list = rn->info) != NULL)
1102 {
1eb8ef25 1103 for (ALL_LIST_ELEMENTS (or_list, node, nnode, or))
1104 ospf_route_free (or);
718e3744 1105
0c0f9cd5 1106 list_delete (or_list);
718e3744 1107
0c0f9cd5 1108 /* Unlock the node. */
1109 rn->info = NULL;
1110 route_unlock_node (rn);
718e3744 1111 }
1112 route_table_finish (rtrs);
1113}
1114
075e12f5 1115#if 0
4dadc291 1116static void
718e3744 1117ospf_rtrs_print (struct route_table *rtrs)
1118{
1119 struct route_node *rn;
52dc7ee6 1120 struct list *or_list;
1121 struct listnode *ln;
1122 struct listnode *pnode;
718e3744 1123 struct ospf_route *or;
1124 struct ospf_path *path;
1125 char buf1[BUFSIZ];
1126 char buf2[BUFSIZ];
1127
1128 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1129 zlog_debug ("ospf_rtrs_print() start");
718e3744 1130
1131 for (rn = route_top (rtrs); rn; rn = route_next (rn))
1132 if ((or_list = rn->info) != NULL)
1eb8ef25 1133 for (ALL_LIST_ELEMENTS_RO (or_list, ln, or))
718e3744 1134 {
718e3744 1135 switch (or->path_type)
1136 {
1137 case OSPF_PATH_INTRA_AREA:
0c0f9cd5 1138 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1139 zlog_debug ("%s [%d] area: %s",
0c0f9cd5 1140 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1141 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1142 buf2, BUFSIZ));
718e3744 1143 break;
1144 case OSPF_PATH_INTER_AREA:
0c0f9cd5 1145 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1146 zlog_debug ("%s IA [%d] area: %s",
0c0f9cd5 1147 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1148 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1149 buf2, BUFSIZ));
718e3744 1150 break;
1151 default:
1152 break;
1153 }
1154
1eb8ef25 1155 for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path))
718e3744 1156 {
718e3744 1157 if (path->nexthop.s_addr == 0)
0c0f9cd5 1158 {
1159 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1160 zlog_debug (" directly attached to %s\r\n",
a8ba847f 1161 ifindex2ifname (path->ifindex));
0c0f9cd5 1162 }
1163 else
1164 {
1165 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1166 zlog_debug (" via %s, %s\r\n",
a8ba847f
JT
1167 inet_ntoa (path->nexthop),
1168 ifindex2ifname (path->ifindex));
0c0f9cd5 1169 }
718e3744 1170 }
1171 }
1172
2a42e285 1173 zlog_debug ("ospf_rtrs_print() end");
718e3744 1174}
075e12f5 1175#endif
718e3744 1176
1177/* Calculating the shortest-path tree for an area. */
4dadc291 1178static void
0c0f9cd5 1179ospf_spf_calculate (struct ospf_area *area, struct route_table *new_table,
718e3744 1180 struct route_table *new_rtrs)
1181{
462f20d5 1182 struct pqueue *candidate;
718e3744 1183 struct vertex *v;
eb3da6df 1184
718e3744 1185 if (IS_DEBUG_OSPF_EVENT)
1186 {
2a42e285 1187 zlog_debug ("ospf_spf_calculate: Start");
1188 zlog_debug ("ospf_spf_calculate: running Dijkstra for area %s",
0c0f9cd5 1189 inet_ntoa (area->area_id));
718e3744 1190 }
1191
1192 /* Check router-lsa-self. If self-router-lsa is not yet allocated,
1193 return this area's calculation. */
0c0f9cd5 1194 if (!area->router_lsa_self)
718e3744 1195 {
1196 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1197 zlog_debug ("ospf_spf_calculate: "
0c0f9cd5 1198 "Skip area %s's calculation due to empty router_lsa_self",
1199 inet_ntoa (area->area_id));
718e3744 1200 return;
1201 }
1202
1203 /* RFC2328 16.1. (1). */
0c0f9cd5 1204 /* Initialize the algorithm's data structures. */
462f20d5 1205
1206 /* This function scans all the LSA database and set the stat field to
1207 * LSA_SPF_NOT_EXPLORED. */
1208 ospf_lsdb_clean_stat (area->lsdb);
1209 /* Create a new heap for the candidates. */
1210 candidate = pqueue_create();
1211 candidate->cmp = cmp;
1212 candidate->update = update_stat;
718e3744 1213
1214 /* Initialize the shortest-path tree to only the root (which is the
1215 router doing the calculation). */
1216 ospf_spf_init (area);
1217 v = area->spf;
462f20d5 1218 /* Set LSA position to LSA_SPF_IN_SPFTREE. This vertex is the root of the
1219 * spanning tree. */
1220 *(v->stat) = LSA_SPF_IN_SPFTREE;
718e3744 1221
1222 /* Set Area A's TransitCapability to FALSE. */
1223 area->transit = OSPF_TRANSIT_FALSE;
1224 area->shortcut_capability = 1;
eb3da6df 1225
718e3744 1226 for (;;)
1227 {
1228 /* RFC2328 16.1. (2). */
462f20d5 1229 ospf_spf_next (v, area, candidate);
718e3744 1230
1231 /* RFC2328 16.1. (3). */
1232 /* If at this step the candidate list is empty, the shortest-
1233 path tree (of transit vertices) has been completely built and
1234 this stage of the procedure terminates. */
462f20d5 1235 if (candidate->size == 0)
718e3744 1236 break;
1237
1238 /* Otherwise, choose the vertex belonging to the candidate list
1239 that is closest to the root, and add it to the shortest-path
1240 tree (removing it from the candidate list in the
0c0f9cd5 1241 process). */
462f20d5 1242 /* Extract from the candidates the node with the lower key. */
1243 v = (struct vertex *) pqueue_dequeue (candidate);
1244 /* Update stat field in vertex. */
1245 *(v->stat) = LSA_SPF_IN_SPFTREE;
eb3da6df 1246
718e3744 1247 ospf_vertex_add_parent (v);
1248
718e3744 1249 /* RFC2328 16.1. (4). */
1250 if (v->type == OSPF_VERTEX_ROUTER)
1251 ospf_intra_add_router (new_rtrs, v, area);
0c0f9cd5 1252 else
718e3744 1253 ospf_intra_add_transit (new_table, v, area);
1254
1255 /* RFC2328 16.1. (5). */
1256 /* Iterate the algorithm by returning to Step 2. */
630e4807 1257
1258 } /* end loop until no more candidate vertices */
718e3744 1259
1260 if (IS_DEBUG_OSPF_EVENT)
1261 {
1262 ospf_spf_dump (area->spf, 0);
1263 ospf_route_table_dump (new_table);
1264 }
1265
1266 /* Second stage of SPF calculation procedure's */
b3bc68e5 1267 ospf_spf_process_stubs (area, area->spf, new_table, 0);
718e3744 1268
eb3da6df 1269 /* Free candidate queue. */
462f20d5 1270 pqueue_delete (candidate);
cf744958 1271
eb3da6df 1272 ospf_vertex_dump (__func__, area->spf, 0, 1);
1273 /* Free nexthop information, canonical versions of which are attached
1274 * the first level of router vertices attached to the root vertex, see
1275 * ospf_nexthop_calculation.
1276 */
1277 ospf_canonical_nexthops_free (area->spf);
cf744958 1278
718e3744 1279 /* Increment SPF Calculation Counter. */
1280 area->spf_calculation++;
1281
2518efd1 1282 quagga_gettime (QUAGGA_CLK_MONOTONIC, &area->ospf->ts_spf);
cf744958 1283 area->ts_spf = area->ospf->ts_spf;
718e3744 1284
1285 if (IS_DEBUG_OSPF_EVENT)
4fede82a 1286 zlog_debug ("ospf_spf_calculate: Stop. %zd vertices",
9c27ef9b 1287 mtype_stats_alloc(MTYPE_OSPF_VERTEX));
cf744958
DS
1288
1289 /* Free SPF vertices, but not the list. List has ospf_vertex_free
1290 * as deconstructor.
1291 */
1292 list_delete_all_node (&vertex_list);
718e3744 1293}
6b0655a2 1294
718e3744 1295/* Timer for SPF calculation. */
4dadc291 1296static int
68980084 1297ospf_spf_calculate_timer (struct thread *thread)
718e3744 1298{
68980084 1299 struct ospf *ospf = THREAD_ARG (thread);
718e3744 1300 struct route_table *new_table, *new_rtrs;
1eb8ef25 1301 struct ospf_area *area;
1302 struct listnode *node, *nnode;
cf744958
DS
1303 struct timeval start_time, stop_time, spf_start_time;
1304 int areas_processed = 0;
1305 unsigned long ia_time, prune_time, rt_time;
1306 unsigned long abr_time, total_spf_time, spf_time;
1307 char rbuf[32]; /* reason_buf */
d3a9c768 1308
718e3744 1309 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1310 zlog_debug ("SPF: Timer (SPF calculation expire)");
0c0f9cd5 1311
718e3744 1312 ospf->t_spf_calc = NULL;
1313
cf744958 1314 quagga_gettime (QUAGGA_CLK_MONOTONIC, &spf_start_time);
718e3744 1315 /* Allocate new table tree. */
1316 new_table = route_table_init ();
0c0f9cd5 1317 new_rtrs = route_table_init ();
718e3744 1318
68980084 1319 ospf_vl_unapprove (ospf);
718e3744 1320
1321 /* Calculate SPF for each area. */
1eb8ef25 1322 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
9c27ef9b
PJ
1323 {
1324 /* Do backbone last, so as to first discover intra-area paths
1325 * for any back-bone virtual-links
1326 */
1327 if (ospf->backbone && ospf->backbone == area)
1328 continue;
cf744958 1329
9c27ef9b 1330 ospf_spf_calculate (area, new_table, new_rtrs);
cf744958 1331 areas_processed++;
9c27ef9b 1332 }
cf744958 1333
9c27ef9b
PJ
1334 /* SPF for backbone, if required */
1335 if (ospf->backbone)
cf744958
DS
1336 {
1337 ospf_spf_calculate (ospf->backbone, new_table, new_rtrs);
1338 areas_processed++;
1339 }
1340
1341 quagga_gettime (QUAGGA_CLK_MONOTONIC, &stop_time);
1342 spf_time = timeval_elapsed (stop_time, spf_start_time);
1343
68980084 1344 ospf_vl_shut_unapproved (ospf);
718e3744 1345
cf744958
DS
1346 start_time = stop_time; /* saving a call */
1347
68980084 1348 ospf_ia_routing (ospf, new_table, new_rtrs);
718e3744 1349
cf744958
DS
1350 quagga_gettime (QUAGGA_CLK_MONOTONIC, &stop_time);
1351 ia_time = timeval_elapsed (stop_time, start_time);
1352
1353 quagga_gettime (QUAGGA_CLK_MONOTONIC, &start_time);
718e3744 1354 ospf_prune_unreachable_networks (new_table);
1355 ospf_prune_unreachable_routers (new_rtrs);
1356
cf744958
DS
1357 quagga_gettime (QUAGGA_CLK_MONOTONIC, &stop_time);
1358 prune_time = timeval_elapsed (stop_time, start_time);
718e3744 1359 /* AS-external-LSA calculation should not be performed here. */
1360
1361 /* If new Router Route is installed,
1362 then schedule re-calculate External routes. */
1363 if (1)
68980084 1364 ospf_ase_calculate_schedule (ospf);
718e3744 1365
68980084 1366 ospf_ase_calculate_timer_add (ospf);
718e3744 1367
cf744958
DS
1368 quagga_gettime (QUAGGA_CLK_MONOTONIC, &start_time);
1369
718e3744 1370 /* Update routing table. */
68980084 1371 ospf_route_install (ospf, new_table);
718e3744 1372
cf744958
DS
1373 quagga_gettime (QUAGGA_CLK_MONOTONIC, &stop_time);
1374 rt_time = timeval_elapsed (stop_time, start_time);
718e3744 1375 /* Update ABR/ASBR routing table */
68980084 1376 if (ospf->old_rtrs)
718e3744 1377 {
1378 /* old_rtrs's node holds linked list of ospf_route. --kunihiro. */
68980084 1379 /* ospf_route_delete (ospf->old_rtrs); */
1380 ospf_rtrs_free (ospf->old_rtrs);
718e3744 1381 }
1382
68980084 1383 ospf->old_rtrs = ospf->new_rtrs;
1384 ospf->new_rtrs = new_rtrs;
718e3744 1385
cf744958 1386 quagga_gettime (QUAGGA_CLK_MONOTONIC, &start_time);
0c0f9cd5 1387 if (IS_OSPF_ABR (ospf))
68980084 1388 ospf_abr_task (ospf);
718e3744 1389
cf744958
DS
1390 quagga_gettime (QUAGGA_CLK_MONOTONIC, &stop_time);
1391 abr_time = timeval_elapsed (stop_time, start_time);
1392
1393 quagga_gettime (QUAGGA_CLK_MONOTONIC, &stop_time);
1394 total_spf_time = timeval_elapsed (stop_time, spf_start_time);
1395 ospf->ts_spf_duration.tv_sec = total_spf_time/1000000;
1396 ospf->ts_spf_duration.tv_usec = total_spf_time % 1000000;
1397
1398 ospf_get_spf_reason_str (rbuf);
1399
d3a9c768
PJ
1400 if (IS_DEBUG_OSPF_EVENT)
1401 {
1402 zlog_info ("SPF Processing Time(usecs): %ld", total_spf_time);
1403 zlog_info ("\t SPF Time: %ld", spf_time);
1404 zlog_info ("\t InterArea: %ld", ia_time);
1405 zlog_info ("\t Prune: %ld", prune_time);
1406 zlog_info ("\tRouteInstall: %ld", rt_time);
1407 if (IS_OSPF_ABR (ospf))
1408 zlog_info ("\t ABR: %ld (%d areas)",
1409 abr_time, areas_processed);
1410 zlog_info ("Reason(s) for SPF: %s", rbuf);
1411 }
cf744958
DS
1412
1413 ospf_clear_spf_reason_flags ();
718e3744 1414
1415 return 0;
1416}
1417
1418/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
1419 set timer for SPF calc. */
1420void
d3a9c768 1421ospf_spf_calculate_schedule (struct ospf *ospf, ospf_spf_reason_t reason)
718e3744 1422{
d24f6e2a 1423 unsigned long delay, elapsed, ht;
1424 struct timeval result;
718e3744 1425
1426 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1427 zlog_debug ("SPF: calculation timer scheduled");
718e3744 1428
1429 /* OSPF instance does not exist. */
68980084 1430 if (ospf == NULL)
718e3744 1431 return;
d24f6e2a 1432
d3a9c768
PJ
1433 ospf_spf_set_reason (reason);
1434
718e3744 1435 /* SPF calculation timer is already scheduled. */
68980084 1436 if (ospf->t_spf_calc)
718e3744 1437 {
1438 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1439 zlog_debug ("SPF: calculation timer is already scheduled: %p",
6c4f4e6e 1440 (void *)ospf->t_spf_calc);
718e3744 1441 return;
1442 }
d24f6e2a 1443
1444 /* XXX Monotic timers: we only care about relative time here. */
2518efd1 1445 result = tv_sub (recent_relative_time (), ospf->ts_spf);
d24f6e2a 1446
1447 elapsed = (result.tv_sec * 1000) + (result.tv_usec / 1000);
1448 ht = ospf->spf_holdtime * ospf->spf_hold_multiplier;
1449
1450 if (ht > ospf->spf_max_holdtime)
1451 ht = ospf->spf_max_holdtime;
1452
718e3744 1453 /* Get SPF calculation delay time. */
d24f6e2a 1454 if (elapsed < ht)
718e3744 1455 {
d24f6e2a 1456 /* Got an event within the hold time of last SPF. We need to
1457 * increase the hold_multiplier, if it's not already at/past
1458 * maximum value, and wasn't already increased..
1459 */
1460 if (ht < ospf->spf_max_holdtime)
1461 ospf->spf_hold_multiplier++;
1462
1463 /* always honour the SPF initial delay */
1464 if ( (ht - elapsed) < ospf->spf_delay)
0c0f9cd5 1465 delay = ospf->spf_delay;
718e3744 1466 else
d24f6e2a 1467 delay = ht - elapsed;
718e3744 1468 }
1469 else
d24f6e2a 1470 {
1471 /* Event is past required hold-time of last SPF */
1472 delay = ospf->spf_delay;
1473 ospf->spf_hold_multiplier = 1;
1474 }
1475
718e3744 1476 if (IS_DEBUG_OSPF_EVENT)
d24f6e2a 1477 zlog_debug ("SPF: calculation timer delay = %ld", delay);
1478
cf744958
DS
1479 zlog_info ("SPF: Scheduled in %ld msec", delay);
1480
68980084 1481 ospf->t_spf_calc =
d24f6e2a 1482 thread_add_timer_msec (master, ospf_spf_calculate_timer, ospf, delay);
718e3744 1483}