Diff for /embedaddon/quagga/isisd/isis_spf.c between versions 1.1.1.1 and 1.1.1.3

version 1.1.1.1, 2012/02/21 17:26:11 version 1.1.1.3, 2013/07/21 23:54:38
Line 36 Line 36
   
 #include "isis_constants.h"  #include "isis_constants.h"
 #include "isis_common.h"  #include "isis_common.h"
   #include "isis_flags.h"
 #include "dict.h"  #include "dict.h"
 #include "isisd.h"  #include "isisd.h"
 #include "isis_misc.h"  #include "isis_misc.h"
Line 49 Line 50
 #include "isis_route.h"  #include "isis_route.h"
 #include "isis_csm.h"  #include "isis_csm.h"
   
 extern struct isis *isis;  
 extern struct thread_master *master;  
 extern struct host host;  
   
 int isis_run_spf_l1 (struct thread *thread);  int isis_run_spf_l1 (struct thread *thread);
 int isis_run_spf_l2 (struct thread *thread);  int isis_run_spf_l2 (struct thread *thread);
   
Line 113  remove_excess_adjs (struct list *adjs) Line 110  remove_excess_adjs (struct list *adjs)
   return;    return;
 }  }
   
 #ifdef EXTREME_DEBUG  
 static const char *  static const char *
 vtype2string (enum vertextype vtype)  vtype2string (enum vertextype vtype)
 {  {
Line 164  vid2string (struct isis_vertex *vertex, u_char * buff) Line 160  vid2string (struct isis_vertex *vertex, u_char * buff)
     {      {
     case VTYPE_PSEUDO_IS:      case VTYPE_PSEUDO_IS:
     case VTYPE_PSEUDO_TE_IS:      case VTYPE_PSEUDO_TE_IS:
      return rawlspid_print (vertex->N.id);      return print_sys_hostname (vertex->N.id);
       break;        break;
     case VTYPE_NONPSEUDO_IS:      case VTYPE_NONPSEUDO_IS:
     case VTYPE_NONPSEUDO_TE_IS:      case VTYPE_NONPSEUDO_TE_IS:
     case VTYPE_ES:      case VTYPE_ES:
      return sysid_print (vertex->N.id);      return print_sys_hostname (vertex->N.id);
       break;        break;
     case VTYPE_IPREACH_INTERNAL:      case VTYPE_IPREACH_INTERNAL:
     case VTYPE_IPREACH_EXTERNAL:      case VTYPE_IPREACH_EXTERNAL:
Line 186  vid2string (struct isis_vertex *vertex, u_char * buff) Line 182  vid2string (struct isis_vertex *vertex, u_char * buff)
   
   return (char *) buff;    return (char *) buff;
 }  }
 #endif /* EXTREME_DEBUG */  
   
static struct isis_spftree *static struct isis_vertex *
isis_spftree_new ()isis_vertex_new (void *id, enum vertextype vtype)
 {  {
  struct isis_spftree *tree;  struct isis_vertex *vertex;
   
  tree = XCALLOC (MTYPE_ISIS_SPFTREE, sizeof (struct isis_spftree));  vertex = XCALLOC (MTYPE_ISIS_VERTEX, sizeof (struct isis_vertex));
  if (tree == NULL)  if (vertex == NULL)
     {      {
      zlog_err ("ISIS-Spf: isis_spftree_new Out of memory!");      zlog_err ("isis_vertex_new Out of memory!");
       return NULL;        return NULL;
     }      }
   
  tree->tents = list_new ();  vertex->type = vtype;
  tree->paths = list_new ();  switch (vtype)
  return tree;    {
     case VTYPE_ES:
     case VTYPE_NONPSEUDO_IS:
     case VTYPE_NONPSEUDO_TE_IS:
       memcpy (vertex->N.id, (u_char *) id, ISIS_SYS_ID_LEN);
       break;
     case VTYPE_PSEUDO_IS:
     case VTYPE_PSEUDO_TE_IS:
       memcpy (vertex->N.id, (u_char *) id, ISIS_SYS_ID_LEN + 1);
       break;
     case VTYPE_IPREACH_INTERNAL:
     case VTYPE_IPREACH_EXTERNAL:
     case VTYPE_IPREACH_TE:
 #ifdef HAVE_IPV6
     case VTYPE_IP6REACH_INTERNAL:
     case VTYPE_IP6REACH_EXTERNAL:
 #endif /* HAVE_IPV6 */
       memcpy (&vertex->N.prefix, (struct prefix *) id,
               sizeof (struct prefix));
       break;
     default:
       zlog_err ("WTF!");
     }
 
   vertex->Adj_N = list_new ();
   vertex->parents = list_new ();
   vertex->children = list_new ();
 
   return vertex;
 }  }
   
 static void  static void
 isis_vertex_del (struct isis_vertex *vertex)  isis_vertex_del (struct isis_vertex *vertex)
 {  {
   list_delete (vertex->Adj_N);    list_delete (vertex->Adj_N);
     vertex->Adj_N = NULL;
     list_delete (vertex->parents);
     vertex->parents = NULL;
     list_delete (vertex->children);
     vertex->children = NULL;
   
     memset(vertex, 0, sizeof(struct isis_vertex));
   XFREE (MTYPE_ISIS_VERTEX, vertex);    XFREE (MTYPE_ISIS_VERTEX, vertex);
   
   return;    return;
 }  }
   
 #if 0 /* HT: Not used yet. */  
 static void  static void
   isis_vertex_adj_del (struct isis_vertex *vertex, struct isis_adjacency *adj)
   {
     struct listnode *node, *nextnode;
     if (!vertex)
       return;
     for (node = listhead (vertex->Adj_N); node; node = nextnode)
     {
       nextnode = listnextnode(node);
       if (listgetdata(node) == adj)
         list_delete_node(vertex->Adj_N, node);
     }
     return;
   }
   
   struct isis_spftree *
   isis_spftree_new (struct isis_area *area)
   {
     struct isis_spftree *tree;
   
     tree = XCALLOC (MTYPE_ISIS_SPFTREE, sizeof (struct isis_spftree));
     if (tree == NULL)
       {
         zlog_err ("ISIS-Spf: isis_spftree_new Out of memory!");
         return NULL;
       }
   
     tree->tents = list_new ();
     tree->paths = list_new ();
     tree->area = area;
     tree->last_run_timestamp = 0;
     tree->last_run_duration = 0;
     tree->runcount = 0;
     tree->pending = 0;
     return tree;
   }
   
   void
 isis_spftree_del (struct isis_spftree *spftree)  isis_spftree_del (struct isis_spftree *spftree)
 {  {
     THREAD_TIMER_OFF (spftree->t_spf);
   
   spftree->tents->del = (void (*)(void *)) isis_vertex_del;    spftree->tents->del = (void (*)(void *)) isis_vertex_del;
   list_delete (spftree->tents);    list_delete (spftree->tents);
     spftree->tents = NULL;
   
   spftree->paths->del = (void (*)(void *)) isis_vertex_del;    spftree->paths->del = (void (*)(void *)) isis_vertex_del;
   list_delete (spftree->paths);    list_delete (spftree->paths);
     spftree->paths = NULL;
   
   XFREE (MTYPE_ISIS_SPFTREE, spftree);    XFREE (MTYPE_ISIS_SPFTREE, spftree);
   
   return;    return;
 }  }
 #endif   
   
 void  void
   isis_spftree_adj_del (struct isis_spftree *spftree, struct isis_adjacency *adj)
   {
     struct listnode *node;
     if (!adj)
       return;
     for (node = listhead (spftree->tents); node; node = listnextnode (node))
       isis_vertex_adj_del (listgetdata (node), adj);
     for (node = listhead (spftree->paths); node; node = listnextnode (node))
       isis_vertex_adj_del (listgetdata (node), adj);
     return;
   }
   
   void
 spftree_area_init (struct isis_area *area)  spftree_area_init (struct isis_area *area)
 {  {
  if ((area->is_type & IS_LEVEL_1) && area->spftree[0] == NULL)  if (area->is_type & IS_LEVEL_1)
    {  {
      area->spftree[0] = isis_spftree_new ();    if (area->spftree[0] == NULL)
       area->spftree[0] = isis_spftree_new (area);
 #ifdef HAVE_IPV6  #ifdef HAVE_IPV6
      area->spftree6[0] = isis_spftree_new ();    if (area->spftree6[0] == NULL)
       area->spftree6[0] = isis_spftree_new (area);
 #endif  #endif
     }
   
      /*    thread_add_timer (master, isis_run_spf_l1, area,   if (area->is_type & IS_LEVEL_2)
         isis_jitter (PERIODIC_SPF_INTERVAL, 10)); */  {
    }    if (area->spftree[1] == NULL)
      area->spftree[1] = isis_spftree_new (area);
  if ((area->is_type & IS_LEVEL_2) && area->spftree[1] == NULL) 
    { 
      area->spftree[1] = isis_spftree_new (); 
 #ifdef HAVE_IPV6  #ifdef HAVE_IPV6
      area->spftree6[1] = isis_spftree_new ();    if (area->spftree6[1] == NULL)
       area->spftree6[1] = isis_spftree_new (area);
 #endif  #endif
      /*    thread_add_timer (master, isis_run_spf_l2, area,   }
         isis_jitter (PERIODIC_SPF_INTERVAL, 10)); */ 
    } 
   
   return;    return;
 }  }
   
static struct isis_vertex *void
isis_vertex_new (void *id, enum vertextype vtype)spftree_area_del (struct isis_area *area)
 {  {
  struct isis_vertex *vertex;  if (area->is_type & IS_LEVEL_1)
  {
  vertex = XCALLOC (MTYPE_ISIS_VERTEX, sizeof (struct isis_vertex));    if (area->spftree[0] != NULL)
  if (vertex == NULL) 
     {      {
      zlog_err ("isis_vertex_new Out of memory!");      isis_spftree_del (area->spftree[0]);
      return NULL;      area->spftree[0] = NULL;
     }      }
   #ifdef HAVE_IPV6
       if (area->spftree6[0])
       {
         isis_spftree_del (area->spftree6[0]);
         area->spftree6[0] = NULL;
       }
   #endif
     }
   
  vertex->type = vtype;  if (area->is_type & IS_LEVEL_2)
  switch (vtype)  {
     if (area->spftree[1] != NULL)
     {      {
    case VTYPE_ES:      isis_spftree_del (area->spftree[1]);
    case VTYPE_NONPSEUDO_IS:      area->spftree[1] = NULL;
    case VTYPE_NONPSEUDO_TE_IS:    }
      memcpy (vertex->N.id, (u_char *) id, ISIS_SYS_ID_LEN); 
      break; 
    case VTYPE_PSEUDO_IS: 
    case VTYPE_PSEUDO_TE_IS: 
      memcpy (vertex->N.id, (u_char *) id, ISIS_SYS_ID_LEN + 1); 
      break; 
    case VTYPE_IPREACH_INTERNAL: 
    case VTYPE_IPREACH_EXTERNAL: 
    case VTYPE_IPREACH_TE: 
 #ifdef HAVE_IPV6  #ifdef HAVE_IPV6
    case VTYPE_IP6REACH_INTERNAL:    if (area->spftree6[1] != NULL)
    case VTYPE_IP6REACH_EXTERNAL:    {
#endif /* HAVE_IPV6 */      isis_spftree_del (area->spftree6[1]);
      memcpy (&vertex->N.prefix, (struct prefix *) id,      area->spftree6[1] = NULL;
              sizeof (struct prefix)); 
      break; 
    default: 
      zlog_err ("WTF!"); 
     }      }
   #endif
     }
   
  vertex->Adj_N = list_new ();  return;
 }
   
  return vertex;void
 spftree_area_adj_del (struct isis_area *area, struct isis_adjacency *adj)
 {
   if (area->is_type & IS_LEVEL_1)
   {
     if (area->spftree[0] != NULL)
       isis_spftree_adj_del (area->spftree[0], adj);
 #ifdef HAVE_IPV6
     if (area->spftree6[0] != NULL)
       isis_spftree_adj_del (area->spftree6[0], adj);
 #endif
   }
 
   if (area->is_type & IS_LEVEL_2)
   {
     if (area->spftree[1] != NULL)
       isis_spftree_adj_del (area->spftree[1], adj);
 #ifdef HAVE_IPV6
     if (area->spftree6[1] != NULL)
       isis_spftree_adj_del (area->spftree6[1], adj);
 #endif
   }
 
   return;
 }  }
   
   /* 
    * Find the system LSP: returns the LSP in our LSP database 
    * associated with the given system ID.
    */
   static struct isis_lsp *
   isis_root_system_lsp (struct isis_area *area, int level, u_char *sysid)
   {
     struct isis_lsp *lsp;
     u_char lspid[ISIS_SYS_ID_LEN + 2];
   
     memcpy (lspid, sysid, ISIS_SYS_ID_LEN);
     LSP_PSEUDO_ID (lspid) = 0;
     LSP_FRAGMENT (lspid) = 0;
     lsp = lsp_search (lspid, area->lspdb[level - 1]);
     if (lsp && lsp->lsp_header->rem_lifetime != 0)
       return lsp;
     return NULL;
   }
   
 /*  /*
  * Add this IS to the root of SPT   * Add this IS to the root of SPT
  */   */
static voidstatic struct isis_vertex *
isis_spf_add_self (struct isis_spftree *spftree, struct isis_area *area,isis_spf_add_root (struct isis_spftree *spftree, int level, u_char *sysid)
                   int level) 
 {  {
   struct isis_vertex *vertex;    struct isis_vertex *vertex;
   struct isis_lsp *lsp;    struct isis_lsp *lsp;
   u_char lspid[ISIS_SYS_ID_LEN + 2];  
 #ifdef EXTREME_DEBUG  #ifdef EXTREME_DEBUG
   u_char buff[BUFSIZ];    u_char buff[BUFSIZ];
 #endif /* EXTREME_DEBUG */  #endif /* EXTREME_DEBUG */
   memcpy (lspid, isis->sysid, ISIS_SYS_ID_LEN);  
   LSP_PSEUDO_ID (lspid) = 0;  
   LSP_FRAGMENT (lspid) = 0;  
   
  lsp = lsp_search (lspid, area->lspdb[level - 1]);  lsp = isis_root_system_lsp (spftree->area, level, sysid);
 
   if (lsp == NULL)    if (lsp == NULL)
     zlog_warn ("ISIS-Spf: could not find own l%d LSP!", level);      zlog_warn ("ISIS-Spf: could not find own l%d LSP!", level);
   
  if (!area->oldmetric)  if (!spftree->area->oldmetric)
    vertex = isis_vertex_new (isis->sysid, VTYPE_NONPSEUDO_TE_IS);    vertex = isis_vertex_new (sysid, VTYPE_NONPSEUDO_TE_IS);
   else    else
    vertex = isis_vertex_new (isis->sysid, VTYPE_NONPSEUDO_IS);    vertex = isis_vertex_new (sysid, VTYPE_NONPSEUDO_IS);
   
   vertex->lsp = lsp;  
   
   listnode_add (spftree->paths, vertex);    listnode_add (spftree->paths, vertex);
   
 #ifdef EXTREME_DEBUG  #ifdef EXTREME_DEBUG
Line 338  isis_spf_add_self (struct isis_spftree *spftree, struc Line 450  isis_spf_add_self (struct isis_spftree *spftree, struc
               vertex->depth, vertex->d_N);                vertex->depth, vertex->d_N);
 #endif /* EXTREME_DEBUG */  #endif /* EXTREME_DEBUG */
   
  return;  return vertex;
 }  }
   
 static struct isis_vertex *  static struct isis_vertex *
Line 390  isis_find_vertex (struct list *list, void *id, enum ve Line 502  isis_find_vertex (struct list *list, void *id, enum ve
  */   */
 static struct isis_vertex *  static struct isis_vertex *
 isis_spf_add2tent (struct isis_spftree *spftree, enum vertextype vtype,  isis_spf_add2tent (struct isis_spftree *spftree, enum vertextype vtype,
                   void *id, struct isis_adjacency *adj, u_int32_t cost,                   void *id, uint32_t cost, int depth, int family,
                   int depth, int family)                   struct isis_adjacency *adj, struct isis_vertex *parent)
 {  {
   struct isis_vertex *vertex, *v;    struct isis_vertex *vertex, *v;
   struct listnode *node;    struct listnode *node;
     struct isis_adjacency *parent_adj;
 #ifdef EXTREME_DEBUG  #ifdef EXTREME_DEBUG
   u_char buff[BUFSIZ];    u_char buff[BUFSIZ];
 #endif  #endif
   
     assert (isis_find_vertex (spftree->paths, id, vtype) == NULL);
     assert (isis_find_vertex (spftree->tents, id, vtype) == NULL);
   vertex = isis_vertex_new (id, vtype);    vertex = isis_vertex_new (id, vtype);
   vertex->d_N = cost;    vertex->d_N = cost;
   vertex->depth = depth;    vertex->depth = depth;
   
  if (adj)  if (parent) {
     listnode_add (vertex->parents, parent);
     if (listnode_lookup (parent->children, vertex) == NULL)
       listnode_add (parent->children, vertex);
   }
 
   if (parent && parent->Adj_N && listcount(parent->Adj_N) > 0) {
     for (ALL_LIST_ELEMENTS_RO (parent->Adj_N, node, parent_adj))
       listnode_add (vertex->Adj_N, parent_adj);
   } else if (adj) {
     listnode_add (vertex->Adj_N, adj);      listnode_add (vertex->Adj_N, adj);
     }
   
 #ifdef EXTREME_DEBUG  #ifdef EXTREME_DEBUG
  zlog_debug ("ISIS-Spf: add to TENT  %s %s depth %d dist %d",  zlog_debug ("ISIS-Spf: add to TENT %s %s %s depth %d dist %d adjcount %d",
               print_sys_hostname (vertex->N.id),
               vtype2string (vertex->type), vid2string (vertex, buff),                vtype2string (vertex->type), vid2string (vertex, buff),
              vertex->depth, vertex->d_N);              vertex->depth, vertex->d_N, listcount(vertex->Adj_N));
 #endif /* EXTREME_DEBUG */  #endif /* EXTREME_DEBUG */
  listnode_add (spftree->tents, vertex);
   if (list_isempty (spftree->tents))    if (list_isempty (spftree->tents))
     {      {
       listnode_add (spftree->tents, vertex);        listnode_add (spftree->tents, vertex);
       return vertex;        return vertex;
     }      }
  
  /* XXX: This cant use the standard ALL_LIST_ELEMENT macro */  /* XXX: This cant use the standard ALL_LIST_ELEMENTS macro */
   for (node = listhead (spftree->tents); node; node = listnextnode (node))    for (node = listhead (spftree->tents); node; node = listnextnode (node))
     {      {
       v = listgetdata (node);        v = listgetdata (node);
Line 426  isis_spf_add2tent (struct isis_spftree *spftree, enum  Line 553  isis_spf_add2tent (struct isis_spftree *spftree, enum 
           list_add_node_prev (spftree->tents, node, vertex);            list_add_node_prev (spftree->tents, node, vertex);
           break;            break;
         }          }
      else if (v->d_N == vertex->d_N)      else if (v->d_N == vertex->d_N && v->type > vertex->type)
         {          {
           /*  Tie break, add according to type */            /*  Tie break, add according to type */
          while (v && v->d_N == vertex->d_N && v->type > vertex->type)          list_add_node_prev (spftree->tents, node, vertex);
            { 
              if (v->type > vertex->type) 
                { 
                  break; 
                } 
              /* XXX: this seems dubious, node is the loop iterator */ 
              node = listnextnode (node); 
              (node) ? (v = listgetdata (node)) : (v = NULL); 
            } 
          list_add_node_prev (spftree->tents, node, vertex); 
           break;            break;
         }          }
       else if (node->next == NULL)  
         {  
           list_add_node_next (spftree->tents, node, vertex);  
           break;  
         }  
     }      }
   
     if (node == NULL)
         listnode_add (spftree->tents, vertex);
   
   return vertex;    return vertex;
 }  }
   
static struct isis_vertex *static void
 isis_spf_add_local (struct isis_spftree *spftree, enum vertextype vtype,  isis_spf_add_local (struct isis_spftree *spftree, enum vertextype vtype,
                    void *id, struct isis_adjacency *adj, u_int32_t cost,                    void *id, struct isis_adjacency *adj, uint32_t cost,
                    int family)                    int family, struct isis_vertex *parent)
 {  {
   struct isis_vertex *vertex;    struct isis_vertex *vertex;
   
Line 470  isis_spf_add_local (struct isis_spftree *spftree, enum Line 586  isis_spf_add_local (struct isis_spftree *spftree, enum
           /*       d) */            /*       d) */
           if (listcount (vertex->Adj_N) > ISIS_MAX_PATH_SPLITS)            if (listcount (vertex->Adj_N) > ISIS_MAX_PATH_SPLITS)
             remove_excess_adjs (vertex->Adj_N);              remove_excess_adjs (vertex->Adj_N);
             if (parent && (listnode_lookup (vertex->parents, parent) == NULL))
               listnode_add (vertex->parents, parent);
             if (parent && (listnode_lookup (parent->children, vertex) == NULL))
               listnode_add (parent->children, vertex);
             return;
         }          }
      /*         f) */      else if (vertex->d_N < cost)
      else if (vertex->d_N > cost) 
         {          {
          listnode_delete (spftree->tents, vertex);          /*       e) do nothing */
          goto add2tent;          return;
         }          }
      /*       e) do nothing */      else {  /* vertex->d_N > cost */
      return vertex;          /*         f) */
           struct listnode *pnode, *pnextnode;
           struct isis_vertex *pvertex;
           listnode_delete (spftree->tents, vertex);
           assert (listcount (vertex->children) == 0);
           for (ALL_LIST_ELEMENTS (vertex->parents, pnode, pnextnode, pvertex))
             listnode_delete(pvertex->children, vertex);
           isis_vertex_del (vertex);
       }
     }      }
   
add2tent:  isis_spf_add2tent (spftree, vtype, id, cost, 1, family, adj, parent);
  return isis_spf_add2tent (spftree, vtype, id, adj, cost, 1, family);  return;
 }  }
   
 static void  static void
 process_N (struct isis_spftree *spftree, enum vertextype vtype, void *id,  process_N (struct isis_spftree *spftree, enum vertextype vtype, void *id,
           u_int16_t dist, u_int16_t depth, struct isis_adjacency *adj,           uint32_t dist, uint16_t depth, int family,
           int family)           struct isis_vertex *parent)
 {  {
   struct isis_vertex *vertex;    struct isis_vertex *vertex;
 #ifdef EXTREME_DEBUG  #ifdef EXTREME_DEBUG
   u_char buff[255];    u_char buff[255];
 #endif  #endif
   
     assert (spftree && parent);
   
     /* RFC3787 section 5.1 */
     if (spftree->area->newmetric == 1)
       {
         if (dist > MAX_WIDE_PATH_METRIC)
           return;
       }
   /* C.2.6 b)    */    /* C.2.6 b)    */
  if (dist > MAX_PATH_METRIC)  else if (spftree->area->oldmetric == 1)
    return;    {
       if (dist > MAX_NARROW_PATH_METRIC)
         return;
     }
 
   /*       c)    */    /*       c)    */
   vertex = isis_find_vertex (spftree->paths, id, vtype);    vertex = isis_find_vertex (spftree->paths, id, vtype);
   if (vertex)    if (vertex)
     {      {
 #ifdef EXTREME_DEBUG  #ifdef EXTREME_DEBUG
      zlog_debug ("ISIS-Spf: process_N  %s %s dist %d already found from PATH",      zlog_debug ("ISIS-Spf: process_N %s %s %s dist %d already found from PATH",
                   print_sys_hostname (vertex->N.id),
                   vtype2string (vtype), vid2string (vertex, buff), dist);                    vtype2string (vtype), vid2string (vertex, buff), dist);
 #endif /* EXTREME_DEBUG */  #endif /* EXTREME_DEBUG */
       assert (dist >= vertex->d_N);        assert (dist >= vertex->d_N);
Line 516  process_N (struct isis_spftree *spftree, enum vertexty Line 657  process_N (struct isis_spftree *spftree, enum vertexty
     {      {
       /*        1) */        /*        1) */
 #ifdef EXTREME_DEBUG  #ifdef EXTREME_DEBUG
      zlog_debug ("ISIS-Spf: process_N  %s %s dist %d",      zlog_debug ("ISIS-Spf: process_N %s %s %s dist %d parent %s adjcount %d",
                  vtype2string (vtype), vid2string (vertex, buff), dist);                  print_sys_hostname (vertex->N.id),
                   vtype2string (vtype), vid2string (vertex, buff), dist,
                   (parent ? print_sys_hostname (parent->N.id) : "null"),
                   (parent ? listcount (parent->Adj_N) : 0));
 #endif /* EXTREME_DEBUG */  #endif /* EXTREME_DEBUG */
       if (vertex->d_N == dist)        if (vertex->d_N == dist)
         {          {
          if (adj)          struct listnode *node;
            listnode_add (vertex->Adj_N, adj);          struct isis_adjacency *parent_adj;
           for (ALL_LIST_ELEMENTS_RO (parent->Adj_N, node, parent_adj))
             if (listnode_lookup(vertex->Adj_N, parent_adj) == NULL)
               listnode_add (vertex->Adj_N, parent_adj);
           /*      2) */            /*      2) */
           if (listcount (vertex->Adj_N) > ISIS_MAX_PATH_SPLITS)            if (listcount (vertex->Adj_N) > ISIS_MAX_PATH_SPLITS)
             remove_excess_adjs (vertex->Adj_N);              remove_excess_adjs (vertex->Adj_N);
             if (listnode_lookup (vertex->parents, parent) == NULL)
               listnode_add (vertex->parents, parent);
             if (listnode_lookup (parent->children, vertex) == NULL)
               listnode_add (parent->children, vertex);
           /*      3) */            /*      3) */
           return;            return;
         }          }
Line 536  process_N (struct isis_spftree *spftree, enum vertexty Line 687  process_N (struct isis_spftree *spftree, enum vertexty
         }          }
       else        else
         {          {
             struct listnode *pnode, *pnextnode;
             struct isis_vertex *pvertex;
           listnode_delete (spftree->tents, vertex);            listnode_delete (spftree->tents, vertex);
             assert (listcount (vertex->children) == 0);
             for (ALL_LIST_ELEMENTS (vertex->parents, pnode, pnextnode, pvertex))
               listnode_delete(pvertex->children, vertex);
             isis_vertex_del (vertex);
         }          }
     }      }
   
  isis_spf_add2tent (spftree, vtype, id, adj, dist, depth, family);#ifdef EXTREME_DEBUG
   zlog_debug ("ISIS-Spf: process_N add2tent %s %s dist %d parent %s",
               print_sys_hostname(id), vtype2string (vtype), dist,
               (parent ? print_sys_hostname (parent->N.id) : "null"));
 #endif /* EXTREME_DEBUG */
 
   isis_spf_add2tent (spftree, vtype, id, dist, depth, family, NULL, parent);
   return;    return;
 }  }
   
Line 549  process_N (struct isis_spftree *spftree, enum vertexty Line 712  process_N (struct isis_spftree *spftree, enum vertexty
  */   */
 static int  static int
 isis_spf_process_lsp (struct isis_spftree *spftree, struct isis_lsp *lsp,  isis_spf_process_lsp (struct isis_spftree *spftree, struct isis_lsp *lsp,
                      uint32_t cost, uint16_t depth, int family)                      uint32_t cost, uint16_t depth, int family,
                       u_char *root_sysid, struct isis_vertex *parent)
 {  {
   struct listnode *node, *fragnode = NULL;    struct listnode *node, *fragnode = NULL;
  u_int16_t dist;  uint32_t dist;
   struct is_neigh *is_neigh;    struct is_neigh *is_neigh;
   struct te_is_neigh *te_is_neigh;    struct te_is_neigh *te_is_neigh;
   struct ipv4_reachability *ipreach;    struct ipv4_reachability *ipreach;
Line 562  isis_spf_process_lsp (struct isis_spftree *spftree, st Line 726  isis_spf_process_lsp (struct isis_spftree *spftree, st
 #ifdef HAVE_IPV6  #ifdef HAVE_IPV6
   struct ipv6_reachability *ip6reach;    struct ipv6_reachability *ip6reach;
 #endif /* HAVE_IPV6 */  #endif /* HAVE_IPV6 */
     static const u_char null_sysid[ISIS_SYS_ID_LEN];
   
  if (!speaks (lsp->tlv_data.nlpids, family))
  if (!lsp->adj) 
    return ISIS_WARNING; 
  if (lsp->tlv_data.nlpids == NULL || !speaks (lsp->tlv_data.nlpids, family)) 
     return ISIS_OK;      return ISIS_OK;
   
 lspfragloop:  lspfragloop:
   if (lsp->lsp_header->seq_num == 0)    if (lsp->lsp_header->seq_num == 0)
     {      {
      zlog_warn ("isis_spf_process_lsp(): lsp with 0 seq_num"      zlog_warn ("isis_spf_process_lsp(): lsp with 0 seq_num - ignore");
                 " - do not process"); 
       return ISIS_WARNING;        return ISIS_WARNING;
     }      }
   
   #ifdef EXTREME_DEBUG
         zlog_debug ("ISIS-Spf: process_lsp %s", print_sys_hostname(lsp->lsp_header->lsp_id));
   #endif /* EXTREME_DEBUG */
   
   if (!ISIS_MASK_LSP_OL_BIT (lsp->lsp_header->lsp_bits))    if (!ISIS_MASK_LSP_OL_BIT (lsp->lsp_header->lsp_bits))
     {
       if (lsp->tlv_data.is_neighs)
     {      {
      if (lsp->tlv_data.is_neighs)      for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.is_neighs, node, is_neigh))
        {      {
          for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.is_neighs, node, is_neigh))        /* C.2.6 a) */
            {        /* Two way connectivity */
              /* C.2.6 a) */        if (!memcmp (is_neigh->neigh_id, root_sysid, ISIS_SYS_ID_LEN))
              /* Two way connectivity */          continue;
              if (!memcmp (is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN))        if (!memcmp (is_neigh->neigh_id, null_sysid, ISIS_SYS_ID_LEN))
                continue;          continue;
              dist = cost + is_neigh->metrics.metric_default;        dist = cost + is_neigh->metrics.metric_default;
              vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS        vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS
                : VTYPE_NONPSEUDO_IS;          : VTYPE_NONPSEUDO_IS;
              process_N (spftree, vtype, (void *) is_neigh->neigh_id, dist,        process_N (spftree, vtype, (void *) is_neigh->neigh_id, dist,
                         depth + 1, lsp->adj, family);            depth + 1, family, parent);
            }      }
        }    }
      if (lsp->tlv_data.te_is_neighs)    if (lsp->tlv_data.te_is_neighs)
        {    {
          for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_is_neighs, node,      for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_is_neighs, node,
                                     te_is_neigh))            te_is_neigh))
            {      {
              uint32_t metric;        if (!memcmp (te_is_neigh->neigh_id, root_sysid, ISIS_SYS_ID_LEN))
              if (!memcmp (te_is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN))          continue;
                continue;        if (!memcmp (te_is_neigh->neigh_id, null_sysid, ISIS_SYS_ID_LEN))
              memcpy (&metric, te_is_neigh->te_metric, 3);          continue;
              dist = cost + ntohl (metric << 8);        dist = cost + GET_TE_METRIC(te_is_neigh);
              vtype = LSP_PSEUDO_ID (te_is_neigh->neigh_id) ? VTYPE_PSEUDO_TE_IS        vtype = LSP_PSEUDO_ID (te_is_neigh->neigh_id) ? VTYPE_PSEUDO_TE_IS
                : VTYPE_NONPSEUDO_TE_IS;          : VTYPE_NONPSEUDO_TE_IS;
              process_N (spftree, vtype, (void *) te_is_neigh->neigh_id, dist,        process_N (spftree, vtype, (void *) te_is_neigh->neigh_id, dist,
                         depth + 1, lsp->adj, family);            depth + 1, family, parent);
            }      }
        }    }
      if (family == AF_INET && lsp->tlv_data.ipv4_int_reachs)  }
        { 
          prefix.family = AF_INET; 
          for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_int_reachs,  
                                     node, ipreach)) 
            { 
              dist = cost + ipreach->metrics.metric_default; 
              vtype = VTYPE_IPREACH_INTERNAL; 
              prefix.u.prefix4 = ipreach->prefix; 
              prefix.prefixlen = ip_masklen (ipreach->mask); 
              process_N (spftree, vtype, (void *) &prefix, dist, depth + 1, 
                         lsp->adj, family); 
            } 
        } 
   
      if (family == AF_INET && lsp->tlv_data.ipv4_ext_reachs)  if (family == AF_INET && lsp->tlv_data.ipv4_int_reachs)
        {  {
          prefix.family = AF_INET;    prefix.family = AF_INET;
          for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_ext_reachs,    for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_int_reachs, node, ipreach))
                                     node, ipreach))    {
            {      dist = cost + ipreach->metrics.metric_default;
              dist = cost + ipreach->metrics.metric_default;      vtype = VTYPE_IPREACH_INTERNAL;
              vtype = VTYPE_IPREACH_EXTERNAL;      prefix.u.prefix4 = ipreach->prefix;
              prefix.u.prefix4 = ipreach->prefix;      prefix.prefixlen = ip_masklen (ipreach->mask);
              prefix.prefixlen = ip_masklen (ipreach->mask);      apply_mask (&prefix);
              process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,      process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
                         lsp->adj, family);                 family, parent);
            }    }
        }  }
      if (family == AF_INET && lsp->tlv_data.te_ipv4_reachs)  if (family == AF_INET && lsp->tlv_data.ipv4_ext_reachs)
        {  {
          prefix.family = AF_INET;    prefix.family = AF_INET;
          for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_ipv4_reachs,    for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_ext_reachs, node, ipreach))
                                     node, te_ipv4_reach))    {
            {      dist = cost + ipreach->metrics.metric_default;
              dist = cost + ntohl (te_ipv4_reach->te_metric);      vtype = VTYPE_IPREACH_EXTERNAL;
              vtype = VTYPE_IPREACH_TE;      prefix.u.prefix4 = ipreach->prefix;
              prefix.u.prefix4 = newprefix2inaddr (&te_ipv4_reach->prefix_start,      prefix.prefixlen = ip_masklen (ipreach->mask);
                                                   te_ipv4_reach->control);      apply_mask (&prefix);
              prefix.prefixlen = (te_ipv4_reach->control & 0x3F);      process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
              process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,                 family, parent);
                         lsp->adj, family);    }
            }  }
        }  if (family == AF_INET && lsp->tlv_data.te_ipv4_reachs)
   {
     prefix.family = AF_INET;
     for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_ipv4_reachs,
                                node, te_ipv4_reach))
     {
       assert ((te_ipv4_reach->control & 0x3F) <= IPV4_MAX_BITLEN);
 
       dist = cost + ntohl (te_ipv4_reach->te_metric);
       vtype = VTYPE_IPREACH_TE;
       prefix.u.prefix4 = newprefix2inaddr (&te_ipv4_reach->prefix_start,
                                            te_ipv4_reach->control);
       prefix.prefixlen = (te_ipv4_reach->control & 0x3F);
       apply_mask (&prefix);
       process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
                  family, parent);
     }
   }
 #ifdef HAVE_IPV6  #ifdef HAVE_IPV6
      if (family == AF_INET6 && lsp->tlv_data.ipv6_reachs)  if (family == AF_INET6 && lsp->tlv_data.ipv6_reachs)
        {  {
          prefix.family = AF_INET6;    prefix.family = AF_INET6;
          for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv6_reachs,     for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv6_reachs, node, ip6reach))
                                     node, ip6reach))    {
            {      assert (ip6reach->prefix_len <= IPV6_MAX_BITLEN);
              dist = cost + ip6reach->metric;
              vtype = (ip6reach->control_info & CTRL_INFO_DISTRIBUTION) ?      dist = cost + ntohl(ip6reach->metric);
                VTYPE_IP6REACH_EXTERNAL : VTYPE_IP6REACH_INTERNAL;      vtype = (ip6reach->control_info & CTRL_INFO_DISTRIBUTION) ?
              prefix.prefixlen = ip6reach->prefix_len;        VTYPE_IP6REACH_EXTERNAL : VTYPE_IP6REACH_INTERNAL;
              memcpy (&prefix.u.prefix6.s6_addr, ip6reach->prefix,      prefix.prefixlen = ip6reach->prefix_len;
                      PSIZE (ip6reach->prefix_len));      memcpy (&prefix.u.prefix6.s6_addr, ip6reach->prefix,
              process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,              PSIZE (ip6reach->prefix_len));
                         lsp->adj, family);      apply_mask (&prefix);
            }      process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
        }                 family, parent);
