Annotation of embedaddon/quagga/ospfd/ospf_spf.c, revision 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>