Diff for /embedaddon/quagga/ospfd/ospf_spf.c between versions 1.1.1.1 and 1.1.1.4

version 1.1.1.1, 2012/02/21 17:26:12 version 1.1.1.4, 2016/11/02 10:09:12
Line 46  Software Foundation, Inc., 59 Temple Place - Suite 330 Line 46  Software Foundation, Inc., 59 Temple Place - Suite 330
 #include "ospfd/ospf_abr.h"  #include "ospfd/ospf_abr.h"
 #include "ospfd/ospf_dump.h"  #include "ospfd/ospf_dump.h"
   
   /* Variables to ensure a SPF scheduled log message is printed only once */
   
   static unsigned int spf_reason_flags = 0;
   
   static void
   ospf_clear_spf_reason_flags ()
   {
     spf_reason_flags = 0;
   }
   
   static void 
   ospf_spf_set_reason (ospf_spf_reason_t reason)
   {
     spf_reason_flags |= 1 << reason;
   }
   
   static void
   ospf_get_spf_reason_str (char *buf)
   {
     if (!buf)
      return;
    
     buf[0] = '\0';
     if (spf_reason_flags)
       {
         if (spf_reason_flags & SPF_FLAG_ROUTER_LSA_INSTALL)
           strcat (buf, "R, ");
         if (spf_reason_flags & SPF_FLAG_NETWORK_LSA_INSTALL)
           strcat (buf, "N, ");
         if (spf_reason_flags & SPF_FLAG_SUMMARY_LSA_INSTALL)
           strcat (buf, "S, ");
         if (spf_reason_flags & SPF_FLAG_ASBR_SUMMARY_LSA_INSTALL)
           strcat (buf, "AS, ");
         if (spf_reason_flags & SPF_FLAG_ABR_STATUS_CHANGE)
           strcat (buf, "ABR, ");
         if (spf_reason_flags & SPF_FLAG_ASBR_STATUS_CHANGE)
           strcat (buf, "ASBR, ");
         if (spf_reason_flags & SPF_FLAG_MAXAGE)
           strcat (buf, "M, ");
         buf[strlen(buf)-2] = '\0'; /* skip the last ", " */
       }
   }
   
 static void ospf_vertex_free (void *);  static void ospf_vertex_free (void *);
 /* List of allocated vertices, to simplify cleanup of SPF.  /* List of allocated vertices, to simplify cleanup of SPF.
  * Not thread-safe obviously. If it ever needs to be, it'd have to be   * Not thread-safe obviously. If it ever needs to be, it'd have to be
  * dynamically allocated at begin of ospf_spf_calculate   * dynamically allocated at begin of ospf_spf_calculate
  */   */
 static struct list vertex_list = { .del = ospf_vertex_free };  static struct list vertex_list = { .del = ospf_vertex_free };
 /* Heap related functions, for the managment of the candidates, to  /* Heap related functions, for the managment of the candidates, to
  * be used with pqueue. */   * be used with pqueue. */
 static int  static int
Line 90  update_stat (void *node , int position) Line 133  update_stat (void *node , int position)
   /* Set the status of the vertex, when its position changes. */    /* Set the status of the vertex, when its position changes. */
   *(v->stat) = position;    *(v->stat) = position;
 }  }
 static struct vertex_nexthop *  static struct vertex_nexthop *
 vertex_nexthop_new (void)  vertex_nexthop_new (void)
 {  {
Line 134  ospf_canonical_nexthops_free (struct vertex *root) Line 177  ospf_canonical_nexthops_free (struct vertex *root)
           vertex_nexthop_free (vp->nexthop);            vertex_nexthop_free (vp->nexthop);
     }      }
 }        }      
 /* TODO: Parent list should be excised, in favour of maintaining only  /* TODO: Parent list should be excised, in favour of maintaining only
  * vertex_nexthop, with refcounts.   * vertex_nexthop, with refcounts.
  */   */