#endif /* HAVE_IPV6 */ 
     }      }
     }
   #endif /* HAVE_IPV6 */
   
   if (fragnode == NULL)    if (fragnode == NULL)
     fragnode = listhead (lsp->lspu.frags);      fragnode = listhead (lsp->lspu.frags);
Line 690  lspfragloop: Line 862  lspfragloop:
   
 static int  static int
 isis_spf_process_pseudo_lsp (struct isis_spftree *spftree,  isis_spf_process_pseudo_lsp (struct isis_spftree *spftree,
                             struct isis_lsp *lsp, uint16_t cost,                             struct isis_lsp *lsp, uint32_t cost,
                             uint16_t depth, int family)                             uint16_t depth, int family,
                              u_char *root_sysid,
                              struct isis_vertex *parent)
 {  {
   struct listnode *node, *fragnode = NULL;    struct listnode *node, *fragnode = NULL;
   struct is_neigh *is_neigh;    struct is_neigh *is_neigh;
   struct te_is_neigh *te_is_neigh;    struct te_is_neigh *te_is_neigh;
   enum vertextype vtype;    enum vertextype vtype;
     uint32_t dist;
   
 pseudofragloop:  pseudofragloop:
   
Line 707  pseudofragloop: Line 882  pseudofragloop:
       return ISIS_WARNING;        return ISIS_WARNING;
     }      }
   
   #ifdef EXTREME_DEBUG
         zlog_debug ("ISIS-Spf: process_pseudo_lsp %s",
                     print_sys_hostname(lsp->lsp_header->lsp_id));
   #endif /* EXTREME_DEBUG */
   
     /* RFC3787 section 4 SHOULD ignore overload bit in pseudo LSPs */
   
   if (lsp->tlv_data.is_neighs)    if (lsp->tlv_data.is_neighs)
     for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.is_neighs, node, is_neigh))      for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.is_neighs, node, is_neigh))
       {        {
         vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS  
           : VTYPE_NONPSEUDO_IS;  
         /* Two way connectivity */          /* Two way connectivity */
        if (!memcmp (is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN))        if (!memcmp (is_neigh->neigh_id, root_sysid, ISIS_SYS_ID_LEN))
           continue;            continue;
        if (isis_find_vertex        dist = cost + is_neigh->metrics.metric_default;
            (spftree->tents, (void *) is_neigh->neigh_id, vtype) == NULL        vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS
            && isis_find_vertex (spftree->paths, (void *) is_neigh->neigh_id,          : VTYPE_NONPSEUDO_IS;
                               vtype) == NULL)        process_N (spftree, vtype, (void *) is_neigh->neigh_id, dist,
          {            depth + 1, family, parent);
            /* C.2.5 i) */ 
            isis_spf_add2tent (spftree, vtype, is_neigh->neigh_id, lsp->adj, 
                             cost, depth, family); 
          } 
       }        }
   if (lsp->tlv_data.te_is_neighs)    if (lsp->tlv_data.te_is_neighs)
     for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_is_neighs, node, te_is_neigh))      for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_is_neighs, node, te_is_neigh))
       {        {
         vtype = LSP_PSEUDO_ID (te_is_neigh->neigh_id) ? VTYPE_PSEUDO_TE_IS  
           : VTYPE_NONPSEUDO_TE_IS;  
         /* Two way connectivity */          /* Two way connectivity */
        if (!memcmp (te_is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN))        if (!memcmp (te_is_neigh->neigh_id, root_sysid, ISIS_SYS_ID_LEN))
           continue;            continue;
        if (isis_find_vertex        dist = cost + GET_TE_METRIC(te_is_neigh);
            (spftree->tents, (void *) te_is_neigh->neigh_id, vtype) == NULL        vtype = LSP_PSEUDO_ID (te_is_neigh->neigh_id) ? VTYPE_PSEUDO_TE_IS
            && isis_find_vertex (spftree->paths, (void *) te_is_neigh->neigh_id,          : VTYPE_NONPSEUDO_TE_IS;
                                 vtype) == NULL)        process_N (spftree, vtype, (void *) te_is_neigh->neigh_id, dist,
          {            depth + 1, family, parent);
            /* C.2.5 i) */ 
            isis_spf_add2tent (spftree, vtype, te_is_neigh->neigh_id, lsp->adj, 
                               cost, depth, family); 
          } 
       }        }
   
   if (fragnode == NULL)    if (fragnode == NULL)
