File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / bgpd / bgp_table.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:26:11 2012 UTC (12 years, 4 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_21, v0_99_20_1, v0_99_20, HEAD
quagga

    1: /* BGP routing table
    2:    Copyright (C) 1998, 2001 Kunihiro Ishiguro
    3: 
    4: This file is part of GNU Zebra.
    5: 
    6: GNU Zebra is free software; you can redistribute it and/or modify it
    7: under the terms of the GNU General Public License as published by the
    8: Free Software Foundation; either version 2, or (at your option) any
    9: later version.
   10: 
   11: GNU Zebra is distributed in the hope that it will be useful, but
   12: WITHOUT ANY WARRANTY; without even the implied warranty of
   13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14: General Public License for more details.
   15: 
   16: You should have received a copy of the GNU General Public License
   17: along with GNU Zebra; see the file COPYING.  If not, write to the Free
   18: Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   19: 02111-1307, USA.  */
   20: 
   21: #include <zebra.h>
   22: 
   23: #include "prefix.h"
   24: #include "memory.h"
   25: #include "sockunion.h"
   26: #include "vty.h"
   27: 
   28: #include "bgpd/bgpd.h"
   29: #include "bgpd/bgp_table.h"
   30: 
   31: static void bgp_node_delete (struct bgp_node *);
   32: static void bgp_table_free (struct bgp_table *);
   33: 
   34: struct bgp_table *
   35: bgp_table_init (afi_t afi, safi_t safi)
   36: {
   37:   struct bgp_table *rt;
   38: 
   39:   rt = XCALLOC (MTYPE_BGP_TABLE, sizeof (struct bgp_table));
   40: 
   41:   bgp_table_lock(rt);
   42:   rt->type = BGP_TABLE_MAIN;
   43:   rt->afi = afi;
   44:   rt->safi = safi;
   45:   
   46:   return rt;
   47: }
   48: 
   49: void
   50: bgp_table_lock (struct bgp_table *rt)
   51: {
   52:   rt->lock++;
   53: }
   54: 
   55: void
   56: bgp_table_unlock (struct bgp_table *rt)
   57: {
   58:   assert (rt->lock > 0);
   59:   rt->lock--;
   60: 
   61:   if (rt->lock == 0)
   62:     bgp_table_free (rt);
   63: }
   64: 
   65: void
   66: bgp_table_finish (struct bgp_table **rt)
   67: {
   68:   if (*rt != NULL)
   69:     {
   70:       bgp_table_unlock(*rt);
   71:       *rt = NULL;
   72:     }
   73: }
   74: 
   75: static struct bgp_node *
   76: bgp_node_create (void)
   77: {
   78:   return XCALLOC (MTYPE_BGP_NODE, sizeof (struct bgp_node));
   79: }
   80: 
   81: /* Allocate new route node with prefix set. */
   82: static struct bgp_node *
   83: bgp_node_set (struct bgp_table *table, struct prefix *prefix)
   84: {
   85:   struct bgp_node *node;
   86:   
   87:   node = bgp_node_create ();
   88: 
   89:   prefix_copy (&node->p, prefix);
   90:   node->table = table;
   91: 
   92:   return node;
   93: }
   94: 
   95: /* Free route node. */
   96: static void
   97: bgp_node_free (struct bgp_node *node)
   98: {
   99:   XFREE (MTYPE_BGP_NODE, node);
  100: }
  101: 
  102: /* Free route table. */
  103: static void
  104: bgp_table_free (struct bgp_table *rt)
  105: {
  106:   struct bgp_node *tmp_node;
  107:   struct bgp_node *node;
  108:  
  109:   if (rt == NULL)
  110:     return;
  111: 
  112:   node = rt->top;
  113: 
  114:   /* Bulk deletion of nodes remaining in this table.  This function is not
  115:      called until workers have completed their dependency on this table.
  116:      A final bgp_unlock_node() will not be called for these nodes. */
  117:   while (node)
  118:     {
  119:       if (node->l_left)
  120: 	{
  121: 	  node = node->l_left;
  122: 	  continue;
  123: 	}
  124: 
  125:       if (node->l_right)
  126: 	{
  127: 	  node = node->l_right;
  128: 	  continue;
  129: 	}
  130: 
  131:       tmp_node = node;
  132:       node = node->parent;
  133: 
  134:       tmp_node->table->count--;
  135:       tmp_node->lock = 0;  /* to cause assert if unlocked after this */
  136:       bgp_node_free (tmp_node);
  137: 
  138:       if (node != NULL)
  139: 	{
  140: 	  if (node->l_left == tmp_node)
  141: 	    node->l_left = NULL;
  142: 	  else
  143: 	    node->l_right = NULL;
  144: 	}
  145:       else
  146: 	{
  147: 	  break;
  148: 	}
  149:     }
  150:  
  151:   assert (rt->count == 0);
  152: 
  153:   if (rt->owner)
  154:     {
  155:       peer_unlock (rt->owner);
  156:       rt->owner = NULL;
  157:     }
  158: 
  159:   XFREE (MTYPE_BGP_TABLE, rt);
  160:   return;
  161: }
  162: 
  163: /* Utility mask array. */
  164: static u_char maskbit[] = 
  165: {
  166:   0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
  167: };
  168: 
  169: /* Common prefix route genaration. */
  170: static void
  171: route_common (struct prefix *n, struct prefix *p, struct prefix *new)
  172: {
  173:   int i;
  174:   u_char diff;
  175:   u_char mask;
  176: 
  177:   u_char *np = (u_char *)&n->u.prefix;
  178:   u_char *pp = (u_char *)&p->u.prefix;
  179:   u_char *newp = (u_char *)&new->u.prefix;
  180: 
  181:   for (i = 0; i < p->prefixlen / 8; i++)
  182:     {
  183:       if (np[i] == pp[i])
  184: 	newp[i] = np[i];
  185:       else
  186: 	break;
  187:     }
  188: 
  189:   new->prefixlen = i * 8;
  190: 
  191:   if (new->prefixlen != p->prefixlen)
  192:     {
  193:       diff = np[i] ^ pp[i];
  194:       mask = 0x80;
  195:       while (new->prefixlen < p->prefixlen && !(mask & diff))
  196: 	{
  197: 	  mask >>= 1;
  198: 	  new->prefixlen++;
  199: 	}
  200:       newp[i] = np[i] & maskbit[new->prefixlen % 8];
  201:     }
  202: }
  203: 
  204: static void
  205: set_link (struct bgp_node *node, struct bgp_node *new)
  206: {
  207:   unsigned int bit = prefix_bit (&new->p.u.prefix, node->p.prefixlen);
  208: 
  209:   node->link[bit] = new;
  210:   new->parent = node;
  211: }
  212: 
  213: /* Lock node. */
  214: struct bgp_node *
  215: bgp_lock_node (struct bgp_node *node)
  216: {
  217:   node->lock++;
  218:   return node;
  219: }
  220: 
  221: /* Unlock node. */
  222: void
  223: bgp_unlock_node (struct bgp_node *node)
  224: {
  225:   assert (node->lock > 0);
  226:   node->lock--;
  227: 
  228:   if (node->lock == 0)
  229:     bgp_node_delete (node);
  230: }
  231: 
  232: /* Find matched prefix. */
  233: struct bgp_node *
  234: bgp_node_match (const struct bgp_table *table, struct prefix *p)
  235: {
  236:   struct bgp_node *node;
  237:   struct bgp_node *matched;
  238: 
  239:   matched = NULL;
  240:   node = table->top;
  241: 
  242:   /* Walk down tree.  If there is matched route then store it to
  243:      matched. */
  244:   while (node && node->p.prefixlen <= p->prefixlen && 
  245: 	 prefix_match (&node->p, p))
  246:     {
  247:       if (node->info)
  248: 	matched = node;
  249:       node = node->link[prefix_bit(&p->u.prefix, node->p.prefixlen)];
  250:     }
  251: 
  252:   /* If matched route found, return it. */
  253:   if (matched)
  254:     return bgp_lock_node (matched);
  255: 
  256:   return NULL;
  257: }
  258: 
  259: struct bgp_node *
  260: bgp_node_match_ipv4 (const struct bgp_table *table, struct in_addr *addr)
  261: {
  262:   struct prefix_ipv4 p;
  263: 
  264:   memset (&p, 0, sizeof (struct prefix_ipv4));
  265:   p.family = AF_INET;
  266:   p.prefixlen = IPV4_MAX_PREFIXLEN;
  267:   p.prefix = *addr;
  268: 
  269:   return bgp_node_match (table, (struct prefix *) &p);
  270: }
  271: 
  272: #ifdef HAVE_IPV6
  273: struct bgp_node *
  274: bgp_node_match_ipv6 (const struct bgp_table *table, struct in6_addr *addr)
  275: {
  276:   struct prefix_ipv6 p;
  277: 
  278:   memset (&p, 0, sizeof (struct prefix_ipv6));
  279:   p.family = AF_INET6;
  280:   p.prefixlen = IPV6_MAX_PREFIXLEN;
  281:   p.prefix = *addr;
  282: 
  283:   return bgp_node_match (table, (struct prefix *) &p);
  284: }
  285: #endif /* HAVE_IPV6 */
  286: 
  287: /* Lookup same prefix node.  Return NULL when we can't find route. */
  288: struct bgp_node *
  289: bgp_node_lookup (const struct bgp_table *table, struct prefix *p)
  290: {
  291:   struct bgp_node *node;
  292: 
  293:   node = table->top;
  294: 
  295:   while (node && node->p.prefixlen <= p->prefixlen && 
  296: 	 prefix_match (&node->p, p))
  297:     {
  298:       if (node->p.prefixlen == p->prefixlen && node->info)
  299: 	return bgp_lock_node (node);
  300: 
  301:       node = node->link[prefix_bit(&p->u.prefix, node->p.prefixlen)];
  302:     }
  303: 
  304:   return NULL;
  305: }
  306: 
  307: /* Add node to routing table. */
  308: struct bgp_node *
  309: bgp_node_get (struct bgp_table *const table, struct prefix *p)
  310: {
  311:   struct bgp_node *new;
  312:   struct bgp_node *node;
  313:   struct bgp_node *match;
  314: 
  315:   match = NULL;
  316:   node = table->top;
  317:   while (node && node->p.prefixlen <= p->prefixlen && 
  318: 	 prefix_match (&node->p, p))
  319:     {
  320:       if (node->p.prefixlen == p->prefixlen)
  321: 	{
  322: 	  bgp_lock_node (node);
  323: 	  return node;
  324: 	}
  325:       match = node;
  326:       node = node->link[prefix_bit(&p->u.prefix, node->p.prefixlen)];
  327:     }
  328: 
  329:   if (node == NULL)
  330:     {
  331:       new = bgp_node_set (table, p);
  332:       if (match)
  333: 	set_link (match, new);
  334:       else
  335: 	table->top = new;
  336:     }
  337:   else
  338:     {
  339:       new = bgp_node_create ();
  340:       route_common (&node->p, p, &new->p);
  341:       new->p.family = p->family;
  342:       new->table = table;
  343:       set_link (new, node);
  344: 
  345:       if (match)
  346: 	set_link (match, new);
  347:       else
  348: 	table->top = new;
  349: 
  350:       if (new->p.prefixlen != p->prefixlen)
  351: 	{
  352: 	  match = new;
  353: 	  new = bgp_node_set (table, p);
  354: 	  set_link (match, new);
  355: 	  table->count++;
  356: 	}
  357:     }
  358:   table->count++;
  359:   bgp_lock_node (new);
  360:   
  361:   return new;
  362: }
  363: 
  364: /* Delete node from the routing table. */
  365: static void
  366: bgp_node_delete (struct bgp_node *node)
  367: {
  368:   struct bgp_node *child;
  369:   struct bgp_node *parent;
  370: 
  371:   assert (node->lock == 0);
  372:   assert (node->info == NULL);
  373: 
  374:   if (node->l_left && node->l_right)
  375:     return;
  376: 
  377:   if (node->l_left)
  378:     child = node->l_left;
  379:   else
  380:     child = node->l_right;
  381: 
  382:   parent = node->parent;
  383: 
  384:   if (child)
  385:     child->parent = parent;
  386: 
  387:   if (parent)
  388:     {
  389:       if (parent->l_left == node)
  390: 	parent->l_left = child;
  391:       else
  392: 	parent->l_right = child;
  393:     }
  394:   else
  395:     node->table->top = child;
  396:   
  397:   node->table->count--;
  398:   
  399:   bgp_node_free (node);
  400: 
  401:   /* If parent node is stub then delete it also. */
  402:   if (parent && parent->lock == 0)
  403:     bgp_node_delete (parent);
  404: }
  405: 
  406: /* Get fist node and lock it.  This function is useful when one want
  407:    to lookup all the node exist in the routing table. */
  408: struct bgp_node *
  409: bgp_table_top (const struct bgp_table *const table)
  410: {
  411:   /* If there is no node in the routing table return NULL. */
  412:   if (table->top == NULL)
  413:     return NULL;
  414: 
  415:   /* Lock the top node and return it. */
  416:   bgp_lock_node (table->top);
  417:   return table->top;
  418: }
  419: 
  420: /* Unlock current node and lock next node then return it. */
  421: struct bgp_node *
  422: bgp_route_next (struct bgp_node *node)
  423: {
  424:   struct bgp_node *next;
  425:   struct bgp_node *start;
  426: 
  427:   /* Node may be deleted from bgp_unlock_node so we have to preserve
  428:      next node's pointer. */
  429: 
  430:   if (node->l_left)
  431:     {
  432:       next = node->l_left;
  433:       bgp_lock_node (next);
  434:       bgp_unlock_node (node);
  435:       return next;
  436:     }
  437:   if (node->l_right)
  438:     {
  439:       next = node->l_right;
  440:       bgp_lock_node (next);
  441:       bgp_unlock_node (node);
  442:       return next;
  443:     }
  444: 
  445:   start = node;
  446:   while (node->parent)
  447:     {
  448:       if (node->parent->l_left == node && node->parent->l_right)
  449: 	{
  450: 	  next = node->parent->l_right;
  451: 	  bgp_lock_node (next);
  452: 	  bgp_unlock_node (start);
  453: 	  return next;
  454: 	}
  455:       node = node->parent;
  456:     }
  457:   bgp_unlock_node (start);
  458:   return NULL;
  459: }
  460: 
  461: /* Unlock current node and lock next node until limit. */
  462: struct bgp_node *
  463: bgp_route_next_until (struct bgp_node *node, struct bgp_node *limit)
  464: {
  465:   struct bgp_node *next;
  466:   struct bgp_node *start;
  467: 
  468:   /* Node may be deleted from bgp_unlock_node so we have to preserve
  469:      next node's pointer. */
  470: 
  471:   if (node->l_left)
  472:     {
  473:       next = node->l_left;
  474:       bgp_lock_node (next);
  475:       bgp_unlock_node (node);
  476:       return next;
  477:     }
  478:   if (node->l_right)
  479:     {
  480:       next = node->l_right;
  481:       bgp_lock_node (next);
  482:       bgp_unlock_node (node);
  483:       return next;
  484:     }
  485: 
  486:   start = node;
  487:   while (node->parent && node != limit)
  488:     {
  489:       if (node->parent->l_left == node && node->parent->l_right)
  490: 	{
  491: 	  next = node->parent->l_right;
  492: 	  bgp_lock_node (next);
  493: 	  bgp_unlock_node (start);
  494: 	  return next;
  495: 	}
  496:       node = node->parent;
  497:     }
  498:   bgp_unlock_node (start);
  499:   return NULL;
  500: }
  501: 
  502: unsigned long
  503: bgp_table_count (const struct bgp_table *table)
  504: {
  505:   return table->count;
  506: }

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