Annotation of embedaddon/quagga/bgpd/bgp_table.c, revision 1.1.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>