Line 759  pseudofragloop: Line 929  pseudofragloop:
 }  }
   
 static int  static int
isis_spf_preload_tent (struct isis_spftree *spftree,isis_spf_preload_tent (struct isis_spftree *spftree, int level,
                       struct isis_area *area, int level, int family)                       int family, u_char *root_sysid,
                        struct isis_vertex *parent)
 {  {
   struct isis_vertex *vertex;  
   struct isis_circuit *circuit;    struct isis_circuit *circuit;
   struct listnode *cnode, *anode, *ipnode;    struct listnode *cnode, *anode, *ipnode;
   struct isis_adjacency *adj;    struct isis_adjacency *adj;
Line 773  isis_spf_preload_tent (struct isis_spftree *spftree, Line 943  isis_spf_preload_tent (struct isis_spftree *spftree,
   struct prefix prefix;    struct prefix prefix;
   int retval = ISIS_OK;    int retval = ISIS_OK;
   u_char lsp_id[ISIS_SYS_ID_LEN + 2];    u_char lsp_id[ISIS_SYS_ID_LEN + 2];
     static u_char null_lsp_id[ISIS_SYS_ID_LEN + 2];
 #ifdef HAVE_IPV6  #ifdef HAVE_IPV6
   struct prefix_ipv6 *ipv6;    struct prefix_ipv6 *ipv6;
 #endif /* HAVE_IPV6 */  #endif /* HAVE_IPV6 */
   
  for (ALL_LIST_ELEMENTS_RO (area->circuit_list, cnode, circuit))  for (ALL_LIST_ELEMENTS_RO (spftree->area->circuit_list, cnode, circuit))
     {      {
       if (circuit->state != C_STATE_UP)        if (circuit->state != C_STATE_UP)
         continue;          continue;
      if (!(circuit->circuit_is_type & level))      if (!(circuit->is_type & level))
         continue;          continue;
       if (family == AF_INET && !circuit->ip_router)        if (family == AF_INET && !circuit->ip_router)
         continue;          continue;
Line 799  isis_spf_preload_tent (struct isis_spftree *spftree, Line 970  isis_spf_preload_tent (struct isis_spftree *spftree,
             {              {
               prefix.u.prefix4 = ipv4->prefix;                prefix.u.prefix4 = ipv4->prefix;
               prefix.prefixlen = ipv4->prefixlen;                prefix.prefixlen = ipv4->prefixlen;
                 apply_mask (&prefix);
               isis_spf_add_local (spftree, VTYPE_IPREACH_INTERNAL, &prefix,                isis_spf_add_local (spftree, VTYPE_IPREACH_INTERNAL, &prefix,
                                  NULL, 0, family);                                  NULL, 0, family, parent);
             }              }
         }          }
 #ifdef HAVE_IPV6  #ifdef HAVE_IPV6
Line 811  isis_spf_preload_tent (struct isis_spftree *spftree, Line 983  isis_spf_preload_tent (struct isis_spftree *spftree,
             {              {
               prefix.prefixlen = ipv6->prefixlen;                prefix.prefixlen = ipv6->prefixlen;
               prefix.u.prefix6 = ipv6->prefix;                prefix.u.prefix6 = ipv6->prefix;
                 apply_mask (&prefix);
               isis_spf_add_local (spftree, VTYPE_IP6REACH_INTERNAL,                isis_spf_add_local (spftree, VTYPE_IP6REACH_INTERNAL,
                                  &prefix, NULL, 0, family);                                  &prefix, NULL, 0, family, parent);
             }              }
         }          }
 #endif /* HAVE_IPV6 */  #endif /* HAVE_IPV6 */
Line 832  isis_spf_preload_tent (struct isis_spftree *spftree, Line 1005  isis_spf_preload_tent (struct isis_spftree *spftree,
                             level, circuit->interface->name);                              level, circuit->interface->name);
               continue;                continue;
             }              }
          anode = listhead (adj_list);          for (ALL_LIST_ELEMENTS_RO (adj_list, anode, adj))
          while (anode) 
             {              {
               adj = listgetdata (anode);  
               if (!speaks (&adj->nlpids, family))                if (!speaks (&adj->nlpids, family))
                 {  
                   anode = listnextnode (anode);  
                   continue;                    continue;
                 }  
               switch (adj->sys_type)                switch (adj->sys_type)
                 {                  {
                 case ISIS_SYSTYPE_ES:                  case ISIS_SYSTYPE_ES:
                   isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj,                    isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj,
                                      circuit->te_metric[level - 1], family);                                      circuit->te_metric[level - 1],
                                       family, parent);
                   break;                    break;
                 case ISIS_SYSTYPE_IS:                  case ISIS_SYSTYPE_IS:
                 case ISIS_SYSTYPE_L1_IS:                  case ISIS_SYSTYPE_L1_IS:
                 case ISIS_SYSTYPE_L2_IS:                  case ISIS_SYSTYPE_L2_IS:
                  vertex =                  isis_spf_add_local (spftree,
                    isis_spf_add_local (spftree, VTYPE_NONPSEUDO_IS,                                      spftree->area->oldmetric ?
                                        adj->sysid, adj,                                      VTYPE_NONPSEUDO_IS :
                                        circuit->te_metric[level - 1], family);                                      VTYPE_NONPSEUDO_TE_IS,
                                       adj->sysid, adj,
                                       circuit->te_metric[level - 1],
                                       family, parent);
                   memcpy (lsp_id, adj->sysid, ISIS_SYS_ID_LEN);                    memcpy (lsp_id, adj->sysid, ISIS_SYS_ID_LEN);
                   LSP_PSEUDO_ID (lsp_id) = 0;                    LSP_PSEUDO_ID (lsp_id) = 0;
                   LSP_FRAGMENT (lsp_id) = 0;                    LSP_FRAGMENT (lsp_id) = 0;
                  lsp = lsp_search (lsp_id, area->lspdb[level - 1]);                  lsp = lsp_search (lsp_id, spftree->area->lspdb[level - 1]);
                  if (!lsp)                  if (lsp == NULL || lsp->lsp_header->rem_lifetime == 0)
                    zlog_warn ("No lsp found for IS adjacency");                    zlog_warn ("ISIS-Spf: No LSP %s found for IS adjacency "
                  /*          else {                        "L%d on %s (ID %u)",
                     isis_spf_process_lsp (spftree, lsp, vertex->d_N, 1, family);                        rawlspid_print (lsp_id), level,
                     } */                        circuit->interface->name, circuit->circuit_id);
                   break;                    break;
                 case ISIS_SYSTYPE_UNKNOWN:                  case ISIS_SYSTYPE_UNKNOWN:
                 default:                  default:
                   zlog_warn ("isis_spf_preload_tent unknow adj type");                    zlog_warn ("isis_spf_preload_tent unknow adj type");
                 }                  }
               anode = listnextnode (anode);  
             }              }
           list_delete (adj_list);            list_delete (adj_list);
           /*            /*
Line 878  isis_spf_preload_tent (struct isis_spftree *spftree, Line 1049  isis_spf_preload_tent (struct isis_spftree *spftree,
             memcpy (lsp_id, circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1);              memcpy (lsp_id, circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1);
           else            else
             memcpy (lsp_id, circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1);              memcpy (lsp_id, circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1);
          lsp = lsp_search (lsp_id, area->lspdb[level - 1]);          /* can happen during DR reboot */
           if (memcmp (lsp_id, null_lsp_id, ISIS_SYS_ID_LEN + 1) == 0)
             {
               if (isis->debugs & DEBUG_SPF_EVENTS)
                 zlog_debug ("ISIS-Spf: No L%d DR on %s (ID %d)",
                     level, circuit->interface->name, circuit->circuit_id);
               continue;
             }
           adj = isis_adj_lookup (lsp_id, adjdb);            adj = isis_adj_lookup (lsp_id, adjdb);
           /* if no adj, we are the dis or error */            /* if no adj, we are the dis or error */
           if (!adj && !circuit->u.bc.is_dr[level - 1])            if (!adj && !circuit->u.bc.is_dr[level - 1])
             {              {
              zlog_warn ("ISIS-Spf: No adjacency found for DR");              zlog_warn ("ISIS-Spf: No adjacency found from root "
                   "to L%d DR %s on %s (ID %d)",
                   level, rawlspid_print (lsp_id),
                   circuit->interface->name, circuit->circuit_id);
               continue;
             }              }
             lsp = lsp_search (lsp_id, spftree->area->lspdb[level - 1]);
           if (lsp == NULL || lsp->lsp_header->rem_lifetime == 0)            if (lsp == NULL || lsp->lsp_header->rem_lifetime == 0)
             {              {
              zlog_warn ("ISIS-Spf: No lsp found for DR");              zlog_warn ("ISIS-Spf: No lsp (%p) found from root "
                   "to L%d DR %s on %s (ID %d)",
                   lsp, level, rawlspid_print (lsp_id), 
                   circuit->interface->name, circuit->circuit_id);
               continue;
             }              }
          else          isis_spf_process_pseudo_lsp (spftree, lsp,
            {                                       circuit->te_metric[level - 1], 0,
              isis_spf_process_pseudo_lsp (spftree, lsp,                                       family, root_sysid, parent);
                                  circuit->te_metric[level - 1], 0, family); 
 
            } 
         }          }
       else if (circuit->circ_type == CIRCUIT_T_P2P)        else if (circuit->circ_type == CIRCUIT_T_P2P)
         {          {
Line 905  isis_spf_preload_tent (struct isis_spftree *spftree, Line 1089  isis_spf_preload_tent (struct isis_spftree *spftree,
             {              {
             case ISIS_SYSTYPE_ES:              case ISIS_SYSTYPE_ES:
               isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj,                isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj,
                                  circuit->te_metric[level - 1], family);                                  circuit->te_metric[level - 1], family,
                                   parent);
               break;                break;
             case ISIS_SYSTYPE_IS:              case ISIS_SYSTYPE_IS:
             case ISIS_SYSTYPE_L1_IS:              case ISIS_SYSTYPE_L1_IS:
             case ISIS_SYSTYPE_L2_IS:              case ISIS_SYSTYPE_L2_IS:
               if (speaks (&adj->nlpids, family))                if (speaks (&adj->nlpids, family))
                isis_spf_add_local (spftree, VTYPE_NONPSEUDO_IS, adj->sysid,                isis_spf_add_local (spftree,
                                     spftree->area->oldmetric ?
                                     VTYPE_NONPSEUDO_IS :
                                     VTYPE_NONPSEUDO_TE_IS,
                                     adj->sysid,
                                     adj, circuit->te_metric[level - 1],                                      adj, circuit->te_metric[level - 1],
                                    family);                                    family, parent);
               break;                break;
             case ISIS_SYSTYPE_UNKNOWN:              case ISIS_SYSTYPE_UNKNOWN:
             default:              default:
              zlog_warn ("isis_spf_preload_tent unknow adj type");              zlog_warn ("isis_spf_preload_tent unknown adj type");
               break;                break;
             }              }
         }          }
         else if (circuit->circ_type == CIRCUIT_T_LOOPBACK)
           {
             continue;
           }
       else        else
         {          {
           zlog_warn ("isis_spf_preload_tent unsupported media");            zlog_warn ("isis_spf_preload_tent unsupported media");
           retval = ISIS_WARNING;            retval = ISIS_WARNING;
         }          }
   
     }      }
   
   return retval;    return retval;
