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

网络

开发平台:

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 "linklist.h"
  25. #include "thread.h"
  26. #include "vty.h"
  27. #include "command.h"
  28. #include "if.h"
  29. #include "prefix.h"
  30. #include "table.h"
  31. #include "plist.h"
  32. #include "filter.h"
  33. #include "ospf6_proto.h"
  34. #include "ospf6_lsa.h"
  35. #include "ospf6_lsdb.h"
  36. #include "ospf6_route.h"
  37. #include "ospf6_spf.h"
  38. #include "ospf6_top.h"
  39. #include "ospf6_area.h"
  40. #include "ospf6_interface.h"
  41. #include "ospf6_intra.h"
  42. #include "ospf6_abr.h"
  43. #include "ospf6d.h"
  44. int
  45. ospf6_area_cmp (void *va, void *vb)
  46. {
  47.   struct ospf6_area *oa = (struct ospf6_area *) va;
  48.   struct ospf6_area *ob = (struct ospf6_area *) vb;
  49.   return (ntohl (oa->area_id) < ntohl (ob->area_id) ? -1 : 1);
  50. }
  51. /* schedule routing table recalculation */
  52. void
  53. ospf6_area_lsdb_hook_add (struct ospf6_lsa *lsa)
  54. {
  55.   switch (ntohs (lsa->header->type))
  56.     {
  57.     case OSPF6_LSTYPE_ROUTER:
  58.     case OSPF6_LSTYPE_NETWORK:
  59.       if (IS_OSPF6_DEBUG_EXAMIN_TYPE (lsa->header->type))
  60.         {
  61.           zlog_info ("Examin %s", lsa->name);
  62.           zlog_info ("Schedule SPF Calculation for %s",
  63.                      OSPF6_AREA (lsa->lsdb->data)->name);
  64.         }
  65.       ospf6_spf_schedule (OSPF6_AREA (lsa->lsdb->data));
  66.       break;
  67.     case OSPF6_LSTYPE_INTRA_PREFIX:
  68.       ospf6_intra_prefix_lsa_add (lsa);
  69.       break;
  70.     case OSPF6_LSTYPE_INTER_PREFIX:
  71.     case OSPF6_LSTYPE_INTER_ROUTER:
  72.       ospf6_abr_examin_summary (lsa, (struct ospf6_area *) lsa->lsdb->data);
  73.       break;
  74.     default:
  75.       break;
  76.     }
  77. }
  78. void
  79. ospf6_area_lsdb_hook_remove (struct ospf6_lsa *lsa)
  80. {
  81.   switch (ntohs (lsa->header->type))
  82.     {
  83.     case OSPF6_LSTYPE_ROUTER:
  84.     case OSPF6_LSTYPE_NETWORK:
  85.       if (IS_OSPF6_DEBUG_EXAMIN_TYPE (lsa->header->type))
  86.         {
  87.           zlog_info ("LSA disappearing: %s", lsa->name);
  88.           zlog_info ("Schedule SPF Calculation for %s",
  89.                      OSPF6_AREA (lsa->lsdb->data)->name);
  90.         }
  91.       ospf6_spf_schedule (OSPF6_AREA (lsa->lsdb->data));
  92.       break;
  93.     case OSPF6_LSTYPE_INTRA_PREFIX:
  94.       ospf6_intra_prefix_lsa_remove (lsa);
  95.       break;
  96.     case OSPF6_LSTYPE_INTER_PREFIX:
  97.     case OSPF6_LSTYPE_INTER_ROUTER:
  98.       ospf6_abr_examin_summary (lsa, (struct ospf6_area *) lsa->lsdb->data);
  99.       break;
  100.     default:
  101.       break;
  102.     }
  103. }
  104. void
  105. ospf6_area_route_hook_add (struct ospf6_route *route)
  106. {
  107.   struct ospf6_route *copy = ospf6_route_copy (route);
  108.   ospf6_route_add (copy, ospf6->route_table);
  109. }
  110. void
  111. ospf6_area_route_hook_remove (struct ospf6_route *route)
  112. {
  113.   struct ospf6_route *copy;
  114.   copy = ospf6_route_lookup_identical (route, ospf6->route_table);
  115.   if (copy)
  116.     ospf6_route_remove (copy, ospf6->route_table);
  117. }
  118. /* Make new area structure */
  119. struct ospf6_area *
  120. ospf6_area_create (u_int32_t area_id, struct ospf6 *o)
  121. {
  122.   struct ospf6_area *oa;
  123.   struct ospf6_route *route;
  124.   oa = XCALLOC (MTYPE_OSPF6_AREA, sizeof (struct ospf6_area));
  125.   inet_ntop (AF_INET, &area_id, oa->name, sizeof (oa->name));
  126.   oa->area_id = area_id;
  127.   oa->if_list = list_new ();
  128.   oa->lsdb = ospf6_lsdb_create (oa);
  129.   oa->lsdb->hook_add = ospf6_area_lsdb_hook_add;
  130.   oa->lsdb->hook_remove = ospf6_area_lsdb_hook_remove;
  131.   oa->lsdb_self = ospf6_lsdb_create (oa);
  132.   oa->spf_table = ospf6_route_table_create ();
  133.   oa->route_table = ospf6_route_table_create ();
  134.   oa->route_table->hook_add = ospf6_area_route_hook_add;
  135.   oa->route_table->hook_remove = ospf6_area_route_hook_remove;
  136.   oa->range_table = ospf6_route_table_create ();
  137.   oa->summary_prefix = ospf6_route_table_create ();
  138.   oa->summary_router = ospf6_route_table_create ();
  139.   /* set default options */
  140.   OSPF6_OPT_SET (oa->options, OSPF6_OPT_V6);
  141.   OSPF6_OPT_SET (oa->options, OSPF6_OPT_E);
  142.   OSPF6_OPT_SET (oa->options, OSPF6_OPT_R);
  143.   oa->ospf6 = o;
  144.   listnode_add_sort (o->area_list, oa);
  145.   /* import athoer area's routes as inter-area routes */
  146.   for (route = ospf6_route_head (o->route_table); route;
  147.        route = ospf6_route_next (route))
  148.     ospf6_abr_originate_summary_to_area (route, oa);
  149.   return oa;
  150. }
  151. void
  152. ospf6_area_delete (struct ospf6_area *oa)
  153. {
  154.   listnode n;
  155.   struct ospf6_interface *oi;
  156.   ospf6_route_table_delete (oa->range_table);
  157.   ospf6_route_table_delete (oa->summary_prefix);
  158.   ospf6_route_table_delete (oa->summary_router);
  159.   /* ospf6 interface list */
  160.   for (n = listhead (oa->if_list); n; nextnode (n))
  161.     {
  162.       oi = (struct ospf6_interface *) getdata (n);
  163.       ospf6_interface_delete (oi);
  164.     }
  165.   list_delete (oa->if_list);
  166.   ospf6_lsdb_delete (oa->lsdb);
  167.   ospf6_lsdb_delete (oa->lsdb_self);
  168.   ospf6_route_table_delete (oa->spf_table);
  169.   ospf6_route_table_delete (oa->route_table);
  170. #if 0
  171.   ospf6_spftree_delete (oa->spf_tree);
  172.   ospf6_route_table_delete (oa->topology_table);
  173. #endif /*0*/
  174.   THREAD_OFF (oa->thread_spf_calculation);
  175.   THREAD_OFF (oa->thread_route_calculation);
  176.   listnode_delete (oa->ospf6->area_list, oa);
  177.   oa->ospf6 = NULL;
  178.   /* free area */
  179.   XFREE (MTYPE_OSPF6_AREA, oa);
  180. }
  181. struct ospf6_area *
  182. ospf6_area_lookup (u_int32_t area_id, struct ospf6 *ospf6)
  183. {
  184.   struct ospf6_area *oa;
  185.   listnode n;
  186.   for (n = listhead (ospf6->area_list); n; nextnode (n))
  187.     {
  188.       oa = (struct ospf6_area *) getdata (n);
  189.       if (oa->area_id == area_id)
  190.         return oa;
  191.     }
  192.   return (struct ospf6_area *) NULL;
  193. }
  194. struct ospf6_area *
  195. ospf6_area_get (u_int32_t area_id, struct ospf6 *o)
  196. {
  197.   struct ospf6_area *oa;
  198.   oa = ospf6_area_lookup (area_id, o);
  199.   if (oa == NULL)
  200.     oa = ospf6_area_create (area_id, o);
  201.   return oa;
  202. }
  203. void
  204. ospf6_area_enable (struct ospf6_area *oa)
  205. {
  206.   listnode i;
  207.   struct ospf6_interface *oi;
  208.   SET_FLAG (oa->flag, OSPF6_AREA_ENABLE);
  209.   for (i = listhead (oa->if_list); i; nextnode (i))
  210.     {
  211.       oi = (struct ospf6_interface *) getdata (i);
  212.       ospf6_interface_enable (oi);
  213.     }
  214. }
  215. void
  216. ospf6_area_disable (struct ospf6_area *oa)
  217. {
  218.   listnode i;
  219.   struct ospf6_interface *oi;
  220.   UNSET_FLAG (oa->flag, OSPF6_AREA_ENABLE);
  221.   for (i = listhead (oa->if_list); i; nextnode (i))
  222.     {
  223.       oi = (struct ospf6_interface *) getdata (i);
  224.       ospf6_interface_disable (oi);
  225.     }
  226. }
  227. void
  228. ospf6_area_show (struct vty *vty, struct ospf6_area *oa)
  229. {
  230.   listnode i;
  231.   struct ospf6_interface *oi;
  232.   vty_out (vty, " Area %s%s", oa->name, VNL);
  233.   vty_out (vty, "     Number of Area scoped LSAs is %u%s",
  234.            oa->lsdb->count, VNL);
  235.   vty_out (vty, "     Interface attached to this area:");
  236.   for (i = listhead (oa->if_list); i; nextnode (i))
  237.     {
  238.       oi = (struct ospf6_interface *) getdata (i);
  239.       vty_out (vty, " %s", oi->interface->name);
  240.     }
  241.   vty_out (vty, "%s", VNL);
  242. }
  243. #define OSPF6_CMD_AREA_LOOKUP(str, oa)                     
  244. {                                                          
  245.   u_int32_t area_id = 0;                                   
  246.   if (inet_pton (AF_INET, str, &area_id) != 1)             
  247.     {                                                      
  248.       vty_out (vty, "Malformed Area-ID: %s%s", str, VNL);  
  249.       return CMD_SUCCESS;                                  
  250.     }                                                      
  251.   oa = ospf6_area_lookup (area_id, ospf6);                 
  252.   if (oa == NULL)                                          
  253.     {                                                      
  254.       vty_out (vty, "No such Area: %s%s", str, VNL);       
  255.       return CMD_SUCCESS;                                  
  256.     }                                                      
  257. }
  258. #define OSPF6_CMD_AREA_GET(str, oa)                        
  259. {                                                          
  260.   u_int32_t area_id = 0;                                   
  261.   if (inet_pton (AF_INET, str, &area_id) != 1)             
  262.     {                                                      
  263.       vty_out (vty, "Malformed Area-ID: %s%s", str, VNL);  
  264.       return CMD_SUCCESS;                                  
  265.     }                                                      
  266.   oa = ospf6_area_get (area_id, ospf6);                    
  267. }
  268. DEFUN (area_range,
  269.        area_range_cmd,
  270.        "area A.B.C.D range X:X::X:X/M",
  271.        "OSPF area parametersn"
  272.        OSPF6_AREA_ID_STR
  273.        "Configured address rangen"
  274.        "Specify IPv6 prefixn"
  275.        )
  276. {
  277.   int ret;
  278.   struct ospf6_area *oa;
  279.   struct prefix prefix;
  280.   struct ospf6_route *range;
  281.   OSPF6_CMD_AREA_GET (argv[0], oa);
  282.   argc--;
  283.   argv++;
  284.   ret = str2prefix (argv[0], &prefix);
  285.   if (ret != 1 || prefix.family != AF_INET6)
  286.     {
  287.       vty_out (vty, "Malformed argument: %s%s", argv[0], VNL);
  288.       return CMD_SUCCESS;
  289.     }
  290.   argc--;
  291.   argv++;
  292.   range = ospf6_route_lookup (&prefix, oa->range_table);
  293.   if (range == NULL)
  294.     {
  295.       range = ospf6_route_create ();
  296.       range->type = OSPF6_DEST_TYPE_RANGE;
  297.       range->prefix = prefix;
  298.     }
  299.   if (argc)
  300.     {
  301.       if (! strcmp (argv[0], "not-advertise"))
  302.         SET_FLAG (range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
  303.       else if (! strcmp (argv[0], "advertise"))
  304.         UNSET_FLAG (range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
  305.     }
  306.   ospf6_route_add (range, oa->range_table);
  307.   return CMD_SUCCESS;
  308. }
  309. ALIAS (area_range,
  310.        area_range_advertise_cmd,
  311.        "area A.B.C.D range X:X::X:X/M (advertise|not-advertise)",
  312.        "OSPF area parametersn"
  313.        OSPF6_AREA_ID_STR
  314.        "Configured address rangen"
  315.        "Specify IPv6 prefixn"
  316.        );
  317. DEFUN (no_area_range,
  318.        no_area_range_cmd,
  319.        "no area A.B.C.D range X:X::X:X/M",
  320.        "OSPF area parametersn"
  321.        OSPF6_AREA_ID_STR
  322.        "Configured address rangen"
  323.        "Specify IPv6 prefixn"
  324.        )
  325. {
  326.   int ret;
  327.   struct ospf6_area *oa;
  328.   struct prefix prefix;
  329.   struct ospf6_route *range;
  330.   OSPF6_CMD_AREA_GET (argv[0], oa);
  331.   argc--;
  332.   argv++;
  333.   ret = str2prefix (argv[0], &prefix);
  334.   if (ret != 1 || prefix.family != AF_INET6)
  335.     {
  336.       vty_out (vty, "Malformed argument: %s%s", argv[0], VNL);
  337.       return CMD_SUCCESS;
  338.     }
  339.   range = ospf6_route_lookup (&prefix, oa->range_table);
  340.   if (range == NULL)
  341.     {
  342.       vty_out (vty, "Range %s does not exists.%s", argv[0], VNL);
  343.       return CMD_SUCCESS;
  344.     }
  345.   ospf6_route_remove (range, oa->range_table);
  346.   return CMD_SUCCESS;
  347. }
  348. void
  349. ospf6_area_config_write (struct vty *vty)
  350. {
  351.   listnode node;
  352.   struct ospf6_area *oa;
  353.   struct ospf6_route *range;
  354.   char buf[128];
  355.   for (node = listhead (ospf6->area_list); node; nextnode (node))
  356.     {
  357.       oa = OSPF6_AREA (getdata (node));
  358.       for (range = ospf6_route_head (oa->range_table); range;
  359.            range = ospf6_route_next (range))
  360.         {
  361.           prefix2str (&range->prefix, buf, sizeof (buf));
  362.           vty_out (vty, " area %s range %s%s", oa->name, buf, VNL);
  363.         }
  364.     }
  365. }
  366. DEFUN (area_filter_list,
  367.        area_filter_list_cmd,
  368.        "area A.B.C.D filter-list prefix WORD (in|out)",
  369.        "OSPFv6 area parametersn"
  370.        "OSPFv6 area ID in IP address formatn"
  371.        "Filter networks between OSPFv6 areasn"
  372.        "Filter prefixes between OSPFv6 areasn"
  373.        "Name of an IPv6 prefix-listn"
  374.        "Filter networks sent to this arean"
  375.        "Filter networks sent from this arean")
  376. {
  377.   struct ospf6_area *area;
  378.   struct prefix_list *plist;
  379.   OSPF6_CMD_AREA_GET (argv[0], area);
  380.   argc--;
  381.   argv++;
  382.   plist = prefix_list_lookup (AFI_IP6, argv[1]);
  383.   if (strncmp (argv[2], "in", 2) == 0)
  384.     {
  385.       PREFIX_LIST_IN (area) = plist;
  386.       if (PREFIX_NAME_IN (area))
  387. free (PREFIX_NAME_IN (area));
  388.       PREFIX_NAME_IN (area) = strdup (argv[1]);
  389.       ospf6_abr_reimport (area);
  390.     }
  391.   else
  392.     {
  393.       PREFIX_LIST_OUT (area) = plist;
  394.       if (PREFIX_NAME_OUT (area))
  395. free (PREFIX_NAME_OUT (area));
  396.       PREFIX_NAME_OUT (area) = strdup (argv[1]);
  397.       ospf6_abr_enable_area (area);
  398.     }
  399.   return CMD_SUCCESS;
  400. }
  401.      
  402. DEFUN (no_area_filter_list,
  403.        no_area_filter_list_cmd,
  404.        "no area A.B.C.D filter-list prefix WORD (in|out)",
  405.        NO_STR
  406.        "OSPFv6 area parametersn"
  407.        "OSPFv6 area ID in IP address formatn"
  408.        "Filter networks between OSPFv6 areasn"
  409.        "Filter prefixes between OSPFv6 areasn"
  410.        "Name of an IPv6 prefix-listn"
  411.        "Filter networks sent to this arean"
  412.        "Filter networks sent from this arean")
  413. {
  414.   struct ospf6_area *area;
  415.   struct prefix_list *plist;
  416.   OSPF6_CMD_AREA_GET (argv[0], area);
  417.   argc--;
  418.   argv++;
  419.   plist = prefix_list_lookup (AFI_IP6, argv[1]);
  420.   if (strncmp (argv[2], "in", 2) == 0)
  421.     {
  422.       if (PREFIX_NAME_IN (area))
  423. if (strcmp (PREFIX_NAME_IN (area), argv[1]) != 0)
  424.   return CMD_SUCCESS;
  425.       PREFIX_LIST_IN (area) = NULL;
  426.       if (PREFIX_NAME_IN (area))
  427. free (PREFIX_NAME_IN (area));
  428.       PREFIX_NAME_IN (area) = NULL;
  429.       ospf6_abr_reimport (area);
  430.     }
  431.   else
  432.     {
  433.       if (PREFIX_NAME_OUT (area))
  434. if (strcmp (PREFIX_NAME_OUT (area), argv[1]) != 0)
  435.   return CMD_SUCCESS;
  436.       PREFIX_LIST_OUT (area) = NULL;
  437.       if (PREFIX_NAME_OUT (area))
  438. free (PREFIX_NAME_OUT (area));
  439.       PREFIX_NAME_OUT (area) = NULL;
  440.       ospf6_abr_enable_area (area);
  441.     }
  442.   return CMD_SUCCESS;
  443. }
  444. DEFUN (area_import_list,
  445.        area_import_list_cmd,
  446.        "area A.B.C.D import-list NAME",
  447.        "OSPFv6 area parametersn"
  448.        "OSPFv6 area ID in IP address formatn"
  449.        "Set the filter for networks from other areas announced to the specified onen"
  450.        "Name of the acess-listn")
  451. {
  452.   struct ospf6_area *area;
  453.   struct access_list *list;
  454.   OSPF6_CMD_AREA_GET(argv[0], area);
  455.   list = access_list_lookup (AFI_IP6, argv[1]);
  456.   IMPORT_LIST (area) = list;
  457.   if (IMPORT_NAME (area))
  458.     free (IMPORT_NAME (area));
  459.   IMPORT_NAME (area) = strdup (argv[1]);
  460.   ospf6_abr_reimport (area);
  461.   return CMD_SUCCESS; 
  462. }
  463. DEFUN (no_area_import_list,
  464.        no_area_import_list_cmd,
  465.        "no area A.B.C.D import-list NAME",
  466.        "OSPFv6 area parametersn"
  467.        "OSPFv6 area ID in IP address formatn"
  468.        "Unset the filter for networks announced to other areasn"
  469.        "NAme of the access-listn")
  470. {
  471.   struct ospf6_area *area;
  472.   OSPF6_CMD_AREA_GET(argv[0], area);
  473.   IMPORT_LIST (area) = 0;
  474.   if (IMPORT_NAME (area))
  475.     free (IMPORT_NAME (area));
  476.   IMPORT_NAME (area) = NULL;
  477.   ospf6_abr_reimport (area);
  478.   return CMD_SUCCESS;
  479. }
  480. DEFUN (area_export_list,
  481.        area_export_list_cmd,
  482.        "area A.B.C.D export-list NAME",
  483.        "OSPFv6 area parametersn"
  484.        "OSPFv6 area ID in IP address formatn"
  485.        "Set the filter for networks announced to other areasn"
  486.        "Name of the acess-listn")
  487. {
  488.   struct ospf6_area *area;
  489.   struct access_list *list;
  490.   OSPF6_CMD_AREA_GET(argv[0], area);
  491.   list = access_list_lookup (AFI_IP6, argv[1]);
  492.   EXPORT_LIST (area) = list;
  493.   if (EXPORT_NAME (area))
  494.     free (EXPORT_NAME (area));
  495.   EXPORT_NAME (area) = strdup (argv[1]);
  496.   ospf6_abr_enable_area (area);
  497.   return CMD_SUCCESS; 
  498. }
  499. DEFUN (no_area_export_list,
  500.        no_area_export_list_cmd,
  501.        "no area A.B.C.D export-list NAME",
  502.        "OSPFv6 area parametersn"
  503.        "OSPFv6 area ID in IP address formatn"
  504.        "Unset the filter for networks announced to other areasn"
  505.        "Name of the access-listn")
  506. {
  507.   struct ospf6_area *area;
  508.   OSPF6_CMD_AREA_GET(argv[0], area);
  509.   EXPORT_LIST (area) = 0;
  510.   if (EXPORT_NAME (area))
  511.     free (EXPORT_NAME (area));
  512.   EXPORT_NAME (area) = NULL;
  513.   ospf6_abr_enable_area (area);
  514.   return CMD_SUCCESS;
  515. }
  516. DEFUN (show_ipv6_ospf6_spf_tree,
  517.        show_ipv6_ospf6_spf_tree_cmd,
  518.        "show ipv6 ospf6 spf tree",
  519.        SHOW_STR
  520.        IP6_STR
  521.        OSPF6_STR
  522.        "Shortest Path First caculationn"
  523.        "Show SPF treen")
  524. {
  525.   listnode node;
  526.   struct ospf6_area *oa;
  527.   struct ospf6_vertex *root;
  528.   struct ospf6_route *route;
  529.   struct prefix prefix;
  530.   ospf6_linkstate_prefix (ospf6->router_id, htonl (0), &prefix);
  531.   for (node = listhead (ospf6->area_list); node; nextnode (node))
  532.     {
  533.       oa = (struct ospf6_area *) getdata (node);
  534.       route = ospf6_route_lookup (&prefix, oa->spf_table);
  535.       if (route == NULL)
  536.         {
  537.           vty_out (vty, "LS entry for root not found in area %s%s",
  538.                    oa->name, VNL);
  539.           continue;
  540.         }
  541.       root = (struct ospf6_vertex *) route->route_option;
  542.       ospf6_spf_display_subtree (vty, "", 0, root);
  543.     }
  544.   return CMD_SUCCESS;
  545. }
  546. DEFUN (show_ipv6_ospf6_area_spf_tree,
  547.        show_ipv6_ospf6_area_spf_tree_cmd,
  548.        "show ipv6 ospf6 area A.B.C.D spf tree",
  549.        SHOW_STR
  550.        IP6_STR
  551.        OSPF6_STR
  552.        OSPF6_AREA_STR
  553.        OSPF6_AREA_ID_STR
  554.        "Shortest Path First caculationn"
  555.        "Show SPF treen")
  556. {
  557.   u_int32_t area_id;
  558.   struct ospf6_area *oa;
  559.   struct ospf6_vertex *root;
  560.   struct ospf6_route *route;
  561.   struct prefix prefix;
  562.   ospf6_linkstate_prefix (ospf6->router_id, htonl (0), &prefix);
  563.   if (inet_pton (AF_INET, argv[0], &area_id) != 1)
  564.     {
  565.       vty_out (vty, "Malformed Area-ID: %s%s", argv[0], VNL);
  566.       return CMD_SUCCESS;
  567.     }
  568.   oa = ospf6_area_lookup (area_id, ospf6);
  569.   if (oa == NULL)
  570.     {
  571.       vty_out (vty, "No such Area: %s%s", argv[0], VNL);
  572.       return CMD_SUCCESS;
  573.     }
  574.   route = ospf6_route_lookup (&prefix, oa->spf_table);
  575.   if (route == NULL)
  576.     {
  577.       vty_out (vty, "LS entry for root not found in area %s%s",
  578.                oa->name, VNL);
  579.       return CMD_SUCCESS;
  580.     }
  581.   root = (struct ospf6_vertex *) route->route_option;
  582.   ospf6_spf_display_subtree (vty, "", 0, root);
  583.   return CMD_SUCCESS;
  584. }
  585. DEFUN (show_ipv6_ospf6_simulate_spf_tree_root,
  586.        show_ipv6_ospf6_simulate_spf_tree_root_cmd,
  587.        "show ipv6 ospf6 simulate spf-tree A.B.C.D area A.B.C.D",
  588.        SHOW_STR
  589.        IP6_STR
  590.        OSPF6_STR
  591.        "Shortest Path First caculationn"
  592.        "Show SPF treen"
  593.        "Specify root's router-id to calculate another router's SPF treen")
  594. {
  595.   u_int32_t area_id;
  596.   struct ospf6_area *oa;
  597.   struct ospf6_vertex *root;
  598.   struct ospf6_route *route;
  599.   struct prefix prefix;
  600.   u_int32_t router_id;
  601.   struct ospf6_route_table *spf_table;
  602.   unsigned char tmp_debug_ospf6_spf = 0;
  603.   inet_pton (AF_INET, argv[0], &router_id);
  604.   ospf6_linkstate_prefix (router_id, htonl (0), &prefix);
  605.   if (inet_pton (AF_INET, argv[1], &area_id) != 1)
  606.     {
  607.       vty_out (vty, "Malformed Area-ID: %s%s", argv[1], VNL);
  608.       return CMD_SUCCESS;
  609.     }
  610.   oa = ospf6_area_lookup (area_id, ospf6);
  611.   if (oa == NULL)
  612.     {
  613.       vty_out (vty, "No such Area: %s%s", argv[1], VNL);
  614.       return CMD_SUCCESS;
  615.     }
  616.   tmp_debug_ospf6_spf = conf_debug_ospf6_spf;
  617.   conf_debug_ospf6_spf = 0;
  618.   spf_table = ospf6_route_table_create ();
  619.   ospf6_spf_calculation (router_id, spf_table, oa);
  620.   conf_debug_ospf6_spf = tmp_debug_ospf6_spf;
  621.   route = ospf6_route_lookup (&prefix, spf_table);
  622.   if (route == NULL)
  623.     {
  624.       ospf6_spf_table_finish (spf_table);
  625.       ospf6_route_table_delete (spf_table);
  626.       return CMD_SUCCESS;
  627.     }
  628.   root = (struct ospf6_vertex *) route->route_option;
  629.   ospf6_spf_display_subtree (vty, "", 0, root);
  630.   ospf6_spf_table_finish (spf_table);
  631.   ospf6_route_table_delete (spf_table);
  632.   return CMD_SUCCESS;
  633. }
  634. void
  635. ospf6_area_init ()
  636. {
  637.   install_element (VIEW_NODE, &show_ipv6_ospf6_spf_tree_cmd);
  638.   install_element (VIEW_NODE, &show_ipv6_ospf6_area_spf_tree_cmd);
  639.   install_element (VIEW_NODE, &show_ipv6_ospf6_simulate_spf_tree_root_cmd);
  640.   install_element (ENABLE_NODE, &show_ipv6_ospf6_spf_tree_cmd);
  641.   install_element (ENABLE_NODE, &show_ipv6_ospf6_area_spf_tree_cmd);
  642.   install_element (ENABLE_NODE, &show_ipv6_ospf6_simulate_spf_tree_root_cmd);
  643.   install_element (OSPF6_NODE, &area_range_cmd);
  644.   install_element (OSPF6_NODE, &area_range_advertise_cmd);
  645.   install_element (OSPF6_NODE, &no_area_range_cmd);
  646.   install_element (OSPF6_NODE, &area_import_list_cmd);
  647.   install_element (OSPF6_NODE, &no_area_import_list_cmd);
  648.   install_element (OSPF6_NODE, &area_export_list_cmd);
  649.   install_element (OSPF6_NODE, &no_area_export_list_cmd);
  650.   install_element (OSPF6_NODE, &area_filter_list_cmd);
  651.   install_element (OSPF6_NODE, &no_area_filter_list_cmd);
  652. }