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

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: 
1.1.1.2 ! misho     307: #ifdef DEBUG
1.1       misho     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)
1.1.1.2 ! misho     353: #endif /*DEBUG*/
1.1       misho     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),
1.1.1.2 ! misho     377:                 (void *)table, (void *)route, buf);
1.1       misho     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",
1.1.1.2 ! misho     411:                         ospf6_route_table_name (table),
        !           412:                         (void *)table, (void *)route, (void *)old);
1.1       misho     413:           else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
                    414:             zlog_debug ("%s: route add: needless update",
                    415:                         ospf6_route_table_name (table));
                    416: 
                    417:           ospf6_route_delete (route);
                    418:           SET_FLAG (old->flag, OSPF6_ROUTE_ADD);
                    419:           ospf6_route_table_assert (table);
                    420: 
                    421:           return old;
                    422:         }
                    423: 
                    424:       if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
                    425:         zlog_debug ("%s %p: route add %p: update of %p",
1.1.1.2 ! misho     426:                     ospf6_route_table_name (table),
        !           427:                     (void *)table, (void *)route, (void *)old);
1.1       misho     428:       else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
                    429:         zlog_debug ("%s: route add: update",
                    430:                     ospf6_route_table_name (table));
                    431: 
                    432:       /* replace old one if exists */
                    433:       if (node->info == old)
                    434:         {
                    435:           node->info = route;
                    436:           SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
                    437:         }
                    438: 
                    439:       if (old->prev)
                    440:         old->prev->next = route;
                    441:       route->prev = old->prev;
                    442:       if (old->next)
                    443:         old->next->prev = route;
                    444:       route->next = old->next;
                    445: 
                    446:       route->installed = old->installed;
                    447:       route->changed = now;
                    448:       assert (route->table == NULL);
                    449:       route->table = table;
                    450: 
                    451:       ospf6_route_unlock (old); /* will be deleted later */
                    452:       ospf6_route_lock (route);
                    453: 
                    454:       SET_FLAG (route->flag, OSPF6_ROUTE_CHANGE);
                    455:       ospf6_route_table_assert (table);
                    456: 
                    457:       if (table->hook_add)
                    458:         (*table->hook_add) (route);
                    459: 
                    460:       return route;
                    461:     }
                    462: 
                    463:   /* insert if previous or next node found */
                    464:   if (prev || next)
                    465:     {
                    466:       if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
                    467:         zlog_debug ("%s %p: route add %p: another path: prev %p, next %p",
1.1.1.2 ! misho     468:                     ospf6_route_table_name (table),
        !           469:                     (void *)table, (void *)route, (void *)prev, (void *)next);
1.1       misho     470:       else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
                    471:         zlog_debug ("%s: route add: another path found",
                    472:                     ospf6_route_table_name (table));
                    473: 
                    474:       if (prev == NULL)
                    475:         prev = next->prev;
                    476:       if (next == NULL)
                    477:         next = prev->next;
                    478: 
                    479:       if (prev)
                    480:         prev->next = route;
                    481:       route->prev = prev;
                    482:       if (next)
                    483:         next->prev = route;
                    484:       route->next = next;
                    485: 
                    486:       if (node->info == next)
                    487:         {
                    488:           assert (next->rnode == node);
                    489:           node->info = route;
                    490:           UNSET_FLAG (next->flag, OSPF6_ROUTE_BEST);
                    491:           SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
                    492:           if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
                    493:             zlog_info ("%s %p: route add %p: replacing previous best: %p",
1.1.1.2 ! misho     494:                        ospf6_route_table_name (table),
        !           495:                        (void *)table, (void *)route, (void *)next);
1.1       misho     496:         }
                    497: 
                    498:       route->installed = now;
                    499:       route->changed = now;
                    500:       assert (route->table == NULL);
                    501:       route->table = table;
                    502: 
                    503:       ospf6_route_lock (route);
                    504:       table->count++;
                    505:       ospf6_route_table_assert (table);
                    506: 
                    507:       SET_FLAG (route->flag, OSPF6_ROUTE_ADD);
                    508:       if (table->hook_add)
                    509:         (*table->hook_add) (route);
                    510: 
                    511:       return route;
                    512:     }
                    513: 
                    514:   /* Else, this is the brand new route regarding to the prefix */
                    515:   if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
                    516:     zlog_debug ("%s %p: route add %p: brand new route",
1.1.1.2 ! misho     517:                 ospf6_route_table_name (table), (void *)table, (void *)route);
1.1       misho     518:   else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
                    519:     zlog_debug ("%s: route add: brand new route",
                    520:                 ospf6_route_table_name (table));
                    521: 
                    522:   assert (node->info == NULL);
                    523:   node->info = route;
                    524:   SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
                    525:   ospf6_route_lock (route);
                    526:   route->installed = now;
                    527:   route->changed = now;
                    528:   assert (route->table == NULL);
                    529:   route->table = table;
                    530: 
                    531:   /* lookup real existing next route */
                    532:   nextnode = node;
                    533:   route_lock_node (nextnode);
                    534:   do {
                    535:     nextnode = route_next (nextnode);
                    536:   } while (nextnode && nextnode->info == NULL);
                    537: 
                    538:   /* set next link */
                    539:   if (nextnode == NULL)
                    540:     route->next = NULL;
                    541:   else
                    542:     {
                    543:       route_unlock_node (nextnode);
                    544: 
                    545:       next = nextnode->info;
                    546:       route->next = next;
                    547:       next->prev = route;
                    548:     }
                    549: 
                    550:   /* lookup real existing prev route */
                    551:   prevnode = node;
                    552:   route_lock_node (prevnode);
                    553:   do {
                    554:     prevnode = route_prev (prevnode);
                    555:   } while (prevnode && prevnode->info == NULL);
                    556: 
                    557:   /* set prev link */
                    558:   if (prevnode == NULL)
                    559:     route->prev = NULL;
                    560:   else
                    561:     {
                    562:       route_unlock_node (prevnode);
                    563: 
                    564:       prev = prevnode->info;
                    565:       while (prev->next && ospf6_route_is_same (prev, prev->next))
                    566:         prev = prev->next;
                    567:       route->prev = prev;
                    568:       prev->next = route;
                    569:     }
                    570: 
                    571:   table->count++;
                    572:   ospf6_route_table_assert (table);
                    573: 
                    574:   SET_FLAG (route->flag, OSPF6_ROUTE_ADD);
                    575:   if (table->hook_add)
                    576:     (*table->hook_add) (route);
                    577: 
                    578:   return route;
                    579: }
                    580: 
                    581: void
                    582: ospf6_route_remove (struct ospf6_route *route,
                    583:                     struct ospf6_route_table *table)
                    584: {
                    585:   struct route_node *node;
                    586:   struct ospf6_route *current;
                    587:   char buf[64];
                    588: 
                    589:   if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
                    590:     ospf6_linkstate_prefix2str (&route->prefix, buf, sizeof (buf));
                    591:   else
                    592:     prefix2str (&route->prefix, buf, sizeof (buf));
                    593: 
                    594:   if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
                    595:     zlog_debug ("%s %p: route remove %p: %s",
1.1.1.2 ! misho     596:                 ospf6_route_table_name (table),
        !           597:                 (void *)table, (void *)route, buf);
1.1       misho     598:   else if (IS_OSPF6_DEBUG_ROUTE (TABLE))
                    599:     zlog_debug ("%s: route remove: %s", ospf6_route_table_name (table), buf);
                    600: 
                    601:   node = route_node_lookup (table->table, &route->prefix);
                    602:   assert (node);
                    603: 
                    604:   /* find the route to remove, making sure that the route pointer
                    605:      is from the route table. */
                    606:   current = node->info;
                    607:   while (current && ospf6_route_is_same (current, route))
                    608:     {
                    609:       if (current == route)
                    610:         break;
                    611:       current = current->next;
                    612:     }
                    613:   assert (current == route);
                    614: 
                    615:   /* adjust doubly linked list */
                    616:   if (route->prev)
                    617:     route->prev->next = route->next;
                    618:   if (route->next)
                    619:     route->next->prev = route->prev;
                    620: 
                    621:   if (node->info == route)
                    622:     {
                    623:       if (route->next && ospf6_route_is_same (route->next, route))
                    624:         {
                    625:           node->info = route->next;
                    626:           SET_FLAG (route->next->flag, OSPF6_ROUTE_BEST);
                    627:         }
                    628:       else
                    629:         node->info = NULL; /* should unlock route_node here ? */
                    630:     }
                    631: 
                    632:   table->count--;
                    633:   ospf6_route_table_assert (table);
                    634: 
                    635:   SET_FLAG (route->flag, OSPF6_ROUTE_WAS_REMOVED);
                    636: 
                    637:   if (table->hook_remove)
                    638:     (*table->hook_remove) (route);
                    639: 
                    640:   ospf6_route_unlock (route);
                    641: }
                    642: 
                    643: struct ospf6_route *
                    644: ospf6_route_head (struct ospf6_route_table *table)
                    645: {
                    646:   struct route_node *node;
                    647:   struct ospf6_route *route;
                    648: 
                    649:   node = route_top (table->table);
                    650:   if (node == NULL)
                    651:     return NULL;
                    652: 
                    653:   /* skip to the real existing entry */
                    654:   while (node && node->info == NULL)
                    655:     node = route_next (node);
                    656:   if (node == NULL)
                    657:     return NULL;
                    658: 
                    659:   route_unlock_node (node);
                    660:   assert (node->info);
                    661: 
                    662:   route = (struct ospf6_route *) node->info;
                    663:   assert (route->prev == NULL);
                    664:   assert (route->table == table);
                    665:   ospf6_route_lock (route);
                    666: 
                    667:   if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
                    668:     zlog_info ("%s %p: route head: %p<-[%p]->%p",
1.1.1.2 ! misho     669:                ospf6_route_table_name (table), (void *)table,
        !           670:                (void *)route->prev, (void *)route, (void *)route->next);
1.1       misho     671: 
                    672:   return route;
                    673: }
                    674: 
                    675: struct ospf6_route *
                    676: ospf6_route_next (struct ospf6_route *route)
                    677: {
                    678:   struct ospf6_route *next = route->next;
                    679: 
                    680:   if (IS_OSPF6_DEBUG_ROUTE (MEMORY))
                    681:     zlog_info ("%s %p: route next: %p<-[%p]->%p",
1.1.1.2 ! misho     682:                ospf6_route_table_name (route->table), (void *)route->table,
        !           683:                (void *)route->prev, (void *)route, (void *)route->next);
1.1       misho     684: 
                    685:   ospf6_route_unlock (route);
                    686:   if (next)
                    687:     ospf6_route_lock (next);
                    688: 
                    689:   return next;
                    690: }
                    691: 
                    692: struct ospf6_route *
                    693: ospf6_route_best_next (struct ospf6_route *route)
                    694: {
                    695:   struct route_node *rnode;
                    696:   struct ospf6_route *next;
                    697: 
                    698:   ospf6_route_unlock (route);
                    699: 
                    700:   rnode = route->rnode;
                    701:   route_lock_node (rnode);
                    702:   rnode = route_next (rnode);
                    703:   while (rnode && rnode->info == NULL)
                    704:     rnode = route_next (rnode);
                    705:   if (rnode == NULL)
                    706:     return NULL;
                    707:   route_unlock_node (rnode);
                    708: 
                    709:   assert (rnode->info);
                    710:   next = (struct ospf6_route *) rnode->info;
                    711:   ospf6_route_lock (next);
                    712:   return next;
                    713: }
                    714: 
                    715: struct ospf6_route *
                    716: ospf6_route_match_head (struct prefix *prefix,
                    717:                         struct ospf6_route_table *table)
                    718: {
                    719:   struct route_node *node;
                    720:   struct ospf6_route *route;
                    721: 
                    722:   /* Walk down tree. */
                    723:   node = table->table->top;
                    724:   while (node && node->p.prefixlen < prefix->prefixlen &&
                    725:         prefix_match (&node->p, prefix))
                    726:     node = node->link[prefix_bit(&prefix->u.prefix, node->p.prefixlen)];
                    727: 
                    728:   if (node)
                    729:     route_lock_node (node);
                    730:   while (node && node->info == NULL)
                    731:     node = route_next (node);
                    732:   if (node == NULL)
                    733:     return NULL;
                    734:   route_unlock_node (node);
                    735: 
                    736:   if (! prefix_match (prefix, &node->p))
                    737:     return NULL;
                    738: 
                    739:   route = node->info;
                    740:   ospf6_route_lock (route);
                    741:   return route;
                    742: }
                    743: 
                    744: struct ospf6_route *
                    745: ospf6_route_match_next (struct prefix *prefix,
                    746:                         struct ospf6_route *route)
                    747: {
                    748:   struct ospf6_route *next;
                    749: 
                    750:   next = ospf6_route_next (route);
                    751:   if (next && ! prefix_match (prefix, &next->prefix))
                    752:     {
                    753:       ospf6_route_unlock (next);
                    754:       next = NULL;
                    755:     }
                    756: 
                    757:   return next;
                    758: }
                    759: 
                    760: void
                    761: ospf6_route_remove_all (struct ospf6_route_table *table)
                    762: {
                    763:   struct ospf6_route *route;
                    764:   for (route = ospf6_route_head (table); route;
                    765:        route = ospf6_route_next (route))
                    766:     ospf6_route_remove (route, table);
                    767: }
                    768: 
                    769: struct ospf6_route_table *
                    770: ospf6_route_table_create (int s, int t)
                    771: {
                    772:   struct ospf6_route_table *new;
                    773:   new = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route_table));
                    774:   new->table = route_table_init ();
                    775:   new->scope_type = s;
                    776:   new->table_type = t;
                    777:   return new;
                    778: }
                    779: 
                    780: void
                    781: ospf6_route_table_delete (struct ospf6_route_table *table)
                    782: {
                    783:   ospf6_route_remove_all (table);
                    784:   route_table_finish (table->table);
                    785:   XFREE (MTYPE_OSPF6_ROUTE, table);
                    786: }
                    787: 
