Annotation of embedaddon/quagga/ospfd/ospf_spf.c, revision 1.1.1.1
1.1 misho 1: /* OSPF SPF calculation.
2: Copyright (C) 1999, 2000 Kunihiro Ishiguro, Toshiaki Takada
3:
4: This file is part of GNU Zebra.
5:
6: GNU Zebra is free software; you can redistribute it and/or modify it
7: under the terms of the GNU General Public License as published by the
8: Free Software Foundation; either version 2, or (at your option) any
9: later version.
10:
11: GNU Zebra is distributed in the hope that it will be useful, but
12: WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14: General Public License for more details.
15:
16: You should have received a copy of the GNU General Public License
17: along with GNU Zebra; see the file COPYING. If not, write to the Free
18: Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19: 02111-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: #include "pqueue.h"
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: static void ospf_vertex_free (void *);
50: /* List of allocated vertices, to simplify cleanup of SPF.
51: * Not thread-safe obviously. If it ever needs to be, it'd have to be
52: * dynamically allocated at begin of ospf_spf_calculate
53: */
54: static struct list vertex_list = { .del = ospf_vertex_free };
55:
56: /* Heap related functions, for the managment of the candidates, to
57: * be used with pqueue. */
58: static int
59: cmp (void * node1 , void * node2)
60: {
61: struct vertex * v1 = (struct vertex *) node1;
62: struct vertex * v2 = (struct vertex *) node2;
63: if (v1 != NULL && v2 != NULL )
64: {
65: /* network vertices must be chosen before router vertices of same
66: * cost in order to find all shortest paths
67: */
68: if ( ((v1->distance - v2->distance) == 0)
69: && (v1->type != v2->type))
70: {
71: switch (v1->type)
72: {
73: case OSPF_VERTEX_NETWORK:
74: return -1;
75: case OSPF_VERTEX_ROUTER:
76: return 1;
77: }
78: }
79: else
80: return (v1->distance - v2->distance);
81: }
82: return 0;
83: }
84:
85: static void
86: update_stat (void *node , int position)
87: {
88: struct vertex *v = node;
89:
90: /* Set the status of the vertex, when its position changes. */
91: *(v->stat) = position;
92: }
93:
94: static struct vertex_nexthop *
95: vertex_nexthop_new (void)
96: {
97: return XCALLOC (MTYPE_OSPF_NEXTHOP, sizeof (struct vertex_nexthop));
98: }
99:
100: static void
101: vertex_nexthop_free (struct vertex_nexthop *nh)
102: {
103: XFREE (MTYPE_OSPF_NEXTHOP, nh);
104: }
105:
106: /* Free the canonical nexthop objects for an area, ie the nexthop objects
107: * attached to the first-hop router vertices, and any intervening network
108: * vertices.
109: */
110: static void
111: ospf_canonical_nexthops_free (struct vertex *root)
112: {
113: struct listnode *node, *nnode;
114: struct vertex *child;
115:
116: for (ALL_LIST_ELEMENTS (root->children, node, nnode, child))
117: {
118: struct listnode *n2, *nn2;
119: struct vertex_parent *vp;
120:
121: /* router vertices through an attached network each
122: * have a distinct (canonical / not inherited) nexthop
123: * which must be freed.
124: *
125: * A network vertex can only have router vertices as its
126: * children, so only one level of recursion is possible.
127: */
128: if (child->type == OSPF_VERTEX_NETWORK)
129: ospf_canonical_nexthops_free (child);
130:
131: /* Free child nexthops pointing back to this root vertex */
132: for (ALL_LIST_ELEMENTS (child->parents, n2, nn2, vp))
133: if (vp->parent == root && vp->nexthop)
134: vertex_nexthop_free (vp->nexthop);
135: }
136: }
137:
138: /* TODO: Parent list should be excised, in favour of maintaining only
139: * vertex_nexthop, with refcounts.
140: */
141: static struct vertex_parent *
142: vertex_parent_new (struct vertex *v, int backlink, struct vertex_nexthop *hop)
143: {
144: struct vertex_parent *new;
145:
146: new = XMALLOC (MTYPE_OSPF_VERTEX_PARENT, sizeof (struct vertex_parent));
147:
148: if (new == NULL)
149: return NULL;
150:
151: new->parent = v;
152: new->backlink = backlink;
153: new->nexthop = hop;
154: return new;
155: }
156:
157: static void
158: vertex_parent_free (void *p)
159: {
160: XFREE (MTYPE_OSPF_VERTEX_PARENT, p);
161: }
162:
163: static struct vertex *
164: ospf_vertex_new (struct ospf_lsa *lsa)
165: {
166: struct vertex *new;
167:
168: new = XCALLOC (MTYPE_OSPF_VERTEX, sizeof (struct vertex));
169:
170: new->flags = 0;
171: new->stat = &(lsa->stat);
172: new->type = lsa->data->type;
173: new->id = lsa->data->id;
174: new->lsa = lsa->data;
175: new->children = list_new ();
176: new->parents = list_new ();
177: new->parents->del = vertex_parent_free;
178:
179: listnode_add (&vertex_list, new);
180:
181: if (IS_DEBUG_OSPF_EVENT)
182: zlog_debug ("%s: Created %s vertex %s", __func__,
183: new->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
184: inet_ntoa (new->lsa->id));
185: return new;
186: }
187:
188: static void
189: ospf_vertex_free (void *data)
190: {
191: struct vertex *v = data;
192:
193: if (IS_DEBUG_OSPF_EVENT)
194: zlog_debug ("%s: Free %s vertex %s", __func__,
195: v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
196: inet_ntoa (v->lsa->id));
197:
198: /* There should be no parents potentially holding references to this vertex
199: * Children however may still be there, but presumably referenced by other
200: * vertices
201: */
202: //assert (listcount (v->parents) == 0);
203:
204: if (v->children)
205: list_delete (v->children);
206: v->children = NULL;
207:
208: if (v->parents)
209: list_delete (v->parents);
210: v->parents = NULL;
211:
212: v->lsa = NULL;
213:
214: XFREE (MTYPE_OSPF_VERTEX, v);
215: }
216:
217: static void
218: ospf_vertex_dump(const char *msg, struct vertex *v,
219: int print_parents, int print_children)
220: {
221: if ( ! IS_DEBUG_OSPF_EVENT)
222: return;
223:
224: zlog_debug("%s %s vertex %s distance %u flags %u",
225: msg,
226: v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
227: inet_ntoa(v->lsa->id),
228: v->distance,
229: (unsigned int)v->flags);
230:
231: if (print_parents)
232: {
233: struct listnode *node;
234: struct vertex_parent *vp;
235:
236: for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
237: {
238: char buf1[BUFSIZ];
239:
240: if (vp)
241: {
242: zlog_debug ("parent %s backlink %d nexthop %s interface %s",
243: inet_ntoa(vp->parent->lsa->id), vp->backlink,
244: inet_ntop(AF_INET, &vp->nexthop->router, buf1, BUFSIZ),
245: vp->nexthop->oi ? IF_NAME(vp->nexthop->oi) : "NULL");
246: }
247: }
248: }
249:
250: if (print_children)
251: {
252: struct listnode *cnode;
253: struct vertex *cv;
254:
255: for (ALL_LIST_ELEMENTS_RO (v->children, cnode, cv))
256: ospf_vertex_dump(" child:", cv, 0, 0);
257: }
258: }
259:
260:
261: /* Add a vertex to the list of children in each of its parents. */
262: static void
263: ospf_vertex_add_parent (struct vertex *v)
264: {
265: struct vertex_parent *vp;
266: struct listnode *node;
267:
268: assert (v && v->parents);
269:
270: for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
271: {
272: assert (vp->parent && vp->parent->children);
273:
274: /* No need to add two links from the same parent. */
275: if (listnode_lookup (vp->parent->children, v) == NULL)
276: listnode_add (vp->parent->children, v);
277: }
278: }
279:
280: static void
281: ospf_spf_init (struct ospf_area *area)
282: {
283: struct vertex *v;
284:
285: /* Create root node. */
286: v = ospf_vertex_new (area->router_lsa_self);
287:
288: area->spf = v;
289:
290: /* Reset ABR and ASBR router counts. */
291: area->abr_count = 0;
292: area->asbr_count = 0;
293: }
294:
295: /* return index of link back to V from W, or -1 if no link found */
296: static int
297: ospf_lsa_has_link (struct lsa_header *w, struct lsa_header *v)
298: {
299: unsigned int i, length;
300: struct router_lsa *rl;
301: struct network_lsa *nl;
302:
303: /* In case of W is Network LSA. */
304: if (w->type == OSPF_NETWORK_LSA)
305: {
306: if (v->type == OSPF_NETWORK_LSA)
307: return -1;
308:
309: nl = (struct network_lsa *) w;
310: length = (ntohs (w->length) - OSPF_LSA_HEADER_SIZE - 4) / 4;
311:
312: for (i = 0; i < length; i++)
313: if (IPV4_ADDR_SAME (&nl->routers[i], &v->id))
314: return i;
315: return -1;
316: }
317:
318: /* In case of W is Router LSA. */
319: if (w->type == OSPF_ROUTER_LSA)
320: {
321: rl = (struct router_lsa *) w;
322:
323: length = ntohs (w->length);
324:
325: for (i = 0;
326: i < ntohs (rl->links) && length >= sizeof (struct router_lsa);
327: i++, length -= 12)
328: {
329: switch (rl->link[i].type)
330: {
331: case LSA_LINK_TYPE_POINTOPOINT:
332: case LSA_LINK_TYPE_VIRTUALLINK:
333: /* Router LSA ID. */
334: if (v->type == OSPF_ROUTER_LSA &&
335: IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
336: {
337: return i;
338: }
339: break;
340: case LSA_LINK_TYPE_TRANSIT:
341: /* Network LSA ID. */
342: if (v->type == OSPF_NETWORK_LSA &&
343: IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
344: {
345: return i;
346: }
347: break;
348: case LSA_LINK_TYPE_STUB:
349: /* Stub can't lead anywhere, carry on */
350: continue;
351: default:
352: break;
353: }
354: }
355: }
356: return -1;
357: }
358:
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: */
363: static struct router_lsa_link *
364: ospf_get_next_link (struct vertex *v, struct vertex *w,
365: struct router_lsa_link *prev_link)
366: {
367: u_char *p;
368: u_char *lim;
369: u_char lsa_type = LSA_LINK_TYPE_TRANSIT;
370: struct router_lsa_link *l;
371:
372: if (w->type == OSPF_VERTEX_ROUTER)
373: lsa_type = LSA_LINK_TYPE_POINTOPOINT;
374:
375: if (prev_link == NULL)
376: p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
377: else
378: {
379: p = (u_char *) prev_link;
380: p += (OSPF_ROUTER_LSA_LINK_SIZE +
381: (prev_link->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
382: }
383:
384: lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
385:
386: while (p < lim)
387: {
388: l = (struct router_lsa_link *) p;
389:
390: p += (OSPF_ROUTER_LSA_LINK_SIZE + (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
391:
392: if (l->m[0].type != lsa_type)
393: continue;
394:
395: if (IPV4_ADDR_SAME (&l->link_id, &w->id))
396: return l;
397: }
398:
399: return NULL;
400: }
401:
402: static void
403: ospf_spf_flush_parents (struct vertex *w)
404: {
405: struct vertex_parent *vp;
406: struct listnode *ln, *nn;
407:
408: /* delete the existing nexthops */
409: for (ALL_LIST_ELEMENTS (w->parents, ln, nn, vp))
410: {
411: list_delete_node (w->parents, ln);
412: vertex_parent_free (vp);
413: }
414: }
415:
416: /*
417: * Consider supplied next-hop for inclusion to the supplied list of
418: * equal-cost next-hops, adjust list as neccessary.
419: */
420: static void
421: ospf_spf_add_parent (struct vertex *v, struct vertex *w,
422: struct vertex_nexthop *newhop,
423: unsigned int distance)
424: {
425: struct vertex_parent *vp;
426:
427: /* we must have a newhop, and a distance */
428: assert (v && w && newhop);
429: assert (distance);
430:
431: /* IFF w has already been assigned a distance, then we shouldn't get here
432: * unless callers have determined V(l)->W is shortest / equal-shortest
433: * path (0 is a special case distance (no distance yet assigned)).
434: */
435: if (w->distance)
436: assert (distance <= w->distance);
437: else
438: w->distance = distance;
439:
440: if (IS_DEBUG_OSPF_EVENT)
441: {
442: char buf[2][INET_ADDRSTRLEN];
443: zlog_debug ("%s: Adding %s as parent of %s",
444: __func__,
445: inet_ntop(AF_INET, &v->lsa->id, buf[0], sizeof(buf[0])),
446: inet_ntop(AF_INET, &w->lsa->id, buf[1], sizeof(buf[1])));
447: }
448:
449: /* Adding parent for a new, better path: flush existing parents from W. */
450: if (distance < w->distance)
451: {
452: if (IS_DEBUG_OSPF_EVENT)
453: zlog_debug ("%s: distance %d better than %d, flushing existing parents",
454: __func__, distance, w->distance);
455: ospf_spf_flush_parents (w);
456: w->distance = distance;
457: }
458:
459: /* new parent is <= existing parents, add it to parent list */
460: vp = vertex_parent_new (v, ospf_lsa_has_link (w->lsa, v->lsa), newhop);
461: listnode_add (w->parents, vp);
462:
463: return;
464: }
465:
466: /* 16.1.1. Calculate nexthop from root through V (parent) to
467: * vertex W (destination), with given distance from root->W.
468: *
469: * The link must be supplied if V is the root vertex. In all other cases
470: * it may be NULL.
471: *
472: * Note that this function may fail, hence the state of the destination
473: * vertex, W, should /not/ be modified in a dependent manner until
474: * this function returns. This function will update the W vertex with the
475: * provided distance as appropriate.
476: */
477: static unsigned int
478: ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v,
479: struct vertex *w, struct router_lsa_link *l,
480: unsigned int distance)
481: {
482: struct listnode *node, *nnode;
483: struct vertex_nexthop *nh;
484: struct vertex_parent *vp;
485: struct ospf_interface *oi = NULL;
486: unsigned int added = 0;
487:
488: if (IS_DEBUG_OSPF_EVENT)
489: {
490: zlog_debug ("ospf_nexthop_calculation(): Start");
491: ospf_vertex_dump("V (parent):", v, 1, 1);
492: ospf_vertex_dump("W (dest) :", w, 1, 1);
493: zlog_debug ("V->W distance: %d", distance);
494: }
495:
496: if (v == area->spf)
497: {
498: /* 16.1.1 para 4. In the first case, the parent vertex (V) is the
499: root (the calculating router itself). This means that the
500: destination is either a directly connected network or directly
501: connected router. The outgoing interface in this case is simply
502: the OSPF interface connecting to the destination network/router.
503: */
504:
505: if (w->type == OSPF_VERTEX_ROUTER)
506: {
507: /* l is a link from v to w
508: * l2 will be link from w to v
509: */
510: struct router_lsa_link *l2 = NULL;
511:
512: /* we *must* be supplied with the link data */
513: assert (l != NULL);
514:
515: if (IS_DEBUG_OSPF_EVENT)
516: {
517: char buf1[BUFSIZ];
518: char buf2[BUFSIZ];
519:
520: zlog_debug("ospf_nexthop_calculation(): considering link "
521: "type %d link_id %s link_data %s",
522: l->m[0].type,
523: inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ),
524: inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ));
525: }
526:
527: if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT)
528: {
529: /* If the destination is a router which connects to
530: the calculating router via a Point-to-MultiPoint
531: network, the destination's next hop IP address(es)
532: can be determined by examining the destination's
533: router-LSA: each link pointing back to the
534: calculating router and having a Link Data field
535: belonging to the Point-to-MultiPoint network
536: provides an IP address of the next hop router.
537:
538: At this point l is a link from V to W, and V is the
539: root ("us"). Find the local interface associated
540: with l (its address is in l->link_data). If it
541: is a point-to-multipoint interface, then look through
542: the links in the opposite direction (W to V). If
543: any of them have an address that lands within the
544: subnet declared by the PtMP link, then that link
545: is a constituent of the PtMP link, and its address is
546: a nexthop address for V.
547: */
548: oi = ospf_if_is_configured (area->ospf, &l->link_data);
549: if (oi && oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
550: {
551: struct prefix_ipv4 la;
552:
553: la.family = AF_INET;
554: la.prefixlen = oi->address->prefixlen;
555:
556: /* V links to W on PtMP interface
557: - find the interface address on W */
558: while ((l2 = ospf_get_next_link (w, v, l2)))
559: {
560: la.prefix = l2->link_data;
561:
562: if (prefix_cmp ((struct prefix *) &la,
563: oi->address) == 0)
564: /* link_data is on our PtMP network */
565: break;
566: }
567: } /* end l is on point-to-multipoint link */
568: else
569: {
570: /* l is a regular point-to-point link.
571: Look for a link from W to V.
572: */
573: while ((l2 = ospf_get_next_link (w, v, l2)))
574: {
575: oi = ospf_if_is_configured (area->ospf,
576: &(l2->link_data));
577:
578: if (oi == NULL)
579: continue;
580:
581: if (!IPV4_ADDR_SAME (&oi->address->u.prefix4,
582: &l->link_data))
583: continue;
584:
585: break;
586: }
587: }
588:
589: if (oi && l2)
590: {
591: /* found all necessary info to build nexthop */
592: nh = vertex_nexthop_new ();
593: nh->oi = oi;
594: nh->router = l2->link_data;
595: ospf_spf_add_parent (v, w, nh, distance);
596: return 1;
597: }
598: else
599: zlog_info("ospf_nexthop_calculation(): "
600: "could not determine nexthop for link");
601: } /* end point-to-point link from V to W */
602: else if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK)
603: {
604: struct ospf_vl_data *vl_data;
605:
606: /* VLink implementation limitations:
607: * a) vl_data can only reference one nexthop, so no ECMP
608: * to backbone through VLinks. Though transit-area
609: * summaries may be considered, and those can be ECMP.
610: * b) We can only use /one/ VLink, even if multiple ones
611: * exist this router through multiple transit-areas.
612: */
613: vl_data = ospf_vl_lookup (area->ospf, NULL, l->link_id);
614:
615: if (vl_data
616: && CHECK_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED))
617: {
618: nh = vertex_nexthop_new ();
619: nh->oi = vl_data->nexthop.oi;
620: nh->router = vl_data->nexthop.router;
621: ospf_spf_add_parent (v, w, nh, distance);
622: return 1;
623: }
624: else
625: zlog_info("ospf_nexthop_calculation(): "
626: "vl_data for VL link not found");
627: } /* end virtual-link from V to W */
628: return 0;
629: } /* end W is a Router vertex */
630: else
631: {
632: assert(w->type == OSPF_VERTEX_NETWORK);
633: oi = ospf_if_is_configured (area->ospf, &(l->link_data));
634: if (oi)
635: {
636: nh = vertex_nexthop_new ();
637: nh->oi = oi;
638: nh->router.s_addr = 0;
639: ospf_spf_add_parent (v, w, nh, distance);
640: return 1;
641: }
642: }
643: zlog_info("ospf_nexthop_calculation(): "
644: "Unknown attached link");
645: return 0;
646: } /* end V is the root */
647: /* Check if W's parent is a network connected to root. */
648: else if (v->type == OSPF_VERTEX_NETWORK)
649: {
650: /* See if any of V's parents are the root. */
651: for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
652: {
653: if (vp->parent == area->spf) /* connects to root? */
654: {
655: /* 16.1.1 para 5. ...the parent vertex is a network that
656: * directly connects the calculating router to the destination
657: * router. The list of next hops is then determined by
658: * examining the destination's router-LSA...
659: */
660:
661: assert(w->type == OSPF_VERTEX_ROUTER);
662: while ((l = ospf_get_next_link (w, v, l)))
663: {
664: /* ...For each link in the router-LSA that points back to the
665: * parent network, the link's Link Data field provides the IP
666: * address of a next hop router. The outgoing interface to
667: * use can then be derived from the next hop IP address (or
668: * it can be inherited from the parent network).
669: */
670: nh = vertex_nexthop_new ();
671: nh->oi = vp->nexthop->oi;
672: nh->router = l->link_data;
673: added = 1;
674: ospf_spf_add_parent (v, w, nh, distance);
675: }
676: }
677: }
678: /* NB: This code is non-trivial.
679: *
680: * E.g. it is not enough to know that V connects to the root. It is
681: * also important that the while above, looping through all links from
682: * W->V found at least one link, so that we know there is
683: * bi-directional connectivity between V and W. Otherwise, if we
684: * /always/ return here, but don't check that W->V exists then we
685: * we will prevent SPF from finding/using higher cost paths..
686: *
687: * See also bug #330, and also:
688: *
689: * http://blogs.sun.com/paulj/entry/the_difference_a_line_makes
690: */
691: if (added)
692: return added;
693: }
694:
695: /* 16.1.1 para 4. If there is at least one intervening router in the
696: * current shortest path between the destination and the root, the
697: * destination simply inherits the set of next hops from the
698: * parent.
699: */
700: if (IS_DEBUG_OSPF_EVENT)
701: zlog_debug ("%s: Intervening routers, adding parent(s)", __func__);
702:
703: for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
704: {
705: added = 1;
706: ospf_spf_add_parent (v, w, vp->nexthop, distance);
707: }
708:
709: return added;
710: }
711:
712: /* RFC2328 Section 16.1 (2).
713: * v is on the SPF tree. Examine the links in v's LSA. Update the list
714: * of candidates with any vertices not already on the list. If a lower-cost
715: * path is found to a vertex already on the candidate list, store the new cost.
716: */
717: static void
718: ospf_spf_next (struct vertex *v, struct ospf_area *area,
719: struct pqueue * candidate)
720: {
721: struct ospf_lsa *w_lsa = NULL;
722: u_char *p;
723: u_char *lim;
724: struct router_lsa_link *l = NULL;
725: struct in_addr *r;
726: int type = 0;
727:
728: /* If this is a router-LSA, and bit V of the router-LSA (see Section
729: A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE. */
730: if (v->type == OSPF_VERTEX_ROUTER)
731: {
732: if (IS_ROUTER_LSA_VIRTUAL ((struct router_lsa *) v->lsa))
733: area->transit = OSPF_TRANSIT_TRUE;
734: }
735:
736: if (IS_DEBUG_OSPF_EVENT)
737: zlog_debug ("%s: Next vertex of %s vertex %s",
738: __func__,
739: v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
740: inet_ntoa(v->lsa->id));
741:
742: p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
743: lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
744:
745: while (p < lim)
746: {
747: struct vertex *w;
748: unsigned int distance;
749:
750: /* In case of V is Router-LSA. */
751: if (v->lsa->type == OSPF_ROUTER_LSA)
752: {
753: l = (struct router_lsa_link *) p;
754:
755: p += (OSPF_ROUTER_LSA_LINK_SIZE +
756: (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
757:
758: /* (a) If this is a link to a stub network, examine the next
759: link in V's LSA. Links to stub networks will be
760: considered in the second stage of the shortest path
761: calculation. */
762: if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB)
763: continue;
764:
765: /* Infinite distance links shouldn't be followed, except
766: * for local links (a stub-routed router still wants to
767: * calculate tree, so must follow its own links).
768: */
769: if ((v != area->spf) && l->m[0].metric >= OSPF_OUTPUT_COST_INFINITE)
770: continue;
771:
772: /* (b) Otherwise, W is a transit vertex (router or transit
773: network). Look up the vertex W's LSA (router-LSA or
774: network-LSA) in Area A's link state database. */
775: switch (type)
776: {
777: case LSA_LINK_TYPE_POINTOPOINT:
778: case LSA_LINK_TYPE_VIRTUALLINK:
779: if (type == LSA_LINK_TYPE_VIRTUALLINK)
780: {
781: if (IS_DEBUG_OSPF_EVENT)
782: zlog_debug ("looking up LSA through VL: %s",
783: inet_ntoa (l->link_id));
784: }
785:
786: w_lsa = ospf_lsa_lookup (area, OSPF_ROUTER_LSA, l->link_id,
787: l->link_id);
788: if (w_lsa)
789: {
790: if (IS_DEBUG_OSPF_EVENT)
791: zlog_debug ("found Router LSA %s", inet_ntoa (l->link_id));
792: }
793: break;
794: case LSA_LINK_TYPE_TRANSIT:
795: if (IS_DEBUG_OSPF_EVENT)
796: zlog_debug ("Looking up Network LSA, ID: %s",
797: inet_ntoa (l->link_id));
798: w_lsa = ospf_lsa_lookup_by_id (area, OSPF_NETWORK_LSA,
799: l->link_id);
800: if (w_lsa)
801: if (IS_DEBUG_OSPF_EVENT)
802: zlog_debug ("found the LSA");
803: break;
804: default:
805: zlog_warn ("Invalid LSA link type %d", type);
806: continue;
807: }
808: }
809: else
810: {
811: /* In case of V is Network-LSA. */
812: r = (struct in_addr *) p;
813: p += sizeof (struct in_addr);
814:
815: /* Lookup the vertex W's LSA. */
816: w_lsa = ospf_lsa_lookup_by_id (area, OSPF_ROUTER_LSA, *r);
817: if (w_lsa)
818: {
819: if (IS_DEBUG_OSPF_EVENT)
820: zlog_debug ("found Router LSA %s", inet_ntoa (w_lsa->data->id));
821: }
822: }
823:
824: /* (b cont.) If the LSA does not exist, or its LS age is equal
825: to MaxAge, or it does not have a link back to vertex V,
826: examine the next link in V's LSA.[23] */
827: if (w_lsa == NULL)
828: {
829: if (IS_DEBUG_OSPF_EVENT)
830: zlog_debug ("No LSA found");
831: continue;
832: }
833:
834: if (IS_LSA_MAXAGE (w_lsa))
835: {
836: if (IS_DEBUG_OSPF_EVENT)
837: zlog_debug ("LSA is MaxAge");
838: continue;
839: }
840:
841: if (ospf_lsa_has_link (w_lsa->data, v->lsa) < 0 )
842: {
843: if (IS_DEBUG_OSPF_EVENT)
844: zlog_debug ("The LSA doesn't have a link back");
845: continue;
846: }
847:
848: /* (c) If vertex W is already on the shortest-path tree, examine
849: the next link in the LSA. */
850: if (w_lsa->stat == LSA_SPF_IN_SPFTREE)
851: {
852: if (IS_DEBUG_OSPF_EVENT)
853: zlog_debug ("The LSA is already in SPF");
854: continue;
855: }
856:
857: /* (d) Calculate the link state cost D of the resulting path
858: from the root to vertex W. D is equal to the sum of the link
859: state cost of the (already calculated) shortest path to
860: vertex V and the advertised cost of the link between vertices
861: V and W. If D is: */
862:
863: /* calculate link cost D. */
864: if (v->lsa->type == OSPF_ROUTER_LSA)
865: distance = v->distance + ntohs (l->m[0].metric);
866: else /* v is not a Router-LSA */
867: distance = v->distance;
868:
869: /* Is there already vertex W in candidate list? */
870: if (w_lsa->stat == LSA_SPF_NOT_EXPLORED)
871: {
872: /* prepare vertex W. */
873: w = ospf_vertex_new (w_lsa);
874:
875: /* Calculate nexthop to W. */
876: if (ospf_nexthop_calculation (area, v, w, l, distance))
877: pqueue_enqueue (w, candidate);
878: else if (IS_DEBUG_OSPF_EVENT)
879: zlog_debug ("Nexthop Calc failed");
880: }
881: else if (w_lsa->stat >= 0)
882: {
883: /* Get the vertex from candidates. */
884: w = candidate->array[w_lsa->stat];
885:
886: /* if D is greater than. */
887: if (w->distance < distance)
888: {
889: continue;
890: }
891: /* equal to. */
892: else if (w->distance == distance)
893: {
894: /* Found an equal-cost path to W.
895: * Calculate nexthop of to W from V. */
896: ospf_nexthop_calculation (area, v, w, l, distance);
897: }
898: /* less than. */
899: else
900: {
901: /* Found a lower-cost path to W.
902: * nexthop_calculation is conditional, if it finds
903: * valid nexthop it will call spf_add_parents, which
904: * will flush the old parents
905: */
906: if (ospf_nexthop_calculation (area, v, w, l, distance))
907: /* Decrease the key of the node in the heap.
908: * trickle-sort it up towards root, just in case this
909: * node should now be the new root due the cost change.
910: * (next pqueu_{de,en}queue will fully re-heap the queue).
911: */
912: trickle_up (w_lsa->stat, candidate);
913: }
914: } /* end W is already on the candidate list */
915: } /* end loop over the links in V's LSA */
916: }
917:
918: static void
919: ospf_spf_dump (struct vertex *v, int i)
920: {
921: struct listnode *cnode;
922: struct listnode *nnode;
923: struct vertex_parent *parent;
924:
925: if (v->type == OSPF_VERTEX_ROUTER)
926: {
927: if (IS_DEBUG_OSPF_EVENT)
928: zlog_debug ("SPF Result: %d [R] %s", i, inet_ntoa (v->lsa->id));
929: }
930: else
931: {
932: struct network_lsa *lsa = (struct network_lsa *) v->lsa;
933: if (IS_DEBUG_OSPF_EVENT)
934: zlog_debug ("SPF Result: %d [N] %s/%d", i, inet_ntoa (v->lsa->id),
935: ip_masklen (lsa->mask));
936: }
937:
938: if (IS_DEBUG_OSPF_EVENT)
939: for (ALL_LIST_ELEMENTS_RO (v->parents, nnode, parent))
940: {
941: zlog_debug (" nexthop %p %s %s",
942: parent->nexthop,
943: inet_ntoa (parent->nexthop->router),
944: parent->nexthop->oi ? IF_NAME(parent->nexthop->oi)
945: : "NULL");
946: }
947:
948: i++;
949:
950: for (ALL_LIST_ELEMENTS_RO (v->children, cnode, v))
951: ospf_spf_dump (v, i);
952: }
953:
954: /* Second stage of SPF calculation. */
955: static void
956: ospf_spf_process_stubs (struct ospf_area *area, struct vertex *v,
957: struct route_table *rt,
958: int parent_is_root)
959: {
960: struct listnode *cnode, *cnnode;
961: struct vertex *child;
962:
963: if (IS_DEBUG_OSPF_EVENT)
964: zlog_debug ("ospf_process_stub():processing stubs for area %s",
965: inet_ntoa (area->area_id));
966: if (v->type == OSPF_VERTEX_ROUTER)
967: {
968: u_char *p;
969: u_char *lim;
970: struct router_lsa_link *l;
971: struct router_lsa *rlsa;
972:
973: if (IS_DEBUG_OSPF_EVENT)
974: zlog_debug ("ospf_process_stubs():processing router LSA, id: %s",
975: inet_ntoa (v->lsa->id));
976: rlsa = (struct router_lsa *) v->lsa;
977:
978:
979: if (IS_DEBUG_OSPF_EVENT)
980: zlog_debug ("ospf_process_stubs(): we have %d links to process",
981: ntohs (rlsa->links));
982: p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
983: lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
984:
985: while (p < lim)
986: {
987: l = (struct router_lsa_link *) p;
988:
989: p += (OSPF_ROUTER_LSA_LINK_SIZE +
990: (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
991:
992: if (l->m[0].type == LSA_LINK_TYPE_STUB)
993: ospf_intra_add_stub (rt, l, v, area, parent_is_root);
994: }
995: }
996:
997: ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1, 1);
998:
999: for (ALL_LIST_ELEMENTS (v->children, cnode, cnnode, child))
1000: {
1001: if (CHECK_FLAG (child->flags, OSPF_VERTEX_PROCESSED))
1002: continue;
1003:
1004: /* the first level of routers connected to the root
1005: * should have 'parent_is_root' set, including those
1006: * connected via a network vertex.
1007: */
1008: if (area->spf == v)
1009: parent_is_root = 1;
1010: else if (v->type == OSPF_VERTEX_ROUTER)
1011: parent_is_root = 0;
1012:
1013: ospf_spf_process_stubs (area, child, rt, parent_is_root);
1014:
1015: SET_FLAG (child->flags, OSPF_VERTEX_PROCESSED);
1016: }
1017: }
1018:
1019: void
1020: ospf_rtrs_free (struct route_table *rtrs)
1021: {
1022: struct route_node *rn;
1023: struct list *or_list;
1024: struct ospf_route *or;
1025: struct listnode *node, *nnode;
1026:
1027: if (IS_DEBUG_OSPF_EVENT)
1028: zlog_debug ("Route: Router Routing Table free");
1029:
1030: for (rn = route_top (rtrs); rn; rn = route_next (rn))
1031: if ((or_list = rn->info) != NULL)
1032: {
1033: for (ALL_LIST_ELEMENTS (or_list, node, nnode, or))
1034: ospf_route_free (or);
1035:
1036: list_delete (or_list);
1037:
1038: /* Unlock the node. */
1039: rn->info = NULL;
1040: route_unlock_node (rn);
1041: }
1042: route_table_finish (rtrs);
1043: }
1044:
1045: static void
1046: ospf_rtrs_print (struct route_table *rtrs)
1047: {
1048: struct route_node *rn;
1049: struct list *or_list;
1050: struct listnode *ln;
1051: struct listnode *pnode;
1052: struct ospf_route *or;
1053: struct ospf_path *path;
1054: char buf1[BUFSIZ];
1055: char buf2[BUFSIZ];
1056:
1057: if (IS_DEBUG_OSPF_EVENT)
1058: zlog_debug ("ospf_rtrs_print() start");
1059:
1060: for (rn = route_top (rtrs); rn; rn = route_next (rn))
1061: if ((or_list = rn->info) != NULL)
1062: for (ALL_LIST_ELEMENTS_RO (or_list, ln, or))
1063: {
1064: switch (or->path_type)
1065: {
1066: case OSPF_PATH_INTRA_AREA:
1067: if (IS_DEBUG_OSPF_EVENT)
1068: zlog_debug ("%s [%d] area: %s",
1069: inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1070: or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1071: buf2, BUFSIZ));
1072: break;
1073: case OSPF_PATH_INTER_AREA:
1074: if (IS_DEBUG_OSPF_EVENT)
1075: zlog_debug ("%s IA [%d] area: %s",
1076: inet_ntop (AF_INET, &or->id, buf1, BUFSIZ),
1077: or->cost, inet_ntop (AF_INET, &or->u.std.area_id,
1078: buf2, BUFSIZ));
1079: break;
1080: default:
1081: break;
1082: }
1083:
1084: for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path))
1085: {
1086: if (path->nexthop.s_addr == 0)
1087: {
1088: if (IS_DEBUG_OSPF_EVENT)
1089: zlog_debug (" directly attached to %s\r\n",
1090: ifindex2ifname (path->ifindex));
1091: }
1092: else
1093: {
1094: if (IS_DEBUG_OSPF_EVENT)
1095: zlog_debug (" via %s, %s\r\n",
1096: inet_ntoa (path->nexthop),
1097: ifindex2ifname (path->ifindex));
1098: }
1099: }
1100: }
1101:
1102: zlog_debug ("ospf_rtrs_print() end");
1103: }
1104:
1105: /* Calculating the shortest-path tree for an area. */
1106: static void
1107: ospf_spf_calculate (struct ospf_area *area, struct route_table *new_table,
1108: struct route_table *new_rtrs)
1109: {
1110: struct pqueue *candidate;
1111: struct vertex *v;
1112:
1113: if (IS_DEBUG_OSPF_EVENT)
1114: {
1115: zlog_debug ("ospf_spf_calculate: Start");
1116: zlog_debug ("ospf_spf_calculate: running Dijkstra for area %s",
1117: inet_ntoa (area->area_id));
1118: }
1119:
1120: /* Check router-lsa-self. If self-router-lsa is not yet allocated,
1121: return this area's calculation. */
1122: if (!area->router_lsa_self)
1123: {
1124: if (IS_DEBUG_OSPF_EVENT)
1125: zlog_debug ("ospf_spf_calculate: "
1126: "Skip area %s's calculation due to empty router_lsa_self",
1127: inet_ntoa (area->area_id));
1128: return;
1129: }
1130:
1131: /* RFC2328 16.1. (1). */
1132: /* Initialize the algorithm's data structures. */
1133:
1134: /* This function scans all the LSA database and set the stat field to
1135: * LSA_SPF_NOT_EXPLORED. */
1136: ospf_lsdb_clean_stat (area->lsdb);
1137: /* Create a new heap for the candidates. */
1138: candidate = pqueue_create();
1139: candidate->cmp = cmp;
1140: candidate->update = update_stat;
1141:
1142: /* Initialize the shortest-path tree to only the root (which is the
1143: router doing the calculation). */
1144: ospf_spf_init (area);
1145: v = area->spf;
1146: /* Set LSA position to LSA_SPF_IN_SPFTREE. This vertex is the root of the
1147: * spanning tree. */
1148: *(v->stat) = LSA_SPF_IN_SPFTREE;
1149:
1150: /* Set Area A's TransitCapability to FALSE. */
1151: area->transit = OSPF_TRANSIT_FALSE;
1152: area->shortcut_capability = 1;
1153:
1154: for (;;)
1155: {
1156: /* RFC2328 16.1. (2). */
1157: ospf_spf_next (v, area, candidate);
1158:
1159: /* RFC2328 16.1. (3). */
1160: /* If at this step the candidate list is empty, the shortest-
1161: path tree (of transit vertices) has been completely built and
1162: this stage of the procedure terminates. */
1163: if (candidate->size == 0)
1164: break;
1165:
1166: /* Otherwise, choose the vertex belonging to the candidate list
1167: that is closest to the root, and add it to the shortest-path
1168: tree (removing it from the candidate list in the
1169: process). */
1170: /* Extract from the candidates the node with the lower key. */
1171: v = (struct vertex *) pqueue_dequeue (candidate);
1172: /* Update stat field in vertex. */
1173: *(v->stat) = LSA_SPF_IN_SPFTREE;
1174:
1175: ospf_vertex_add_parent (v);
1176:
1177: /* RFC2328 16.1. (4). */
1178: if (v->type == OSPF_VERTEX_ROUTER)
1179: ospf_intra_add_router (new_rtrs, v, area);
1180: else
1181: ospf_intra_add_transit (new_table, v, area);
1182:
1183: /* RFC2328 16.1. (5). */
1184: /* Iterate the algorithm by returning to Step 2. */
1185:
1186: } /* end loop until no more candidate vertices */
1187:
1188: if (IS_DEBUG_OSPF_EVENT)
1189: {
1190: ospf_spf_dump (area->spf, 0);
1191: ospf_route_table_dump (new_table);
1192: }
1193:
1194: /* Second stage of SPF calculation procedure's */
1195: ospf_spf_process_stubs (area, area->spf, new_table, 0);
1196:
1197: /* Free candidate queue. */
1198: pqueue_delete (candidate);
1199:
1200: ospf_vertex_dump (__func__, area->spf, 0, 1);
1201: /* Free nexthop information, canonical versions of which are attached
1202: * the first level of router vertices attached to the root vertex, see
1203: * ospf_nexthop_calculation.
1204: */
1205: ospf_canonical_nexthops_free (area->spf);
1206:
1207: /* Free SPF vertices, but not the list. List has ospf_vertex_free
1208: * as deconstructor.
1209: */
1210: list_delete_all_node (&vertex_list);
1211:
1212: /* Increment SPF Calculation Counter. */
1213: area->spf_calculation++;
1214:
1215: quagga_gettime (QUAGGA_CLK_MONOTONIC, &area->ospf->ts_spf);
1216:
1217: if (IS_DEBUG_OSPF_EVENT)
1218: zlog_debug ("ospf_spf_calculate: Stop. %ld vertices",
1219: mtype_stats_alloc(MTYPE_OSPF_VERTEX));
1220: }
1221:
1222: /* Timer for SPF calculation. */
1223: static int
1224: ospf_spf_calculate_timer (struct thread *thread)
1225: {
1226: struct ospf *ospf = THREAD_ARG (thread);
1227: struct route_table *new_table, *new_rtrs;
1228: struct ospf_area *area;
1229: struct listnode *node, *nnode;
1230:
1231: if (IS_DEBUG_OSPF_EVENT)
1232: zlog_debug ("SPF: Timer (SPF calculation expire)");
1233:
1234: ospf->t_spf_calc = NULL;
1235:
1236: /* Allocate new table tree. */
1237: new_table = route_table_init ();
1238: new_rtrs = route_table_init ();
1239:
1240: ospf_vl_unapprove (ospf);
1241:
1242: /* Calculate SPF for each area. */
1243: for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
1244: {
1245: /* Do backbone last, so as to first discover intra-area paths
1246: * for any back-bone virtual-links
1247: */
1248: if (ospf->backbone && ospf->backbone == area)
1249: continue;
1250:
1251: ospf_spf_calculate (area, new_table, new_rtrs);
1252: }
1253:
1254: /* SPF for backbone, if required */
1255: if (ospf->backbone)
1256: ospf_spf_calculate (ospf->backbone, new_table, new_rtrs);
1257:
1258: ospf_vl_shut_unapproved (ospf);
1259:
1260: ospf_ia_routing (ospf, new_table, new_rtrs);
1261:
1262: ospf_prune_unreachable_networks (new_table);
1263: ospf_prune_unreachable_routers (new_rtrs);
1264:
1265: /* AS-external-LSA calculation should not be performed here. */
1266:
1267: /* If new Router Route is installed,
1268: then schedule re-calculate External routes. */
1269: if (1)
1270: ospf_ase_calculate_schedule (ospf);
1271:
1272: ospf_ase_calculate_timer_add (ospf);
1273:
1274: /* Update routing table. */
1275: ospf_route_install (ospf, new_table);
1276:
1277: /* Update ABR/ASBR routing table */
1278: if (ospf->old_rtrs)
1279: {
1280: /* old_rtrs's node holds linked list of ospf_route. --kunihiro. */
1281: /* ospf_route_delete (ospf->old_rtrs); */
1282: ospf_rtrs_free (ospf->old_rtrs);
1283: }
1284:
1285: ospf->old_rtrs = ospf->new_rtrs;
1286: ospf->new_rtrs = new_rtrs;
1287:
1288: if (IS_OSPF_ABR (ospf))
1289: ospf_abr_task (ospf);
1290:
1291: if (IS_DEBUG_OSPF_EVENT)
1292: zlog_debug ("SPF: calculation complete");
1293:
1294: return 0;
1295: }
1296:
1297: /* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
1298: set timer for SPF calc. */
1299: void
1300: ospf_spf_calculate_schedule (struct ospf *ospf)
1301: {
1302: unsigned long delay, elapsed, ht;
1303: struct timeval result;
1304:
1305: if (IS_DEBUG_OSPF_EVENT)
1306: zlog_debug ("SPF: calculation timer scheduled");
1307:
1308: /* OSPF instance does not exist. */
1309: if (ospf == NULL)
1310: return;
1311:
1312: /* SPF calculation timer is already scheduled. */
1313: if (ospf->t_spf_calc)
1314: {
1315: if (IS_DEBUG_OSPF_EVENT)
1316: zlog_debug ("SPF: calculation timer is already scheduled: %p",
1317: ospf->t_spf_calc);
1318: return;
1319: }
1320:
1321: /* XXX Monotic timers: we only care about relative time here. */
1322: result = tv_sub (recent_relative_time (), ospf->ts_spf);
1323:
1324: elapsed = (result.tv_sec * 1000) + (result.tv_usec / 1000);
1325: ht = ospf->spf_holdtime * ospf->spf_hold_multiplier;
1326:
1327: if (ht > ospf->spf_max_holdtime)
1328: ht = ospf->spf_max_holdtime;
1329:
1330: /* Get SPF calculation delay time. */
1331: if (elapsed < ht)
1332: {
1333: /* Got an event within the hold time of last SPF. We need to
1334: * increase the hold_multiplier, if it's not already at/past
1335: * maximum value, and wasn't already increased..
1336: */
1337: if (ht < ospf->spf_max_holdtime)
1338: ospf->spf_hold_multiplier++;
1339:
1340: /* always honour the SPF initial delay */
1341: if ( (ht - elapsed) < ospf->spf_delay)
1342: delay = ospf->spf_delay;
1343: else
1344: delay = ht - elapsed;
1345: }
1346: else
1347: {
1348: /* Event is past required hold-time of last SPF */
1349: delay = ospf->spf_delay;
1350: ospf->spf_hold_multiplier = 1;
1351: }
1352:
1353: if (IS_DEBUG_OSPF_EVENT)
1354: zlog_debug ("SPF: calculation timer delay = %ld", delay);
1355:
1356: ospf->t_spf_calc =
1357: thread_add_timer_msec (master, ospf_spf_calculate_timer, ospf, delay);
1358: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>