]>
Commit | Line | Data |
---|---|---|
718e3744 | 1 | /* |
2 | * OSPF6 Area Data Structure | |
3 | * Copyright (C) 1999-2002 Yasuhiro Ohara | |
4 | * | |
5 | * This file is part of GNU Zebra. | |
6 | * | |
7 | * GNU Zebra is free software; you can redistribute it and/or modify it | |
8 | * under the terms of the GNU General Public License as published by the | |
9 | * Free Software Foundation; either version 2, or (at your option) any | |
10 | * later version. | |
11 | * | |
12 | * GNU Zebra is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with GNU Zebra; see the file COPYING. If not, write to the | |
19 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
20 | * Boston, MA 02111-1307, USA. | |
21 | */ | |
22 | ||
23 | #include "ospf6d.h" | |
24 | ||
25 | static int area_index; | |
26 | #define IS_OSPF6_DUMP_AREA (ospf6_dump_is_on (area_index)) | |
27 | ||
28 | static void | |
29 | ospf6_area_foreach_interface (struct ospf6_area *o6a, void *arg, int val, | |
30 | void (*func) (void *, int, void *)) | |
31 | { | |
32 | listnode node; | |
33 | struct ospf6_interface *o6i; | |
34 | ||
35 | for (node = listhead (o6a->if_list); node; nextnode (node)) | |
36 | { | |
37 | o6i = (struct ospf6_interface *) getdata (node); | |
38 | (*func) (arg, val, o6i); | |
39 | } | |
40 | } | |
41 | ||
42 | static void | |
43 | ospf6_area_foreach_neighbor (struct ospf6_area *o6a, void *arg, int val, | |
44 | void (*func) (void *, int, void *)) | |
45 | { | |
46 | listnode node; | |
47 | struct ospf6_interface *o6i; | |
48 | ||
49 | for (node = listhead (o6a->if_list); node; nextnode (node)) | |
50 | { | |
51 | o6i = (struct ospf6_interface *) getdata (node); | |
52 | (*o6i->foreach_nei) (o6i, arg, val, func); | |
53 | } | |
54 | } | |
55 | ||
56 | static int | |
57 | ospf6_area_maxage_remover (struct thread *t) | |
58 | { | |
59 | int count; | |
60 | struct ospf6_area *o6a = (struct ospf6_area *) THREAD_ARG (t); | |
61 | ||
62 | o6a->maxage_remover = (struct thread *) NULL; | |
63 | ||
64 | count = 0; | |
65 | o6a->foreach_nei (o6a, &count, NBS_EXCHANGE, ospf6_count_state); | |
66 | o6a->foreach_nei (o6a, &count, NBS_LOADING, ospf6_count_state); | |
67 | if (count != 0) | |
68 | return 0; | |
69 | ||
70 | ospf6_lsdb_remove_maxage (o6a->lsdb); | |
71 | return 0; | |
72 | } | |
73 | ||
74 | void | |
75 | ospf6_area_schedule_maxage_remover (void *arg, int val, void *obj) | |
76 | { | |
77 | struct ospf6_area *o6a = (struct ospf6_area *) obj; | |
78 | ||
79 | if (o6a->maxage_remover != NULL) | |
80 | return; | |
81 | ||
82 | o6a->maxage_remover = | |
83 | thread_add_event (master, ospf6_area_maxage_remover, o6a, 0); | |
84 | } | |
85 | ||
86 | int | |
87 | ospf6_area_is_stub (struct ospf6_area *o6a) | |
88 | { | |
89 | if (OSPF6_OPT_ISSET (o6a->options, OSPF6_OPT_E)) | |
90 | return 0; | |
91 | return 1; | |
92 | } | |
93 | ||
94 | int | |
95 | ospf6_area_is_transit (struct ospf6_area *o6a) | |
96 | { | |
97 | return 0; | |
98 | } | |
99 | ||
100 | \f | |
101 | ||
102 | void | |
103 | ospf6_area_route_add (void *data) | |
104 | { | |
105 | struct ospf6_route_req *route = data; | |
106 | struct in6_addr local; | |
107 | ||
108 | inet_pton (AF_INET6, "::1", &local); | |
109 | if (! memcmp (&route->nexthop.address, &local, sizeof (struct in6_addr))) | |
110 | { | |
111 | if (IS_OSPF6_DUMP_AREA) | |
112 | zlog_info ("AREA: Self-originated route add, ignore"); | |
113 | return; | |
114 | } | |
115 | ||
116 | ospf6_route_add (route, ospf6->route_table); | |
117 | } | |
118 | ||
119 | void | |
120 | ospf6_area_route_remove (void *data) | |
121 | { | |
122 | struct ospf6_route_req *route = data; | |
123 | struct in6_addr local; | |
124 | ||
125 | inet_pton (AF_INET6, "::1", &local); | |
126 | if (! memcmp (&route->nexthop.address, &local, sizeof (struct in6_addr))) | |
127 | { | |
128 | if (IS_OSPF6_DUMP_AREA) | |
129 | zlog_info ("AREA: Self-originated route remove, ignore"); | |
130 | return; | |
131 | } | |
132 | ||
133 | ospf6_route_remove (route, ospf6->route_table); | |
134 | } | |
135 | ||
136 | /* Make new area structure */ | |
137 | struct ospf6_area * | |
138 | ospf6_area_create (u_int32_t area_id) | |
139 | { | |
140 | struct ospf6_area *o6a; | |
141 | char namebuf[64]; | |
142 | ||
143 | /* allocate memory */ | |
144 | o6a = XCALLOC (MTYPE_OSPF6_AREA, sizeof (struct ospf6_area)); | |
145 | ||
146 | /* initialize */ | |
147 | inet_ntop (AF_INET, &area_id, o6a->str, sizeof (o6a->str)); | |
148 | o6a->area_id = area_id; | |
149 | o6a->if_list = list_new (); | |
150 | ||
151 | o6a->lsdb = ospf6_lsdb_create (); | |
152 | o6a->spf_tree = ospf6_spftree_create (); | |
153 | ||
154 | snprintf (namebuf, sizeof (namebuf), "Area %s's route table", o6a->str); | |
155 | o6a->route_table = ospf6_route_table_create (namebuf); | |
156 | o6a->route_table->hook_add = ospf6_area_route_add; | |
157 | o6a->route_table->hook_change = ospf6_area_route_add; | |
158 | o6a->route_table->hook_remove = ospf6_area_route_remove; | |
159 | ||
160 | snprintf (namebuf, sizeof (namebuf), "Area %s's topology table", o6a->str); | |
161 | o6a->table_topology = ospf6_route_table_create (namebuf); | |
162 | o6a->table_topology->hook_add = ospf6_intra_topology_add; | |
163 | o6a->table_topology->hook_change = ospf6_intra_topology_add; | |
164 | o6a->table_topology->hook_remove = ospf6_intra_topology_remove; | |
165 | ||
166 | /* xxx, set options */ | |
167 | OSPF6_OPT_SET (o6a->options, OSPF6_OPT_V6); | |
168 | OSPF6_OPT_SET (o6a->options, OSPF6_OPT_E); | |
169 | OSPF6_OPT_SET (o6a->options, OSPF6_OPT_R); | |
170 | ||
171 | o6a->foreach_if = ospf6_area_foreach_interface; | |
172 | o6a->foreach_nei = ospf6_area_foreach_neighbor; | |
173 | ||
174 | return o6a; | |
175 | } | |
176 | ||
177 | void | |
178 | ospf6_area_bind_top (struct ospf6_area *o6a, struct ospf6 *o6) | |
179 | { | |
180 | o6a->ospf6 = o6; | |
181 | CALL_CHANGE_HOOK (&area_hook, o6a); | |
182 | return; | |
183 | } | |
184 | ||
185 | void | |
186 | ospf6_area_delete (struct ospf6_area *o6a) | |
187 | { | |
188 | listnode n; | |
189 | struct ospf6_interface *o6i; | |
190 | ||
191 | CALL_REMOVE_HOOK (&area_hook, o6a); | |
192 | ||
193 | /* ospf6 interface list */ | |
194 | for (n = listhead (o6a->if_list); n; nextnode (n)) | |
195 | { | |
196 | o6i = (struct ospf6_interface *) getdata (n); | |
197 | /* ospf6_interface_delete (o6i); */ | |
198 | } | |
199 | list_delete (o6a->if_list); | |
200 | ||
201 | /* terminate LSDB */ | |
202 | ospf6_lsdb_remove_all (o6a->lsdb); | |
203 | ||
204 | /* spf tree terminate */ | |
205 | /* xxx */ | |
206 | ||
207 | /* threads */ | |
208 | if (o6a->spf_calc) | |
209 | thread_cancel (o6a->spf_calc); | |
210 | o6a->spf_calc = (struct thread *) NULL; | |
211 | if (o6a->route_calc) | |
212 | thread_cancel (o6a->route_calc); | |
213 | o6a->route_calc = (struct thread *) NULL; | |
214 | ||
215 | /* new */ | |
216 | ospf6_route_table_delete (o6a->route_table); | |
217 | ||
218 | ospf6_spftree_delete (o6a->spf_tree); | |
219 | ospf6_route_table_delete (o6a->table_topology); | |
220 | ||
221 | /* free area */ | |
222 | XFREE (MTYPE_OSPF6_AREA, o6a); | |
223 | } | |
224 | ||
225 | struct ospf6_area * | |
226 | ospf6_area_lookup (u_int32_t area_id, struct ospf6 *o6) | |
227 | { | |
228 | struct ospf6_area *o6a; | |
229 | listnode n; | |
230 | ||
231 | for (n = listhead (o6->area_list); n; nextnode (n)) | |
232 | { | |
233 | o6a = (struct ospf6_area *) getdata (n); | |
234 | if (o6a->area_id == area_id) | |
235 | return o6a; | |
236 | } | |
237 | ||
238 | return (struct ospf6_area *) NULL; | |
239 | } | |
240 | ||
241 | void | |
242 | ospf6_area_show (struct vty *vty, struct ospf6_area *o6a) | |
243 | { | |
244 | listnode i; | |
245 | struct ospf6_interface *o6i; | |
246 | ||
247 | vty_out (vty, " Area %s%s", o6a->str, VTY_NEWLINE); | |
248 | vty_out (vty, " Number of Area scoped LSAs is %u%s", | |
249 | o6a->lsdb->count, VTY_NEWLINE); | |
250 | ||
251 | ospf6_spf_statistics_show (vty, o6a->spf_tree); | |
252 | ||
253 | vty_out (vty, " Interface attached to this area:"); | |
254 | for (i = listhead (o6a->if_list); i; nextnode (i)) | |
255 | { | |
256 | o6i = (struct ospf6_interface *) getdata (i); | |
257 | vty_out (vty, " %s", o6i->interface->name); | |
258 | } | |
259 | vty_out (vty, "%s", VTY_NEWLINE); | |
260 | ||
261 | for (i = listhead (o6a->if_list); i; nextnode (i)) | |
262 | { | |
263 | o6i = (struct ospf6_interface *) getdata (i); | |
264 | if (listcount (o6i->neighbor_list) != 0) | |
265 | ospf6_interface_statistics_show (vty, o6i); | |
266 | } | |
267 | } | |
268 | ||
269 | void | |
270 | ospf6_area_statistics_show (struct vty *vty, struct ospf6_area *o6a) | |
271 | { | |
272 | #if 0 | |
273 | listnode node; | |
274 | struct ospf6_interface *o6i; | |
275 | ||
276 | vty_out (vty, " Statistics of Area %s%s", o6a->str, VTY_NEWLINE); | |
277 | #endif | |
278 | } | |
279 | ||
280 | DEFUN (show_ipv6_ospf6_area_route, | |
281 | show_ipv6_ospf6_area_route_cmd, | |
282 | "show ipv6 ospf6 area A.B.C.D route", | |
283 | SHOW_STR | |
284 | IP6_STR | |
285 | OSPF6_STR | |
286 | OSPF6_AREA_STR | |
287 | OSPF6_AREA_ID_STR | |
288 | ROUTE_STR | |
289 | ) | |
290 | { | |
291 | struct ospf6_area *o6a; | |
292 | u_int32_t area_id; | |
293 | ||
294 | OSPF6_CMD_CHECK_RUNNING (); | |
295 | ||
296 | inet_pton (AF_INET, argv[0], &area_id); | |
297 | o6a = ospf6_area_lookup (area_id, ospf6); | |
298 | ||
299 | if (! o6a) | |
300 | return CMD_SUCCESS; | |
301 | ||
302 | argc -= 1; | |
303 | argv += 1; | |
304 | ||
305 | return ospf6_route_table_show (vty, argc, argv, o6a->route_table); | |
306 | } | |
307 | ||
308 | ALIAS (show_ipv6_ospf6_area_route, | |
309 | show_ipv6_ospf6_area_route_prefix_cmd, | |
310 | "show ipv6 ospf6 area A.B.C.D route (X::X|detail)", | |
311 | SHOW_STR | |
312 | IP6_STR | |
313 | OSPF6_STR | |
314 | OSPF6_AREA_STR | |
315 | OSPF6_AREA_ID_STR | |
316 | ROUTE_STR | |
317 | "Specify IPv6 address\n" | |
318 | "Detailed information\n" | |
319 | ) | |
320 | ||
321 | void | |
322 | ospf6_area_init () | |
323 | { | |
324 | area_index = ospf6_dump_install ("area", "Area information\n"); | |
325 | ||
326 | install_element (VIEW_NODE, &show_ipv6_ospf6_area_route_cmd); | |
327 | install_element (VIEW_NODE, &show_ipv6_ospf6_area_route_prefix_cmd); | |
328 | install_element (ENABLE_NODE, &show_ipv6_ospf6_area_route_cmd); | |
329 | install_element (ENABLE_NODE, &show_ipv6_ospf6_area_route_prefix_cmd); | |
330 | } | |
331 | ||
332 |