Line 938  isis_spf_preload_tent (struct isis_spftree *spftree, Line 1130  isis_spf_preload_tent (struct isis_spftree *spftree,
  */   */
 static void  static void
 add_to_paths (struct isis_spftree *spftree, struct isis_vertex *vertex,  add_to_paths (struct isis_spftree *spftree, struct isis_vertex *vertex,
              struct isis_area *area, int level)              int level)
 {  {
 #ifdef EXTREME_DEBUG  
   u_char buff[BUFSIZ];    u_char buff[BUFSIZ];
#endif /* EXTREME_DEBUG */
   if (isis_find_vertex (spftree->paths, vertex->N.id, vertex->type))
     return;
   listnode_add (spftree->paths, vertex);    listnode_add (spftree->paths, vertex);
   
 #ifdef EXTREME_DEBUG  #ifdef EXTREME_DEBUG
  zlog_debug ("ISIS-Spf: added  %s %s depth %d dist %d to PATHS",  zlog_debug ("ISIS-Spf: added %s %s %s depth %d dist %d to PATHS",
               print_sys_hostname (vertex->N.id),
               vtype2string (vertex->type), vid2string (vertex, buff),                vtype2string (vertex->type), vid2string (vertex, buff),
               vertex->depth, vertex->d_N);                vertex->depth, vertex->d_N);
 #endif /* EXTREME_DEBUG */  #endif /* EXTREME_DEBUG */
   
   if (vertex->type > VTYPE_ES)    if (vertex->type > VTYPE_ES)
     {      {
       if (listcount (vertex->Adj_N) > 0)        if (listcount (vertex->Adj_N) > 0)
         isis_route_create ((struct prefix *) &vertex->N.prefix, vertex->d_N,          isis_route_create ((struct prefix *) &vertex->N.prefix, vertex->d_N,
                           vertex->depth, vertex->Adj_N, area, level);                           vertex->depth, vertex->Adj_N, spftree->area, level);
       else if (isis->debugs & DEBUG_SPF_EVENTS)        else if (isis->debugs & DEBUG_SPF_EVENTS)
        zlog_debug ("ISIS-Spf: no adjacencies do not install route");        zlog_debug ("ISIS-Spf: no adjacencies do not install route for "
                     "%s depth %d dist %d", vid2string (vertex, buff),
                     vertex->depth, vertex->d_N);
     }      }
   
   return;    return;
Line 969  init_spt (struct isis_spftree *spftree) Line 1166  init_spt (struct isis_spftree *spftree)
   list_delete_all_node (spftree->tents);    list_delete_all_node (spftree->tents);
   list_delete_all_node (spftree->paths);    list_delete_all_node (spftree->paths);
   spftree->tents->del = spftree->paths->del = NULL;    spftree->tents->del = spftree->paths->del = NULL;
   
   return;    return;
 }  }
   
 static int  static int
isis_run_spf (struct isis_area *area, int level, int family)isis_run_spf (struct isis_area *area, int level, int family, u_char *sysid)
 {  {
   int retval = ISIS_OK;    int retval = ISIS_OK;
   struct listnode *node;    struct listnode *node;
   struct isis_vertex *vertex;    struct isis_vertex *vertex;
     struct isis_vertex *root_vertex;
   struct isis_spftree *spftree = NULL;    struct isis_spftree *spftree = NULL;
   u_char lsp_id[ISIS_SYS_ID_LEN + 2];    u_char lsp_id[ISIS_SYS_ID_LEN + 2];
   struct isis_lsp *lsp;    struct isis_lsp *lsp;
   struct route_table *table = NULL;    struct route_table *table = NULL;
  struct route_node *rode;  struct timeval time_now;
  struct isis_route_info *rinfo;  unsigned long long start_time, end_time;
   
     /* Get time that can't roll backwards. */
     quagga_gettime(QUAGGA_CLK_MONOTONIC, &time_now);
     start_time = time_now.tv_sec;
     start_time = (start_time * 1000000) + time_now.tv_usec;
   
   if (family == AF_INET)    if (family == AF_INET)
     spftree = area->spftree[level - 1];      spftree = area->spftree[level - 1];
 #ifdef HAVE_IPV6  #ifdef HAVE_IPV6
   else if (family == AF_INET6)    else if (family == AF_INET6)
     spftree = area->spftree6[level - 1];      spftree = area->spftree6[level - 1];
 #endif  #endif
   
   assert (spftree);    assert (spftree);
     assert (sysid);
   
   /* Make all routes in current route table inactive. */    /* Make all routes in current route table inactive. */
   if (family == AF_INET)    if (family == AF_INET)
Line 1003  isis_run_spf (struct isis_area *area, int level, int f Line 1205  isis_run_spf (struct isis_area *area, int level, int f
     table = area->route_table6[level - 1];      table = area->route_table6[level - 1];
 #endif  #endif
   
  for (rode = route_top (table); rode; rode = route_next (rode))  isis_route_invalidate_table (area, table);
    { 
      if (rode->info == NULL) 
        continue; 
      rinfo = rode->info; 
   
       UNSET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE);  
     }  
   
   /*    /*
    * C.2.5 Step 0     * C.2.5 Step 0
    */     */
   init_spt (spftree);    init_spt (spftree);
   /*              a) */    /*              a) */
  isis_spf_add_self (spftree, area, level);  root_vertex = isis_spf_add_root (spftree, level, sysid);
   /*              b) */    /*              b) */
  retval = isis_spf_preload_tent (spftree, area, level, family);  retval = isis_spf_preload_tent (spftree, level, family, sysid, root_vertex);
   if (retval != ISIS_OK)
     {
       zlog_warn ("ISIS-Spf: failed to load TENT SPF-root:%s", print_sys_hostname(sysid));
       goto out;
     }
   
   /*    /*
    * C.2.7 Step 2     * C.2.7 Step 2
    */     */
   if (listcount (spftree->tents) == 0)    if (listcount (spftree->tents) == 0)
     {      {
      zlog_warn ("ISIS-Spf: TENT is empty");      zlog_warn ("ISIS-Spf: TENT is empty SPF-root:%s", print_sys_hostname(sysid));
       goto out;        goto out;
     }      }
   
Line 1034  isis_run_spf (struct isis_area *area, int level, int f Line 1234  isis_run_spf (struct isis_area *area, int level, int f
     {      {
       node = listhead (spftree->tents);        node = listhead (spftree->tents);
       vertex = listgetdata (node);        vertex = listgetdata (node);
      /* Remove from tent list */
 #ifdef EXTREME_DEBUG
   zlog_debug ("ISIS-Spf: get TENT node %s %s depth %d dist %d to PATHS",
               print_sys_hostname (vertex->N.id),
               vtype2string (vertex->type), vertex->depth, vertex->d_N);
 #endif /* EXTREME_DEBUG */
 
       /* Remove from tent list and add to paths list */
       list_delete_node (spftree->tents, node);        list_delete_node (spftree->tents, node);
      if (isis_find_vertex (spftree->paths, vertex->N.id, vertex->type))      add_to_paths (spftree, vertex, level);
        continue;      switch (vertex->type)
      add_to_paths (spftree, vertex, area, level);        {
      if (vertex->type == VTYPE_PSEUDO_IS ||        case VTYPE_PSEUDO_IS:
          vertex->type == VTYPE_NONPSEUDO_IS)        case VTYPE_NONPSEUDO_IS:
        {        case VTYPE_PSEUDO_TE_IS:
         case VTYPE_NONPSEUDO_TE_IS:
           memcpy (lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1);            memcpy (lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1);
           LSP_FRAGMENT (lsp_id) = 0;            LSP_FRAGMENT (lsp_id) = 0;
           lsp = lsp_search (lsp_id, area->lspdb[level - 1]);            lsp = lsp_search (lsp_id, area->lspdb[level - 1]);
          if (lsp)          if (lsp && lsp->lsp_header->rem_lifetime != 0)
             {              {
               if (LSP_PSEUDO_ID (lsp_id))                if (LSP_PSEUDO_ID (lsp_id))
                 {                  {
                   isis_spf_process_pseudo_lsp (spftree, lsp, vertex->d_N,                    isis_spf_process_pseudo_lsp (spftree, lsp, vertex->d_N,
                                               vertex->depth, family);                                               vertex->depth, family, sysid,
                                               vertex);
                 }                  }
               else                else
                 {                  {
                   isis_spf_process_lsp (spftree, lsp, vertex->d_N,                    isis_spf_process_lsp (spftree, lsp, vertex->d_N,
                                        vertex->depth, family);                                        vertex->depth, family, sysid, vertex);
                 }                  }
             }              }
           else            else
Line 1064  isis_run_spf (struct isis_area *area, int level, int f Line 1272  isis_run_spf (struct isis_area *area, int level, int f
               zlog_warn ("ISIS-Spf: No LSP found for %s",                zlog_warn ("ISIS-Spf: No LSP found for %s",
                          rawlspid_print (lsp_id));                           rawlspid_print (lsp_id));
             }              }
             break;
           default:;
         }          }
     }      }
   
 out:  out:
  thread_add_event (master, isis_route_validate, area, 0);  isis_route_validate (area);
  spftree->lastrun = time (NULL); 
   spftree->pending = 0;    spftree->pending = 0;
     spftree->runcount++;
     spftree->last_run_timestamp = time (NULL);
     quagga_gettime(QUAGGA_CLK_MONOTONIC, &time_now);
     end_time = time_now.tv_sec;
     end_time = (end_time * 1000000) + time_now.tv_usec;
     spftree->last_run_duration = end_time - start_time;
   
   
   return retval;    return retval;
 }  }
   
Line 1085  isis_run_spf_l1 (struct thread *thread) Line 1301  isis_run_spf_l1 (struct thread *thread)
   assert (area);    assert (area);
   
   area->spftree[0]->t_spf = NULL;    area->spftree[0]->t_spf = NULL;
     area->spftree[0]->pending = 0;
   
   if (!(area->is_type & IS_LEVEL_1))    if (!(area->is_type & IS_LEVEL_1))
     {      {
Line 1098  isis_run_spf_l1 (struct thread *thread) Line 1315  isis_run_spf_l1 (struct thread *thread)
     zlog_debug ("ISIS-Spf (%s) L1 SPF needed, periodic SPF", area->area_tag);      zlog_debug ("ISIS-Spf (%s) L1 SPF needed, periodic SPF", area->area_tag);
   
   if (area->ip_circuits)    if (area->ip_circuits)
    retval = isis_run_spf (area, 1, AF_INET);    retval = isis_run_spf (area, 1, AF_INET, isis->sysid);
   
   THREAD_TIMER_ON (master, area->spftree[0]->t_spf, isis_run_spf_l1, area,  
                    isis_jitter (PERIODIC_SPF_INTERVAL, 10));  
   
   return retval;    return retval;
 }  }
   
Line 1116  isis_run_spf_l2 (struct thread *thread) Line 1330  isis_run_spf_l2 (struct thread *thread)
   assert (area);    assert (area);
   
   area->spftree[1]->t_spf = NULL;    area->spftree[1]->t_spf = NULL;
     area->spftree[1]->pending = 0;
   
   if (!(area->is_type & IS_LEVEL_2))    if (!(area->is_type & IS_LEVEL_2))
     {      {
Line 1128  isis_run_spf_l2 (struct thread *thread) Line 1343  isis_run_spf_l2 (struct thread *thread)
     zlog_debug ("ISIS-Spf (%s) L2 SPF needed, periodic SPF", area->area_tag);      zlog_debug ("ISIS-Spf (%s) L2 SPF needed, periodic SPF", area->area_tag);
   
   if (area->ip_circuits)    if (area->ip_circuits)
    retval = isis_run_spf (area, 2, AF_INET);    retval = isis_run_spf (area, 2, AF_INET, isis->sysid);
   
   THREAD_TIMER_ON (master, area->spftree[1]->t_spf, isis_run_spf_l2, area,  
                    isis_jitter (PERIODIC_SPF_INTERVAL, 10));  
   
   return retval;    return retval;
 }  }
   
 int  int
 isis_spf_schedule (struct isis_area *area, int level)  isis_spf_schedule (struct isis_area *area, int level)
 {  {
   int retval = ISIS_OK;  
   struct isis_spftree *spftree = area->spftree[level - 1];    struct isis_spftree *spftree = area->spftree[level - 1];
  time_t diff, now = time (NULL);  time_t now = time (NULL);
   int diff = now - spftree->last_run_timestamp;
   
  if (spftree->pending)  assert (diff >= 0);
    return retval;  assert (area->is_type & level);
   
  diff = now - spftree->lastrun;  if (isis->debugs & DEBUG_SPF_EVENTS)
     zlog_debug ("ISIS-Spf (%s) L%d SPF schedule called, lastrun %d sec ago",
                 area->area_tag, level, diff);
   
  /* FIXME: let's wait a minute before doing the SPF */  if (spftree->pending)
  if (now - isis->uptime < 60 || isis->uptime == 0)    return ISIS_OK;
    { 
      if (level == 1) 
        THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area, 60); 
      else 
        THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area, 60); 
   
       spftree->pending = 1;  
       return retval;  
     }  
   
   THREAD_TIMER_OFF (spftree->t_spf);    THREAD_TIMER_OFF (spftree->t_spf);
   
  if (diff < MINIMUM_SPF_INTERVAL)  /* wait configured min_spf_interval before doing the SPF */
    {  if (diff >= area->min_spf_interval[level-1])
      if (level == 1)      return isis_run_spf (area, level, AF_INET, isis->sysid);
        THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area, 
                         MINIMUM_SPF_INTERVAL - diff); 
      else 
        THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area, 
                         MINIMUM_SPF_INTERVAL - diff); 
   
      spftree->pending = 1;  if (level == 1)
    }    THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area,
                      area->min_spf_interval[0] - diff);
   else    else
    {    THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area,
      spftree->pending = 0;                     area->min_spf_interval[1] - diff);
      retval = isis_run_spf (area, level, AF_INET); 
      if (level == 1) 
        THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area, 
                         isis_jitter (PERIODIC_SPF_INTERVAL, 10)); 
      else 
        THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area, 
                         isis_jitter (PERIODIC_SPF_INTERVAL, 10)); 
    } 
   
  return retval;  if (isis->debugs & DEBUG_SPF_EVENTS)
     zlog_debug ("ISIS-Spf (%s) L%d SPF scheduled %d sec from now",
                 area->area_tag, level, area->min_spf_interval[level-1] - diff);
 
   spftree->pending = 1;
 
   return ISIS_OK;
 }  }
   
 #ifdef HAVE_IPV6  #ifdef HAVE_IPV6
