Diff for /embedaddon/quagga/bgpd/bgp_table.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, 2016/11/02 10:09:10
Line 24  Software Foundation, Inc., 59 Temple Place - Suite 330 Line 24  Software Foundation, Inc., 59 Temple Place - Suite 330
 #include "memory.h"  #include "memory.h"
 #include "sockunion.h"  #include "sockunion.h"
 #include "vty.h"  #include "vty.h"
   #include "filter.h"
   
 #include "bgpd/bgpd.h"  #include "bgpd/bgpd.h"
 #include "bgpd/bgp_table.h"  #include "bgpd/bgp_table.h"
   
 static void bgp_node_delete (struct bgp_node *);  
 static void bgp_table_free (struct bgp_table *);  
   
 struct bgp_table *  
 bgp_table_init (afi_t afi, safi_t safi)  
 {  
   struct bgp_table *rt;  
   
   rt = XCALLOC (MTYPE_BGP_TABLE, sizeof (struct bgp_table));  
   
   bgp_table_lock(rt);  
   rt->type = BGP_TABLE_MAIN;  
   rt->afi = afi;  
   rt->safi = safi;  
     
   return rt;  
 }  
   
 void  void
 bgp_table_lock (struct bgp_table *rt)  bgp_table_lock (struct bgp_table *rt)
 {  {
Line 58  bgp_table_unlock (struct bgp_table *rt) Line 41  bgp_table_unlock (struct bgp_table *rt)
   assert (rt->lock > 0);    assert (rt->lock > 0);
   rt->lock--;    rt->lock--;
   
  if (rt->lock == 0)  if (rt->lock != 0) 
    bgp_table_free (rt); 
} 
 
void 
bgp_table_finish (struct bgp_table **rt) 
{ 
  if (*rt != NULL) 
     {      {
      bgp_table_unlock(*rt);      return;
      *rt = NULL; 
     }      }
 }  
   
static struct bgp_node *  route_table_finish (rt->route_table);
bgp_node_create (void)  rt->route_table = NULL;
{ 
  return XCALLOC (MTYPE_BGP_NODE, sizeof (struct bgp_node)); 
} 
   
 /* Allocate new route node with prefix set. */  
 static struct bgp_node *  
 bgp_node_set (struct bgp_table *table, struct prefix *prefix)  
 {  
   struct bgp_node *node;  
     
   node = bgp_node_create ();  
   
   prefix_copy (&node->p, prefix);  
   node->table = table;  
   
   return node;  
 }  
   
 /* Free route node. */  
 static void  
 bgp_node_free (struct bgp_node *node)  
 {  
   XFREE (MTYPE_BGP_NODE, node);  
 }  
   
 /* Free route table. */  
 static void  
 bgp_table_free (struct bgp_table *rt)  
 {  
   struct bgp_node *tmp_node;  
   struct bgp_node *node;  
    
   if (rt == NULL)  
     return;  
   
   node = rt->top;  
   
   /* Bulk deletion of nodes remaining in this table.  This function is not  
      called until workers have completed their dependency on this table.  
      A final bgp_unlock_node() will not be called for these nodes. */  
   while (node)  
     {  
       if (node->l_left)  
         {  
           node = node->l_left;  
           continue;  
         }  
   
       if (node->l_right)  
         {  
           node = node->l_right;  
           continue;  
         }  
   
       tmp_node = node;  
       node = node->parent;  
   
       tmp_node->table->count--;  
       tmp_node->lock = 0;  /* to cause assert if unlocked after this */  
       bgp_node_free (tmp_node);  
   
       if (node != NULL)  
         {  
           if (node->l_left == tmp_node)  
             node->l_left = NULL;  
           else  
             node->l_right = NULL;  
         }  
       else  
         {  
           break;  
         }  
     }  
    
   assert (rt->count == 0);  
   
   if (rt->owner)    if (rt->owner)
     {      {
       peer_unlock (rt->owner);        peer_unlock (rt->owner);
Line 157  bgp_table_free (struct bgp_table *rt) Line 56  bgp_table_free (struct bgp_table *rt)
     }      }
   
   XFREE (MTYPE_BGP_TABLE, rt);    XFREE (MTYPE_BGP_TABLE, rt);
   return;  
 }  }
   
 /* Utility mask array. */  
 static u_char maskbit[] =   
 {  
   0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff  
 };  
   
 /* Common prefix route genaration. */  
 static void  
 route_common (struct prefix *n, struct prefix *p, struct prefix *new)  
 {  
   int i;  
   u_char diff;  
   u_char mask;  
   
   u_char *np = (u_char *)&n->u.prefix;  
   u_char *pp = (u_char *)&p->u.prefix;  
   u_char *newp = (u_char *)&new->u.prefix;  
   
   for (i = 0; i < p->prefixlen / 8; i++)  
     {  
       if (np[i] == pp[i])  
         newp[i] = np[i];  
       else  
         break;  
     }  
   
   new->prefixlen = i * 8;  
   
   if (new->prefixlen != p->prefixlen)  
     {  
       diff = np[i] ^ pp[i];  
       mask = 0x80;  
       while (new->prefixlen < p->prefixlen && !(mask & diff))  
         {  
           mask >>= 1;  
           new->prefixlen++;  
         }  
       newp[i] = np[i] & maskbit[new->prefixlen % 8];  
     }  
 }  
   
 static void  
 set_link (struct bgp_node *node, struct bgp_node *new)  
 {  
   unsigned int bit = prefix_bit (&new->p.u.prefix, node->p.prefixlen);  
   
   node->link[bit] = new;  
   new->parent = node;  
 }  
   
 /* Lock node. */  
 struct bgp_node *  
 bgp_lock_node (struct bgp_node *node)  
 {  
   node->lock++;  
   return node;  
 }  
   
 /* Unlock node. */  
 void  void
