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