Line 1199  isis_run_spf6_l1 (struct thread *thread) Line 1398  isis_run_spf6_l1 (struct thread *thread)
   assert (area);    assert (area);
   
   area->spftree6[0]->t_spf = NULL;    area->spftree6[0]->t_spf = NULL;
     area->spftree6[0]->pending = 0;
   
   if (!(area->is_type & IS_LEVEL_1))    if (!(area->is_type & IS_LEVEL_1))
     {      {
       if (isis->debugs & DEBUG_SPF_EVENTS)        if (isis->debugs & DEBUG_SPF_EVENTS)
        zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);        zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
       return ISIS_WARNING;        return ISIS_WARNING;
     }      }
   
Line 1211  isis_run_spf6_l1 (struct thread *thread) Line 1411  isis_run_spf6_l1 (struct thread *thread)
     zlog_debug ("ISIS-Spf (%s) L1 SPF needed, periodic SPF", area->area_tag);      zlog_debug ("ISIS-Spf (%s) L1 SPF needed, periodic SPF", area->area_tag);
   
   if (area->ipv6_circuits)    if (area->ipv6_circuits)
    retval = isis_run_spf (area, 1, AF_INET6);    retval = isis_run_spf (area, 1, AF_INET6, isis->sysid);
   
   THREAD_TIMER_ON (master, area->spftree6[0]->t_spf, isis_run_spf6_l1, area,  
                    isis_jitter (PERIODIC_SPF_INTERVAL, 10));  
   
   return retval;    return retval;
 }  }
   
