]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_area.c
2005-04-07 Paul Jakma <paul.jakma@sun.com>
[mirror_frr.git] / ospf6d / ospf6_area.c
1 /*
2 * Copyright (C) 2003 Yasuhiro Ohara
3 *
4 * This file is part of GNU Zebra.
5 *
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
9 * later version.
10 *
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.
15 *
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.
20 */
21
22 #include <zebra.h>
23
24 #include "log.h"
25 #include "memory.h"
26 #include "linklist.h"
27 #include "thread.h"
28 #include "vty.h"
29 #include "command.h"
30 #include "if.h"
31 #include "prefix.h"
32 #include "table.h"
33
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"
44 #include "ospf6d.h"
45
46 int
47 ospf6_area_cmp (void *va, void *vb)
48 {
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);
52 }
53
54 /* schedule routing table recalculation */
55 void
56 ospf6_area_lsdb_hook_add (struct ospf6_lsa *lsa)
57 {
58 switch (ntohs (lsa->header->type))
59 {
60 case OSPF6_LSTYPE_ROUTER:
61 case OSPF6_LSTYPE_NETWORK:
62 if (IS_OSPF6_DEBUG_EXAMIN_TYPE (lsa->header->type))
63 {
64 zlog_debug ("Examin %s", lsa->name);
65 zlog_debug ("Schedule SPF Calculation for %s",
66 OSPF6_AREA (lsa->lsdb->data)->name);
67 }
68 ospf6_spf_schedule (OSPF6_AREA (lsa->lsdb->data));
69 break;
70
71 case OSPF6_LSTYPE_INTRA_PREFIX:
72 ospf6_intra_prefix_lsa_add (lsa);
73 break;
74
75 case OSPF6_LSTYPE_INTER_PREFIX:
76 case OSPF6_LSTYPE_INTER_ROUTER:
77 ospf6_abr_examin_summary (lsa, (struct ospf6_area *) lsa->lsdb->data);
78 break;
79
80 default:
81 break;
82 }
83 }
84
85 void
86 ospf6_area_lsdb_hook_remove (struct ospf6_lsa *lsa)
87 {
88 switch (ntohs (lsa->header->type))
89 {
90 case OSPF6_LSTYPE_ROUTER:
91 case OSPF6_LSTYPE_NETWORK:
92 if (IS_OSPF6_DEBUG_EXAMIN_TYPE (lsa->header->type))
93 {
94 zlog_debug ("LSA disappearing: %s", lsa->name);
95 zlog_debug ("Schedule SPF Calculation for %s",
96 OSPF6_AREA (lsa->lsdb->data)->name);
97 }
98 ospf6_spf_schedule (OSPF6_AREA (lsa->lsdb->data));
99 break;
100
101 case OSPF6_LSTYPE_INTRA_PREFIX:
102 ospf6_intra_prefix_lsa_remove (lsa);
103 break;
104
105 case OSPF6_LSTYPE_INTER_PREFIX:
106 case OSPF6_LSTYPE_INTER_ROUTER:
107 ospf6_abr_examin_summary (lsa, (struct ospf6_area *) lsa->lsdb->data);
108 break;
109
110 default:
111 break;
112 }
113 }
114
115 void
116 ospf6_area_route_hook_add (struct ospf6_route *route)
117 {
118 struct ospf6_route *copy = ospf6_route_copy (route);
119 ospf6_route_add (copy, ospf6->route_table);
120 }
121
122 void
123 ospf6_area_route_hook_remove (struct ospf6_route *route)
124 {
125 struct ospf6_route *copy;
126
127 copy = ospf6_route_lookup_identical (route, ospf6->route_table);
128 if (copy)
129 ospf6_route_remove (copy, ospf6->route_table);
130 }
131
132 /* Make new area structure */
133 struct ospf6_area *
134 ospf6_area_create (u_int32_t area_id, struct ospf6 *o)
135 {
136 struct ospf6_area *oa;
137 struct ospf6_route *route;
138
139 oa = XCALLOC (MTYPE_OSPF6_AREA, sizeof (struct ospf6_area));
140
141 inet_ntop (AF_INET, &area_id, oa->name, sizeof (oa->name));
142 oa->area_id = area_id;
143 oa->if_list = list_new ();
144
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);
149
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;
154
155 oa->range_table = ospf6_route_table_create ();
156 oa->summary_prefix = ospf6_route_table_create ();
157 oa->summary_router = ospf6_route_table_create ();
158
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);
163
164 oa->ospf6 = o;
165 listnode_add_sort (o->area_list, oa);
166
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);
171
172 return oa;
173 }
174
175 void
176 ospf6_area_delete (struct ospf6_area *oa)
177 {
178 struct listnode *n, *nnode;
179 struct ospf6_interface *oi;
180
181 ospf6_route_table_delete (oa->range_table);
182 ospf6_route_table_delete (oa->summary_prefix);
183 ospf6_route_table_delete (oa->summary_router);
184
185 /* ospf6 interface list */
186 for (ALL_LIST_ELEMENTS (oa->if_list, n, nnode, oi))
187 {
188 ospf6_interface_delete (oi);
189 }
190 list_delete (oa->if_list);
191
192 ospf6_lsdb_delete (oa->lsdb);
193 ospf6_lsdb_delete (oa->lsdb_self);
194
195 ospf6_route_table_delete (oa->spf_table);
196 ospf6_route_table_delete (oa->route_table);
197
198 #if 0
199 ospf6_spftree_delete (oa->spf_tree);
200 ospf6_route_table_delete (oa->topology_table);
201 #endif /*0*/
202
203 THREAD_OFF (oa->thread_spf_calculation);
204 THREAD_OFF (oa->thread_route_calculation);
205
206 listnode_delete (oa->ospf6->area_list, oa);
207 oa->ospf6 = NULL;
208
209 /* free area */
210 XFREE (MTYPE_OSPF6_AREA, oa);
211 }
212
213 struct ospf6_area *
214 ospf6_area_lookup (u_int32_t area_id, struct ospf6 *ospf6)
215 {
216 struct ospf6_area *oa;
217 struct listnode *n;
218
219 for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, n, oa))
220 if (oa->area_id == area_id)
221 return oa;
222
223 return (struct ospf6_area *) NULL;
224 }
225
226 struct ospf6_area *
227 ospf6_area_get (u_int32_t area_id, struct ospf6 *o)
228 {
229 struct ospf6_area *oa;
230 oa = ospf6_area_lookup (area_id, o);
231 if (oa == NULL)
232 oa = ospf6_area_create (area_id, o);
233 return oa;
234 }
235
236 void
237 ospf6_area_enable (struct ospf6_area *oa)
238 {
239 struct listnode *node, *nnode;
240 struct ospf6_interface *oi;
241
242 SET_FLAG (oa->flag, OSPF6_AREA_ENABLE);
243
244 for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi))
245 ospf6_interface_enable (oi);
246 }
247
248 void
249 ospf6_area_disable (struct ospf6_area *oa)
250 {
251 struct listnode *node, *nnode;
252 struct ospf6_interface *oi;
253
254 UNSET_FLAG (oa->flag, OSPF6_AREA_ENABLE);
255
256 for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi))
257 ospf6_interface_disable (oi);
258 }
259
260 \f
261 void
262 ospf6_area_show (struct vty *vty, struct ospf6_area *oa)
263 {
264 struct listnode *i;
265 struct ospf6_interface *oi;
266
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);
270
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);
274
275 vty_out (vty, "%s", VNL);
276 }
277
278
279 #define OSPF6_CMD_AREA_LOOKUP(str, oa) \
280 { \
281 u_int32_t area_id = 0; \
282 if (inet_pton (AF_INET, str, &area_id) != 1) \
283 { \
284 vty_out (vty, "Malformed Area-ID: %s%s", str, VNL); \
285 return CMD_SUCCESS; \
286 } \
287 oa = ospf6_area_lookup (area_id, ospf6); \
288 if (oa == NULL) \
289 { \
290 vty_out (vty, "No such Area: %s%s", str, VNL); \
291 return CMD_SUCCESS; \
292 } \
293 }
294
295 #define OSPF6_CMD_AREA_GET(str, oa) \
296 { \
297 u_int32_t area_id = 0; \
298 if (inet_pton (AF_INET, str, &area_id) != 1) \
299 { \
300 vty_out (vty, "Malformed Area-ID: %s%s", str, VNL); \
301 return CMD_SUCCESS; \
302 } \
303 oa = ospf6_area_get (area_id, ospf6); \
304 }
305
306 DEFUN (area_range,
307 area_range_cmd,
308 "area A.B.C.D range X:X::X:X/M",
309 "OSPF area parameters\n"
310 OSPF6_AREA_ID_STR
311 "Configured address range\n"
312 "Specify IPv6 prefix\n"
313 )
314 {
315 int ret;
316 struct ospf6_area *oa;
317 struct prefix prefix;
318 struct ospf6_route *range;
319
320 OSPF6_CMD_AREA_GET (argv[0], oa);
321 argc--;
322 argv++;
323
324 ret = str2prefix (argv[0], &prefix);
325 if (ret != 1 || prefix.family != AF_INET6)
326 {
327 vty_out (vty, "Malformed argument: %s%s", argv[0], VNL);
328 return CMD_SUCCESS;
329 }
330 argc--;
331 argv++;
332
333 range = ospf6_route_lookup (&prefix, oa->range_table);
334 if (range == NULL)
335 {
336 range = ospf6_route_create ();
337 range->type = OSPF6_DEST_TYPE_RANGE;
338 range->prefix = prefix;
339 }
340
341 if (argc)
342 {
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);
347 }
348
349 ospf6_route_add (range, oa->range_table);
350 return CMD_SUCCESS;
351 }
352
353 ALIAS (area_range,
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"
357 OSPF6_AREA_ID_STR
358 "Configured address range\n"
359 "Specify IPv6 prefix\n"
360 );
361
362 DEFUN (no_area_range,
363 no_area_range_cmd,
364 "no area A.B.C.D range X:X::X:X/M",
365 "OSPF area parameters\n"
366 OSPF6_AREA_ID_STR
367 "Configured address range\n"
368 "Specify IPv6 prefix\n"
369 )
370 {
371 int ret;
372 struct ospf6_area *oa;
373 struct prefix prefix;
374 struct ospf6_route *range;
375
376 OSPF6_CMD_AREA_GET (argv[0], oa);
377 argc--;
378 argv++;
379
380 ret = str2prefix (argv[0], &prefix);
381 if (ret != 1 || prefix.family != AF_INET6)
382 {
383 vty_out (vty, "Malformed argument: %s%s", argv[0], VNL);
384 return CMD_SUCCESS;
385 }
386
387 range = ospf6_route_lookup (&prefix, oa->range_table);
388 if (range == NULL)
389 {
390 vty_out (vty, "Range %s does not exists.%s", argv[0], VNL);
391 return CMD_SUCCESS;
392 }
393
394 ospf6_route_remove (range, oa->range_table);
395 return CMD_SUCCESS;
396 }
397
398 void
399 ospf6_area_config_write (struct vty *vty)
400 {
401 struct listnode *node;
402 struct ospf6_area *oa;
403 struct ospf6_route *range;
404 char buf[128];
405
406 for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, node, oa))
407 {
408 for (range = ospf6_route_head (oa->range_table); range;
409 range = ospf6_route_next (range))
410 {
411 prefix2str (&range->prefix, buf, sizeof (buf));
412 vty_out (vty, " area %s range %s%s", oa->name, buf, VNL);
413 }
414 }
415 }
416
417 DEFUN (show_ipv6_ospf6_spf_tree,
418 show_ipv6_ospf6_spf_tree_cmd,
419 "show ipv6 ospf6 spf tree",
420 SHOW_STR
421 IP6_STR
422 OSPF6_STR
423 "Shortest Path First caculation\n"
424 "Show SPF tree\n")
425 {
426 struct listnode *node;
427 struct ospf6_area *oa;
428 struct ospf6_vertex *root;
429 struct ospf6_route *route;
430 struct prefix prefix;
431
432 ospf6_linkstate_prefix (ospf6->router_id, htonl (0), &prefix);
433
434 for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, node, oa))
435 {
436 route = ospf6_route_lookup (&prefix, oa->spf_table);
437 if (route == NULL)
438 {
439 vty_out (vty, "LS entry for root not found in area %s%s",
440 oa->name, VNL);
441 continue;
442 }
443 root = (struct ospf6_vertex *) route->route_option;
444 ospf6_spf_display_subtree (vty, "", 0, root);
445 }
446
447 return CMD_SUCCESS;
448 }
449
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",
453 SHOW_STR
454 IP6_STR
455 OSPF6_STR
456 OSPF6_AREA_STR
457 OSPF6_AREA_ID_STR
458 "Shortest Path First caculation\n"
459 "Show SPF tree\n")
460 {
461 u_int32_t area_id;
462 struct ospf6_area *oa;
463 struct ospf6_vertex *root;
464 struct ospf6_route *route;
465 struct prefix prefix;
466
467 ospf6_linkstate_prefix (ospf6->router_id, htonl (0), &prefix);
468
469 if (inet_pton (AF_INET, argv[0], &area_id) != 1)
470 {
471 vty_out (vty, "Malformed Area-ID: %s%s", argv[0], VNL);
472 return CMD_SUCCESS;
473 }
474 oa = ospf6_area_lookup (area_id, ospf6);
475 if (oa == NULL)
476 {
477 vty_out (vty, "No such Area: %s%s", argv[0], VNL);
478 return CMD_SUCCESS;
479 }
480
481 route = ospf6_route_lookup (&prefix, oa->spf_table);
482 if (route == NULL)
483 {
484 vty_out (vty, "LS entry for root not found in area %s%s",
485 oa->name, VNL);
486 return CMD_SUCCESS;
487 }
488 root = (struct ospf6_vertex *) route->route_option;
489 ospf6_spf_display_subtree (vty, "", 0, root);
490
491 return CMD_SUCCESS;
492 }
493
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",
497 SHOW_STR
498 IP6_STR
499 OSPF6_STR
500 "Shortest Path First caculation\n"
501 "Show SPF tree\n"
502 "Specify root's router-id to calculate another router's SPF tree\n")
503 {
504 u_int32_t area_id;
505 struct ospf6_area *oa;
506 struct ospf6_vertex *root;
507 struct ospf6_route *route;
508 struct prefix prefix;
509 u_int32_t router_id;
510 struct ospf6_route_table *spf_table;
511 unsigned char tmp_debug_ospf6_spf = 0;
512
513 inet_pton (AF_INET, argv[0], &router_id);
514 ospf6_linkstate_prefix (router_id, htonl (0), &prefix);
515
516 if (inet_pton (AF_INET, argv[1], &area_id) != 1)
517 {
518 vty_out (vty, "Malformed Area-ID: %s%s", argv[1], VNL);
519 return CMD_SUCCESS;
520 }
521 oa = ospf6_area_lookup (area_id, ospf6);
522 if (oa == NULL)
523 {
524 vty_out (vty, "No such Area: %s%s", argv[1], VNL);
525 return CMD_SUCCESS;
526 }
527
528 tmp_debug_ospf6_spf = conf_debug_ospf6_spf;
529 conf_debug_ospf6_spf = 0;
530
531 spf_table = ospf6_route_table_create ();
532 ospf6_spf_calculation (router_id, spf_table, oa);
533
534 conf_debug_ospf6_spf = tmp_debug_ospf6_spf;
535
536 route = ospf6_route_lookup (&prefix, spf_table);
537 if (route == NULL)
538 {
539 ospf6_spf_table_finish (spf_table);
540 ospf6_route_table_delete (spf_table);
541 return CMD_SUCCESS;
542 }
543 root = (struct ospf6_vertex *) route->route_option;
544 ospf6_spf_display_subtree (vty, "", 0, root);
545
546 ospf6_spf_table_finish (spf_table);
547 ospf6_route_table_delete (spf_table);
548
549 return CMD_SUCCESS;
550 }
551
552 void
553 ospf6_area_init ()
554 {
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);
558
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);
562
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);
566 }
567
568