Annotation of embedaddon/quagga/ospf6d/ospf6_route.c, revision 1.1.1.1

1.1       misho       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 "log.h"
                     25: #include "memory.h"
                     26: #include "prefix.h"
                     27: #include "table.h"
                     28: #include "vty.h"
                     29: #include "command.h"
                     30: #include "linklist.h"
                     31: 
                     32: #include "ospf6_proto.h"
                     33: #include "ospf6_lsa.h"
                     34: #include "ospf6_lsdb.h"
                     35: #include "ospf6_route.h"
                     36: #include "ospf6_top.h"
                     37: #include "ospf6_area.h"
                     38: #include "ospf6_interface.h"
                     39: #include "ospf6d.h"
                     40: 
                     41: unsigned char conf_debug_ospf6_route = 0;
                     42: 
                     43: static char *
                     44: ospf6_route_table_name (struct ospf6_route_table *table)
                     45: {
                     46:   static char name[32];
                     47:   switch (table->scope_type)
                     48:     {
                     49:       case OSPF6_SCOPE_TYPE_GLOBAL:
                     50:         {
                     51:           switch (table->table_type)
                     52:             {
                     53:               case OSPF6_TABLE_TYPE_ROUTES:
                     54:                 snprintf (name, sizeof (name), "global route table");
                     55:                 break;
                     56:               case OSPF6_TABLE_TYPE_BORDER_ROUTERS:
                     57:                 snprintf (name, sizeof (name), "global brouter table");
                     58:                 break;
                     59:               case OSPF6_TABLE_TYPE_EXTERNAL_ROUTES:
                     60:                 snprintf (name, sizeof (name), "global external table");
                     61:                 break;
                     62:               default:
                     63:                 snprintf (name, sizeof (name), "global unknown table");
                     64:                 break;
                     65:             }
                     66:         }
                     67:         break;
                     68: 
                     69:       case OSPF6_SCOPE_TYPE_AREA:
                     70:         {
                     71:           struct ospf6_area *oa = (struct ospf6_area *) table->scope;
                     72:           switch (table->table_type)
                     73:             {
                     74:               case OSPF6_TABLE_TYPE_SPF_RESULTS:
                     75:                 snprintf (name, sizeof (name),
                     76:                           "area %s spf table", oa->name);
                     77:                 break;
                     78:               case OSPF6_TABLE_TYPE_ROUTES:
                     79:                 snprintf (name, sizeof (name),
                     80:                           "area %s route table", oa->name);
                     81:                 break;
                     82:               case OSPF6_TABLE_TYPE_PREFIX_RANGES:
                     83:                 snprintf (name, sizeof (name),
                     84:                           "area %s range table", oa->name);
                     85:                 break;
                     86:               case OSPF6_TABLE_TYPE_SUMMARY_PREFIXES:
                     87:                 snprintf (name, sizeof (name),
                     88:                           "area %s summary prefix table", oa->name);
                     89:                 break;
                     90:               case OSPF6_TABLE_TYPE_SUMMARY_ROUTERS:
                     91:                 snprintf (name, sizeof (name),
                     92:                           "area %s summary router table", oa->name);
                     93:                 break;
                     94:               default:
                     95:                 snprintf (name, sizeof (name),
                     96:                           "area %s unknown table", oa->name);
                     97:                 break;
                     98:             }
                     99:         }
                    100:         break;
                    101: 
                    102:       case OSPF6_SCOPE_TYPE_INTERFACE:
                    103:         {
                    104:           struct ospf6_interface *oi = (struct ospf6_interface *) table->scope;
                    105:           switch (table->table_type)
                    106:             {
                    107:               case OSPF6_TABLE_TYPE_CONNECTED_ROUTES:
                    108:                 snprintf (name, sizeof (name), "interface %s connected table",
                    109:                           oi->interface->name);
                    110:                 break;
                    111:               default:
                    112:                 snprintf (name, sizeof (name), "interface %s unknown table",
                    113:                           oi->interface->name);
                    114:                 break;
                    115:             }
                    116:         }
                    117:         break;
                    118: 
                    119:       default:
                    120:         {
                    121:           switch (table->table_type)
                    122:             {
                    123:               case OSPF6_TABLE_TYPE_SPF_RESULTS:
                    124:                 snprintf (name, sizeof (name), "temporary spf table");
                    125:                 break;
                    126:               default:
                    127:                 snprintf (name, sizeof (name), "temporary unknown table");
                    128:                 break;
                    129:             }
                    130:         }
                    131:         break;
                    132:     }
                    133:   return name;
                    134: }
                    135: 
                    136: void
                    137: ospf6_linkstate_prefix (u_int32_t adv_router, u_int32_t id,
                    138:                         struct prefix *prefix)
                    139: {
                    140:   memset (prefix, 0, sizeof (struct prefix));
                    141:   prefix->family = AF_INET6;
                    142:   prefix->prefixlen = 64;
                    143:   memcpy (&prefix->u.prefix6.s6_addr[0], &adv_router, 4);
                    144:   memcpy (&prefix->u.prefix6.s6_addr[4], &id, 4);
                    145: }
                    146: 
                    147: void
                    148: ospf6_linkstate_prefix2str (struct prefix *prefix, char *buf, int size)
                    149: {
                    150:   u_int32_t adv_router, id;
                    151:   char adv_router_str[16], id_str[16];
                    152:   memcpy (&adv_router, &prefix->u.prefix6.s6_addr[0], 4);
                    153:   memcpy (&id, &prefix->u.prefix6.s6_addr[4], 4);
                    154:   inet_ntop (AF_INET, &adv_router, adv_router_str, sizeof (adv_router_str));
                    155:   inet_ntop (AF_INET, &id, id_str, sizeof (id_str));
                    156:   if (ntohl (id))
                    157:     snprintf (buf, size, "%s Net-ID: %s", adv_router_str, id_str);
                    158:   else
                    159:     snprintf (buf, size, "%s", adv_router_str);
                    160: }
                    161: 
                    162: /* Global strings for logging */
                    163: const char *ospf6_dest_type_str[OSPF6_DEST_TYPE_MAX] =
                    164: { "Unknown", "Router", "Network", "Discard", "Linkstate", "AddressRange", };
                    165: 
                    166: const char *ospf6_dest_type_substr[OSPF6_DEST_TYPE_MAX] =
                    167: { "?", "R", "N", "D", "L", "A", };
                    168: 
                    169: const char *ospf6_path_type_str[OSPF6_PATH_TYPE_MAX] =
                    170: { "Unknown", "Intra-Area", "Inter-Area", "External-1", "External-2", };
                    171: 
                    172: const char *ospf6_path_type_substr[OSPF6_PATH_TYPE_MAX] =
                    173: { "??", "IA", "IE", "E1", "E2", };
                    174: 
                    175: 
                    176: struct ospf6_route *
                    177: ospf6_route_create (void)
                    178: {
                    179:   struct ospf6_route *route;
                    180:   route = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route));
                    181:   return route;
                    182: }
                    183: 
                    184: void
                    185: ospf6_route_delete (struct ospf6_route *route)
                    186: {
                    187:   XFREE (MTYPE_OSPF6_ROUTE, route);
                    188: }
                    189: 
                    190: struct ospf6_route *
                    191: ospf6_route_copy (struct ospf6_route *route)
                    192: {
                    193:   struct ospf6_route *new;
                    194: 
                    195:   new = ospf6_route_create ();
                    196:   memcpy (new, route, sizeof (struct ospf6_route));
                    197:   new->rnode = NULL;
                    198:   new->prev = NULL;
                    199:   new->next = NULL;
                    200:   new->table = NULL;
                    201:   new->lock = 0;
                    202:   return new;
                    203: }
                    204: 
                    205: void
                    206: ospf6_route_lock (struct ospf6_route *route)
                    207: {
                    208:   route->lock++;
                    209: }
                    210: 
                    211: void
                    212: ospf6_route_unlock (struct ospf6_route *route)
                    213: {
                    214:   assert (route->lock > 0);
                    215:   route->lock--;
                    216:   if (route->lock == 0)
                    217:     {
                    218:       /* Can't detach from the table until here
                    219:          because ospf6_route_next () will use
                    220:          the 'route->table' pointer for logging */
                    221:       route->table = NULL;
                    222:       ospf6_route_delete (route);
                    223:     }
                    224: }
                    225: 
                    226: /* Route compare function. If ra is more preferred, it returns
                    227:    less than 0. If rb is more preferred returns greater than 0.
                    228:    Otherwise (neither one is preferred), returns 0 */
                    229: static int
                    230: ospf6_route_cmp (struct ospf6_route *ra, struct ospf6_route *rb)
                    231: {
                    232:   assert (ospf6_route_is_same (ra, rb));
                    233:   assert (OSPF6_PATH_TYPE_NONE < ra->path.type &&
                    234:           ra->path.type < OSPF6_PATH_TYPE_MAX);
                    235:   assert (OSPF6_PATH_TYPE_NONE < rb->path.type &&
                    236:           rb->path.type < OSPF6_PATH_TYPE_MAX);
                    237: 
                    238:   if (ra->type != rb->type)
                    239:     return (ra->type - rb->type);
                    240: 
                    241:   if (ra->path.area_id != rb->path.area_id)
                    242:     return (ntohl (ra->path.area_id) - ntohl (rb->path.area_id));
                    243: 
                    244:   if (ra->path.type != rb->path.type)
                    245:     return (ra->path.type - rb->path.type);
                    246: 
                    247:   if (ra->path.type == OSPF6_PATH_TYPE_EXTERNAL2)
                    248:     {
                    249:       if (ra->path.cost_e2 != rb->path.cost_e2)
                    250:         return (ra->path.cost_e2 - rb->path.cost_e2);
                    251:     }
                    252:   else
                    253:     {
                    254:       if (ra->path.cost != rb->path.cost)
                    255:         return (ra->path.cost - rb->path.cost);
                    256:     }
                    257: 
                    258:   return 0;
                    259: }
                    260: 
                    261: struct ospf6_route *
                    262: ospf6_route_lookup (struct prefix *prefix,
                    263:                     struct ospf6_route_table *table)
                    264: {
                    265:   struct route_node *node;
                    266:   struct ospf6_route *route;
                    267: 
                    268:   node = route_node_lookup (table->table, prefix);
                    269:   if (node == NULL)
                    270:     return NULL;
                    271: 
                    272:   route = (struct ospf6_route *) node->info;
                    273:   return route;
                    274: }
                    275: 
                    276: struct ospf6_route *
                    277: ospf6_route_lookup_identical (struct ospf6_route *route,
                    278:                               struct ospf6_route_table *table)
                    279: {
                    280:   struct ospf6_route *target;
                    281: 
                    282:   for (target = ospf6_route_lookup (&route->prefix, table);
                    283:        target; target = target->next)
                    284:     {
                    285:       if (ospf6_route_is_identical (target, route))
                    286:         return target;
                    287:     }
                    288:   return NULL;
                    289: }
                    290: 
                    291: struct ospf6_route *
                    292: ospf6_route_lookup_bestmatch (struct prefix *prefix,
                    293:                               struct ospf6_route_table *table)
                    294: {
                    295:   struct route_node *node;
                    296:   struct ospf6_route *route;
                    297: 
                    298:   node = route_node_match (table->table, prefix);
                    299:   if (node == NULL)
                    300:     return NULL;
                    301:   route_unlock_node (node);
                    302: 
                    303:   route = (struct ospf6_route *) node->info;
                    304:   return route;
                    305: }
                    306: 
                    307: #ifndef NDEBUG
                    308: static void
                    309: route_table_assert (struct ospf6_route_table *table)
                    310: {
                    311:   struct ospf6_route *prev, *r, *next;
                    312:   char buf[64];
                    313:   unsigned int link_error = 0, num = 0;
                    314:   
                    315:   r = ospf6_route_head (table);
                    316:   prev = NULL;
                    317:   while (r)
                    318:     {
                    319:       if (r->prev != prev)
                    320:         link_error++;
                    321:       
                    322:       next = ospf6_route_next (r);
                    323:       
                    324:       if (r->next != next)
                    325:         link_error++;
                    326:       
                    327:       prev = r;
                    328:       r = next;
                    329:     }
                    330:   
                    331:   for (r = ospf6_route_head (table); r; r = ospf6_route_next (r))
                    332:     num++;
                    333:   
                    334:   if (link_error == 0 && num == table->count)
                    335:     return;
                    336: 
                    337:   zlog_err ("PANIC !!");
                    338:   zlog_err ("Something has gone wrong with ospf6_route_table[%p]", table);
                    339:   zlog_debug ("table count = %d, real number = %d", table->count, num);
                    340:   zlog_debug ("DUMP START");
                    341:   for (r = ospf6_route_head (table); r; r = ospf6_route_next (r))
                    342:     {
                    343:       prefix2str (&r->prefix, buf, sizeof (buf));
                    344:       zlog_info ("%p<-[%p]->%p : %s", r->prev, r, r->next, buf);
                    345:     }
                    346:   zlog_debug ("DUMP END");
                    347: 
                    348:   assert (link_error == 0 && num == table->count);
                    349: }
                    350: #define ospf6_route_table_assert(t) (route_table_assert (t))
                    351: #else
                    352: #define ospf6_route_table_assert(t) ((void) 0)
                    353: #endif /*NDEBUG*/
                    354: 
                    355: struct ospf6_route *
                    356: ospf6_route_add (struct ospf6_route *route,
                    357:                  struct ospf6_route_table *table)
                    358: {
                    359:   struct route_node *node, *nextnode, *prevnode;
                    360:   struct ospf6_route *current = NULL;
                    361:   struct ospf6_route *prev = NULL, *old = NULL, *next = NULL;
                    362:   char buf[64];
                    363:   struct timeval now;
                    364: 
                    365:   assert (route->rnode == NULL);
                    366:   assert (route->lock == 0);
                    367:   assert (route->next == NULL);
                    368:   assert (route->prev == NULL);
                    369: 
                    370:   if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
                    371:     ospf6_linkstate_prefix2str (&route->prefix, buf, sizeof (buf));
                    372:   else
                    373:     prefix2str (&route->prefix, buf, sizeof (buf));
                    374: 
                    375:   if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
                    376:     zlog_debug ("%s %p: route add %p: %s", ospf6_route_table_name (table),
                    377:                 table, route, buf);
                    378:   else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
                    379:     zlog_debug ("%s: route add: %s", ospf6_route_table_name (table), buf);
                    380: 
                    381:   quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
                    382: 
                    383:   node = route_node_get (table->table, &route->prefix);
                    384:   route->rnode = node;
                    385: 
                    386:   /* find place to insert */
                    387:   for (current = node->info; current; current = current->next)
                    388:     {
                    389:       if (! ospf6_route_is_same (current, route))
                    390:         next = current;
                    391:       else if (current->type != route->type)
                    392:         prev = current;
                    393:       else if (ospf6_route_is_same_origin (current, route))
                    394:         old = current;
                    395:       else if (ospf6_route_cmp (current, route) > 0)
                    396:         next = current;
                    397:       else
                    398:         prev = current;
                    399: 
                    400:       if (old || next)
                    401:         break;
                    402:     }
                    403: 
                    404:   if (old)
                    405:     {
                    406:       /* if route does not actually change, return unchanged */
                    407:       if (ospf6_route_is_identical (old, route))
                    408:         {
                    409:           if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
                    410:             zlog_debug ("%s %p: route add %p: needless update of %p",
                    411:                         ospf6_route_table_name (table), table, route, old);
                    412:           else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
                    413:             zlog_debug ("%s: route add: needless update",
                    414:                         ospf6_route_table_name (table));
                    415: 
                    416:           ospf6_route_delete (route);
                    417:           SET_FLAG (old->flag, OSPF6_ROUTE_ADD);
                    418:           ospf6_route_table_assert (table);
                    419: 
                    420:           return old;
                    421:         }
                    422: 
                    423:       if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
                    424:         zlog_debug ("%s %p: route add %p: update of %p",
                    425:                     ospf6_route_table_name (table), table, route, old);
                    426:       else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
                    427:         zlog_debug ("%s: route add: update",
                    428:                     ospf6_route_table_name (table));
                    429: 
                    430:       /* replace old one if exists */
                    431:       if (node->info == old)
                    432:         {
                    433:           node->info = route;
                    434:           SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
                    435:         }
                    436: 
                    437:       if (old->prev)
                    438:         old->prev->next = route;
                    439:       route->prev = old->prev;
                    440:       if (old->next)
                    441:         old->next->prev = route;
                    442:       route->next = old->next;
                    443: 
                    444:       route->installed = old->installed;
                    445:       route->changed = now;
                    446:       assert (route->table == NULL);
                    447:       route->table = table;
                    448: 
                    449:       ospf6_route_unlock (old); /* will be deleted later */
                    450:       ospf6_route_lock (route);
                    451: 
                    452:       SET_FLAG (route->flag, OSPF6_ROUTE_CHANGE);
                    453:       ospf6_route_table_assert (table);
                    454: 
                    455:       if (table->hook_add)
                    456:         (*table->hook_add) (route);
                    457: 
                    458:       return route;
                    459:     }
                    460: 
                    461:   /* insert if previous or next node found */
                    462:   if (prev || next)
                    463:     {
                    464:       if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
                    465:         zlog_debug ("%s %p: route add %p: another path: prev %p, next %p",
                    466:                    ospf6_route_table_name (table), table, route, prev, next);
                    467:       else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
                    468:         zlog_debug ("%s: route add: another path found",
                    469:                     ospf6_route_table_name (table));
                    470: 
                    471:       if (prev == NULL)
                    472:         prev = next->prev;
                    473:       if (next == NULL)
                    474:         next = prev->next;
                    475: 
                    476:       if (prev)
                    477:         prev->next = route;
                    478:       route->prev = prev;
                    479:       if (next)
                    480:         next->prev = route;
                    481:       route->next = next;
                    482: 
                    483:       if (node->info == next)
                    484:         {
                    485:           assert (next->rnode == node);
                    486:           node->info = route;
                    487:           UNSET_FLAG (next->flag, OSPF6_ROUTE_BEST);
                    488:           SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
                    489:           if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
                    490:             zlog_info ("%s %p: route add %p: replacing previous best: %p",
                    491:                        ospf6_route_table_name (table), table, route, next);
                    492:         }
                    493: 
                    494:       route->installed = now;
                    495:       route->changed = now;
                    496:       assert (route->table == NULL);
                    497:       route->table = table;
                    498: 
                    499:       ospf6_route_lock (route);
                    500:       table->count++;
                    501:       ospf6_route_table_assert (table);
                    502: 
                    503:       SET_FLAG (route->flag, OSPF6_ROUTE_ADD);
                    504:       if (table->hook_add)
                    505:         (*table->hook_add) (route);
                    506: 
                    507:       return route;
                    508:     }
                    509: 
                    510:   /* Else, this is the brand new route regarding to the prefix */
                    511:   if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
                    512:     zlog_debug ("%s %p: route add %p: brand new route",
                    513:                 ospf6_route_table_name (table), table, route);
                    514:   else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
                    515:     zlog_debug ("%s: route add: brand new route",
                    516:                 ospf6_route_table_name (table));
                    517: 
                    518:   assert (node->info == NULL);
                    519:   node->info = route;
                    520:   SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
                    521:   ospf6_route_lock (route);
                    522:   route->installed = now;
                    523:   route->changed = now;
                    524:   assert (route->table == NULL);
                    525:   route->table = table;
                    526: 
                    527:   /* lookup real existing next route */
                    528:   nextnode = node;
                    529:   route_lock_node (nextnode);
                    530:   do {
                    531:     nextnode = route_next (nextnode);
                    532:   } while (nextnode && nextnode->info == NULL);
                    533: 
                    534:   /* set next link */
                    535:   if (nextnode == NULL)
                    536:     route->next = NULL;
                    537:   else
                    538:     {
                    539:       route_unlock_node (nextnode);
                    540: 
                    541:       next = nextnode->info;
                    542:       route->next = next;
                    543:       next->prev = route;
                    544:     }
                    545: 
                    546:   /* lookup real existing prev route */
                    547:   prevnode = node;
                    548:   route_lock_node (prevnode);
                    549:   do {
                    550:     prevnode = route_prev (prevnode);
                    551:   } while (prevnode && prevnode->info == NULL);
                    552: 
                    553:   /* set prev link */
                    554:   if (prevnode == NULL)
                    555:     route->prev = NULL;
                    556:   else
                    557:     {
                    558:       route_unlock_node (prevnode);
                    559: 
                    560:       prev = prevnode->info;
                    561:       while (prev->next && ospf6_route_is_same (prev, prev->next))
                    562:         prev = prev->next;
                    563:       route->prev = prev;
                    564:       prev->next = route;
                    565:     }
                    566: 
                    567:   table->count++;
                    568:   ospf6_route_table_assert (table);
                    569: 
                    570:   SET_FLAG (route->flag, OSPF6_ROUTE_ADD);
                    571:   if (table->hook_add)
                    572:     (*table->hook_add) (route);
                    573: 
                    574:   return route;
                    575: }
                    576: 
                    577: void
                    578: ospf6_route_remove (struct ospf6_route *route,
                    579:                     struct ospf6_route_table *table)
                    580: {
                    581:   struct route_node *node;
                    582:   struct ospf6_route *current;
                    583:   char buf[64];
                    584: 
                    585:   if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
                    586:     ospf6_linkstate_prefix2str (&route->prefix, buf, sizeof (buf));
                    587:   else
                    588:     prefix2str (&route->prefix, buf, sizeof (buf));
                    589: 
                    590:   if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
                    591:     zlog_debug ("%s %p: route remove %p: %s",
                    592:                 ospf6_route_table_name (table), table, route, buf);
                    593:   else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
                    594:     zlog_debug ("%s: route remove: %s", ospf6_route_table_name (table), buf);
                    595: 
                    596:   node = route_node_lookup (table->table, &route->prefix);
                    597:   assert (node);
                    598: 
                    599:   /* find the route to remove, making sure that the route pointer
                    600:      is from the route table. */
                    601:   current = node->info;
                    602:   while (current && ospf6_route_is_same (current, route))
                    603:     {
                    604:       if (current == route)
                    605:         break;
                    606:       current = current->next;
                    607:     }
                    608:   assert (current == route);
                    609: 
                    610:   /* adjust doubly linked list */
                    611:   if (route->prev)
                    612:     route->prev->next = route->next;
                    613:   if (route->next)
                    614:     route->next->prev = route->prev;
                    615: 
                    616:   if (node->info == route)
                    617:     {
                    618:       if (route->next && ospf6_route_is_same (route->next, route))
                    619:         {
                    620:           node->info = route->next;
                    621:           SET_FLAG (route->next->flag, OSPF6_ROUTE_BEST);
                    622:         }
                    623:       else
                    624:         node->info = NULL; /* should unlock route_node here ? */
                    625:     }
                    626: 
                    627:   table->count--;
                    628:   ospf6_route_table_assert (table);
                    629: 
                    630:   SET_FLAG (route->flag, OSPF6_ROUTE_WAS_REMOVED);
                    631: 
                    632:   if (table->hook_remove)
                    633:     (*table->hook_remove) (route);
                    634: 
                    635:   ospf6_route_unlock (route);
                    636: }
                    637: 
                    638: struct ospf6_route *
                    639: ospf6_route_head (struct ospf6_route_table *table)
                    640: {
                    641:   struct route_node *node;
                    642:   struct ospf6_route *route;
                    643: 
                    644:   node = route_top (table->table);
                    645:   if (node == NULL)
                    646:     return NULL;
                    647: 
                    648:   /* skip to the real existing entry */
                    649:   while (node && node->info == NULL)
                    650:     node = route_next (node);
                    651:   if (node == NULL)
                    652:     return NULL;
                    653: 
                    654:   route_unlock_node (node);
                    655:   assert (node->info);
                    656: 
                    657:   route = (struct ospf6_route *) node->info;
                    658:   assert (route->prev == NULL);
                    659:   assert (route->table == table);
                    660:   ospf6_route_lock (route);
                    661: 
                    662:   if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
                    663:     zlog_info ("%s %p: route head: %p<-[%p]->%p",
                    664:                ospf6_route_table_name (table), table,
                    665:                route->prev, route, route->next);
                    666: 
                    667:   return route;
                    668: }
                    669: 
                    670: struct ospf6_route *
                    671: ospf6_route_next (struct ospf6_route *route)
                    672: {
                    673:   struct ospf6_route *next = route->next;
                    674: 
                    675:   if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
                    676:     zlog_info ("%s %p: route next: %p<-[%p]->%p",
                    677:                ospf6_route_table_name (route->table), route->table,
                    678:                route->prev, route, route->next);
                    679: 
                    680:   ospf6_route_unlock (route);
                    681:   if (next)
                    682:     ospf6_route_lock (next);
                    683: 
                    684:   return next;
                    685: }
                    686: 
                    687: struct ospf6_route *
                    688: ospf6_route_best_next (struct ospf6_route *route)
                    689: {
                    690:   struct route_node *rnode;
                    691:   struct ospf6_route *next;
                    692: 
                    693:   ospf6_route_unlock (route);
                    694: 
                    695:   rnode = route->rnode;
                    696:   route_lock_node (rnode);
                    697:   rnode = route_next (rnode);
                    698:   while (rnode && rnode->info == NULL)
                    699:     rnode = route_next (rnode);
                    700:   if (rnode == NULL)
                    701:     return NULL;
                    702:   route_unlock_node (rnode);
                    703: 
                    704:   assert (rnode->info);
                    705:   next = (struct ospf6_route *) rnode->info;
                    706:   ospf6_route_lock (next);
                    707:   return next;
                    708: }
                    709: 
                    710: struct ospf6_route *
                    711: ospf6_route_match_head (struct prefix *prefix,
                    712:                         struct ospf6_route_table *table)
                    713: {
                    714:   struct route_node *node;
                    715:   struct ospf6_route *route;
                    716: 
                    717:   /* Walk down tree. */
                    718:   node = table->table->top;
                    719:   while (node && node->p.prefixlen < prefix->prefixlen &&
                    720:         prefix_match (&node->p, prefix))
                    721:     node = node->link[prefix_bit(&prefix->u.prefix, node->p.prefixlen)];
                    722: 
                    723:   if (node)
                    724:     route_lock_node (node);
                    725:   while (node && node->info == NULL)
                    726:     node = route_next (node);
                    727:   if (node == NULL)
                    728:     return NULL;
                    729:   route_unlock_node (node);
                    730: 
                    731:   if (! prefix_match (prefix, &node->p))
                    732:     return NULL;
                    733: 
                    734:   route = node->info;
                    735:   ospf6_route_lock (route);
                    736:   return route;
                    737: }
                    738: 
                    739: struct ospf6_route *
                    740: ospf6_route_match_next (struct prefix *prefix,
                    741:                         struct ospf6_route *route)
                    742: {
                    743:   struct ospf6_route *next;
                    744: 
                    745:   next = ospf6_route_next (route);
                    746:   if (next && ! prefix_match (prefix, &next->prefix))
                    747:     {
                    748:       ospf6_route_unlock (next);
                    749:       next = NULL;
                    750:     }
                    751: 
                    752:   return next;
                    753: }
                    754: 
                    755: void
                    756: ospf6_route_remove_all (struct ospf6_route_table *table)
                    757: {
                    758:   struct ospf6_route *route;
                    759:   for (route = ospf6_route_head (table); route;
                    760:        route = ospf6_route_next (route))
                    761:     ospf6_route_remove (route, table);
                    762: }
                    763: 
                    764: struct ospf6_route_table *
                    765: ospf6_route_table_create (int s, int t)
                    766: {
                    767:   struct ospf6_route_table *new;
                    768:   new = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route_table));
                    769:   new->table = route_table_init ();
                    770:   new->scope_type = s;
                    771:   new->table_type = t;
                    772:   return new;
                    773: }
                    774: 
                    775: void
                    776: ospf6_route_table_delete (struct ospf6_route_table *table)
                    777: {
                    778:   ospf6_route_remove_all (table);
                    779:   route_table_finish (table->table);
                    780:   XFREE (MTYPE_OSPF6_ROUTE, table);
                    781: }
                    782: 
                    783: 
                    784: /* VTY commands */
                    785: void
                    786: ospf6_route_show (struct vty *vty, struct ospf6_route *route)
                    787: {
                    788:   int i;
                    789:   char destination[64], nexthop[64];
                    790:   char duration[16], ifname[IFNAMSIZ];
                    791:   struct timeval now, res;
                    792: 
                    793:   quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
                    794:   timersub (&now, &route->changed, &res);
                    795:   timerstring (&res, duration, sizeof (duration));
                    796: 
                    797:   /* destination */
                    798:   if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
                    799:     ospf6_linkstate_prefix2str (&route->prefix, destination,
                    800:                                 sizeof (destination));
                    801:   else if (route->type == OSPF6_DEST_TYPE_ROUTER)
                    802:     inet_ntop (route->prefix.family, &route->prefix.u.prefix,
                    803:                destination, sizeof (destination));
                    804:   else
                    805:     prefix2str (&route->prefix, destination, sizeof (destination));
                    806: 
                    807:   /* nexthop */
                    808:   inet_ntop (AF_INET6, &route->nexthop[0].address, nexthop,
                    809:              sizeof (nexthop));
                    810:   if (! if_indextoname (route->nexthop[0].ifindex, ifname))
                    811:     snprintf (ifname, sizeof (ifname), "%d", route->nexthop[0].ifindex);
                    812: 
                    813:   vty_out (vty, "%c%1s %2s %-30s %-25s %6.*s %s%s",
                    814:            (ospf6_route_is_best (route) ? '*' : ' '),
                    815:            OSPF6_DEST_TYPE_SUBSTR (route->type),
                    816:            OSPF6_PATH_TYPE_SUBSTR (route->path.type),
                    817:            destination, nexthop, IFNAMSIZ, ifname, duration, VNL);
                    818: 
                    819:   for (i = 1; ospf6_nexthop_is_set (&route->nexthop[i]) &&
                    820:        i < OSPF6_MULTI_PATH_LIMIT; i++)
                    821:     {
                    822:       /* nexthop */
                    823:       inet_ntop (AF_INET6, &route->nexthop[i].address, nexthop,
                    824:                  sizeof (nexthop));
                    825:       if (! if_indextoname (route->nexthop[i].ifindex, ifname))
                    826:         snprintf (ifname, sizeof (ifname), "%d", route->nexthop[i].ifindex);
                    827: 
                    828:       vty_out (vty, "%c%1s %2s %-30s %-25s %6.*s %s%s",
                    829:                ' ', "", "", "", nexthop, IFNAMSIZ, ifname, "", VNL);
                    830:     }
                    831: }
                    832: 
                    833: void
                    834: ospf6_route_show_detail (struct vty *vty, struct ospf6_route *route)
                    835: {
                    836:   char destination[64], nexthop[64], ifname[IFNAMSIZ];
                    837:   char area_id[16], id[16], adv_router[16], capa[16], options[16];
                    838:   struct timeval now, res;
                    839:   char duration[16];
                    840:   int i;
                    841: 
                    842:   quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
                    843: 
                    844:   /* destination */
                    845:   if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
                    846:     ospf6_linkstate_prefix2str (&route->prefix, destination,
                    847:                                 sizeof (destination));
                    848:   else if (route->type == OSPF6_DEST_TYPE_ROUTER)
                    849:     inet_ntop (route->prefix.family, &route->prefix.u.prefix,
                    850:                destination, sizeof (destination));
                    851:   else
                    852:     prefix2str (&route->prefix, destination, sizeof (destination));
                    853:   vty_out (vty, "Destination: %s%s", destination, VNL);
                    854: 
                    855:   /* destination type */
                    856:   vty_out (vty, "Destination type: %s%s",
                    857:            OSPF6_DEST_TYPE_NAME (route->type),
                    858:            VNL);
                    859: 
                    860:   /* Time */
                    861:   timersub (&now, &route->installed, &res);
                    862:   timerstring (&res, duration, sizeof (duration));
                    863:   vty_out (vty, "Installed Time: %s ago%s", duration, VNL);
                    864: 
                    865:   timersub (&now, &route->changed, &res);
                    866:   timerstring (&res, duration, sizeof (duration));
                    867:   vty_out (vty, "  Changed Time: %s ago%s", duration, VNL);
                    868: 
                    869:   /* Debugging info */
                    870:   vty_out (vty, "Lock: %d Flags: %s%s%s%s%s", route->lock,
                    871:            (CHECK_FLAG (route->flag, OSPF6_ROUTE_BEST)   ? "B" : "-"),
                    872:            (CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD)    ? "A" : "-"),
                    873:            (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE) ? "R" : "-"),
                    874:            (CHECK_FLAG (route->flag, OSPF6_ROUTE_CHANGE) ? "C" : "-"),
                    875:            VNL);
                    876:   vty_out (vty, "Memory: prev: %p this: %p next: %p%s",
                    877:            route->prev, route, route->next, VNL);
                    878: 
                    879:   /* Path section */
                    880: 
                    881:   /* Area-ID */
                    882:   inet_ntop (AF_INET, &route->path.area_id, area_id, sizeof (area_id));
                    883:   vty_out (vty, "Associated Area: %s%s", area_id, VNL);
                    884: 
                    885:   /* Path type */
                    886:   vty_out (vty, "Path Type: %s%s",
                    887:            OSPF6_PATH_TYPE_NAME (route->path.type), VNL);
                    888: 
                    889:   /* LS Origin */
                    890:   inet_ntop (AF_INET, &route->path.origin.id, id, sizeof (id));
                    891:   inet_ntop (AF_INET, &route->path.origin.adv_router, adv_router,
                    892:              sizeof (adv_router));
                    893:   vty_out (vty, "LS Origin: %s Id: %s Adv: %s%s",
                    894:            ospf6_lstype_name (route->path.origin.type),
                    895:            id, adv_router, VNL);
                    896: 
                    897:   /* Options */
                    898:   ospf6_options_printbuf (route->path.options, options, sizeof (options));
                    899:   vty_out (vty, "Options: %s%s", options, VNL);
                    900: 
                    901:   /* Router Bits */
                    902:   ospf6_capability_printbuf (route->path.router_bits, capa, sizeof (capa));
                    903:   vty_out (vty, "Router Bits: %s%s", capa, VNL);
                    904: 
                    905:   /* Prefix Options */
                    906:   vty_out (vty, "Prefix Options: xxx%s", VNL);
                    907: 
                    908:   /* Metrics */
                    909:   vty_out (vty, "Metric Type: %d%s", route->path.metric_type,
                    910:            VNL);
                    911:   vty_out (vty, "Metric: %d (%d)%s",
                    912:            route->path.cost, route->path.cost_e2, VNL);
                    913: 
                    914:   /* Nexthops */
                    915:   vty_out (vty, "Nexthop:%s", VNL);
                    916:   for (i = 0; ospf6_nexthop_is_set (&route->nexthop[i]) &&
                    917:        i < OSPF6_MULTI_PATH_LIMIT; i++)
                    918:     {
                    919:       /* nexthop */
                    920:       inet_ntop (AF_INET6, &route->nexthop[i].address, nexthop,
                    921:                  sizeof (nexthop));
                    922:       if (! if_indextoname (route->nexthop[i].ifindex, ifname))
                    923:         snprintf (ifname, sizeof (ifname), "%d", route->nexthop[i].ifindex);
                    924:       vty_out (vty, "  %s %.*s%s", nexthop, IFNAMSIZ, ifname, VNL);
                    925:     }
                    926:   vty_out (vty, "%s", VNL);
                    927: }
                    928: 
                    929: static void
                    930: ospf6_route_show_table_summary (struct vty *vty,
                    931:                                 struct ospf6_route_table *table)
                    932: {
                    933:   struct ospf6_route *route, *prev = NULL;
                    934:   int i, pathtype[OSPF6_PATH_TYPE_MAX];
                    935:   unsigned int number = 0;
                    936:   int nhinval = 0, ecmp = 0;
                    937:   int alternative = 0, destination = 0;
                    938: 
                    939:   for (i = 0; i < OSPF6_PATH_TYPE_MAX; i++)
                    940:     pathtype[i] = 0;
                    941: 
                    942:   for (route = ospf6_route_head (table); route;
                    943:        route = ospf6_route_next (route))
                    944:     {
                    945:       if (prev == NULL || ! ospf6_route_is_same (prev, route))
                    946:         destination++;
                    947:       else
                    948:         alternative++;
                    949:       if (! ospf6_nexthop_is_set (&route->nexthop[0]))
                    950:         nhinval++;
                    951:       else if (ospf6_nexthop_is_set (&route->nexthop[1]))
                    952:         ecmp++;
                    953:       pathtype[route->path.type]++;
                    954:       number++;
                    955: 
                    956:       prev = route;
                    957:     }
                    958: 
                    959:   assert (number == table->count);
                    960: 
                    961:   vty_out (vty, "Number of OSPFv3 routes: %d%s", number, VNL);
                    962:   vty_out (vty, "Number of Destination: %d%s", destination, VNL);
                    963:   vty_out (vty, "Number of Alternative routes: %d%s", alternative, VNL);
                    964:   vty_out (vty, "Number of Equal Cost Multi Path: %d%s", ecmp, VNL);
                    965:   for (i = OSPF6_PATH_TYPE_INTRA; i <= OSPF6_PATH_TYPE_EXTERNAL2; i++)
                    966:     {
                    967:       vty_out (vty, "Number of %s routes: %d%s",
                    968:                OSPF6_PATH_TYPE_NAME (i), pathtype[i], VNL);
                    969:     }
                    970: }
                    971: 
                    972: static void
                    973: ospf6_route_show_table_prefix (struct vty *vty,
                    974:                                struct prefix *prefix,
                    975:                                struct ospf6_route_table *table)
                    976: {
                    977:   struct ospf6_route *route;
                    978: 
                    979:   route = ospf6_route_lookup (prefix, table);
                    980:   if (route == NULL)
                    981:     return;
                    982: 
                    983:   ospf6_route_lock (route);
                    984:   while (route && ospf6_route_is_prefix (prefix, route))
                    985:     {
                    986:       /* Specifying a prefix will always display details */
                    987:       ospf6_route_show_detail (vty, route);
                    988:       route = ospf6_route_next (route);
                    989:     }
                    990:   if (route)
                    991:     ospf6_route_unlock (route);
                    992: }
                    993: 
                    994: static void
                    995: ospf6_route_show_table_address (struct vty *vty,
                    996:                                 struct prefix *prefix,
                    997:                                 struct ospf6_route_table *table)
                    998: {
                    999:   struct ospf6_route *route;
                   1000: 
                   1001:   route = ospf6_route_lookup_bestmatch (prefix, table);
                   1002:   if (route == NULL)
                   1003:     return;
                   1004: 
                   1005:   prefix = &route->prefix;
                   1006:   ospf6_route_lock (route);
                   1007:   while (route && ospf6_route_is_prefix (prefix, route))
                   1008:     {
                   1009:       /* Specifying a prefix will always display details */
                   1010:       ospf6_route_show_detail (vty, route);
                   1011:       route = ospf6_route_next (route);
                   1012:     }
                   1013:   if (route)
                   1014:     ospf6_route_unlock (route);
                   1015: }
                   1016: 
                   1017: static void
                   1018: ospf6_route_show_table_match (struct vty *vty, int detail,
                   1019:                               struct prefix *prefix,
                   1020:                               struct ospf6_route_table *table)
                   1021: {
                   1022:   struct ospf6_route *route;
                   1023:   assert (prefix->family);
                   1024: 
                   1025:   route = ospf6_route_match_head (prefix, table);
                   1026:   while (route)
                   1027:     {
                   1028:       if (detail)
                   1029:         ospf6_route_show_detail (vty, route);
                   1030:       else
                   1031:         ospf6_route_show (vty, route);
                   1032:       route = ospf6_route_match_next (prefix, route);
                   1033:     }
                   1034: }
                   1035: 
                   1036: static void
                   1037: ospf6_route_show_table_type (struct vty *vty, int detail, u_char type,
                   1038:                              struct ospf6_route_table *table)
                   1039: {
                   1040:   struct ospf6_route *route;
                   1041: 
                   1042:   route = ospf6_route_head (table);
                   1043:   while (route)
                   1044:     {
                   1045:       if (route->path.type == type)
                   1046:         {
                   1047:           if (detail)
                   1048:             ospf6_route_show_detail (vty, route);
                   1049:           else
                   1050:             ospf6_route_show (vty, route);
                   1051:         }
                   1052:       route = ospf6_route_next (route);
                   1053:     }
                   1054: }
                   1055: 
                   1056: static void
                   1057: ospf6_route_show_table (struct vty *vty, int detail,
                   1058:                         struct ospf6_route_table *table)
                   1059: {
                   1060:   struct ospf6_route *route;
                   1061: 
                   1062:   route = ospf6_route_head (table);
                   1063:   while (route)
                   1064:     {
                   1065:       if (detail)
                   1066:         ospf6_route_show_detail (vty, route);
                   1067:       else
                   1068:         ospf6_route_show (vty, route);
                   1069:       route = ospf6_route_next (route);
                   1070:     }
                   1071: }
                   1072: 
                   1073: int
                   1074: ospf6_route_table_show (struct vty *vty, int argc, const char *argv[],
                   1075:                         struct ospf6_route_table *table)
                   1076: {
                   1077:   int summary = 0;
                   1078:   int match = 0;
                   1079:   int detail = 0;
                   1080:   int slash = 0;
                   1081:   int isprefix = 0;
                   1082:   int i, ret;
                   1083:   struct prefix prefix;
                   1084:   u_char type = 0;
                   1085: 
                   1086:   memset (&prefix, 0, sizeof (struct prefix));
                   1087: 
                   1088:   for (i = 0; i < argc; i++)
                   1089:     {
                   1090:       if (! strcmp (argv[i], "summary"))
                   1091:         {
                   1092:           summary++;
                   1093:           continue;
                   1094:         }
                   1095: 
                   1096:       if (! strcmp (argv[i], "intra-area"))
                   1097:         {
                   1098:           type = OSPF6_PATH_TYPE_INTRA;
                   1099:           continue;
                   1100:         }
                   1101: 
                   1102:       if (! strcmp (argv[i], "inter-area"))
                   1103:         {
                   1104:           type = OSPF6_PATH_TYPE_INTER;
                   1105:           continue;
                   1106:         }
                   1107: 
                   1108:       if (! strcmp (argv[i], "external-1"))
                   1109:         {
                   1110:           type = OSPF6_PATH_TYPE_EXTERNAL1;
                   1111:           continue;
                   1112:         }
                   1113: 
                   1114:       if (! strcmp (argv[i], "external-2"))
                   1115:         {
                   1116:           type = OSPF6_PATH_TYPE_EXTERNAL2;
                   1117:           continue;
                   1118:         }
                   1119: 
                   1120:       if (! strcmp (argv[i], "detail"))
                   1121:         {
                   1122:           detail++;
                   1123:           continue;
                   1124:         }
                   1125: 
                   1126:       if (! strcmp (argv[i], "match"))
                   1127:         {
                   1128:           match++;
                   1129:           continue;
                   1130:         }
                   1131: 
                   1132:       ret = str2prefix (argv[i], &prefix);
                   1133:       if (ret == 1 && prefix.family == AF_INET6)
                   1134:         {
                   1135:           isprefix++;
                   1136:           if (strchr (argv[i], '/'))
                   1137:             slash++;
                   1138:           continue;
                   1139:         }
                   1140: 
                   1141:       vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
                   1142:       return CMD_SUCCESS;
                   1143:     }
                   1144: 
                   1145:   /* Give summary of this route table */
                   1146:   if (summary)
                   1147:     {
                   1148:       ospf6_route_show_table_summary (vty, table);
                   1149:       return CMD_SUCCESS;
                   1150:     }
                   1151: 
                   1152:   /* Give exact prefix-match route */
                   1153:   if (isprefix && ! match)
                   1154:     {
                   1155:       /* If exact address, give best matching route */
                   1156:       if (! slash)
                   1157:         ospf6_route_show_table_address (vty, &prefix, table);
                   1158:       else
                   1159:         ospf6_route_show_table_prefix (vty, &prefix, table);
                   1160: 
                   1161:       return CMD_SUCCESS;
                   1162:     }
                   1163: 
                   1164:   if (match)
                   1165:     ospf6_route_show_table_match (vty, detail, &prefix, table);
                   1166:   else if (type)
                   1167:     ospf6_route_show_table_type (vty, detail, type, table);
                   1168:   else
                   1169:     ospf6_route_show_table (vty, detail, table);
                   1170: 
                   1171:   return CMD_SUCCESS;
                   1172: }
                   1173: 
                   1174: static void
                   1175: ospf6_linkstate_show_header (struct vty *vty)
                   1176: {
                   1177:   vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %s%s",
                   1178:            "Type", "Router-ID", "Net-ID", "Rtr-Bits", "Options", "Cost", VNL);
                   1179: }
                   1180: 
                   1181: static void
                   1182: ospf6_linkstate_show (struct vty *vty, struct ospf6_route *route)
                   1183: {
                   1184:   u_int32_t router, id;
                   1185:   char routername[16], idname[16], rbits[16], options[16];
                   1186: 
                   1187:   router = ospf6_linkstate_prefix_adv_router (&route->prefix);
                   1188:   inet_ntop (AF_INET, &router, routername, sizeof (routername));
                   1189:   id = ospf6_linkstate_prefix_id (&route->prefix);
                   1190:   inet_ntop (AF_INET, &id, idname, sizeof (idname));
                   1191: 
                   1192:   ospf6_capability_printbuf (route->path.router_bits, rbits, sizeof (rbits));
                   1193:   ospf6_options_printbuf (route->path.options, options, sizeof (options));
                   1194: 
                   1195:   if (ntohl (id))
                   1196:     vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %lu%s",
                   1197:              "Network", routername, idname, rbits, options,
                   1198:              (unsigned long) route->path.cost, VNL);
                   1199:   else
                   1200:     vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %lu%s",
                   1201:              "Router", routername, idname, rbits, options,
                   1202:              (unsigned long) route->path.cost, VNL);
                   1203: }
                   1204: 
                   1205: 
                   1206: static void
                   1207: ospf6_linkstate_show_table_exact (struct vty *vty,
                   1208:                                   struct prefix *prefix,
                   1209:                                   struct ospf6_route_table *table)
                   1210: {
                   1211:   struct ospf6_route *route;
                   1212: 
                   1213:   route = ospf6_route_lookup (prefix, table);
                   1214:   if (route == NULL)
                   1215:     return;
                   1216: 
                   1217:   ospf6_route_lock (route);
                   1218:   while (route && ospf6_route_is_prefix (prefix, route))
                   1219:     {
                   1220:       /* Specifying a prefix will always display details */
                   1221:       ospf6_route_show_detail (vty, route);
                   1222:       route = ospf6_route_next (route);
                   1223:     }
                   1224:   if (route)
                   1225:     ospf6_route_unlock (route);
                   1226: }
                   1227: 
                   1228: static void
                   1229: ospf6_linkstate_show_table (struct vty *vty, int detail,
                   1230:                             struct ospf6_route_table *table)
                   1231: {
                   1232:   struct ospf6_route *route;
                   1233: 
                   1234:   if (! detail)
                   1235:     ospf6_linkstate_show_header (vty);
                   1236: 
                   1237:   route = ospf6_route_head (table);
                   1238:   while (route)
                   1239:     {
                   1240:       if (detail)
                   1241:         ospf6_route_show_detail (vty, route);
                   1242:       else
                   1243:         ospf6_linkstate_show (vty, route);
                   1244:       route = ospf6_route_next (route);
                   1245:     }
                   1246: }
                   1247: 
                   1248: int
                   1249: ospf6_linkstate_table_show (struct vty *vty, int argc, const char *argv[],
                   1250:                             struct ospf6_route_table *table)
                   1251: {
                   1252:   int detail = 0;
                   1253:   int is_id = 0;
                   1254:   int is_router = 0;
                   1255:   int i, ret;
                   1256:   struct prefix router, id, prefix;
                   1257: 
                   1258:   memset (&router, 0, sizeof (struct prefix));
                   1259:   memset (&id, 0, sizeof (struct prefix));
                   1260:   memset (&prefix, 0, sizeof (struct prefix));
                   1261: 
                   1262:   for (i = 0; i < argc; i++)
                   1263:     {
                   1264:       if (! strcmp (argv[i], "detail"))
                   1265:         {
                   1266:           detail++;
                   1267:           continue;
                   1268:         }
                   1269: 
                   1270:       if (! is_router)
                   1271:         {
                   1272:           ret = str2prefix (argv[i], &router);
                   1273:           if (ret == 1 && router.family == AF_INET)
                   1274:             {
                   1275:               is_router++;
                   1276:               continue;
                   1277:             }
                   1278:           vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
                   1279:           return CMD_SUCCESS;
                   1280:         }
                   1281: 
                   1282:       if (! is_id)
                   1283:         {
                   1284:           ret = str2prefix (argv[i], &id);
                   1285:           if (ret == 1 && id.family == AF_INET)
                   1286:             {
                   1287:               is_id++;
                   1288:               continue;
                   1289:             }
                   1290:           vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
                   1291:           return CMD_SUCCESS;
                   1292:         }
                   1293: 
                   1294:       vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
                   1295:       return CMD_SUCCESS;
                   1296:     }
                   1297: 
                   1298:   if (is_router)
                   1299:     ospf6_linkstate_prefix (router.u.prefix4.s_addr,
                   1300:                             id.u.prefix4.s_addr, &prefix);
                   1301: 
                   1302:   if (prefix.family)
                   1303:     ospf6_linkstate_show_table_exact (vty, &prefix, table);
                   1304:   else
                   1305:     ospf6_linkstate_show_table (vty, detail, table);
                   1306: 
                   1307:   return CMD_SUCCESS;
                   1308: }
                   1309: 
                   1310: 
                   1311: void
                   1312: ospf6_brouter_show_header (struct vty *vty)
                   1313: {
                   1314:   vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
                   1315:            "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL);
                   1316: }
                   1317: 
                   1318: void
                   1319: ospf6_brouter_show (struct vty *vty, struct ospf6_route *route)
                   1320: {
                   1321:   u_int32_t adv_router;
                   1322:   char adv[16], rbits[16], options[16], area[16];
                   1323: 
                   1324:   adv_router = ospf6_linkstate_prefix_adv_router (&route->prefix);
                   1325:   inet_ntop (AF_INET, &adv_router, adv, sizeof (adv));
                   1326:   ospf6_capability_printbuf (route->path.router_bits, rbits, sizeof (rbits));
                   1327:   ospf6_options_printbuf (route->path.options, options, sizeof (options));
                   1328:   inet_ntop (AF_INET, &route->path.area_id, area, sizeof (area));
                   1329: 
                   1330:   /* vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
                   1331:            "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL); */
                   1332:   vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
                   1333:            adv, rbits, options, OSPF6_PATH_TYPE_NAME (route->path.type),
                   1334:            area, VNL);
                   1335: }
                   1336: 
                   1337: DEFUN (debug_ospf6_route,
                   1338:        debug_ospf6_route_cmd,
                   1339:        "debug ospf6 route (table|intra-area|inter-area|memory)",
                   1340:        DEBUG_STR
                   1341:        OSPF6_STR
                   1342:        "Debug route table calculation\n"
                   1343:        "Debug detail\n"
                   1344:        "Debug intra-area route calculation\n"
                   1345:        "Debug inter-area route calculation\n"
                   1346:        "Debug route memory use\n"
                   1347:        )
                   1348: {
                   1349:   unsigned char level = 0;
                   1350: 
                   1351:   if (! strncmp (argv[0], "table", 5))
                   1352:     level = OSPF6_DEBUG_ROUTE_TABLE;
                   1353:   else if (! strncmp (argv[0], "intra", 5))
                   1354:     level = OSPF6_DEBUG_ROUTE_INTRA;
                   1355:   else if (! strncmp (argv[0], "inter", 5))
                   1356:     level = OSPF6_DEBUG_ROUTE_INTER;
                   1357:   else if (! strncmp (argv[0], "memor", 5))
                   1358:     level = OSPF6_DEBUG_ROUTE_MEMORY;
                   1359:   OSPF6_DEBUG_ROUTE_ON (level);
                   1360:   return CMD_SUCCESS;
                   1361: }
                   1362: 
                   1363: DEFUN (no_debug_ospf6_route,
                   1364:        no_debug_ospf6_route_cmd,
                   1365:        "no debug ospf6 route (table|intra-area|inter-area|memory)",
                   1366:        NO_STR
                   1367:        DEBUG_STR
                   1368:        OSPF6_STR
                   1369:        "Debug route table calculation\n"
                   1370:        "Debug intra-area route calculation\n"
                   1371:        "Debug route memory use\n")
                   1372: {
                   1373:   unsigned char level = 0;
                   1374: 
                   1375:   if (! strncmp (argv[0], "table", 5))
                   1376:     level = OSPF6_DEBUG_ROUTE_TABLE;
                   1377:   else if (! strncmp (argv[0], "intra", 5))
                   1378:     level = OSPF6_DEBUG_ROUTE_INTRA;
                   1379:   else if (! strncmp (argv[0], "inter", 5))
                   1380:     level = OSPF6_DEBUG_ROUTE_INTER;
                   1381:   else if (! strncmp (argv[0], "memor", 5))
                   1382:     level = OSPF6_DEBUG_ROUTE_MEMORY;
                   1383:   OSPF6_DEBUG_ROUTE_OFF (level);
                   1384:   return CMD_SUCCESS;
                   1385: }
                   1386: 
                   1387: int
                   1388: config_write_ospf6_debug_route (struct vty *vty)
                   1389: {
                   1390:   if (IS_OSPF6_DEBUG_ROUTE (TABLE))
                   1391:     vty_out (vty, "debug ospf6 route table%s", VNL);
                   1392:   if (IS_OSPF6_DEBUG_ROUTE (INTRA))
                   1393:     vty_out (vty, "debug ospf6 route intra-area%s", VNL);
                   1394:   if (IS_OSPF6_DEBUG_ROUTE (INTER))
                   1395:     vty_out (vty, "debug ospf6 route inter-area%s", VNL);
                   1396:   return 0;
                   1397: }
                   1398: 
                   1399: void
                   1400: install_element_ospf6_debug_route (void)
                   1401: {
                   1402:   install_element (ENABLE_NODE, &debug_ospf6_route_cmd);
                   1403:   install_element (ENABLE_NODE, &no_debug_ospf6_route_cmd);
                   1404:   install_element (CONFIG_NODE, &debug_ospf6_route_cmd);
                   1405:   install_element (CONFIG_NODE, &no_debug_ospf6_route_cmd);
                   1406: }
                   1407: 
                   1408: 
                   1409: 

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