Line 1229  isis_run_spf6_l2 (struct thread *thread) Line 1426  isis_run_spf6_l2 (struct thread *thread)
   assert (area);    assert (area);
   
   area->spftree6[1]->t_spf = NULL;    area->spftree6[1]->t_spf = NULL;
     area->spftree6[1]->pending = 0;
   
   if (!(area->is_type & IS_LEVEL_2))    if (!(area->is_type & IS_LEVEL_2))
     {      {
Line 1241  isis_run_spf6_l2 (struct thread *thread) Line 1439  isis_run_spf6_l2 (struct thread *thread)
     zlog_debug ("ISIS-Spf (%s) L2 SPF needed, periodic SPF.", area->area_tag);      zlog_debug ("ISIS-Spf (%s) L2 SPF needed, periodic SPF.", area->area_tag);
   
   if (area->ipv6_circuits)    if (area->ipv6_circuits)
    retval = isis_run_spf (area, 2, AF_INET6);    retval = isis_run_spf (area, 2, AF_INET6, isis->sysid);
   
   THREAD_TIMER_ON (master, area->spftree6[1]->t_spf, isis_run_spf6_l2, area,  
                    isis_jitter (PERIODIC_SPF_INTERVAL, 10));  
   
   return retval;    return retval;
 }  }
   
