Annotation of embedaddon/quagga/bgpd/bgp_table.c, revision 1.1

1.1     ! misho       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>