Line 159  vertex_parent_free (void *p) Line 202  vertex_parent_free (void *p)
 {  {
   XFREE (MTYPE_OSPF_VERTEX_PARENT, p);    XFREE (MTYPE_OSPF_VERTEX_PARENT, p);
 }  }
 static struct vertex *  static struct vertex *
 ospf_vertex_new (struct ospf_lsa *lsa)  ospf_vertex_new (struct ospf_lsa *lsa)
 {  {
Line 276  ospf_vertex_add_parent (struct vertex *v) Line 319  ospf_vertex_add_parent (struct vertex *v)
         listnode_add (vp->parent->children, v);          listnode_add (vp->parent->children, v);
     }      }
 }  }
 static void  static void
 ospf_spf_init (struct ospf_area *area)  ospf_spf_init (struct ospf_area *area)
 {  {
Line 422  ospf_spf_add_parent (struct vertex *v, struct vertex * Line 465  ospf_spf_add_parent (struct vertex *v, struct vertex *
                      struct vertex_nexthop *newhop,                       struct vertex_nexthop *newhop,
                      unsigned int distance)                       unsigned int distance)
 {  {
  struct vertex_parent *vp;  struct vertex_parent *vp, *wp;
   struct listnode *node;
           
   /* we must have a newhop, and a distance */    /* we must have a newhop, and a distance */
   assert (v && w && newhop);    assert (v && w && newhop);
Line 456  ospf_spf_add_parent (struct vertex *v, struct vertex * Line 500  ospf_spf_add_parent (struct vertex *v, struct vertex *
       w->distance = distance;        w->distance = distance;
     }      }
       
  /* new parent is <= existing parents, add it to parent list */    /* new parent is <= existing parents, add it to parent list (if nexthop
    * not on parent list)
    */  
   for (ALL_LIST_ELEMENTS_RO(w->parents, node, wp))
     {
       if (memcmp(newhop, wp->nexthop, sizeof(*newhop)) == 0)
         {
           if (IS_DEBUG_OSPF_EVENT)
             zlog_debug ("%s: ... nexthop already on parent list, skipping add", __func__);
           return;
         }
     }
 
   vp = vertex_parent_new (v, ospf_lsa_has_link (w->lsa, v->lsa), newhop);    vp = vertex_parent_new (v, ospf_lsa_has_link (w->lsa, v->lsa), newhop);
   listnode_add (w->parents, vp);    listnode_add (w->parents, vp);
   
Line 477  ospf_spf_add_parent (struct vertex *v, struct vertex * Line 533  ospf_spf_add_parent (struct vertex *v, struct vertex *
 static unsigned int  static unsigned int
 ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v,  ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v,
                           struct vertex *w, struct router_lsa_link *l,                            struct vertex *w, struct router_lsa_link *l,
                          unsigned int distance)                          unsigned int distance, int lsa_pos)
 {  {
   struct listnode *node, *nnode;    struct listnode *node, *nnode;
   struct vertex_nexthop *nh;    struct vertex_nexthop *nh;
   struct vertex_parent *vp;    struct vertex_parent *vp;
   struct ospf_interface *oi = NULL;    struct ospf_interface *oi = NULL;
   unsigned int added = 0;    unsigned int added = 0;
     char buf1[BUFSIZ];
     char buf2[BUFSIZ];
   
   if (IS_DEBUG_OSPF_EVENT)    if (IS_DEBUG_OSPF_EVENT)
     {      {
Line 502  ospf_nexthop_calculation (struct ospf_area *area, stru Line 560  ospf_nexthop_calculation (struct ospf_area *area, stru
          the OSPF interface connecting to the destination network/router.           the OSPF interface connecting to the destination network/router.
       */        */
   
         /* we *must* be supplied with the link data */
         assert (l != NULL);
         oi = ospf_if_lookup_by_lsa_pos (area, lsa_pos);
         if (!oi)
           {
             zlog_debug("%s: OI not found in LSA: lsa_pos:%d link_id:%s link_data:%s",
                        __func__, lsa_pos,
                        inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ),
                        inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ));
             return 0;
           }
   
         if (IS_DEBUG_OSPF_EVENT)
           {
             zlog_debug("%s: considering link:%s "
                        "type:%d link_id:%s link_data:%s",
                        __func__, oi->ifp->name, l->m[0].type,
                        inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ),
                        inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ));
           }
   
       if (w->type == OSPF_VERTEX_ROUTER)        if (w->type == OSPF_VERTEX_ROUTER)
         {          {
           /* l  is a link from v to w            /* l  is a link from v to w
            * l2 will be link from w to v             * l2 will be link from w to v
            */             */
           struct router_lsa_link *l2 = NULL;            struct router_lsa_link *l2 = NULL;
             
           /* we *must* be supplied with the link data */  
           assert (l != NULL);  
             
           if (IS_DEBUG_OSPF_EVENT)  
             {  
               char buf1[BUFSIZ];  
               char buf2[BUFSIZ];  
                 
               zlog_debug("ospf_nexthop_calculation(): considering link "  
                         "type %d link_id %s link_data %s",  
                         l->m[0].type,  
                         inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ),  
                         inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ));  
             }  
   
           if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT)            if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT)
             {              {
                 struct in_addr nexthop = { .s_addr = 0 };
   
               /* If the destination is a router which connects to                /* If the destination is a router which connects to
                  the calculating router via a Point-to-MultiPoint                   the calculating router via a Point-to-MultiPoint
                  network, the destination's next hop IP address(es)                   network, the destination's next hop IP address(es)
Line 536  ospf_nexthop_calculation (struct ospf_area *area, stru Line 602  ospf_nexthop_calculation (struct ospf_area *area, stru
                  provides an IP address of the next hop router.                   provides an IP address of the next hop router.
   
                  At this point l is a link from V to W, and V is the                   At this point l is a link from V to W, and V is the
                 root ("us").  Find the local interface associated                  root ("us"). If it is a point-to-multipoint interface,
                 with l (its address is in l->link_data).  If it                 then look through the links in the opposite direction (W to V).
                 is a point-to-multipoint interface, then look through                 If any of them have an address that lands within the
                 the links in the opposite direction (W to V).  If 
                 any of them have an address that lands within the 
                  subnet declared by the PtMP link, then that link                   subnet declared by the PtMP link, then that link
                 is a constituent of the PtMP link, and its address is                  is a constituent of the PtMP link, and its address is
                  a nexthop address for V.                   a nexthop address for V.
               */                */
              oi = ospf_if_is_configured (area->ospf, &l->link_data);              if (oi->type == OSPF_IFTYPE_POINTOPOINT)
              if (oi && oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)                {
                {                  /* Having nexthop = 0 is tempting, but NOT acceptable.
                  struct prefix_ipv4 la;                     It breaks AS-External routes with a forwarding address,
                      since ospf_ase_complete_direct_routes() will mistakenly
                      assume we've reached the last hop and should place the
                      forwarding address as nexthop.
                      Also, users may configure multi-access links in p2p mode,
                      so we need the IP to ARP the nexthop.
                   */
                   struct ospf_neighbor *nbr_w;
   
                  la.family = AF_INET;                  nbr_w = ospf_nbr_lookup_by_routerid (oi->nbrs, &l->link_id);
                  la.prefixlen = oi->address->prefixlen;                  if (nbr_w != NULL)
                     {
                       added = 1;
                       nexthop = nbr_w->src;
                     }
                 }
               else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
                 {
                   struct prefix_ipv4 la;
   
                  /* V links to W on PtMP interface                  la.family = AF_INET;
                     - find the interface address on W */                  la.prefixlen = oi->address->prefixlen;
                  while ((l2 = ospf_get_next_link (w, v, l2))) 
                    { 
                      la.prefix = l2->link_data; 
   
                      if (prefix_cmp ((struct prefix *) &la,                  /* V links to W on PtMP interface
                                      oi->address) == 0)                     - find the interface address on W */
                        /* link_data is on our PtMP network */                  while ((l2 = ospf_get_next_link (w, v, l2)))
                        break;                    {
                    }                      la.prefix = l2->link_data;
                } /* end l is on point-to-multipoint link */ 
              else 
                { 
                  /* l is a regular point-to-point link. 
                     Look for a link from W to V. 
                   */ 
                  while ((l2 = ospf_get_next_link (w, v, l2))) 
                    { 
                      oi = ospf_if_is_configured (area->ospf, 
                                                  &(l2->link_data)); 
   
                      if (oi == NULL)                      if (prefix_cmp ((struct prefix *) &la,
                        continue;                                      oi->address) != 0)
                         continue;
                       /* link_data is on our PtMP network */
                       added = 1;
                       nexthop = l2->link_data;
                       break;
                     }
                 }
   
                      if (!IPV4_ADDR_SAME (&oi->address->u.prefix4,              if (added)
                                           &l->link_data)) 
                        continue; 
 
                      break; 
                    } 
                } 
 
              if (oi && l2) 
                 {                  {
                   /* found all necessary info to build nexthop */                    /* found all necessary info to build nexthop */
                   nh = vertex_nexthop_new ();                    nh = vertex_nexthop_new ();
                   nh->oi = oi;                    nh->oi = oi;
                  nh->router = l2->link_data;                  nh->router = nexthop;
                   ospf_spf_add_parent (v, w, nh, distance);                    ospf_spf_add_parent (v, w, nh, distance);
                   return 1;                    return 1;
                 }                  }
               else                else
                zlog_info("ospf_nexthop_calculation(): "                zlog_info("%s: could not determine nexthop for link %s",
                          "could not determine nexthop for link");                          __func__, oi->ifp->name);
             } /* end point-to-point link from V to W */              } /* end point-to-point link from V to W */
           else if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK)            else if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK)
             {              {
Line 630  ospf_nexthop_calculation (struct ospf_area *area, stru Line 695  ospf_nexthop_calculation (struct ospf_area *area, stru
       else        else
         {          {
           assert(w->type == OSPF_VERTEX_NETWORK);            assert(w->type == OSPF_VERTEX_NETWORK);
          oi = ospf_if_is_configured (area->ospf, &(l->link_data));
          if (oi)          nh = vertex_nexthop_new ();
            {          nh->oi = oi;
              nh = vertex_nexthop_new ();          nh->router.s_addr = 0; /* Nexthop not required */
              nh->oi = oi;          ospf_spf_add_parent (v, w, nh, distance);
              nh->router.s_addr = 0;          return 1;
              ospf_spf_add_parent (v, w, nh, distance); 
              return 1; 
            } 
         }          }
       zlog_info("ospf_nexthop_calculation(): "  
                 "Unknown attached link");  
       return 0;  
     } /* end V is the root */      } /* end V is the root */
   /* Check if W's parent is a network connected to root. */    /* Check if W's parent is a network connected to root. */
   else if (v->type == OSPF_VERTEX_NETWORK)    else if (v->type == OSPF_VERTEX_NETWORK)
Line 673  ospf_nexthop_calculation (struct ospf_area *area, stru Line 732  ospf_nexthop_calculation (struct ospf_area *area, stru
                   added = 1;                    added = 1;
                   ospf_spf_add_parent (v, w, nh, distance);                    ospf_spf_add_parent (v, w, nh, distance);
                 }                  }
            }              /* Note lack of return is deliberate. See next comment. */
           }
         }          }
       /* NB: This code is non-trivial.        /* NB: This code is non-trivial.
        *          * 
        * E.g. it is not enough to know that V connects to the root. It is         * E.g. it is not enough to know that V connects to the root. It is
        * also important that the while above, looping through all links from         * also important that the while above, looping through all links from
        * W->V found at least one link, so that we know there is         * W->V found at least one link, so that we know there is
       * bi-directional connectivity between V and W.  Otherwise, if we       * bi-directional connectivity between V and W (which need not be the
       * /always/ return here, but don't check that W->V exists then we       * case, e.g.  when OSPF has not yet converged fully).  Otherwise, if
       * we will prevent SPF from finding/using higher cost paths..       * we /always/ return here, without having checked that root->V->-W
        * actually resulted in a valid nexthop being created, then we we will
        * prevent SPF from finding/using higher cost paths.
        *         *
       * See also bug #330, and also:       * It is important, if root->V->W has not been added, that we continue
        * through to the intervening-router nexthop code below.  So as to
        * ensure other paths to V may be used.  This avoids unnecessary
        * blackholes while OSPF is convergening.
        *         *
       * http://blogs.sun.com/paulj/entry/the_difference_a_line_makes       * I.e. we may have arrived at this function, examining V -> W, via
        * workable paths other than root -> V, and it's important to avoid
        * getting "confused" by non-working root->V->W path - it's important
        * to *not* lose the working non-root paths, just because of a
        * non-viable root->V->W.
        *
        * See also bug #330 (required reading!), and:
        *
        * http://blogs.oracle.com/paulj/entry/the_difference_a_line_makes
        */         */
       if (added)        if (added)
         return added;          return added;
Line 723  ospf_spf_next (struct vertex *v, struct ospf_area *are Line 796  ospf_spf_next (struct vertex *v, struct ospf_area *are
   u_char *lim;    u_char *lim;
   struct router_lsa_link *l = NULL;    struct router_lsa_link *l = NULL;
   struct in_addr *r;    struct in_addr *r;
  int type = 0;  int type = 0, lsa_pos=-1, lsa_pos_next=0;
   
   /* If this is a router-LSA, and bit V of the router-LSA (see Section    /* If this is a router-LSA, and bit V of the router-LSA (see Section
      A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE.  */       A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE.  */
Line 752  ospf_spf_next (struct vertex *v, struct ospf_area *are Line 825  ospf_spf_next (struct vertex *v, struct ospf_area *are
         {          {
           l = (struct router_lsa_link *) p;            l = (struct router_lsa_link *) p;
   
             lsa_pos = lsa_pos_next; /* LSA link position */
             lsa_pos_next++;
           p += (OSPF_ROUTER_LSA_LINK_SIZE +            p += (OSPF_ROUTER_LSA_LINK_SIZE +
                 (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));                  (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
   
Line 873  ospf_spf_next (struct vertex *v, struct ospf_area *are Line 948  ospf_spf_next (struct vertex *v, struct ospf_area *are
           w = ospf_vertex_new (w_lsa);            w = ospf_vertex_new (w_lsa);
   
           /* Calculate nexthop to W. */            /* Calculate nexthop to W. */
          if (ospf_nexthop_calculation (area, v, w, l, distance))          if (ospf_nexthop_calculation (area, v, w, l, distance, lsa_pos))
             pqueue_enqueue (w, candidate);              pqueue_enqueue (w, candidate);
           else if (IS_DEBUG_OSPF_EVENT)            else if (IS_DEBUG_OSPF_EVENT)
             zlog_debug ("Nexthop Calc failed");              zlog_debug ("Nexthop Calc failed");
Line 893  ospf_spf_next (struct vertex *v, struct ospf_area *are Line 968  ospf_spf_next (struct vertex *v, struct ospf_area *are
             {              {
               /* Found an equal-cost path to W.                  /* Found an equal-cost path to W.  
                * Calculate nexthop of to W from V. */                 * Calculate nexthop of to W from V. */
              ospf_nexthop_calculation (area, v, w, l, distance);              ospf_nexthop_calculation (area, v, w, l, distance, lsa_pos);
             }              }
            /* less than. */             /* less than. */
           else            else
Line 903  ospf_spf_next (struct vertex *v, struct ospf_area *are Line 978  ospf_spf_next (struct vertex *v, struct ospf_area *are
                * valid nexthop it will call spf_add_parents, which                 * valid nexthop it will call spf_add_parents, which
                * will flush the old parents                 * will flush the old parents
                */                 */
              if (ospf_nexthop_calculation (area, v, w, l, distance))              if (ospf_nexthop_calculation (area, v, w, l, distance, lsa_pos))
                 /* Decrease the key of the node in the heap.                  /* Decrease the key of the node in the heap.
                  * trickle-sort it up towards root, just in case this                   * trickle-sort it up towards root, just in case this
                  * node should now be the new root due the cost change.                    * node should now be the new root due the cost change. 
Line 939  ospf_spf_dump (struct vertex *v, int i) Line 1014  ospf_spf_dump (struct vertex *v, int i)
     for (ALL_LIST_ELEMENTS_RO (v->parents, nnode, parent))      for (ALL_LIST_ELEMENTS_RO (v->parents, nnode, parent))
       {        {
         zlog_debug (" nexthop %p %s %s",           zlog_debug (" nexthop %p %s %s", 
                    parent->nexthop,                    (void *)parent->nexthop,
                     inet_ntoa (parent->nexthop->router),                      inet_ntoa (parent->nexthop->router),
                     parent->nexthop->oi ? IF_NAME(parent->nexthop->oi)                      parent->nexthop->oi ? IF_NAME(parent->nexthop->oi)
                                         : "NULL");                                          : "NULL");
Line 969  ospf_spf_process_stubs (struct ospf_area *area, struct Line 1044  ospf_spf_process_stubs (struct ospf_area *area, struct
       u_char *lim;        u_char *lim;
       struct router_lsa_link *l;        struct router_lsa_link *l;
       struct router_lsa *rlsa;        struct router_lsa *rlsa;
         int lsa_pos = 0;
   
       if (IS_DEBUG_OSPF_EVENT)        if (IS_DEBUG_OSPF_EVENT)
         zlog_debug ("ospf_process_stubs():processing router LSA, id: %s",          zlog_debug ("ospf_process_stubs():processing router LSA, id: %s",
Line 990  ospf_spf_process_stubs (struct ospf_area *area, struct Line 1066  ospf_spf_process_stubs (struct ospf_area *area, struct
                 (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));                  (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
   
           if (l->m[0].type == LSA_LINK_TYPE_STUB)            if (l->m[0].type == LSA_LINK_TYPE_STUB)
            ospf_intra_add_stub (rt, l, v, area, parent_is_root);            ospf_intra_add_stub (rt, l, v, area, parent_is_root, lsa_pos);
           lsa_pos++;
         }          }
     }      }
   
Line 1042  ospf_rtrs_free (struct route_table *rtrs) Line 1119  ospf_rtrs_free (struct route_table *rtrs)
   route_table_finish (rtrs);    route_table_finish (rtrs);
 }  }
   
   #if 0
 static void  static void
 ospf_rtrs_print (struct route_table *rtrs)  ospf_rtrs_print (struct route_table *rtrs)
 {  {
Line 1101  ospf_rtrs_print (struct route_table *rtrs) Line 1179  ospf_rtrs_print (struct route_table *rtrs)
   
   zlog_debug ("ospf_rtrs_print() end");    zlog_debug ("ospf_rtrs_print() end");
 }  }
   #endif
   
 /* Calculating the shortest-path tree for an area. */  /* Calculating the shortest-path tree for an area. */
 static void  static void
Line 1196  ospf_spf_calculate (struct ospf_area *area, struct rou Line 1275  ospf_spf_calculate (struct ospf_area *area, struct rou
   
   /* Free candidate queue. */    /* Free candidate queue. */
   pqueue_delete (candidate);    pqueue_delete (candidate);
  
   ospf_vertex_dump (__func__, area->spf, 0, 1);    ospf_vertex_dump (__func__, area->spf, 0, 1);
   /* Free nexthop information, canonical versions of which are attached    /* Free nexthop information, canonical versions of which are attached
    * the first level of router vertices attached to the root vertex, see     * the first level of router vertices attached to the root vertex, see
    * ospf_nexthop_calculation.     * ospf_nexthop_calculation.
    */     */
   ospf_canonical_nexthops_free (area->spf);    ospf_canonical_nexthops_free (area->spf);
  
  /* Free SPF vertices, but not the list. List has ospf_vertex_free 
   * as deconstructor. 
   */ 
  list_delete_all_node (&vertex_list); 
   
   /* Increment SPF Calculation Counter. */    /* Increment SPF Calculation Counter. */
   area->spf_calculation++;    area->spf_calculation++;
   
   quagga_gettime (QUAGGA_CLK_MONOTONIC, &area->ospf->ts_spf);    quagga_gettime (QUAGGA_CLK_MONOTONIC, &area->ospf->ts_spf);
     area->ts_spf = area->ospf->ts_spf;
   
   if (IS_DEBUG_OSPF_EVENT)    if (IS_DEBUG_OSPF_EVENT)
     zlog_debug ("ospf_spf_calculate: Stop. %ld vertices",      zlog_debug ("ospf_spf_calculate: Stop. %ld vertices",
                 mtype_stats_alloc(MTYPE_OSPF_VERTEX));                  mtype_stats_alloc(MTYPE_OSPF_VERTEX));
   
     /* Free SPF vertices, but not the list. List has ospf_vertex_free
      * as deconstructor.
      */
     list_delete_all_node (&vertex_list);
 }  }
 /* Timer for SPF calculation. */  /* Timer for SPF calculation. */
 static int  static int
 ospf_spf_calculate_timer (struct thread *thread)  ospf_spf_calculate_timer (struct thread *thread)
Line 1227  ospf_spf_calculate_timer (struct thread *thread) Line 1307  ospf_spf_calculate_timer (struct thread *thread)
   struct route_table *new_table, *new_rtrs;    struct route_table *new_table, *new_rtrs;
   struct ospf_area *area;    struct ospf_area *area;
   struct listnode *node, *nnode;    struct listnode *node, *nnode;
  struct timeval start_time, stop_time, spf_start_time;
   int areas_processed = 0;
   unsigned long ia_time, prune_time, rt_time;
   unsigned long abr_time, total_spf_time, spf_time;
   char rbuf[32];                /* reason_buf */
   
   if (IS_DEBUG_OSPF_EVENT)    if (IS_DEBUG_OSPF_EVENT)
     zlog_debug ("SPF: Timer (SPF calculation expire)");      zlog_debug ("SPF: Timer (SPF calculation expire)");
   
   ospf->t_spf_calc = NULL;    ospf->t_spf_calc = NULL;
   
     quagga_gettime (QUAGGA_CLK_MONOTONIC, &spf_start_time);
   /* Allocate new table tree. */    /* Allocate new table tree. */
   new_table = route_table_init ();    new_table = route_table_init ();
   new_rtrs = route_table_init ();    new_rtrs = route_table_init ();
Line 1247  ospf_spf_calculate_timer (struct thread *thread) Line 1333  ospf_spf_calculate_timer (struct thread *thread)
        */         */
       if (ospf->backbone && ospf->backbone == area)        if (ospf->backbone && ospf->backbone == area)
         continue;          continue;
      
       ospf_spf_calculate (area, new_table, new_rtrs);        ospf_spf_calculate (area, new_table, new_rtrs);
         areas_processed++;
     }      }
  
   /* SPF for backbone, if required */    /* SPF for backbone, if required */
   if (ospf->backbone)    if (ospf->backbone)
    ospf_spf_calculate (ospf->backbone, new_table, new_rtrs);    {
        ospf_spf_calculate (ospf->backbone, new_table, new_rtrs);
       areas_processed++;
     }
 
   quagga_gettime (QUAGGA_CLK_MONOTONIC, &stop_time);
   spf_time = timeval_elapsed (stop_time, spf_start_time);
 
   ospf_vl_shut_unapproved (ospf);    ospf_vl_shut_unapproved (ospf);
   
     start_time = stop_time;       /* saving a call */
   
   ospf_ia_routing (ospf, new_table, new_rtrs);    ospf_ia_routing (ospf, new_table, new_rtrs);
   
     quagga_gettime (QUAGGA_CLK_MONOTONIC, &stop_time);
     ia_time = timeval_elapsed (stop_time, start_time);
   
     quagga_gettime (QUAGGA_CLK_MONOTONIC, &start_time);
   ospf_prune_unreachable_networks (new_table);    ospf_prune_unreachable_networks (new_table);
   ospf_prune_unreachable_routers (new_rtrs);    ospf_prune_unreachable_routers (new_rtrs);
   
     quagga_gettime (QUAGGA_CLK_MONOTONIC, &stop_time);
     prune_time = timeval_elapsed (stop_time, start_time);
   /* AS-external-LSA calculation should not be performed here. */    /* AS-external-LSA calculation should not be performed here. */
   
   /* If new Router Route is installed,    /* If new Router Route is installed,
Line 1271  ospf_spf_calculate_timer (struct thread *thread) Line 1372  ospf_spf_calculate_timer (struct thread *thread)
   
   ospf_ase_calculate_timer_add (ospf);    ospf_ase_calculate_timer_add (ospf);
   
     quagga_gettime (QUAGGA_CLK_MONOTONIC, &start_time);
   
   /* Update routing table. */    /* Update routing table. */
   ospf_route_install (ospf, new_table);    ospf_route_install (ospf, new_table);
   
     quagga_gettime (QUAGGA_CLK_MONOTONIC, &stop_time);
     rt_time = timeval_elapsed (stop_time, start_time);
   /* Update ABR/ASBR routing table */    /* Update ABR/ASBR routing table */
   if (ospf->old_rtrs)    if (ospf->old_rtrs)
     {      {
Line 1285  ospf_spf_calculate_timer (struct thread *thread) Line 1390  ospf_spf_calculate_timer (struct thread *thread)
   ospf->old_rtrs = ospf->new_rtrs;    ospf->old_rtrs = ospf->new_rtrs;
   ospf->new_rtrs = new_rtrs;    ospf->new_rtrs = new_rtrs;
   
     quagga_gettime (QUAGGA_CLK_MONOTONIC, &start_time);
   if (IS_OSPF_ABR (ospf))    if (IS_OSPF_ABR (ospf))
     ospf_abr_task (ospf);      ospf_abr_task (ospf);
   
     quagga_gettime (QUAGGA_CLK_MONOTONIC, &stop_time);
     abr_time = timeval_elapsed (stop_time, start_time);
   
     quagga_gettime (QUAGGA_CLK_MONOTONIC, &stop_time);
     total_spf_time = timeval_elapsed (stop_time, spf_start_time);
     ospf->ts_spf_duration.tv_sec = total_spf_time/1000000;
     ospf->ts_spf_duration.tv_usec = total_spf_time % 1000000;
   
     ospf_get_spf_reason_str (rbuf);
   
   if (IS_DEBUG_OSPF_EVENT)    if (IS_DEBUG_OSPF_EVENT)
    zlog_debug ("SPF: calculation complete");    {
       zlog_info ("SPF Processing Time(usecs): %ld", total_spf_time);
       zlog_info ("\t    SPF Time: %ld", spf_time);
       zlog_info ("\t   InterArea: %ld", ia_time);
       zlog_info ("\t       Prune: %ld", prune_time);
       zlog_info ("\tRouteInstall: %ld", rt_time);
       if (IS_OSPF_ABR (ospf))
         zlog_info ("\t         ABR: %ld (%d areas)",
                    abr_time, areas_processed);
       zlog_info ("Reason(s) for SPF: %s", rbuf);
     }
   
     ospf_clear_spf_reason_flags ();
   
   return 0;    return 0;
 }  }
   
 /* Add schedule for SPF calculation.  To avoid frequenst SPF calc, we  /* Add schedule for SPF calculation.  To avoid frequenst SPF calc, we
    set timer for SPF calc. */     set timer for SPF calc. */
 void  void
ospf_spf_calculate_schedule (struct ospf *ospf)ospf_spf_calculate_schedule (struct ospf *ospf, ospf_spf_reason_t reason)
 {  {
   unsigned long delay, elapsed, ht;    unsigned long delay, elapsed, ht;
   struct timeval result;    struct timeval result;
Line 1309  ospf_spf_calculate_schedule (struct ospf *ospf) Line 1437  ospf_spf_calculate_schedule (struct ospf *ospf)
   if (ospf == NULL)    if (ospf == NULL)
     return;      return;
       
     ospf_spf_set_reason (reason);
     
   /* SPF calculation timer is already scheduled. */    /* SPF calculation timer is already scheduled. */
   if (ospf->t_spf_calc)    if (ospf->t_spf_calc)
     {      {
       if (IS_DEBUG_OSPF_EVENT)        if (IS_DEBUG_OSPF_EVENT)
         zlog_debug ("SPF: calculation timer is already scheduled: %p",          zlog_debug ("SPF: calculation timer is already scheduled: %p",
                   ospf->t_spf_calc);                    (void *)ospf->t_spf_calc);
       return;        return;
     }      }
       
Line 1352  ospf_spf_calculate_schedule (struct ospf *ospf) Line 1482  ospf_spf_calculate_schedule (struct ospf *ospf)
       
   if (IS_DEBUG_OSPF_EVENT)    if (IS_DEBUG_OSPF_EVENT)
     zlog_debug ("SPF: calculation timer delay = %ld", delay);      zlog_debug ("SPF: calculation timer delay = %ld", delay);
   
     zlog_info ("SPF: Scheduled in %ld msec", delay);
   
   ospf->t_spf_calc =    ospf->t_spf_calc =
     thread_add_timer_msec (master, ospf_spf_calculate_timer, ospf, delay);      thread_add_timer_msec (master, ospf_spf_calculate_timer, ospf, delay);

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.4


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