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.
34 #include "ospf6_proto.h"
35 #include "ospf6_lsa.h"
36 #include "ospf6_lsdb.h"
37 #include "ospf6_route.h"
38 #include "ospf6_spf.h"
39 #include "ospf6_top.h"
40 #include "ospf6_area.h"
41 #include "ospf6_interface.h"
42 #include "ospf6_intra.h"
43 #include "ospf6_abr.h"
47 ospf6_area_cmp (void *va
, void *vb
)
49 struct ospf6_area
*oa
= (struct ospf6_area
*) va
;
50 struct ospf6_area
*ob
= (struct ospf6_area
*) vb
;
51 return (ntohl (oa
->area_id
) < ntohl (ob
->area_id
) ? -1 : 1);
54 /* schedule routing table recalculation */
56 ospf6_area_lsdb_hook_add (struct ospf6_lsa
*lsa
)
58 switch (ntohs (lsa
->header
->type
))
60 case OSPF6_LSTYPE_ROUTER
:
61 case OSPF6_LSTYPE_NETWORK
:
62 if (IS_OSPF6_DEBUG_EXAMIN_TYPE (lsa
->header
->type
))
64 zlog_debug ("Examin %s", lsa
->name
);
65 zlog_debug ("Schedule SPF Calculation for %s",
66 OSPF6_AREA (lsa
->lsdb
->data
)->name
);
68 ospf6_spf_schedule (OSPF6_AREA (lsa
->lsdb
->data
));
71 case OSPF6_LSTYPE_INTRA_PREFIX
:
72 ospf6_intra_prefix_lsa_add (lsa
);
75 case OSPF6_LSTYPE_INTER_PREFIX
:
76 case OSPF6_LSTYPE_INTER_ROUTER
:
77 ospf6_abr_examin_summary (lsa
, (struct ospf6_area
*) lsa
->lsdb
->data
);
86 ospf6_area_lsdb_hook_remove (struct ospf6_lsa
*lsa
)
88 switch (ntohs (lsa
->header
->type
))
90 case OSPF6_LSTYPE_ROUTER
:
91 case OSPF6_LSTYPE_NETWORK
:
92 if (IS_OSPF6_DEBUG_EXAMIN_TYPE (lsa
->header
->type
))
94 zlog_debug ("LSA disappearing: %s", lsa
->name
);
95 zlog_debug ("Schedule SPF Calculation for %s",
96 OSPF6_AREA (lsa
->lsdb
->data
)->name
);
98 ospf6_spf_schedule (OSPF6_AREA (lsa
->lsdb
->data
));
101 case OSPF6_LSTYPE_INTRA_PREFIX
:
102 ospf6_intra_prefix_lsa_remove (lsa
);
105 case OSPF6_LSTYPE_INTER_PREFIX
:
106 case OSPF6_LSTYPE_INTER_ROUTER
:
107 ospf6_abr_examin_summary (lsa
, (struct ospf6_area
*) lsa
->lsdb
->data
);
116 ospf6_area_route_hook_add (struct ospf6_route
*route
)
118 struct ospf6_route
*copy
= ospf6_route_copy (route
);
119 ospf6_route_add (copy
, ospf6
->route_table
);
123 ospf6_area_route_hook_remove (struct ospf6_route
*route
)
125 struct ospf6_route
*copy
;
127 copy
= ospf6_route_lookup_identical (route
, ospf6
->route_table
);
129 ospf6_route_remove (copy
, ospf6
->route_table
);
132 /* Make new area structure */
134 ospf6_area_create (u_int32_t area_id
, struct ospf6
*o
)
136 struct ospf6_area
*oa
;
137 struct ospf6_route
*route
;
139 oa
= XCALLOC (MTYPE_OSPF6_AREA
, sizeof (struct ospf6_area
));
141 inet_ntop (AF_INET
, &area_id
, oa
->name
, sizeof (oa
->name
));
142 oa
->area_id
= area_id
;
143 oa
->if_list
= list_new ();
145 oa
->lsdb
= ospf6_lsdb_create (oa
);
146 oa
->lsdb
->hook_add
= ospf6_area_lsdb_hook_add
;
147 oa
->lsdb
->hook_remove
= ospf6_area_lsdb_hook_remove
;
148 oa
->lsdb_self
= ospf6_lsdb_create (oa
);
150 oa
->spf_table
= ospf6_route_table_create ();
151 oa
->route_table
= ospf6_route_table_create ();
152 oa
->route_table
->hook_add
= ospf6_area_route_hook_add
;
153 oa
->route_table
->hook_remove
= ospf6_area_route_hook_remove
;
155 oa
->range_table
= ospf6_route_table_create ();
156 oa
->summary_prefix
= ospf6_route_table_create ();
157 oa
->summary_router
= ospf6_route_table_create ();
159 /* set default options */
160 OSPF6_OPT_SET (oa
->options
, OSPF6_OPT_V6
);
161 OSPF6_OPT_SET (oa
->options
, OSPF6_OPT_E
);
162 OSPF6_OPT_SET (oa
->options
, OSPF6_OPT_R
);
165 listnode_add_sort (o
->area_list
, oa
);
167 /* import athoer area's routes as inter-area routes */
168 for (route
= ospf6_route_head (o
->route_table
); route
;
169 route
= ospf6_route_next (route
))
170 ospf6_abr_originate_summary_to_area (route
, oa
);
176 ospf6_area_delete (struct ospf6_area
*oa
)
178 struct listnode
*n
, *nnode
;
179 struct ospf6_interface
*oi
;
181 ospf6_route_table_delete (oa
->range_table
);
182 ospf6_route_table_delete (oa
->summary_prefix
);
183 ospf6_route_table_delete (oa
->summary_router
);
185 /* ospf6 interface list */
186 for (ALL_LIST_ELEMENTS (oa
->if_list
, n
, nnode
, oi
))
188 ospf6_interface_delete (oi
);
190 list_delete (oa
->if_list
);
192 ospf6_lsdb_delete (oa
->lsdb
);
193 ospf6_lsdb_delete (oa
->lsdb_self
);
195 ospf6_route_table_delete (oa
->spf_table
);
196 ospf6_route_table_delete (oa
->route_table
);
199 ospf6_spftree_delete (oa
->spf_tree
);
200 ospf6_route_table_delete (oa
->topology_table
);
203 THREAD_OFF (oa
->thread_spf_calculation
);
204 THREAD_OFF (oa
->thread_route_calculation
);
206 listnode_delete (oa
->ospf6
->area_list
, oa
);
210 XFREE (MTYPE_OSPF6_AREA
, oa
);
214 ospf6_area_lookup (u_int32_t area_id
, struct ospf6
*ospf6
)
216 struct ospf6_area
*oa
;
219 for (ALL_LIST_ELEMENTS_RO (ospf6
->area_list
, n
, oa
))
220 if (oa
->area_id
== area_id
)
223 return (struct ospf6_area
*) NULL
;
227 ospf6_area_get (u_int32_t area_id
, struct ospf6
*o
)
229 struct ospf6_area
*oa
;
230 oa
= ospf6_area_lookup (area_id
, o
);
232 oa
= ospf6_area_create (area_id
, o
);
237 ospf6_area_enable (struct ospf6_area
*oa
)
239 struct listnode
*node
, *nnode
;
240 struct ospf6_interface
*oi
;
242 SET_FLAG (oa
->flag
, OSPF6_AREA_ENABLE
);
244 for (ALL_LIST_ELEMENTS (oa
->if_list
, node
, nnode
, oi
))
245 ospf6_interface_enable (oi
);
249 ospf6_area_disable (struct ospf6_area
*oa
)
251 struct listnode
*node
, *nnode
;
252 struct ospf6_interface
*oi
;
254 UNSET_FLAG (oa
->flag
, OSPF6_AREA_ENABLE
);
256 for (ALL_LIST_ELEMENTS (oa
->if_list
, node
, nnode
, oi
))
257 ospf6_interface_disable (oi
);
262 ospf6_area_show (struct vty
*vty
, struct ospf6_area
*oa
)
265 struct ospf6_interface
*oi
;
267 vty_out (vty
, " Area %s%s", oa
->name
, VNL
);
268 vty_out (vty
, " Number of Area scoped LSAs is %u%s",
269 oa
->lsdb
->count
, VNL
);
271 vty_out (vty
, " Interface attached to this area:");
272 for (ALL_LIST_ELEMENTS_RO (oa
->if_list
, i
, oi
))
273 vty_out (vty
, " %s", oi
->interface
->name
);
275 vty_out (vty
, "%s", VNL
);
279 #define OSPF6_CMD_AREA_LOOKUP(str, oa) \
281 u_int32_t area_id = 0; \
282 if (inet_pton (AF_INET, str, &area_id) != 1) \
284 vty_out (vty, "Malformed Area-ID: %s%s", str, VNL); \
285 return CMD_SUCCESS; \
287 oa = ospf6_area_lookup (area_id, ospf6); \
290 vty_out (vty, "No such Area: %s%s", str, VNL); \
291 return CMD_SUCCESS; \
295 #define OSPF6_CMD_AREA_GET(str, oa) \
297 u_int32_t area_id = 0; \
298 if (inet_pton (AF_INET, str, &area_id) != 1) \
300 vty_out (vty, "Malformed Area-ID: %s%s", str, VNL); \
301 return CMD_SUCCESS; \
303 oa = ospf6_area_get (area_id, ospf6); \
308 "area A.B.C.D range X:X::X:X/M",
309 "OSPF area parameters\n"
311 "Configured address range\n"
312 "Specify IPv6 prefix\n"
316 struct ospf6_area
*oa
;
317 struct prefix prefix
;
318 struct ospf6_route
*range
;
320 OSPF6_CMD_AREA_GET (argv
[0], oa
);
324 ret
= str2prefix (argv
[0], &prefix
);
325 if (ret
!= 1 || prefix
.family
!= AF_INET6
)
327 vty_out (vty
, "Malformed argument: %s%s", argv
[0], VNL
);
333 range
= ospf6_route_lookup (&prefix
, oa
->range_table
);
336 range
= ospf6_route_create ();
337 range
->type
= OSPF6_DEST_TYPE_RANGE
;
338 range
->prefix
= prefix
;
343 if (! strcmp (argv
[0], "not-advertise"))
344 SET_FLAG (range
->flag
, OSPF6_ROUTE_DO_NOT_ADVERTISE
);
345 else if (! strcmp (argv
[0], "advertise"))
346 UNSET_FLAG (range
->flag
, OSPF6_ROUTE_DO_NOT_ADVERTISE
);
349 ospf6_route_add (range
, oa
->range_table
);
354 area_range_advertise_cmd
,
355 "area A.B.C.D range X:X::X:X/M (advertise|not-advertise)",
356 "OSPF area parameters\n"
358 "Configured address range\n"
359 "Specify IPv6 prefix\n"
362 DEFUN (no_area_range
,
364 "no area A.B.C.D range X:X::X:X/M",
365 "OSPF area parameters\n"
367 "Configured address range\n"
368 "Specify IPv6 prefix\n"
372 struct ospf6_area
*oa
;
373 struct prefix prefix
;
374 struct ospf6_route
*range
;
376 OSPF6_CMD_AREA_GET (argv
[0], oa
);
380 ret
= str2prefix (argv
[0], &prefix
);
381 if (ret
!= 1 || prefix
.family
!= AF_INET6
)
383 vty_out (vty
, "Malformed argument: %s%s", argv
[0], VNL
);
387 range
= ospf6_route_lookup (&prefix
, oa
->range_table
);
390 vty_out (vty
, "Range %s does not exists.%s", argv
[0], VNL
);
394 ospf6_route_remove (range
, oa
->range_table
);
399 ospf6_area_config_write (struct vty
*vty
)
401 struct listnode
*node
;
402 struct ospf6_area
*oa
;
403 struct ospf6_route
*range
;
406 for (ALL_LIST_ELEMENTS_RO (ospf6
->area_list
, node
, oa
))
408 for (range
= ospf6_route_head (oa
->range_table
); range
;
409 range
= ospf6_route_next (range
))
411 prefix2str (&range
->prefix
, buf
, sizeof (buf
));
412 vty_out (vty
, " area %s range %s%s", oa
->name
, buf
, VNL
);
417 DEFUN (show_ipv6_ospf6_spf_tree
,
418 show_ipv6_ospf6_spf_tree_cmd
,
419 "show ipv6 ospf6 spf tree",
423 "Shortest Path First caculation\n"
426 struct listnode
*node
;
427 struct ospf6_area
*oa
;
428 struct ospf6_vertex
*root
;
429 struct ospf6_route
*route
;
430 struct prefix prefix
;
432 ospf6_linkstate_prefix (ospf6
->router_id
, htonl (0), &prefix
);
434 for (ALL_LIST_ELEMENTS_RO (ospf6
->area_list
, node
, oa
))
436 route
= ospf6_route_lookup (&prefix
, oa
->spf_table
);
439 vty_out (vty
, "LS entry for root not found in area %s%s",
443 root
= (struct ospf6_vertex
*) route
->route_option
;
444 ospf6_spf_display_subtree (vty
, "", 0, root
);
450 DEFUN (show_ipv6_ospf6_area_spf_tree
,
451 show_ipv6_ospf6_area_spf_tree_cmd
,
452 "show ipv6 ospf6 area A.B.C.D spf tree",
458 "Shortest Path First caculation\n"
462 struct ospf6_area
*oa
;
463 struct ospf6_vertex
*root
;
464 struct ospf6_route
*route
;
465 struct prefix prefix
;
467 ospf6_linkstate_prefix (ospf6
->router_id
, htonl (0), &prefix
);
469 if (inet_pton (AF_INET
, argv
[0], &area_id
) != 1)
471 vty_out (vty
, "Malformed Area-ID: %s%s", argv
[0], VNL
);
474 oa
= ospf6_area_lookup (area_id
, ospf6
);
477 vty_out (vty
, "No such Area: %s%s", argv
[0], VNL
);
481 route
= ospf6_route_lookup (&prefix
, oa
->spf_table
);
484 vty_out (vty
, "LS entry for root not found in area %s%s",
488 root
= (struct ospf6_vertex
*) route
->route_option
;
489 ospf6_spf_display_subtree (vty
, "", 0, root
);
494 DEFUN (show_ipv6_ospf6_simulate_spf_tree_root
,
495 show_ipv6_ospf6_simulate_spf_tree_root_cmd
,
496 "show ipv6 ospf6 simulate spf-tree A.B.C.D area A.B.C.D",
500 "Shortest Path First caculation\n"
502 "Specify root's router-id to calculate another router's SPF tree\n")
505 struct ospf6_area
*oa
;
506 struct ospf6_vertex
*root
;
507 struct ospf6_route
*route
;
508 struct prefix prefix
;
510 struct ospf6_route_table
*spf_table
;
511 unsigned char tmp_debug_ospf6_spf
= 0;
513 inet_pton (AF_INET
, argv
[0], &router_id
);
514 ospf6_linkstate_prefix (router_id
, htonl (0), &prefix
);
516 if (inet_pton (AF_INET
, argv
[1], &area_id
) != 1)
518 vty_out (vty
, "Malformed Area-ID: %s%s", argv
[1], VNL
);
521 oa
= ospf6_area_lookup (area_id
, ospf6
);
524 vty_out (vty
, "No such Area: %s%s", argv
[1], VNL
);
528 tmp_debug_ospf6_spf
= conf_debug_ospf6_spf
;
529 conf_debug_ospf6_spf
= 0;
531 spf_table
= ospf6_route_table_create ();
532 ospf6_spf_calculation (router_id
, spf_table
, oa
);
534 conf_debug_ospf6_spf
= tmp_debug_ospf6_spf
;
536 route
= ospf6_route_lookup (&prefix
, spf_table
);
539 ospf6_spf_table_finish (spf_table
);
540 ospf6_route_table_delete (spf_table
);
543 root
= (struct ospf6_vertex
*) route
->route_option
;
544 ospf6_spf_display_subtree (vty
, "", 0, root
);
546 ospf6_spf_table_finish (spf_table
);
547 ospf6_route_table_delete (spf_table
);
555 install_element (VIEW_NODE
, &show_ipv6_ospf6_spf_tree_cmd
);
556 install_element (VIEW_NODE
, &show_ipv6_ospf6_area_spf_tree_cmd
);
557 install_element (VIEW_NODE
, &show_ipv6_ospf6_simulate_spf_tree_root_cmd
);
559 install_element (ENABLE_NODE
, &show_ipv6_ospf6_spf_tree_cmd
);
560 install_element (ENABLE_NODE
, &show_ipv6_ospf6_area_spf_tree_cmd
);
561 install_element (ENABLE_NODE
, &show_ipv6_ospf6_simulate_spf_tree_root_cmd
);
563 install_element (OSPF6_NODE
, &area_range_cmd
);
564 install_element (OSPF6_NODE
, &area_range_advertise_cmd
);
565 install_element (OSPF6_NODE
, &no_area_range_cmd
);