Annotation of embedaddon/quagga/ospf6d/ospf6_route.c, revision 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>