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

version 1.1.1.3, 2013/07/21 23:54:40 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 547  ospf_nexthop_calculation (struct ospf_area *area, stru Line 590  ospf_nexthop_calculation (struct ospf_area *area, stru
   
           if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT)            if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT)
             {              {
              struct in_addr nexthop;              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
Line 568  ospf_nexthop_calculation (struct ospf_area *area, stru Line 611  ospf_nexthop_calculation (struct ospf_area *area, stru
               */                */
               if (oi->type == OSPF_IFTYPE_POINTOPOINT)                if (oi->type == OSPF_IFTYPE_POINTOPOINT)
                 {                  {
                  added = 1;                  /* Having nexthop = 0 is tempting, but NOT acceptable.
                  nexthop.s_addr = 0; /* Nexthop not required */                     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;
 
                   nbr_w = ospf_nbr_lookup_by_routerid (oi->nbrs, &l->link_id);
                   if (nbr_w != NULL)
                     {
                       added = 1;
                       nexthop = nbr_w->src;
                     }
                 }                  }
               else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)                else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
                 {                  {
Line 957  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 1218  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 1249  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 1269  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 1293  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 1307  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 1331  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 1374  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.3  
changed lines
  Added in v.1.1.1.4


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