Diff for /embedaddon/quagga/zebra/zebra_rib.c between versions 1.1.1.2 and 1.1.1.3

version 1.1.1.2, 2012/10/09 09:22:29 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 74  static const struct Line 75  static const struct
 /* 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 87  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[AFI_IP][SAFI_MULTICAST] = route_table_init ();  vrf_table_create (vrf, AFI_IP, SAFI_MULTICAST);
  vrf->table[AFI_IP6][SAFI_MULTICAST] = route_table_init ();  vrf_table_create (vrf, AFI_IP6, SAFI_MULTICAST);
   vrf->stable[AFI_IP][SAFI_MULTICAST] = route_table_init ();    vrf->stable[AFI_IP][SAFI_MULTICAST] = route_table_init ();
   vrf->stable[AFI_IP6][SAFI_MULTICAST] = route_table_init ();    vrf->stable[AFI_IP6][SAFI_MULTICAST] = route_table_init ();
   
Line 133  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 146  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 351  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 452  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 543  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 601  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 658  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 678  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 688  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 725  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 915  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 942  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 966  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 975  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 993  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 1017  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 1074  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 1091  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 1132  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 1150  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 1171  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 1189  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 1223  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 1251  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 1264  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 1286  rib_queue_add (struct zebra_t *zebra, struct route_nod Line 1427  rib_queue_add (struct zebra_t *zebra, struct route_nod
     inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN);      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 */    /* Pointless to queue a route_node with no RIB entries to add or remove */
  if (!rn->info)  if (!rnode_to_ribs (rn))
     {      {
       zlog_debug ("%s: called for route_node (%p, %d) with no ribs",        zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
                   __func__, rn, rn->lock);                    __func__, rn, rn->lock);
Line 1395  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 1416  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 1429  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 1465  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 1480  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 1487  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 1506  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 1546  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)
     {      {
      if ((unsigned)type >= sizeof(route_info) / sizeof(route_info[0]))      if ((unsigned)type >= array_size(route_info))
         distance = 150;          distance = 150;
       else        else
         distance = route_info[type].distance;          distance = route_info[type].distance;
Line 1561  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 1717  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 1764  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 1816  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 1907  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 2000  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 2036  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 2095  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 2354  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 2457  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 2550  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 2647  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 2843  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 2864  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 2896  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 2932  rib_score_proto_table (u_char proto, struct route_tabl Line 3081  rib_score_proto_table (u_char proto, struct route_tabl
   
   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;
           if (rib->type == proto)            if (rib->type == proto)
Line 2964  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 2987  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.2  
changed lines
  Added in v.1.1.1.3


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