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

    1: /*
    2:  * Copyright (C) 2003 Yasuhiro Ohara
    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 
   18:  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 
   19:  * Boston, MA 02111-1307, USA.  
   20:  */
   21: 
   22: #include <zebra.h>
   23: 
   24: #include "memory.h"
   25: #include "log.h"
   26: #include "command.h"
   27: #include "prefix.h"
   28: #include "table.h"
   29: #include "vty.h"
   30: 
   31: #include "ospf6_proto.h"
   32: #include "ospf6_lsa.h"
   33: #include "ospf6_lsdb.h"
   34: #include "ospf6d.h"
   35: 
   36: struct ospf6_lsdb *
   37: ospf6_lsdb_create (void *data)
   38: {
   39:   struct ospf6_lsdb *lsdb;
   40: 
   41:   lsdb = XCALLOC (MTYPE_OSPF6_LSDB, sizeof (struct ospf6_lsdb));
   42:   if (lsdb == NULL)
   43:     {
   44:       zlog_warn ("Can't malloc lsdb");
   45:       return NULL;
   46:     }
   47:   memset (lsdb, 0, sizeof (struct ospf6_lsdb));
   48: 
   49:   lsdb->data = data;
   50:   lsdb->table = route_table_init ();
   51:   return lsdb;
   52: }
   53: 
   54: void
   55: ospf6_lsdb_delete (struct ospf6_lsdb *lsdb)
   56: {
   57:   ospf6_lsdb_remove_all (lsdb);
   58:   route_table_finish (lsdb->table);
   59:   XFREE (MTYPE_OSPF6_LSDB, lsdb);
   60: }
   61: 
   62: static void
   63: ospf6_lsdb_set_key (struct prefix_ipv6 *key, void *value, int len)
   64: {
   65:   assert (key->prefixlen % 8 == 0);
   66: 
   67:   memcpy ((caddr_t) &key->prefix + key->prefixlen / 8,
   68:           (caddr_t) value, len);
   69:   key->family = AF_INET6;
   70:   key->prefixlen += len * 8;
   71: }
   72: 
   73: #ifndef NDEBUG
   74: static void
   75: _lsdb_count_assert (struct ospf6_lsdb *lsdb)
   76: {
   77:   struct ospf6_lsa *debug;
   78:   unsigned int num = 0;
   79:   for (debug = ospf6_lsdb_head (lsdb); debug;
   80:        debug = ospf6_lsdb_next (debug))
   81:     num++;
   82: 
   83:   if (num == lsdb->count)
   84:     return;
   85: 
   86:   zlog_debug ("PANIC !! lsdb[%p]->count = %d, real = %d",
   87:              lsdb, lsdb->count, num);
   88:   for (debug = ospf6_lsdb_head (lsdb); debug;
   89:        debug = ospf6_lsdb_next (debug))
   90:     zlog_debug ("%p %p %s lsdb[%p]", debug->prev, debug->next, debug->name,
   91:                debug->lsdb);
   92:   zlog_debug ("DUMP END");
   93: 
   94:   assert (num == lsdb->count);
   95: }
   96: #define ospf6_lsdb_count_assert(t) (_lsdb_count_assert (t))
   97: #else /*NDEBUG*/
   98: #define ospf6_lsdb_count_assert(t) ((void) 0)
   99: #endif /*NDEBUG*/
  100: 
  101: void
  102: ospf6_lsdb_add (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
  103: {
  104:   struct prefix_ipv6 key;
  105:   struct route_node *current, *nextnode, *prevnode;
  106:   struct ospf6_lsa *next, *prev, *old = NULL;
  107: 
  108:   memset (&key, 0, sizeof (key));
  109:   ospf6_lsdb_set_key (&key, &lsa->header->type, sizeof (lsa->header->type));
  110:   ospf6_lsdb_set_key (&key, &lsa->header->adv_router,
  111:                       sizeof (lsa->header->adv_router));
  112:   ospf6_lsdb_set_key (&key, &lsa->header->id, sizeof (lsa->header->id));
  113: 
  114:   current = route_node_get (lsdb->table, (struct prefix *) &key);
  115:   old = current->info;
  116:   current->info = lsa;
  117:   ospf6_lsa_lock (lsa);
  118: 
  119:   if (old)
  120:     {
  121:       if (old->prev)
  122:         old->prev->next = lsa;
  123:       if (old->next)
  124:         old->next->prev = lsa;
  125:       lsa->next = old->next;
  126:       lsa->prev = old->prev;
  127:     }
  128:   else
  129:     {
  130:       /* next link */
  131:       nextnode = current;
  132:       route_lock_node (nextnode);
  133:       do {
  134:         nextnode = route_next (nextnode);
  135:       } while (nextnode && nextnode->info == NULL);
  136:       if (nextnode == NULL)
  137:         lsa->next = NULL;
  138:       else
  139:         {
  140:           next = nextnode->info;
  141:           lsa->next = next;
  142:           next->prev = lsa;
  143:           route_unlock_node (nextnode);
  144:         }
  145: 
  146:       /* prev link */
  147:       prevnode = current;
  148:       route_lock_node (prevnode);
  149:       do {
  150:         prevnode = route_prev (prevnode);
  151:       } while (prevnode && prevnode->info == NULL);
  152:       if (prevnode == NULL)
  153:         lsa->prev = NULL;
  154:       else
  155:         {
  156:           prev = prevnode->info;
  157:           lsa->prev = prev;
  158:           prev->next = lsa;
  159:           route_unlock_node (prevnode);
  160:         }
  161: 
  162:       lsdb->count++;
  163:     }
  164: 
  165:   if (old)
  166:     {
  167:       if (OSPF6_LSA_IS_CHANGED (old, lsa))
  168:         {
  169:           if (OSPF6_LSA_IS_MAXAGE (lsa))
  170:             {
  171:               if (lsdb->hook_remove)
  172:                 {
  173:                   (*lsdb->hook_remove) (old);
  174:                   (*lsdb->hook_remove) (lsa);
  175:                 }
  176:             }
  177:           else if (OSPF6_LSA_IS_MAXAGE (old))
  178:             {
  179:               if (lsdb->hook_add)
  180:                 (*lsdb->hook_add) (lsa);
  181:             }
  182:           else
  183:             {
  184:               if (lsdb->hook_remove)
  185:                 (*lsdb->hook_remove) (old);
  186:               if (lsdb->hook_add)
  187:                 (*lsdb->hook_add) (lsa);
  188:             }
  189:         }
  190:     }
  191:   else if (OSPF6_LSA_IS_MAXAGE (lsa))
  192:     {
  193:       if (lsdb->hook_remove)
  194:         (*lsdb->hook_remove) (lsa);
  195:     }
  196:   else
  197:     {
  198:       if (lsdb->hook_add)
  199:         (*lsdb->hook_add) (lsa);
  200:     }
  201: 
  202:   if (old)
  203:     ospf6_lsa_unlock (old);
  204: 
  205:   ospf6_lsdb_count_assert (lsdb);
  206: }
  207: 
  208: void
  209: ospf6_lsdb_remove (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
  210: {
  211:   struct route_node *node;
  212:   struct prefix_ipv6 key;
  213: 
  214:   memset (&key, 0, sizeof (key));
  215:   ospf6_lsdb_set_key (&key, &lsa->header->type, sizeof (lsa->header->type));
  216:   ospf6_lsdb_set_key (&key, &lsa->header->adv_router,
  217:                       sizeof (lsa->header->adv_router));
  218:   ospf6_lsdb_set_key (&key, &lsa->header->id, sizeof (lsa->header->id));
  219: 
  220:   node = route_node_lookup (lsdb->table, (struct prefix *) &key);
  221:   assert (node && node->info == lsa);
  222: 
  223:   if (lsa->prev)
  224:     lsa->prev->next = lsa->next;
  225:   if (lsa->next)
  226:     lsa->next->prev = lsa->prev;
  227: 
  228:   node->info = NULL;
  229:   lsdb->count--;
  230: 
  231:   if (lsdb->hook_remove)
  232:     (*lsdb->hook_remove) (lsa);
  233: 
  234:   ospf6_lsa_unlock (lsa);
  235:   route_unlock_node (node);
  236: 
  237:   ospf6_lsdb_count_assert (lsdb);
  238: }
  239: 
  240: struct ospf6_lsa *
  241: ospf6_lsdb_lookup (u_int16_t type, u_int32_t id, u_int32_t adv_router,
  242:                    struct ospf6_lsdb *lsdb)
  243: {
  244:   struct route_node *node;
  245:   struct prefix_ipv6 key;
  246: 
  247:   if (lsdb == NULL)
  248:     return NULL;
  249: 
  250:   memset (&key, 0, sizeof (key));
  251:   ospf6_lsdb_set_key (&key, &type, sizeof (type));
  252:   ospf6_lsdb_set_key (&key, &adv_router, sizeof (adv_router));
  253:   ospf6_lsdb_set_key (&key, &id, sizeof (id));
  254: 
  255:   node = route_node_lookup (lsdb->table, (struct prefix *) &key);
  256:   if (node == NULL || node->info == NULL)
  257:     return NULL;
  258:   return (struct ospf6_lsa *) node->info;
  259: }
  260: 
  261: struct ospf6_lsa *
  262: ospf6_lsdb_lookup_next (u_int16_t type, u_int32_t id, u_int32_t adv_router,
  263:                         struct ospf6_lsdb *lsdb)
  264: {
  265:   struct route_node *node;
  266:   struct route_node *matched = NULL;
  267:   struct prefix_ipv6 key;
  268:   struct prefix *p;
  269: 
  270:   if (lsdb == NULL)
  271:     return NULL;
  272: 
  273:   memset (&key, 0, sizeof (key));
  274:   ospf6_lsdb_set_key (&key, &type, sizeof (type));
  275:   ospf6_lsdb_set_key (&key, &adv_router, sizeof (adv_router));
  276:   ospf6_lsdb_set_key (&key, &id, sizeof (id));
  277:   p = (struct prefix *) &key;
  278: 
  279:   {
  280:     char buf[64];
  281:     prefix2str (p, buf, sizeof (buf));
  282:     zlog_debug ("lsdb_lookup_next: key: %s", buf);
  283:   }
  284: 
  285:   node = lsdb->table->top;
  286:   /* walk down tree. */
  287:   while (node && node->p.prefixlen <= p->prefixlen &&
  288:          prefix_match (&node->p, p))
  289:     {
  290:       matched = node;
  291:       node = node->link[prefix_bit(&p->u.prefix, node->p.prefixlen)];
  292:     }
  293: 
  294:   if (matched)
  295:     node = matched;
  296:   else
  297:     node = lsdb->table->top;
  298:   route_lock_node (node);
  299: 
  300:   /* skip to real existing entry */
  301:   while (node && node->info == NULL)
  302:     node = route_next (node);
  303: 
  304:   if (! node)
  305:     return NULL;
  306: 
  307:   if (prefix_same (&node->p, p))
  308:     {
  309:       struct route_node *prev = node;
  310:       struct ospf6_lsa *lsa_prev;
  311:       struct ospf6_lsa *lsa_next;
  312: 
  313:       node = route_next (node);
  314:       while (node && node->info == NULL)
  315:         node = route_next (node);
  316: 
  317:       lsa_prev = prev->info;
  318:       lsa_next = (node ? node->info : NULL);
  319:       assert (lsa_prev);
  320:       assert (lsa_prev->next == lsa_next);
  321:       if (lsa_next)
  322:         assert (lsa_next->prev == lsa_prev);
  323:       zlog_debug ("lsdb_lookup_next: assert OK with previous LSA");
  324:     }
  325: 
  326:   if (! node)
  327:     return NULL;
  328: 
  329:   route_unlock_node (node);
  330:   return (struct ospf6_lsa *) node->info;
  331: }
  332: 
  333: /* Iteration function */
  334: struct ospf6_lsa *
  335: ospf6_lsdb_head (struct ospf6_lsdb *lsdb)
  336: {
  337:   struct route_node *node;
  338: 
  339:   node = route_top (lsdb->table);
  340:   if (node == NULL)
  341:     return NULL;
  342: 
  343:   /* skip to the existing lsdb entry */
  344:   while (node && node->info == NULL)
  345:     node = route_next (node);
  346:   if (node == NULL)
  347:     return NULL;
  348: 
  349:   route_unlock_node (node);
  350:   if (node->info)
  351:     ospf6_lsa_lock ((struct ospf6_lsa *) node->info);
  352:   return (struct ospf6_lsa *) node->info;
  353: }
  354: 
  355: struct ospf6_lsa *
  356: ospf6_lsdb_next (struct ospf6_lsa *lsa)
  357: {
  358:   struct ospf6_lsa *next = lsa->next;
  359: 
  360:   ospf6_lsa_unlock (lsa);
  361:   if (next)
  362:     ospf6_lsa_lock (next);
  363: 
  364:   return next;
  365: }
  366: 
  367: struct ospf6_lsa *
  368: ospf6_lsdb_type_router_head (u_int16_t type, u_int32_t adv_router,
  369:                              struct ospf6_lsdb *lsdb)
  370: {
  371:   struct route_node *node;
  372:   struct prefix_ipv6 key;
  373:   struct ospf6_lsa *lsa;
  374: 
  375:   memset (&key, 0, sizeof (key));
  376:   ospf6_lsdb_set_key (&key, &type, sizeof (type));
  377:   ospf6_lsdb_set_key (&key, &adv_router, sizeof (adv_router));
  378: 
  379:   node = lsdb->table->top;
  380: 
  381:   /* Walk down tree. */
  382:   while (node && node->p.prefixlen <= key.prefixlen &&
  383: 	 prefix_match (&node->p, (struct prefix *) &key))
  384:     node = node->link[prefix6_bit(&key.prefix, node->p.prefixlen)];
  385: 
  386:   if (node)
  387:     route_lock_node (node);
  388:   while (node && node->info == NULL)
  389:     node = route_next (node);
  390: 
  391:   if (node == NULL)
  392:     return NULL;
  393:   else
  394:     route_unlock_node (node);
  395: 
  396:   if (! prefix_match ((struct prefix *) &key, &node->p))
  397:     return NULL;
  398: 
  399:   lsa = node->info;
  400:   ospf6_lsa_lock (lsa);
  401: 
  402:   return lsa;
  403: }
  404: 
  405: struct ospf6_lsa *
  406: ospf6_lsdb_type_router_next (u_int16_t type, u_int32_t adv_router,
  407:                              struct ospf6_lsa *lsa)
  408: {
  409:   struct ospf6_lsa *next = lsa->next;
  410: 
  411:   if (next)
  412:     {
  413:       if (next->header->type != type ||
  414:           next->header->adv_router != adv_router)
  415:         next = NULL;
  416:     }
  417: 
  418:   if (next)
  419:     ospf6_lsa_lock (next);
  420:   ospf6_lsa_unlock (lsa);
  421:   return next;
  422: }
  423: 
  424: struct ospf6_lsa *
  425: ospf6_lsdb_type_head (u_int16_t type, struct ospf6_lsdb *lsdb)
  426: {
  427:   struct route_node *node;
  428:   struct prefix_ipv6 key;
  429:   struct ospf6_lsa *lsa;
  430: 
  431:   memset (&key, 0, sizeof (key));
  432:   ospf6_lsdb_set_key (&key, &type, sizeof (type));
  433: 
  434:   /* Walk down tree. */
  435:   node = lsdb->table->top;
  436:   while (node && node->p.prefixlen <= key.prefixlen &&
  437: 	 prefix_match (&node->p, (struct prefix *) &key))
  438:     node = node->link[prefix6_bit(&key.prefix, node->p.prefixlen)];
  439: 
  440:   if (node)
  441:     route_lock_node (node);
  442:   while (node && node->info == NULL)
  443:     node = route_next (node);
  444: 
  445:   if (node == NULL)
  446:     return NULL;
  447:   else
  448:     route_unlock_node (node);
  449: 
  450:   if (! prefix_match ((struct prefix *) &key, &node->p))
  451:     return NULL;
  452: 
  453:   lsa = node->info;
  454:   ospf6_lsa_lock (lsa);
  455: 
  456:   return lsa;
  457: }
  458: 
  459: struct ospf6_lsa *
  460: ospf6_lsdb_type_next (u_int16_t type, struct ospf6_lsa *lsa)
  461: {
  462:   struct ospf6_lsa *next = lsa->next;
  463: 
  464:   if (next)
  465:     {
  466:       if (next->header->type != type)
  467:         next = NULL;
  468:     }
  469: 
  470:   if (next)
  471:     ospf6_lsa_lock (next);
  472:   ospf6_lsa_unlock (lsa);
  473:   return next;
  474: }
  475: 
  476: void
  477: ospf6_lsdb_remove_all (struct ospf6_lsdb *lsdb)
  478: {
  479:   struct ospf6_lsa *lsa;
  480:   for (lsa = ospf6_lsdb_head (lsdb); lsa; lsa = ospf6_lsdb_next (lsa))
  481:     ospf6_lsdb_remove (lsa, lsdb);
  482: }
  483: 
  484: void
  485: ospf6_lsdb_show (struct vty *vty, int level,
  486:                  u_int16_t *type, u_int32_t *id, u_int32_t *adv_router,
  487:                  struct ospf6_lsdb *lsdb)
  488: {
  489:   struct ospf6_lsa *lsa;
  490:   void (*showfunc) (struct vty *, struct ospf6_lsa *) = NULL;
  491: 
  492:   if (level == OSPF6_LSDB_SHOW_LEVEL_NORMAL)
  493:     showfunc = ospf6_lsa_show_summary;
  494:   else if (level == OSPF6_LSDB_SHOW_LEVEL_DETAIL)
  495:     showfunc = ospf6_lsa_show;
  496:   else if (level == OSPF6_LSDB_SHOW_LEVEL_INTERNAL)
  497:     showfunc = ospf6_lsa_show_internal;
  498:   else if (level == OSPF6_LSDB_SHOW_LEVEL_DUMP)
  499:     showfunc = ospf6_lsa_show_dump;
  500: 
  501:   if (type && id && adv_router)
  502:     {
  503:       lsa = ospf6_lsdb_lookup (*type, *id, *adv_router, lsdb);
  504:       if (lsa)
  505:         {
  506:           if (level == OSPF6_LSDB_SHOW_LEVEL_NORMAL)
  507:             ospf6_lsa_show (vty, lsa);
  508:           else
  509:             (*showfunc) (vty, lsa);
  510:         }
  511:       return;
  512:     }
  513: 
  514:   if (level == OSPF6_LSDB_SHOW_LEVEL_NORMAL)
  515:     ospf6_lsa_show_summary_header (vty);
  516: 
  517:   if (type && adv_router)
  518:     lsa = ospf6_lsdb_type_router_head (*type, *adv_router, lsdb);
  519:   else if (type)
  520:     lsa = ospf6_lsdb_type_head (*type, lsdb);
  521:   else
  522:     lsa = ospf6_lsdb_head (lsdb);
  523:   while (lsa)
  524:     {
  525:       if ((! adv_router || lsa->header->adv_router == *adv_router) &&
  526:           (! id || lsa->header->id == *id))
  527:         (*showfunc) (vty, lsa);
  528: 
  529:       if (type && adv_router)
  530:         lsa = ospf6_lsdb_type_router_next (*type, *adv_router, lsa);
  531:       else if (type)
  532:         lsa = ospf6_lsdb_type_next (*type, lsa);
  533:       else
  534:         lsa = ospf6_lsdb_next (lsa);
  535:     }
  536: }
  537: 
  538: /* Decide new Link State ID to originate.
  539:    note return value is network byte order */
  540: u_int32_t
  541: ospf6_new_ls_id (u_int16_t type, u_int32_t adv_router,
  542:                  struct ospf6_lsdb *lsdb)
  543: {
  544:   struct ospf6_lsa *lsa;
  545:   u_int32_t id = 1;
  546: 
  547:   for (lsa = ospf6_lsdb_type_router_head (type, adv_router, lsdb); lsa;
  548:        lsa = ospf6_lsdb_type_router_next (type, adv_router, lsa))
  549:     {
  550:       if (ntohl (lsa->header->id) < id)
  551:         continue;
  552:       if (ntohl (lsa->header->id) > id)
  553:       {
  554:         ospf6_lsa_unlock (lsa);
  555:         break;
  556:       }
  557:       id++;
  558:     }
  559: 
  560:   return ((u_int32_t) htonl (id));
  561: }
  562: 
  563: /* Decide new LS sequence number to originate.
  564:    note return value is network byte order */
  565: u_int32_t
  566: ospf6_new_ls_seqnum (u_int16_t type, u_int32_t id, u_int32_t adv_router,
  567:                      struct ospf6_lsdb *lsdb)
  568: {
  569:   struct ospf6_lsa *lsa;
  570:   signed long seqnum = 0;
  571: 
  572:   /* if current database copy not found, return InitialSequenceNumber */
  573:   lsa = ospf6_lsdb_lookup (type, id, adv_router, lsdb);
  574:   if (lsa == NULL)
  575:     seqnum = INITIAL_SEQUENCE_NUMBER;
  576:   else
  577:     seqnum = (signed long) ntohl (lsa->header->seqnum) + 1;
  578: 
  579:   return ((u_int32_t) htonl (seqnum));
  580: }
  581: 
  582: 

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