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_spf_table_finish (oa
->spf_table
);
203 ospf6_route_table_delete (oa
->spf_table
);
204 ospf6_route_table_delete (oa
->route_table
);
207 ospf6_spftree_delete (oa
->spf_tree
);
208 ospf6_route_table_delete (oa
->topology_table
);
211 THREAD_OFF (oa
->thread_spf_calculation
);
212 THREAD_OFF (oa
->thread_route_calculation
);
214 listnode_delete (oa
->ospf6
->area_list
, oa
);
218 XFREE (MTYPE_OSPF6_AREA
, oa
);
222 ospf6_area_lookup (u_int32_t area_id
, struct ospf6
*ospf6
)
224 struct ospf6_area
*oa
;
227 for (ALL_LIST_ELEMENTS_RO (ospf6
->area_list
, n
, oa
))
228 if (oa
->area_id
== area_id
)
231 return (struct ospf6_area
*) NULL
;
234 static struct ospf6_area
*
235 ospf6_area_get (u_int32_t area_id
, struct ospf6
*o
)
237 struct ospf6_area
*oa
;
238 oa
= ospf6_area_lookup (area_id
, o
);
240 oa
= ospf6_area_create (area_id
, o
);
245 ospf6_area_enable (struct ospf6_area
*oa
)
247 struct listnode
*node
, *nnode
;
248 struct ospf6_interface
*oi
;
250 SET_FLAG (oa
->flag
, OSPF6_AREA_ENABLE
);
252 for (ALL_LIST_ELEMENTS (oa
->if_list
, node
, nnode
, oi
))
253 ospf6_interface_enable (oi
);
257 ospf6_area_disable (struct ospf6_area
*oa
)
259 struct listnode
*node
, *nnode
;
260 struct ospf6_interface
*oi
;
262 UNSET_FLAG (oa
->flag
, OSPF6_AREA_ENABLE
);
264 for (ALL_LIST_ELEMENTS (oa
->if_list
, node
, nnode
, oi
))
265 ospf6_interface_disable (oi
);
270 ospf6_area_show (struct vty
*vty
, struct ospf6_area
*oa
)
273 struct ospf6_interface
*oi
;
275 vty_out (vty
, " Area %s%s", oa
->name
, VNL
);
276 vty_out (vty
, " Number of Area scoped LSAs is %u%s",
277 oa
->lsdb
->count
, VNL
);
279 vty_out (vty
, " Interface attached to this area:");
280 for (ALL_LIST_ELEMENTS_RO (oa
->if_list
, i
, oi
))
281 vty_out (vty
, " %s", oi
->interface
->name
);
283 vty_out (vty
, "%s", VNL
);
287 #define OSPF6_CMD_AREA_LOOKUP(str, oa) \
289 u_int32_t area_id = 0; \
290 if (inet_pton (AF_INET, str, &area_id) != 1) \
292 vty_out (vty, "Malformed Area-ID: %s%s", str, VNL); \
293 return CMD_SUCCESS; \
295 oa = ospf6_area_lookup (area_id, ospf6); \
298 vty_out (vty, "No such Area: %s%s", str, VNL); \
299 return CMD_SUCCESS; \
303 #define OSPF6_CMD_AREA_GET(str, oa) \
305 u_int32_t area_id = 0; \
306 if (inet_pton (AF_INET, str, &area_id) != 1) \
308 vty_out (vty, "Malformed Area-ID: %s%s", str, VNL); \
309 return CMD_SUCCESS; \
311 oa = ospf6_area_get (area_id, ospf6); \
316 "area A.B.C.D range X:X::X:X/M",
317 "OSPF area parameters\n"
319 "Configured address range\n"
320 "Specify IPv6 prefix\n"
324 struct ospf6_area
*oa
;
325 struct prefix prefix
;
326 struct ospf6_route
*range
;
328 OSPF6_CMD_AREA_GET (argv
[0], oa
);
332 ret
= str2prefix (argv
[0], &prefix
);
333 if (ret
!= 1 || prefix
.family
!= AF_INET6
)
335 vty_out (vty
, "Malformed argument: %s%s", argv
[0], VNL
);
341 range
= ospf6_route_lookup (&prefix
, oa
->range_table
);
344 range
= ospf6_route_create ();
345 range
->type
= OSPF6_DEST_TYPE_RANGE
;
346 range
->prefix
= prefix
;
351 if (! strcmp (argv
[0], "not-advertise"))
352 SET_FLAG (range
->flag
, OSPF6_ROUTE_DO_NOT_ADVERTISE
);
353 else if (! strcmp (argv
[0], "advertise"))
354 UNSET_FLAG (range
->flag
, OSPF6_ROUTE_DO_NOT_ADVERTISE
);
359 vty_out (vty
, "Range already defined: %s%s", argv
[-1], VNL
);
363 ospf6_route_add (range
, oa
->range_table
);
368 area_range_advertise_cmd
,
369 "area A.B.C.D range X:X::X:X/M (advertise|not-advertise)",
370 "OSPF area parameters\n"
372 "Configured address range\n"
373 "Specify IPv6 prefix\n"
376 DEFUN (no_area_range
,
378 "no area A.B.C.D range X:X::X:X/M",
379 "OSPF area parameters\n"
381 "Configured address range\n"
382 "Specify IPv6 prefix\n"
386 struct ospf6_area
*oa
;
387 struct prefix prefix
;
388 struct ospf6_route
*range
;
390 OSPF6_CMD_AREA_GET (argv
[0], oa
);
394 ret
= str2prefix (argv
[0], &prefix
);
395 if (ret
!= 1 || prefix
.family
!= AF_INET6
)
397 vty_out (vty
, "Malformed argument: %s%s", argv
[0], VNL
);
401 range
= ospf6_route_lookup (&prefix
, oa
->range_table
);
404 vty_out (vty
, "Range %s does not exists.%s", argv
[0], VNL
);
408 ospf6_route_remove (range
, oa
->range_table
);
413 ospf6_area_config_write (struct vty
*vty
)
415 struct listnode
*node
;
416 struct ospf6_area
*oa
;
417 struct ospf6_route
*range
;
420 for (ALL_LIST_ELEMENTS_RO (ospf6
->area_list
, node
, oa
))
422 for (range
= ospf6_route_head (oa
->range_table
); range
;
423 range
= ospf6_route_next (range
))
425 prefix2str (&range
->prefix
, buf
, sizeof (buf
));
426 vty_out (vty
, " area %s range %s%s", oa
->name
, buf
, VNL
);
431 DEFUN (area_filter_list
,
432 area_filter_list_cmd
,
433 "area A.B.C.D filter-list prefix WORD (in|out)",
434 "OSPFv6 area parameters\n"
435 "OSPFv6 area ID in IP address format\n"
436 "Filter networks between OSPFv6 areas\n"
437 "Filter prefixes between OSPFv6 areas\n"
438 "Name of an IPv6 prefix-list\n"
439 "Filter networks sent to this area\n"
440 "Filter networks sent from this area\n")
442 struct ospf6_area
*area
;
443 struct prefix_list
*plist
;
445 OSPF6_CMD_AREA_GET (argv
[0], area
);
449 plist
= prefix_list_lookup (AFI_IP6
, argv
[1]);
450 if (strncmp (argv
[2], "in", 2) == 0)
452 PREFIX_LIST_IN (area
) = plist
;
453 if (PREFIX_NAME_IN (area
))
454 free (PREFIX_NAME_IN (area
));
456 PREFIX_NAME_IN (area
) = strdup (argv
[1]);
457 ospf6_abr_reimport (area
);
461 PREFIX_LIST_OUT (area
) = plist
;
462 if (PREFIX_NAME_OUT (area
))
463 free (PREFIX_NAME_OUT (area
));
465 PREFIX_NAME_OUT (area
) = strdup (argv
[1]);
466 ospf6_abr_enable_area (area
);
472 DEFUN (no_area_filter_list
,
473 no_area_filter_list_cmd
,
474 "no area A.B.C.D filter-list prefix WORD (in|out)",
476 "OSPFv6 area parameters\n"
477 "OSPFv6 area ID in IP address format\n"
478 "Filter networks between OSPFv6 areas\n"
479 "Filter prefixes between OSPFv6 areas\n"
480 "Name of an IPv6 prefix-list\n"
481 "Filter networks sent to this area\n"
482 "Filter networks sent from this area\n")
484 struct ospf6_area
*area
;
485 struct prefix_list
*plist
;
487 OSPF6_CMD_AREA_GET (argv
[0], area
);
491 plist
= prefix_list_lookup (AFI_IP6
, argv
[1]);
492 if (strncmp (argv
[2], "in", 2) == 0)
494 if (PREFIX_NAME_IN (area
))
495 if (strcmp (PREFIX_NAME_IN (area
), argv
[1]) != 0)
498 PREFIX_LIST_IN (area
) = NULL
;
499 if (PREFIX_NAME_IN (area
))
500 free (PREFIX_NAME_IN (area
));
502 PREFIX_NAME_IN (area
) = NULL
;
503 ospf6_abr_reimport (area
);
507 if (PREFIX_NAME_OUT (area
))
508 if (strcmp (PREFIX_NAME_OUT (area
), argv
[1]) != 0)
511 PREFIX_LIST_OUT (area
) = NULL
;
512 if (PREFIX_NAME_OUT (area
))
513 free (PREFIX_NAME_OUT (area
));
515 PREFIX_NAME_OUT (area
) = NULL
;
516 ospf6_abr_enable_area (area
);
522 DEFUN (area_import_list
,
523 area_import_list_cmd
,
524 "area A.B.C.D import-list NAME",
525 "OSPFv6 area parameters\n"
526 "OSPFv6 area ID in IP address format\n"
527 "Set the filter for networks from other areas announced to the specified one\n"
528 "Name of the acess-list\n")
530 struct ospf6_area
*area
;
531 struct access_list
*list
;
533 OSPF6_CMD_AREA_GET(argv
[0], area
);
535 list
= access_list_lookup (AFI_IP6
, argv
[1]);
537 IMPORT_LIST (area
) = list
;
539 if (IMPORT_NAME (area
))
540 free (IMPORT_NAME (area
));
542 IMPORT_NAME (area
) = strdup (argv
[1]);
543 ospf6_abr_reimport (area
);
548 DEFUN (no_area_import_list
,
549 no_area_import_list_cmd
,
550 "no area A.B.C.D import-list NAME",
551 "OSPFv6 area parameters\n"
552 "OSPFv6 area ID in IP address format\n"
553 "Unset the filter for networks announced to other areas\n"
554 "NAme of the access-list\n")
556 struct ospf6_area
*area
;
558 OSPF6_CMD_AREA_GET(argv
[0], area
);
560 IMPORT_LIST (area
) = 0;
562 if (IMPORT_NAME (area
))
563 free (IMPORT_NAME (area
));
565 IMPORT_NAME (area
) = NULL
;
566 ospf6_abr_reimport (area
);
571 DEFUN (area_export_list
,
572 area_export_list_cmd
,
573 "area A.B.C.D export-list NAME",
574 "OSPFv6 area parameters\n"
575 "OSPFv6 area ID in IP address format\n"
576 "Set the filter for networks announced to other areas\n"
577 "Name of the acess-list\n")
579 struct ospf6_area
*area
;
580 struct access_list
*list
;
582 OSPF6_CMD_AREA_GET(argv
[0], area
);
584 list
= access_list_lookup (AFI_IP6
, argv
[1]);
586 EXPORT_LIST (area
) = list
;
588 if (EXPORT_NAME (area
))
589 free (EXPORT_NAME (area
));
591 EXPORT_NAME (area
) = strdup (argv
[1]);
592 ospf6_abr_enable_area (area
);
597 DEFUN (no_area_export_list
,
598 no_area_export_list_cmd
,
599 "no area A.B.C.D export-list NAME",
600 "OSPFv6 area parameters\n"
601 "OSPFv6 area ID in IP address format\n"
602 "Unset the filter for networks announced to other areas\n"
603 "Name of the access-list\n")
605 struct ospf6_area
*area
;
607 OSPF6_CMD_AREA_GET(argv
[0], area
);
609 EXPORT_LIST (area
) = 0;
611 if (EXPORT_NAME (area
))
612 free (EXPORT_NAME (area
));
614 EXPORT_NAME (area
) = NULL
;
615 ospf6_abr_enable_area (area
);
620 DEFUN (show_ipv6_ospf6_spf_tree
,
621 show_ipv6_ospf6_spf_tree_cmd
,
622 "show ipv6 ospf6 spf tree",
626 "Shortest Path First caculation\n"
629 struct listnode
*node
;
630 struct ospf6_area
*oa
;
631 struct ospf6_vertex
*root
;
632 struct ospf6_route
*route
;
633 struct prefix prefix
;
635 ospf6_linkstate_prefix (ospf6
->router_id
, htonl (0), &prefix
);
637 for (ALL_LIST_ELEMENTS_RO (ospf6
->area_list
, node
, oa
))
639 route
= ospf6_route_lookup (&prefix
, oa
->spf_table
);
642 vty_out (vty
, "LS entry for root not found in area %s%s",
646 root
= (struct ospf6_vertex
*) route
->route_option
;
647 ospf6_spf_display_subtree (vty
, "", 0, root
);
653 DEFUN (show_ipv6_ospf6_area_spf_tree
,
654 show_ipv6_ospf6_area_spf_tree_cmd
,
655 "show ipv6 ospf6 area A.B.C.D spf tree",
661 "Shortest Path First caculation\n"
665 struct ospf6_area
*oa
;
666 struct ospf6_vertex
*root
;
667 struct ospf6_route
*route
;
668 struct prefix prefix
;
670 ospf6_linkstate_prefix (ospf6
->router_id
, htonl (0), &prefix
);
672 if (inet_pton (AF_INET
, argv
[0], &area_id
) != 1)
674 vty_out (vty
, "Malformed Area-ID: %s%s", argv
[0], VNL
);
677 oa
= ospf6_area_lookup (area_id
, ospf6
);
680 vty_out (vty
, "No such Area: %s%s", argv
[0], VNL
);
684 route
= ospf6_route_lookup (&prefix
, oa
->spf_table
);
687 vty_out (vty
, "LS entry for root not found in area %s%s",
691 root
= (struct ospf6_vertex
*) route
->route_option
;
692 ospf6_spf_display_subtree (vty
, "", 0, root
);
697 DEFUN (show_ipv6_ospf6_simulate_spf_tree_root
,
698 show_ipv6_ospf6_simulate_spf_tree_root_cmd
,
699 "show ipv6 ospf6 simulate spf-tree A.B.C.D area A.B.C.D",
703 "Shortest Path First caculation\n"
705 "Specify root's router-id to calculate another router's SPF tree\n")
708 struct ospf6_area
*oa
;
709 struct ospf6_vertex
*root
;
710 struct ospf6_route
*route
;
711 struct prefix prefix
;
713 struct ospf6_route_table
*spf_table
;
714 unsigned char tmp_debug_ospf6_spf
= 0;
716 inet_pton (AF_INET
, argv
[0], &router_id
);
717 ospf6_linkstate_prefix (router_id
, htonl (0), &prefix
);
719 if (inet_pton (AF_INET
, argv
[1], &area_id
) != 1)
721 vty_out (vty
, "Malformed Area-ID: %s%s", argv
[1], VNL
);
724 oa
= ospf6_area_lookup (area_id
, ospf6
);
727 vty_out (vty
, "No such Area: %s%s", argv
[1], VNL
);
731 tmp_debug_ospf6_spf
= conf_debug_ospf6_spf
;
732 conf_debug_ospf6_spf
= 0;
734 spf_table
= OSPF6_ROUTE_TABLE_CREATE (NONE
, SPF_RESULTS
);
735 ospf6_spf_calculation (router_id
, spf_table
, oa
);
737 conf_debug_ospf6_spf
= tmp_debug_ospf6_spf
;
739 route
= ospf6_route_lookup (&prefix
, spf_table
);
742 ospf6_spf_table_finish (spf_table
);
743 ospf6_route_table_delete (spf_table
);
746 root
= (struct ospf6_vertex
*) route
->route_option
;
747 ospf6_spf_display_subtree (vty
, "", 0, root
);
749 ospf6_spf_table_finish (spf_table
);
750 ospf6_route_table_delete (spf_table
);
756 ospf6_area_init (void)
758 install_element (VIEW_NODE
, &show_ipv6_ospf6_spf_tree_cmd
);
759 install_element (VIEW_NODE
, &show_ipv6_ospf6_area_spf_tree_cmd
);
760 install_element (VIEW_NODE
, &show_ipv6_ospf6_simulate_spf_tree_root_cmd
);
762 install_element (ENABLE_NODE
, &show_ipv6_ospf6_spf_tree_cmd
);
763 install_element (ENABLE_NODE
, &show_ipv6_ospf6_area_spf_tree_cmd
);
764 install_element (ENABLE_NODE
, &show_ipv6_ospf6_simulate_spf_tree_root_cmd
);
766 install_element (OSPF6_NODE
, &area_range_cmd
);
767 install_element (OSPF6_NODE
, &area_range_advertise_cmd
);
768 install_element (OSPF6_NODE
, &no_area_range_cmd
);
770 install_element (OSPF6_NODE
, &area_import_list_cmd
);
771 install_element (OSPF6_NODE
, &no_area_import_list_cmd
);
772 install_element (OSPF6_NODE
, &area_export_list_cmd
);
773 install_element (OSPF6_NODE
, &no_area_export_list_cmd
);
775 install_element (OSPF6_NODE
, &area_filter_list_cmd
);
776 install_element (OSPF6_NODE
, &no_area_filter_list_cmd
);