Line 1254  isis_spf_schedule6 (struct isis_area *area, int level) Line 1449  isis_spf_schedule6 (struct isis_area *area, int level)
 {  {
   int retval = ISIS_OK;    int retval = ISIS_OK;
   struct isis_spftree *spftree = area->spftree6[level - 1];    struct isis_spftree *spftree = area->spftree6[level - 1];
  time_t diff, now = time (NULL);  time_t now = time (NULL);
   time_t diff = now - spftree->last_run_timestamp;
   
  if (spftree->pending)  assert (diff >= 0);
    return retval;  assert (area->is_type & level);
   
  diff = now - spftree->lastrun;  if (isis->debugs & DEBUG_SPF_EVENTS)
     zlog_debug ("ISIS-Spf (%s) L%d SPF schedule called, lastrun %d sec ago",
                 area->area_tag, level, diff);
   
  /* FIXME: let's wait a minute before doing the SPF */  if (spftree->pending)
  if (now - isis->uptime < 60 || isis->uptime == 0)    return ISIS_OK;
    { 
      if (level == 1) 
        THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area, 60); 
      else 
        THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area, 60); 
   
       spftree->pending = 1;  
       return retval;  
     }  
     
   THREAD_TIMER_OFF (spftree->t_spf);    THREAD_TIMER_OFF (spftree->t_spf);
   
  if (diff < MINIMUM_SPF_INTERVAL)  /* wait configured min_spf_interval before doing the SPF */
    {  if (diff >= area->min_spf_interval[level-1])
      if (level == 1)      return isis_run_spf (area, level, AF_INET6, isis->sysid);
        THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area, 
                         MINIMUM_SPF_INTERVAL - diff); 
      else 
        THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area, 
                         MINIMUM_SPF_INTERVAL - diff); 
   
      spftree->pending = 1;  if (level == 1)
    }    THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area,
                      area->min_spf_interval[0] - diff);
   else    else
    {    THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area,
      spftree->pending = 0;                     area->min_spf_interval[1] - diff);
      retval = isis_run_spf (area, level, AF_INET6); 
   
      if (level == 1)  if (isis->debugs & DEBUG_SPF_EVENTS)
        THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area,    zlog_debug ("ISIS-Spf (%s) L%d SPF scheduled %d sec from now",
                         isis_jitter (PERIODIC_SPF_INTERVAL, 10));                area->area_tag, level, area->min_spf_interval[level-1] - diff);
      else 
        THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area, 
                         isis_jitter (PERIODIC_SPF_INTERVAL, 10)); 
    } 
   
     spftree->pending = 1;
   
   return retval;    return retval;
 }  }
 #endif  #endif
   
 static void  static void
