New upstream version 1.2.3
[quagga-debian.git] / ospf6d / ospf6_area.c
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 "linklist.h"
27 #include "thread.h"
28 #include "vty.h"
29 #include "command.h"
30 #include "if.h"
31 #include "prefix.h"
32 #include "table.h"
33 #include "plist.h"
34 #include "filter.h"
35
36 #include "ospf6_proto.h"
37 #include "ospf6_lsa.h"
38 #include "ospf6_lsdb.h"
39 #include "ospf6_route.h"
40 #include "ospf6_spf.h"
41 #include "ospf6_top.h"
42 #include "ospf6_area.h"
43 #include "ospf6_interface.h"
44 #include "ospf6_intra.h"
45 #include "ospf6_abr.h"
46 #include "ospf6d.h"
47
48 int
49 ospf6_area_cmp (void *va, void *vb)
50 {
51   struct ospf6_area *oa = (struct ospf6_area *) va;
52   struct ospf6_area *ob = (struct ospf6_area *) vb;
53   return (ntohl (oa->area_id) < ntohl (ob->area_id) ? -1 : 1);
54 }
55
56 /* schedule routing table recalculation */
57 static void
58 ospf6_area_lsdb_hook_add (struct ospf6_lsa *lsa)
59 {
60   switch (ntohs (lsa->header->type))
61     {
62     case OSPF6_LSTYPE_ROUTER:
63     case OSPF6_LSTYPE_NETWORK:
64       if (IS_OSPF6_DEBUG_EXAMIN_TYPE (lsa->header->type))
65         {
66           zlog_debug ("Examin %s", lsa->name);
67           zlog_debug ("Schedule SPF Calculation for %s",
68                       OSPF6_AREA (lsa->lsdb->data)->name);
69         }
70       ospf6_spf_schedule (OSPF6_PROCESS(OSPF6_AREA (lsa->lsdb->data)->ospf6),
71                           ospf6_lsadd_to_spf_reason(lsa));
72       break;
73
74     case OSPF6_LSTYPE_INTRA_PREFIX:
75       ospf6_intra_prefix_lsa_add (lsa);
76       break;
77
78     case OSPF6_LSTYPE_INTER_PREFIX:
79     case OSPF6_LSTYPE_INTER_ROUTER:
80       ospf6_abr_examin_summary (lsa, (struct ospf6_area *) lsa->lsdb->data);
81       break;
82
83     default:
84       break;
85     }
86 }
87
88 static void
89 ospf6_area_lsdb_hook_remove (struct ospf6_lsa *lsa)
90 {
91   switch (ntohs (lsa->header->type))
92     {
93     case OSPF6_LSTYPE_ROUTER:
94     case OSPF6_LSTYPE_NETWORK:
95       if (IS_OSPF6_DEBUG_EXAMIN_TYPE (lsa->header->type))
96         {
97           zlog_debug ("LSA disappearing: %s", lsa->name);
98           zlog_debug ("Schedule SPF Calculation for %s",
99                      OSPF6_AREA (lsa->lsdb->data)->name);
100         }
101       ospf6_spf_schedule (OSPF6_PROCESS(OSPF6_AREA (lsa->lsdb->data)->ospf6),
102                           ospf6_lsremove_to_spf_reason(lsa));
103       break;
104
105     case OSPF6_LSTYPE_INTRA_PREFIX:
106       ospf6_intra_prefix_lsa_remove (lsa);
107       break;
108
109     case OSPF6_LSTYPE_INTER_PREFIX:
110     case OSPF6_LSTYPE_INTER_ROUTER:
111       ospf6_abr_examin_summary (lsa, (struct ospf6_area *) lsa->lsdb->data);
112       break;
113
114     default:
115       break;
116     }
117 }
118
119 static void
120 ospf6_area_route_hook_add (struct ospf6_route *route)
121 {
122   struct ospf6_route *copy = ospf6_route_copy (route);
123   ospf6_route_add (copy, ospf6->route_table);
124 }
125
126 static void
127 ospf6_area_route_hook_remove (struct ospf6_route *route)
128 {
129   struct ospf6_route *copy;
130
131   copy = ospf6_route_lookup_identical (route, ospf6->route_table);
132   if (copy)
133     ospf6_route_remove (copy, ospf6->route_table);
134 }
135
136 /* Make new area structure */
137 struct ospf6_area *
138 ospf6_area_create (u_int32_t area_id, struct ospf6 *o)
139 {
140   struct ospf6_area *oa;
141   struct ospf6_route *route;
142
143   oa = XCALLOC (MTYPE_OSPF6_AREA, sizeof (struct ospf6_area));
144
145   inet_ntop (AF_INET, &area_id, oa->name, sizeof (oa->name));
146   oa->area_id = area_id;
147   oa->if_list = list_new ();
148
149   oa->lsdb = ospf6_lsdb_create (oa);
150   oa->lsdb->hook_add = ospf6_area_lsdb_hook_add;
151   oa->lsdb->hook_remove = ospf6_area_lsdb_hook_remove;
152   oa->lsdb_self = ospf6_lsdb_create (oa);
153
154   oa->spf_table = OSPF6_ROUTE_TABLE_CREATE (AREA, SPF_RESULTS);
155   oa->spf_table->scope = oa;
156   oa->route_table = OSPF6_ROUTE_TABLE_CREATE (AREA, ROUTES);
157   oa->route_table->scope = oa;
158   oa->route_table->hook_add = ospf6_area_route_hook_add;
159   oa->route_table->hook_remove = ospf6_area_route_hook_remove;
160
161   oa->range_table = OSPF6_ROUTE_TABLE_CREATE (AREA, PREFIX_RANGES);
162   oa->range_table->scope = oa;
163   oa->summary_prefix = OSPF6_ROUTE_TABLE_CREATE (AREA, SUMMARY_PREFIXES);
164   oa->summary_prefix->scope = oa;
165   oa->summary_router = OSPF6_ROUTE_TABLE_CREATE (AREA, SUMMARY_ROUTERS);
166   oa->summary_router->scope = oa;
167
168   /* set default options */
169   if (CHECK_FLAG (o->flag, OSPF6_STUB_ROUTER))
170     {
171       OSPF6_OPT_CLEAR (oa->options, OSPF6_OPT_V6);
172       OSPF6_OPT_CLEAR (oa->options, OSPF6_OPT_R);
173     }
174   else
175     {
176       OSPF6_OPT_SET (oa->options, OSPF6_OPT_V6);
177       OSPF6_OPT_SET (oa->options, OSPF6_OPT_R);
178     }
179
180   OSPF6_OPT_SET (oa->options, OSPF6_OPT_E);
181
182   oa->ospf6 = o;
183   listnode_add_sort (o->area_list, oa);
184
185   /* import athoer area's routes as inter-area routes */
186   for (route = ospf6_route_head (o->route_table); route;
187        route = ospf6_route_next (route))
188     ospf6_abr_originate_summary_to_area (route, oa);
189
190   return oa;
191 }
192
193 void
194 ospf6_area_delete (struct ospf6_area *oa)
195 {
196   struct listnode *n;
197   struct ospf6_interface *oi;
198
199   ospf6_route_table_delete (oa->range_table);
200   ospf6_route_table_delete (oa->summary_prefix);
201   ospf6_route_table_delete (oa->summary_router);
202
203   /* The ospf6_interface structs store configuration
204    * information which should not be lost/reset when
205    * deleting an area.
206    * So just detach the interface from the area and
207    * keep it around. */
208   for (ALL_LIST_ELEMENTS_RO (oa->if_list, n, oi))
209     oi->area = NULL;
210
211   list_delete (oa->if_list);
212
213   ospf6_lsdb_delete (oa->lsdb);
214   ospf6_lsdb_delete (oa->lsdb_self);
215
216   ospf6_spf_table_finish (oa->spf_table);
217   ospf6_route_table_delete (oa->spf_table);
218   ospf6_route_table_delete (oa->route_table);
219
220   THREAD_OFF (oa->thread_spf_calculation);
221   THREAD_OFF (oa->thread_route_calculation);
222
223   listnode_delete (oa->ospf6->area_list, oa);
224   oa->ospf6 = NULL;
225
226   /* free area */
227   XFREE (MTYPE_OSPF6_AREA, oa);
228 }
229
230 struct ospf6_area *
231 ospf6_area_lookup (u_int32_t area_id, struct ospf6 *ospf6)
232 {
233   struct ospf6_area *oa;
234   struct listnode *n;
235
236   for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, n, oa))
237     if (oa->area_id == area_id)
238       return oa;
239
240   return (struct ospf6_area *) NULL;
241 }
242
243 static struct ospf6_area *
244 ospf6_area_get (u_int32_t area_id, struct ospf6 *o)
245 {
246   struct ospf6_area *oa;
247   oa = ospf6_area_lookup (area_id, o);
248   if (oa == NULL)
249     oa = ospf6_area_create (area_id, o);
250   return oa;
251 }
252
253 void
254 ospf6_area_enable (struct ospf6_area *oa)
255 {
256   struct listnode *node, *nnode;
257   struct ospf6_interface *oi;
258
259   SET_FLAG (oa->flag, OSPF6_AREA_ENABLE);
260
261   for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi))
262     ospf6_interface_enable (oi);
263   ospf6_abr_enable_area (oa);
264 }
265
266 void
267 ospf6_area_disable (struct ospf6_area *oa)
268 {
269   struct listnode *node, *nnode;
270   struct ospf6_interface *oi;
271
272   UNSET_FLAG (oa->flag, OSPF6_AREA_ENABLE);
273
274   for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi))
275     ospf6_interface_disable (oi);
276
277   ospf6_abr_disable_area (oa);
278   ospf6_lsdb_remove_all (oa->lsdb);
279   ospf6_lsdb_remove_all (oa->lsdb_self);
280
281   ospf6_spf_table_finish(oa->spf_table);
282   ospf6_route_remove_all(oa->route_table);
283
284   THREAD_OFF (oa->thread_spf_calculation);
285   THREAD_OFF (oa->thread_route_calculation);
286
287   THREAD_OFF (oa->thread_router_lsa);
288   THREAD_OFF (oa->thread_intra_prefix_lsa);
289 }
290
291
292 void
293 ospf6_area_show (struct vty *vty, struct ospf6_area *oa)
294 {
295   struct listnode *i;
296   struct ospf6_interface *oi;
297
298   vty_out (vty, " Area %s%s", oa->name, VNL);
299   vty_out (vty, "     Number of Area scoped LSAs is %u%s",
300            oa->lsdb->count, VNL);
301
302   vty_out (vty, "     Interface attached to this area:");
303   for (ALL_LIST_ELEMENTS_RO (oa->if_list, i, oi))
304     vty_out (vty, " %s", oi->interface->name);
305   
306   vty_out (vty, "%s", VNL);
307 }
308
309
310 #define OSPF6_CMD_AREA_LOOKUP(str, oa)                     \
311 {                                                          \
312   u_int32_t area_id = 0;                                   \
313   if (inet_pton (AF_INET, str, &area_id) != 1)             \
314     {                                                      \
315       vty_out (vty, "Malformed Area-ID: %s%s", str, VNL);  \
316       return CMD_SUCCESS;                                  \
317     }                                                      \
318   oa = ospf6_area_lookup (area_id, ospf6);                 \
319   if (oa == NULL)                                          \
320     {                                                      \
321       vty_out (vty, "No such Area: %s%s", str, VNL);       \
322       return CMD_SUCCESS;                                  \
323     }                                                      \
324 }
325
326 #define OSPF6_CMD_AREA_GET(str, oa)                        \
327 {                                                          \
328   u_int32_t area_id = 0;                                   \
329   if (inet_pton (AF_INET, str, &area_id) != 1)             \
330     {                                                      \
331       vty_out (vty, "Malformed Area-ID: %s%s", str, VNL);  \
332       return CMD_SUCCESS;                                  \
333     }                                                      \
334   oa = ospf6_area_get (area_id, ospf6);                    \
335 }
336
337 DEFUN (area_range,
338        area_range_cmd,
339        "area A.B.C.D range X:X::X:X/M",
340        "OSPF area parameters\n"
341        OSPF6_AREA_ID_STR
342        "Configured address range\n"
343        "Specify IPv6 prefix\n"
344        )
345 {
346   int ret;
347   struct ospf6_area *oa;
348   struct prefix prefix;
349   struct ospf6_route *range;
350
351   OSPF6_CMD_AREA_GET (argv[0], oa);
352   argc--;
353   argv++;
354
355   ret = str2prefix (argv[0], &prefix);
356   if (ret != 1 || prefix.family != AF_INET6)
357     {
358       vty_out (vty, "Malformed argument: %s%s", argv[0], VNL);
359       return CMD_SUCCESS;
360     }
361   argc--;
362   argv++;
363
364   range = ospf6_route_lookup (&prefix, oa->range_table);
365   if (range == NULL)
366     {
367       range = ospf6_route_create ();
368       range->type = OSPF6_DEST_TYPE_RANGE;
369       range->prefix = prefix;
370     }
371
372   if (argc)
373     {
374       if (! strcmp (argv[0], "not-advertise"))
375         SET_FLAG (range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
376       else if (! strcmp (argv[0], "advertise"))
377         UNSET_FLAG (range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
378     }
379
380   if (range->rnode)
381     {
382       vty_out (vty, "Range already defined: %s%s", argv[-1], VNL);
383       return CMD_WARNING;
384     }
385
386   ospf6_route_add (range, oa->range_table);
387   return CMD_SUCCESS;
388 }
389
390 ALIAS (area_range,
391        area_range_advertise_cmd,
392        "area A.B.C.D range X:X::X:X/M (advertise|not-advertise)",
393        "OSPF area parameters\n"
394        OSPF6_AREA_ID_STR
395        "Configured address range\n"
396        "Specify IPv6 prefix\n"
397        )
398
399 DEFUN (no_area_range,
400        no_area_range_cmd,
401        "no area A.B.C.D range X:X::X:X/M",
402        "OSPF area parameters\n"
403        OSPF6_AREA_ID_STR
404        "Configured address range\n"
405        "Specify IPv6 prefix\n"
406        )
407 {
408   int ret;
409   struct ospf6_area *oa;
410   struct prefix prefix;
411   struct ospf6_route *range;
412
413   OSPF6_CMD_AREA_GET (argv[0], oa);
414   argc--;
415   argv++;
416
417   ret = str2prefix (argv[0], &prefix);
418   if (ret != 1 || prefix.family != AF_INET6)
419     {
420       vty_out (vty, "Malformed argument: %s%s", argv[0], VNL);
421       return CMD_SUCCESS;
422     }
423
424   range = ospf6_route_lookup (&prefix, oa->range_table);
425   if (range == NULL)
426     {
427       vty_out (vty, "Range %s does not exists.%s", argv[0], VNL);
428       return CMD_SUCCESS;
429     }
430
431   ospf6_route_remove (range, oa->range_table);
432
433   return CMD_SUCCESS;
434 }
435
436 void
437 ospf6_area_config_write (struct vty *vty)
438 {
439   struct listnode *node;
440   struct ospf6_area *oa;
441   struct ospf6_route *range;
442   char buf[128];
443
444   for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, node, oa))
445     {
446       for (range = ospf6_route_head (oa->range_table); range;
447            range = ospf6_route_next (range))
448         {
449           prefix2str (&range->prefix, buf, sizeof (buf));
450           vty_out (vty, " area %s range %s%s", oa->name, buf, VNL);
451         }
452       if (PREFIX_NAME_IN (oa))
453         vty_out (vty, " area %s filter-list prefix %s in%s",
454                  oa->name, PREFIX_NAME_IN (oa), VNL);
455       if (PREFIX_NAME_OUT (oa))
456         vty_out (vty, " area %s filter-list prefix %s out%s",
457                  oa->name, PREFIX_NAME_OUT (oa), VNL);
458       if (IMPORT_NAME (oa))
459         vty_out (vty, " area %s import-list %s%s",
460                  oa->name, IMPORT_NAME (oa), VNL);
461       if (EXPORT_NAME (oa))
462         vty_out (vty, " area %s export-list %s%s",
463                  oa->name, EXPORT_NAME (oa), VNL);
464     }
465 }
466
467 DEFUN (area_filter_list,
468        area_filter_list_cmd,
469        "area A.B.C.D filter-list prefix WORD (in|out)",
470        "OSPFv6 area parameters\n"
471        "OSPFv6 area ID in IP address format\n"
472        "Filter networks between OSPFv6 areas\n"
473        "Filter prefixes between OSPFv6 areas\n"
474        "Name of an IPv6 prefix-list\n"
475        "Filter networks sent to this area\n"
476        "Filter networks sent from this area\n")
477 {
478   struct ospf6_area *area;
479   struct prefix_list *plist;
480
481   OSPF6_CMD_AREA_GET (argv[0], area);
482   argc--;
483   argv++;
484
485   plist = prefix_list_lookup (AFI_IP6, argv[0]);
486   if (strncmp (argv[1], "in", 2) == 0)
487     {
488       PREFIX_LIST_IN (area) = plist;
489       if (PREFIX_NAME_IN (area))
490         free (PREFIX_NAME_IN (area));
491
492       PREFIX_NAME_IN (area) = strdup (argv[0]);
493       ospf6_abr_reimport (area);
494     }
495   else
496     {
497       PREFIX_LIST_OUT (area) = plist;
498       if (PREFIX_NAME_OUT (area))
499         free (PREFIX_NAME_OUT (area));
500
501       PREFIX_NAME_OUT (area) = strdup (argv[0]);
502       ospf6_abr_enable_area (area);
503     }
504
505   return CMD_SUCCESS;
506 }
507      
508 DEFUN (no_area_filter_list,
509        no_area_filter_list_cmd,
510        "no area A.B.C.D filter-list prefix WORD (in|out)",
511        NO_STR
512        "OSPFv6 area parameters\n"
513        "OSPFv6 area ID in IP address format\n"
514        "Filter networks between OSPFv6 areas\n"
515        "Filter prefixes between OSPFv6 areas\n"
516        "Name of an IPv6 prefix-list\n"
517        "Filter networks sent to this area\n"
518        "Filter networks sent from this area\n")
519 {
520   struct ospf6_area *area;
521
522   OSPF6_CMD_AREA_GET (argv[0], area);
523   argc--;
524   argv++;
525
526   if (strncmp (argv[1], "in", 2) == 0)
527     {
528       if (PREFIX_NAME_IN (area))
529         if (strcmp (PREFIX_NAME_IN (area), argv[0]) != 0)
530           return CMD_SUCCESS;
531
532       PREFIX_LIST_IN (area) = NULL;
533       if (PREFIX_NAME_IN (area))
534         free (PREFIX_NAME_IN (area));
535
536       PREFIX_NAME_IN (area) = NULL;
537       ospf6_abr_reimport (area);
538     }
539   else
540     {
541       if (PREFIX_NAME_OUT (area))
542         if (strcmp (PREFIX_NAME_OUT (area), argv[0]) != 0)
543           return CMD_SUCCESS;
544
545       PREFIX_LIST_OUT (area) = NULL;
546       if (PREFIX_NAME_OUT (area))
547         free (PREFIX_NAME_OUT (area));
548
549       PREFIX_NAME_OUT (area) = NULL;
550       ospf6_abr_enable_area (area);
551     }
552
553   return CMD_SUCCESS;
554 }
555
556 DEFUN (area_import_list,
557        area_import_list_cmd,
558        "area A.B.C.D import-list NAME",
559        "OSPFv6 area parameters\n"
560        "OSPFv6 area ID in IP address format\n"
561        "Set the filter for networks from other areas announced to the specified one\n"
562        "Name of the acess-list\n")
563 {
564   struct ospf6_area *area;
565   struct access_list *list;
566
567   OSPF6_CMD_AREA_GET(argv[0], area);
568
569   list = access_list_lookup (AFI_IP6, argv[1]);
570
571   IMPORT_LIST (area) = list;
572
573   if (IMPORT_NAME (area))
574     free (IMPORT_NAME (area));
575
576   IMPORT_NAME (area) = strdup (argv[1]);
577   ospf6_abr_reimport (area);
578
579   return CMD_SUCCESS; 
580 }
581
582 DEFUN (no_area_import_list,
583        no_area_import_list_cmd,
584        "no area A.B.C.D import-list NAME",
585        "OSPFv6 area parameters\n"
586        "OSPFv6 area ID in IP address format\n"
587        "Unset the filter for networks announced to other areas\n"
588        "NAme of the access-list\n")
589 {
590   struct ospf6_area *area;
591
592   OSPF6_CMD_AREA_GET(argv[0], area);
593
594   IMPORT_LIST (area) = 0;
595
596   if (IMPORT_NAME (area))
597     free (IMPORT_NAME (area));
598
599   IMPORT_NAME (area) = NULL;
600   ospf6_abr_reimport (area);
601
602   return CMD_SUCCESS;
603 }
604
605 DEFUN (area_export_list,
606        area_export_list_cmd,
607        "area A.B.C.D export-list NAME",
608        "OSPFv6 area parameters\n"
609        "OSPFv6 area ID in IP address format\n"
610        "Set the filter for networks announced to other areas\n"
611        "Name of the acess-list\n")
612 {
613   struct ospf6_area *area;
614   struct access_list *list;
615
616   OSPF6_CMD_AREA_GET(argv[0], area);
617
618   list = access_list_lookup (AFI_IP6, argv[1]);
619
620   EXPORT_LIST (area) = list;
621
622   if (EXPORT_NAME (area))
623     free (EXPORT_NAME (area));
624
625   EXPORT_NAME (area) = strdup (argv[1]);
626   ospf6_abr_enable_area (area);
627
628   return CMD_SUCCESS; 
629 }
630
631 DEFUN (no_area_export_list,
632        no_area_export_list_cmd,
633        "no area A.B.C.D export-list NAME",
634        "OSPFv6 area parameters\n"
635        "OSPFv6 area ID in IP address format\n"
636        "Unset the filter for networks announced to other areas\n"
637        "Name of the access-list\n")
638 {
639   struct ospf6_area *area;
640
641   OSPF6_CMD_AREA_GET(argv[0], area);
642
643   EXPORT_LIST (area) = 0;
644
645   if (EXPORT_NAME (area))
646     free (EXPORT_NAME (area));
647
648   EXPORT_NAME (area) = NULL;
649   ospf6_abr_enable_area (area);
650
651   return CMD_SUCCESS;
652 }
653
654 DEFUN (show_ipv6_ospf6_spf_tree,
655        show_ipv6_ospf6_spf_tree_cmd,
656        "show ipv6 ospf6 spf tree",
657        SHOW_STR
658        IP6_STR
659        OSPF6_STR
660        "Shortest Path First calculation\n"
661        "Show SPF tree\n")
662 {
663   struct listnode *node;
664   struct ospf6_area *oa;
665   struct ospf6_vertex *root;
666   struct ospf6_route *route;
667   struct prefix prefix;
668
669   OSPF6_CMD_CHECK_RUNNING ();
670
671   ospf6_linkstate_prefix (ospf6->router_id, htonl (0), &prefix);
672
673   for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, node, oa))
674     {
675       route = ospf6_route_lookup (&prefix, oa->spf_table);
676       if (route == NULL)
677         {
678           vty_out (vty, "LS entry for root not found in area %s%s",
679                    oa->name, VNL);
680           continue;
681         }
682       root = (struct ospf6_vertex *) route->route_option;
683       ospf6_spf_display_subtree (vty, "", 0, root);
684     }
685
686   return CMD_SUCCESS;
687 }
688
689 DEFUN (show_ipv6_ospf6_area_spf_tree,
690        show_ipv6_ospf6_area_spf_tree_cmd,
691        "show ipv6 ospf6 area A.B.C.D spf tree",
692        SHOW_STR
693        IP6_STR
694        OSPF6_STR
695        OSPF6_AREA_STR
696        OSPF6_AREA_ID_STR
697        "Shortest Path First calculation\n"
698        "Show SPF tree\n")
699 {
700   u_int32_t area_id;
701   struct ospf6_area *oa;
702   struct ospf6_vertex *root;
703   struct ospf6_route *route;
704   struct prefix prefix;
705
706   OSPF6_CMD_CHECK_RUNNING ();
707
708   ospf6_linkstate_prefix (ospf6->router_id, htonl (0), &prefix);
709
710   if (inet_pton (AF_INET, argv[0], &area_id) != 1)
711     {
712       vty_out (vty, "Malformed Area-ID: %s%s", argv[0], VNL);
713       return CMD_SUCCESS;
714     }
715   oa = ospf6_area_lookup (area_id, ospf6);
716   if (oa == NULL)
717     {
718       vty_out (vty, "No such Area: %s%s", argv[0], VNL);
719       return CMD_SUCCESS;
720     }
721
722   route = ospf6_route_lookup (&prefix, oa->spf_table);
723   if (route == NULL)
724     {
725       vty_out (vty, "LS entry for root not found in area %s%s",
726                oa->name, VNL);
727       return CMD_SUCCESS;
728     }
729   root = (struct ospf6_vertex *) route->route_option;
730   ospf6_spf_display_subtree (vty, "", 0, root);
731
732   return CMD_SUCCESS;
733 }
734
735 DEFUN (show_ipv6_ospf6_simulate_spf_tree_root,
736        show_ipv6_ospf6_simulate_spf_tree_root_cmd,
737        "show ipv6 ospf6 simulate spf-tree A.B.C.D area A.B.C.D",
738        SHOW_STR
739        IP6_STR
740        OSPF6_STR
741        "Shortest Path First calculation\n"
742        "Show SPF tree\n"
743        "Specify root's router-id to calculate another router's SPF tree\n")
744 {
745   u_int32_t area_id;
746   struct ospf6_area *oa;
747   struct ospf6_vertex *root;
748   struct ospf6_route *route;
749   struct prefix prefix;
750   u_int32_t router_id;
751   struct ospf6_route_table *spf_table;
752   unsigned char tmp_debug_ospf6_spf = 0;
753
754   OSPF6_CMD_CHECK_RUNNING ();
755
756   inet_pton (AF_INET, argv[0], &router_id);
757   ospf6_linkstate_prefix (router_id, htonl (0), &prefix);
758
759   if (inet_pton (AF_INET, argv[1], &area_id) != 1)
760     {
761       vty_out (vty, "Malformed Area-ID: %s%s", argv[1], VNL);
762       return CMD_SUCCESS;
763     }
764   oa = ospf6_area_lookup (area_id, ospf6);
765   if (oa == NULL)
766     {
767       vty_out (vty, "No such Area: %s%s", argv[1], VNL);
768       return CMD_SUCCESS;
769     }
770
771   tmp_debug_ospf6_spf = conf_debug_ospf6_spf;
772   conf_debug_ospf6_spf = 0;
773
774   spf_table = OSPF6_ROUTE_TABLE_CREATE (NONE, SPF_RESULTS);
775   ospf6_spf_calculation (router_id, spf_table, oa);
776
777   conf_debug_ospf6_spf = tmp_debug_ospf6_spf;
778
779   route = ospf6_route_lookup (&prefix, spf_table);
780   if (route == NULL)
781     {
782       ospf6_spf_table_finish (spf_table);
783       ospf6_route_table_delete (spf_table);
784       return CMD_SUCCESS;
785     }
786   root = (struct ospf6_vertex *) route->route_option;
787   ospf6_spf_display_subtree (vty, "", 0, root);
788
789   ospf6_spf_table_finish (spf_table);
790   ospf6_route_table_delete (spf_table);
791
792   return CMD_SUCCESS;
793 }
794
795 void
796 ospf6_area_init (void)
797 {
798   install_element (VIEW_NODE, &show_ipv6_ospf6_spf_tree_cmd);
799   install_element (VIEW_NODE, &show_ipv6_ospf6_area_spf_tree_cmd);
800   install_element (VIEW_NODE, &show_ipv6_ospf6_simulate_spf_tree_root_cmd);
801
802   install_element (OSPF6_NODE, &area_range_cmd);
803   install_element (OSPF6_NODE, &area_range_advertise_cmd);
804   install_element (OSPF6_NODE, &no_area_range_cmd);
805
806   install_element (OSPF6_NODE, &area_import_list_cmd);
807   install_element (OSPF6_NODE, &no_area_import_list_cmd);
808   install_element (OSPF6_NODE, &area_export_list_cmd);
809   install_element (OSPF6_NODE, &no_area_export_list_cmd);
810
811   install_element (OSPF6_NODE, &area_filter_list_cmd);
812   install_element (OSPF6_NODE, &no_area_filter_list_cmd);
813
814 }
815
816