Diff for /embedaddon/quagga/zebra/zebra_rib.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:41
Line 40 Line 40
 #include "zebra/zserv.h"  #include "zebra/zserv.h"
 #include "zebra/redistribute.h"  #include "zebra/redistribute.h"
 #include "zebra/debug.h"  #include "zebra/debug.h"
   #include "zebra/zebra_fpm.h"
   
 /* Default rtm_table for all clients */  /* Default rtm_table for all clients */
 extern struct zebra_t zebrad;  extern struct zebra_t zebrad;
Line 55  static const struct Line 56  static const struct
 {    {  
   int key;    int key;
   int distance;    int distance;
} route_info[] =} route_info[ZEBRA_ROUTE_MAX] =
 {  {
  {ZEBRA_ROUTE_SYSTEM,    0},  [ZEBRA_ROUTE_SYSTEM]  = {ZEBRA_ROUTE_SYSTEM,    0},
  {ZEBRA_ROUTE_KERNEL,    0},  [ZEBRA_ROUTE_KERNEL]  = {ZEBRA_ROUTE_KERNEL,    0},
  {ZEBRA_ROUTE_CONNECT,   0},  [ZEBRA_ROUTE_CONNECT] = {ZEBRA_ROUTE_CONNECT,   0},
  {ZEBRA_ROUTE_STATIC,    1},  [ZEBRA_ROUTE_STATIC]  = {ZEBRA_ROUTE_STATIC,    1},
  {ZEBRA_ROUTE_RIP,     120},  [ZEBRA_ROUTE_RIP]     = {ZEBRA_ROUTE_RIP,     120},
  {ZEBRA_ROUTE_RIPNG,   120},  [ZEBRA_ROUTE_RIPNG]   = {ZEBRA_ROUTE_RIPNG,   120},
  {ZEBRA_ROUTE_OSPF,    110},  [ZEBRA_ROUTE_OSPF]    = {ZEBRA_ROUTE_OSPF,    110},
  {ZEBRA_ROUTE_OSPF6,   110},  [ZEBRA_ROUTE_OSPF6]   = {ZEBRA_ROUTE_OSPF6,   110},
  {ZEBRA_ROUTE_ISIS,    115},  [ZEBRA_ROUTE_ISIS]    = {ZEBRA_ROUTE_ISIS,    115},
  {ZEBRA_ROUTE_BGP,      20  /* IBGP is 200. */}  [ZEBRA_ROUTE_BGP]     = {ZEBRA_ROUTE_BGP,      20  /* IBGP is 200. */},
   [ZEBRA_ROUTE_BABEL]   = {ZEBRA_ROUTE_BABEL,    95},
   /* no entry/default: 150 */
 };  };
   
 /* Vector for routing table.  */  /* Vector for routing table.  */
 static vector vrf_vector;  static vector vrf_vector;
   
   /*
    * vrf_table_create
    */
   static void
   vrf_table_create (struct vrf *vrf, afi_t afi, safi_t safi)
   {
     rib_table_info_t *info;
     struct route_table *table;
   
     assert (!vrf->table[afi][safi]);
   
     table = route_table_init ();
     vrf->table[afi][safi] = table;
   
     info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info));
     info->vrf = vrf;
     info->afi = afi;
     info->safi = safi;
     table->info = info;
   }
   
 /* Allocate new VRF.  */  /* Allocate new VRF.  */
 static struct vrf *  static struct vrf *
 vrf_alloc (const char *name)  vrf_alloc (const char *name)
Line 85  vrf_alloc (const char *name) Line 109  vrf_alloc (const char *name)
     vrf->name = XSTRDUP (MTYPE_VRF_NAME, name);      vrf->name = XSTRDUP (MTYPE_VRF_NAME, name);
   
   /* Allocate routing table and static table.  */    /* Allocate routing table and static table.  */
  vrf->table[AFI_IP][SAFI_UNICAST] = route_table_init ();  vrf_table_create (vrf, AFI_IP, SAFI_UNICAST);
  vrf->table[AFI_IP6][SAFI_UNICAST] = route_table_init ();  vrf_table_create (vrf, AFI_IP6, SAFI_UNICAST);
   vrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();    vrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();
   vrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init ();    vrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init ();
     vrf_table_create (vrf, AFI_IP, SAFI_MULTICAST);
     vrf_table_create (vrf, AFI_IP6, SAFI_MULTICAST);
     vrf->stable[AFI_IP][SAFI_MULTICAST] = route_table_init ();
     vrf->stable[AFI_IP6][SAFI_MULTICAST] = route_table_init ();
   
   
   return vrf;    return vrf;
 }  }
   
Line 126  vrf_table (afi_t afi, safi_t safi, u_int32_t id) Line 155  vrf_table (afi_t afi, safi_t safi, u_int32_t id)
   if (! vrf)    if (! vrf)
     return NULL;      return NULL;
   
     if( afi >= AFI_MAX  || safi >= SAFI_MAX )
       return NULL;
   
   return vrf->table[afi][safi];    return vrf->table[afi][safi];
 }  }
   
Line 139  vrf_static_table (afi_t afi, safi_t safi, u_int32_t id Line 171  vrf_static_table (afi_t afi, safi_t safi, u_int32_t id
   if (! vrf)    if (! vrf)
     return NULL;      return NULL;
   
     if( afi >= AFI_MAX  || safi >= SAFI_MAX )
       return NULL;
   
   return vrf->stable[afi][safi];    return vrf->stable[afi][safi];
 }  }
   
   /*
    * nexthop_type_to_str
    */
   const char *
   nexthop_type_to_str (enum nexthop_types_t nh_type)
   {
     static const char *desc[] = {
       "none",
       "Directly connected",
       "Interface route",
       "IPv4 nexthop",
       "IPv4 nexthop with ifindex",
       "IPv4 nexthop with ifname",
       "IPv6 nexthop",
       "IPv6 nexthop with ifindex",
       "IPv6 nexthop with ifname",
       "Null0 nexthop",
     };
   
     if (nh_type >= ZEBRA_NUM_OF (desc))
       return "<Invalid nh type>";
   
     return desc[nh_type];
   }
   
 /* Add nexthop to the end of the list.  */  /* Add nexthop to the end of the list.  */
 static void  static void
 nexthop_add (struct rib *rib, struct nexthop *nexthop)  nexthop_add (struct rib *rib, struct nexthop *nexthop)
