]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_area.c
ospf6d: improve ordered shutdown
[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;
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 \f
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 struct prefix_list *plist;
522
523 OSPF6_CMD_AREA_GET (argv[0], area);
524 argc--;
525 argv++;
526
527 plist = prefix_list_lookup (AFI_IP6, argv[0]);
528 if (strncmp (argv[1], "in", 2) == 0)
529 {
530 if (PREFIX_NAME_IN (area))
531 if (strcmp (PREFIX_NAME_IN (area), argv[0]) != 0)
532 return CMD_SUCCESS;
533
534 PREFIX_LIST_IN (area) = NULL;
535 if (PREFIX_NAME_IN (area))
536 free (PREFIX_NAME_IN (area));
537
538 PREFIX_NAME_IN (area) = NULL;
539 ospf6_abr_reimport (area);
540 }
541 else
542 {
543 if (PREFIX_NAME_OUT (area))
544 if (strcmp (PREFIX_NAME_OUT (area), argv[0]) != 0)
545 return CMD_SUCCESS;
546
547 PREFIX_LIST_OUT (area) = NULL;
548 if (PREFIX_NAME_OUT (area))
549 free (PREFIX_NAME_OUT (area));
550
551 PREFIX_NAME_OUT (area) = NULL;
552 ospf6_abr_enable_area (area);
553 }
554
555 return CMD_SUCCESS;
556 }
557
558 DEFUN (area_import_list,
559 area_import_list_cmd,
560 "area A.B.C.D import-list NAME",
561 "OSPFv6 area parameters\n"
562 "OSPFv6 area ID in IP address format\n"
563 "Set the filter for networks from other areas announced to the specified one\n"
564 "Name of the acess-list\n")
565 {
566 struct ospf6_area *area;
567 struct access_list *list;
568
569 OSPF6_CMD_AREA_GET(argv[0], area);
570
571 list = access_list_lookup (AFI_IP6, argv[1]);
572
573 IMPORT_LIST (area) = list;
574
575 if (IMPORT_NAME (area))
576 free (IMPORT_NAME (area));
577
578 IMPORT_NAME (area) = strdup (argv[1]);
579 ospf6_abr_reimport (area);
580
581 return CMD_SUCCESS;
582 }
583
584 DEFUN (no_area_import_list,
585 no_area_import_list_cmd,
586 "no area A.B.C.D import-list NAME",
587 "OSPFv6 area parameters\n"
588 "OSPFv6 area ID in IP address format\n"
589 "Unset the filter for networks announced to other areas\n"
590 "NAme of the access-list\n")
591 {
592 struct ospf6_area *area;
593
594 OSPF6_CMD_AREA_GET(argv[0], area);
595
596 IMPORT_LIST (area) = 0;
597
598 if (IMPORT_NAME (area))
599 free (IMPORT_NAME (area));
600
601 IMPORT_NAME (area) = NULL;
602 ospf6_abr_reimport (area);
603
604 return CMD_SUCCESS;
605 }
606
607 DEFUN (area_export_list,
608 area_export_list_cmd,
609 "area A.B.C.D export-list NAME",
610 "OSPFv6 area parameters\n"
611 "OSPFv6 area ID in IP address format\n"
612 "Set the filter for networks announced to other areas\n"
613 "Name of the acess-list\n")
614 {
615 struct ospf6_area *area;
616 struct access_list *list;
617
618 OSPF6_CMD_AREA_GET(argv[0], area);
619
620 list = access_list_lookup (AFI_IP6, argv[1]);
621
622 EXPORT_LIST (area) = list;
623
624 if (EXPORT_NAME (area))
625 free (EXPORT_NAME (area));
626
627 EXPORT_NAME (area) = strdup (argv[1]);
628 ospf6_abr_enable_area (area);
629
630 return CMD_SUCCESS;
631 }
632
633 DEFUN (no_area_export_list,
634 no_area_export_list_cmd,
635 "no area A.B.C.D export-list NAME",
636 "OSPFv6 area parameters\n"
637 "OSPFv6 area ID in IP address format\n"
638 "Unset the filter for networks announced to other areas\n"
639 "Name of the access-list\n")
640 {
641 struct ospf6_area *area;
642
643 OSPF6_CMD_AREA_GET(argv[0], area);
644
645 EXPORT_LIST (area) = 0;
646
647 if (EXPORT_NAME (area))
648 free (EXPORT_NAME (area));
649
650 EXPORT_NAME (area) = NULL;
651 ospf6_abr_enable_area (area);
652
653 return CMD_SUCCESS;
654 }
655
656 DEFUN (show_ipv6_ospf6_spf_tree,
657 show_ipv6_ospf6_spf_tree_cmd,
658 "show ipv6 ospf6 spf tree",
659 SHOW_STR
660 IP6_STR
661 OSPF6_STR
662 "Shortest Path First caculation\n"
663 "Show SPF tree\n")
664 {
665 struct listnode *node;
666 struct ospf6_area *oa;
667 struct ospf6_vertex *root;
668 struct ospf6_route *route;
669 struct prefix prefix;
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 caculation\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_linkstate_prefix (ospf6->router_id, htonl (0), &prefix);
707
708 if (inet_pton (AF_INET, argv[0], &area_id) != 1)
709 {
710 vty_out (vty, "Malformed Area-ID: %s%s", argv[0], VNL);
711 return CMD_SUCCESS;
712 }
713 oa = ospf6_area_lookup (area_id, ospf6);
714 if (oa == NULL)
715 {
716 vty_out (vty, "No such Area: %s%s", argv[0], VNL);
717 return CMD_SUCCESS;
718 }
719
720 route = ospf6_route_lookup (&prefix, oa->spf_table);
721 if (route == NULL)
722 {
723 vty_out (vty, "LS entry for root not found in area %s%s",
724 oa->name, VNL);
725 return CMD_SUCCESS;
726 }
727 root = (struct ospf6_vertex *) route->route_option;
728 ospf6_spf_display_subtree (vty, "", 0, root);
729
730 return CMD_SUCCESS;
731 }
732
733 DEFUN (show_ipv6_ospf6_simulate_spf_tree_root,
734 show_ipv6_ospf6_simulate_spf_tree_root_cmd,
735 "show ipv6 ospf6 simulate spf-tree A.B.C.D area A.B.C.D",
736 SHOW_STR
737 IP6_STR
738 OSPF6_STR
739 "Shortest Path First caculation\n"
740 "Show SPF tree\n"
741 "Specify root's router-id to calculate another router's SPF tree\n")
742 {
743 u_int32_t area_id;
744 struct ospf6_area *oa;
745 struct ospf6_vertex *root;
746 struct ospf6_route *route;
747 struct prefix prefix;
748 u_int32_t router_id;
749 struct ospf6_route_table *spf_table;
750 unsigned char tmp_debug_ospf6_spf = 0;
751
752 inet_pton (AF_INET, argv[0], &router_id);
753 ospf6_linkstate_prefix (router_id, htonl (0), &prefix);
754
755 if (inet_pton (AF_INET, argv[1], &area_id) != 1)
756 {
757 vty_out (vty, "Malformed Area-ID: %s%s", argv[1], VNL);
758 return CMD_SUCCESS;
759 }
760 oa = ospf6_area_lookup (area_id, ospf6);
761 if (oa == NULL)
762 {
763 vty_out (vty, "No such Area: %s%s", argv[1], VNL);
764 return CMD_SUCCESS;
765 }
766
767 tmp_debug_ospf6_spf = conf_debug_ospf6_spf;
768 conf_debug_ospf6_spf = 0;
769
770 spf_table = OSPF6_ROUTE_TABLE_CREATE (NONE, SPF_RESULTS);
771 ospf6_spf_calculation (router_id, spf_table, oa);
772
773 conf_debug_ospf6_spf = tmp_debug_ospf6_spf;
774
775 route = ospf6_route_lookup (&prefix, spf_table);
776 if (route == NULL)
777 {
778 ospf6_spf_table_finish (spf_table);
779 ospf6_route_table_delete (spf_table);
780 return CMD_SUCCESS;
781 }
782 root = (struct ospf6_vertex *) route->route_option;
783 ospf6_spf_display_subtree (vty, "", 0, root);
784
785 ospf6_spf_table_finish (spf_table);
786 ospf6_route_table_delete (spf_table);
787
788 return CMD_SUCCESS;
789 }
790
791 void
792 ospf6_area_init (void)
793 {
794 install_element (VIEW_NODE, &show_ipv6_ospf6_spf_tree_cmd);
795 install_element (VIEW_NODE, &show_ipv6_ospf6_area_spf_tree_cmd);
796 install_element (VIEW_NODE, &show_ipv6_ospf6_simulate_spf_tree_root_cmd);
797
798 install_element (ENABLE_NODE, &show_ipv6_ospf6_spf_tree_cmd);
799 install_element (ENABLE_NODE, &show_ipv6_ospf6_area_spf_tree_cmd);
800 install_element (ENABLE_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