Diff for /embedaddon/quagga/isisd/isis_route.c between versions 1.1.1.1 and 1.1.1.2

version 1.1.1.1, 2012/02/21 17:26:11 version 1.1.1.2, 2012/10/09 09:22:28
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 48 Line 49
 #include "isis_route.h"  #include "isis_route.h"
 #include "isis_zebra.h"  #include "isis_zebra.h"
   
 extern struct isis *isis;  
 extern struct thread_master *master;  
   
 static struct isis_nexthop *  static struct isis_nexthop *
 isis_nexthop_create (struct in_addr *ip, unsigned int ifindex)  isis_nexthop_create (struct in_addr *ip, unsigned int ifindex)
 {  {
Line 246  adjinfo2nexthop (struct list *nexthops, struct isis_ad Line 244  adjinfo2nexthop (struct list *nexthops, struct isis_ad
         {          {
           nh = isis_nexthop_create (ipv4_addr,            nh = isis_nexthop_create (ipv4_addr,
                                     adj->circuit->interface->ifindex);                                      adj->circuit->interface->ifindex);
             nh->router_address = adj->router_address;
           listnode_add (nexthops, nh);            listnode_add (nexthops, nh);
         }          }
     }      }
Line 269  adjinfo2nexthop6 (struct list *nexthops6, struct isis_ Line 268  adjinfo2nexthop6 (struct list *nexthops6, struct isis_
         {          {
           nh6 = isis_nexthop6_create (ipv6_addr,            nh6 = isis_nexthop6_create (ipv6_addr,
                                       adj->circuit->interface->ifindex);                                        adj->circuit->interface->ifindex);
             nh6->router_address6 = adj->router_address6;
           listnode_add (nexthops6, nh6);            listnode_add (nexthops6, nh6);
         }          }
     }      }
Line 276  adjinfo2nexthop6 (struct list *nexthops6, struct isis_ Line 276  adjinfo2nexthop6 (struct list *nexthops6, struct isis_
 #endif /* HAVE_IPV6 */  #endif /* HAVE_IPV6 */
   
 static struct isis_route_info *  static struct isis_route_info *
isis_route_info_new (uint32_t cost, uint32_t depth, u_char family,isis_route_info_new (struct prefix *prefix, uint32_t cost, uint32_t depth,
                     struct list *adjacencies)                     struct list *adjacencies)
 {  {
   struct isis_route_info *rinfo;    struct isis_route_info *rinfo;
   struct isis_adjacency *adj;    struct isis_adjacency *adj;
Line 290  isis_route_info_new (uint32_t cost, uint32_t depth, u_ Line 290  isis_route_info_new (uint32_t cost, uint32_t depth, u_
       return NULL;        return NULL;
     }      }
   
  if (family == AF_INET)  if (prefix->family == AF_INET)
     {      {
       rinfo->nexthops = list_new ();        rinfo->nexthops = list_new ();
       for (ALL_LIST_ELEMENTS_RO (adjacencies, node, adj))        for (ALL_LIST_ELEMENTS_RO (adjacencies, node, adj))
        adjinfo2nexthop (rinfo->nexthops, adj);        {
           /* check for force resync this route */
           if (CHECK_FLAG (adj->circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF))
             SET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
           /* update neighbor router address */
           if (depth == 2 && prefix->prefixlen == 32)
             adj->router_address = prefix->u.prefix4;
           adjinfo2nexthop (rinfo->nexthops, adj);
         }
     }      }
 #ifdef HAVE_IPV6  #ifdef HAVE_IPV6
  if (family == AF_INET6)  if (prefix->family == AF_INET6)
     {      {
       rinfo->nexthops6 = list_new ();        rinfo->nexthops6 = list_new ();
       for (ALL_LIST_ELEMENTS_RO (adjacencies, node, adj))        for (ALL_LIST_ELEMENTS_RO (adjacencies, node, adj))
        adjinfo2nexthop6 (rinfo->nexthops6, adj);        {
           /* check for force resync this route */
           if (CHECK_FLAG (adj->circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF))
             SET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
           /* update neighbor router address */
           if (depth == 2 && prefix->prefixlen == 128)
             adj->router_address6 = prefix->u.prefix6;
           adjinfo2nexthop6 (rinfo->nexthops6, adj);
         }
     }      }
   
 #endif /* HAVE_IPV6 */  #endif /* HAVE_IPV6 */
Line 353  isis_route_info_same (struct isis_route_info *new, Line 369  isis_route_info_same (struct isis_route_info *new,
 #ifdef HAVE_IPV6  #ifdef HAVE_IPV6
   struct isis_nexthop6 *nexthop6;    struct isis_nexthop6 *nexthop6;
 #endif /* HAVE_IPV6 */  #endif /* HAVE_IPV6 */
   
     if (!CHECK_FLAG (old->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
       return 0;
   
     if (CHECK_FLAG (new->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC))
       return 0;
   
   if (!isis_route_info_same_attrib (new, old))    if (!isis_route_info_same_attrib (new, old))
     return 0;      return 0;
   
   if (family == AF_INET)    if (family == AF_INET)
     {      {
       for (ALL_LIST_ELEMENTS_RO (new->nexthops, node, nexthop))        for (ALL_LIST_ELEMENTS_RO (new->nexthops, node, nexthop))
        if (nexthoplookup (old->nexthops, &nexthop->ip, nexthop->ifindex)         if (nexthoplookup (old->nexthops, &nexthop->ip, nexthop->ifindex)
               == 0)                == 0)
           return 0;            return 0;
   
       for (ALL_LIST_ELEMENTS_RO (old->nexthops, node, nexthop))        for (ALL_LIST_ELEMENTS_RO (old->nexthops, node, nexthop))
        if (nexthoplookup (new->nexthops, &nexthop->ip, nexthop->ifindex)         if (nexthoplookup (new->nexthops, &nexthop->ip, nexthop->ifindex)
              == 0)               == 0)
           return 0;            return 0;
     }      }
Line 386  isis_route_info_same (struct isis_route_info *new, Line 409  isis_route_info_same (struct isis_route_info *new,
   return 1;    return 1;
 }  }
   
 static void  
 isis_nexthops_merge (struct list *new, struct list *old)  
 {  
   struct listnode *node;  
   struct isis_nexthop *nexthop;  
   
   for (ALL_LIST_ELEMENTS_RO (new, node, nexthop))  
     {  
       if (nexthoplookup (old, &nexthop->ip, nexthop->ifindex))  
         continue;  
       listnode_add (old, nexthop);  
       nexthop->lock++;  
     }  
 }  
   
 #ifdef HAVE_IPV6  
 static void  
 isis_nexthops6_merge (struct list *new, struct list *old)  
 {  
   struct listnode *node;  
   struct isis_nexthop6 *nexthop6;  
   
   for (ALL_LIST_ELEMENTS_RO (new, node, nexthop6))  
     {  
       if (nexthop6lookup (old, &nexthop6->ip6, nexthop6->ifindex))  
         continue;  
       listnode_add (old, nexthop6);  
       nexthop6->lock++;  
     }  
 }  
 #endif /* HAVE_IPV6 */  
   
 static void  
 isis_route_info_merge (struct isis_route_info *new,  
                        struct isis_route_info *old, u_char family)  
 {  
   if (family == AF_INET)  
     isis_nexthops_merge (new->nexthops, old->nexthops);  
 #ifdef HAVE_IPV6  
   else if (family == AF_INET6)  
     isis_nexthops6_merge (new->nexthops6, old->nexthops6);  
 #endif /* HAVE_IPV6 */  
   
   return;  
 }  
   
 static int  
 isis_route_info_prefer_new (struct isis_route_info *new,  
                             struct isis_route_info *old)  
 {  
   if (!CHECK_FLAG (old->flag, ISIS_ROUTE_FLAG_ACTIVE))  
     return 1;  
   
   if (new->cost < old->cost)  
     return 1;  
   
   return 0;  
 }  
   
 struct isis_route_info *  struct isis_route_info *
 isis_route_create (struct prefix *prefix, u_int32_t cost, u_int32_t depth,  isis_route_create (struct prefix *prefix, u_int32_t cost, u_int32_t depth,
                    struct list *adjacencies, struct isis_area *area,                     struct list *adjacencies, struct isis_area *area,
Line 459  isis_route_create (struct prefix *prefix, u_int32_t co Line 423  isis_route_create (struct prefix *prefix, u_int32_t co
   /* for debugs */    /* for debugs */
   prefix2str (prefix, (char *) buff, BUFSIZ);    prefix2str (prefix, (char *) buff, BUFSIZ);
   
  rinfo_new = isis_route_info_new (cost, depth, family, adjacencies);  rinfo_new = isis_route_info_new (prefix, cost, depth, adjacencies);
   if (!rinfo_new)    if (!rinfo_new)
     {      {
       zlog_err ("ISIS-Rte (%s): isis_route_create: out of memory!",        zlog_err ("ISIS-Rte (%s): isis_route_create: out of memory!",
Line 479  isis_route_create (struct prefix *prefix, u_int32_t co Line 443  isis_route_create (struct prefix *prefix, u_int32_t co
   if (!rinfo_old)    if (!rinfo_old)
     {      {
       if (isis->debugs & DEBUG_RTE_EVENTS)        if (isis->debugs & DEBUG_RTE_EVENTS)
        zlog_debug ("ISIS-Rte (%s) route created: %s", area->area_tag, buff);        zlog_debug ("ISIS-Rte (%s) route created: %s", area->area_tag, buff);
      SET_FLAG (rinfo_new->flag, ISIS_ROUTE_FLAG_ACTIVE);      route_info = rinfo_new;
      route_node->info = rinfo_new;      UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
      return rinfo_new; 
     }      }
   
   if (isis->debugs & DEBUG_RTE_EVENTS)  
     zlog_debug ("ISIS-Rte (%s) route already exists: %s", area->area_tag,  
                buff);  
   
   if (isis_route_info_same (rinfo_new, rinfo_old, family))  
     {  
       if (isis->debugs & DEBUG_RTE_EVENTS)  
         zlog_debug ("ISIS-Rte (%s) route unchanged: %s", area->area_tag, buff);  
       isis_route_info_delete (rinfo_new);  
       route_info = rinfo_old;  
     }  
   else if (isis_route_info_same_attrib (rinfo_new, rinfo_old))  
     {  
       /* merge the nexthop lists */  
       if (isis->debugs & DEBUG_RTE_EVENTS)  
         zlog_debug ("ISIS-Rte (%s) route changed (same attribs): %s",  
                    area->area_tag, buff);  
 #ifdef EXTREME_DEBUG  
       if (family == AF_INET)  
         {  
           zlog_debug ("Old nexthops");  
           nexthops_print (rinfo_old->nexthops);  
           zlog_debug ("New nexthops");  
           nexthops_print (rinfo_new->nexthops);  
         }  
       else if (family == AF_INET6)  
         {  
           zlog_debug ("Old nexthops");  
           nexthops6_print (rinfo_old->nexthops6);  
           zlog_debug ("New nexthops");  
           nexthops6_print (rinfo_new->nexthops6);  
         }  
 #endif /* EXTREME_DEBUG */  
       isis_route_info_merge (rinfo_new, rinfo_old, family);  
       isis_route_info_delete (rinfo_new);  
       route_info = rinfo_old;  
       UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC);  
     }  
   else    else
     {      {
      if (isis_route_info_prefer_new (rinfo_new, rinfo_old))      if (isis->debugs & DEBUG_RTE_EVENTS)
        {        zlog_debug ("ISIS-Rte (%s) route already exists: %s", area->area_tag,
          if (isis->debugs & DEBUG_RTE_EVENTS)                   buff);
            zlog_debug ("ISIS-Rte (%s) route changed: %s", area->area_tag,      if (isis_route_info_same (rinfo_new, rinfo_old, family))
                        buff);        {
          isis_route_info_delete (rinfo_old);          if (isis->debugs & DEBUG_RTE_EVENTS)
          route_info = rinfo_new;            zlog_debug ("ISIS-Rte (%s) route unchanged: %s", area->area_tag,
        }                        buff);
           isis_route_info_delete (rinfo_new);
           route_info = rinfo_old;
         }
       else        else
        {        {
          if (isis->debugs & DEBUG_RTE_EVENTS)          if (isis->debugs & DEBUG_RTE_EVENTS)
            zlog_debug ("ISIS-Rte (%s) route rejected: %s", area->area_tag,            zlog_debug ("ISIS-Rte (%s) route changed: %s", area->area_tag,
                        buff);                        buff);
          isis_route_info_delete (rinfo_new);          isis_route_info_delete (rinfo_old);
          route_info = rinfo_old;          route_info = rinfo_new;
        }          UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
         }
     }      }
   
   SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ACTIVE);    SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ACTIVE);
Line 570  isis_route_delete (struct prefix *prefix, struct route Line 498  isis_route_delete (struct prefix *prefix, struct route
       return;        return;
     }      }
   
  if (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC))  if (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
     {      {
       UNSET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE);        UNSET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE);
       if (isis->debugs & DEBUG_RTE_EVENTS)        if (isis->debugs & DEBUG_RTE_EVENTS)
Line 600  isis_route_validate_table (struct isis_area *area, str Line 528  isis_route_validate_table (struct isis_area *area, str
       if (isis->debugs & DEBUG_RTE_EVENTS)        if (isis->debugs & DEBUG_RTE_EVENTS)
         {          {
           prefix2str (&rnode->p, (char *) buff, BUFSIZ);            prefix2str (&rnode->p, (char *) buff, BUFSIZ);
          zlog_debug ("ISIS-Rte (%s): route validate: %s %s %s",          zlog_debug ("ISIS-Rte (%s): route validate: %s %s %s %s",
                       area->area_tag,                        area->area_tag,
                      (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC) ?                      (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED) ?
                      "sync'ed" : "nosync"),                      "synced" : "not-synced"),
                       (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC) ?
                       "resync" : "not-resync"),
                       (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE) ?                        (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE) ?
                       "active" : "inactive"), buff);                        "active" : "inactive"), buff);
         }          }
Line 706  isis_route_validate_merge (struct isis_area *area, int Line 636  isis_route_validate_merge (struct isis_area *area, int
   
 /* Walk through route tables and propagate necessary changes into RIB. In case  /* Walk through route tables and propagate necessary changes into RIB. In case
  * of L1L2 area, level tables have to be merged at first. */   * of L1L2 area, level tables have to be merged at first. */
intvoid
isis_route_validate (struct thread *thread)isis_route_validate (struct isis_area *area)
 {  {
  struct isis_area *area;  struct listnode *node;
   struct isis_circuit *circuit;
   
   area = THREAD_ARG (thread);  
   
   if (area->is_type == IS_LEVEL_1)    if (area->is_type == IS_LEVEL_1)
    {     isis_route_validate_table (area, area->route_table[0]);
      isis_route_validate_table (area, area->route_table[0]);  else if (area->is_type == IS_LEVEL_2)
      goto validate_ipv6;    isis_route_validate_table (area, area->route_table[1]);
    }  else
  if (area->is_type == IS_LEVEL_2)    isis_route_validate_merge (area, AF_INET);
    { 
      isis_route_validate_table (area, area->route_table[1]); 
      goto validate_ipv6; 
    } 
   
   isis_route_validate_merge (area, AF_INET);  
   
 validate_ipv6:  
 #ifdef HAVE_IPV6  #ifdef HAVE_IPV6
   if (area->is_type == IS_LEVEL_1)    if (area->is_type == IS_LEVEL_1)
       isis_route_validate_table (area, area->route_table6[0]);
     else if (area->is_type == IS_LEVEL_2)
       isis_route_validate_table (area, area->route_table6[1]);
     else
       isis_route_validate_merge (area, AF_INET6);
   #endif
   
     /* walk all circuits and reset any spf specific flags */
     for (ALL_LIST_ELEMENTS_RO (area->circuit_list, node, circuit))
       UNSET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF);
   
     return;
   }
   
   void
   isis_route_invalidate_table (struct isis_area *area, struct route_table *table)
   {
     struct route_node *rode;
     struct isis_route_info *rinfo;
     for (rode = route_top (table); rode; rode = route_next (rode))
     {      {
      isis_route_validate_table (area, area->route_table6[0]);      if (rode->info == NULL)
      return ISIS_OK;        continue;
       rinfo = rode->info;
 
       UNSET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE);
     }      }
  if (area->is_type == IS_LEVEL_2)}
    { 
      isis_route_validate_table (area, area->route_table6[1]); 
      return ISIS_OK; 
    } 
   
  isis_route_validate_merge (area, AF_INET6);void
#endifisis_route_invalidate (struct isis_area *area)
{
  return ISIS_OK;  if (area->is_type & IS_LEVEL_1)
     isis_route_invalidate_table (area, area->route_table[0]);
   if (area->is_type & IS_LEVEL_2)
     isis_route_invalidate_table (area, area->route_table[1]);
 }  }

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


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