1.1.1.2 ! misho     788: 
1.1       misho     789: /* VTY commands */
                    790: void
                    791: ospf6_route_show (struct vty *vty, struct ospf6_route *route)
                    792: {
                    793:   int i;
                    794:   char destination[64], nexthop[64];
1.1.1.2 ! misho     795:   char duration[16];
        !           796:   const char *ifname;
1.1       misho     797:   struct timeval now, res;
                    798: 
                    799:   quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
                    800:   timersub (&now, &route->changed, &res);
                    801:   timerstring (&res, duration, sizeof (duration));
                    802: 
                    803:   /* destination */
                    804:   if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
                    805:     ospf6_linkstate_prefix2str (&route->prefix, destination,
                    806:                                 sizeof (destination));
                    807:   else if (route->type == OSPF6_DEST_TYPE_ROUTER)
                    808:     inet_ntop (route->prefix.family, &route->prefix.u.prefix,
                    809:                destination, sizeof (destination));
                    810:   else
                    811:     prefix2str (&route->prefix, destination, sizeof (destination));
                    812: 
                    813:   /* nexthop */
                    814:   inet_ntop (AF_INET6, &route->nexthop[0].address, nexthop,
                    815:              sizeof (nexthop));
1.1.1.2 ! misho     816:   ifname = ifindex2ifname (route->nexthop[0].ifindex);
1.1       misho     817: 
                    818:   vty_out (vty, "%c%1s %2s %-30s %-25s %6.*s %s%s",
                    819:            (ospf6_route_is_best (route) ? '*' : ' '),
                    820:            OSPF6_DEST_TYPE_SUBSTR (route->type),
                    821:            OSPF6_PATH_TYPE_SUBSTR (route->path.type),
                    822:            destination, nexthop, IFNAMSIZ, ifname, duration, VNL);
                    823: 
                    824:   for (i = 1; ospf6_nexthop_is_set (&route->nexthop[i]) &&
                    825:        i < OSPF6_MULTI_PATH_LIMIT; i++)
                    826:     {
                    827:       /* nexthop */
                    828:       inet_ntop (AF_INET6, &route->nexthop[i].address, nexthop,
                    829:                  sizeof (nexthop));
1.1.1.2 ! misho     830:       ifname = ifindex2ifname (route->nexthop[i].ifindex);
1.1       misho     831: 
                    832:       vty_out (vty, "%c%1s %2s %-30s %-25s %6.*s %s%s",
                    833:                ' ', "", "", "", nexthop, IFNAMSIZ, ifname, "", VNL);
                    834:     }
                    835: }
                    836: 
                    837: void
                    838: ospf6_route_show_detail (struct vty *vty, struct ospf6_route *route)
                    839: {
1.1.1.2 ! misho     840:   const char *ifname;
        !           841:   char destination[64], nexthop[64];
1.1       misho     842:   char area_id[16], id[16], adv_router[16], capa[16], options[16];
                    843:   struct timeval now, res;
                    844:   char duration[16];
                    845:   int i;
                    846: 
                    847:   quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
                    848: 
                    849:   /* destination */
                    850:   if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
                    851:     ospf6_linkstate_prefix2str (&route->prefix, destination,
                    852:                                 sizeof (destination));
                    853:   else if (route->type == OSPF6_DEST_TYPE_ROUTER)
                    854:     inet_ntop (route->prefix.family, &route->prefix.u.prefix,
                    855:                destination, sizeof (destination));
                    856:   else
                    857:     prefix2str (&route->prefix, destination, sizeof (destination));
                    858:   vty_out (vty, "Destination: %s%s", destination, VNL);
                    859: 
                    860:   /* destination type */
                    861:   vty_out (vty, "Destination type: %s%s",
                    862:            OSPF6_DEST_TYPE_NAME (route->type),
                    863:            VNL);
                    864: 
                    865:   /* Time */
                    866:   timersub (&now, &route->installed, &res);
                    867:   timerstring (&res, duration, sizeof (duration));
                    868:   vty_out (vty, "Installed Time: %s ago%s", duration, VNL);
                    869: 
                    870:   timersub (&now, &route->changed, &res);
                    871:   timerstring (&res, duration, sizeof (duration));
                    872:   vty_out (vty, "  Changed Time: %s ago%s", duration, VNL);
                    873: 
                    874:   /* Debugging info */
                    875:   vty_out (vty, "Lock: %d Flags: %s%s%s%s%s", route->lock,
                    876:            (CHECK_FLAG (route->flag, OSPF6_ROUTE_BEST)   ? "B" : "-"),
                    877:            (CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD)    ? "A" : "-"),
                    878:            (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE) ? "R" : "-"),
                    879:            (CHECK_FLAG (route->flag, OSPF6_ROUTE_CHANGE) ? "C" : "-"),
                    880:            VNL);
                    881:   vty_out (vty, "Memory: prev: %p this: %p next: %p%s",
1.1.1.2 ! misho     882:            (void *)route->prev, (void *)route, (void *)route->next, VNL);
1.1       misho     883: 
                    884:   /* Path section */
                    885: 
                    886:   /* Area-ID */
                    887:   inet_ntop (AF_INET, &route->path.area_id, area_id, sizeof (area_id));
                    888:   vty_out (vty, "Associated Area: %s%s", area_id, VNL);
                    889: 
                    890:   /* Path type */
                    891:   vty_out (vty, "Path Type: %s%s",
                    892:            OSPF6_PATH_TYPE_NAME (route->path.type), VNL);
                    893: 
                    894:   /* LS Origin */
                    895:   inet_ntop (AF_INET, &route->path.origin.id, id, sizeof (id));
                    896:   inet_ntop (AF_INET, &route->path.origin.adv_router, adv_router,
                    897:              sizeof (adv_router));
                    898:   vty_out (vty, "LS Origin: %s Id: %s Adv: %s%s",
                    899:            ospf6_lstype_name (route->path.origin.type),
                    900:            id, adv_router, VNL);
                    901: 
                    902:   /* Options */
                    903:   ospf6_options_printbuf (route->path.options, options, sizeof (options));
                    904:   vty_out (vty, "Options: %s%s", options, VNL);
                    905: 
                    906:   /* Router Bits */
                    907:   ospf6_capability_printbuf (route->path.router_bits, capa, sizeof (capa));
                    908:   vty_out (vty, "Router Bits: %s%s", capa, VNL);
                    909: 
                    910:   /* Prefix Options */
                    911:   vty_out (vty, "Prefix Options: xxx%s", VNL);
                    912: 
                    913:   /* Metrics */
                    914:   vty_out (vty, "Metric Type: %d%s", route->path.metric_type,
                    915:            VNL);
                    916:   vty_out (vty, "Metric: %d (%d)%s",
                    917:            route->path.cost, route->path.cost_e2, VNL);
                    918: 
                    919:   /* Nexthops */
                    920:   vty_out (vty, "Nexthop:%s", VNL);
                    921:   for (i = 0; ospf6_nexthop_is_set (&route->nexthop[i]) &&
                    922:        i < OSPF6_MULTI_PATH_LIMIT; i++)
                    923:     {
                    924:       /* nexthop */
                    925:       inet_ntop (AF_INET6, &route->nexthop[i].address, nexthop,
                    926:                  sizeof (nexthop));
1.1.1.2 ! misho     927:       ifname = ifindex2ifname (route->nexthop[i].ifindex);
1.1       misho     928:       vty_out (vty, "  %s %.*s%s", nexthop, IFNAMSIZ, ifname, VNL);
                    929:     }
                    930:   vty_out (vty, "%s", VNL);
                    931: }
                    932: 
                    933: static void
                    934: ospf6_route_show_table_summary (struct vty *vty,
                    935:                                 struct ospf6_route_table *table)
                    936: {
                    937:   struct ospf6_route *route, *prev = NULL;
                    938:   int i, pathtype[OSPF6_PATH_TYPE_MAX];
                    939:   unsigned int number = 0;
                    940:   int nhinval = 0, ecmp = 0;
                    941:   int alternative = 0, destination = 0;
                    942: 
                    943:   for (i = 0; i < OSPF6_PATH_TYPE_MAX; i++)
                    944:     pathtype[i] = 0;
                    945: 
                    946:   for (route = ospf6_route_head (table); route;
                    947:        route = ospf6_route_next (route))
                    948:     {
                    949:       if (prev == NULL || ! ospf6_route_is_same (prev, route))
                    950:         destination++;
                    951:       else
                    952:         alternative++;
                    953:       if (! ospf6_nexthop_is_set (&route->nexthop[0]))
                    954:         nhinval++;
                    955:       else if (ospf6_nexthop_is_set (&route->nexthop[1]))
                    956:         ecmp++;
                    957:       pathtype[route->path.type]++;
                    958:       number++;
                    959: 
                    960:       prev = route;
                    961:     }
                    962: 
                    963:   assert (number == table->count);
                    964: 
                    965:   vty_out (vty, "Number of OSPFv3 routes: %d%s", number, VNL);
                    966:   vty_out (vty, "Number of Destination: %d%s", destination, VNL);
                    967:   vty_out (vty, "Number of Alternative routes: %d%s", alternative, VNL);
                    968:   vty_out (vty, "Number of Equal Cost Multi Path: %d%s", ecmp, VNL);
                    969:   for (i = OSPF6_PATH_TYPE_INTRA; i <= OSPF6_PATH_TYPE_EXTERNAL2; i++)
                    970:     {
                    971:       vty_out (vty, "Number of %s routes: %d%s",
                    972:                OSPF6_PATH_TYPE_NAME (i), pathtype[i], VNL);
                    973:     }
                    974: }
                    975: 
                    976: static void
                    977: ospf6_route_show_table_prefix (struct vty *vty,
                    978:                                struct prefix *prefix,
                    979:                                struct ospf6_route_table *table)
                    980: {
                    981:   struct ospf6_route *route;
                    982: 
                    983:   route = ospf6_route_lookup (prefix, table);
                    984:   if (route == NULL)
                    985:     return;
                    986: 
                    987:   ospf6_route_lock (route);
                    988:   while (route && ospf6_route_is_prefix (prefix, route))
                    989:     {
                    990:       /* Specifying a prefix will always display details */
                    991:       ospf6_route_show_detail (vty, route);
                    992:       route = ospf6_route_next (route);
                    993:     }
                    994:   if (route)
                    995:     ospf6_route_unlock (route);
                    996: }
                    997: 
                    998: static void
                    999: ospf6_route_show_table_address (struct vty *vty,
                   1000:                                 struct prefix *prefix,
                   1001:                                 struct ospf6_route_table *table)
                   1002: {
                   1003:   struct ospf6_route *route;
                   1004: 
                   1005:   route = ospf6_route_lookup_bestmatch (prefix, table);
                   1006:   if (route == NULL)
                   1007:     return;
                   1008: 
                   1009:   prefix = &route->prefix;
                   1010:   ospf6_route_lock (route);
                   1011:   while (route && ospf6_route_is_prefix (prefix, route))
                   1012:     {
                   1013:       /* Specifying a prefix will always display details */
                   1014:       ospf6_route_show_detail (vty, route);
                   1015:       route = ospf6_route_next (route);
                   1016:     }
                   1017:   if (route)
                   1018:     ospf6_route_unlock (route);
                   1019: }
                   1020: 
                   1021: static void
                   1022: ospf6_route_show_table_match (struct vty *vty, int detail,
                   1023:                               struct prefix *prefix,
                   1024:                               struct ospf6_route_table *table)
                   1025: {
                   1026:   struct ospf6_route *route;
                   1027:   assert (prefix->family);
                   1028: 
                   1029:   route = ospf6_route_match_head (prefix, table);
                   1030:   while (route)
                   1031:     {
                   1032:       if (detail)
                   1033:         ospf6_route_show_detail (vty, route);
                   1034:       else
                   1035:         ospf6_route_show (vty, route);
                   1036:       route = ospf6_route_match_next (prefix, route);
                   1037:     }
                   1038: }
                   1039: 
                   1040: static void
                   1041: ospf6_route_show_table_type (struct vty *vty, int detail, u_char type,
                   1042:                              struct ospf6_route_table *table)
                   1043: {
                   1044:   struct ospf6_route *route;
                   1045: 
                   1046:   route = ospf6_route_head (table);
                   1047:   while (route)
                   1048:     {
                   1049:       if (route->path.type == type)
                   1050:         {
                   1051:           if (detail)
                   1052:             ospf6_route_show_detail (vty, route);
                   1053:           else
                   1054:             ospf6_route_show (vty, route);
                   1055:         }
                   1056:       route = ospf6_route_next (route);
                   1057:     }
                   1058: }
                   1059: 
                   1060: static void
                   1061: ospf6_route_show_table (struct vty *vty, int detail,
                   1062:                         struct ospf6_route_table *table)
                   1063: {
                   1064:   struct ospf6_route *route;
                   1065: 
                   1066:   route = ospf6_route_head (table);
                   1067:   while (route)
                   1068:     {
                   1069:       if (detail)
                   1070:         ospf6_route_show_detail (vty, route);
                   1071:       else
                   1072:         ospf6_route_show (vty, route);
                   1073:       route = ospf6_route_next (route);
                   1074:     }
                   1075: }
                   1076: 
                   1077: int
                   1078: ospf6_route_table_show (struct vty *vty, int argc, const char *argv[],
                   1079:                         struct ospf6_route_table *table)
                   1080: {
                   1081:   int summary = 0;
                   1082:   int match = 0;
                   1083:   int detail = 0;
                   1084:   int slash = 0;
                   1085:   int isprefix = 0;
                   1086:   int i, ret;
                   1087:   struct prefix prefix;
                   1088:   u_char type = 0;
                   1089: 
                   1090:   memset (&prefix, 0, sizeof (struct prefix));
                   1091: 
                   1092:   for (i = 0; i < argc; i++)
                   1093:     {
                   1094:       if (! strcmp (argv[i], "summary"))
                   1095:         {
                   1096:           summary++;
                   1097:           continue;
                   1098:         }
                   1099: 
                   1100:       if (! strcmp (argv[i], "intra-area"))
                   1101:         {
                   1102:           type = OSPF6_PATH_TYPE_INTRA;
                   1103:           continue;
                   1104:         }
                   1105: 
                   1106:       if (! strcmp (argv[i], "inter-area"))
                   1107:         {
                   1108:           type = OSPF6_PATH_TYPE_INTER;
                   1109:           continue;
                   1110:         }
                   1111: 
                   1112:       if (! strcmp (argv[i], "external-1"))
                   1113:         {
                   1114:           type = OSPF6_PATH_TYPE_EXTERNAL1;
                   1115:           continue;
                   1116:         }
                   1117: 
                   1118:       if (! strcmp (argv[i], "external-2"))
                   1119:         {
                   1120:           type = OSPF6_PATH_TYPE_EXTERNAL2;
                   1121:           continue;
                   1122:         }
                   1123: 
                   1124:       if (! strcmp (argv[i], "detail"))
                   1125:         {
                   1126:           detail++;
                   1127:           continue;
                   1128:         }
                   1129: 
                   1130:       if (! strcmp (argv[i], "match"))
                   1131:         {
                   1132:           match++;
                   1133:           continue;
                   1134:         }
                   1135: 
                   1136:       ret = str2prefix (argv[i], &prefix);
                   1137:       if (ret == 1 && prefix.family == AF_INET6)
                   1138:         {
                   1139:           isprefix++;
                   1140:           if (strchr (argv[i], '/'))
                   1141:             slash++;
                   1142:           continue;
                   1143:         }
                   1144: 
                   1145:       vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
                   1146:       return CMD_SUCCESS;
                   1147:     }
                   1148: 
                   1149:   /* Give summary of this route table */
                   1150:   if (summary)
                   1151:     {
                   1152:       ospf6_route_show_table_summary (vty, table);
                   1153:       return CMD_SUCCESS;
                   1154:     }
                   1155: 
                   1156:   /* Give exact prefix-match route */
                   1157:   if (isprefix && ! match)
                   1158:     {
                   1159:       /* If exact address, give best matching route */
                   1160:       if (! slash)
                   1161:         ospf6_route_show_table_address (vty, &prefix, table);
                   1162:       else
                   1163:         ospf6_route_show_table_prefix (vty, &prefix, table);
                   1164: 
                   1165:       return CMD_SUCCESS;
                   1166:     }
                   1167: 
                   1168:   if (match)
                   1169:     ospf6_route_show_table_match (vty, detail, &prefix, table);
                   1170:   else if (type)
                   1171:     ospf6_route_show_table_type (vty, detail, type, table);
                   1172:   else
                   1173:     ospf6_route_show_table (vty, detail, table);
                   1174: 
                   1175:   return CMD_SUCCESS;
                   1176: }
                   1177: 
                   1178: static void
                   1179: ospf6_linkstate_show_header (struct vty *vty)
                   1180: {
                   1181:   vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %s%s",
                   1182:            "Type", "Router-ID", "Net-ID", "Rtr-Bits", "Options", "Cost", VNL);
                   1183: }
                   1184: 
                   1185: static void
                   1186: ospf6_linkstate_show (struct vty *vty, struct ospf6_route *route)
                   1187: {
                   1188:   u_int32_t router, id;
                   1189:   char routername[16], idname[16], rbits[16], options[16];
                   1190: 
                   1191:   router = ospf6_linkstate_prefix_adv_router (&route->prefix);
                   1192:   inet_ntop (AF_INET, &router, routername, sizeof (routername));
                   1193:   id = ospf6_linkstate_prefix_id (&route->prefix);
                   1194:   inet_ntop (AF_INET, &id, idname, sizeof (idname));
                   1195: 
                   1196:   ospf6_capability_printbuf (route->path.router_bits, rbits, sizeof (rbits));
                   1197:   ospf6_options_printbuf (route->path.options, options, sizeof (options));
                   1198: 
                   1199:   if (ntohl (id))
                   1200:     vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %lu%s",
                   1201:              "Network", routername, idname, rbits, options,
                   1202:              (unsigned long) route->path.cost, VNL);
                   1203:   else
                   1204:     vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %lu%s",
                   1205:              "Router", routername, idname, rbits, options,
                   1206:              (unsigned long) route->path.cost, VNL);
                   1207: }
                   1208: 
                   1209: 
                   1210: static void
                   1211: ospf6_linkstate_show_table_exact (struct vty *vty,
                   1212:                                   struct prefix *prefix,
                   1213:                                   struct ospf6_route_table *table)
                   1214: {
                   1215:   struct ospf6_route *route;
                   1216: 
                   1217:   route = ospf6_route_lookup (prefix, table);
                   1218:   if (route == NULL)
                   1219:     return;
                   1220: 
                   1221:   ospf6_route_lock (route);
                   1222:   while (route && ospf6_route_is_prefix (prefix, route))
                   1223:     {
                   1224:       /* Specifying a prefix will always display details */
                   1225:       ospf6_route_show_detail (vty, route);
                   1226:       route = ospf6_route_next (route);
                   1227:     }
                   1228:   if (route)
                   1229:     ospf6_route_unlock (route);
                   1230: }
                   1231: 
                   1232: static void
                   1233: ospf6_linkstate_show_table (struct vty *vty, int detail,
                   1234:                             struct ospf6_route_table *table)
                   1235: {
                   1236:   struct ospf6_route *route;
                   1237: 
                   1238:   if (! detail)
                   1239:     ospf6_linkstate_show_header (vty);
                   1240: 
                   1241:   route = ospf6_route_head (table);
                   1242:   while (route)
                   1243:     {
                   1244:       if (detail)
                   1245:         ospf6_route_show_detail (vty, route);
                   1246:       else
                   1247:         ospf6_linkstate_show (vty, route);
                   1248:       route = ospf6_route_next (route);
                   1249:     }
                   1250: }
                   1251: 
                   1252: int
                   1253: ospf6_linkstate_table_show (struct vty *vty, int argc, const char *argv[],
                   1254:                             struct ospf6_route_table *table)
                   1255: {
                   1256:   int detail = 0;
                   1257:   int is_id = 0;
                   1258:   int is_router = 0;
                   1259:   int i, ret;
                   1260:   struct prefix router, id, prefix;
                   1261: 
                   1262:   memset (&router, 0, sizeof (struct prefix));
                   1263:   memset (&id, 0, sizeof (struct prefix));
                   1264:   memset (&prefix, 0, sizeof (struct prefix));
                   1265: 
                   1266:   for (i = 0; i < argc; i++)
                   1267:     {
                   1268:       if (! strcmp (argv[i], "detail"))
                   1269:         {
                   1270:           detail++;
                   1271:           continue;
                   1272:         }
                   1273: 
                   1274:       if (! is_router)
                   1275:         {
                   1276:           ret = str2prefix (argv[i], &router);
                   1277:           if (ret == 1 && router.family == AF_INET)
                   1278:             {
                   1279:               is_router++;
                   1280:               continue;
                   1281:             }
                   1282:           vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
                   1283:           return CMD_SUCCESS;
                   1284:         }
                   1285: 
                   1286:       if (! is_id)
                   1287:         {
                   1288:           ret = str2prefix (argv[i], &id);
                   1289:           if (ret == 1 && id.family == AF_INET)
                   1290:             {
                   1291:               is_id++;
                   1292:               continue;
                   1293:             }
                   1294:           vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
                   1295:           return CMD_SUCCESS;
                   1296:         }
                   1297: 
                   1298:       vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
                   1299:       return CMD_SUCCESS;
                   1300:     }
                   1301: 
                   1302:   if (is_router)
                   1303:     ospf6_linkstate_prefix (router.u.prefix4.s_addr,
                   1304:                             id.u.prefix4.s_addr, &prefix);
                   1305: 
                   1306:   if (prefix.family)
                   1307:     ospf6_linkstate_show_table_exact (vty, &prefix, table);
                   1308:   else
                   1309:     ospf6_linkstate_show_table (vty, detail, table);
                   1310: 
                   1311:   return CMD_SUCCESS;
                   1312: }
                   1313: 
                   1314: 
                   1315: void
                   1316: ospf6_brouter_show_header (struct vty *vty)
                   1317: {
                   1318:   vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
                   1319:            "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL);
                   1320: }
                   1321: 
                   1322: void
                   1323: ospf6_brouter_show (struct vty *vty, struct ospf6_route *route)
                   1324: {
                   1325:   u_int32_t adv_router;
                   1326:   char adv[16], rbits[16], options[16], area[16];
                   1327: 
                   1328:   adv_router = ospf6_linkstate_prefix_adv_router (&route->prefix);
                   1329:   inet_ntop (AF_INET, &adv_router, adv, sizeof (adv));
                   1330:   ospf6_capability_printbuf (route->path.router_bits, rbits, sizeof (rbits));
                   1331:   ospf6_options_printbuf (route->path.options, options, sizeof (options));
                   1332:   inet_ntop (AF_INET, &route->path.area_id, area, sizeof (area));
                   1333: 
                   1334:   /* vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
                   1335:            "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL); */
                   1336:   vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
                   1337:            adv, rbits, options, OSPF6_PATH_TYPE_NAME (route->path.type),
                   1338:            area, VNL);
                   1339: }
                   1340: 
                   1341: DEFUN (debug_ospf6_route,
                   1342:        debug_ospf6_route_cmd,
                   1343:        "debug ospf6 route (table|intra-area|inter-area|memory)",
                   1344:        DEBUG_STR
                   1345:        OSPF6_STR
                   1346:        "Debug route table calculation\n"
                   1347:        "Debug detail\n"
                   1348:        "Debug intra-area route calculation\n"
                   1349:        "Debug inter-area route calculation\n"
                   1350:        "Debug route memory use\n"
                   1351:        )
                   1352: {
                   1353:   unsigned char level = 0;
                   1354: 
                   1355:   if (! strncmp (argv[0], "table", 5))
                   1356:     level = OSPF6_DEBUG_ROUTE_TABLE;
                   1357:   else if (! strncmp (argv[0], "intra", 5))
                   1358:     level = OSPF6_DEBUG_ROUTE_INTRA;
                   1359:   else if (! strncmp (argv[0], "inter", 5))
                   1360:     level = OSPF6_DEBUG_ROUTE_INTER;
                   1361:   else if (! strncmp (argv[0], "memor", 5))
                   1362:     level = OSPF6_DEBUG_ROUTE_MEMORY;
                   1363:   OSPF6_DEBUG_ROUTE_ON (level);
                   1364:   return CMD_SUCCESS;
                   1365: }
                   1366: 
                   1367: DEFUN (no_debug_ospf6_route,
                   1368:        no_debug_ospf6_route_cmd,
                   1369:        "no debug ospf6 route (table|intra-area|inter-area|memory)",
                   1370:        NO_STR
                   1371:        DEBUG_STR
                   1372:        OSPF6_STR
                   1373:        "Debug route table calculation\n"
                   1374:        "Debug intra-area route calculation\n"
                   1375:        "Debug route memory use\n")
                   1376: {
                   1377:   unsigned char level = 0;
                   1378: 
                   1379:   if (! strncmp (argv[0], "table", 5))
                   1380:     level = OSPF6_DEBUG_ROUTE_TABLE;
                   1381:   else if (! strncmp (argv[0], "intra", 5))
                   1382:     level = OSPF6_DEBUG_ROUTE_INTRA;
                   1383:   else if (! strncmp (argv[0], "inter", 5))
                   1384:     level = OSPF6_DEBUG_ROUTE_INTER;
                   1385:   else if (! strncmp (argv[0], "memor", 5))
                   1386:     level = OSPF6_DEBUG_ROUTE_MEMORY;
                   1387:   OSPF6_DEBUG_ROUTE_OFF (level);
                   1388:   return CMD_SUCCESS;
                   1389: }
                   1390: 
                   1391: int
                   1392: config_write_ospf6_debug_route (struct vty *vty)
                   1393: {
                   1394:   if (IS_OSPF6_DEBUG_ROUTE (TABLE))
                   1395:     vty_out (vty, "debug ospf6 route table%s", VNL);
                   1396:   if (IS_OSPF6_DEBUG_ROUTE (INTRA))
                   1397:     vty_out (vty, "debug ospf6 route intra-area%s", VNL);
                   1398:   if (IS_OSPF6_DEBUG_ROUTE (INTER))
                   1399:     vty_out (vty, "debug ospf6 route inter-area%s", VNL);
                   1400:   return 0;
                   1401: }
                   1402: 
                   1403: void
                   1404: install_element_ospf6_debug_route (void)
                   1405: {
                   1406:   install_element (ENABLE_NODE, &debug_ospf6_route_cmd);
                   1407:   install_element (ENABLE_NODE, &no_debug_ospf6_route_cmd);
                   1408:   install_element (CONFIG_NODE, &debug_ospf6_route_cmd);
                   1409:   install_element (CONFIG_NODE, &no_debug_ospf6_route_cmd);
                   1410: }
                   1411: 
                   1412: 
                   1413: 

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