]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_area.c
Fix by Vadim Suraev - [zebra 14710] #6.
[mirror_frr.git] / ospf6d / ospf6_area.c
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