bgp_unlock_node (struct bgp_node *node)bgp_table_finish (struct bgp_table **rt)
 {  {
  assert (node->lock > 0);  if (*rt != NULL)
  node->lock--; 
 
  if (node->lock == 0) 
    bgp_node_delete (node); 
} 
 
/* Find matched prefix. */ 
struct bgp_node * 
bgp_node_match (const struct bgp_table *table, struct prefix *p) 
{ 
  struct bgp_node *node; 
  struct bgp_node *matched; 
 
  matched = NULL; 
  node = table->top; 
 
  /* Walk down tree.  If there is matched route then store it to 
     matched. */ 
  while (node && node->p.prefixlen <= p->prefixlen &&  
         prefix_match (&node->p, p)) 
     {      {
      if (node->info)      bgp_table_unlock(*rt);
        matched = node;      *rt = NULL;
      node = node->link[prefix_bit(&p->u.prefix, node->p.prefixlen)]; 
     }      }
   
   /* If matched route found, return it. */  
   if (matched)  
     return bgp_lock_node (matched);  
   
   return NULL;  
 }  }
   
struct bgp_node */*
bgp_node_match_ipv4 (const struct bgp_table *table, struct in_addr *addr) * bgp_node_create
  */
 static struct route_node *
 bgp_node_create (route_table_delegate_t *delegate, struct route_table *table)
 {  {
   struct prefix_ipv4 p;  
   
   memset (&p, 0, sizeof (struct prefix_ipv4));  
   p.family = AF_INET;  
   p.prefixlen = IPV4_MAX_PREFIXLEN;  
   p.prefix = *addr;  
   
   return bgp_node_match (table, (struct prefix *) &p);  
 }  
   
 #ifdef HAVE_IPV6  
 struct bgp_node *  
 bgp_node_match_ipv6 (const struct bgp_table *table, struct in6_addr *addr)  
 {  
   struct prefix_ipv6 p;  
   
   memset (&p, 0, sizeof (struct prefix_ipv6));  
   p.family = AF_INET6;  
   p.prefixlen = IPV6_MAX_PREFIXLEN;  
   p.prefix = *addr;  
   
   return bgp_node_match (table, (struct prefix *) &p);  
 }  
 #endif /* HAVE_IPV6 */  
   
 /* Lookup same prefix node.  Return NULL when we can't find route. */  
 struct bgp_node *  
 bgp_node_lookup (const struct bgp_table *table, struct prefix *p)  
 {  
   struct bgp_node *node;    struct bgp_node *node;
  node = XCALLOC (MTYPE_BGP_NODE, sizeof (struct bgp_node));
  node = table->top;  return bgp_node_to_rnode (node);
 
  while (node && node->p.prefixlen <= p->prefixlen &&  
         prefix_match (&node->p, p)) 
    { 
      if (node->p.prefixlen == p->prefixlen && node->info) 
        return bgp_lock_node (node); 
 
      node = node->link[prefix_bit(&p->u.prefix, node->p.prefixlen)]; 
    } 
 
  return NULL; 
 }  }
   
/* Add node to routing table. *//*
struct bgp_node * * bgp_node_destroy
bgp_node_get (struct bgp_table *const table, struct prefix *p) */
{ 
  struct bgp_node *new; 
  struct bgp_node *node; 
  struct bgp_node *match; 
 
  match = NULL; 
  node = table->top; 
  while (node && node->p.prefixlen <= p->prefixlen &&  
         prefix_match (&node->p, p)) 
    { 
      if (node->p.prefixlen == p->prefixlen) 
        { 
          bgp_lock_node (node); 
          return node; 
        } 
      match = node; 
      node = node->link[prefix_bit(&p->u.prefix, node->p.prefixlen)]; 
    } 
 
  if (node == NULL) 
    { 
      new = bgp_node_set (table, p); 
      if (match) 
        set_link (match, new); 
      else 
        table->top = new; 
    } 
  else 
    { 
      new = bgp_node_create (); 
      route_common (&node->p, p, &new->p); 
      new->p.family = p->family; 
      new->table = table; 
      set_link (new, node); 
 
      if (match) 
        set_link (match, new); 
      else 
        table->top = new; 
 
      if (new->p.prefixlen != p->prefixlen) 
        { 
          match = new; 
          new = bgp_node_set (table, p); 
          set_link (match, new); 
          table->count++; 
        } 
    } 
  table->count++; 
  bgp_lock_node (new); 
   
  return new; 
} 
 
