2 * Copyright (C) 2003 Yasuhiro Ohara
4 * This file is part of GNU Zebra.
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
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.
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.
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"
49 ospf6_area_cmp (void *va, void *vb)
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);
56 /* schedule routing table recalculation */
58 ospf6_area_lsdb_hook_add (struct ospf6_lsa *lsa)
60 switch (ntohs (lsa->header->type))
62 case OSPF6_LSTYPE_ROUTER:
63 case OSPF6_LSTYPE_NETWORK:
64 if (IS_OSPF6_DEBUG_EXAMIN_TYPE (lsa->header->type))
66 zlog_debug ("Examin %s", lsa->name);
67 zlog_debug ("Schedule SPF Calculation for %s",
68 OSPF6_AREA (lsa->lsdb->data)->name);
70 ospf6_spf_schedule (OSPF6_PROCESS(OSPF6_AREA (lsa->lsdb->data)->ospf6),
71 ospf6_lsadd_to_spf_reason(lsa));
74 case OSPF6_LSTYPE_INTRA_PREFIX:
75 ospf6_intra_prefix_lsa_add (lsa);
78 case OSPF6_LSTYPE_INTER_PREFIX:
79 case OSPF6_LSTYPE_INTER_ROUTER:
80 ospf6_abr_examin_summary (lsa, (struct ospf6_area *) lsa->lsdb->data);
89 ospf6_area_lsdb_hook_remove (struct ospf6_lsa *lsa)
91 switch (ntohs (lsa->header->type))
93 case OSPF6_LSTYPE_ROUTER:
94 case OSPF6_LSTYPE_NETWORK:
95 if (IS_OSPF6_DEBUG_EXAMIN_TYPE (lsa->header->type))
97 zlog_debug ("LSA disappearing: %s", lsa->name);
98 zlog_debug ("Schedule SPF Calculation for %s",
99 OSPF6_AREA (lsa->lsdb->data)->name);
101 ospf6_spf_schedule (OSPF6_PROCESS(OSPF6_AREA (lsa->lsdb->data)->ospf6),
102 ospf6_lsremove_to_spf_reason(lsa));
105 case OSPF6_LSTYPE_INTRA_PREFIX:
106 ospf6_intra_prefix_lsa_remove (lsa);
109 case OSPF6_LSTYPE_INTER_PREFIX:
110 case OSPF6_LSTYPE_INTER_ROUTER:
111 ospf6_abr_examin_summary (lsa, (struct ospf6_area *) lsa->lsdb->data);
120 ospf6_area_route_hook_add (struct ospf6_route *route)
122 struct ospf6_route *copy = ospf6_route_copy (route);
123 ospf6_route_add (copy, ospf6->route_table);
127 ospf6_area_route_hook_remove (struct ospf6_route *route)
129 struct ospf6_route *copy;
131 copy = ospf6_route_lookup_identical (route, ospf6->route_table);
133 ospf6_route_remove (copy, ospf6->route_table);
136 /* Make new area structure */
138 ospf6_area_create (u_int32_t area_id, struct ospf6 *o)
140 struct ospf6_area *oa;
141 struct ospf6_route *route;
143 oa = XCALLOC (MTYPE_OSPF6_AREA, sizeof (struct ospf6_area));
145 inet_ntop (AF_INET, &area_id, oa->name, sizeof (oa->name));
146 oa->area_id = area_id;
147 oa->if_list = list_new ();
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);
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;
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;
168 /* set default options */
169 if (CHECK_FLAG (o->flag, OSPF6_STUB_ROUTER))
171 OSPF6_OPT_CLEAR (oa->options, OSPF6_OPT_V6);
172 OSPF6_OPT_CLEAR (oa->options, OSPF6_OPT_R);
176 OSPF6_OPT_SET (oa->options, OSPF6_OPT_V6);
177 OSPF6_OPT_SET (oa->options, OSPF6_OPT_R);
180 OSPF6_OPT_SET (oa->options, OSPF6_OPT_E);
183 listnode_add_sort (o->area_list, oa);
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);
194 ospf6_area_delete (struct ospf6_area *oa)
197 struct ospf6_interface *oi;
199 ospf6_route_table_delete (oa->range_table);
200 ospf6_route_table_delete (oa->summary_prefix);
201 ospf6_route_table_delete (oa->summary_router);
203 /* The ospf6_interface structs store configuration
204 * information which should not be lost/reset when
206 * So just detach the interface from the area and
208 for (ALL_LIST_ELEMENTS_RO (oa->if_list, n, oi))
211 list_delete (oa->if_list);
213 ospf6_lsdb_delete (oa->lsdb);
214 ospf6_lsdb_delete (oa->lsdb_self);
216 ospf6_spf_table_finish (oa->spf_table);
217 ospf6_route_table_delete (oa->spf_table);
218 ospf6_route_table_delete (oa->route_table);
220 THREAD_OFF (oa->thread_spf_calculation);
221 THREAD_OFF (oa->thread_route_calculation);
223 listnode_delete (oa->ospf6->area_list, oa);
227 XFREE (MTYPE_OSPF6_AREA, oa);
231 ospf6_area_lookup (u_int32_t area_id, struct ospf6 *ospf6)
233 struct ospf6_area *oa;
236 for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, n, oa))
237 if (oa->area_id == area_id)
240 return (struct ospf6_area *) NULL;
243 static struct ospf6_area *
244 ospf6_area_get (u_int32_t area_id, struct ospf6 *o)
246 struct ospf6_area *oa;
247 oa = ospf6_area_lookup (area_id, o);
249 oa = ospf6_area_create (area_id, o);
254 ospf6_area_enable (struct ospf6_area *oa)
256 struct listnode *node, *nnode;
257 struct ospf6_interface *oi;
259 SET_FLAG (oa->flag, OSPF6_AREA_ENABLE);
261 for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi))
262 ospf6_interface_enable (oi);
263 ospf6_abr_enable_area (oa);
267 ospf6_area_disable (struct ospf6_area *oa)
269 struct listnode *node, *nnode;
270 struct ospf6_interface *oi;
272 UNSET_FLAG (oa->flag, OSPF6_AREA_ENABLE);
274 for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi))
275 ospf6_interface_disable (oi);
277 ospf6_abr_disable_area (oa);
278 ospf6_lsdb_remove_all (oa->lsdb);
279 ospf6_lsdb_remove_all (oa->lsdb_self);
281 ospf6_spf_table_finish(oa->spf_table);
282 ospf6_route_remove_all(oa->route_table);
284 THREAD_OFF (oa->thread_spf_calculation);
285 THREAD_OFF (oa->thread_route_calculation);
287 THREAD_OFF (oa->thread_router_lsa);
288 THREAD_OFF (oa->thread_intra_prefix_lsa);
293 ospf6_area_show (struct vty *vty, struct ospf6_area *oa)
296 struct ospf6_interface *oi;
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);
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);
306 vty_out (vty, "%s", VNL);
310 #define OSPF6_CMD_AREA_LOOKUP(str, oa) \
312 u_int32_t area_id = 0; \
313 if (inet_pton (AF_INET, str, &area_id) != 1) \
315 vty_out (vty, "Malformed Area-ID: %s%s", str, VNL); \
316 return CMD_SUCCESS; \
318 oa = ospf6_area_lookup (area_id, ospf6); \
321 vty_out (vty, "No such Area: %s%s", str, VNL); \
322 return CMD_SUCCESS; \
326 #define OSPF6_CMD_AREA_GET(str, oa) \
328 u_int32_t area_id = 0; \
329 if (inet_pton (AF_INET, str, &area_id) != 1) \
331 vty_out (vty, "Malformed Area-ID: %s%s", str, VNL); \
332 return CMD_SUCCESS; \
334 oa = ospf6_area_get (area_id, ospf6); \
339 "area A.B.C.D range X:X::X:X/M",
340 "OSPF area parameters\n"
342 "Configured address range\n"
343 "Specify IPv6 prefix\n"
347 struct ospf6_area *oa;
348 struct prefix prefix;
349 struct ospf6_route *range;
351 OSPF6_CMD_AREA_GET (argv[0], oa);
355 ret = str2prefix (argv[0], &prefix);
356 if (ret != 1 || prefix.family != AF_INET6)
358 vty_out (vty, "Malformed argument: %s%s", argv[0], VNL);
364 range = ospf6_route_lookup (&prefix, oa->range_table);
367 range = ospf6_route_create ();
368 range->type = OSPF6_DEST_TYPE_RANGE;
369 range->prefix = prefix;
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);
382 vty_out (vty, "Range already defined: %s%s", argv[-1], VNL);
386 ospf6_route_add (range, oa->range_table);
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"
395 "Configured address range\n"
396 "Specify IPv6 prefix\n"
399 DEFUN (no_area_range,
401 "no area A.B.C.D range X:X::X:X/M",
402 "OSPF area parameters\n"
404 "Configured address range\n"
405 "Specify IPv6 prefix\n"
409 struct ospf6_area *oa;
410 struct prefix prefix;
411 struct ospf6_route *range;
413 OSPF6_CMD_AREA_GET (argv[0], oa);
417 ret = str2prefix (argv[0], &prefix);
418 if (ret != 1 || prefix.family != AF_INET6)
420 vty_out (vty, "Malformed argument: %s%s", argv[0], VNL);
424 range = ospf6_route_lookup (&prefix, oa->range_table);
427 vty_out (vty, "Range %s does not exists.%s", argv[0], VNL);
431 ospf6_route_remove (range, oa->range_table);
437 ospf6_area_config_write (struct vty *vty)
439 struct listnode *node;
440 struct ospf6_area *oa;
441 struct ospf6_route *range;
444 for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, node, oa))
446 for (range = ospf6_route_head (oa->range_table); range;
447 range = ospf6_route_next (range))
449 prefix2str (&range->prefix, buf, sizeof (buf));
450 vty_out (vty, " area %s range %s%s", oa->name, buf, VNL);
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);
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")
478 struct ospf6_area *area;
479 struct prefix_list *plist;
481 OSPF6_CMD_AREA_GET (argv[0], area);
485 plist = prefix_list_lookup (AFI_IP6, argv[0]);
486 if (strncmp (argv[1], "in", 2) == 0)
488 PREFIX_LIST_IN (area) = plist;
489 if (PREFIX_NAME_IN (area))
490 free (PREFIX_NAME_IN (area));
492 PREFIX_NAME_IN (area) = strdup (argv[0]);
493 ospf6_abr_reimport (area);
497 PREFIX_LIST_OUT (area) = plist;
498 if (PREFIX_NAME_OUT (area))
499 free (PREFIX_NAME_OUT (area));
501 PREFIX_NAME_OUT (area) = strdup (argv[0]);
502 ospf6_abr_enable_area (area);
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)",
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")
520 struct ospf6_area *area;
522 OSPF6_CMD_AREA_GET (argv[0], area);
526 if (strncmp (argv[1], "in", 2) == 0)
528 if (PREFIX_NAME_IN (area))
529 if (strcmp (PREFIX_NAME_IN (area), argv[0]) != 0)
532 PREFIX_LIST_IN (area) = NULL;
533 if (PREFIX_NAME_IN (area))
534 free (PREFIX_NAME_IN (area));
536 PREFIX_NAME_IN (area) = NULL;
537 ospf6_abr_reimport (area);
541 if (PREFIX_NAME_OUT (area))
542 if (strcmp (PREFIX_NAME_OUT (area), argv[0]) != 0)
545 PREFIX_LIST_OUT (area) = NULL;
546 if (PREFIX_NAME_OUT (area))
547 free (PREFIX_NAME_OUT (area));
549 PREFIX_NAME_OUT (area) = NULL;
550 ospf6_abr_enable_area (area);
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")
564 struct ospf6_area *area;
565 struct access_list *list;
567 OSPF6_CMD_AREA_GET(argv[0], area);
569 list = access_list_lookup (AFI_IP6, argv[1]);
571 IMPORT_LIST (area) = list;
573 if (IMPORT_NAME (area))
574 free (IMPORT_NAME (area));
576 IMPORT_NAME (area) = strdup (argv[1]);
577 ospf6_abr_reimport (area);
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")
590 struct ospf6_area *area;
592 OSPF6_CMD_AREA_GET(argv[0], area);
594 IMPORT_LIST (area) = 0;
596 if (IMPORT_NAME (area))
597 free (IMPORT_NAME (area));
599 IMPORT_NAME (area) = NULL;
600 ospf6_abr_reimport (area);
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")
613 struct ospf6_area *area;
614 struct access_list *list;
616 OSPF6_CMD_AREA_GET(argv[0], area);
618 list = access_list_lookup (AFI_IP6, argv[1]);
620 EXPORT_LIST (area) = list;
622 if (EXPORT_NAME (area))
623 free (EXPORT_NAME (area));
625 EXPORT_NAME (area) = strdup (argv[1]);
626 ospf6_abr_enable_area (area);
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")
639 struct ospf6_area *area;
641 OSPF6_CMD_AREA_GET(argv[0], area);
643 EXPORT_LIST (area) = 0;
645 if (EXPORT_NAME (area))
646 free (EXPORT_NAME (area));
648 EXPORT_NAME (area) = NULL;
649 ospf6_abr_enable_area (area);
654 DEFUN (show_ipv6_ospf6_spf_tree,
655 show_ipv6_ospf6_spf_tree_cmd,
656 "show ipv6 ospf6 spf tree",
660 "Shortest Path First caculation\n"
663 struct listnode *node;
664 struct ospf6_area *oa;
665 struct ospf6_vertex *root;
666 struct ospf6_route *route;
667 struct prefix prefix;
669 OSPF6_CMD_CHECK_RUNNING ();
671 ospf6_linkstate_prefix (ospf6->router_id, htonl (0), &prefix);
673 for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, node, oa))
675 route = ospf6_route_lookup (&prefix, oa->spf_table);
678 vty_out (vty, "LS entry for root not found in area %s%s",
682 root = (struct ospf6_vertex *) route->route_option;
683 ospf6_spf_display_subtree (vty, "", 0, root);
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",
697 "Shortest Path First caculation\n"
701 struct ospf6_area *oa;
702 struct ospf6_vertex *root;
703 struct ospf6_route *route;
704 struct prefix prefix;
706 OSPF6_CMD_CHECK_RUNNING ();
708 ospf6_linkstate_prefix (ospf6->router_id, htonl (0), &prefix);
710 if (inet_pton (AF_INET, argv[0], &area_id) != 1)
712 vty_out (vty, "Malformed Area-ID: %s%s", argv[0], VNL);
715 oa = ospf6_area_lookup (area_id, ospf6);
718 vty_out (vty, "No such Area: %s%s", argv[0], VNL);
722 route = ospf6_route_lookup (&prefix, oa->spf_table);
725 vty_out (vty, "LS entry for root not found in area %s%s",
729 root = (struct ospf6_vertex *) route->route_option;
730 ospf6_spf_display_subtree (vty, "", 0, root);
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",
741 "Shortest Path First caculation\n"
743 "Specify root's router-id to calculate another router's SPF tree\n")
746 struct ospf6_area *oa;
747 struct ospf6_vertex *root;
748 struct ospf6_route *route;
749 struct prefix prefix;
751 struct ospf6_route_table *spf_table;
752 unsigned char tmp_debug_ospf6_spf = 0;
754 OSPF6_CMD_CHECK_RUNNING ();
756 inet_pton (AF_INET, argv[0], &router_id);
757 ospf6_linkstate_prefix (router_id, htonl (0), &prefix);
759 if (inet_pton (AF_INET, argv[1], &area_id) != 1)
761 vty_out (vty, "Malformed Area-ID: %s%s", argv[1], VNL);
764 oa = ospf6_area_lookup (area_id, ospf6);
767 vty_out (vty, "No such Area: %s%s", argv[1], VNL);
771 tmp_debug_ospf6_spf = conf_debug_ospf6_spf;
772 conf_debug_ospf6_spf = 0;
774 spf_table = OSPF6_ROUTE_TABLE_CREATE (NONE, SPF_RESULTS);
775 ospf6_spf_calculation (router_id, spf_table, oa);
777 conf_debug_ospf6_spf = tmp_debug_ospf6_spf;
779 route = ospf6_route_lookup (&prefix, spf_table);
782 ospf6_spf_table_finish (spf_table);
783 ospf6_route_table_delete (spf_table);
786 root = (struct ospf6_vertex *) route->route_option;
787 ospf6_spf_display_subtree (vty, "", 0, root);
789 ospf6_spf_table_finish (spf_table);
790 ospf6_route_table_delete (spf_table);
796 ospf6_area_init (void)
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);
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);
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);
811 install_element (OSPF6_NODE, &area_filter_list_cmd);
812 install_element (OSPF6_NODE, &no_area_filter_list_cmd);