]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_area.c
Merge pull request #381 from donaldsharp/pimmerino
[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 #include "plist.h"
34 #include "filter.h"
35
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"
46 #include "ospf6_asbr.h"
47 #include "ospf6d.h"
48
49 int
50 ospf6_area_cmp (void *va, void *vb)
51 {
52 struct ospf6_area *oa = (struct ospf6_area *) va;
53 struct ospf6_area *ob = (struct ospf6_area *) vb;
54 return (ntohl (oa->area_id) < ntohl (ob->area_id) ? -1 : 1);
55 }
56
57 /* schedule routing table recalculation */
58 static void
59 ospf6_area_lsdb_hook_add (struct ospf6_lsa *lsa)
60 {
61 switch (ntohs (lsa->header->type))
62 {
63 case OSPF6_LSTYPE_ROUTER:
64 case OSPF6_LSTYPE_NETWORK:
65 if (IS_OSPF6_DEBUG_EXAMIN_TYPE (lsa->header->type))
66 {
67 zlog_debug ("Examin %s", lsa->name);
68 zlog_debug ("Schedule SPF Calculation for %s",
69 OSPF6_AREA (lsa->lsdb->data)->name);
70 }
71 ospf6_spf_schedule (OSPF6_PROCESS(OSPF6_AREA (lsa->lsdb->data)->ospf6),
72 ospf6_lsadd_to_spf_reason(lsa));
73 break;
74
75 case OSPF6_LSTYPE_INTRA_PREFIX:
76 ospf6_intra_prefix_lsa_add (lsa);
77 break;
78
79 case OSPF6_LSTYPE_INTER_PREFIX:
80 case OSPF6_LSTYPE_INTER_ROUTER:
81 ospf6_abr_examin_summary (lsa, (struct ospf6_area *) lsa->lsdb->data);
82 break;
83
84 default:
85 break;
86 }
87 }
88
89 static void
90 ospf6_area_lsdb_hook_remove (struct ospf6_lsa *lsa)
91 {
92 switch (ntohs (lsa->header->type))
93 {
94 case OSPF6_LSTYPE_ROUTER:
95 case OSPF6_LSTYPE_NETWORK:
96 if (IS_OSPF6_DEBUG_EXAMIN_TYPE (lsa->header->type))
97 {
98 zlog_debug ("LSA disappearing: %s", lsa->name);
99 zlog_debug ("Schedule SPF Calculation for %s",
100 OSPF6_AREA (lsa->lsdb->data)->name);
101 }
102 ospf6_spf_schedule (OSPF6_PROCESS(OSPF6_AREA (lsa->lsdb->data)->ospf6),
103 ospf6_lsremove_to_spf_reason(lsa));
104 break;
105
106 case OSPF6_LSTYPE_INTRA_PREFIX:
107 ospf6_intra_prefix_lsa_remove (lsa);
108 break;
109
110 case OSPF6_LSTYPE_INTER_PREFIX:
111 case OSPF6_LSTYPE_INTER_ROUTER:
112 ospf6_abr_examin_summary (lsa, (struct ospf6_area *) lsa->lsdb->data);
113 break;
114
115 default:
116 break;
117 }
118 }
119
120 static void
121 ospf6_area_route_hook_add (struct ospf6_route *route)
122 {
123 struct ospf6_route *copy = ospf6_route_copy (route);
124 ospf6_route_add (copy, ospf6->route_table);
125 }
126
127 static void
128 ospf6_area_route_hook_remove (struct ospf6_route *route)
129 {
130 struct ospf6_route *copy;
131
132 copy = ospf6_route_lookup_identical (route, ospf6->route_table);
133 if (copy)
134 ospf6_route_remove (copy, ospf6->route_table);
135 }
136
137 static void
138 ospf6_area_stub_update (struct ospf6_area *area)
139 {
140
141 if (IS_AREA_STUB (area))
142 {
143 if (IS_OSPF6_DEBUG_ORIGINATE (ROUTER))
144 zlog_debug ("Stubbing out area for if %s\n", area->name);
145 OSPF6_OPT_CLEAR (area->options, OSPF6_OPT_E);
146 }
147 else if (IS_AREA_ENABLED (area))
148 {
149 if (IS_OSPF6_DEBUG_ORIGINATE (ROUTER))
150 zlog_debug ("Normal area for if %s\n", area->name);
151 OSPF6_OPT_SET (area->options, OSPF6_OPT_E);
152 ospf6_asbr_send_externals_to_area (area);
153 }
154
155 OSPF6_ROUTER_LSA_SCHEDULE(area);
156 }
157
158 static int
159 ospf6_area_stub_set (struct ospf6 *ospf6, struct ospf6_area *area)
160 {
161 if (!IS_AREA_STUB(area))
162 {
163 SET_FLAG (area->flag, OSPF6_AREA_STUB);
164 ospf6_area_stub_update (area);
165 }
166
167 return (1);
168 }
169
170 static void
171 ospf6_area_stub_unset (struct ospf6 *ospf6, struct ospf6_area *area)
172 {
173 if (IS_AREA_STUB (area))
174 {
175 UNSET_FLAG (area->flag, OSPF6_AREA_STUB);
176 ospf6_area_stub_update (area);
177 }
178 }
179
180 static void
181 ospf6_area_no_summary_set (struct ospf6 *ospf6, struct ospf6_area *area)
182 {
183 if (area)
184 {
185 if (!area->no_summary)
186 {
187 area->no_summary = 1;
188 ospf6_abr_range_reset_cost (ospf6);
189 ospf6_abr_prefix_resummarize (ospf6);
190 }
191 }
192 }
193
194 static void
195 ospf6_area_no_summary_unset (struct ospf6 *ospf6, struct ospf6_area *area)
196 {
197 if (area)
198 {
199 if (area->no_summary)
200 {
201 area->no_summary = 0;
202 ospf6_abr_range_reset_cost (ospf6);
203 ospf6_abr_prefix_resummarize (ospf6);
204 }
205 }
206 }
207
208 /* Make new area structure */
209 struct ospf6_area *
210 ospf6_area_create (u_int32_t area_id, struct ospf6 *o)
211 {
212 struct ospf6_area *oa;
213
214 oa = XCALLOC (MTYPE_OSPF6_AREA, sizeof (struct ospf6_area));
215
216 inet_ntop (AF_INET, &area_id, oa->name, sizeof (oa->name));
217 oa->area_id = area_id;
218 oa->if_list = list_new ();
219
220 oa->lsdb = ospf6_lsdb_create (oa);
221 oa->lsdb->hook_add = ospf6_area_lsdb_hook_add;
222 oa->lsdb->hook_remove = ospf6_area_lsdb_hook_remove;
223 oa->lsdb_self = ospf6_lsdb_create (oa);
224
225 oa->spf_table = OSPF6_ROUTE_TABLE_CREATE (AREA, SPF_RESULTS);
226 oa->spf_table->scope = oa;
227 oa->route_table = OSPF6_ROUTE_TABLE_CREATE (AREA, ROUTES);
228 oa->route_table->scope = oa;
229 oa->route_table->hook_add = ospf6_area_route_hook_add;
230 oa->route_table->hook_remove = ospf6_area_route_hook_remove;
231
232 oa->range_table = OSPF6_ROUTE_TABLE_CREATE (AREA, PREFIX_RANGES);
233 oa->range_table->scope = oa;
234 bf_init(oa->range_table->idspace, 32);
235 oa->summary_prefix = OSPF6_ROUTE_TABLE_CREATE (AREA, SUMMARY_PREFIXES);
236 oa->summary_prefix->scope = oa;
237 oa->summary_router = OSPF6_ROUTE_TABLE_CREATE (AREA, SUMMARY_ROUTERS);
238 oa->summary_router->scope = oa;
239
240 /* set default options */
241 if (CHECK_FLAG (o->flag, OSPF6_STUB_ROUTER))
242 {
243 OSPF6_OPT_CLEAR (oa->options, OSPF6_OPT_V6);
244 OSPF6_OPT_CLEAR (oa->options, OSPF6_OPT_R);
245 }
246 else
247 {
248 OSPF6_OPT_SET (oa->options, OSPF6_OPT_V6);
249 OSPF6_OPT_SET (oa->options, OSPF6_OPT_R);
250 }
251
252 OSPF6_OPT_SET (oa->options, OSPF6_OPT_E);
253
254 SET_FLAG (oa->flag, OSPF6_AREA_ACTIVE);
255 SET_FLAG (oa->flag, OSPF6_AREA_ENABLE);
256
257 oa->ospf6 = o;
258 listnode_add_sort (o->area_list, oa);
259
260 if (area_id == OSPF_AREA_BACKBONE)
261 {
262 o->backbone = oa;
263 }
264
265 return oa;
266 }
267
268 void
269 ospf6_area_delete (struct ospf6_area *oa)
270 {
271 struct listnode *n;
272 struct ospf6_interface *oi;
273
274 /* The ospf6_interface structs store configuration
275 * information which should not be lost/reset when
276 * deleting an area.
277 * So just detach the interface from the area and
278 * keep it around. */
279 for (ALL_LIST_ELEMENTS_RO (oa->if_list, n, oi))
280 oi->area = NULL;
281
282 list_delete (oa->if_list);
283
284 ospf6_lsdb_delete (oa->lsdb);
285 ospf6_lsdb_delete (oa->lsdb_self);
286
287 ospf6_spf_table_finish (oa->spf_table);
288 ospf6_route_table_delete (oa->spf_table);
289 ospf6_route_table_delete (oa->route_table);
290
291 ospf6_route_table_delete (oa->range_table);
292 ospf6_route_table_delete (oa->summary_prefix);
293 ospf6_route_table_delete (oa->summary_router);
294
295 listnode_delete (oa->ospf6->area_list, oa);
296 oa->ospf6 = NULL;
297
298 /* free area */
299 XFREE (MTYPE_OSPF6_AREA, oa);
300 }
301
302 struct ospf6_area *
303 ospf6_area_lookup (u_int32_t area_id, struct ospf6 *ospf6)
304 {
305 struct ospf6_area *oa;
306 struct listnode *n;
307
308 for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, n, oa))
309 if (oa->area_id == area_id)
310 return oa;
311
312 return (struct ospf6_area *) NULL;
313 }
314
315 static struct ospf6_area *
316 ospf6_area_get (u_int32_t area_id, struct ospf6 *o)
317 {
318 struct ospf6_area *oa;
319 oa = ospf6_area_lookup (area_id, o);
320 if (oa == NULL)
321 oa = ospf6_area_create (area_id, o);
322 return oa;
323 }
324
325 void
326 ospf6_area_enable (struct ospf6_area *oa)
327 {
328 struct listnode *node, *nnode;
329 struct ospf6_interface *oi;
330
331 SET_FLAG (oa->flag, OSPF6_AREA_ENABLE);
332
333 for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi))
334 ospf6_interface_enable (oi);
335 ospf6_abr_enable_area (oa);
336 }
337
338 void
339 ospf6_area_disable (struct ospf6_area *oa)
340 {
341 struct listnode *node, *nnode;
342 struct ospf6_interface *oi;
343
344 UNSET_FLAG (oa->flag, OSPF6_AREA_ENABLE);
345
346 for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi))
347 ospf6_interface_disable (oi);
348
349 ospf6_abr_disable_area (oa);
350 ospf6_lsdb_remove_all (oa->lsdb);
351 ospf6_lsdb_remove_all (oa->lsdb_self);
352
353 ospf6_spf_table_finish(oa->spf_table);
354 ospf6_route_remove_all(oa->route_table);
355
356 THREAD_OFF (oa->thread_router_lsa);
357 THREAD_OFF (oa->thread_intra_prefix_lsa);
358 }
359
360
361 void
362 ospf6_area_show (struct vty *vty, struct ospf6_area *oa)
363 {
364 struct listnode *i;
365 struct ospf6_interface *oi;
366 unsigned long result;
367
368 if (!IS_AREA_STUB (oa))
369 vty_out (vty, " Area %s%s", oa->name, VNL);
370 else
371 {
372 if (oa->no_summary)
373 {
374 vty_out (vty, " Area %s[Stub, No Summary]%s", oa->name, VNL);
375 }
376 else
377 {
378 vty_out (vty, " Area %s[Stub]%s", oa->name, VNL);
379 }
380 }
381 vty_out (vty, " Number of Area scoped LSAs is %u%s",
382 oa->lsdb->count, VNL);
383
384 vty_out (vty, " Interface attached to this area:");
385 for (ALL_LIST_ELEMENTS_RO (oa->if_list, i, oi))
386 vty_out (vty, " %s", oi->interface->name);
387 vty_out (vty, "%s", VNL);
388
389 if (oa->ts_spf.tv_sec || oa->ts_spf.tv_usec)
390 {
391 result = monotime_since(&oa->ts_spf, NULL);
392 if (result/TIMER_SECOND_MICRO > 0)
393 {
394 vty_out (vty, "SPF last executed %ld.%lds ago%s",
395 result/TIMER_SECOND_MICRO,
396 result%TIMER_SECOND_MICRO, VTY_NEWLINE);
397 }
398 else
399 {
400 vty_out (vty, "SPF last executed %ldus ago%s",
401 result, VTY_NEWLINE);
402 }
403 }
404 else
405 vty_out (vty, "SPF has not been run%s", VTY_NEWLINE);
406 }
407
408
409 #define OSPF6_CMD_AREA_LOOKUP(str, oa) \
410 { \
411 u_int32_t area_id = 0; \
412 if (inet_pton (AF_INET, str, &area_id) != 1) \
413 { \
414 vty_out (vty, "Malformed Area-ID: %s%s", str, VNL); \
415 return CMD_SUCCESS; \
416 } \
417 oa = ospf6_area_lookup (area_id, ospf6); \
418 if (oa == NULL) \
419 { \
420 vty_out (vty, "No such Area: %s%s", str, VNL); \
421 return CMD_SUCCESS; \
422 } \
423 }
424
425 #define OSPF6_CMD_AREA_GET(str, oa) \
426 { \
427 u_int32_t area_id = 0; \
428 if (inet_pton (AF_INET, str, &area_id) != 1) \
429 { \
430 vty_out (vty, "Malformed Area-ID: %s%s", str, VNL); \
431 return CMD_SUCCESS; \
432 } \
433 oa = ospf6_area_get (area_id, ospf6); \
434 }
435
436 DEFUN (area_range,
437 area_range_cmd,
438 "area <A.B.C.D|(0-4294967295)> range X:X::X:X/M [<advertise|not-advertise|cost (0-16777215)>]",
439 "OSPF6 area parameters\n"
440 "OSPF6 area ID in IP address format\n"
441 "OSPF6 area ID as a decimal value\n"
442 "Configured address range\n"
443 "Specify IPv6 prefix\n"
444 "Advertise\n"
445 "Do not advertise\n"
446 "User specified metric for this range\n"
447 "Advertised metric for this range\n")
448 {
449 int idx_ipv4 = 1;
450 int idx_ipv6_prefixlen = 3;
451 int idx_type = 4;
452 int ret;
453 struct ospf6_area *oa;
454 struct prefix prefix;
455 struct ospf6_route *range;
456 u_int32_t cost = OSPF_AREA_RANGE_COST_UNSPEC;
457
458 OSPF6_CMD_AREA_GET (argv[idx_ipv4]->arg, oa);
459
460 ret = str2prefix (argv[idx_ipv6_prefixlen]->arg, &prefix);
461 if (ret != 1 || prefix.family != AF_INET6)
462 {
463 vty_out (vty, "Malformed argument: %s%s", argv[idx_ipv6_prefixlen]->arg, VNL);
464 return CMD_SUCCESS;
465 }
466
467 range = ospf6_route_lookup (&prefix, oa->range_table);
468 if (range == NULL)
469 {
470 range = ospf6_route_create ();
471 range->type = OSPF6_DEST_TYPE_RANGE;
472 range->prefix = prefix;
473 range->path.area_id = oa->area_id;
474 range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC;
475 }
476
477 if (argc > idx_type)
478 {
479 if (strmatch (argv[idx_type]->text, "not-advertise"))
480 {
481 SET_FLAG (range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
482 }
483 else if (strmatch (argv[idx_type]->text, "advertise"))
484 {
485 UNSET_FLAG (range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
486 }
487 else
488 {
489 VTY_GET_INTEGER_RANGE ("cost", cost, argv[5]->arg, 0, OSPF_LS_INFINITY);
490 UNSET_FLAG (range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
491 }
492 }
493
494 range->path.u.cost_config = cost;
495
496 zlog_debug ("%s: for prefix %s, flag = %x\n", __func__, argv[idx_ipv6_prefixlen]->arg, range->flag);
497 if (range->rnode == NULL)
498 {
499 ospf6_route_add (range, oa->range_table);
500 }
501
502 if (ospf6_is_router_abr (ospf6))
503 {
504 /* Redo summaries if required */
505 ospf6_abr_prefix_resummarize (ospf6);
506 }
507
508 return CMD_SUCCESS;
509 }
510
511 DEFUN (no_area_range,
512 no_area_range_cmd,
513 "no area <A.B.C.D|(0-4294967295)> range X:X::X:X/M [<advertise|not-advertise|cost (0-16777215)>]",
514 NO_STR
515 "OSPF6 area parameters\n"
516 "OSPF6 area ID in IP address format\n"
517 "OSPF6 area ID as a decimal value\n"
518 "Configured address range\n"
519 "Specify IPv6 prefix\n"
520 "Advertise\n"
521 "Do not advertise\n"
522 "User specified metric for this range\n"
523 "Advertised metric for this range\n")
524 {
525 int idx_ipv4 = 2;
526 int ret;
527 struct ospf6_area *oa;
528 struct prefix prefix;
529 struct ospf6_route *range, *route;
530
531 OSPF6_CMD_AREA_GET (argv[idx_ipv4]->arg, oa);
532
533 ret = str2prefix (argv[idx_ipv4]->arg, &prefix);
534 if (ret != 1 || prefix.family != AF_INET6)
535 {
536 vty_out (vty, "Malformed argument: %s%s", argv[idx_ipv4]->arg, VNL);
537 return CMD_SUCCESS;
538 }
539
540 range = ospf6_route_lookup (&prefix, oa->range_table);
541 if (range == NULL)
542 {
543 vty_out (vty, "Range %s does not exists.%s", argv[idx_ipv4]->arg, VNL);
544 return CMD_SUCCESS;
545 }
546
547 if (ospf6_is_router_abr(oa->ospf6))
548 {
549 /* Blow away the aggregated LSA and route */
550 SET_FLAG (range->flag, OSPF6_ROUTE_REMOVE);
551
552 /* Redo summaries if required */
553 for (route = ospf6_route_head (ospf6->route_table); route;
554 route = ospf6_route_next (route))
555 ospf6_abr_originate_summary(route);
556
557 /* purge the old aggregated summary LSA */
558 ospf6_abr_originate_summary(range);
559 }
560 ospf6_route_remove (range, oa->range_table);
561
562 return CMD_SUCCESS;
563 }
564
565
566
567
568 void
569 ospf6_area_config_write (struct vty *vty)
570 {
571 struct listnode *node;
572 struct ospf6_area *oa;
573 struct ospf6_route *range;
574 char buf[PREFIX2STR_BUFFER];
575
576 for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, node, oa))
577 {
578 for (range = ospf6_route_head (oa->range_table); range;
579 range = ospf6_route_next (range))
580 {
581 prefix2str (&range->prefix, buf, sizeof (buf));
582 vty_out (vty, " area %s range %s", oa->name, buf);
583
584 if (CHECK_FLAG (range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE))
585 {
586 vty_out (vty, " not-advertise");
587 }
588 else
589 {
590 // "advertise" is the default so we do not display it
591 if (range->path.u.cost_config != OSPF_AREA_RANGE_COST_UNSPEC)
592 vty_out (vty, " cost %d", range->path.u.cost_config);
593 }
594 vty_out (vty, "%s", VNL);
595
596 }
597 if (IS_AREA_STUB (oa))
598 {
599 if (oa->no_summary)
600 vty_out (vty, " area %s stub no-summary%s", oa->name, VNL);
601 else
602 vty_out (vty, " area %s stub%s", oa->name, VNL);
603 }
604 if (PREFIX_NAME_IN (oa))
605 vty_out (vty, " area %s filter-list prefix %s in%s",
606 oa->name, PREFIX_NAME_IN (oa), VNL);
607 if (PREFIX_NAME_OUT (oa))
608 vty_out (vty, " area %s filter-list prefix %s out%s",
609 oa->name, PREFIX_NAME_OUT (oa), VNL);
610 if (IMPORT_NAME (oa))
611 vty_out (vty, " area %s import-list %s%s",
612 oa->name, IMPORT_NAME (oa), VNL);
613 if (EXPORT_NAME (oa))
614 vty_out (vty, " area %s export-list %s%s",
615 oa->name, EXPORT_NAME (oa), VNL);
616 }
617 }
618
619 DEFUN (area_filter_list,
620 area_filter_list_cmd,
621 "area A.B.C.D filter-list prefix WORD <in|out>",
622 "OSPF6 area parameters\n"
623 "OSPF6 area ID in IP address format\n"
624 "Filter networks between OSPF6 areas\n"
625 "Filter prefixes between OSPF6 areas\n"
626 "Name of an IPv6 prefix-list\n"
627 "Filter networks sent to this area\n"
628 "Filter networks sent from this area\n")
629 {
630 int idx_ipv4 = 1;
631 int idx_word = 4;
632 struct ospf6_area *area;
633 struct prefix_list *plist;
634
635 OSPF6_CMD_AREA_GET (argv[idx_ipv4]->arg, area);
636
637 plist = prefix_list_lookup (AFI_IP6, argv[idx_ipv4]->arg);
638 if (strncmp (argv[idx_word]->arg, "in", 2) == 0)
639 {
640 PREFIX_LIST_IN (area) = plist;
641 if (PREFIX_NAME_IN (area))
642 free (PREFIX_NAME_IN (area));
643
644 PREFIX_NAME_IN (area) = strdup (argv[idx_ipv4]->arg);
645 ospf6_abr_reimport (area);
646 }
647 else
648 {
649 PREFIX_LIST_OUT (area) = plist;
650 if (PREFIX_NAME_OUT (area))
651 free (PREFIX_NAME_OUT (area));
652
653 PREFIX_NAME_OUT (area) = strdup (argv[idx_ipv4]->arg);
654 ospf6_abr_enable_area (area);
655 }
656
657 return CMD_SUCCESS;
658 }
659
660 DEFUN (no_area_filter_list,
661 no_area_filter_list_cmd,
662 "no area A.B.C.D filter-list prefix WORD <in|out>",
663 NO_STR
664 "OSPF6 area parameters\n"
665 "OSPF6 area ID in IP address format\n"
666 "Filter networks between OSPF6 areas\n"
667 "Filter prefixes between OSPF6 areas\n"
668 "Name of an IPv6 prefix-list\n"
669 "Filter networks sent to this area\n"
670 "Filter networks sent from this area\n")
671 {
672 int idx_ipv4 = 2;
673 int idx_word = 5;
674 struct ospf6_area *area;
675
676 OSPF6_CMD_AREA_GET (argv[idx_ipv4]->arg, area);
677
678 if (strncmp (argv[idx_word]->arg, "in", 2) == 0)
679 {
680 if (PREFIX_NAME_IN (area))
681 if (strcmp (PREFIX_NAME_IN (area), argv[idx_ipv4]->arg) != 0)
682 return CMD_SUCCESS;
683
684 PREFIX_LIST_IN (area) = NULL;
685 if (PREFIX_NAME_IN (area))
686 free (PREFIX_NAME_IN (area));
687
688 PREFIX_NAME_IN (area) = NULL;
689 ospf6_abr_reimport (area);
690 }
691 else
692 {
693 if (PREFIX_NAME_OUT (area))
694 if (strcmp (PREFIX_NAME_OUT (area), argv[idx_ipv4]->arg) != 0)
695 return CMD_SUCCESS;
696
697 PREFIX_LIST_OUT (area) = NULL;
698 if (PREFIX_NAME_OUT (area))
699 free (PREFIX_NAME_OUT (area));
700
701 PREFIX_NAME_OUT (area) = NULL;
702 ospf6_abr_enable_area (area);
703 }
704
705 return CMD_SUCCESS;
706 }
707
708 DEFUN (area_import_list,
709 area_import_list_cmd,
710 "area A.B.C.D import-list NAME",
711 "OSPF6 area parameters\n"
712 "OSPF6 area ID in IP address format\n"
713 "Set the filter for networks from other areas announced to the specified one\n"
714 "Name of the acess-list\n")
715 {
716 int idx_ipv4 = 1;
717 int idx_name = 3;
718 struct ospf6_area *area;
719 struct access_list *list;
720
721 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
722
723 list = access_list_lookup (AFI_IP6, argv[idx_name]->arg);
724
725 IMPORT_LIST (area) = list;
726
727 if (IMPORT_NAME (area))
728 free (IMPORT_NAME (area));
729
730 IMPORT_NAME (area) = strdup (argv[idx_name]->arg);
731 ospf6_abr_reimport (area);
732
733 return CMD_SUCCESS;
734 }
735
736 DEFUN (no_area_import_list,
737 no_area_import_list_cmd,
738 "no area A.B.C.D import-list NAME",
739 NO_STR
740 "OSPF6 area parameters\n"
741 "OSPF6 area ID in IP address format\n"
742 "Unset the filter for networks announced to other areas\n"
743 "Name of the access-list\n")
744 {
745 int idx_ipv4 = 2;
746 struct ospf6_area *area;
747
748 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
749
750 IMPORT_LIST (area) = 0;
751
752 if (IMPORT_NAME (area))
753 free (IMPORT_NAME (area));
754
755 IMPORT_NAME (area) = NULL;
756 ospf6_abr_reimport (area);
757
758 return CMD_SUCCESS;
759 }
760
761 DEFUN (area_export_list,
762 area_export_list_cmd,
763 "area A.B.C.D export-list NAME",
764 "OSPF6 area parameters\n"
765 "OSPF6 area ID in IP address format\n"
766 "Set the filter for networks announced to other areas\n"
767 "Name of the acess-list\n")
768 {
769 int idx_ipv4 = 1;
770 int idx_name = 3;
771 struct ospf6_area *area;
772 struct access_list *list;
773
774 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
775
776 list = access_list_lookup (AFI_IP6, argv[idx_name]->arg);
777
778 EXPORT_LIST (area) = list;
779
780 if (EXPORT_NAME (area))
781 free (EXPORT_NAME (area));
782
783 EXPORT_NAME (area) = strdup (argv[idx_name]->arg);
784 ospf6_abr_enable_area (area);
785
786 return CMD_SUCCESS;
787 }
788
789 DEFUN (no_area_export_list,
790 no_area_export_list_cmd,
791 "no area A.B.C.D export-list NAME",
792 NO_STR
793 "OSPF6 area parameters\n"
794 "OSPF6 area ID in IP address format\n"
795 "Unset the filter for networks announced to other areas\n"
796 "Name of the access-list\n")
797 {
798 int idx_ipv4 = 2;
799 struct ospf6_area *area;
800
801 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
802
803 EXPORT_LIST (area) = 0;
804
805 if (EXPORT_NAME (area))
806 free (EXPORT_NAME (area));
807
808 EXPORT_NAME (area) = NULL;
809 ospf6_abr_enable_area (area);
810
811 return CMD_SUCCESS;
812 }
813
814 DEFUN (show_ipv6_ospf6_spf_tree,
815 show_ipv6_ospf6_spf_tree_cmd,
816 "show ipv6 ospf6 spf tree",
817 SHOW_STR
818 IP6_STR
819 OSPF6_STR
820 "Shortest Path First caculation\n"
821 "Show SPF tree\n")
822 {
823 struct listnode *node;
824 struct ospf6_area *oa;
825 struct ospf6_vertex *root;
826 struct ospf6_route *route;
827 struct prefix prefix;
828
829 OSPF6_CMD_CHECK_RUNNING ();
830
831 ospf6_linkstate_prefix (ospf6->router_id, htonl (0), &prefix);
832
833 for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, node, oa))
834 {
835 route = ospf6_route_lookup (&prefix, oa->spf_table);
836 if (route == NULL)
837 {
838 vty_out (vty, "LS entry for root not found in area %s%s",
839 oa->name, VNL);
840 continue;
841 }
842 root = (struct ospf6_vertex *) route->route_option;
843 ospf6_spf_display_subtree (vty, "", 0, root);
844 }
845
846 return CMD_SUCCESS;
847 }
848
849 DEFUN (show_ipv6_ospf6_area_spf_tree,
850 show_ipv6_ospf6_area_spf_tree_cmd,
851 "show ipv6 ospf6 area A.B.C.D spf tree",
852 SHOW_STR
853 IP6_STR
854 OSPF6_STR
855 OSPF6_AREA_STR
856 OSPF6_AREA_ID_STR
857 "Shortest Path First caculation\n"
858 "Show SPF tree\n")
859 {
860 int idx_ipv4 = 4;
861 u_int32_t area_id;
862 struct ospf6_area *oa;
863 struct ospf6_vertex *root;
864 struct ospf6_route *route;
865 struct prefix prefix;
866
867 OSPF6_CMD_CHECK_RUNNING ();
868
869 ospf6_linkstate_prefix (ospf6->router_id, htonl (0), &prefix);
870
871 if (inet_pton (AF_INET, argv[idx_ipv4]->arg, &area_id) != 1)
872 {
873 vty_out (vty, "Malformed Area-ID: %s%s", argv[idx_ipv4]->arg, VNL);
874 return CMD_SUCCESS;
875 }
876 oa = ospf6_area_lookup (area_id, ospf6);
877 if (oa == NULL)
878 {
879 vty_out (vty, "No such Area: %s%s", argv[idx_ipv4]->arg, VNL);
880 return CMD_SUCCESS;
881 }
882
883 route = ospf6_route_lookup (&prefix, oa->spf_table);
884 if (route == NULL)
885 {
886 vty_out (vty, "LS entry for root not found in area %s%s",
887 oa->name, VNL);
888 return CMD_SUCCESS;
889 }
890 root = (struct ospf6_vertex *) route->route_option;
891 ospf6_spf_display_subtree (vty, "", 0, root);
892
893 return CMD_SUCCESS;
894 }
895
896 DEFUN (show_ipv6_ospf6_simulate_spf_tree_root,
897 show_ipv6_ospf6_simulate_spf_tree_root_cmd,
898 "show ipv6 ospf6 simulate spf-tree A.B.C.D area A.B.C.D",
899 SHOW_STR
900 IP6_STR
901 OSPF6_STR
902 "Shortest Path First calculation\n"
903 "Show SPF tree\n"
904 "Specify root's router-id to calculate another router's SPF tree\n"
905 "OSPF6 area parameters\n"
906 OSPF6_AREA_ID_STR)
907 {
908 int idx_ipv4 = 5;
909 int idx_ipv4_2 = 7;
910 u_int32_t area_id;
911 struct ospf6_area *oa;
912 struct ospf6_vertex *root;
913 struct ospf6_route *route;
914 struct prefix prefix;
915 u_int32_t router_id;
916 struct ospf6_route_table *spf_table;
917 unsigned char tmp_debug_ospf6_spf = 0;
918
919 OSPF6_CMD_CHECK_RUNNING ();
920
921 inet_pton (AF_INET, argv[idx_ipv4]->arg, &router_id);
922 ospf6_linkstate_prefix (router_id, htonl (0), &prefix);
923
924 if (inet_pton (AF_INET, argv[idx_ipv4_2]->arg, &area_id) != 1)
925 {
926 vty_out (vty, "Malformed Area-ID: %s%s", argv[idx_ipv4_2]->arg, VNL);
927 return CMD_SUCCESS;
928 }
929 oa = ospf6_area_lookup (area_id, ospf6);
930 if (oa == NULL)
931 {
932 vty_out (vty, "No such Area: %s%s", argv[idx_ipv4_2]->arg, VNL);
933 return CMD_SUCCESS;
934 }
935
936 tmp_debug_ospf6_spf = conf_debug_ospf6_spf;
937 conf_debug_ospf6_spf = 0;
938
939 spf_table = OSPF6_ROUTE_TABLE_CREATE (NONE, SPF_RESULTS);
940 ospf6_spf_calculation (router_id, spf_table, oa);
941
942 conf_debug_ospf6_spf = tmp_debug_ospf6_spf;
943
944 route = ospf6_route_lookup (&prefix, spf_table);
945 if (route == NULL)
946 {
947 ospf6_spf_table_finish (spf_table);
948 ospf6_route_table_delete (spf_table);
949 return CMD_SUCCESS;
950 }
951 root = (struct ospf6_vertex *) route->route_option;
952 ospf6_spf_display_subtree (vty, "", 0, root);
953
954 ospf6_spf_table_finish (spf_table);
955 ospf6_route_table_delete (spf_table);
956
957 return CMD_SUCCESS;
958 }
959
960 DEFUN (ospf6_area_stub,
961 ospf6_area_stub_cmd,
962 "area <A.B.C.D|(0-4294967295)> stub",
963 "OSPF6 area parameters\n"
964 "OSPF6 area ID in IP address format\n"
965 "OSPF6 area ID as a decimal value\n"
966 "Configure OSPF6 area as stub\n")
967 {
968 int idx_ipv4_number = 1;
969 struct ospf6_area *area;
970
971 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
972
973 if (!ospf6_area_stub_set (ospf6, area))
974 {
975 vty_out (vty, "First deconfigure all virtual link through this area%s",
976 VTY_NEWLINE);
977 return CMD_WARNING;
978 }
979
980 ospf6_area_no_summary_unset (ospf6, area);
981
982 return CMD_SUCCESS;
983 }
984
985 DEFUN (ospf6_area_stub_no_summary,
986 ospf6_area_stub_no_summary_cmd,
987 "area <A.B.C.D|(0-4294967295)> stub no-summary",
988 "OSPF6 stub parameters\n"
989 "OSPF6 area ID in IP address format\n"
990 "OSPF6 area ID as a decimal value\n"
991 "Configure OSPF6 area as stub\n"
992 "Do not inject inter-area routes into stub\n")
993 {
994 int idx_ipv4_number = 1;
995 struct ospf6_area *area;
996
997 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
998
999 if (!ospf6_area_stub_set (ospf6, area))
1000 {
1001 vty_out (vty, "First deconfigure all virtual link through this area%s",
1002 VTY_NEWLINE);
1003 return CMD_WARNING;
1004 }
1005
1006 ospf6_area_no_summary_set (ospf6, area);
1007
1008 return CMD_SUCCESS;
1009 }
1010
1011 DEFUN (no_ospf6_area_stub,
1012 no_ospf6_area_stub_cmd,
1013 "no area <A.B.C.D|(0-4294967295)> stub",
1014 NO_STR
1015 "OSPF6 area parameters\n"
1016 "OSPF6 area ID in IP address format\n"
1017 "OSPF6 area ID as a decimal value\n"
1018 "Configure OSPF6 area as stub\n")
1019 {
1020 int idx_ipv4_number = 2;
1021 struct ospf6_area *area;
1022
1023 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
1024
1025 ospf6_area_stub_unset (ospf6, area);
1026 ospf6_area_no_summary_unset (ospf6, area);
1027
1028 return CMD_SUCCESS;
1029 }
1030
1031 DEFUN (no_ospf6_area_stub_no_summary,
1032 no_ospf6_area_stub_no_summary_cmd,
1033 "no area <A.B.C.D|(0-4294967295)> stub no-summary",
1034 NO_STR
1035 "OSPF6 area parameters\n"
1036 "OSPF6 area ID in IP address format\n"
1037 "OSPF6 area ID as a decimal value\n"
1038 "Configure OSPF6 area as stub\n"
1039 "Do not inject inter-area routes into area\n")
1040 {
1041 int idx_ipv4_number = 2;
1042 struct ospf6_area *area;
1043
1044 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
1045
1046 ospf6_area_stub_unset (ospf6, area);
1047 ospf6_area_no_summary_unset (ospf6, area);
1048
1049 return CMD_SUCCESS;
1050 }
1051
1052 void
1053 ospf6_area_init (void)
1054 {
1055 install_element (VIEW_NODE, &show_ipv6_ospf6_spf_tree_cmd);
1056 install_element (VIEW_NODE, &show_ipv6_ospf6_area_spf_tree_cmd);
1057 install_element (VIEW_NODE, &show_ipv6_ospf6_simulate_spf_tree_root_cmd);
1058
1059 install_element (OSPF6_NODE, &area_range_cmd);
1060 install_element (OSPF6_NODE, &no_area_range_cmd);
1061 install_element (OSPF6_NODE, &ospf6_area_stub_no_summary_cmd);
1062 install_element (OSPF6_NODE, &ospf6_area_stub_cmd);
1063 install_element (OSPF6_NODE, &no_ospf6_area_stub_no_summary_cmd);
1064 install_element (OSPF6_NODE, &no_ospf6_area_stub_cmd);
1065
1066
1067 install_element (OSPF6_NODE, &area_import_list_cmd);
1068 install_element (OSPF6_NODE, &no_area_import_list_cmd);
1069 install_element (OSPF6_NODE, &area_export_list_cmd);
1070 install_element (OSPF6_NODE, &no_area_export_list_cmd);
1071
1072 install_element (OSPF6_NODE, &area_filter_list_cmd);
1073 install_element (OSPF6_NODE, &no_area_filter_list_cmd);
1074
1075 }
1076
1077