ospf6_route.c
上传用户:xiaozhuqw
上传日期:2009-11-15
资源大小:1338k
文件大小:32k
源码类别:

网络

开发平台:

Unix_Linux

  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. #include <zebra.h>
  22. #include "log.h"
  23. #include "memory.h"
  24. #include "prefix.h"
  25. #include "table.h"
  26. #include "vty.h"
  27. #include "command.h"
  28. #include "ospf6_proto.h"
  29. #include "ospf6_lsa.h"
  30. #include "ospf6_lsdb.h"
  31. #include "ospf6_route.h"
  32. #include "ospf6d.h"
  33. unsigned char conf_debug_ospf6_route = 0;
  34. void
  35. ospf6_linkstate_prefix (u_int32_t adv_router, u_int32_t id,
  36.                         struct prefix *prefix)
  37. {
  38.   memset (prefix, 0, sizeof (struct prefix));
  39.   prefix->family = AF_INET6;
  40.   prefix->prefixlen = 64;
  41.   memcpy (&prefix->u.prefix6.s6_addr[0], &adv_router, 4);
  42.   memcpy (&prefix->u.prefix6.s6_addr[4], &id, 4);
  43. }
  44. void
  45. ospf6_linkstate_prefix2str (struct prefix *prefix, char *buf, int size)
  46. {
  47.   u_int32_t adv_router, id;
  48.   char adv_router_str[16], id_str[16];
  49.   memcpy (&adv_router, &prefix->u.prefix6.s6_addr[0], 4);
  50.   memcpy (&id, &prefix->u.prefix6.s6_addr[4], 4);
  51.   inet_ntop (AF_INET, &adv_router, adv_router_str, sizeof (adv_router_str));
  52.   inet_ntop (AF_INET, &id, id_str, sizeof (id_str));
  53.   if (ntohl (id))
  54.     snprintf (buf, size, "%s Net-ID: %s", adv_router_str, id_str);
  55.   else
  56.     snprintf (buf, size, "%s", adv_router_str);
  57. }
  58. /* Global strings for logging */
  59. char *ospf6_dest_type_str[OSPF6_DEST_TYPE_MAX] =
  60. { "Unknown", "Router", "Network", "Discard", "Linkstate", "AddressRange", };
  61. char *ospf6_dest_type_substr[OSPF6_DEST_TYPE_MAX] =
  62. { "?", "R", "N", "D", "L", "A", };
  63. char *ospf6_path_type_str[OSPF6_PATH_TYPE_MAX] =
  64. { "Unknown", "Intra-Area", "Inter-Area", "External-1", "External-2", };
  65. char *ospf6_path_type_substr[OSPF6_PATH_TYPE_MAX] =
  66. { "??", "IA", "IE", "E1", "E2", };
  67. struct ospf6_route *
  68. ospf6_route_create ()
  69. {
  70.   struct ospf6_route *route;
  71.   route = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route));
  72.   return route;
  73. }
  74. void
  75. ospf6_route_delete (struct ospf6_route *route)
  76. {
  77.   XFREE (MTYPE_OSPF6_ROUTE, route);
  78. }
  79. struct ospf6_route *
  80. ospf6_route_copy (struct ospf6_route *route)
  81. {
  82.   struct ospf6_route *new;
  83.   new = ospf6_route_create ();
  84.   memcpy (new, route, sizeof (struct ospf6_route));
  85.   new->rnode = NULL;
  86.   new->prev = NULL;
  87.   new->next = NULL;
  88.   new->lock = 0;
  89.   return new;
  90. }
  91. void
  92. ospf6_route_lock (struct ospf6_route *route)
  93. {
  94.   route->lock++;
  95. }
  96. void
  97. ospf6_route_unlock (struct ospf6_route *route)
  98. {
  99.   assert (route->lock > 0);
  100.   route->lock--;
  101.   if (route->lock == 0)
  102.     ospf6_route_delete (route);
  103. }
  104. /* Route compare function. If ra is more preferred, it returns
  105.    less than 0. If rb is more preferred returns greater than 0.
  106.    Otherwise (neither one is preferred), returns 0 */
  107. static int
  108. ospf6_route_cmp (struct ospf6_route *ra, struct ospf6_route *rb)
  109. {
  110.   assert (ospf6_route_is_same (ra, rb));
  111.   assert (OSPF6_PATH_TYPE_NONE < ra->path.type &&
  112.           ra->path.type < OSPF6_PATH_TYPE_MAX);
  113.   assert (OSPF6_PATH_TYPE_NONE < rb->path.type &&
  114.           rb->path.type < OSPF6_PATH_TYPE_MAX);
  115.   if (ra->type != rb->type)
  116.     return (ra->type - rb->type);
  117.   if (ra->path.area_id != rb->path.area_id)
  118.     return (ntohl (ra->path.area_id) - ntohl (rb->path.area_id));
  119.   if (ra->path.type != rb->path.type)
  120.     return (ra->path.type - rb->path.type);
  121.   if (ra->path.type == OSPF6_PATH_TYPE_EXTERNAL2)
  122.     {
  123.       if (ra->path.cost_e2 != rb->path.cost_e2)
  124.         return (ra->path.cost_e2 - rb->path.cost_e2);
  125.     }
  126.   else
  127.     {
  128.       if (ra->path.cost != rb->path.cost)
  129.         return (ra->path.cost - rb->path.cost);
  130.     }
  131.   return 0;
  132. }
  133. struct ospf6_route *
  134. ospf6_route_lookup (struct prefix *prefix,
  135.                     struct ospf6_route_table *table)
  136. {
  137.   struct route_node *node;
  138.   struct ospf6_route *route;
  139.   node = route_node_lookup (table->table, prefix);
  140.   if (node == NULL)
  141.     return NULL;
  142.   route = (struct ospf6_route *) node->info;
  143.   return route;
  144. }
  145. struct ospf6_route *
  146. ospf6_route_lookup_identical (struct ospf6_route *route,
  147.                               struct ospf6_route_table *table)
  148. {
  149.   struct ospf6_route *target;
  150.   for (target = ospf6_route_lookup (&route->prefix, table);
  151.        target; target = target->next)
  152.     {
  153.       if (ospf6_route_is_identical (target, route))
  154.         return target;
  155.     }
  156.   return NULL;
  157. }
  158. struct ospf6_route *
  159. ospf6_route_lookup_bestmatch (struct prefix *prefix,
  160.                               struct ospf6_route_table *table)
  161. {
  162.   struct route_node *node;
  163.   struct ospf6_route *route;
  164.   node = route_node_match (table->table, prefix);
  165.   if (node == NULL)
  166.     return NULL;
  167.   route_unlock_node (node);
  168.   route = (struct ospf6_route *) node->info;
  169.   return route;
  170. }
  171. #ifndef NDEBUG
  172. static void
  173. _route_count_assert (struct ospf6_route_table *table)
  174. {
  175.   struct ospf6_route *debug;
  176.   char buf[64];
  177.   int num = 0;
  178.   for (debug = ospf6_route_head (table); debug;
  179.        debug = ospf6_route_next (debug))
  180.     num++;
  181.   if (num == table->count)
  182.     return;
  183.   zlog_info ("PANIC !! table[%p]->count = %d, real = %d",
  184.              table, table->count, num);
  185.   for (debug = ospf6_route_head (table); debug;
  186.        debug = ospf6_route_next (debug))
  187.     {
  188.       prefix2str (&debug->prefix, buf, sizeof (buf));
  189.       zlog_info ("%p %p %s", debug->prev, debug->next, buf);
  190.     }
  191.   zlog_info ("DUMP END");
  192.   assert (num == table->count);
  193. }
  194. #define ospf6_route_count_assert(t) (_route_count_assert (t))
  195. #else
  196. #define ospf6_route_count_assert(t) ((void) 0)
  197. #endif /*NDEBUG*/
  198. struct ospf6_route *
  199. ospf6_route_add (struct ospf6_route *route,
  200.                  struct ospf6_route_table *table)
  201. {
  202.   struct route_node *node, *nextnode, *prevnode;
  203.   struct ospf6_route *current = NULL;
  204.   struct ospf6_route *prev = NULL, *old = NULL, *next = NULL;
  205.   char buf[64];
  206.   struct timeval now;
  207.   assert (route->rnode == NULL);
  208.   assert (route->lock == 0);
  209.   assert (route->next == NULL);
  210.   assert (route->prev == NULL);
  211.   if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
  212.     ospf6_linkstate_prefix2str (&route->prefix, buf, sizeof (buf));
  213.   else
  214.     prefix2str (&route->prefix, buf, sizeof (buf));
  215.   if (IS_OSPF6_DEBUG_ROUTE (TABLE))
  216.     zlog_info ("route add %s", buf);
  217.   gettimeofday (&now, NULL);
  218.   node = route_node_get (table->table, &route->prefix);
  219.   route->rnode = node;
  220.   /* find place to insert */
  221.   for (current = node->info; current; current = current->next)
  222.     {
  223.       if (! ospf6_route_is_same (current, route))
  224.         next = current;
  225.       else if (current->type != route->type)
  226.         prev = current;
  227.       else if (ospf6_route_is_same_origin (current, route))
  228.         old = current;
  229.       else if (ospf6_route_cmp (current, route) > 0)
  230.         next = current;
  231.       else
  232.         prev = current;
  233.       if (old || next)
  234.         break;
  235.     }
  236.   if (old)
  237.     {
  238.       /* if route does not actually change, return unchanged */
  239.       if (ospf6_route_is_identical (old, route))
  240.         {
  241.           if (IS_OSPF6_DEBUG_ROUTE (TABLE))
  242.             zlog_info ("  identical route found, ignore");
  243.           ospf6_route_delete (route);
  244.           SET_FLAG (old->flag, OSPF6_ROUTE_ADD);
  245.           ospf6_route_count_assert (table);
  246.           return old;
  247.         }
  248.       if (IS_OSPF6_DEBUG_ROUTE (TABLE))
  249.         zlog_info ("  old route found, replace");
  250.       /* replace old one if exists */
  251.       if (node->info == old)
  252.         {
  253.           node->info = route;
  254.           SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
  255.         }
  256.       if (old->prev)
  257.         old->prev->next = route;
  258.       route->prev = old->prev;
  259.       if (old->next)
  260.         old->next->prev = route;
  261.       route->next = old->next;
  262.       route->installed = old->installed;
  263.       route->changed = now;
  264.       ospf6_route_unlock (old); /* will be deleted later */
  265.       ospf6_route_lock (route);
  266.       SET_FLAG (route->flag, OSPF6_ROUTE_CHANGE);
  267.       ospf6_route_count_assert (table);
  268.       if (table->hook_add)
  269.         (*table->hook_add) (route);
  270.       return route;
  271.     }
  272.   /* insert if previous or next node found */
  273.   if (prev || next)
  274.     {
  275.       if (IS_OSPF6_DEBUG_ROUTE (TABLE))
  276.         zlog_info ("  another path found, insert");
  277.       if (prev == NULL)
  278.         prev = next->prev;
  279.       if (next == NULL)
  280.         next = prev->next;
  281.       if (prev)
  282.         prev->next = route;
  283.       route->prev = prev;
  284.       if (next)
  285.         next->prev = route;
  286.       route->next = next;
  287.       if (node->info == next)
  288.         {
  289.           assert (next->rnode == node);
  290.           node->info = route;
  291.           UNSET_FLAG (next->flag, OSPF6_ROUTE_BEST);
  292.           SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
  293.         }
  294.       route->installed = now;
  295.       route->changed = now;
  296.       ospf6_route_lock (route);
  297.       table->count++;
  298.       ospf6_route_count_assert (table);
  299.       SET_FLAG (route->flag, OSPF6_ROUTE_ADD);
  300.       if (table->hook_add)
  301.         (*table->hook_add) (route);
  302.       return route;
  303.     }
  304.   /* Else, this is the brand new route regarding to the prefix */
  305.   if (IS_OSPF6_DEBUG_ROUTE (TABLE))
  306.     zlog_info ("  brand new route, add");
  307.   assert (node->info == NULL);
  308.   node->info = route;
  309.   SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
  310.   ospf6_route_lock (route);
  311.   route->installed = now;
  312.   route->changed = now;
  313.   /* lookup real existing next route */
  314.   nextnode = node;
  315.   route_lock_node (nextnode);
  316.   do {
  317.     nextnode = route_next (nextnode);
  318.   } while (nextnode && nextnode->info == NULL);
  319.   /* set next link */
  320.   if (nextnode == NULL)
  321.     route->next = NULL;
  322.   else
  323.     {
  324.       route_unlock_node (nextnode);
  325.       next = nextnode->info;
  326.       route->next = next;
  327.       next->prev = route;
  328.     }
  329.   /* lookup real existing prev route */
  330.   prevnode = node;
  331.   route_lock_node (prevnode);
  332.   do {
  333.     prevnode = route_prev (prevnode);
  334.   } while (prevnode && prevnode->info == NULL);
  335.   /* set prev link */
  336.   if (prevnode == NULL)
  337.     route->prev = NULL;
  338.   else
  339.     {
  340.       route_unlock_node (prevnode);
  341.       prev = prevnode->info;
  342.       while (prev->next && ospf6_route_is_same (prev, prev->next))
  343.         prev = prev->next;
  344.       route->prev = prev;
  345.       prev->next = route;
  346.     }
  347.   table->count++;
  348.   ospf6_route_count_assert (table);
  349.   SET_FLAG (route->flag, OSPF6_ROUTE_ADD);
  350.   if (table->hook_add)
  351.     (*table->hook_add) (route);
  352.   return route;
  353. }
  354. void
  355. ospf6_route_remove (struct ospf6_route *route,
  356.                     struct ospf6_route_table *table)
  357. {
  358.   struct route_node *node;
  359.   struct ospf6_route *current;
  360.   char buf[64];
  361.   if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
  362.     ospf6_linkstate_prefix2str (&route->prefix, buf, sizeof (buf));
  363.   else
  364.     prefix2str (&route->prefix, buf, sizeof (buf));
  365.   if (IS_OSPF6_DEBUG_ROUTE (TABLE))
  366.     zlog_info ("route remove: %s", buf);
  367.   node = route_node_lookup (table->table, &route->prefix);
  368.   assert (node);
  369.   /* find the route to remove, making sure that the route pointer
  370.      is from the route table. */
  371.   current = node->info;
  372.   while (current && ospf6_route_is_same (current, route))
  373.     {
  374.       if (current == route)
  375.         break;
  376.       current = current->next;
  377.     }
  378.   assert (current == route);
  379.   /* adjust doubly linked list */
  380.   if (route->prev)
  381.     route->prev->next = route->next;
  382.   if (route->next)
  383.     route->next->prev = route->prev;
  384.   if (node->info == route)
  385.     {
  386.       if (route->next && ospf6_route_is_same (route->next, route))
  387.         {
  388.           node->info = route->next;
  389.           SET_FLAG (route->next->flag, OSPF6_ROUTE_BEST);
  390.         }
  391.       else
  392.         node->info = NULL; /* should unlock route_node here ? */
  393.     }
  394.   table->count--;
  395.   ospf6_route_count_assert (table);
  396.   SET_FLAG (route->flag, OSPF6_ROUTE_WAS_REMOVED);
  397.   if (table->hook_remove)
  398.     (*table->hook_remove) (route);
  399.   ospf6_route_unlock (route);
  400. }
  401. struct ospf6_route *
  402. ospf6_route_head (struct ospf6_route_table *table)
  403. {
  404.   struct route_node *node;
  405.   struct ospf6_route *route;
  406.   node = route_top (table->table);
  407.   if (node == NULL)
  408.     return NULL;
  409.   /* skip to the real existing entry */
  410.   while (node && node->info == NULL)
  411.     node = route_next (node);
  412.   if (node == NULL)
  413.     return NULL;
  414.   route_unlock_node (node);
  415.   assert (node->info);
  416.   route = (struct ospf6_route *) node->info;
  417.   assert (route->prev == NULL);
  418.   ospf6_route_lock (route);
  419.   return route;
  420. }
  421. struct ospf6_route *
  422. ospf6_route_next (struct ospf6_route *route)
  423. {
  424.   struct ospf6_route *next = route->next;
  425.   ospf6_route_unlock (route);
  426.   if (next)
  427.     ospf6_route_lock (next);
  428.   return next;
  429. }
  430. struct ospf6_route *
  431. ospf6_route_best_next (struct ospf6_route *route)
  432. {
  433.   struct route_node *rnode;
  434.   struct ospf6_route *next;
  435.   rnode = route->rnode;
  436.   route_lock_node (rnode);
  437.   rnode = route_next (rnode);
  438.   while (rnode && rnode->info == NULL)
  439.     rnode = route_next (rnode);
  440.   if (rnode == NULL)
  441.     return NULL;
  442.   route_unlock_node (rnode);
  443.   assert (rnode->info);
  444.   next = (struct ospf6_route *) rnode->info;
  445.   ospf6_route_unlock (route);
  446.   ospf6_route_lock (next);
  447.   return next;
  448. }
  449. /* Macro version of check_bit (). */
  450. #define CHECK_BIT(X,P) ((((u_char *)(X))[(P) / 8]) >> (7 - ((P) % 8)) & 1)
  451. struct ospf6_route *
  452. ospf6_route_match_head (struct prefix *prefix,
  453.                         struct ospf6_route_table *table)
  454. {
  455.   struct route_node *node;
  456.   struct ospf6_route *route;
  457.   /* Walk down tree. */
  458.   node = table->table->top;
  459.   while (node && node->p.prefixlen < prefix->prefixlen &&
  460.  prefix_match (&node->p, prefix))
  461.     node = node->link[CHECK_BIT(&prefix->u.prefix, node->p.prefixlen)];
  462.   if (node)
  463.     route_lock_node (node);
  464.   while (node && node->info == NULL)
  465.     node = route_next (node);
  466.   if (node == NULL)
  467.     return NULL;
  468.   route_unlock_node (node);
  469.   if (! prefix_match (prefix, &node->p))
  470.     return NULL;
  471.   route = node->info;
  472.   ospf6_route_lock (route);
  473.   return route;
  474. }
  475. struct ospf6_route *
  476. ospf6_route_match_next (struct prefix *prefix,
  477.                         struct ospf6_route *route)
  478. {
  479.   struct ospf6_route *next;
  480.   next = ospf6_route_next (route);
  481.   if (next && ! prefix_match (prefix, &next->prefix))
  482.     {
  483.       ospf6_route_unlock (next);
  484.       next = NULL;
  485.     }
  486.   return next;
  487. }
  488. void
  489. ospf6_route_remove_all (struct ospf6_route_table *table)
  490. {
  491.   struct ospf6_route *route;
  492.   for (route = ospf6_route_head (table); route;
  493.        route = ospf6_route_next (route))
  494.     ospf6_route_remove (route, table);
  495. }
  496. struct ospf6_route_table *
  497. ospf6_route_table_create ()
  498. {
  499.   struct ospf6_route_table *new;
  500.   new = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route_table));
  501.   new->table = route_table_init ();
  502.   return new;
  503. }
  504. void
  505. ospf6_route_table_delete (struct ospf6_route_table *table)
  506. {
  507.   ospf6_route_remove_all (table);
  508.   route_table_finish (table->table);
  509.   XFREE (MTYPE_OSPF6_ROUTE, table);
  510. }
  511. /* VTY commands */
  512. void
  513. ospf6_route_show (struct vty *vty, struct ospf6_route *route)
  514. {
  515.   int i;
  516.   char destination[64], nexthop[64];
  517.   char duration[16], ifname[IFNAMSIZ];
  518.   struct timeval now, res;
  519.   gettimeofday (&now, (struct timezone *) NULL);
  520.   timersub (&now, &route->changed, &res);
  521.   timerstring (&res, duration, sizeof (duration));
  522.   /* destination */
  523.   if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
  524.     ospf6_linkstate_prefix2str (&route->prefix, destination,
  525.                                 sizeof (destination));
  526.   else if (route->type == OSPF6_DEST_TYPE_ROUTER)
  527.     inet_ntop (route->prefix.family, &route->prefix.u.prefix,
  528.                destination, sizeof (destination));
  529.   else
  530.     prefix2str (&route->prefix, destination, sizeof (destination));
  531.   /* nexthop */
  532.   inet_ntop (AF_INET6, &route->nexthop[0].address, nexthop,
  533.              sizeof (nexthop));
  534.   if (! if_indextoname (route->nexthop[0].ifindex, ifname))
  535.     snprintf (ifname, sizeof (ifname), "%d", route->nexthop[0].ifindex);
  536.   vty_out (vty, "%c%1s %2s %-30s %-25s %6s %s%s",
  537.            (ospf6_route_is_best (route) ? '*' : ' '),
  538.            OSPF6_DEST_TYPE_SUBSTR (route->type),
  539.            OSPF6_PATH_TYPE_SUBSTR (route->path.type),
  540.            destination, nexthop, ifname, duration, VNL);
  541.   for (i = 1; ospf6_nexthop_is_set (&route->nexthop[i]) &&
  542.        i < OSPF6_MULTI_PATH_LIMIT; i++)
  543.     {
  544.       /* nexthop */
  545.       inet_ntop (AF_INET6, &route->nexthop[i].address, nexthop,
  546.                  sizeof (nexthop));
  547.       if (! if_indextoname (route->nexthop[i].ifindex, ifname))
  548.         snprintf (ifname, sizeof (ifname), "%d", route->nexthop[i].ifindex);
  549.       vty_out (vty, "%c%1s %2s %-30s %-25s %6s %s%s",
  550.                ' ', "", "", "", nexthop, ifname, "", VNL);
  551.     }
  552. }
  553. void
  554. ospf6_route_show_detail (struct vty *vty, struct ospf6_route *route)
  555. {
  556.   char destination[64], nexthop[64], ifname[IFNAMSIZ];
  557.   char area_id[16], id[16], adv_router[16], capa[16], options[16];
  558.   struct timeval now, res;
  559.   char duration[16];
  560.   int i;
  561.   gettimeofday (&now, (struct timezone *) NULL);
  562.   /* destination */
  563.   if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
  564.     ospf6_linkstate_prefix2str (&route->prefix, destination,
  565.                                 sizeof (destination));
  566.   else if (route->type == OSPF6_DEST_TYPE_ROUTER)
  567.     inet_ntop (route->prefix.family, &route->prefix.u.prefix,
  568.                destination, sizeof (destination));
  569.   else
  570.     prefix2str (&route->prefix, destination, sizeof (destination));
  571.   vty_out (vty, "Destination: %s%s", destination, VNL);
  572.   /* destination type */
  573.   vty_out (vty, "Destination type: %s%s",
  574.            OSPF6_DEST_TYPE_NAME (route->type),
  575.            VNL);
  576.   /* Time */
  577.   timersub (&now, &route->installed, &res);
  578.   timerstring (&res, duration, sizeof (duration));
  579.   vty_out (vty, "Installed Time: %s ago%s", duration, VNL);
  580.   timersub (&now, &route->changed, &res);
  581.   timerstring (&res, duration, sizeof (duration));
  582.   vty_out (vty, "  Changed Time: %s ago%s", duration, VNL);
  583.   /* Debugging info */
  584.   vty_out (vty, "Lock: %d Flags: %s%s%s%s%s", route->lock,
  585.            (CHECK_FLAG (route->flag, OSPF6_ROUTE_BEST)   ? "B" : "-"),
  586.            (CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD)    ? "A" : "-"),
  587.            (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE) ? "R" : "-"),
  588.            (CHECK_FLAG (route->flag, OSPF6_ROUTE_CHANGE) ? "C" : "-"),
  589.            VNL);
  590.   vty_out (vty, "Memory: prev: %p this: %p next: %p%s",
  591.            route->prev, route, route->next, VNL);
  592.   /* Path section */
  593.   /* Area-ID */
  594.   inet_ntop (AF_INET, &route->path.area_id, area_id, sizeof (area_id));
  595.   vty_out (vty, "Associated Area: %s%s", area_id, VNL);
  596.   /* Path type */
  597.   vty_out (vty, "Path Type: %s%s",
  598.            OSPF6_PATH_TYPE_NAME (route->path.type), VNL);
  599.   /* LS Origin */
  600.   inet_ntop (AF_INET, &route->path.origin.id, id, sizeof (id));
  601.   inet_ntop (AF_INET, &route->path.origin.adv_router, adv_router,
  602.              sizeof (adv_router));
  603.   vty_out (vty, "LS Origin: %s Id: %s Adv: %s%s",
  604.            ospf6_lstype_name (route->path.origin.type),
  605.            id, adv_router, VNL);
  606.   /* Options */
  607.   ospf6_options_printbuf (route->path.options, options, sizeof (options));
  608.   vty_out (vty, "Options: %s%s", options, VNL);
  609.   /* Router Bits */
  610.   ospf6_capability_printbuf (route->path.router_bits, capa, sizeof (capa));
  611.   vty_out (vty, "Router Bits: %s%s", capa, VNL);
  612.   /* Prefix Options */
  613.   vty_out (vty, "Prefix Options: xxx%s", VNL);
  614.   /* Metrics */
  615.   vty_out (vty, "Metric Type: %d%s", route->path.metric_type,
  616.            VNL);
  617.   vty_out (vty, "Metric: %d (%d)%s",
  618.            route->path.cost, route->path.cost_e2, VNL);
  619.   /* Nexthops */
  620.   vty_out (vty, "Nexthop:%s", VNL);
  621.   for (i = 0; ospf6_nexthop_is_set (&route->nexthop[i]) &&
  622.        i < OSPF6_MULTI_PATH_LIMIT; i++)
  623.     {
  624.       /* nexthop */
  625.       inet_ntop (AF_INET6, &route->nexthop[i].address, nexthop,
  626.                  sizeof (nexthop));
  627.       if (! if_indextoname (route->nexthop[i].ifindex, ifname))
  628.         snprintf (ifname, sizeof (ifname), "%d", route->nexthop[i].ifindex);
  629.       vty_out (vty, "  %s %s%s", nexthop, ifname, VNL);
  630.     }
  631.   vty_out (vty, "%s", VNL);
  632. }
  633. void
  634. ospf6_route_show_table_summary (struct vty *vty,
  635.                                 struct ospf6_route_table *table)
  636. {
  637.   struct ospf6_route *route, *prev = NULL;
  638.   int i, pathtype[OSPF6_PATH_TYPE_MAX];
  639.   int number = 0;
  640.   int nhinval = 0, ecmp = 0;
  641.   int alternative = 0, destination = 0;
  642.   for (i = 0; i < OSPF6_PATH_TYPE_MAX; i++)
  643.     pathtype[i] = 0;
  644.   for (route = ospf6_route_head (table); route;
  645.        route = ospf6_route_next (route))
  646.     {
  647.       if (prev == NULL || ! ospf6_route_is_same (prev, route))
  648.         destination++;
  649.       else
  650.         alternative++;
  651.       if (! ospf6_nexthop_is_set (&route->nexthop[0]))
  652.         nhinval++;
  653.       else if (ospf6_nexthop_is_set (&route->nexthop[1]))
  654.         ecmp++;
  655.       pathtype[route->path.type]++;
  656.       number++;
  657.       prev = route;
  658.     }
  659.   assert (number == table->count);
  660.   vty_out (vty, "Number of OSPFv3 routes: %d%s", number, VNL);
  661.   vty_out (vty, "Number of Destination: %d%s", destination, VNL);
  662.   vty_out (vty, "Number of Alternative routes: %d%s", alternative, VNL);
  663.   vty_out (vty, "Number of Equal Cost Multi Path: %d%s", ecmp, VNL);
  664.   for (i = OSPF6_PATH_TYPE_INTRA; i <= OSPF6_PATH_TYPE_EXTERNAL2; i++)
  665.     {
  666.       vty_out (vty, "Number of %s routes: %d%s",
  667.                OSPF6_PATH_TYPE_NAME (i), pathtype[i], VNL);
  668.     }
  669. }
  670. void
  671. ospf6_route_show_table_prefix (struct vty *vty,
  672.                                struct prefix *prefix,
  673.                                struct ospf6_route_table *table)
  674. {
  675.   struct ospf6_route *route;
  676.   route = ospf6_route_lookup (prefix, table);
  677.   if (route == NULL)
  678.     return;
  679.   ospf6_route_lock (route);
  680.   while (route && ospf6_route_is_prefix (prefix, route))
  681.     {
  682.       /* Specifying a prefix will always display details */
  683.       ospf6_route_show_detail (vty, route);
  684.       route = ospf6_route_next (route);
  685.     }
  686.   if (route)
  687.     ospf6_route_unlock (route);
  688. }
  689. void
  690. ospf6_route_show_table_address (struct vty *vty,
  691.                                 struct prefix *prefix,
  692.                                 struct ospf6_route_table *table)
  693. {
  694.   struct ospf6_route *route;
  695.   route = ospf6_route_lookup_bestmatch (prefix, table);
  696.   if (route == NULL)
  697.     return;
  698.   prefix = &route->prefix;
  699.   ospf6_route_lock (route);
  700.   while (route && ospf6_route_is_prefix (prefix, route))
  701.     {
  702.       /* Specifying a prefix will always display details */
  703.       ospf6_route_show_detail (vty, route);
  704.       route = ospf6_route_next (route);
  705.     }
  706.   if (route)
  707.     ospf6_route_unlock (route);
  708. }
  709. void
  710. ospf6_route_show_table_match (struct vty *vty, int detail,
  711.                               struct prefix *prefix,
  712.                               struct ospf6_route_table *table)
  713. {
  714.   struct ospf6_route *route;
  715.   assert (prefix->family);
  716.   route = ospf6_route_match_head (prefix, table);
  717.   while (route)
  718.     {
  719.       if (detail)
  720.         ospf6_route_show_detail (vty, route);
  721.       else
  722.         ospf6_route_show (vty, route);
  723.       route = ospf6_route_match_next (prefix, route);
  724.     }
  725. }
  726. void
  727. ospf6_route_show_table_type (struct vty *vty, int detail, u_char type,
  728.                              struct ospf6_route_table *table)
  729. {
  730.   struct ospf6_route *route;
  731.   route = ospf6_route_head (table);
  732.   while (route)
  733.     {
  734.       if (route->path.type == type)
  735.         {
  736.           if (detail)
  737.             ospf6_route_show_detail (vty, route);
  738.           else
  739.             ospf6_route_show (vty, route);
  740.         }
  741.       route = ospf6_route_next (route);
  742.     }
  743. }
  744. void
  745. ospf6_route_show_table (struct vty *vty, int detail,
  746.                         struct ospf6_route_table *table)
  747. {
  748.   struct ospf6_route *route;
  749.   route = ospf6_route_head (table);
  750.   while (route)
  751.     {
  752.       if (detail)
  753.         ospf6_route_show_detail (vty, route);
  754.       else
  755.         ospf6_route_show (vty, route);
  756.       route = ospf6_route_next (route);
  757.     }
  758. }
  759. int
  760. ospf6_route_table_show (struct vty *vty, int argc, char **argv,
  761.                         struct ospf6_route_table *table)
  762. {
  763.   int summary = 0;
  764.   int match = 0;
  765.   int detail = 0;
  766.   int slash = 0;
  767.   int isprefix = 0;
  768.   int i, ret;
  769.   struct prefix prefix;
  770.   u_char type = 0;
  771.   memset (&prefix, 0, sizeof (struct prefix));
  772.   for (i = 0; i < argc; i++)
  773.     {
  774.       if (! strcmp (argv[i], "summary"))
  775.         {
  776.           summary++;
  777.           continue;
  778.         }
  779.       if (! strcmp (argv[i], "intra-area"))
  780.         {
  781.           type = OSPF6_PATH_TYPE_INTRA;
  782.           continue;
  783.         }
  784.       if (! strcmp (argv[i], "inter-area"))
  785.         {
  786.           type = OSPF6_PATH_TYPE_INTER;
  787.           continue;
  788.         }
  789.       if (! strcmp (argv[i], "external-1"))
  790.         {
  791.           type = OSPF6_PATH_TYPE_EXTERNAL1;
  792.           continue;
  793.         }
  794.       if (! strcmp (argv[i], "external-2"))
  795.         {
  796.           type = OSPF6_PATH_TYPE_EXTERNAL2;
  797.           continue;
  798.         }
  799.       if (! strcmp (argv[i], "detail"))
  800.         {
  801.           detail++;
  802.           continue;
  803.         }
  804.       if (! strcmp (argv[i], "match"))
  805.         {
  806.           match++;
  807.           continue;
  808.         }
  809.       ret = str2prefix (argv[i], &prefix);
  810.       if (ret == 1 && prefix.family == AF_INET6)
  811.         {
  812.           isprefix++;
  813.           if (strchr (argv[i], '/'))
  814.             slash++;
  815.           continue;
  816.         }
  817.       vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
  818.       return CMD_SUCCESS;
  819.     }
  820.   /* Give summary of this route table */
  821.   if (summary)
  822.     {
  823.       ospf6_route_show_table_summary (vty, table);
  824.       return CMD_SUCCESS;
  825.     }
  826.   /* Give exact prefix-match route */
  827.   if (isprefix && ! match)
  828.     {
  829.       /* If exact address, give best matching route */
  830.       if (! slash)
  831.         ospf6_route_show_table_address (vty, &prefix, table);
  832.       else
  833.         ospf6_route_show_table_prefix (vty, &prefix, table);
  834.       return CMD_SUCCESS;
  835.     }
  836.   if (match)
  837.     ospf6_route_show_table_match (vty, detail, &prefix, table);
  838.   else if (type)
  839.     ospf6_route_show_table_type (vty, detail, type, table);
  840.   else
  841.     ospf6_route_show_table (vty, detail, table);
  842.   return CMD_SUCCESS;
  843. }
  844. void
  845. ospf6_linkstate_show_header (struct vty *vty)
  846. {
  847.   vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %s%s",
  848.            "Type", "Router-ID", "Net-ID", "Rtr-Bits", "Options", "Cost", VNL);
  849. }
  850. void
  851. ospf6_linkstate_show (struct vty *vty, struct ospf6_route *route)
  852. {
  853.   u_int32_t router, id;
  854.   char routername[16], idname[16], rbits[16], options[16];
  855.   router = ospf6_linkstate_prefix_adv_router (&route->prefix);
  856.   inet_ntop (AF_INET, &router, routername, sizeof (routername));
  857.   id = ospf6_linkstate_prefix_id (&route->prefix);
  858.   inet_ntop (AF_INET, &id, idname, sizeof (idname));
  859.   ospf6_capability_printbuf (route->path.router_bits, rbits, sizeof (rbits));
  860.   ospf6_options_printbuf (route->path.options, options, sizeof (options));
  861.   if (ntohl (id))
  862.     vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %lu%s",
  863.              "Network", routername, idname, rbits, options,
  864.              (unsigned long) route->path.cost, VNL);
  865.   else
  866.     vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %lu%s",
  867.              "Router", routername, idname, rbits, options,
  868.              (unsigned long) route->path.cost, VNL);
  869. }
  870. void
  871. ospf6_linkstate_show_table_exact (struct vty *vty,
  872.                                   struct prefix *prefix,
  873.                                   struct ospf6_route_table *table)
  874. {
  875.   struct ospf6_route *route;
  876.   route = ospf6_route_lookup (prefix, table);
  877.   if (route == NULL)
  878.     return;
  879.   ospf6_route_lock (route);
  880.   while (route && ospf6_route_is_prefix (prefix, route))
  881.     {
  882.       /* Specifying a prefix will always display details */
  883.       ospf6_route_show_detail (vty, route);
  884.       route = ospf6_route_next (route);
  885.     }
  886.   if (route)
  887.     ospf6_route_unlock (route);
  888. }
  889. void
  890. ospf6_linkstate_show_table (struct vty *vty, int detail,
  891.                             struct ospf6_route_table *table)
  892. {
  893.   struct ospf6_route *route;
  894.   if (! detail)
  895.     ospf6_linkstate_show_header (vty);
  896.   route = ospf6_route_head (table);
  897.   while (route)
  898.     {
  899.       if (detail)
  900.         ospf6_route_show_detail (vty, route);
  901.       else
  902.         ospf6_linkstate_show (vty, route);
  903.       route = ospf6_route_next (route);
  904.     }
  905. }
  906. int
  907. ospf6_linkstate_table_show (struct vty *vty, int argc, char **argv,
  908.                             struct ospf6_route_table *table)
  909. {
  910.   int detail = 0;
  911.   int is_id = 0;
  912.   int is_router = 0;
  913.   int i, ret;
  914.   struct prefix router, id, prefix;
  915.   memset (&router, 0, sizeof (struct prefix));
  916.   memset (&id, 0, sizeof (struct prefix));
  917.   memset (&prefix, 0, sizeof (struct prefix));
  918.   for (i = 0; i < argc; i++)
  919.     {
  920.       if (! strcmp (argv[i], "detail"))
  921.         {
  922.           detail++;
  923.           continue;
  924.         }
  925.       if (! is_router)
  926.         {
  927.           ret = str2prefix (argv[i], &router);
  928.           if (ret == 1 && router.family == AF_INET)
  929.             {
  930.               is_router++;
  931.               continue;
  932.             }
  933.           vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
  934.           return CMD_SUCCESS;
  935.         }
  936.       if (! is_id)
  937.         {
  938.           ret = str2prefix (argv[i], &id);
  939.           if (ret == 1 && id.family == AF_INET)
  940.             {
  941.               is_id++;
  942.               continue;
  943.             }
  944.           vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
  945.           return CMD_SUCCESS;
  946.         }
  947.       vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
  948.       return CMD_SUCCESS;
  949.     }
  950.   if (is_router)
  951.     ospf6_linkstate_prefix (router.u.prefix4.s_addr,
  952.                             id.u.prefix4.s_addr, &prefix);
  953.   if (prefix.family)
  954.     ospf6_linkstate_show_table_exact (vty, &prefix, table);
  955.   else
  956.     ospf6_linkstate_show_table (vty, detail, table);
  957.   return CMD_SUCCESS;
  958. }
  959. void
  960. ospf6_brouter_show_header (struct vty *vty)
  961. {
  962.   vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
  963.            "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL);
  964. }
  965. void
  966. ospf6_brouter_show (struct vty *vty, struct ospf6_route *route)
  967. {
  968.   u_int32_t adv_router;
  969.   char adv[16], rbits[16], options[16], area[16];
  970.   adv_router = ospf6_linkstate_prefix_adv_router (&route->prefix);
  971.   inet_ntop (AF_INET, &adv_router, adv, sizeof (adv));
  972.   ospf6_capability_printbuf (route->path.router_bits, rbits, sizeof (rbits));
  973.   ospf6_options_printbuf (route->path.options, options, sizeof (options));
  974.   inet_ntop (AF_INET, &route->path.area_id, area, sizeof (area));
  975.   /* vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
  976.            "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL); */
  977.   vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
  978.            adv, rbits, options, OSPF6_PATH_TYPE_NAME (route->path.type),
  979.            area, VNL);
  980. }
  981. DEFUN (debug_ospf6_route,
  982.        debug_ospf6_route_cmd,
  983.        "debug ospf6 route (table|intra-area|inter-area)",
  984.        DEBUG_STR
  985.        OSPF6_STR
  986.        "Debug route table calculationn"
  987.        "Debug detailn"
  988.        "Debug intra-area route calculationn"
  989.        "Debug inter-area route calculationn"
  990.        )
  991. {
  992.   unsigned char level = 0;
  993.   if (! strncmp (argv[0], "table", 5))
  994.     level = OSPF6_DEBUG_ROUTE_TABLE;
  995.   else if (! strncmp (argv[0], "intra", 5))
  996.     level = OSPF6_DEBUG_ROUTE_INTRA;
  997.   else if (! strncmp (argv[0], "inter", 5))
  998.     level = OSPF6_DEBUG_ROUTE_INTER;
  999.   OSPF6_DEBUG_ROUTE_ON (level);
  1000.   return CMD_SUCCESS;
  1001. }
  1002. DEFUN (no_debug_ospf6_route,
  1003.        no_debug_ospf6_route_cmd,
  1004.        "no debug ospf6 route (table|intra-area|inter-area)",
  1005.        NO_STR
  1006.        DEBUG_STR
  1007.        OSPF6_STR
  1008.        "Debug route table calculationn"
  1009.        "Debug intra-area route calculationn")
  1010. {
  1011.   unsigned char level = 0;
  1012.   if (! strncmp (argv[0], "table", 5))
  1013.     level = OSPF6_DEBUG_ROUTE_TABLE;
  1014.   else if (! strncmp (argv[0], "intra", 5))
  1015.     level = OSPF6_DEBUG_ROUTE_INTRA;
  1016.   else if (! strncmp (argv[0], "inter", 5))
  1017.     level = OSPF6_DEBUG_ROUTE_INTER;
  1018.   OSPF6_DEBUG_ROUTE_OFF (level);
  1019.   return CMD_SUCCESS;
  1020. }
  1021. int
  1022. config_write_ospf6_debug_route (struct vty *vty)
  1023. {
  1024.   if (IS_OSPF6_DEBUG_ROUTE (TABLE))
  1025.     vty_out (vty, "debug ospf6 route table%s", VNL);
  1026.   if (IS_OSPF6_DEBUG_ROUTE (INTRA))
  1027.     vty_out (vty, "debug ospf6 route intra-area%s", VNL);
  1028.   if (IS_OSPF6_DEBUG_ROUTE (INTER))
  1029.     vty_out (vty, "debug ospf6 route inter-area%s", VNL);
  1030.   return 0;
  1031. }
  1032. void
  1033. install_element_ospf6_debug_route ()
  1034. {
  1035.   install_element (ENABLE_NODE, &debug_ospf6_route_cmd);
  1036.   install_element (ENABLE_NODE, &no_debug_ospf6_route_cmd);
  1037.   install_element (CONFIG_NODE, &debug_ospf6_route_cmd);
  1038.   install_element (CONFIG_NODE, &no_debug_ospf6_route_cmd);
  1039. }