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