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