]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_spf.c
Added -p to the recommended diff flags.
[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
49#define DEBUG
50
462f20d5 51/* Heap related functions, for the managment of the candidates, to
52 * be used with pqueue. */
53static int
54cmp (void * node1 , void * node2)
55{
56 struct vertex * v1 = (struct vertex *) node1;
57 struct vertex * v2 = (struct vertex *) node2;
58 if (v1 != NULL && v2 != NULL )
59 return (v1->distance - v2->distance);
60 else
61 return 0;
62}
63
64static void
65update_stat (void * node , int position)
66{
67 struct vertex * v = (struct vertex *) node;
68 /* Set the status of the vertex, when its position changes. */
69 *(v->stat) = position;
70}
71/* End of the heap related functions. */
72
718e3744 73struct vertex_nexthop *
74vertex_nexthop_new (struct vertex *parent)
75{
76 struct vertex_nexthop *new;
77
78 new = XCALLOC (MTYPE_OSPF_NEXTHOP, sizeof (struct vertex_nexthop));
79 new->parent = parent;
80
81 return new;
82}
83
84void
85vertex_nexthop_free (struct vertex_nexthop *nh)
86{
87 XFREE (MTYPE_OSPF_NEXTHOP, nh);
88}
89
90struct vertex_nexthop *
91vertex_nexthop_dup (struct vertex_nexthop *nh)
92{
93 struct vertex_nexthop *new;
94
95 new = vertex_nexthop_new (nh->parent);
96
97 new->oi = nh->oi;
98 new->router = nh->router;
99
100 return new;
101}
718e3744 102\f
0c0f9cd5 103
718e3744 104struct vertex *
105ospf_vertex_new (struct ospf_lsa *lsa)
106{
107 struct vertex *new;
108
109 new = XMALLOC (MTYPE_OSPF_VERTEX, sizeof (struct vertex));
110 memset (new, 0, sizeof (struct vertex));
111
112 new->flags = 0;
462f20d5 113 new->stat = &(lsa->stat);
718e3744 114 new->type = lsa->data->type;
115 new->id = lsa->data->id;
116 new->lsa = lsa->data;
117 new->distance = 0;
118 new->child = list_new ();
119 new->nexthop = list_new ();
d355bfa7 120 new->backlink = -1;
718e3744 121
122 return new;
123}
124
125void
126ospf_vertex_free (struct vertex *v)
127{
52dc7ee6 128 struct listnode *node;
718e3744 129
130 list_delete (v->child);
131
132 if (listcount (v->nexthop) > 0)
133 for (node = listhead (v->nexthop); node; nextnode (node))
134 vertex_nexthop_free (node->data);
135
136 list_delete (v->nexthop);
137
138 XFREE (MTYPE_OSPF_VERTEX, v);
139}
140
630e4807 141void
eb1ce605 142ospf_vertex_dump(const char *msg, struct vertex *v,
630e4807 143 int print_nexthops, int print_children)
144{
145 if ( ! IS_DEBUG_OSPF_EVENT)
146 return;
147
2a42e285 148 zlog_debug("%s %s vertex %s distance %u backlink %d flags %u",
630e4807 149 msg,
150 v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
151 inet_ntoa(v->lsa->id),
152 v->distance,
153 v->backlink,
154 (unsigned int)v->flags);
155
156 if (print_nexthops)
157 {
52dc7ee6 158 struct listnode *nnode;
630e4807 159 for (nnode = listhead (v->nexthop); nnode; nextnode (nnode))
160 {
161 char buf1[BUFSIZ];
162 char buf2[BUFSIZ];
163 struct vertex_nexthop *nexthop;
164
165 nexthop = getdata (nnode);
166 if (nexthop)
167 {
2a42e285 168 zlog_debug (" nexthop %s interface %s parent %s",
630e4807 169 inet_ntop(AF_INET, &nexthop->router, buf1, BUFSIZ),
170 nexthop->oi ? IF_NAME(nexthop->oi) : "NULL",
171 nexthop->parent ? inet_ntop(AF_INET,
172 &nexthop->parent->id,
173 buf2, BUFSIZ)
174 : "NULL");
175 }
176 }
177 }
178
179 if (print_children)
180 {
52dc7ee6 181 struct listnode *cnode;
630e4807 182 for (cnode = listhead (v->child); cnode; nextnode (cnode))
183 {
184 struct vertex *cv = getdata (cnode);
185 if (cv)
186 ospf_vertex_dump(" child:", cv, 0, 0);
187 }
188 }
189}
190
191
192/* Add a vertex to the list of children in each of its parents. */
718e3744 193void
194ospf_vertex_add_parent (struct vertex *v)
195{
196 struct vertex_nexthop *nh;
52dc7ee6 197 struct listnode *node;
718e3744 198
199 for (node = listhead (v->nexthop); node; nextnode (node))
200 {
201 nh = (struct vertex_nexthop *) getdata (node);
202
203 /* No need to add two links from the same parent. */
204 if (listnode_lookup (nh->parent->child, v) == NULL)
0c0f9cd5 205 listnode_add (nh->parent->child, v);
718e3744 206 }
207}
208\f
209void
210ospf_spf_init (struct ospf_area *area)
211{
212 struct vertex *v;
213
214 /* Create root node. */
215 v = ospf_vertex_new (area->router_lsa_self);
216
217 area->spf = v;
218
219 /* Reset ABR and ASBR router counts. */
220 area->abr_count = 0;
221 area->asbr_count = 0;
222}
223
d355bfa7 224/* return index of link back to V from W, or -1 if no link found */
718e3744 225int
226ospf_lsa_has_link (struct lsa_header *w, struct lsa_header *v)
227{
eb1ce605 228 unsigned int i, length;
718e3744 229 struct router_lsa *rl;
230 struct network_lsa *nl;
231
232 /* In case of W is Network LSA. */
233 if (w->type == OSPF_NETWORK_LSA)
234 {
235 if (v->type == OSPF_NETWORK_LSA)
d355bfa7 236 return -1;
718e3744 237
238 nl = (struct network_lsa *) w;
239 length = (ntohs (w->length) - OSPF_LSA_HEADER_SIZE - 4) / 4;
0c0f9cd5 240
718e3744 241 for (i = 0; i < length; i++)
242 if (IPV4_ADDR_SAME (&nl->routers[i], &v->id))
d355bfa7 243 return i;
244 return -1;
718e3744 245 }
246
247 /* In case of W is Router LSA. */
248 if (w->type == OSPF_ROUTER_LSA)
249 {
250 rl = (struct router_lsa *) w;
251
252 length = ntohs (w->length);
253
254 for (i = 0;
0c0f9cd5 255 i < ntohs (rl->links) && length >= sizeof (struct router_lsa);
256 i++, length -= 12)
718e3744 257 {
258 switch (rl->link[i].type)
259 {
260 case LSA_LINK_TYPE_POINTOPOINT:
261 case LSA_LINK_TYPE_VIRTUALLINK:
262 /* Router LSA ID. */
263 if (v->type == OSPF_ROUTER_LSA &&
264 IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
265 {
d355bfa7 266 return i;
718e3744 267 }
268 break;
269 case LSA_LINK_TYPE_TRANSIT:
270 /* Network LSA ID. */
271 if (v->type == OSPF_NETWORK_LSA &&
272 IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
273 {
d355bfa7 274 return i;
0c0f9cd5 275 }
718e3744 276 break;
277 case LSA_LINK_TYPE_STUB:
278 /* Not take into count? */
279 continue;
280 default:
281 break;
282 }
283 }
284 }
d355bfa7 285 return -1;
718e3744 286}
287
288/* Add the nexthop to the list, only if it is unique.
289 * If it's not unique, free the nexthop entry.
290 */
291void
52dc7ee6 292ospf_nexthop_add_unique (struct vertex_nexthop *new, struct list *nexthop)
718e3744 293{
294 struct vertex_nexthop *nh;
52dc7ee6 295 struct listnode *node;
718e3744 296 int match;
297
298 match = 0;
299 for (node = listhead (nexthop); node; nextnode (node))
300 {
301 nh = node->data;
302
303 /* Compare the two entries. */
304 /* XXX
305 * Comparing the parent preserves the shortest path tree
306 * structure even when the nexthops are identical.
307 */
308 if (nh->oi == new->oi &&
0c0f9cd5 309 IPV4_ADDR_SAME (&nh->router, &new->router) &&
310 nh->parent == new->parent)
311 {
312 match = 1;
313 break;
314 }
718e3744 315 }
316
317 if (!match)
318 listnode_add (nexthop, new);
319 else
320 vertex_nexthop_free (new);
321}
322
323/* Merge entries in list b into list a. */
324void
52dc7ee6 325ospf_nexthop_merge (struct list *a, struct list *b)
718e3744 326{
327 struct listnode *n;
328
329 for (n = listhead (b); n; nextnode (n))
330 {
331 ospf_nexthop_add_unique (n->data, a);
332 }
333}
334
335#define ROUTER_LSA_MIN_SIZE 12
336#define ROUTER_LSA_TOS_SIZE 4
337
630e4807 338/* Find the next link after prev_link from v to w. If prev_link is
339 * NULL, return the first link from v to w. Ignore stub and virtual links;
340 * these link types will never be returned.
341 */
718e3744 342struct router_lsa_link *
343ospf_get_next_link (struct vertex *v, struct vertex *w,
0c0f9cd5 344 struct router_lsa_link *prev_link)
718e3744 345{
346 u_char *p;
347 u_char *lim;
348 struct router_lsa_link *l;
349
350 if (prev_link == NULL)
630e4807 351 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
718e3744 352 else
353 {
0c0f9cd5 354 p = (u_char *) prev_link;
718e3744 355 p += (ROUTER_LSA_MIN_SIZE +
356 (prev_link->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
357 }
0c0f9cd5 358
718e3744 359 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
360
361 while (p < lim)
362 {
363 l = (struct router_lsa_link *) p;
364
0c0f9cd5 365 p += (ROUTER_LSA_MIN_SIZE + (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
718e3744 366
367 if (l->m[0].type == LSA_LINK_TYPE_STUB)
368 continue;
369
370 /* Defer NH calculation via VLs until summaries from
371 transit areas area confidered */
372
373 if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK)
0c0f9cd5 374 continue;
718e3744 375
376 if (IPV4_ADDR_SAME (&l->link_id, &w->id))
0c0f9cd5 377 return l;
718e3744 378 }
379
380 return NULL;
381}
382
75ee0b8e 383/*
384 * Consider supplied next-hop for inclusion to the supplied list of
385 * equal-cost next-hops, adjust list as neccessary.
386 *
387 * (Discussed on GNU Zebra list 27 May 2003, [zebra 19184])
388 *
389 * Note that below is a bit of a hack, and limits ECMP to paths that go to
390 * same nexthop. Where as paths via inequal output_cost interfaces could
391 * still quite easily be ECMP due to remote cost differences.
392 *
393 * TODO: It really should be done by way of recording currently valid
394 * backlinks and determining the appropriate nexthops from the list of
395 * backlinks, or even simpler, just flushing nexthop list if we find a lower
396 * cost path to a candidate vertex in SPF, maybe.
bf9392c6 397 */
0c0f9cd5 398void
399ospf_spf_consider_nexthop (struct list *nexthops,
400 struct vertex_nexthop *newhop)
bf9392c6 401{
bf9392c6 402 struct vertex_nexthop *hop;
75ee0b8e 403 struct listnode *ln, *nn;
0c0f9cd5 404
75ee0b8e 405 /* nexthop list should contain only the set of nexthops that have the lowest
406 * equal cost
407 */
408 if (nexthops->head != NULL)
409 {
410 hop = getdata (nexthops->head);
411
412 /* weed out hops with higher cost than the newhop */
413 if (hop->oi->output_cost > newhop->oi->output_cost)
414 {
415 /* delete the existing nexthops */
416 for (ln = nexthops->head; ln; ln = nn)
417 {
418 nn = ln->next;
419 hop = getdata (ln);
420
421 listnode_delete (nexthops, hop);
422 vertex_nexthop_free (hop);
423 }
424 }
425 else if (hop->oi->output_cost < newhop->oi->output_cost)
0c0f9cd5 426 return;
75ee0b8e 427 }
0c0f9cd5 428
bf9392c6 429 /* new hop is <= existing hops, add it */
0c0f9cd5 430 listnode_add (nexthops, newhop);
bf9392c6 431
432 return;
433}
434
630e4807 435/* 16.1.1. Calculate nexthop from root through V (parent) to
436 * vertex W (destination).
437 */
718e3744 438void
439ospf_nexthop_calculation (struct ospf_area *area,
440 struct vertex *v, struct vertex *w)
441{
52dc7ee6 442 struct listnode *node;
718e3744 443 struct vertex_nexthop *nh, *x;
444 struct ospf_interface *oi = NULL;
445 struct router_lsa_link *l = NULL;
0c0f9cd5 446
447
718e3744 448 if (IS_DEBUG_OSPF_EVENT)
630e4807 449 {
2a42e285 450 zlog_debug ("ospf_nexthop_calculation(): Start");
630e4807 451 ospf_vertex_dump("V (parent):", v, 1, 1);
452 ospf_vertex_dump("W (dest) :", w, 1, 1);
453 }
718e3744 454
718e3744 455 if (v == area->spf)
456 {
630e4807 457 /* 16.1.1 para 4. In the first case, the parent vertex (V) is the
458 root (the calculating router itself). This means that the
459 destination is either a directly connected network or directly
460 connected router. The outgoing interface in this case is simply
461 the OSPF interface connecting to the destination network/router.
462 */
463
718e3744 464 if (w->type == OSPF_VERTEX_ROUTER)
0c0f9cd5 465 {
466 while ((l = ospf_get_next_link (v, w, l)))
467 {
630e4807 468 /* l is a link from v to w
469 * l2 will be link from w to v
470 */
0c0f9cd5 471 struct router_lsa_link *l2 = NULL;
472
630e4807 473 if (IS_DEBUG_OSPF_EVENT)
474 {
475 char buf1[BUFSIZ];
2a42e285 476 zlog_debug("ospf_nexthop_calculation(): considering link "
630e4807 477 "type %d link_id %s link_data %s",
478 l->m[0].type,
479 inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ),
480 inet_ntop (AF_INET, &l->link_data, buf1, BUFSIZ));
481 }
482
0c0f9cd5 483 if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT)
484 {
630e4807 485 /* If the destination is a router which connects to
486 the calculating router via a Point-to-MultiPoint
487 network, the destination's next hop IP address(es)
488 can be determined by examining the destination's
489 router-LSA: each link pointing back to the
490 calculating router and having a Link Data field
491 belonging to the Point-to-MultiPoint network
492 provides an IP address of the next hop router.
493
494 At this point l is a link from V to W, and V is the
495 root ("us"). Find the local interface associated
496 with l (its address is in l->link_data). If it
497 is a point-to-multipoint interface, then look through
498 the links in the opposite direction (W to V). If
499 any of them have an address that lands within the
500 subnet declared by the PtMP link, then that link
501 is a constituent of the PtMP link, and its address is
502 a nexthop address for V.
503 */
68980084 504 oi = ospf_if_is_configured (area->ospf, &l->link_data);
7afa08da 505 if (oi && oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
0c0f9cd5 506 {
507 struct prefix_ipv4 la;
630e4807 508
509 la.family = AF_INET;
0c0f9cd5 510 la.prefixlen = oi->address->prefixlen;
630e4807 511
512 /* V links to W on PtMP interface
513 - find the interface address on W */
0c0f9cd5 514 while ((l2 = ospf_get_next_link (w, v, l2)))
515 {
516 la.prefix = l2->link_data;
517
518 if (prefix_cmp ((struct prefix *) &la,
519 oi->address) == 0)
520 /* link_data is on our PtMP network */
521 break;
522 }
630e4807 523 } /* end l is on point-to-multipoint link */
0c0f9cd5 524 else
525 {
630e4807 526 /* l is a regular point-to-point link.
527 Look for a link from W to V.
528 */
0c0f9cd5 529 while ((l2 = ospf_get_next_link (w, v, l2)))
530 {
531 oi = ospf_if_is_configured (area->ospf,
532 &(l2->link_data));
533
534 if (oi == NULL)
535 continue;
536
537 if (!IPV4_ADDR_SAME (&oi->address->u.prefix4,
538 &l->link_data))
539 continue;
540
541 break;
542 }
543 }
544
545 if (oi && l2)
546 {
630e4807 547 /* found all necessary info to build nexthop */
0c0f9cd5 548 nh = vertex_nexthop_new (v);
549 nh->oi = oi;
550 nh->router = l2->link_data;
551 ospf_spf_consider_nexthop (w->nexthop, nh);
552 }
630e4807 553 else
554 {
555 zlog_info("ospf_nexthop_calculation(): "
556 "could not determine nexthop for link");
557 }
558 } /* end point-to-point link from V to W */
559 } /* end iterate over links in W */
560 } /* end W is a Router vertex */
718e3744 561 else
0c0f9cd5 562 {
630e4807 563 assert(w->type == OSPF_VERTEX_NETWORK);
0c0f9cd5 564 while ((l = ospf_get_next_link (v, w, l)))
565 {
566 oi = ospf_if_is_configured (area->ospf, &(l->link_data));
567 if (oi)
568 {
569 nh = vertex_nexthop_new (v);
570 nh->oi = oi;
571 nh->router.s_addr = 0;
75ee0b8e 572 ospf_spf_consider_nexthop (w->nexthop, nh);
0c0f9cd5 573 }
574 }
575 }
718e3744 576 return;
630e4807 577 } /* end V is the root */
578
579 /* Check if W's parent is a network connected to root. */
718e3744 580 else if (v->type == OSPF_VERTEX_NETWORK)
581 {
630e4807 582 /* See if any of V's parents are the root. */
718e3744 583 for (node = listhead (v->nexthop); node; nextnode (node))
584 {
630e4807 585 x = (struct vertex_nexthop *) getdata (node);
586 if (x->parent == area->spf) /* connects to root? */
587 {
588 /* 16.1.1 para 5. ...the parent vertex is a network that
589 * directly connects the calculating router to the destination
590 * router. The list of next hops is then determined by
591 * examining the destination's router-LSA...
592 */
593
594 assert(w->type == OSPF_VERTEX_ROUTER);
0c0f9cd5 595 while ((l = ospf_get_next_link (w, v, l)))
596 {
630e4807 597 /* ...For each link in the router-LSA that points back to the
598 * parent network, the link's Link Data field provides the IP
599 * address of a next hop router. The outgoing interface to
600 * use can then be derived from the next hop IP address (or
601 * it can be inherited from the parent network).
602 */
0c0f9cd5 603 nh = vertex_nexthop_new (v);
604 nh->oi = x->oi;
605 nh->router = l->link_data;
75ee0b8e 606 ospf_spf_consider_nexthop (w->nexthop, nh);
0c0f9cd5 607 }
608 return;
609 }
718e3744 610 }
611 }
612
630e4807 613 /* 16.1.1 para 4. If there is at least one intervening router in the
614 * current shortest path between the destination and the root, the
615 * destination simply inherits the set of next hops from the
616 * parent.
617 */
718e3744 618 for (node = listhead (v->nexthop); node; nextnode (node))
619 {
620 nh = vertex_nexthop_dup (node->data);
621 nh->parent = v;
622 ospf_nexthop_add_unique (nh, w->nexthop);
623 }
624}
625
630e4807 626/* RFC2328 Section 16.1 (2).
627 * v is on the SPF tree. Examine the links in v's LSA. Update the list
628 * of candidates with any vertices not already on the list. If a lower-cost
629 * path is found to a vertex already on the candidate list, store the new cost.
630 */
718e3744 631void
632ospf_spf_next (struct vertex *v, struct ospf_area *area,
462f20d5 633 struct pqueue * candidate)
718e3744 634{
635 struct ospf_lsa *w_lsa = NULL;
636 struct vertex *w, *cw;
637 u_char *p;
638 u_char *lim;
639 struct router_lsa_link *l = NULL;
640 struct in_addr *r;
718e3744 641 int type = 0;
642
643 /* If this is a router-LSA, and bit V of the router-LSA (see Section
644 A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE. */
645 if (v->type == OSPF_VERTEX_ROUTER)
646 {
647 if (IS_ROUTER_LSA_VIRTUAL ((struct router_lsa *) v->lsa))
648 area->transit = OSPF_TRANSIT_TRUE;
649 }
650
651 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
0c0f9cd5 652 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
653
718e3744 654 while (p < lim)
655 {
d355bfa7 656 int link = -1; /* link index for w's back link */
657
718e3744 658 /* In case of V is Router-LSA. */
659 if (v->lsa->type == OSPF_ROUTER_LSA)
660 {
661 l = (struct router_lsa_link *) p;
662
0c0f9cd5 663 p += (ROUTER_LSA_MIN_SIZE +
718e3744 664 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
665
666 /* (a) If this is a link to a stub network, examine the next
667 link in V's LSA. Links to stub networks will be
668 considered in the second stage of the shortest path
669 calculation. */
670 if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB)
671 continue;
672
673 /* (b) Otherwise, W is a transit vertex (router or transit
674 network). Look up the vertex W's LSA (router-LSA or
675 network-LSA) in Area A's link state database. */
676 switch (type)
677 {
678 case LSA_LINK_TYPE_POINTOPOINT:
679 case LSA_LINK_TYPE_VIRTUALLINK:
680 if (type == LSA_LINK_TYPE_VIRTUALLINK)
0c0f9cd5 681 {
682 if (IS_DEBUG_OSPF_EVENT)
2a42e285 683 zlog_debug ("looking up LSA through VL: %s",
0c0f9cd5 684 inet_ntoa (l->link_id));
685 }
718e3744 686
687 w_lsa = ospf_lsa_lookup (area, OSPF_ROUTER_LSA, l->link_id,
688 l->link_id);
689 if (w_lsa)
0c0f9cd5 690 {
691 if (IS_DEBUG_OSPF_EVENT)
2a42e285 692 zlog_debug ("found Router LSA %s", inet_ntoa (l->link_id));
0c0f9cd5 693 }
718e3744 694 break;
695 case LSA_LINK_TYPE_TRANSIT:
0c0f9cd5 696 if (IS_DEBUG_OSPF_EVENT)
2a42e285 697 zlog_debug ("Looking up Network LSA, ID: %s",
0c0f9cd5 698 inet_ntoa (l->link_id));
718e3744 699 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_NETWORK_LSA,
0c0f9cd5 700 l->link_id);
718e3744 701 if (w_lsa)
0c0f9cd5 702 if (IS_DEBUG_OSPF_EVENT)
2a42e285 703 zlog_debug ("found the LSA");
718e3744 704 break;
705 default:
0c0f9cd5 706 zlog_warn ("Invalid LSA link type %d", type);
718e3744 707 continue;
708 }
709 }
710 else
711 {
712 /* In case of V is Network-LSA. */
0c0f9cd5 713 r = (struct in_addr *) p;
718e3744 714 p += sizeof (struct in_addr);
715
716 /* Lookup the vertex W's LSA. */
717 w_lsa = ospf_lsa_lookup_by_id (area, OSPF_ROUTER_LSA, *r);
718 }
719
720 /* (b cont.) If the LSA does not exist, or its LS age is equal
721 to MaxAge, or it does not have a link back to vertex V,
722 examine the next link in V's LSA.[23] */
723 if (w_lsa == NULL)
724 continue;
725
726 if (IS_LSA_MAXAGE (w_lsa))
727 continue;
728
d355bfa7 729 if ( (link = ospf_lsa_has_link (w_lsa->data, v->lsa)) < 0 )
718e3744 730 {
0c0f9cd5 731 if (IS_DEBUG_OSPF_EVENT)
2a42e285 732 zlog_debug ("The LSA doesn't have a link back");
718e3744 733 continue;
734 }
735
736 /* (c) If vertex W is already on the shortest-path tree, examine
737 the next link in the LSA. */
462f20d5 738 if (w_lsa->stat == LSA_SPF_IN_SPFTREE)
739 {
740 if (IS_DEBUG_OSPF_EVENT)
741 zlog_debug ("The LSA is already in SPF");
742 continue;
743 }
718e3744 744
745 /* (d) Calculate the link state cost D of the resulting path
746 from the root to vertex W. D is equal to the sum of the link
747 state cost of the (already calculated) shortest path to
748 vertex V and the advertised cost of the link between vertices
749 V and W. If D is: */
750
751 /* prepare vertex W. */
752 w = ospf_vertex_new (w_lsa);
753
d355bfa7 754 /* Save W's back link index number, for use by virtual links */
755 w->backlink = link;
756
718e3744 757 /* calculate link cost D. */
758 if (v->lsa->type == OSPF_ROUTER_LSA)
630e4807 759 w->distance = v->distance + ntohs (l->m[0].metric);
760 else /* v is not a Router-LSA */
761 w->distance = v->distance;
718e3744 762
763 /* Is there already vertex W in candidate list? */
462f20d5 764 if (w_lsa->stat == LSA_SPF_NOT_EXPLORED)
765 {
766 /* Calculate nexthop to W. */
767 ospf_nexthop_calculation (area, v, w);
768 pqueue_enqueue (w, candidate);
769 }
770 else if (w_lsa->stat >= 0)
771 {
772 /* Get the vertex from candidates. */
773 cw = (struct vertex *) candidate->array[w_lsa->stat];
718e3744 774
462f20d5 775 /* if D is greater than. */
776 if (cw->distance < w->distance)
718e3744 777 {
778 ospf_vertex_free (w);
779 continue;
780 }
462f20d5 781 /* equal to. */
782 else if (cw->distance == w->distance)
718e3744 783 {
630e4807 784 /* Found an equal-cost path to W. Calculate nexthop to W. */
718e3744 785 ospf_nexthop_calculation (area, v, w);
786 ospf_nexthop_merge (cw->nexthop, w->nexthop);
787 list_delete_all_node (w->nexthop);
788 ospf_vertex_free (w);
789 }
462f20d5 790 /* less than. */
791 else
718e3744 792 {
630e4807 793 /* Found a lower-cost path to W. Calculate nexthop to W. */
718e3744 794 ospf_nexthop_calculation (area, v, w);
795
796 /* Remove old vertex from candidate list. */
797 ospf_vertex_free (cw);
462f20d5 798 candidate->array[w_lsa->stat] = w;
799 /* Decrease the key of the node in the heap, re-sort the heap. */
800 trickle_down (w_lsa->stat, candidate);
718e3744 801 }
630e4807 802 } /* end W is already on the candidate list */
803 } /* end loop over the links in V's LSA */
718e3744 804}
805
718e3744 806void
807ospf_spf_route_free (struct route_table *table)
808{
809 struct route_node *rn;
810 struct vertex *v;
811
812 for (rn = route_top (table); rn; rn = route_next (rn))
813 {
814 if ((v = rn->info))
0c0f9cd5 815 {
816 ospf_vertex_free (v);
817 rn->info = NULL;
818 }
718e3744 819
820 route_unlock_node (rn);
821 }
822
823 route_table_finish (table);
824}
825
826void
827ospf_spf_dump (struct vertex *v, int i)
828{
52dc7ee6 829 struct listnode *cnode;
830 struct listnode *nnode;
718e3744 831 struct vertex_nexthop *nexthop;
832
833 if (v->type == OSPF_VERTEX_ROUTER)
834 {
835 if (IS_DEBUG_OSPF_EVENT)
2a42e285 836 zlog_debug ("SPF Result: %d [R] %s", i, inet_ntoa (v->lsa->id));
718e3744 837 }
838 else
839 {
840 struct network_lsa *lsa = (struct network_lsa *) v->lsa;
841 if (IS_DEBUG_OSPF_EVENT)
2a42e285 842 zlog_debug ("SPF Result: %d [N] %s/%d", i, inet_ntoa (v->lsa->id),
0c0f9cd5 843 ip_masklen (lsa->mask));
630e4807 844 }
718e3744 845
630e4807 846 for (nnode = listhead (v->nexthop); nnode; nextnode (nnode))
847 {
848 nexthop = getdata (nnode);
849 if (IS_DEBUG_OSPF_EVENT)
2a42e285 850 zlog_debug (" nexthop %s", inet_ntoa (nexthop->router));
718e3744 851 }
852
853 i++;
854
855 for (cnode = listhead (v->child); cnode; nextnode (cnode))
856 {
857 v = getdata (cnode);
858 ospf_spf_dump (v, i);
859 }
860}
861
862/* Second stage of SPF calculation. */
863void
0c0f9cd5 864ospf_spf_process_stubs (struct ospf_area *area, struct vertex *v,
718e3744 865 struct route_table *rt)
866{
52dc7ee6 867 struct listnode *cnode;
718e3744 868 struct vertex *child;
869
870 if (IS_DEBUG_OSPF_EVENT)
2a42e285 871 zlog_debug ("ospf_process_stub():processing stubs for area %s",
0c0f9cd5 872 inet_ntoa (area->area_id));
718e3744 873 if (v->type == OSPF_VERTEX_ROUTER)
874 {
875 u_char *p;
876 u_char *lim;
877 struct router_lsa_link *l;
878 struct router_lsa *rlsa;
879
0c0f9cd5 880 if (IS_DEBUG_OSPF_EVENT)
2a42e285 881 zlog_debug ("ospf_process_stubs():processing router LSA, id: %s",
0c0f9cd5 882 inet_ntoa (v->lsa->id));
718e3744 883 rlsa = (struct router_lsa *) v->lsa;
884
885
0c0f9cd5 886 if (IS_DEBUG_OSPF_EVENT)
2a42e285 887 zlog_debug ("ospf_process_stubs(): we have %d links to process",
0c0f9cd5 888 ntohs (rlsa->links));
630e4807 889 p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
718e3744 890 lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
891
892 while (p < lim)
893 {
894 l = (struct router_lsa_link *) p;
895
896 p += (ROUTER_LSA_MIN_SIZE +
897 (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
898
899 if (l->m[0].type == LSA_LINK_TYPE_STUB)
900 ospf_intra_add_stub (rt, l, v, area);
901 }
902 }
903
630e4807 904 ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1, 1);
718e3744 905
906 for (cnode = listhead (v->child); cnode; nextnode (cnode))
907 {
908 child = getdata (cnode);
909
910 if (CHECK_FLAG (child->flags, OSPF_VERTEX_PROCESSED))
0c0f9cd5 911 continue;
718e3744 912
913 ospf_spf_process_stubs (area, child, rt);
914
915 SET_FLAG (child->flags, OSPF_VERTEX_PROCESSED);
916 }
917}
918
919void
920ospf_rtrs_free (struct route_table *rtrs)
921{
922 struct route_node *rn;
52dc7ee6 923 struct list *or_list;
924 struct listnode *node;
718e3744 925
926 if (IS_DEBUG_OSPF_EVENT)
2a42e285 927 zlog_debug ("Route: Router Routing Table free");
718e3744 928
929 for (rn = route_top (rtrs); rn; rn = route_next (rn))
930 if ((or_list = rn->info) != NULL)
931 {
0c0f9cd5 932 for (node = listhead (or_list); node; nextnode (node))
933 ospf_route_free (node->data);
718e3744 934
0c0f9cd5 935 list_delete (or_list);
718e3744 936
0c0f9cd5 937 /* Unlock the node. */
938 rn->info = NULL;
939 route_unlock_node (rn);
718e3744 940 }
941 route_table_finish (rtrs);
942}
943
944void
945ospf_rtrs_print (struct route_table *rtrs)
946{
947 struct route_node *rn;
52dc7ee6 948 struct list *or_list;
949 struct listnode *ln;
950 struct listnode *pnode;
718e3744 951 struct ospf_route *or;
952 struct ospf_path *path;
953 char buf1[BUFSIZ];
954 char buf2[BUFSIZ];
955
956 if (IS_DEBUG_OSPF_EVENT)
2a42e285 957 zlog_debug ("ospf_rtrs_print() start");
718e3744 958
959 for (rn = route_top (rtrs); rn; rn = route_next (rn))
960 if ((or_list = rn->info) != NULL)
961 for (ln = listhead (or_list); ln; nextnode (ln))
962 {
963 or = getdata (ln);
964
965 switch (or->path_type)
966 {
967 case OSPF_PATH_INTRA_AREA:
0c0f9cd5 968 if (IS_DEBUG_OSPF_EVENT)
2a42e285 969 zlog_debug ("%s [%d] area: %s",
0c0f9cd5 970 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
971 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
972 buf2, BUFSIZ));
718e3744 973 break;
974 case OSPF_PATH_INTER_AREA:
0c0f9cd5 975 if (IS_DEBUG_OSPF_EVENT)
2a42e285 976 zlog_debug ("%s IA [%d] area: %s",
0c0f9cd5 977 inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
978 or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
979 buf2, BUFSIZ));
718e3744 980 break;
981 default:
982 break;
983 }
984
96735eea 985 for (pnode = listhead (or->paths); pnode; nextnode (pnode))
718e3744 986 {
987 path = getdata (pnode);
988 if (path->nexthop.s_addr == 0)
0c0f9cd5 989 {
990 if (IS_DEBUG_OSPF_EVENT)
2a42e285 991 zlog_debug (" directly attached to %s\r\n",
0c0f9cd5 992 IF_NAME (path->oi));
993 }
994 else
995 {
996 if (IS_DEBUG_OSPF_EVENT)
2a42e285 997 zlog_debug (" via %s, %s\r\n",
0c0f9cd5 998 inet_ntoa (path->nexthop), IF_NAME (path->oi));
999 }
718e3744 1000 }
1001 }
1002
2a42e285 1003 zlog_debug ("ospf_rtrs_print() end");
718e3744 1004}
1005
1006/* Calculating the shortest-path tree for an area. */
1007void
0c0f9cd5 1008ospf_spf_calculate (struct ospf_area *area, struct route_table *new_table,
718e3744 1009 struct route_table *new_rtrs)
1010{
462f20d5 1011 struct pqueue *candidate;
718e3744 1012 struct vertex *v;
718e3744 1013
1014 if (IS_DEBUG_OSPF_EVENT)
1015 {
2a42e285 1016 zlog_debug ("ospf_spf_calculate: Start");
1017 zlog_debug ("ospf_spf_calculate: running Dijkstra for area %s",
0c0f9cd5 1018 inet_ntoa (area->area_id));
718e3744 1019 }
1020
1021 /* Check router-lsa-self. If self-router-lsa is not yet allocated,
1022 return this area's calculation. */
0c0f9cd5 1023 if (!area->router_lsa_self)
718e3744 1024 {
1025 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1026 zlog_debug ("ospf_spf_calculate: "
0c0f9cd5 1027 "Skip area %s's calculation due to empty router_lsa_self",
1028 inet_ntoa (area->area_id));
718e3744 1029 return;
1030 }
1031
1032 /* RFC2328 16.1. (1). */
0c0f9cd5 1033 /* Initialize the algorithm's data structures. */
462f20d5 1034
1035 /* This function scans all the LSA database and set the stat field to
1036 * LSA_SPF_NOT_EXPLORED. */
1037 ospf_lsdb_clean_stat (area->lsdb);
1038 /* Create a new heap for the candidates. */
1039 candidate = pqueue_create();
1040 candidate->cmp = cmp;
1041 candidate->update = update_stat;
718e3744 1042
1043 /* Initialize the shortest-path tree to only the root (which is the
1044 router doing the calculation). */
1045 ospf_spf_init (area);
1046 v = area->spf;
462f20d5 1047 /* Set LSA position to LSA_SPF_IN_SPFTREE. This vertex is the root of the
1048 * spanning tree. */
1049 *(v->stat) = LSA_SPF_IN_SPFTREE;
718e3744 1050
1051 /* Set Area A's TransitCapability to FALSE. */
1052 area->transit = OSPF_TRANSIT_FALSE;
1053 area->shortcut_capability = 1;
1054
1055 for (;;)
1056 {
1057 /* RFC2328 16.1. (2). */
462f20d5 1058 ospf_spf_next (v, area, candidate);
718e3744 1059
1060 /* RFC2328 16.1. (3). */
1061 /* If at this step the candidate list is empty, the shortest-
1062 path tree (of transit vertices) has been completely built and
1063 this stage of the procedure terminates. */
462f20d5 1064 if (candidate->size == 0)
718e3744 1065 break;
1066
1067 /* Otherwise, choose the vertex belonging to the candidate list
1068 that is closest to the root, and add it to the shortest-path
1069 tree (removing it from the candidate list in the
0c0f9cd5 1070 process). */
462f20d5 1071 /* Extract from the candidates the node with the lower key. */
1072 v = (struct vertex *) pqueue_dequeue (candidate);
1073 /* Update stat field in vertex. */
1074 *(v->stat) = LSA_SPF_IN_SPFTREE;
718e3744 1075 ospf_vertex_add_parent (v);
1076
718e3744 1077 /* Note that when there is a choice of vertices closest to the
1078 root, network vertices must be chosen before router vertices
1079 in order to necessarily find all equal-cost paths. */
1080 /* We don't do this at this moment, we should add the treatment
1081 above codes. -- kunihiro. */
1082
1083 /* RFC2328 16.1. (4). */
1084 if (v->type == OSPF_VERTEX_ROUTER)
1085 ospf_intra_add_router (new_rtrs, v, area);
0c0f9cd5 1086 else
718e3744 1087 ospf_intra_add_transit (new_table, v, area);
1088
1089 /* RFC2328 16.1. (5). */
1090 /* Iterate the algorithm by returning to Step 2. */
630e4807 1091
1092 } /* end loop until no more candidate vertices */
718e3744 1093
1094 if (IS_DEBUG_OSPF_EVENT)
1095 {
1096 ospf_spf_dump (area->spf, 0);
1097 ospf_route_table_dump (new_table);
1098 }
1099
1100 /* Second stage of SPF calculation procedure's */
1101 ospf_spf_process_stubs (area, area->spf, new_table);
1102
462f20d5 1103 /* Free candidates. */
1104 pqueue_delete (candidate);
718e3744 1105
1106 /* Increment SPF Calculation Counter. */
1107 area->spf_calculation++;
1108
68980084 1109 area->ospf->ts_spf = time (NULL);
718e3744 1110
1111 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1112 zlog_debug ("ospf_spf_calculate: Stop");
718e3744 1113}
1114\f
1115/* Timer for SPF calculation. */
1116int
68980084 1117ospf_spf_calculate_timer (struct thread *thread)
718e3744 1118{
68980084 1119 struct ospf *ospf = THREAD_ARG (thread);
718e3744 1120 struct route_table *new_table, *new_rtrs;
52dc7ee6 1121 struct listnode *node;
718e3744 1122
1123 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1124 zlog_debug ("SPF: Timer (SPF calculation expire)");
0c0f9cd5 1125
718e3744 1126 ospf->t_spf_calc = NULL;
1127
1128 /* Allocate new table tree. */
1129 new_table = route_table_init ();
0c0f9cd5 1130 new_rtrs = route_table_init ();
718e3744 1131
68980084 1132 ospf_vl_unapprove (ospf);
718e3744 1133
1134 /* Calculate SPF for each area. */
1135 for (node = listhead (ospf->areas); node; node = nextnode (node))
1136 ospf_spf_calculate (node->data, new_table, new_rtrs);
1137
68980084 1138 ospf_vl_shut_unapproved (ospf);
718e3744 1139
68980084 1140 ospf_ia_routing (ospf, new_table, new_rtrs);
718e3744 1141
1142 ospf_prune_unreachable_networks (new_table);
1143 ospf_prune_unreachable_routers (new_rtrs);
1144
1145 /* AS-external-LSA calculation should not be performed here. */
1146
1147 /* If new Router Route is installed,
1148 then schedule re-calculate External routes. */
1149 if (1)
68980084 1150 ospf_ase_calculate_schedule (ospf);
718e3744 1151
68980084 1152 ospf_ase_calculate_timer_add (ospf);
718e3744 1153
1154 /* Update routing table. */
68980084 1155 ospf_route_install (ospf, new_table);
718e3744 1156
1157 /* Update ABR/ASBR routing table */
68980084 1158 if (ospf->old_rtrs)
718e3744 1159 {
1160 /* old_rtrs's node holds linked list of ospf_route. --kunihiro. */
68980084 1161 /* ospf_route_delete (ospf->old_rtrs); */
1162 ospf_rtrs_free (ospf->old_rtrs);
718e3744 1163 }
1164
68980084 1165 ospf->old_rtrs = ospf->new_rtrs;
1166 ospf->new_rtrs = new_rtrs;
718e3744 1167
0c0f9cd5 1168 if (IS_OSPF_ABR (ospf))
68980084 1169 ospf_abr_task (ospf);
718e3744 1170
1171 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1172 zlog_debug ("SPF: calculation complete");
718e3744 1173
1174 return 0;
1175}
1176
1177/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
1178 set timer for SPF calc. */
1179void
68980084 1180ospf_spf_calculate_schedule (struct ospf *ospf)
718e3744 1181{
1182 time_t ht, delay;
1183
1184 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1185 zlog_debug ("SPF: calculation timer scheduled");
718e3744 1186
1187 /* OSPF instance does not exist. */
68980084 1188 if (ospf == NULL)
718e3744 1189 return;
1190
1191 /* SPF calculation timer is already scheduled. */
68980084 1192 if (ospf->t_spf_calc)
718e3744 1193 {
1194 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1195 zlog_debug ("SPF: calculation timer is already scheduled: %p",
0c0f9cd5 1196 ospf->t_spf_calc);
718e3744 1197 return;
1198 }
1199
68980084 1200 ht = time (NULL) - ospf->ts_spf;
718e3744 1201
1202 /* Get SPF calculation delay time. */
68980084 1203 if (ht < ospf->spf_holdtime)
718e3744 1204 {
68980084 1205 if (ospf->spf_holdtime - ht < ospf->spf_delay)
0c0f9cd5 1206 delay = ospf->spf_delay;
718e3744 1207 else
0c0f9cd5 1208 delay = ospf->spf_holdtime - ht;
718e3744 1209 }
1210 else
68980084 1211 delay = ospf->spf_delay;
718e3744 1212
1213 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1214 zlog_debug ("SPF: calculation timer delay = %ld", (long)delay);
68980084 1215 ospf->t_spf_calc =
1216 thread_add_timer (master, ospf_spf_calculate_timer, ospf, delay);
718e3744 1217}