Annotation of embedaddon/quagga/ospfd/ospf_spf.c, revision 1.1.1.4

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>