]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_area.c
b09d9613c0595ec378dce2863c937e56847c0d0f
[mirror_frr.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, *nnode;
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 /* ospf6 interface list */
204 for (ALL_LIST_ELEMENTS (oa->if_list, n, nnode, oi))
205 {
206 ospf6_interface_delete (oi);
207 }
208 list_delete (oa->if_list);
209
210 ospf6_lsdb_delete (oa->lsdb);
211 ospf6_lsdb_delete (oa->lsdb_self);
212
213 ospf6_spf_table_finish (oa->spf_table);
214 ospf6_route_table_delete (oa->spf_table);
215 ospf6_route_table_delete (oa->route_table);
216
217 THREAD_OFF (oa->thread_spf_calculation);
218 THREAD_OFF (oa->thread_route_calculation);
219
220 listnode_delete (oa->ospf6->area_list, oa);
221 oa->ospf6 = NULL;
222
223 /* free area */
224 XFREE (MTYPE_OSPF6_AREA, oa);
225 }
226
227 struct ospf6_area *
228 ospf6_area_lookup (u_int32_t area_id, struct ospf6 *ospf6)
229 {
230 struct ospf6_area *oa;
231 struct listnode *n;
232
233 for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, n, oa))
234 if (oa->area_id == area_id)
235 return oa;
236
237 return (struct ospf6_area *) NULL;
238 }
239
240 static struct ospf6_area *
241 ospf6_area_get (u_int32_t area_id, struct ospf6 *o)
242 {
243 struct ospf6_area *oa;
244 oa = ospf6_area_lookup (area_id, o);
245 if (oa == NULL)
246 oa = ospf6_area_create (area_id, o);
247 return oa;
248 }
249
250 void
251 ospf6_area_enable (struct ospf6_area *oa)
252 {
253 struct listnode *node, *nnode;
254 struct ospf6_interface *oi;
255
256 SET_FLAG (oa->flag, OSPF6_AREA_ENABLE);
257
258 for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi))
259 ospf6_interface_enable (oi);
260 }
261
262 void
263 ospf6_area_disable (struct ospf6_area *oa)
264 {
265 struct listnode *node, *nnode;
266 struct ospf6_interface *oi;
267
268 UNSET_FLAG (oa->flag, OSPF6_AREA_ENABLE);
269
270 for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi))
271 ospf6_interface_disable (oi);
272 }
273
274 \f
275 void
276 ospf6_area_show (struct vty *vty, struct ospf6_area *oa)
277 {
278 struct listnode *i;
279 struct ospf6_interface *oi;
280
281 vty_out (vty, " Area %s%s", oa->name, VNL);
282 vty_out (vty, " Number of Area scoped LSAs is %u%s",
283 oa->lsdb->count, VNL);
284
285 vty_out (vty, " Interface attached to this area:");
286 for (ALL_LIST_ELEMENTS_RO (oa->if_list, i, oi))
287 vty_out (vty, " %s", oi->interface->name);
288
289 vty_out (vty, "%s", VNL);
290 }
291
292
293 #define OSPF6_CMD_AREA_LOOKUP(str, oa) \
294 { \
295 u_int32_t area_id = 0; \
296 if (inet_pton (AF_INET, str, &area_id) != 1) \
297 { \
298 vty_out (vty, "Malformed Area-ID: %s%s", str, VNL); \
299 return CMD_SUCCESS; \
300 } \
301 oa = ospf6_area_lookup (area_id, ospf6); \
302 if (oa == NULL) \
303 { \
304 vty_out (vty, "No such Area: %s%s", str, VNL); \
305 return CMD_SUCCESS; \
306 } \
307 }
308
309 #define OSPF6_CMD_AREA_GET(str, oa) \
310 { \
311 u_int32_t area_id = 0; \
312 if (inet_pton (AF_INET, str, &area_id) != 1) \
313 { \
314 vty_out (vty, "Malformed Area-ID: %s%s", str, VNL); \
315 return CMD_SUCCESS; \
316 } \
317 oa = ospf6_area_get (area_id, ospf6); \
318 }
319
320 DEFUN (area_range,
321 area_range_cmd,
322 "area A.B.C.D range X:X::X:X/M",
323 "OSPF area parameters\n"
324 OSPF6_AREA_ID_STR
325 "Configured address range\n"
326 "Specify IPv6 prefix\n"
327 )
328 {
329 int ret;
330 struct ospf6_area *oa;
331 struct prefix prefix;
332 struct ospf6_route *range;
333
334 OSPF6_CMD_AREA_GET (argv[0], oa);
335 argc--;
336 argv++;
337
338 ret = str2prefix (argv[0], &prefix);
339 if (ret != 1 || prefix.family != AF_INET6)
340 {
341 vty_out (vty, "Malformed argument: %s%s", argv[0], VNL);
342 return CMD_SUCCESS;
343 }
344 argc--;
345 argv++;
346
347 range = ospf6_route_lookup (&prefix, oa->range_table);
348 if (range == NULL)
349 {
350 range = ospf6_route_create ();
351 range->type = OSPF6_DEST_TYPE_RANGE;
352 range->prefix = prefix;
353 }
354
355 if (argc)
356 {
357 if (! strcmp (argv[0], "not-advertise"))
358 SET_FLAG (range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
359 else if (! strcmp (argv[0], "advertise"))
360 UNSET_FLAG (range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
361 }
362
363 if (range->rnode)
364 {
365 vty_out (vty, "Range already defined: %s%s", argv[-1], VNL);
366 return CMD_WARNING;
367 }
368
369 ospf6_route_add (range, oa->range_table);
370 return CMD_SUCCESS;
371 }
372
373 ALIAS (area_range,
374 area_range_advertise_cmd,
375 "area A.B.C.D range X:X::X:X/M (advertise|not-advertise)",
376 "OSPF area parameters\n"
377 OSPF6_AREA_ID_STR
378 "Configured address range\n"
379 "Specify IPv6 prefix\n"
380 )
381
382 DEFUN (no_area_range,
383 no_area_range_cmd,
384 "no area A.B.C.D range X:X::X:X/M",
385 "OSPF area parameters\n"
386 OSPF6_AREA_ID_STR
387 "Configured address range\n"
388 "Specify IPv6 prefix\n"
389 )
390 {
391 int ret;
392 struct ospf6_area *oa;
393 struct prefix prefix;
394 struct ospf6_route *range;
395
396 OSPF6_CMD_AREA_GET (argv[0], oa);
397 argc--;
398 argv++;
399
400 ret = str2prefix (argv[0], &prefix);
401 if (ret != 1 || prefix.family != AF_INET6)
402 {
403 vty_out (vty, "Malformed argument: %s%s", argv[0], VNL);
404 return CMD_SUCCESS;
405 }
406
407 range = ospf6_route_lookup (&prefix, oa->range_table);
408 if (range == NULL)
409 {
410 vty_out (vty, "Range %s does not exists.%s", argv[0], VNL);
411 return CMD_SUCCESS;
412 }
413
414 ospf6_route_remove (range, oa->range_table);
415
416 return CMD_SUCCESS;
417 }
418
419 void
420 ospf6_area_config_write (struct vty *vty)
421 {
422 struct listnode *node;
423 struct ospf6_area *oa;
424 struct ospf6_route *range;
425 char buf[128];
426
427 for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, node, oa))
428 {
429 for (range = ospf6_route_head (oa->range_table); range;
430 range = ospf6_route_next (range))
431 {
432 prefix2str (&range->prefix, buf, sizeof (buf));
433 vty_out (vty, " area %s range %s%s", oa->name, buf, VNL);
434 }
435 if (PREFIX_NAME_IN (oa))
436 vty_out (vty, " area %s filter-list prefix %s in%s",
437 oa->name, PREFIX_NAME_IN (oa), VNL);
438 if (PREFIX_NAME_OUT (oa))
439 vty_out (vty, " area %s filter-list prefix %s out%s",
440 oa->name, PREFIX_NAME_OUT (oa), VNL);
441 if (IMPORT_NAME (oa))
442 vty_out (vty, " area %s import-list %s%s",
443 oa->name, IMPORT_NAME (oa), VNL);
444 if (EXPORT_NAME (oa))
445 vty_out (vty, " area %s export-list %s%s",
446 oa->name, EXPORT_NAME (oa), VNL);
447 }
448 }
449
450 DEFUN (area_filter_list,
451 area_filter_list_cmd,
452 "area A.B.C.D filter-list prefix WORD (in|out)",
453 "OSPFv6 area parameters\n"
454 "OSPFv6 area ID in IP address format\n"
455 "Filter networks between OSPFv6 areas\n"
456 "Filter prefixes between OSPFv6 areas\n"
457 "Name of an IPv6 prefix-list\n"
458 "Filter networks sent to this area\n"
459 "Filter networks sent from this area\n")
460 {
461 struct ospf6_area *area;
462 struct prefix_list *plist;
463
464 OSPF6_CMD_AREA_GET (argv[0], area);
465 argc--;
466 argv++;
467
468 plist = prefix_list_lookup (AFI_IP6, argv[0]);
469 if (strncmp (argv[1], "in", 2) == 0)
470 {
471 PREFIX_LIST_IN (area) = plist;
472 if (PREFIX_NAME_IN (area))
473 free (PREFIX_NAME_IN (area));
474
475 PREFIX_NAME_IN (area) = strdup (argv[0]);
476 ospf6_abr_reimport (area);
477 }
478 else
479 {
480 PREFIX_LIST_OUT (area) = plist;
481 if (PREFIX_NAME_OUT (area))
482 free (PREFIX_NAME_OUT (area));
483
484 PREFIX_NAME_OUT (area) = strdup (argv[0]);
485 ospf6_abr_enable_area (area);
486 }
487
488 return CMD_SUCCESS;
489 }
490
491 DEFUN (no_area_filter_list,
492 no_area_filter_list_cmd,
493 "no area A.B.C.D filter-list prefix WORD (in|out)",
494 NO_STR
495 "OSPFv6 area parameters\n"
496 "OSPFv6 area ID in IP address format\n"
497 "Filter networks between OSPFv6 areas\n"
498 "Filter prefixes between OSPFv6 areas\n"
499 "Name of an IPv6 prefix-list\n"
500 "Filter networks sent to this area\n"
501 "Filter networks sent from this area\n")
502 {
503 struct ospf6_area *area;
504 struct prefix_list *plist;
505
506 OSPF6_CMD_AREA_GET (argv[0], area);
507 argc--;
508 argv++;
509
510 plist = prefix_list_lookup (AFI_IP6, argv[0]);
511 if (strncmp (argv[1], "in", 2) == 0)
512 {
513 if (PREFIX_NAME_IN (area))
514 if (strcmp (PREFIX_NAME_IN (area), argv[0]) != 0)
515 return CMD_SUCCESS;
516
517 PREFIX_LIST_IN (area) = NULL;
518 if (PREFIX_NAME_IN (area))
519 free (PREFIX_NAME_IN (area));
520
521 PREFIX_NAME_IN (area) = NULL;
522 ospf6_abr_reimport (area);
523 }
524 else
525 {
526 if (PREFIX_NAME_OUT (area))
527 if (strcmp (PREFIX_NAME_OUT (area), argv[0]) != 0)
528 return CMD_SUCCESS;
529
530 PREFIX_LIST_OUT (area) = NULL;
531 if (PREFIX_NAME_OUT (area))
532 free (PREFIX_NAME_OUT (area));
533
534 PREFIX_NAME_OUT (area) = NULL;
535 ospf6_abr_enable_area (area);
536 }
537
538 return CMD_SUCCESS;
539 }
540
541 DEFUN (area_import_list,
542 area_import_list_cmd,
543 "area A.B.C.D import-list NAME",
544 "OSPFv6 area parameters\n"
545 "OSPFv6 area ID in IP address format\n"
546 "Set the filter for networks from other areas announced to the specified one\n"
547 "Name of the acess-list\n")
548 {
549 struct ospf6_area *area;
550 struct access_list *list;
551
552 OSPF6_CMD_AREA_GET(argv[0], area);
553
554 list = access_list_lookup (AFI_IP6, argv[1]);
555
556 IMPORT_LIST (area) = list;
557
558 if (IMPORT_NAME (area))
559 free (IMPORT_NAME (area));
560
561 IMPORT_NAME (area) = strdup (argv[1]);
562 ospf6_abr_reimport (area);
563
564 return CMD_SUCCESS;
565 }
566
567 DEFUN (no_area_import_list,
568 no_area_import_list_cmd,
569 "no area A.B.C.D import-list NAME",
570 "OSPFv6 area parameters\n"
571 "OSPFv6 area ID in IP address format\n"
572 "Unset the filter for networks announced to other areas\n"
573 "NAme of the access-list\n")
574 {
575 struct ospf6_area *area;
576
577 OSPF6_CMD_AREA_GET(argv[0], area);
578
579 IMPORT_LIST (area) = 0;
580
581 if (IMPORT_NAME (area))
582 free (IMPORT_NAME (area));
583
584 IMPORT_NAME (area) = NULL;
585 ospf6_abr_reimport (area);
586
587 return CMD_SUCCESS;
588 }
589
590 DEFUN (area_export_list,
591 area_export_list_cmd,
592 "area A.B.C.D export-list NAME",
593 "OSPFv6 area parameters\n"
594 "OSPFv6 area ID in IP address format\n"
595 "Set the filter for networks announced to other areas\n"
596 "Name of the acess-list\n")
597 {
598 struct ospf6_area *area;
599 struct access_list *list;
600
601 OSPF6_CMD_AREA_GET(argv[0], area);
602
603 list = access_list_lookup (AFI_IP6, argv[1]);
604
605 EXPORT_LIST (area) = list;
606
607 if (EXPORT_NAME (area))
608 free (EXPORT_NAME (area));
609
610 EXPORT_NAME (area) = strdup (argv[1]);
611 ospf6_abr_enable_area (area);
612
613 return CMD_SUCCESS;
614 }
615
616 DEFUN (no_area_export_list,
617 no_area_export_list_cmd,
618 "no area A.B.C.D export-list NAME",
619 "OSPFv6 area parameters\n"
620 "OSPFv6 area ID in IP address format\n"
621 "Unset the filter for networks announced to other areas\n"
622 "Name of the access-list\n")
623 {
624 struct ospf6_area *area;
625
626 OSPF6_CMD_AREA_GET(argv[0], area);
627
628 EXPORT_LIST (area) = 0;
629
630 if (EXPORT_NAME (area))
631 free (EXPORT_NAME (area));
632
633 EXPORT_NAME (area) = NULL;
634 ospf6_abr_enable_area (area);
635
636 return CMD_SUCCESS;
637 }
638
639 DEFUN (show_ipv6_ospf6_spf_tree,
640 show_ipv6_ospf6_spf_tree_cmd,
641 "show ipv6 ospf6 spf tree",
642 SHOW_STR
643 IP6_STR
644 OSPF6_STR
645 "Shortest Path First caculation\n"
646 "Show SPF tree\n")
647 {
648 struct listnode *node;
649 struct ospf6_area *oa;
650 struct ospf6_vertex *root;
651 struct ospf6_route *route;
652 struct prefix prefix;
653
654 ospf6_linkstate_prefix (ospf6->router_id, htonl (0), &prefix);
655
656 for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, node, oa))
657 {
658 route = ospf6_route_lookup (&prefix, oa->spf_table);
659 if (route == NULL)
660 {
661 vty_out (vty, "LS entry for root not found in area %s%s",
662 oa->name, VNL);
663 continue;
664 }
665 root = (struct ospf6_vertex *) route->route_option;
666 ospf6_spf_display_subtree (vty, "", 0, root);
667 }
668
669 return CMD_SUCCESS;
670 }
671
672 DEFUN (show_ipv6_ospf6_area_spf_tree,
673 show_ipv6_ospf6_area_spf_tree_cmd,
674 "show ipv6 ospf6 area A.B.C.D spf tree",
675 SHOW_STR
676 IP6_STR
677 OSPF6_STR
678 OSPF6_AREA_STR
679 OSPF6_AREA_ID_STR
680 "Shortest Path First caculation\n"
681 "Show SPF tree\n")
682 {
683 u_int32_t area_id;
684 struct ospf6_area *oa;
685 struct ospf6_vertex *root;
686 struct ospf6_route *route;
687 struct prefix prefix;
688
689 ospf6_linkstate_prefix (ospf6->router_id, htonl (0), &prefix);
690
691 if (inet_pton (AF_INET, argv[0], &area_id) != 1)
692 {
693 vty_out (vty, "Malformed Area-ID: %s%s", argv[0], VNL);
694 return CMD_SUCCESS;
695 }
696 oa = ospf6_area_lookup (area_id, ospf6);
697 if (oa == NULL)
698 {
699 vty_out (vty, "No such Area: %s%s", argv[0], VNL);
700 return CMD_SUCCESS;
701 }
702
703 route = ospf6_route_lookup (&prefix, oa->spf_table);
704 if (route == NULL)
705 {
706 vty_out (vty, "LS entry for root not found in area %s%s",
707 oa->name, VNL);
708 return CMD_SUCCESS;
709 }
710 root = (struct ospf6_vertex *) route->route_option;
711 ospf6_spf_display_subtree (vty, "", 0, root);
712
713 return CMD_SUCCESS;
714 }
715
716 DEFUN (show_ipv6_ospf6_simulate_spf_tree_root,
717 show_ipv6_ospf6_simulate_spf_tree_root_cmd,
718 "show ipv6 ospf6 simulate spf-tree A.B.C.D area A.B.C.D",
719 SHOW_STR
720 IP6_STR
721 OSPF6_STR
722 "Shortest Path First caculation\n"
723 "Show SPF tree\n"
724 "Specify root's router-id to calculate another router's SPF tree\n")
725 {
726 u_int32_t area_id;
727 struct ospf6_area *oa;
728 struct ospf6_vertex *root;
729 struct ospf6_route *route;
730 struct prefix prefix;
731 u_int32_t router_id;
732 struct ospf6_route_table *spf_table;
733 unsigned char tmp_debug_ospf6_spf = 0;
734
735 inet_pton (AF_INET, argv[0], &router_id);
736 ospf6_linkstate_prefix (router_id, htonl (0), &prefix);
737
738 if (inet_pton (AF_INET, argv[1], &area_id) != 1)
739 {
740 vty_out (vty, "Malformed Area-ID: %s%s", argv[1], VNL);
741 return CMD_SUCCESS;
742 }
743 oa = ospf6_area_lookup (area_id, ospf6);
744 if (oa == NULL)
745 {
746 vty_out (vty, "No such Area: %s%s", argv[1], VNL);
747 return CMD_SUCCESS;
748 }
749
750 tmp_debug_ospf6_spf = conf_debug_ospf6_spf;
751 conf_debug_ospf6_spf = 0;
752
753 spf_table = OSPF6_ROUTE_TABLE_CREATE (NONE, SPF_RESULTS);
754 ospf6_spf_calculation (router_id, spf_table, oa);
755
756 conf_debug_ospf6_spf = tmp_debug_ospf6_spf;
757
758 route = ospf6_route_lookup (&prefix, spf_table);
759 if (route == NULL)
760 {
761 ospf6_spf_table_finish (spf_table);
762 ospf6_route_table_delete (spf_table);
763 return CMD_SUCCESS;
764 }
765 root = (struct ospf6_vertex *) route->route_option;
766 ospf6_spf_display_subtree (vty, "", 0, root);
767
768 ospf6_spf_table_finish (spf_table);
769 ospf6_route_table_delete (spf_table);
770
771 return CMD_SUCCESS;
772 }
773
774 void
775 ospf6_area_init (void)
776 {
777 install_element (VIEW_NODE, &show_ipv6_ospf6_spf_tree_cmd);
778 install_element (VIEW_NODE, &show_ipv6_ospf6_area_spf_tree_cmd);
779 install_element (VIEW_NODE, &show_ipv6_ospf6_simulate_spf_tree_root_cmd);
780
781 install_element (ENABLE_NODE, &show_ipv6_ospf6_spf_tree_cmd);
782 install_element (ENABLE_NODE, &show_ipv6_ospf6_area_spf_tree_cmd);
783 install_element (ENABLE_NODE, &show_ipv6_ospf6_simulate_spf_tree_root_cmd);
784
785 install_element (OSPF6_NODE, &area_range_cmd);
786 install_element (OSPF6_NODE, &area_range_advertise_cmd);
787 install_element (OSPF6_NODE, &no_area_range_cmd);
788
789 install_element (OSPF6_NODE, &area_import_list_cmd);
790 install_element (OSPF6_NODE, &no_area_import_list_cmd);
791 install_element (OSPF6_NODE, &area_export_list_cmd);
792 install_element (OSPF6_NODE, &no_area_export_list_cmd);
793
794 install_element (OSPF6_NODE, &area_filter_list_cmd);
795 install_element (OSPF6_NODE, &no_area_filter_list_cmd);
796
797 }
798
799