Line 225  nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv Line 285  nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv
   return nexthop;    return nexthop;
 }  }
   
static struct nexthop *struct nexthop *
 nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4,   nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4, 
                           struct in_addr *src, unsigned int ifindex)                            struct in_addr *src, unsigned int ifindex)
 {  {
Line 344  nexthop_active_ipv4 (struct rib *rib, struct nexthop * Line 404  nexthop_active_ipv4 (struct rib *rib, struct nexthop *
         return 0;          return 0;
   
       /* Pick up selected route. */        /* Pick up selected route. */
      for (match = rn->info; match; match = match->next)      RNODE_FOREACH_RIB (rn, match)
         {          {
           if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))            if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
             continue;              continue;
Line 445  nexthop_active_ipv6 (struct rib *rib, struct nexthop * Line 505  nexthop_active_ipv6 (struct rib *rib, struct nexthop *
         return 0;          return 0;
   
       /* Pick up selected route. */        /* Pick up selected route. */
      for (match = rn->info; match; match = match->next)      RNODE_FOREACH_RIB (rn, match)
         {          {
           if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))            if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
             continue;              continue;
Line 536  rib_match_ipv4 (struct in_addr addr) Line 596  rib_match_ipv4 (struct in_addr addr)
       route_unlock_node (rn);        route_unlock_node (rn);
               
       /* Pick up selected route. */        /* Pick up selected route. */
      for (match = rn->info; match; match = match->next)      RNODE_FOREACH_RIB (rn, match)
         {          {
           if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))            if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
             continue;              continue;
Line 594  rib_lookup_ipv4 (struct prefix_ipv4 *p) Line 654  rib_lookup_ipv4 (struct prefix_ipv4 *p)
   /* Unlock node. */    /* Unlock node. */
   route_unlock_node (rn);    route_unlock_node (rn);
   
  for (match = rn->info; match; match = match->next)  RNODE_FOREACH_RIB (rn, match)
     {      {
       if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))        if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
         continue;          continue;
Line 651  rib_lookup_ipv4_route (struct prefix_ipv4 *p, union so Line 711  rib_lookup_ipv4_route (struct prefix_ipv4 *p, union so
   route_unlock_node (rn);    route_unlock_node (rn);
   
   /* Find out if a "selected" RR for the discovered RIB entry exists ever. */    /* Find out if a "selected" RR for the discovered RIB entry exists ever. */
  for (match = rn->info; match; match = match->next)  RNODE_FOREACH_RIB (rn, match)
     {      {
       if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))        if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
         continue;          continue;
Line 671  rib_lookup_ipv4_route (struct prefix_ipv4 *p, union so Line 731  rib_lookup_ipv4_route (struct prefix_ipv4 *p, union so
     if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))      if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
     {      {
       /* We are happy with either direct or recursive hexthop */        /* We are happy with either direct or recursive hexthop */
      if (nexthop->gate.ipv4.s_addr == qgate->sin.sin_addr.s_addr ||      if (nexthop->gate.ipv4.s_addr == sockunion2ip (qgate) ||
          nexthop->rgate.ipv4.s_addr == qgate->sin.sin_addr.s_addr)          nexthop->rgate.ipv4.s_addr == sockunion2ip (qgate))
         return ZEBRA_RIB_FOUND_EXACT;          return ZEBRA_RIB_FOUND_EXACT;
       else        else
       {        {
Line 681  rib_lookup_ipv4_route (struct prefix_ipv4 *p, union so Line 741  rib_lookup_ipv4_route (struct prefix_ipv4 *p, union so
           char gate_buf[INET_ADDRSTRLEN], rgate_buf[INET_ADDRSTRLEN], qgate_buf[INET_ADDRSTRLEN];            char gate_buf[INET_ADDRSTRLEN], rgate_buf[INET_ADDRSTRLEN], qgate_buf[INET_ADDRSTRLEN];
           inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, gate_buf, INET_ADDRSTRLEN);            inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, gate_buf, INET_ADDRSTRLEN);
           inet_ntop (AF_INET, &nexthop->rgate.ipv4.s_addr, rgate_buf, INET_ADDRSTRLEN);            inet_ntop (AF_INET, &nexthop->rgate.ipv4.s_addr, rgate_buf, INET_ADDRSTRLEN);
          inet_ntop (AF_INET, &qgate->sin.sin_addr.s_addr, qgate_buf, INET_ADDRSTRLEN);          inet_ntop (AF_INET, &sockunion2ip (qgate), qgate_buf, INET_ADDRSTRLEN);
           zlog_debug ("%s: qgate == %s, gate == %s, rgate == %s", __func__, qgate_buf, gate_buf, rgate_buf);            zlog_debug ("%s: qgate == %s, gate == %s, rgate == %s", __func__, qgate_buf, gate_buf, rgate_buf);
         }          }
         return ZEBRA_RIB_FOUND_NOGATE;          return ZEBRA_RIB_FOUND_NOGATE;
Line 718  rib_match_ipv6 (struct in6_addr *addr) Line 778  rib_match_ipv6 (struct in6_addr *addr)
       route_unlock_node (rn);        route_unlock_node (rn);
               
       /* Pick up selected route. */        /* Pick up selected route. */
      for (match = rn->info; match; match = match->next)      RNODE_FOREACH_RIB (rn, match)
         {          {
           if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))            if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
             continue;              continue;
Line 908  rib_install_kernel (struct route_node *rn, struct rib  Line 968  rib_install_kernel (struct route_node *rn, struct rib 
   int ret = 0;    int ret = 0;
   struct nexthop *nexthop;    struct nexthop *nexthop;
   
     /*
      * Make sure we update the FPM any time we send new information to
      * the kernel.
      */
     zfpm_trigger_update (rn, "installing in kernel");
   switch (PREFIX_FAMILY (&rn->p))    switch (PREFIX_FAMILY (&rn->p))
     {      {
     case AF_INET:      case AF_INET:
Line 935  rib_uninstall_kernel (struct route_node *rn, struct ri Line 1000  rib_uninstall_kernel (struct route_node *rn, struct ri
   int ret = 0;    int ret = 0;
   struct nexthop *nexthop;    struct nexthop *nexthop;
   
     /*
      * Make sure we update the FPM any time we send new information to
      * the kernel.
      */
     zfpm_trigger_update (rn, "uninstalling from kernel");
   
   switch (PREFIX_FAMILY (&rn->p))    switch (PREFIX_FAMILY (&rn->p))
     {      {
     case AF_INET:      case AF_INET:
Line 959  rib_uninstall (struct route_node *rn, struct rib *rib) Line 1030  rib_uninstall (struct route_node *rn, struct rib *rib)
 {  {
   if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))    if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
     {      {
         zfpm_trigger_update (rn, "rib_uninstall");
   
       redistribute_delete (&rn->p, rib);        redistribute_delete (&rn->p, rib);
       if (! RIB_SYSTEM_ROUTE (rib))        if (! RIB_SYSTEM_ROUTE (rib))
         rib_uninstall_kernel (rn, rib);          rib_uninstall_kernel (rn, rib);
Line 968  rib_uninstall (struct route_node *rn, struct rib *rib) Line 1041  rib_uninstall (struct route_node *rn, struct rib *rib)
   
 static void rib_unlink (struct route_node *, struct rib *);  static void rib_unlink (struct route_node *, struct rib *);
   
   /*
    * rib_can_delete_dest
    *
    * Returns TRUE if the given dest can be deleted from the table.
    */
   static int
   rib_can_delete_dest (rib_dest_t *dest)
   {
     if (dest->routes)
       {
         return 0;
       }
   
     /*
      * Don't delete the dest if we have to update the FPM about this
      * prefix.
      */
     if (CHECK_FLAG (dest->flags, RIB_DEST_UPDATE_FPM) ||
         CHECK_FLAG (dest->flags, RIB_DEST_SENT_TO_FPM))
       return 0;
   
     return 1;
   }
   
   /*
    * rib_gc_dest
    *
    * Garbage collect the rib dest corresponding to the given route node
    * if appropriate.
    *
    * Returns TRUE if the dest was deleted, FALSE otherwise.
    */
   int
   rib_gc_dest (struct route_node *rn)
   {
     rib_dest_t *dest;
     char buf[INET6_ADDRSTRLEN];
   
     dest = rib_dest_from_rnode (rn);
     if (!dest)
       return 0;
   
     if (!rib_can_delete_dest (dest))
       return 0;
   
     if (IS_ZEBRA_DEBUG_RIB)
       {
         inet_ntop (rn->p.family, &rn->p.u.prefix, buf, sizeof (buf));
         zlog_debug ("%s: %s/%d: removing dest from table", __func__,
                     buf, rn->p.prefixlen);
       }
   
     dest->rnode = NULL;
     XFREE (MTYPE_RIB_DEST, dest);
     rn->info = NULL;
   
     /*
      * Release the one reference that we keep on the route node.
      */
     route_unlock_node (rn);
     return 1;
   }
   
 /* Core function for processing routing information base. */  /* Core function for processing routing information base. */
 static void  static void
 rib_process (struct route_node *rn)  rib_process (struct route_node *rn)
Line 986  rib_process (struct route_node *rn) Line 1122  rib_process (struct route_node *rn)
   if (IS_ZEBRA_DEBUG_RIB || IS_ZEBRA_DEBUG_RIB_Q)    if (IS_ZEBRA_DEBUG_RIB || IS_ZEBRA_DEBUG_RIB_Q)
     inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);      inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
   
  for (rib = rn->info; rib; rib = next)  RNODE_FOREACH_RIB_SAFE (rn, rib, next)
     {      {
       /* The next pointer is saved, because current pointer  
        * may be passed to rib_unlink() in the middle of iteration.  
        */  
       next = rib->next;  
         
       /* Currently installed rib. */        /* Currently installed rib. */
       if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))        if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
         {          {
Line 1010  rib_process (struct route_node *rn) Line 1141  rib_process (struct route_node *rn)
               if (IS_ZEBRA_DEBUG_RIB)                if (IS_ZEBRA_DEBUG_RIB)
                 zlog_debug ("%s: %s/%d: rn %p, removing rib %p", __func__,                  zlog_debug ("%s: %s/%d: rn %p, removing rib %p", __func__,
                   buf, rn->p.prefixlen, rn, rib);                    buf, rn->p.prefixlen, rn, rib);
                rib_unlink (rn, rib);              rib_unlink (rn, rib);
             }              }
           else            else
             del = rib;              del = rib;
Line 1067  rib_process (struct route_node *rn) Line 1198  rib_process (struct route_node *rn)
       /* metric tie-breaks equal distance */        /* metric tie-breaks equal distance */
       if (rib->metric <= select->metric)        if (rib->metric <= select->metric)
         select = rib;          select = rib;
    } /* for (rib = rn->info; rib; rib = next) */    } /* RNODE_FOREACH_RIB_SAFE */
   
   /* After the cycle is finished, the following pointers will be set:    /* After the cycle is finished, the following pointers will be set:
    * select --- the winner RIB entry, if any was found, otherwise NULL     * select --- the winner RIB entry, if any was found, otherwise NULL
Line 1084  rib_process (struct route_node *rn) Line 1215  rib_process (struct route_node *rn)
                      __func__, buf, rn->p.prefixlen, select, fib);                       __func__, buf, rn->p.prefixlen, select, fib);
       if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))        if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
         {          {
             zfpm_trigger_update (rn, "updating existing route");
   
           redistribute_delete (&rn->p, select);            redistribute_delete (&rn->p, select);
           if (! RIB_SYSTEM_ROUTE (select))            if (! RIB_SYSTEM_ROUTE (select))
             rib_uninstall_kernel (rn, select);              rib_uninstall_kernel (rn, select);
Line 1125  rib_process (struct route_node *rn) Line 1258  rib_process (struct route_node *rn)
       if (IS_ZEBRA_DEBUG_RIB)        if (IS_ZEBRA_DEBUG_RIB)
         zlog_debug ("%s: %s/%d: Removing existing route, fib %p", __func__,          zlog_debug ("%s: %s/%d: Removing existing route, fib %p", __func__,
           buf, rn->p.prefixlen, fib);            buf, rn->p.prefixlen, fib);
   
         zfpm_trigger_update (rn, "removing existing route");
   
       redistribute_delete (&rn->p, fib);        redistribute_delete (&rn->p, fib);
       if (! RIB_SYSTEM_ROUTE (fib))        if (! RIB_SYSTEM_ROUTE (fib))
         rib_uninstall_kernel (rn, fib);          rib_uninstall_kernel (rn, fib);
Line 1143  rib_process (struct route_node *rn) Line 1279  rib_process (struct route_node *rn)
       if (IS_ZEBRA_DEBUG_RIB)        if (IS_ZEBRA_DEBUG_RIB)
         zlog_debug ("%s: %s/%d: Adding route, select %p", __func__, buf,          zlog_debug ("%s: %s/%d: Adding route, select %p", __func__, buf,
           rn->p.prefixlen, select);            rn->p.prefixlen, select);
   
         zfpm_trigger_update (rn, "new route selected");
   
       /* Set real nexthop. */        /* Set real nexthop. */
       nexthop_active_update (rn, select, 1);        nexthop_active_update (rn, select, 1);
   
Line 1164  rib_process (struct route_node *rn) Line 1303  rib_process (struct route_node *rn)
 end:  end:
   if (IS_ZEBRA_DEBUG_RIB_Q)    if (IS_ZEBRA_DEBUG_RIB_Q)
     zlog_debug ("%s: %s/%d: rn %p dequeued", __func__, buf, rn->p.prefixlen, rn);      zlog_debug ("%s: %s/%d: rn %p dequeued", __func__, buf, rn->p.prefixlen, rn);
   
     /*
      * Check if the dest can be deleted now.
      */
     rib_gc_dest (rn);
 }  }
   
 /* Take a list of route_node structs and return 1, if there was a record  /* Take a list of route_node structs and return 1, if there was a record
Line 1182  process_subq (struct list * subq, u_char qindex) Line 1326  process_subq (struct list * subq, u_char qindex)
   rnode = listgetdata (lnode);    rnode = listgetdata (lnode);
   rib_process (rnode);    rib_process (rnode);
   
  if (rnode->info) /* The first RIB record is holding the flags bitmask. */  if (rnode->info)
    UNSET_FLAG (((struct rib *)rnode->info)->rn_status, RIB_ROUTE_QUEUED(qindex));    UNSET_FLAG (rib_dest_from_rnode (rnode)->flags, RIB_ROUTE_QUEUED (qindex));
 
 #if 0  #if 0
   else    else
     {      {
Line 1216  meta_queue_process (struct work_queue *dummy, void *da Line 1361  meta_queue_process (struct work_queue *dummy, void *da
   return mq->size ? WQ_REQUEUE : WQ_SUCCESS;    return mq->size ? WQ_REQUEUE : WQ_SUCCESS;
 }  }
   
/* Map from rib types to queue type (priority) in meta queue *//*
  * Map from rib types to queue type (priority) in meta queue
  */
 static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = {  static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = {
   [ZEBRA_ROUTE_SYSTEM]  = 4,    [ZEBRA_ROUTE_SYSTEM]  = 4,
   [ZEBRA_ROUTE_KERNEL]  = 0,    [ZEBRA_ROUTE_KERNEL]  = 0,
Line 1229  static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] =  Line 1376  static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = 
   [ZEBRA_ROUTE_ISIS]    = 2,    [ZEBRA_ROUTE_ISIS]    = 2,
   [ZEBRA_ROUTE_BGP]     = 3,    [ZEBRA_ROUTE_BGP]     = 3,
   [ZEBRA_ROUTE_HSLS]    = 4,    [ZEBRA_ROUTE_HSLS]    = 4,
     [ZEBRA_ROUTE_BABEL]   = 2,
 };  };
   
 /* Look into the RN and queue it into one or more priority queues,  /* Look into the RN and queue it into one or more priority queues,
Line 1243  rib_meta_queue_add (struct meta_queue *mq, struct rout Line 1391  rib_meta_queue_add (struct meta_queue *mq, struct rout
   if (IS_ZEBRA_DEBUG_RIB_Q)    if (IS_ZEBRA_DEBUG_RIB_Q)
     inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);      inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
   
  for (rib = rn->info; rib; rib = rib->next)  RNODE_FOREACH_RIB (rn, rib)
     {      {
       u_char qindex = meta_queue_map[rib->type];        u_char qindex = meta_queue_map[rib->type];
   
       /* Invariant: at this point we always have rn->info set. */        /* Invariant: at this point we always have rn->info set. */
      if (CHECK_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED(qindex)))      if (CHECK_FLAG (rib_dest_from_rnode (rn)->flags,
                       RIB_ROUTE_QUEUED (qindex)))
         {          {
           if (IS_ZEBRA_DEBUG_RIB_Q)            if (IS_ZEBRA_DEBUG_RIB_Q)
             zlog_debug ("%s: %s/%d: rn %p is already queued in sub-queue %u",              zlog_debug ("%s: %s/%d: rn %p is already queued in sub-queue %u",
Line 1256  rib_meta_queue_add (struct meta_queue *mq, struct rout Line 1405  rib_meta_queue_add (struct meta_queue *mq, struct rout
           continue;            continue;
         }          }
   
      SET_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED(qindex));      SET_FLAG (rib_dest_from_rnode (rn)->flags, RIB_ROUTE_QUEUED (qindex));
       listnode_add (mq->subq[qindex], rn);        listnode_add (mq->subq[qindex], rn);
       route_lock_node (rn);        route_lock_node (rn);
       mq->size++;        mq->size++;
Line 1271  rib_meta_queue_add (struct meta_queue *mq, struct rout Line 1420  rib_meta_queue_add (struct meta_queue *mq, struct rout
 static void  static void
 rib_queue_add (struct zebra_t *zebra, struct route_node *rn)  rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
 {  {
     char buf[INET_ADDRSTRLEN];
     assert (zebra && rn);
       
   if (IS_ZEBRA_DEBUG_RIB_Q)    if (IS_ZEBRA_DEBUG_RIB_Q)
       inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN);
   
     /* Pointless to queue a route_node with no RIB entries to add or remove */
     if (!rnode_to_ribs (rn))
     {      {
      char buf[INET6_ADDRSTRLEN];      zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
                   __func__, rn, rn->lock);
       zlog_backtrace(LOG_DEBUG);
       return;
     }
   
      zlog_info ("%s: %s/%d: work queue added", __func__,  if (IS_ZEBRA_DEBUG_RIB_Q)
                 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN),    zlog_info ("%s: %s/%d: work queue added", __func__, buf, rn->p.prefixlen);
                 rn->p.prefixlen);
   assert (zebra);
 
   if (zebra->ribq == NULL)
     {
       zlog_err ("%s: work_queue does not exist!", __func__);
       return;
     }      }
   
   /*    /*
Line 1293  rib_queue_add (struct zebra_t *zebra, struct route_nod Line 1458  rib_queue_add (struct zebra_t *zebra, struct route_nod
     work_queue_add (zebra->ribq, zebra->mq);      work_queue_add (zebra->ribq, zebra->mq);
   
   rib_meta_queue_add (zebra->mq, rn);    rib_meta_queue_add (zebra->mq, rn);
   
     if (IS_ZEBRA_DEBUG_RIB_Q)
       zlog_debug ("%s: %s/%d: rn %p queued", __func__, buf, rn->p.prefixlen, rn);
   
     return;
 }  }
   
 /* Create new meta queue.  /* Create new meta queue.
Line 1320  meta_queue_new (void) Line 1490  meta_queue_new (void)
 static void  static void
 rib_queue_init (struct zebra_t *zebra)  rib_queue_init (struct zebra_t *zebra)
 {  {
     assert (zebra);
     
   if (! (zebra->ribq = work_queue_new (zebra->master,     if (! (zebra->ribq = work_queue_new (zebra->master, 
                                        "route_node processing")))                                         "route_node processing")))
     {      {
Line 1335  rib_queue_init (struct zebra_t *zebra) Line 1507  rib_queue_init (struct zebra_t *zebra)
   zebra->ribq->spec.hold = rib_process_hold_time;    zebra->ribq->spec.hold = rib_process_hold_time;
       
   if (!(zebra->mq = meta_queue_new ()))    if (!(zebra->mq = meta_queue_new ()))
     {
     zlog_err ("%s: could not initialise meta queue!", __func__);      zlog_err ("%s: could not initialise meta queue!", __func__);
       return;
     }
     return;
 }  }
   
 /* RIB updates are processed via a queue of pointers to route_nodes.  /* RIB updates are processed via a queue of pointers to route_nodes.
Line 1360  rib_queue_init (struct zebra_t *zebra) Line 1536  rib_queue_init (struct zebra_t *zebra)
  * |-> set RIB_ENTRY_REMOVE                           |   * |-> set RIB_ENTRY_REMOVE                           |
  * rib_delnode                                  (RIB freed)   * rib_delnode                                  (RIB freed)
  *   *
 * * The 'info' pointer of a route_node points to a rib_dest_t
 * Queueing state for a route_node is kept in the head RIB entry, this * ('dest'). Queueing state for a route_node is kept on the dest. The
 * state must be preserved as and when the head RIB entry of a * dest is created on-demand by rib_link() and is kept around at least
 * route_node is changed by rib_unlink / rib_link. A small complication, * as long as there are ribs hanging off it (@see rib_gc_dest()).
 * but saves having to allocate a dedicated object for this. 
  *    * 
  * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code):   * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code):
  *   *
  * - route_nodes: refcounted by:   * - route_nodes: refcounted by:
 *   - RIBs attached to route_node: *   - dest attached to route_node:
 *     - managed by: rib_link/unlink *     - managed by: rib_link/rib_gc_dest
  *   - route_node processing queue   *   - route_node processing queue
  *     - managed by: rib_addqueue, rib_process.   *     - managed by: rib_addqueue, rib_process.
  *   *
Line 1381  static void Line 1556  static void
 rib_link (struct route_node *rn, struct rib *rib)  rib_link (struct route_node *rn, struct rib *rib)
 {  {
   struct rib *head;    struct rib *head;
     rib_dest_t *dest;
   char buf[INET6_ADDRSTRLEN];    char buf[INET6_ADDRSTRLEN];
  
   assert (rib && rn);    assert (rib && rn);
       
   route_lock_node (rn); /* rn route table reference */  
   
   if (IS_ZEBRA_DEBUG_RIB)    if (IS_ZEBRA_DEBUG_RIB)
   {    {
     inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);      inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
Line 1394  rib_link (struct route_node *rn, struct rib *rib) Line 1568  rib_link (struct route_node *rn, struct rib *rib)
       buf, rn->p.prefixlen, rn, rib);        buf, rn->p.prefixlen, rn, rib);
   }    }
   
  head = rn->info;  dest = rib_dest_from_rnode (rn);
  if (head)  if (!dest)
     {      {
       if (IS_ZEBRA_DEBUG_RIB)        if (IS_ZEBRA_DEBUG_RIB)
        zlog_debug ("%s: %s/%d: new head, rn_status copied over", __func__,        {
          buf, rn->p.prefixlen);          zlog_debug ("%s: %s/%d: adding dest to table", __func__,
                       buf, rn->p.prefixlen);
         }
 
       dest = XCALLOC (MTYPE_RIB_DEST, sizeof (rib_dest_t));
       route_lock_node (rn); /* rn route table reference */
       rn->info = dest;
       dest->rnode = rn;
     }
 
   head = dest->routes;
   if (head)
     {
       head->prev = rib;        head->prev = rib;
       /* Transfer the rn status flags to the new head RIB */  
       rib->rn_status = head->rn_status;  
     }      }
   rib->next = head;    rib->next = head;
  rn->info = rib;  dest->routes = rib;
   rib_queue_add (&zebrad, rn);    rib_queue_add (&zebrad, rn);
 }  }
   
Line 1430  rib_addnode (struct route_node *rn, struct rib *rib) Line 1614  rib_addnode (struct route_node *rn, struct rib *rib)
   rib_link (rn, rib);    rib_link (rn, rib);
 }  }
   
   /*
    * rib_unlink
    *
    * Detach a rib structure from a route_node.
    *
    * Note that a call to rib_unlink() should be followed by a call to
    * rib_gc_dest() at some point. This allows a rib_dest_t that is no
    * longer required to be deleted.
    */
 static void  static void
 rib_unlink (struct route_node *rn, struct rib *rib)  rib_unlink (struct route_node *rn, struct rib *rib)
 {  {
   struct nexthop *nexthop, *next;    struct nexthop *nexthop, *next;
   char buf[INET6_ADDRSTRLEN];    char buf[INET6_ADDRSTRLEN];
     rib_dest_t *dest;
   
   assert (rn && rib);    assert (rn && rib);
   
Line 1445  rib_unlink (struct route_node *rn, struct rib *rib) Line 1639  rib_unlink (struct route_node *rn, struct rib *rib)
                 __func__, buf, rn->p.prefixlen, rn, rib);                  __func__, buf, rn->p.prefixlen, rn, rib);
   }    }
   
     dest = rib_dest_from_rnode (rn);
   
   if (rib->next)    if (rib->next)
     rib->next->prev = rib->prev;      rib->next->prev = rib->prev;
   
Line 1452  rib_unlink (struct route_node *rn, struct rib *rib) Line 1648  rib_unlink (struct route_node *rn, struct rib *rib)
     rib->prev->next = rib->next;      rib->prev->next = rib->next;
   else    else
     {      {
      rn->info = rib->next;      dest->routes = rib->next;
       
      if (rn->info) 
        { 
          if (IS_ZEBRA_DEBUG_RIB) 
            zlog_debug ("%s: %s/%d: rn %p, rib %p, new head copy", 
                        __func__, buf, rn->p.prefixlen, rn, rib); 
          rib->next->rn_status = rib->rn_status; 
        } 
     }      }
   
   /* free RIB and nexthops */    /* free RIB and nexthops */
Line 1471  rib_unlink (struct route_node *rn, struct rib *rib) Line 1659  rib_unlink (struct route_node *rn, struct rib *rib)
     }      }
   XFREE (MTYPE_RIB, rib);    XFREE (MTYPE_RIB, rib);
   
   route_unlock_node (rn); /* rn route table reference */  
 }  }
   
 static void  static void
Line 1492  int Line 1679  int
 rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,   rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p, 
               struct in_addr *gate, struct in_addr *src,                struct in_addr *gate, struct in_addr *src,
               unsigned int ifindex, u_int32_t vrf_id,                unsigned int ifindex, u_int32_t vrf_id,
              u_int32_t metric, u_char distance)              u_int32_t metric, u_char distance, safi_t safi)
 {  {
   struct rib *rib;    struct rib *rib;
   struct rib *same = NULL;    struct rib *same = NULL;
Line 1501  rib_add_ipv4 (int type, int flags, struct prefix_ipv4  Line 1688  rib_add_ipv4 (int type, int flags, struct prefix_ipv4 
   struct nexthop *nexthop;    struct nexthop *nexthop;
   
   /* Lookup table.  */    /* Lookup table.  */
  table = vrf_table (AFI_IP, SAFI_UNICAST, 0);  table = vrf_table (AFI_IP, safi, 0);
   if (! table)    if (! table)
     return 0;      return 0;
   
Line 1511  rib_add_ipv4 (int type, int flags, struct prefix_ipv4  Line 1698  rib_add_ipv4 (int type, int flags, struct prefix_ipv4 
   /* Set default distance by route type. */    /* Set default distance by route type. */
   if (distance == 0)    if (distance == 0)
     {      {
      distance = route_info[type].distance;      if ((unsigned)type >= array_size(route_info))
         distance = 150;
       else
         distance = route_info[type].distance;
   
       /* iBGP distance is 200. */        /* iBGP distance is 200. */
       if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))        if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
Line 1523  rib_add_ipv4 (int type, int flags, struct prefix_ipv4  Line 1713  rib_add_ipv4 (int type, int flags, struct prefix_ipv4 
   
   /* If same type of route are installed, treat it as a implicit    /* If same type of route are installed, treat it as a implicit
      withdraw. */       withdraw. */
  for (rib = rn->info; rib; rib = rib->next)  RNODE_FOREACH_RIB (rn, rib)
     {      {
       if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))        if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
         continue;          continue;
Line 1679  void rib_lookup_and_dump (struct prefix_ipv4 * p) Line 1869  void rib_lookup_and_dump (struct prefix_ipv4 * p)
   route_unlock_node (rn);    route_unlock_node (rn);
   
   /* let's go */    /* let's go */
  for (rib = rn->info; rib; rib = rib->next)  RNODE_FOREACH_RIB (rn, rib)
   {    {
     zlog_debug      zlog_debug
     (      (
Line 1726  void rib_lookup_and_pushup (struct prefix_ipv4 * p) Line 1916  void rib_lookup_and_pushup (struct prefix_ipv4 * p)
    * RIBQ record already on head. This is necessary for proper revalidation     * RIBQ record already on head. This is necessary for proper revalidation
    * of the rest of the RIB.     * of the rest of the RIB.
    */     */
  for (rib = rn->info; rib; rib = rib->next)  RNODE_FOREACH_RIB (rn, rib)
   {    {
     if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) &&      if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) &&
       ! RIB_SYSTEM_ROUTE (rib))        ! RIB_SYSTEM_ROUTE (rib))
Line 1747  void rib_lookup_and_pushup (struct prefix_ipv4 * p) Line 1937  void rib_lookup_and_pushup (struct prefix_ipv4 * p)
 }  }
   
 int  int
rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib)rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi)
 {  {
   struct route_table *table;    struct route_table *table;
   struct route_node *rn;    struct route_node *rn;
Line 1755  rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct  Line 1945  rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct 
   struct nexthop *nexthop;    struct nexthop *nexthop;
       
   /* Lookup table.  */    /* Lookup table.  */
  table = vrf_table (AFI_IP, SAFI_UNICAST, 0);  table = vrf_table (AFI_IP, safi, 0);
   if (! table)    if (! table)
     return 0;      return 0;
   
   /* Make it sure prefixlen is applied to the prefix. */    /* Make it sure prefixlen is applied to the prefix. */
   apply_mask_ipv4 (p);    apply_mask_ipv4 (p);
   
Line 1777  rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct  Line 1968  rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct 
   
   /* If same type of route are installed, treat it as a implicit    /* If same type of route are installed, treat it as a implicit
      withdraw. */       withdraw. */
  for (same = rn->info; same; same = same->next)  RNODE_FOREACH_RIB (rn, same)
     {      {
       if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED))        if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED))
         continue;          continue;
Line 1820  rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct  Line 2011  rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct 
 /* XXX factor with rib_delete_ipv6 */  /* XXX factor with rib_delete_ipv6 */
 int  int
 rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,  rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
                 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id)                 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi)
 {  {
   struct route_table *table;    struct route_table *table;
   struct route_node *rn;    struct route_node *rn;
Line 1832  rib_delete_ipv4 (int type, int flags, struct prefix_ip Line 2023  rib_delete_ipv4 (int type, int flags, struct prefix_ip
   char buf2[INET_ADDRSTRLEN];    char buf2[INET_ADDRSTRLEN];
   
   /* Lookup table.  */    /* Lookup table.  */
  table = vrf_table (AFI_IP, SAFI_UNICAST, 0);  table = vrf_table (AFI_IP, safi, 0);
   if (! table)    if (! table)
     return 0;      return 0;
   
Line 1868  rib_delete_ipv4 (int type, int flags, struct prefix_ip Line 2059  rib_delete_ipv4 (int type, int flags, struct prefix_ip
     }      }
   
   /* Lookup same type route. */    /* Lookup same type route. */
  for (rib = rn->info; rib; rib = rib->next)  RNODE_FOREACH_RIB (rn, rib)
     {      {
       if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))        if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
         continue;          continue;
Line 1879  rib_delete_ipv4 (int type, int flags, struct prefix_ip Line 2070  rib_delete_ipv4 (int type, int flags, struct prefix_ip
       if (rib->type != type)        if (rib->type != type)
         continue;          continue;
       if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&        if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
          nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex)          nexthop->type == NEXTHOP_TYPE_IFINDEX)
         {          {
             if (nexthop->ifindex != ifindex)
               continue;
           if (rib->refcnt)            if (rib->refcnt)
             {              {
               rib->refcnt--;                rib->refcnt--;
Line 1959  static_install_ipv4 (struct prefix *p, struct static_i Line 2152  static_install_ipv4 (struct prefix *p, struct static_i
   
   /* Lookup existing route */    /* Lookup existing route */
   rn = route_node_get (table, p);    rn = route_node_get (table, p);
  for (rib = rn->info; rib; rib = rib->next)  RNODE_FOREACH_RIB (rn, rib)
     {      {
        if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))         if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
          continue;           continue;
Line 1995  static_install_ipv4 (struct prefix *p, struct static_i Line 2188  static_install_ipv4 (struct prefix *p, struct static_i
       rib->type = ZEBRA_ROUTE_STATIC;        rib->type = ZEBRA_ROUTE_STATIC;
       rib->distance = si->distance;        rib->distance = si->distance;
       rib->metric = 0;        rib->metric = 0;
         rib->table = zebrad.rtm_table_default;
       rib->nexthop_num = 0;        rib->nexthop_num = 0;
   
       switch (si->type)        switch (si->type)
Line 2054  static_uninstall_ipv4 (struct prefix *p, struct static Line 2248  static_uninstall_ipv4 (struct prefix *p, struct static
   if (! rn)    if (! rn)
     return;      return;
   
  for (rib = rn->info; rib; rib = rib->next)  RNODE_FOREACH_RIB (rn, rib)
     {      {
       if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))        if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
         continue;          continue;
Line 2281  rib_bogus_ipv6 (int type, struct prefix_ipv6 *p, Line 2475  rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
 int  int
 rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,  rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
               struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id,                struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
              u_int32_t metric, u_char distance)              u_int32_t metric, u_char distance, safi_t safi)
 {  {
   struct rib *rib;    struct rib *rib;
   struct rib *same = NULL;    struct rib *same = NULL;
Line 2290  rib_add_ipv6 (int type, int flags, struct prefix_ipv6  Line 2484  rib_add_ipv6 (int type, int flags, struct prefix_ipv6 
   struct nexthop *nexthop;    struct nexthop *nexthop;
   
   /* Lookup table.  */    /* Lookup table.  */
  table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);  table = vrf_table (AFI_IP6, safi, 0);
   if (! table)    if (! table)
     return 0;      return 0;
   
Line 2313  rib_add_ipv6 (int type, int flags, struct prefix_ipv6  Line 2507  rib_add_ipv6 (int type, int flags, struct prefix_ipv6 
   
   /* If same type of route are installed, treat it as a implicit    /* If same type of route are installed, treat it as a implicit
      withdraw. */       withdraw. */
  for (rib = rn->info; rib; rib = rib->next)  RNODE_FOREACH_RIB (rn, rib)
     {      {
       if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))        if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
         continue;          continue;
Line 2375  rib_add_ipv6 (int type, int flags, struct prefix_ipv6  Line 2569  rib_add_ipv6 (int type, int flags, struct prefix_ipv6 
 /* XXX factor with rib_delete_ipv6 */  /* XXX factor with rib_delete_ipv6 */
 int  int
 rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,  rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
                 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id)                 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi)
 {  {
   struct route_table *table;    struct route_table *table;
   struct route_node *rn;    struct route_node *rn;
Line 2390  rib_delete_ipv6 (int type, int flags, struct prefix_ip Line 2584  rib_delete_ipv6 (int type, int flags, struct prefix_ip
   apply_mask_ipv6 (p);    apply_mask_ipv6 (p);
   
   /* Lookup table.  */    /* Lookup table.  */
  table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);  table = vrf_table (AFI_IP6, safi, 0);
   if (! table)    if (! table)
     return 0;      return 0;
       
Line 2416  rib_delete_ipv6 (int type, int flags, struct prefix_ip Line 2610  rib_delete_ipv6 (int type, int flags, struct prefix_ip
     }      }
   
   /* Lookup same type route. */    /* Lookup same type route. */
  for (rib = rn->info; rib; rib = rib->next)  RNODE_FOREACH_RIB (rn, rib)
     {      {
       if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))        if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
         continue;          continue;
Line 2427  rib_delete_ipv6 (int type, int flags, struct prefix_ip Line 2621  rib_delete_ipv6 (int type, int flags, struct prefix_ip
       if (rib->type != type)        if (rib->type != type)
         continue;          continue;
       if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&        if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
          nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex)          nexthop->type == NEXTHOP_TYPE_IFINDEX)
         {          {
             if (nexthop->ifindex != ifindex)
               continue;
           if (rib->refcnt)            if (rib->refcnt)
             {              {
               rib->refcnt--;                rib->refcnt--;
Line 2507  static_install_ipv6 (struct prefix *p, struct static_i Line 2703  static_install_ipv6 (struct prefix *p, struct static_i
   
   /* Lookup existing route */    /* Lookup existing route */
   rn = route_node_get (table, p);    rn = route_node_get (table, p);
  for (rib = rn->info; rib; rib = rib->next)  RNODE_FOREACH_RIB (rn, rib)
     {      {
       if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))        if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
         continue;          continue;
Line 2604  static_uninstall_ipv6 (struct prefix *p, struct static Line 2800  static_uninstall_ipv6 (struct prefix *p, struct static
   if (! rn)    if (! rn)
     return;      return;
   
  for (rib = rn->info; rib; rib = rib->next)  RNODE_FOREACH_RIB (rn, rib)
     {      {
       if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))        if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
         continue;          continue;
Line 2800  rib_update (void) Line 2996  rib_update (void)
   table = vrf_table (AFI_IP, SAFI_UNICAST, 0);    table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
   if (table)    if (table)
     for (rn = route_top (table); rn; rn = route_next (rn))      for (rn = route_top (table); rn; rn = route_next (rn))
      if (rn->info)      if (rnode_to_ribs (rn))
         rib_queue_add (&zebrad, rn);          rib_queue_add (&zebrad, rn);
   
   table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);    table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
   if (table)    if (table)
     for (rn = route_top (table); rn; rn = route_next (rn))      for (rn = route_top (table); rn; rn = route_next (rn))
      if (rn->info)      if (rnode_to_ribs (rn))
         rib_queue_add (&zebrad, rn);          rib_queue_add (&zebrad, rn);
 }  }
   
Line 2821  rib_weed_table (struct route_table *table) Line 3017  rib_weed_table (struct route_table *table)
   
   if (table)    if (table)
     for (rn = route_top (table); rn; rn = route_next (rn))      for (rn = route_top (table); rn; rn = route_next (rn))
      for (rib = rn->info; rib; rib = next)      RNODE_FOREACH_RIB_SAFE (rn, rib, next)
         {          {
           next = rib->next;  
   
           if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))            if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
             continue;              continue;
   
Line 2853  rib_sweep_table (struct route_table *table) Line 3047  rib_sweep_table (struct route_table *table)
   
   if (table)    if (table)
     for (rn = route_top (table); rn; rn = route_next (rn))      for (rn = route_top (table); rn; rn = route_next (rn))
      for (rib = rn->info; rib; rib = next)      RNODE_FOREACH_RIB_SAFE (rn, rib, next)
         {          {
           next = rib->next;  
   
           if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))            if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
             continue;              continue;
   
Line 2877  rib_sweep_route (void) Line 3069  rib_sweep_route (void)
   rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));    rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
   rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));    rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
 }  }
 /* Remove specific by protocol routes from 'table'. */
 static unsigned long
 rib_score_proto_table (u_char proto, struct route_table *table)
 {
   struct route_node *rn;
   struct rib *rib;
   struct rib *next;
   unsigned long n = 0;
 
   if (table)
     for (rn = route_top (table); rn; rn = route_next (rn))
       RNODE_FOREACH_RIB_SAFE (rn, rib, next)
         {
           if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
             continue;
           if (rib->type == proto)
             {
               rib_delnode (rn, rib);
               n++;
             }
         }
 
   return n;
 }
 
 /* Remove specific by protocol routes. */
 unsigned long
 rib_score_proto (u_char proto)
 {
   return  rib_score_proto_table (proto, vrf_table (AFI_IP,  SAFI_UNICAST, 0))
          +rib_score_proto_table (proto, vrf_table (AFI_IP6, SAFI_UNICAST, 0));
 }
 
 /* Close RIB and clean up kernel routes. */  /* Close RIB and clean up kernel routes. */
 static void  static void
 rib_close_table (struct route_table *table)  rib_close_table (struct route_table *table)
Line 2887  rib_close_table (struct route_table *table) Line 3112  rib_close_table (struct route_table *table)
   
   if (table)    if (table)
     for (rn = route_top (table); rn; rn = route_next (rn))      for (rn = route_top (table); rn; rn = route_next (rn))
      for (rib = rn->info; rib; rib = rib->next)      RNODE_FOREACH_RIB (rn, rib)
         {          {
          if (! RIB_SYSTEM_ROUTE (rib)          if (!CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
              && CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))            continue;
            rib_uninstall_kernel (rn, rib);
           zfpm_trigger_update (rn, NULL);
 
           if (! RIB_SYSTEM_ROUTE (rib))
             rib_uninstall_kernel (rn, rib);
         }          }
 }  }
   
Line 2910  rib_init (void) Line 3139  rib_init (void)
   rib_queue_init (&zebrad);    rib_queue_init (&zebrad);
   /* VRF initialization.  */    /* VRF initialization.  */
   vrf_init ();    vrf_init ();
   }
   
   /*
    * vrf_id_get_next
    *
    * Get the first vrf id that is greater than the given vrf id if any.
    *
    * Returns TRUE if a vrf id was found, FALSE otherwise.
    */
   static inline int
   vrf_id_get_next (uint32_t id, uint32_t *next_id_p)
   {
     while (++id < vector_active (vrf_vector))
       {
         if (vrf_lookup (id))
           {
             *next_id_p = id;
             return 1;
           }
       }
   
     return 0;
   }
   
   /*
    * rib_tables_iter_next
    *
    * Returns the next table in the iteration.
    */
   struct route_table *
   rib_tables_iter_next (rib_tables_iter_t *iter)
   {
     struct route_table *table;
   
     /*
      * Array that helps us go over all AFI/SAFI combinations via one
      * index.
      */
     static struct {
       afi_t afi;
       safi_t safi;
     } afi_safis[] = {
       { AFI_IP, SAFI_UNICAST },
       { AFI_IP, SAFI_MULTICAST },
       { AFI_IP6, SAFI_UNICAST },
       { AFI_IP6, SAFI_MULTICAST },
     };
   
     table = NULL;
   
     switch (iter->state)
       {
   
       case RIB_TABLES_ITER_S_INIT:
         iter->vrf_id = 0;
         iter->afi_safi_ix = -1;
   
         /* Fall through */
   
       case RIB_TABLES_ITER_S_ITERATING:
         iter->afi_safi_ix++;
         while (1)
           {
   
             while (iter->afi_safi_ix < (int) ZEBRA_NUM_OF (afi_safis))
               {
                 table = vrf_table (afi_safis[iter->afi_safi_ix].afi,
                                    afi_safis[iter->afi_safi_ix].safi,
                                    iter->vrf_id);
                 if (table)
                   break;
   
                 iter->afi_safi_ix++;
               }
   
             /*
              * Found another table in this vrf.
              */
             if (table)
               break;
   
             /*
              * Done with all tables in the current vrf, go to the next
              * one.
              */
             if (!vrf_id_get_next (iter->vrf_id, &iter->vrf_id))
               break;
   
             iter->afi_safi_ix = 0;
           }
   
         break;
   
       case RIB_TABLES_ITER_S_DONE:
         return NULL;
       }
   
     if (table)
       iter->state = RIB_TABLES_ITER_S_ITERATING;
     else
       iter->state = RIB_TABLES_ITER_S_DONE;
   
     return table;
 }  }

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


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