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 48int 49ospf6_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 */ 57static void 58ospf6_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 88static void 89ospf6_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 119static void 120ospf6_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 126static void 127ospf6_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 */ 137struct ospf6_area * 138ospf6_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 193void 194ospf6_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 230struct ospf6_area * 231ospf6_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 243static struct ospf6_area * 244ospf6_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 253void 254ospf6_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 266void 267ospf6_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 292void 293ospf6_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 337DEFUN (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 390ALIAS (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 399DEFUN (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 436void 437ospf6_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 467DEFUN (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 508DEFUN (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 556DEFUN (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 582DEFUN (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 605DEFUN (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 631DEFUN (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 654DEFUN (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 caculation\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_linkstate_prefix (ospf6->router_id, htonl (0), &prefix); 670 671 for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, node, oa)) 672 { 673 route = ospf6_route_lookup (&prefix, oa->spf_table); 674 if (route == NULL) 675 { 676 vty_out (vty, "LS entry for root not found in area %s%s", 677 oa->name, VNL); 678 continue; 679 } 680 root = (struct ospf6_vertex *) route->route_option; 681 ospf6_spf_display_subtree (vty, "", 0, root); 682 } 683 684 return CMD_SUCCESS; 685} 686 687DEFUN (show_ipv6_ospf6_area_spf_tree, 688 show_ipv6_ospf6_area_spf_tree_cmd, 689 "show ipv6 ospf6 area A.B.C.D spf tree", 690 SHOW_STR 691 IP6_STR 692 OSPF6_STR 693 OSPF6_AREA_STR 694 OSPF6_AREA_ID_STR 695 "Shortest Path First caculation\n" 696 "Show SPF tree\n") 697{ 698 u_int32_t area_id; 699 struct ospf6_area *oa; 700 struct ospf6_vertex *root; 701 struct ospf6_route *route; 702 struct prefix prefix; 703 704 ospf6_linkstate_prefix (ospf6->router_id, htonl (0), &prefix); 705 706 if (inet_pton (AF_INET, argv[0], &area_id) != 1) 707 { 708 vty_out (vty, "Malformed Area-ID: %s%s", argv[0], VNL); 709 return CMD_SUCCESS; 710 } 711 oa = ospf6_area_lookup (area_id, ospf6); 712 if (oa == NULL) 713 { 714 vty_out (vty, "No such Area: %s%s", argv[0], VNL); 715 return CMD_SUCCESS; 716 } 717 718 route = ospf6_route_lookup (&prefix, oa->spf_table); 719 if (route == NULL) 720 { 721 vty_out (vty, "LS entry for root not found in area %s%s", 722 oa->name, VNL); 723 return CMD_SUCCESS; 724 } 725 root = (struct ospf6_vertex *) route->route_option; 726 ospf6_spf_display_subtree (vty, "", 0, root); 727 728 return CMD_SUCCESS; 729} 730 731DEFUN (show_ipv6_ospf6_simulate_spf_tree_root, 732 show_ipv6_ospf6_simulate_spf_tree_root_cmd, 733 "show ipv6 ospf6 simulate spf-tree A.B.C.D area A.B.C.D", 734 SHOW_STR 735 IP6_STR 736 OSPF6_STR 737 "Shortest Path First caculation\n" 738 "Show SPF tree\n" 739 "Specify root's router-id to calculate another router's SPF tree\n") 740{ 741 u_int32_t area_id; 742 struct ospf6_area *oa; 743 struct ospf6_vertex *root; 744 struct ospf6_route *route; 745 struct prefix prefix; 746 u_int32_t router_id; 747 struct ospf6_route_table *spf_table; 748 unsigned char tmp_debug_ospf6_spf = 0; 749 750 inet_pton (AF_INET, argv[0], &router_id); 751 ospf6_linkstate_prefix (router_id, htonl (0), &prefix); 752 753 if (inet_pton (AF_INET, argv[1], &area_id) != 1) 754 { 755 vty_out (vty, "Malformed Area-ID: %s%s", argv[1], VNL); 756 return CMD_SUCCESS; 757 } 758 oa = ospf6_area_lookup (area_id, ospf6); 759 if (oa == NULL) 760 { 761 vty_out (vty, "No such Area: %s%s", argv[1], VNL); 762 return CMD_SUCCESS; 763 } 764 765 tmp_debug_ospf6_spf = conf_debug_ospf6_spf; 766 conf_debug_ospf6_spf = 0; 767 768 spf_table = OSPF6_ROUTE_TABLE_CREATE (NONE, SPF_RESULTS); 769 ospf6_spf_calculation (router_id, spf_table, oa); 770 771 conf_debug_ospf6_spf = tmp_debug_ospf6_spf; 772 773 route = ospf6_route_lookup (&prefix, spf_table); 774 if (route == NULL) 775 { 776 ospf6_spf_table_finish (spf_table); 777 ospf6_route_table_delete (spf_table); 778 return CMD_SUCCESS; 779 } 780 root = (struct ospf6_vertex *) route->route_option; 781 ospf6_spf_display_subtree (vty, "", 0, root); 782 783 ospf6_spf_table_finish (spf_table); 784 ospf6_route_table_delete (spf_table); 785 786 return CMD_SUCCESS; 787} 788 789void 790ospf6_area_init (void) 791{ 792 install_element (VIEW_NODE, &show_ipv6_ospf6_spf_tree_cmd); 793 install_element (VIEW_NODE, &show_ipv6_ospf6_area_spf_tree_cmd); 794 install_element (VIEW_NODE, &show_ipv6_ospf6_simulate_spf_tree_root_cmd); 795 796 install_element (ENABLE_NODE, &show_ipv6_ospf6_spf_tree_cmd); 797 install_element (ENABLE_NODE, &show_ipv6_ospf6_area_spf_tree_cmd); 798 install_element (ENABLE_NODE, &show_ipv6_ospf6_simulate_spf_tree_root_cmd); 799 800 install_element (OSPF6_NODE, &area_range_cmd); 801 install_element (OSPF6_NODE, &area_range_advertise_cmd); 802 install_element (OSPF6_NODE, &no_area_range_cmd); 803 804 install_element (OSPF6_NODE, &area_import_list_cmd); 805 install_element (OSPF6_NODE, &no_area_import_list_cmd); 806 install_element (OSPF6_NODE, &area_export_list_cmd); 807 install_element (OSPF6_NODE, &no_area_export_list_cmd); 808 809 install_element (OSPF6_NODE, &area_filter_list_cmd); 810 install_element (OSPF6_NODE, &no_area_filter_list_cmd); 811 812} 813 814 815