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_AREA (lsa
->lsdb
->data
));
73 case OSPF6_LSTYPE_INTRA_PREFIX
:
74 ospf6_intra_prefix_lsa_add (lsa
);
77 case OSPF6_LSTYPE_INTER_PREFIX
:
78 case OSPF6_LSTYPE_INTER_ROUTER
:
79 ospf6_abr_examin_summary (lsa
, (struct ospf6_area
*) lsa
->lsdb
->data
);
88 ospf6_area_lsdb_hook_remove (struct ospf6_lsa
*lsa
)
90 switch (ntohs (lsa
->header
->type
))
92 case OSPF6_LSTYPE_ROUTER
:
93 case OSPF6_LSTYPE_NETWORK
:
94 if (IS_OSPF6_DEBUG_EXAMIN_TYPE (lsa
->header
->type
))
96 zlog_debug ("LSA disappearing: %s", lsa
->name
);
97 zlog_debug ("Schedule SPF Calculation for %s",
98 OSPF6_AREA (lsa
->lsdb
->data
)->name
);
100 ospf6_spf_schedule (OSPF6_AREA (lsa
->lsdb
->data
));
103 case OSPF6_LSTYPE_INTRA_PREFIX
:
104 ospf6_intra_prefix_lsa_remove (lsa
);
107 case OSPF6_LSTYPE_INTER_PREFIX
:
108 case OSPF6_LSTYPE_INTER_ROUTER
:
109 ospf6_abr_examin_summary (lsa
, (struct ospf6_area
*) lsa
->lsdb
->data
);
118 ospf6_area_route_hook_add (struct ospf6_route
*route
)
120 struct ospf6_route
*copy
= ospf6_route_copy (route
);
121 ospf6_route_add (copy
, ospf6
->route_table
);
125 ospf6_area_route_hook_remove (struct ospf6_route
*route
)
127 struct ospf6_route
*copy
;
129 copy
= ospf6_route_lookup_identical (route
, ospf6
->route_table
);
131 ospf6_route_remove (copy
, ospf6
->route_table
);
134 /* Make new area structure */
136 ospf6_area_create (u_int32_t area_id
, struct ospf6
*o
)
138 struct ospf6_area
*oa
;
139 struct ospf6_route
*route
;
141 oa
= XCALLOC (MTYPE_OSPF6_AREA
, sizeof (struct ospf6_area
));
143 inet_ntop (AF_INET
, &area_id
, oa
->name
, sizeof (oa
->name
));
144 oa
->area_id
= area_id
;
145 oa
->if_list
= list_new ();
147 oa
->lsdb
= ospf6_lsdb_create (oa
);
148 oa
->lsdb
->hook_add
= ospf6_area_lsdb_hook_add
;
149 oa
->lsdb
->hook_remove
= ospf6_area_lsdb_hook_remove
;
150 oa
->lsdb_self
= ospf6_lsdb_create (oa
);
152 oa
->spf_table
= OSPF6_ROUTE_TABLE_CREATE (AREA
, SPF_RESULTS
);
153 oa
->spf_table
->scope
= oa
;
154 oa
->route_table
= OSPF6_ROUTE_TABLE_CREATE (AREA
, ROUTES
);
155 oa
->route_table
->scope
= oa
;
156 oa
->route_table
->hook_add
= ospf6_area_route_hook_add
;
157 oa
->route_table
->hook_remove
= ospf6_area_route_hook_remove
;
159 oa
->range_table
= OSPF6_ROUTE_TABLE_CREATE (AREA
, PREFIX_RANGES
);
160 oa
->range_table
->scope
= oa
;
161 oa
->summary_prefix
= OSPF6_ROUTE_TABLE_CREATE (AREA
, SUMMARY_PREFIXES
);
162 oa
->summary_prefix
->scope
= oa
;
163 oa
->summary_router
= OSPF6_ROUTE_TABLE_CREATE (AREA
, SUMMARY_ROUTERS
);
164 oa
->summary_router
->scope
= oa
;
166 /* set default options */
167 OSPF6_OPT_SET (oa
->options
, OSPF6_OPT_V6
);
168 OSPF6_OPT_SET (oa
->options
, OSPF6_OPT_E
);
169 OSPF6_OPT_SET (oa
->options
, OSPF6_OPT_R
);
172 listnode_add_sort (o
->area_list
, oa
);
174 /* import athoer area's routes as inter-area routes */
175 for (route
= ospf6_route_head (o
->route_table
); route
;
176 route
= ospf6_route_next (route
))
177 ospf6_abr_originate_summary_to_area (route
, oa
);
183 ospf6_area_delete (struct ospf6_area
*oa
)
185 struct listnode
*n
, *nnode
;
186 struct ospf6_interface
*oi
;
188 ospf6_route_table_delete (oa
->range_table
);
189 ospf6_route_table_delete (oa
->summary_prefix
);
190 ospf6_route_table_delete (oa
->summary_router
);
192 /* ospf6 interface list */
193 for (ALL_LIST_ELEMENTS (oa
->if_list
, n
, nnode
, oi
))
195 ospf6_interface_delete (oi
);
197 list_delete (oa
->if_list
);
199 ospf6_lsdb_delete (oa
->lsdb
);
200 ospf6_lsdb_delete (oa
->lsdb_self
);
202 ospf6_route_table_delete (oa
->spf_table
);
203 ospf6_route_table_delete (oa
->route_table
);
206 ospf6_spftree_delete (oa
->spf_tree
);
207 ospf6_route_table_delete (oa
->topology_table
);
210 THREAD_OFF (oa
->thread_spf_calculation
);
211 THREAD_OFF (oa
->thread_route_calculation
);
213 listnode_delete (oa
->ospf6
->area_list
, oa
);
217 XFREE (MTYPE_OSPF6_AREA
, oa
);
221 ospf6_area_lookup (u_int32_t area_id
, struct ospf6
*ospf6
)
223 struct ospf6_area
*oa
;
226 for (ALL_LIST_ELEMENTS_RO (ospf6
->area_list
, n
, oa
))
227 if (oa
->area_id
== area_id
)
230 return (struct ospf6_area
*) NULL
;
233 static struct ospf6_area
*
234 ospf6_area_get (u_int32_t area_id
, struct ospf6
*o
)
236 struct ospf6_area
*oa
;
237 oa
= ospf6_area_lookup (area_id
, o
);
239 oa
= ospf6_area_create (area_id
, o
);
244 ospf6_area_enable (struct ospf6_area
*oa
)
246 struct listnode
*node
, *nnode
;
247 struct ospf6_interface
*oi
;
249 SET_FLAG (oa
->flag
, OSPF6_AREA_ENABLE
);
251 for (ALL_LIST_ELEMENTS (oa
->if_list
, node
, nnode
, oi
))
252 ospf6_interface_enable (oi
);
256 ospf6_area_disable (struct ospf6_area
*oa
)
258 struct listnode
*node
, *nnode
;
259 struct ospf6_interface
*oi
;
261 UNSET_FLAG (oa
->flag
, OSPF6_AREA_ENABLE
);
263 for (ALL_LIST_ELEMENTS (oa
->if_list
, node
, nnode
, oi
))
264 ospf6_interface_disable (oi
);
269 ospf6_area_show (struct vty
*vty
, struct ospf6_area
*oa
)
272 struct ospf6_interface
*oi
;
274 vty_out (vty
, " Area %s%s", oa
->name
, VNL
);
275 vty_out (vty
, " Number of Area scoped LSAs is %u%s",
276 oa
->lsdb
->count
, VNL
);
278 vty_out (vty
, " Interface attached to this area:");
279 for (ALL_LIST_ELEMENTS_RO (oa
->if_list
, i
, oi
))
280 vty_out (vty
, " %s", oi
->interface
->name
);
282 vty_out (vty
, "%s", VNL
);
286 #define OSPF6_CMD_AREA_LOOKUP(str, oa) \
288 u_int32_t area_id = 0; \
289 if (inet_pton (AF_INET, str, &area_id) != 1) \
291 vty_out (vty, "Malformed Area-ID: %s%s", str, VNL); \
292 return CMD_SUCCESS; \
294 oa = ospf6_area_lookup (area_id, ospf6); \
297 vty_out (vty, "No such Area: %s%s", str, VNL); \
298 return CMD_SUCCESS; \
302 #define OSPF6_CMD_AREA_GET(str, oa) \
304 u_int32_t area_id = 0; \
305 if (inet_pton (AF_INET, str, &area_id) != 1) \
307 vty_out (vty, "Malformed Area-ID: %s%s", str, VNL); \
308 return CMD_SUCCESS; \
310 oa = ospf6_area_get (area_id, ospf6); \
315 "area A.B.C.D range X:X::X:X/M",
316 "OSPF area parameters\n"
318 "Configured address range\n"
319 "Specify IPv6 prefix\n"
323 struct ospf6_area
*oa
;
324 struct prefix prefix
;
325 struct ospf6_route
*range
;
327 OSPF6_CMD_AREA_GET (argv
[0], oa
);
331 ret
= str2prefix (argv
[0], &prefix
);
332 if (ret
!= 1 || prefix
.family
!= AF_INET6
)
334 vty_out (vty
, "Malformed argument: %s%s", argv
[0], VNL
);
340 range
= ospf6_route_lookup (&prefix
, oa
->range_table
);
343 range
= ospf6_route_create ();
344 range
->type
= OSPF6_DEST_TYPE_RANGE
;
345 range
->prefix
= prefix
;
350 if (! strcmp (argv
[0], "not-advertise"))
351 SET_FLAG (range
->flag
, OSPF6_ROUTE_DO_NOT_ADVERTISE
);
352 else if (! strcmp (argv
[0], "advertise"))
353 UNSET_FLAG (range
->flag
, OSPF6_ROUTE_DO_NOT_ADVERTISE
);
358 vty_out (vty
, "Range already defined: %s%s", argv
[-1], VNL
);
362 ospf6_route_add (range
, oa
->range_table
);
367 area_range_advertise_cmd
,
368 "area A.B.C.D range X:X::X:X/M (advertise|not-advertise)",
369 "OSPF area parameters\n"
371 "Configured address range\n"
372 "Specify IPv6 prefix\n"
375 DEFUN (no_area_range
,
377 "no area A.B.C.D range X:X::X:X/M",
378 "OSPF area parameters\n"
380 "Configured address range\n"
381 "Specify IPv6 prefix\n"
385 struct ospf6_area
*oa
;
386 struct prefix prefix
;
387 struct ospf6_route
*range
;
389 OSPF6_CMD_AREA_GET (argv
[0], oa
);
393 ret
= str2prefix (argv
[0], &prefix
);
394 if (ret
!= 1 || prefix
.family
!= AF_INET6
)
396 vty_out (vty
, "Malformed argument: %s%s", argv
[0], VNL
);
400 range
= ospf6_route_lookup (&prefix
, oa
->range_table
);
403 vty_out (vty
, "Range %s does not exists.%s", argv
[0], VNL
);
407 ospf6_route_remove (range
, oa
->range_table
);
412 ospf6_area_config_write (struct vty
*vty
)
414 struct listnode
*node
;
415 struct ospf6_area
*oa
;
416 struct ospf6_route
*range
;
419 for (ALL_LIST_ELEMENTS_RO (ospf6
->area_list
, node
, oa
))
421 for (range
= ospf6_route_head (oa
->range_table
); range
;
422 range
= ospf6_route_next (range
))
424 prefix2str (&range
->prefix
, buf
, sizeof (buf
));
425 vty_out (vty
, " area %s range %s%s", oa
->name
, buf
, VNL
);
430 DEFUN (area_filter_list
,
431 area_filter_list_cmd
,
432 "area A.B.C.D filter-list prefix WORD (in|out)",
433 "OSPFv6 area parameters\n"
434 "OSPFv6 area ID in IP address format\n"
435 "Filter networks between OSPFv6 areas\n"
436 "Filter prefixes between OSPFv6 areas\n"
437 "Name of an IPv6 prefix-list\n"
438 "Filter networks sent to this area\n"
439 "Filter networks sent from this area\n")
441 struct ospf6_area
*area
;
442 struct prefix_list
*plist
;
444 OSPF6_CMD_AREA_GET (argv
[0], area
);
448 plist
= prefix_list_lookup (AFI_IP6
, argv
[1]);
449 if (strncmp (argv
[2], "in", 2) == 0)
451 PREFIX_LIST_IN (area
) = plist
;
452 if (PREFIX_NAME_IN (area
))
453 free (PREFIX_NAME_IN (area
));
455 PREFIX_NAME_IN (area
) = strdup (argv
[1]);
456 ospf6_abr_reimport (area
);
460 PREFIX_LIST_OUT (area
) = plist
;
461 if (PREFIX_NAME_OUT (area
))
462 free (PREFIX_NAME_OUT (area
));
464 PREFIX_NAME_OUT (area
) = strdup (argv
[1]);
465 ospf6_abr_enable_area (area
);
471 DEFUN (no_area_filter_list
,
472 no_area_filter_list_cmd
,
473 "no area A.B.C.D filter-list prefix WORD (in|out)",
475 "OSPFv6 area parameters\n"
476 "OSPFv6 area ID in IP address format\n"
477 "Filter networks between OSPFv6 areas\n"
478 "Filter prefixes between OSPFv6 areas\n"
479 "Name of an IPv6 prefix-list\n"
480 "Filter networks sent to this area\n"
481 "Filter networks sent from this area\n")
483 struct ospf6_area
*area
;
484 struct prefix_list
*plist
;
486 OSPF6_CMD_AREA_GET (argv
[0], area
);
490 plist
= prefix_list_lookup (AFI_IP6
, argv
[1]);
491 if (strncmp (argv
[2], "in", 2) == 0)
493 if (PREFIX_NAME_IN (area
))
494 if (strcmp (PREFIX_NAME_IN (area
), argv
[1]) != 0)
497 PREFIX_LIST_IN (area
) = NULL
;
498 if (PREFIX_NAME_IN (area
))
499 free (PREFIX_NAME_IN (area
));
501 PREFIX_NAME_IN (area
) = NULL
;
502 ospf6_abr_reimport (area
);
506 if (PREFIX_NAME_OUT (area
))
507 if (strcmp (PREFIX_NAME_OUT (area
), argv
[1]) != 0)
510 PREFIX_LIST_OUT (area
) = NULL
;
511 if (PREFIX_NAME_OUT (area
))
512 free (PREFIX_NAME_OUT (area
));
514 PREFIX_NAME_OUT (area
) = NULL
;
515 ospf6_abr_enable_area (area
);
521 DEFUN (area_import_list
,
522 area_import_list_cmd
,
523 "area A.B.C.D import-list NAME",
524 "OSPFv6 area parameters\n"
525 "OSPFv6 area ID in IP address format\n"
526 "Set the filter for networks from other areas announced to the specified one\n"
527 "Name of the acess-list\n")
529 struct ospf6_area
*area
;
530 struct access_list
*list
;
532 OSPF6_CMD_AREA_GET(argv
[0], area
);
534 list
= access_list_lookup (AFI_IP6
, argv
[1]);
536 IMPORT_LIST (area
) = list
;
538 if (IMPORT_NAME (area
))
539 free (IMPORT_NAME (area
));
541 IMPORT_NAME (area
) = strdup (argv
[1]);
542 ospf6_abr_reimport (area
);
547 DEFUN (no_area_import_list
,
548 no_area_import_list_cmd
,
549 "no area A.B.C.D import-list NAME",
550 "OSPFv6 area parameters\n"
551 "OSPFv6 area ID in IP address format\n"
552 "Unset the filter for networks announced to other areas\n"
553 "NAme of the access-list\n")
555 struct ospf6_area
*area
;
557 OSPF6_CMD_AREA_GET(argv
[0], area
);
559 IMPORT_LIST (area
) = 0;
561 if (IMPORT_NAME (area
))
562 free (IMPORT_NAME (area
));
564 IMPORT_NAME (area
) = NULL
;
565 ospf6_abr_reimport (area
);
570 DEFUN (area_export_list
,
571 area_export_list_cmd
,
572 "area A.B.C.D export-list NAME",
573 "OSPFv6 area parameters\n"
574 "OSPFv6 area ID in IP address format\n"
575 "Set the filter for networks announced to other areas\n"
576 "Name of the acess-list\n")
578 struct ospf6_area
*area
;
579 struct access_list
*list
;
581 OSPF6_CMD_AREA_GET(argv
[0], area
);
583 list
= access_list_lookup (AFI_IP6
, argv
[1]);
585 EXPORT_LIST (area
) = list
;
587 if (EXPORT_NAME (area
))
588 free (EXPORT_NAME (area
));
590 EXPORT_NAME (area
) = strdup (argv
[1]);
591 ospf6_abr_enable_area (area
);
596 DEFUN (no_area_export_list
,
597 no_area_export_list_cmd
,
598 "no area A.B.C.D export-list NAME",
599 "OSPFv6 area parameters\n"
600 "OSPFv6 area ID in IP address format\n"
601 "Unset the filter for networks announced to other areas\n"
602 "Name of the access-list\n")
604 struct ospf6_area
*area
;
606 OSPF6_CMD_AREA_GET(argv
[0], area
);
608 EXPORT_LIST (area
) = 0;
610 if (EXPORT_NAME (area
))
611 free (EXPORT_NAME (area
));
613 EXPORT_NAME (area
) = NULL
;
614 ospf6_abr_enable_area (area
);
619 DEFUN (show_ipv6_ospf6_spf_tree
,
620 show_ipv6_ospf6_spf_tree_cmd
,
621 "show ipv6 ospf6 spf tree",
625 "Shortest Path First caculation\n"
628 struct listnode
*node
;
629 struct ospf6_area
*oa
;
630 struct ospf6_vertex
*root
;
631 struct ospf6_route
*route
;
632 struct prefix prefix
;
634 ospf6_linkstate_prefix (ospf6
->router_id
, htonl (0), &prefix
);
636 for (ALL_LIST_ELEMENTS_RO (ospf6
->area_list
, node
, oa
))
638 route
= ospf6_route_lookup (&prefix
, oa
->spf_table
);
641 vty_out (vty
, "LS entry for root not found in area %s%s",
645 root
= (struct ospf6_vertex
*) route
->route_option
;
646 ospf6_spf_display_subtree (vty
, "", 0, root
);
652 DEFUN (show_ipv6_ospf6_area_spf_tree
,
653 show_ipv6_ospf6_area_spf_tree_cmd
,
654 "show ipv6 ospf6 area A.B.C.D spf tree",
660 "Shortest Path First caculation\n"
664 struct ospf6_area
*oa
;
665 struct ospf6_vertex
*root
;
666 struct ospf6_route
*route
;
667 struct prefix prefix
;
669 ospf6_linkstate_prefix (ospf6
->router_id
, htonl (0), &prefix
);
671 if (inet_pton (AF_INET
, argv
[0], &area_id
) != 1)
673 vty_out (vty
, "Malformed Area-ID: %s%s", argv
[0], VNL
);
676 oa
= ospf6_area_lookup (area_id
, ospf6
);
679 vty_out (vty
, "No such Area: %s%s", argv
[0], VNL
);
683 route
= ospf6_route_lookup (&prefix
, oa
->spf_table
);
686 vty_out (vty
, "LS entry for root not found in area %s%s",
690 root
= (struct ospf6_vertex
*) route
->route_option
;
691 ospf6_spf_display_subtree (vty
, "", 0, root
);
696 DEFUN (show_ipv6_ospf6_simulate_spf_tree_root
,
697 show_ipv6_ospf6_simulate_spf_tree_root_cmd
,
698 "show ipv6 ospf6 simulate spf-tree A.B.C.D area A.B.C.D",
702 "Shortest Path First caculation\n"
704 "Specify root's router-id to calculate another router's SPF tree\n")
707 struct ospf6_area
*oa
;
708 struct ospf6_vertex
*root
;
709 struct ospf6_route
*route
;
710 struct prefix prefix
;
712 struct ospf6_route_table
*spf_table
;
713 unsigned char tmp_debug_ospf6_spf
= 0;
715 inet_pton (AF_INET
, argv
[0], &router_id
);
716 ospf6_linkstate_prefix (router_id
, htonl (0), &prefix
);
718 if (inet_pton (AF_INET
, argv
[1], &area_id
) != 1)
720 vty_out (vty
, "Malformed Area-ID: %s%s", argv
[1], VNL
);
723 oa
= ospf6_area_lookup (area_id
, ospf6
);
726 vty_out (vty
, "No such Area: %s%s", argv
[1], VNL
);
730 tmp_debug_ospf6_spf
= conf_debug_ospf6_spf
;
731 conf_debug_ospf6_spf
= 0;
733 spf_table
= OSPF6_ROUTE_TABLE_CREATE (NONE
, SPF_RESULTS
);
734 ospf6_spf_calculation (router_id
, spf_table
, oa
);
736 conf_debug_ospf6_spf
= tmp_debug_ospf6_spf
;
738 route
= ospf6_route_lookup (&prefix
, spf_table
);
741 ospf6_spf_table_finish (spf_table
);
742 ospf6_route_table_delete (spf_table
);
745 root
= (struct ospf6_vertex
*) route
->route_option
;
746 ospf6_spf_display_subtree (vty
, "", 0, root
);
748 ospf6_spf_table_finish (spf_table
);
749 ospf6_route_table_delete (spf_table
);
755 ospf6_area_init (void)
757 install_element (VIEW_NODE
, &show_ipv6_ospf6_spf_tree_cmd
);
758 install_element (VIEW_NODE
, &show_ipv6_ospf6_area_spf_tree_cmd
);
759 install_element (VIEW_NODE
, &show_ipv6_ospf6_simulate_spf_tree_root_cmd
);
761 install_element (ENABLE_NODE
, &show_ipv6_ospf6_spf_tree_cmd
);
762 install_element (ENABLE_NODE
, &show_ipv6_ospf6_area_spf_tree_cmd
);
763 install_element (ENABLE_NODE
, &show_ipv6_ospf6_simulate_spf_tree_root_cmd
);
765 install_element (OSPF6_NODE
, &area_range_cmd
);
766 install_element (OSPF6_NODE
, &area_range_advertise_cmd
);
767 install_element (OSPF6_NODE
, &no_area_range_cmd
);
769 install_element (OSPF6_NODE
, &area_import_list_cmd
);
770 install_element (OSPF6_NODE
, &no_area_import_list_cmd
);
771 install_element (OSPF6_NODE
, &area_export_list_cmd
);
772 install_element (OSPF6_NODE
, &no_area_export_list_cmd
);
774 install_element (OSPF6_NODE
, &area_filter_list_cmd
);
775 install_element (OSPF6_NODE
, &no_area_filter_list_cmd
);