isis_print_paths (struct vty *vty, struct list *paths)isis_print_paths (struct vty *vty, struct list *paths, u_char *root_sysid)
 {  {
   struct listnode *node;    struct listnode *node;
     struct listnode *anode;
   struct isis_vertex *vertex;    struct isis_vertex *vertex;
   struct isis_dynhn *dyn, *nh_dyn = NULL;  
   struct isis_adjacency *adj;    struct isis_adjacency *adj;
#if 0  u_char buff[BUFSIZ];
  u_char buff[255]; 
#endif /* 0 */ 
   
  vty_out (vty, "System Id            Metric     Next-Hop"  vty_out (vty, "Vertex               Type         Metric "
           "             Interface   SNPA%s", VTY_NEWLINE);                "Next-Hop             Interface Parent%s", VTY_NEWLINE);
   
  for (ALL_LIST_ELEMENTS_RO (paths, node, vertex))  for (ALL_LIST_ELEMENTS_RO (paths, node, vertex)) {
    {      if (memcmp (vertex->N.id, root_sysid, ISIS_SYS_ID_LEN) == 0) {
      if (vertex->type != VTYPE_NONPSEUDO_IS)        vty_out (vty, "%-20s %-12s %-6s", print_sys_hostname (root_sysid),
        continue;                 "", "");
      if (memcmp (vertex->N.id, isis->sysid, ISIS_SYS_ID_LEN) == 0)        vty_out (vty, "%-30s", "");
        {      } else {
          vty_out (vty, "%s             --%s", host.name?host.name:"",        int rows = 0;
                   VTY_NEWLINE);        vty_out (vty, "%-20s %-12s %-6u ", vid2string (vertex, buff),
        }                 vtype2string (vertex->type), vertex->d_N);
      else        for (ALL_LIST_ELEMENTS_RO (vertex->Adj_N, anode, adj)) {
        {          if (adj) {
          dyn = dynhn_find_by_id ((u_char *) vertex->N.id);            if (rows) {
          adj = listgetdata (listhead (vertex->Adj_N));                vty_out (vty, "%s", VTY_NEWLINE);
          if (adj)                vty_out (vty, "%-20s %-12s %-6s ", "", "", "");
            { 
              nh_dyn = dynhn_find_by_id (adj->sysid); 
              vty_out (vty, "%-20s %-10u %-20s %-11s %-5s%s", 
                       (dyn != NULL) ? dyn->name.name : 
                       (const u_char *)rawlspid_print ((u_char *) vertex->N.id), 
                       vertex->d_N, (nh_dyn != NULL) ? nh_dyn->name.name : 
                       (const u_char *)rawlspid_print (adj->sysid), 
                       adj->circuit->interface->name, 
                       snpa_print (adj->snpa), VTY_NEWLINE); 
             }              }
          else            vty_out (vty, "%-20s %-9s ",
            {                     print_sys_hostname (adj->sysid),
              vty_out (vty, "%s              %u %s", dyn ? dyn->name.name :                     adj->circuit->interface->name);
                       (const u_char *) rawlspid_print (vertex->N.id),            ++rows;
                       vertex->d_N, VTY_NEWLINE);          }
            } 
         }          }
           if (rows == 0)
             vty_out (vty, "%-30s ", "");
         }
   
         /* Print list of parents for the ECMP DAG */
         if (listcount (vertex->parents) > 0) {
           struct listnode *pnode;
           struct isis_vertex *pvertex;
           int rows = 0;
           for (ALL_LIST_ELEMENTS_RO (vertex->parents, pnode, pvertex)) {
             if (rows) {
               vty_out (vty, "%s", VTY_NEWLINE);
               vty_out (vty, "%-72s", "");
             }
             vty_out (vty, "%s(%d)",
                      vid2string (pvertex, buff), pvertex->type);
             ++rows;
           }
         } else {
           vty_out (vty, "  NULL ");
         }
   
 #if 0  #if 0
      vty_out (vty, "%s %s %u %s", vtype2string (vertex->type),      if (listcount (vertex->children) > 0) {
               vid2string (vertex, buff), vertex->d_N, VTY_NEWLINE);          struct listnode *cnode;
           struct isis_vertex *cvertex;
           for (ALL_LIST_ELEMENTS_RO (vertex->children, cnode, cvertex)) {
               vty_out (vty, "%s", VTY_NEWLINE);
               vty_out (vty, "%-72s", "");
               vty_out (vty, "%s(%d) ", 
                        vid2string (cvertex, buff), cvertex->type);
             }
         }
 #endif  #endif
         vty_out (vty, "%s", VTY_NEWLINE);
     }      }
 }  }
   
Line 1381  DEFUN (show_isis_topology, Line 1582  DEFUN (show_isis_topology,
             {              {
               vty_out (vty, "IS-IS paths to level-%d routers that speak IP%s",                vty_out (vty, "IS-IS paths to level-%d routers that speak IP%s",
                        level + 1, VTY_NEWLINE);                         level + 1, VTY_NEWLINE);
              isis_print_paths (vty, area->spftree[level]->paths);              isis_print_paths (vty, area->spftree[level]->paths, isis->sysid);
               vty_out (vty, "%s", VTY_NEWLINE);
             }              }
 #ifdef HAVE_IPV6  #ifdef HAVE_IPV6
           if (area->ipv6_circuits > 0 && area->spftree6[level]            if (area->ipv6_circuits > 0 && area->spftree6[level]
Line 1390  DEFUN (show_isis_topology, Line 1592  DEFUN (show_isis_topology,
               vty_out (vty,                vty_out (vty,
                        "IS-IS paths to level-%d routers that speak IPv6%s",                         "IS-IS paths to level-%d routers that speak IPv6%s",
                        level + 1, VTY_NEWLINE);                         level + 1, VTY_NEWLINE);
              isis_print_paths (vty, area->spftree6[level]->paths);              isis_print_paths (vty, area->spftree6[level]->paths, isis->sysid);
               vty_out (vty, "%s", VTY_NEWLINE);
             }              }
 #endif /* HAVE_IPV6 */  #endif /* HAVE_IPV6 */
         }          }
   
         vty_out (vty, "%s", VTY_NEWLINE);
     }      }
   
   return CMD_SUCCESS;    return CMD_SUCCESS;
Line 1423  DEFUN (show_isis_topology_l1, Line 1628  DEFUN (show_isis_topology_l1,
         {          {
           vty_out (vty, "IS-IS paths to level-1 routers that speak IP%s",            vty_out (vty, "IS-IS paths to level-1 routers that speak IP%s",
                    VTY_NEWLINE);                     VTY_NEWLINE);
          isis_print_paths (vty, area->spftree[0]->paths);          isis_print_paths (vty, area->spftree[0]->paths, isis->sysid);
           vty_out (vty, "%s", VTY_NEWLINE);
         }          }
 #ifdef HAVE_IPV6  #ifdef HAVE_IPV6
       if (area->ipv6_circuits > 0 && area->spftree6[0]        if (area->ipv6_circuits > 0 && area->spftree6[0]
Line 1431  DEFUN (show_isis_topology_l1, Line 1637  DEFUN (show_isis_topology_l1,
         {          {
           vty_out (vty, "IS-IS paths to level-1 routers that speak IPv6%s",            vty_out (vty, "IS-IS paths to level-1 routers that speak IPv6%s",
                    VTY_NEWLINE);                     VTY_NEWLINE);
          isis_print_paths (vty, area->spftree6[0]->paths);          isis_print_paths (vty, area->spftree6[0]->paths, isis->sysid);
           vty_out (vty, "%s", VTY_NEWLINE);
         }          }
 #endif /* HAVE_IPV6 */  #endif /* HAVE_IPV6 */
         vty_out (vty, "%s", VTY_NEWLINE);
     }      }
   
   return CMD_SUCCESS;    return CMD_SUCCESS;
Line 1463  DEFUN (show_isis_topology_l2, Line 1671  DEFUN (show_isis_topology_l2,
         {          {
           vty_out (vty, "IS-IS paths to level-2 routers that speak IP%s",            vty_out (vty, "IS-IS paths to level-2 routers that speak IP%s",
                    VTY_NEWLINE);                     VTY_NEWLINE);
          isis_print_paths (vty, area->spftree[1]->paths);          isis_print_paths (vty, area->spftree[1]->paths, isis->sysid);
           vty_out (vty, "%s", VTY_NEWLINE);
         }          }
 #ifdef HAVE_IPV6  #ifdef HAVE_IPV6
       if (area->ipv6_circuits > 0 && area->spftree6[1]        if (area->ipv6_circuits > 0 && area->spftree6[1]
Line 1471  DEFUN (show_isis_topology_l2, Line 1680  DEFUN (show_isis_topology_l2,
         {          {
           vty_out (vty, "IS-IS paths to level-2 routers that speak IPv6%s",            vty_out (vty, "IS-IS paths to level-2 routers that speak IPv6%s",
                    VTY_NEWLINE);                     VTY_NEWLINE);
          isis_print_paths (vty, area->spftree6[1]->paths);          isis_print_paths (vty, area->spftree6[1]->paths, isis->sysid);
           vty_out (vty, "%s", VTY_NEWLINE);
         }          }
 #endif /* HAVE_IPV6 */  #endif /* HAVE_IPV6 */
         vty_out (vty, "%s", VTY_NEWLINE);
     }      }
   
   return CMD_SUCCESS;    return CMD_SUCCESS;

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


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