/* Delete node from the routing table. */ 
 static void  static void
bgp_node_delete (struct bgp_node *node)bgp_node_destroy (route_table_delegate_t *delegate,
                   struct route_table *table, struct route_node *node)
 {  {
  struct bgp_node *child;  struct bgp_node *bgp_node;
  struct bgp_node *parent;  bgp_node = bgp_node_from_rnode (node);
  XFREE (MTYPE_BGP_NODE, bgp_node);
  assert (node->lock == 0); 
  assert (node->info == NULL); 
 
  if (node->l_left && node->l_right) 
    return; 
 
  if (node->l_left) 
    child = node->l_left; 
  else 
    child = node->l_right; 
 
  parent = node->parent; 
 
  if (child) 
    child->parent = parent; 
 
  if (parent) 
    { 
      if (parent->l_left == node) 
        parent->l_left = child; 
      else 
        parent->l_right = child; 
    } 
  else 
    node->table->top = child; 
   
  node->table->count--; 
   
  bgp_node_free (node); 
 
  /* If parent node is stub then delete it also. */ 
  if (parent && parent->lock == 0) 
    bgp_node_delete (parent); 
 }  }
   
/* Get fist node and lock it.  This function is useful when one want/*
   to lookup all the node exist in the routing table. */ * Function vector to customize the behavior of the route table
struct bgp_node * * library for BGP route tables.
bgp_table_top (const struct bgp_table *const table) */
{route_table_delegate_t bgp_table_delegate = {
  /* If there is no node in the routing table return NULL. */  .create_node = bgp_node_create,
  if (table->top == NULL)  .destroy_node = bgp_node_destroy
    return NULL;};
   
  /* Lock the top node and return it. *//*
  bgp_lock_node (table->top); * bgp_table_init
  return table->top; */
}struct bgp_table *
bgp_table_init (afi_t afi, safi_t safi)
/* Unlock current node and lock next node then return it. */ 
struct bgp_node * 
bgp_route_next (struct bgp_node *node) 
 {  {
  struct bgp_node *next;  struct bgp_table *rt;
  struct bgp_node *start; 
   
  /* Node may be deleted from bgp_unlock_node so we have to preserve  rt = XCALLOC (MTYPE_BGP_TABLE, sizeof (struct bgp_table));
     next node's pointer. */ 
   
  if (node->l_left)  rt->route_table = route_table_init_with_delegate (&bgp_table_delegate);
    { 
      next = node->l_left; 
      bgp_lock_node (next); 
      bgp_unlock_node (node); 
      return next; 
    } 
  if (node->l_right) 
    { 
      next = node->l_right; 
      bgp_lock_node (next); 
      bgp_unlock_node (node); 
      return next; 
    } 
   
  start = node;  /*
  while (node->parent)   * Set up back pointer to bgp_table.
    {   */
      if (node->parent->l_left == node && node->parent->l_right)  rt->route_table->info = rt;
        { 
          next = node->parent->l_right; 
          bgp_lock_node (next); 
          bgp_unlock_node (start); 
          return next; 
        } 
      node = node->parent; 
    } 
  bgp_unlock_node (start); 
  return NULL; 
} 
   
/* Unlock current node and lock next node until limit. */  bgp_table_lock (rt);
struct bgp_node *  rt->type = BGP_TABLE_MAIN;
bgp_route_next_until (struct bgp_node *node, struct bgp_node *limit)  rt->afi = afi;
{  rt->safi = safi;
  struct bgp_node *next; 
  struct bgp_node *start; 
   
  /* Node may be deleted from bgp_unlock_node so we have to preserve  return rt;
     next node's pointer. */ 
 
  if (node->l_left) 
    { 
      next = node->l_left; 
      bgp_lock_node (next); 
      bgp_unlock_node (node); 
      return next; 
    } 
  if (node->l_right) 
    { 
      next = node->l_right; 
      bgp_lock_node (next); 
      bgp_unlock_node (node); 
      return next; 
    } 
 
  start = node; 
  while (node->parent && node != limit) 
    { 
      if (node->parent->l_left == node && node->parent->l_right) 
        { 
          next = node->parent->l_right; 
          bgp_lock_node (next); 
          bgp_unlock_node (start); 
          return next; 
        } 
      node = node->parent; 
    } 
  bgp_unlock_node (start); 
  return NULL; 
} 
 
unsigned long 
bgp_table_count (const struct bgp_table *table) 
{ 
  return table->count; 
 }  }

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


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