]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_area.c
doc: Add `show ipv6 rpf X:X::X:X` command to docs
[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_message.h"
43 #include "ospf6_neighbor.h"
44 #include "ospf6_interface.h"
45 #include "ospf6_intra.h"
46 #include "ospf6_abr.h"
47 #include "ospf6_asbr.h"
48 #include "ospf6_zebra.h"
49 #include "ospf6d.h"
50 #include "lib/json.h"
51 #include "ospf6_nssa.h"
52 #include "ospf6d/ospf6_area_clippy.c"
53
54 DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_AREA, "OSPF6 area");
55 DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_PLISTNAME, "Prefix list name");
56
57 int str2area_id(const char *str, uint32_t *area_id, int *area_id_fmt)
58 {
59 char *ep;
60
61 *area_id = htonl(strtoul(str, &ep, 10));
62 if (*ep && inet_pton(AF_INET, str, area_id) != 1)
63 return -1;
64
65 *area_id_fmt =
66 !*ep ? OSPF6_AREA_FMT_DECIMAL : OSPF6_AREA_FMT_DOTTEDQUAD;
67
68 return 0;
69 }
70
71 void area_id2str(char *buf, int len, uint32_t area_id, int area_id_fmt)
72 {
73 if (area_id_fmt == OSPF6_AREA_FMT_DECIMAL)
74 snprintf(buf, len, "%u", ntohl(area_id));
75 else
76 inet_ntop(AF_INET, &area_id, buf, len);
77 }
78
79 int ospf6_area_cmp(void *va, void *vb)
80 {
81 struct ospf6_area *oa = (struct ospf6_area *)va;
82 struct ospf6_area *ob = (struct ospf6_area *)vb;
83 return (ntohl(oa->area_id) < ntohl(ob->area_id) ? -1 : 1);
84 }
85
86 /* schedule routing table recalculation */
87 static void ospf6_area_lsdb_hook_add(struct ospf6_lsa *lsa)
88 {
89 switch (ntohs(lsa->header->type)) {
90
91 case OSPF6_LSTYPE_ROUTER:
92 case OSPF6_LSTYPE_NETWORK:
93 if (IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa->header->type)) {
94 zlog_debug("%s Examin LSA %s", __func__, lsa->name);
95 zlog_debug(" Schedule SPF Calculation for %s",
96 OSPF6_AREA(lsa->lsdb->data)->name);
97 }
98 ospf6_spf_schedule(
99 OSPF6_PROCESS(OSPF6_AREA(lsa->lsdb->data)->ospf6),
100 ospf6_lsadd_to_spf_reason(lsa));
101 break;
102
103 case OSPF6_LSTYPE_INTRA_PREFIX:
104 ospf6_intra_prefix_lsa_add(lsa);
105 break;
106
107 case OSPF6_LSTYPE_INTER_PREFIX:
108 case OSPF6_LSTYPE_INTER_ROUTER:
109 ospf6_abr_examin_summary(lsa,
110 (struct ospf6_area *)lsa->lsdb->data);
111 break;
112
113 case OSPF6_LSTYPE_TYPE_7:
114 ospf6_asbr_lsa_add(lsa);
115 break;
116
117 default:
118 break;
119 }
120 }
121
122 static void ospf6_area_lsdb_hook_remove(struct ospf6_lsa *lsa)
123 {
124 switch (ntohs(lsa->header->type)) {
125 case OSPF6_LSTYPE_ROUTER:
126 case OSPF6_LSTYPE_NETWORK:
127 if (IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa->header->type)) {
128 zlog_debug("LSA disappearing: %s", lsa->name);
129 zlog_debug("Schedule SPF Calculation for %s",
130 OSPF6_AREA(lsa->lsdb->data)->name);
131 }
132 ospf6_spf_schedule(
133 OSPF6_PROCESS(OSPF6_AREA(lsa->lsdb->data)->ospf6),
134 ospf6_lsremove_to_spf_reason(lsa));
135 break;
136
137 case OSPF6_LSTYPE_INTRA_PREFIX:
138 ospf6_intra_prefix_lsa_remove(lsa);
139 break;
140
141 case OSPF6_LSTYPE_INTER_PREFIX:
142 case OSPF6_LSTYPE_INTER_ROUTER:
143 ospf6_abr_examin_summary(lsa,
144 (struct ospf6_area *)lsa->lsdb->data);
145 break;
146 case OSPF6_LSTYPE_TYPE_7:
147 ospf6_asbr_lsa_remove(lsa, NULL);
148 break;
149 default:
150 break;
151 }
152 }
153
154 static void ospf6_area_route_hook_add(struct ospf6_route *route)
155 {
156 struct ospf6_area *oa = route->table->scope;
157 struct ospf6 *ospf6 = oa->ospf6;
158 struct ospf6_route *copy;
159
160 copy = ospf6_route_copy(route);
161 ospf6_route_add(copy, ospf6->route_table);
162 }
163
164 static void ospf6_area_route_hook_remove(struct ospf6_route *route)
165 {
166 struct ospf6_area *oa = route->table->scope;
167 struct ospf6 *ospf6 = oa->ospf6;
168 struct ospf6_route *copy;
169
170 copy = ospf6_route_lookup_identical(route, ospf6->route_table);
171 if (copy)
172 ospf6_route_remove(copy, ospf6->route_table);
173 }
174
175 static void ospf6_area_stub_update(struct ospf6_area *area)
176 {
177
178 if (IS_AREA_STUB(area)) {
179 if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER))
180 zlog_debug("Stubbing out area for area %s", area->name);
181 OSPF6_OPT_CLEAR(area->options, OSPF6_OPT_E);
182 ospf6_asbr_remove_externals_from_area(area);
183 } else if (IS_AREA_ENABLED(area)) {
184 if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER))
185 zlog_debug("Normal area for area %s", area->name);
186 OSPF6_OPT_SET(area->options, OSPF6_OPT_E);
187 ospf6_asbr_send_externals_to_area(area);
188 }
189
190 OSPF6_ROUTER_LSA_SCHEDULE(area);
191 }
192
193 static int ospf6_area_stub_set(struct ospf6 *ospf6, struct ospf6_area *area)
194 {
195 if (!IS_AREA_STUB(area)) {
196 /* Disable NSSA first. */
197 ospf6_area_nssa_unset(ospf6, area);
198
199 SET_FLAG(area->flag, OSPF6_AREA_STUB);
200 ospf6_area_stub_update(area);
201 }
202
203 return 1;
204 }
205
206 void ospf6_area_stub_unset(struct ospf6 *ospf6, struct ospf6_area *area)
207 {
208 if (IS_AREA_STUB(area)) {
209 UNSET_FLAG(area->flag, OSPF6_AREA_STUB);
210 ospf6_area_stub_update(area);
211 }
212 }
213
214 static void ospf6_area_no_summary_set(struct ospf6 *ospf6,
215 struct ospf6_area *area)
216 {
217 if (area) {
218 if (!area->no_summary) {
219 area->no_summary = 1;
220 ospf6_abr_range_reset_cost(ospf6);
221 ospf6_abr_prefix_resummarize(ospf6);
222 }
223 }
224 }
225
226 static void ospf6_area_no_summary_unset(struct ospf6 *ospf6,
227 struct ospf6_area *area)
228 {
229 if (area) {
230 if (area->no_summary) {
231 area->no_summary = 0;
232 ospf6_abr_range_reset_cost(ospf6);
233 ospf6_abr_prefix_resummarize(ospf6);
234 }
235 }
236 }
237
238 static void ospf6_nssa_default_originate_set(struct ospf6 *ospf6,
239 struct ospf6_area *area,
240 int metric, int metric_type)
241 {
242 if (!area->nssa_default_originate.enabled) {
243 area->nssa_default_originate.enabled = true;
244 if (++ospf6->nssa_default_import_check.refcnt == 1) {
245 ospf6->nssa_default_import_check.status = false;
246 ospf6_zebra_import_default_route(ospf6, false);
247 }
248 }
249
250 area->nssa_default_originate.metric_value = metric;
251 area->nssa_default_originate.metric_type = metric_type;
252 }
253
254 static void ospf6_nssa_default_originate_unset(struct ospf6 *ospf6,
255 struct ospf6_area *area)
256 {
257 if (area->nssa_default_originate.enabled) {
258 area->nssa_default_originate.enabled = false;
259 if (--ospf6->nssa_default_import_check.refcnt == 0) {
260 ospf6->nssa_default_import_check.status = false;
261 ospf6_zebra_import_default_route(ospf6, true);
262 }
263 area->nssa_default_originate.metric_value = -1;
264 area->nssa_default_originate.metric_type = -1;
265 }
266 }
267
268 /**
269 * Make new area structure.
270 *
271 * @param area_id - ospf6 area ID
272 * @param o - ospf6 instance
273 * @param df - display format for area ID
274 */
275 struct ospf6_area *ospf6_area_create(uint32_t area_id, struct ospf6 *o, int df)
276 {
277 struct ospf6_area *oa;
278
279 oa = XCALLOC(MTYPE_OSPF6_AREA, sizeof(struct ospf6_area));
280
281 switch (df) {
282 case OSPF6_AREA_FMT_DECIMAL:
283 snprintf(oa->name, sizeof(oa->name), "%u", ntohl(area_id));
284 break;
285 default:
286 case OSPF6_AREA_FMT_DOTTEDQUAD:
287 inet_ntop(AF_INET, &area_id, oa->name, sizeof(oa->name));
288 break;
289 }
290
291 oa->area_id = area_id;
292 oa->if_list = list_new();
293
294 oa->lsdb = ospf6_lsdb_create(oa);
295 oa->lsdb->hook_add = ospf6_area_lsdb_hook_add;
296 oa->lsdb->hook_remove = ospf6_area_lsdb_hook_remove;
297 oa->lsdb_self = ospf6_lsdb_create(oa);
298 oa->temp_router_lsa_lsdb = ospf6_lsdb_create(oa);
299
300 oa->spf_table = OSPF6_ROUTE_TABLE_CREATE(AREA, SPF_RESULTS);
301 oa->spf_table->scope = oa;
302 oa->route_table = OSPF6_ROUTE_TABLE_CREATE(AREA, ROUTES);
303 oa->route_table->scope = oa;
304 oa->route_table->hook_add = ospf6_area_route_hook_add;
305 oa->route_table->hook_remove = ospf6_area_route_hook_remove;
306
307 oa->range_table = OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES);
308 oa->range_table->scope = oa;
309 oa->nssa_range_table = OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES);
310 oa->nssa_range_table->scope = oa;
311 oa->summary_prefix = OSPF6_ROUTE_TABLE_CREATE(AREA, SUMMARY_PREFIXES);
312 oa->summary_prefix->scope = oa;
313 oa->summary_router = OSPF6_ROUTE_TABLE_CREATE(AREA, SUMMARY_ROUTERS);
314 oa->summary_router->scope = oa;
315 oa->router_lsa_size_limit = 1024 + 256;
316
317 /* set default options */
318 if (CHECK_FLAG(o->flag, OSPF6_STUB_ROUTER)) {
319 OSPF6_OPT_CLEAR(oa->options, OSPF6_OPT_V6);
320 OSPF6_OPT_CLEAR(oa->options, OSPF6_OPT_R);
321 } else {
322 OSPF6_OPT_SET(oa->options, OSPF6_OPT_V6);
323 OSPF6_OPT_SET(oa->options, OSPF6_OPT_R);
324 }
325
326 OSPF6_OPT_SET(oa->options, OSPF6_OPT_E);
327
328 SET_FLAG(oa->flag, OSPF6_AREA_ACTIVE);
329 SET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
330
331 oa->ospf6 = o;
332 listnode_add_sort(o->area_list, oa);
333
334 if (area_id == OSPF_AREA_BACKBONE) {
335 o->backbone = oa;
336 }
337
338 return oa;
339 }
340
341 void ospf6_area_delete(struct ospf6_area *oa)
342 {
343 struct listnode *n;
344 struct ospf6_interface *oi;
345
346 /* The ospf6_interface structs store configuration
347 * information which should not be lost/reset when
348 * deleting an area.
349 * So just detach the interface from the area and
350 * keep it around. */
351 for (ALL_LIST_ELEMENTS_RO(oa->if_list, n, oi)) {
352 oi->area = NULL;
353
354 struct listnode *node;
355 struct listnode *nnode;
356 struct ospf6_neighbor *on;
357
358 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on))
359 ospf6_neighbor_delete(on);
360 }
361
362 list_delete(&oa->if_list);
363
364 ospf6_lsdb_delete(oa->lsdb);
365 ospf6_lsdb_delete(oa->lsdb_self);
366 ospf6_lsdb_delete(oa->temp_router_lsa_lsdb);
367
368 ospf6_spf_table_finish(oa->spf_table);
369 ospf6_route_table_delete(oa->spf_table);
370 ospf6_route_table_delete(oa->route_table);
371
372 ospf6_route_table_delete(oa->range_table);
373 ospf6_route_table_delete(oa->nssa_range_table);
374 ospf6_route_table_delete(oa->summary_prefix);
375 ospf6_route_table_delete(oa->summary_router);
376
377 listnode_delete(oa->ospf6->area_list, oa);
378 oa->ospf6 = NULL;
379
380 /* free area */
381 XFREE(MTYPE_OSPF6_AREA, oa);
382 }
383
384 struct ospf6_area *ospf6_area_lookup_by_area_id(uint32_t area_id)
385 {
386 struct ospf6_area *oa;
387 struct listnode *n, *node, *nnode;
388 struct ospf6 *ospf6;
389
390 for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6)) {
391 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa))
392 if (oa->area_id == area_id)
393 return oa;
394 }
395 return (struct ospf6_area *)NULL;
396 }
397
398 struct ospf6_area *ospf6_area_lookup(uint32_t area_id, struct ospf6 *ospf6)
399 {
400 struct ospf6_area *oa;
401 struct listnode *n;
402
403 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa))
404 if (oa->area_id == area_id)
405 return oa;
406
407 return (struct ospf6_area *)NULL;
408 }
409
410 void ospf6_area_enable(struct ospf6_area *oa)
411 {
412 struct listnode *node, *nnode;
413 struct ospf6_interface *oi;
414
415 SET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
416
417 for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi))
418 ospf6_interface_enable(oi);
419 ospf6_abr_enable_area(oa);
420 }
421
422 void ospf6_area_disable(struct ospf6_area *oa)
423 {
424 struct listnode *node, *nnode;
425 struct ospf6_interface *oi;
426
427 UNSET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
428
429 for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi))
430 ospf6_interface_disable(oi);
431
432 ospf6_abr_disable_area(oa);
433 ospf6_lsdb_remove_all(oa->lsdb);
434 ospf6_lsdb_remove_all(oa->lsdb_self);
435
436 ospf6_spf_table_finish(oa->spf_table);
437 ospf6_route_remove_all(oa->route_table);
438
439 THREAD_OFF(oa->thread_router_lsa);
440 THREAD_OFF(oa->thread_intra_prefix_lsa);
441 }
442
443
444 void ospf6_area_show(struct vty *vty, struct ospf6_area *oa,
445 json_object *json_areas, bool use_json)
446 {
447 struct listnode *i;
448 struct ospf6_interface *oi;
449 unsigned long result;
450 json_object *json_area;
451 json_object *array_interfaces;
452
453 if (use_json) {
454 json_area = json_object_new_object();
455 json_object_boolean_add(json_area, "areaIsStub",
456 IS_AREA_STUB(oa));
457 json_object_boolean_add(json_area, "areaIsNSSA",
458 IS_AREA_NSSA(oa));
459 if (IS_AREA_STUB(oa) || IS_AREA_NSSA(oa)) {
460 json_object_boolean_add(json_area, "areaNoSummary",
461 oa->no_summary);
462 }
463
464 json_object_int_add(json_area, "numberOfAreaScopedLsa",
465 oa->lsdb->count);
466 json_object_object_add(
467 json_area, "lsaStatistics",
468 JSON_OBJECT_NEW_ARRAY(json_object_new_int,
469 oa->lsdb->stats,
470 OSPF6_LSTYPE_SIZE));
471
472 /* Interfaces Attached */
473 array_interfaces = json_object_new_array();
474 for (ALL_LIST_ELEMENTS_RO(oa->if_list, i, oi))
475 json_object_array_add(
476 array_interfaces,
477 json_object_new_string(oi->interface->name));
478
479 json_object_object_add(json_area, "interfacesAttachedToArea",
480 array_interfaces);
481
482 if (oa->ts_spf.tv_sec || oa->ts_spf.tv_usec) {
483 json_object_boolean_true_add(json_area, "spfHasRun");
484 result = monotime_since(&oa->ts_spf, NULL);
485 if (result / TIMER_SECOND_MICRO > 0) {
486 json_object_int_add(
487 json_area, "spfLastExecutedSecs",
488 result / TIMER_SECOND_MICRO);
489
490 json_object_int_add(
491 json_area, "spfLastExecutedMicroSecs",
492 result % TIMER_SECOND_MICRO);
493 } else {
494 json_object_int_add(json_area,
495 "spfLastExecutedSecs", 0);
496 json_object_int_add(json_area,
497 "spfLastExecutedMicroSecs",
498 result);
499 }
500 } else
501 json_object_boolean_false_add(json_area, "spfHasRun");
502
503
504 json_object_object_add(json_areas, oa->name, json_area);
505
506 } else {
507
508 if (!IS_AREA_STUB(oa) && !IS_AREA_NSSA(oa))
509 vty_out(vty, " Area %s\n", oa->name);
510 else {
511 if (oa->no_summary) {
512 vty_out(vty, " Area %s[%s, No Summary]\n",
513 oa->name,
514 IS_AREA_STUB(oa) ? "Stub" : "NSSA");
515 } else {
516 vty_out(vty, " Area %s[%s]\n", oa->name,
517 IS_AREA_STUB(oa) ? "Stub" : "NSSA");
518 }
519 }
520 vty_out(vty, " Number of Area scoped LSAs is %u\n",
521 oa->lsdb->count);
522
523 vty_out(vty, " Interface attached to this area:");
524 for (ALL_LIST_ELEMENTS_RO(oa->if_list, i, oi))
525 vty_out(vty, " %s", oi->interface->name);
526 vty_out(vty, "\n");
527
528 if (oa->ts_spf.tv_sec || oa->ts_spf.tv_usec) {
529 result = monotime_since(&oa->ts_spf, NULL);
530 if (result / TIMER_SECOND_MICRO > 0) {
531 vty_out(vty,
532 " SPF last executed %ld.%lds ago\n",
533 result / TIMER_SECOND_MICRO,
534 result % TIMER_SECOND_MICRO);
535 } else {
536 vty_out(vty,
537 " SPF last executed %ldus ago\n",
538 result);
539 }
540 } else
541 vty_out(vty, "SPF has not been run\n");
542 }
543 }
544
545 DEFUN (area_range,
546 area_range_cmd,
547 "area <A.B.C.D|(0-4294967295)> range X:X::X:X/M [<advertise|not-advertise|cost (0-16777215)>]",
548 "OSPF6 area parameters\n"
549 "OSPF6 area ID in IP address format\n"
550 "OSPF6 area ID as a decimal value\n"
551 "Configured address range\n"
552 "Specify IPv6 prefix\n"
553 "Advertise\n"
554 "Do not advertise\n"
555 "User specified metric for this range\n"
556 "Advertised metric for this range\n")
557 {
558 int idx_ipv4 = 1;
559 int idx_ipv6_prefixlen = 3;
560 int idx_type = 4;
561 int ret;
562 struct ospf6_area *oa;
563 struct prefix prefix;
564 struct ospf6_route *range;
565 uint32_t cost;
566
567 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
568
569 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, oa, ospf6);
570
571 ret = str2prefix(argv[idx_ipv6_prefixlen]->arg, &prefix);
572 if (ret != 1 || prefix.family != AF_INET6) {
573 vty_out(vty, "Malformed argument: %s\n",
574 argv[idx_ipv6_prefixlen]->arg);
575 return CMD_SUCCESS;
576 }
577
578 range = ospf6_route_lookup(&prefix, oa->range_table);
579 if (range == NULL) {
580 range = ospf6_route_create(ospf6);
581 range->type = OSPF6_DEST_TYPE_RANGE;
582 range->prefix = prefix;
583 range->path.area_id = oa->area_id;
584 range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC;
585 }
586
587 /* default settings */
588 cost = OSPF_AREA_RANGE_COST_UNSPEC;
589 UNSET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
590
591 if (argc > idx_type) {
592 if (strmatch(argv[idx_type]->text, "not-advertise"))
593 SET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
594 else if (strmatch(argv[idx_type]->text, "cost"))
595 cost = strtoul(argv[5]->arg, NULL, 10);
596 }
597
598 range->path.u.cost_config = cost;
599
600 if (range->rnode == NULL) {
601 ospf6_route_add(range, oa->range_table);
602 }
603
604 if (ospf6_check_and_set_router_abr(ospf6)) {
605 /* Redo summaries if required */
606 ospf6_abr_prefix_resummarize(ospf6);
607 }
608
609 return CMD_SUCCESS;
610 }
611
612 DEFUN (no_area_range,
613 no_area_range_cmd,
614 "no area <A.B.C.D|(0-4294967295)> range X:X::X:X/M [<advertise|not-advertise|cost (0-16777215)>]",
615 NO_STR
616 "OSPF6 area parameters\n"
617 "OSPF6 area ID in IP address format\n"
618 "OSPF6 area ID as a decimal value\n"
619 "Configured address range\n"
620 "Specify IPv6 prefix\n"
621 "Advertise\n"
622 "Do not advertise\n"
623 "User specified metric for this range\n"
624 "Advertised metric for this range\n")
625 {
626 int idx_ipv4 = 2;
627 int idx_ipv6 = 4;
628 int ret;
629 struct ospf6_area *oa;
630 struct prefix prefix;
631 struct ospf6_route *range, *route;
632
633 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
634
635 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, oa, ospf6);
636
637 ret = str2prefix(argv[idx_ipv6]->arg, &prefix);
638 if (ret != 1 || prefix.family != AF_INET6) {
639 vty_out(vty, "Malformed argument: %s\n", argv[idx_ipv6]->arg);
640 return CMD_SUCCESS;
641 }
642
643 range = ospf6_route_lookup(&prefix, oa->range_table);
644 if (range == NULL) {
645 vty_out(vty, "Range %s does not exists.\n",
646 argv[idx_ipv6]->arg);
647 return CMD_SUCCESS;
648 }
649
650 if (ospf6_check_and_set_router_abr(oa->ospf6)) {
651 /* Blow away the aggregated LSA and route */
652 SET_FLAG(range->flag, OSPF6_ROUTE_REMOVE);
653
654 /* Redo summaries if required */
655 for (route = ospf6_route_head(oa->ospf6->route_table); route;
656 route = ospf6_route_next(route))
657 ospf6_abr_originate_summary(route, oa->ospf6);
658
659 /* purge the old aggregated summary LSA */
660 ospf6_abr_originate_summary(range, oa->ospf6);
661 }
662 ospf6_route_remove(range, oa->range_table);
663
664 return CMD_SUCCESS;
665 }
666
667 void ospf6_area_config_write(struct vty *vty, struct ospf6 *ospf6)
668 {
669 struct listnode *node;
670 struct ospf6_area *oa;
671 struct ospf6_route *range;
672
673 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
674 for (range = ospf6_route_head(oa->range_table); range;
675 range = ospf6_route_next(range)) {
676 vty_out(vty, " area %s range %pFX", oa->name,
677 &range->prefix);
678
679 if (CHECK_FLAG(range->flag,
680 OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
681 vty_out(vty, " not-advertise");
682 } else {
683 // "advertise" is the default so we do not
684 // display it
685 if (range->path.u.cost_config
686 != OSPF_AREA_RANGE_COST_UNSPEC)
687 vty_out(vty, " cost %d",
688 range->path.u.cost_config);
689 }
690 vty_out(vty, "\n");
691 }
692 if (IS_AREA_STUB(oa)) {
693 if (oa->no_summary)
694 vty_out(vty, " area %s stub no-summary\n",
695 oa->name);
696 else
697 vty_out(vty, " area %s stub\n", oa->name);
698 }
699 if (IS_AREA_NSSA(oa)) {
700 vty_out(vty, " area %s nssa", oa->name);
701 if (oa->nssa_default_originate.enabled) {
702 vty_out(vty, " default-information-originate");
703 if (oa->nssa_default_originate.metric_value
704 != -1)
705 vty_out(vty, " metric %d",
706 oa->nssa_default_originate
707 .metric_value);
708 if (oa->nssa_default_originate.metric_type
709 != DEFAULT_METRIC_TYPE)
710 vty_out(vty, " metric-type 1");
711 }
712 if (oa->no_summary)
713 vty_out(vty, " no-summary");
714 vty_out(vty, "\n");
715 }
716 for (range = ospf6_route_head(oa->nssa_range_table); range;
717 range = ospf6_route_next(range)) {
718 vty_out(vty, " area %s nssa range %pFX", oa->name,
719 &range->prefix);
720
721 if (CHECK_FLAG(range->flag,
722 OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
723 vty_out(vty, " not-advertise");
724 } else {
725 if (range->path.u.cost_config
726 != OSPF_AREA_RANGE_COST_UNSPEC)
727 vty_out(vty, " cost %u",
728 range->path.u.cost_config);
729 }
730 vty_out(vty, "\n");
731 }
732 if (PREFIX_NAME_IN(oa))
733 vty_out(vty, " area %s filter-list prefix %s in\n",
734 oa->name, PREFIX_NAME_IN(oa));
735 if (PREFIX_NAME_OUT(oa))
736 vty_out(vty, " area %s filter-list prefix %s out\n",
737 oa->name, PREFIX_NAME_OUT(oa));
738 if (IMPORT_NAME(oa))
739 vty_out(vty, " area %s import-list %s\n", oa->name,
740 IMPORT_NAME(oa));
741 if (EXPORT_NAME(oa))
742 vty_out(vty, " area %s export-list %s\n", oa->name,
743 EXPORT_NAME(oa));
744 }
745 }
746
747 DEFUN (area_filter_list,
748 area_filter_list_cmd,
749 "area <A.B.C.D|(0-4294967295)> filter-list prefix PREFIXLIST_NAME <in|out>",
750 "OSPF6 area parameters\n"
751 "OSPF6 area ID in IP address format\n"
752 "OSPF6 area ID as a decimal value\n"
753 "Filter networks between OSPF6 areas\n"
754 "Filter prefixes between OSPF6 areas\n"
755 "Name of an IPv6 prefix-list\n"
756 "Filter networks sent to this area\n"
757 "Filter networks sent from this area\n")
758 {
759 char *inout = argv[argc - 1]->text;
760 char *areaid = argv[1]->arg;
761 char *plistname = argv[4]->arg;
762
763 struct ospf6_area *area;
764 struct prefix_list *plist;
765
766 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
767
768 OSPF6_CMD_AREA_GET(areaid, area, ospf6);
769
770 plist = prefix_list_lookup(AFI_IP6, plistname);
771 if (strmatch(inout, "in")) {
772 PREFIX_LIST_IN(area) = plist;
773 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
774 PREFIX_NAME_IN(area) =
775 XSTRDUP(MTYPE_OSPF6_PLISTNAME, plistname);
776 } else {
777 PREFIX_LIST_OUT(area) = plist;
778 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
779 PREFIX_NAME_OUT(area) =
780 XSTRDUP(MTYPE_OSPF6_PLISTNAME, plistname);
781 }
782
783 /* Redo summaries if required */
784 if (ospf6_check_and_set_router_abr(area->ospf6))
785 ospf6_schedule_abr_task(ospf6);
786
787 return CMD_SUCCESS;
788 }
789
790 DEFUN (no_area_filter_list,
791 no_area_filter_list_cmd,
792 "no area <A.B.C.D|(0-4294967295)> filter-list prefix PREFIXLIST_NAME <in|out>",
793 NO_STR
794 "OSPF6 area parameters\n"
795 "OSPF6 area ID in IP address format\n"
796 "OSPF6 area ID as a decimal value\n"
797 "Filter networks between OSPF6 areas\n"
798 "Filter prefixes between OSPF6 areas\n"
799 "Name of an IPv6 prefix-list\n"
800 "Filter networks sent to this area\n"
801 "Filter networks sent from this area\n")
802 {
803 char *inout = argv[argc - 1]->text;
804 char *areaid = argv[2]->arg;
805 char *plistname = argv[5]->arg;
806
807 struct ospf6_area *area;
808
809 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
810 OSPF6_CMD_AREA_GET(areaid, area, ospf6);
811
812 if (strmatch(inout, "in")) {
813 if (PREFIX_NAME_IN(area))
814 if (!strmatch(PREFIX_NAME_IN(area), plistname))
815 return CMD_SUCCESS;
816
817 PREFIX_LIST_IN(area) = NULL;
818 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
819 } else {
820 if (PREFIX_NAME_OUT(area))
821 if (!strmatch(PREFIX_NAME_OUT(area), plistname))
822 return CMD_SUCCESS;
823
824 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
825 PREFIX_LIST_OUT(area) = NULL;
826 }
827
828 /* Redo summaries if required */
829 if (ospf6_check_and_set_router_abr(area->ospf6))
830 ospf6_schedule_abr_task(ospf6);
831
832 return CMD_SUCCESS;
833 }
834
835 void ospf6_filter_update(struct access_list *access)
836 {
837 struct ospf6_area *oa;
838 struct listnode *n, *node, *nnode;
839 struct ospf6 *ospf6;
840
841 for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6)) {
842 bool update = false;
843
844 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa)) {
845 if (IMPORT_NAME(oa)
846 && strcmp(IMPORT_NAME(oa), access->name) == 0) {
847 IMPORT_LIST(oa) = access_list_lookup(
848 AFI_IP6, IMPORT_NAME(oa));
849 update = true;
850 }
851
852 if (EXPORT_NAME(oa)
853 && strcmp(EXPORT_NAME(oa), access->name) == 0) {
854 EXPORT_LIST(oa) = access_list_lookup(
855 AFI_IP6, EXPORT_NAME(oa));
856 update = true;
857 }
858 }
859
860 if (update && ospf6_check_and_set_router_abr(ospf6))
861 ospf6_schedule_abr_task(ospf6);
862 }
863 }
864
865 void ospf6_plist_update(struct prefix_list *plist)
866 {
867 struct listnode *node, *nnode;
868 struct ospf6_area *oa;
869 struct listnode *n;
870 const char *name = prefix_list_name(plist);
871 struct ospf6 *ospf6 = NULL;
872
873 if (prefix_list_afi(plist) != AFI_IP6)
874 return;
875
876 for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6)) {
877 bool update = false;
878
879 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa)) {
880 if (PREFIX_NAME_IN(oa)
881 && !strcmp(PREFIX_NAME_IN(oa), name)) {
882 PREFIX_LIST_IN(oa) = prefix_list_lookup(
883 AFI_IP6, PREFIX_NAME_IN(oa));
884 update = true;
885 }
886 if (PREFIX_NAME_OUT(oa)
887 && !strcmp(PREFIX_NAME_OUT(oa), name)) {
888 PREFIX_LIST_OUT(oa) = prefix_list_lookup(
889 AFI_IP6, PREFIX_NAME_OUT(oa));
890 update = true;
891 }
892 }
893
894 if (update && ospf6_check_and_set_router_abr(ospf6))
895 ospf6_schedule_abr_task(ospf6);
896 }
897 }
898
899 DEFUN (area_import_list,
900 area_import_list_cmd,
901 "area <A.B.C.D|(0-4294967295)> import-list ACCESSLIST6_NAME",
902 "OSPF6 area parameters\n"
903 "OSPF6 area ID in IP address format\n"
904 "OSPF6 area ID as a decimal value\n"
905 "Set the filter for networks from other areas announced to the specified one\n"
906 "Name of the access-list\n")
907 {
908 int idx_ipv4 = 1;
909 int idx_name = 3;
910 struct ospf6_area *area;
911 struct access_list *list;
912
913 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
914
915 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area, ospf6);
916
917 list = access_list_lookup(AFI_IP6, argv[idx_name]->arg);
918
919 IMPORT_LIST(area) = list;
920
921 if (IMPORT_NAME(area))
922 free(IMPORT_NAME(area));
923
924 IMPORT_NAME(area) = strdup(argv[idx_name]->arg);
925 if (ospf6_check_and_set_router_abr(area->ospf6))
926 ospf6_schedule_abr_task(ospf6);
927
928 return CMD_SUCCESS;
929 }
930
931 DEFUN (no_area_import_list,
932 no_area_import_list_cmd,
933 "no area <A.B.C.D|(0-4294967295)> import-list ACCESSLIST6_NAME",
934 NO_STR
935 "OSPF6 area parameters\n"
936 "OSPF6 area ID in IP address format\n"
937 "OSPF6 area ID as a decimal value\n"
938 "Unset the filter for networks announced to other areas\n"
939 "Name of the access-list\n")
940 {
941 int idx_ipv4 = 2;
942 struct ospf6_area *area;
943
944 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
945
946 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area, ospf6);
947
948 IMPORT_LIST(area) = NULL;
949
950 if (IMPORT_NAME(area))
951 free(IMPORT_NAME(area));
952
953 IMPORT_NAME(area) = NULL;
954 if (ospf6_check_and_set_router_abr(area->ospf6))
955 ospf6_schedule_abr_task(ospf6);
956
957 return CMD_SUCCESS;
958 }
959
960 DEFUN (area_export_list,
961 area_export_list_cmd,
962 "area <A.B.C.D|(0-4294967295)> export-list ACCESSLIST6_NAME",
963 "OSPF6 area parameters\n"
964 "OSPF6 area ID in IP address format\n"
965 "OSPF6 area ID as a decimal value\n"
966 "Set the filter for networks announced to other areas\n"
967 "Name of the access-list\n")
968 {
969 int idx_ipv4 = 1;
970 int idx_name = 3;
971 struct ospf6_area *area;
972 struct access_list *list;
973
974 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
975
976 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area, ospf6);
977
978 list = access_list_lookup(AFI_IP6, argv[idx_name]->arg);
979
980 EXPORT_LIST(area) = list;
981
982 if (EXPORT_NAME(area))
983 free(EXPORT_NAME(area));
984
985 EXPORT_NAME(area) = strdup(argv[idx_name]->arg);
986
987 /* Redo summaries if required */
988 if (ospf6_check_and_set_router_abr(area->ospf6))
989 ospf6_schedule_abr_task(ospf6);
990
991 return CMD_SUCCESS;
992 }
993
994 DEFUN (no_area_export_list,
995 no_area_export_list_cmd,
996 "no area <A.B.C.D|(0-4294967295)> export-list ACCESSLIST6_NAME",
997 NO_STR
998 "OSPF6 area parameters\n"
999 "OSPF6 area ID in IP address format\n"
1000 "OSPF6 area ID as a decimal value\n"
1001 "Unset the filter for networks announced to other areas\n"
1002 "Name of the access-list\n")
1003 {
1004 int idx_ipv4 = 2;
1005 struct ospf6_area *area;
1006
1007 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1008
1009 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area, ospf6);
1010
1011 EXPORT_LIST(area) = NULL;
1012
1013 if (EXPORT_NAME(area))
1014 free(EXPORT_NAME(area));
1015
1016 EXPORT_NAME(area) = NULL;
1017 if (ospf6_check_and_set_router_abr(area->ospf6))
1018 ospf6_schedule_abr_task(ospf6);
1019
1020 return CMD_SUCCESS;
1021 }
1022
1023 static int ipv6_ospf6_spf_tree_common(struct vty *vty, struct ospf6 *ospf6,
1024 bool uj)
1025 {
1026 struct listnode *node;
1027 struct ospf6_area *oa;
1028 struct prefix prefix;
1029 struct ospf6_vertex *root;
1030 struct ospf6_route *route;
1031 json_object *json = NULL;
1032 json_object *json_area = NULL;
1033 json_object *json_head = NULL;
1034
1035 if (uj)
1036 json = json_object_new_object();
1037 ospf6_linkstate_prefix(ospf6->router_id, htonl(0), &prefix);
1038 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
1039 if (uj) {
1040 json_area = json_object_new_object();
1041 json_head = json_object_new_object();
1042 }
1043 route = ospf6_route_lookup(&prefix, oa->spf_table);
1044 if (route == NULL) {
1045 if (uj) {
1046 json_object_string_add(
1047 json, oa->name,
1048 "LS entry for not not found");
1049 json_object_free(json_head);
1050 json_object_free(json_area);
1051 } else
1052 vty_out(vty,
1053 "LS entry for root not found in area %s\n",
1054 oa->name);
1055 continue;
1056 }
1057 root = (struct ospf6_vertex *)route->route_option;
1058 ospf6_spf_display_subtree(vty, "", 0, root, json_head, uj);
1059
1060 if (uj) {
1061 json_object_object_add(json_area, root->name,
1062 json_head);
1063 json_object_object_add(json, oa->name, json_area);
1064 }
1065 }
1066
1067 if (uj)
1068 vty_json(vty, json);
1069
1070 return CMD_SUCCESS;
1071 }
1072
1073 DEFUN(show_ipv6_ospf6_spf_tree, show_ipv6_ospf6_spf_tree_cmd,
1074 "show ipv6 ospf6 [vrf <NAME|all>] spf tree [json]",
1075 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1076 "All VRFs\n"
1077 "Shortest Path First calculation\n"
1078 "Show SPF tree\n" JSON_STR)
1079 {
1080 struct listnode *node;
1081 struct ospf6 *ospf6;
1082 const char *vrf_name = NULL;
1083 bool all_vrf = false;
1084 int idx_vrf = 0;
1085 bool uj = use_json(argc, argv);
1086
1087 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1088
1089 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1090 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1091 ipv6_ospf6_spf_tree_common(vty, ospf6, uj);
1092 if (!all_vrf)
1093 break;
1094 }
1095 }
1096
1097 OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
1098
1099 return CMD_SUCCESS;
1100 }
1101
1102 static int show_ospf6_area_spf_tree_common(struct vty *vty,
1103 struct cmd_token **argv,
1104 struct ospf6 *ospf6,
1105 uint32_t area_id, int idx_ipv4)
1106 {
1107
1108 struct ospf6_area *oa;
1109 struct prefix prefix;
1110 struct ospf6_vertex *root;
1111 struct ospf6_route *route;
1112
1113 ospf6_linkstate_prefix(ospf6->router_id, htonl(0), &prefix);
1114
1115 oa = ospf6_area_lookup(area_id, ospf6);
1116 if (oa == NULL) {
1117 vty_out(vty, "No such Area: %s\n", argv[idx_ipv4]->arg);
1118 return CMD_SUCCESS;
1119 }
1120
1121 route = ospf6_route_lookup(&prefix, oa->spf_table);
1122 if (route == NULL) {
1123 vty_out(vty, "LS entry for root not found in area %s\n",
1124 oa->name);
1125 return CMD_SUCCESS;
1126 }
1127 root = (struct ospf6_vertex *)route->route_option;
1128 ospf6_spf_display_subtree(vty, "", 0, root, NULL, false);
1129
1130 return CMD_SUCCESS;
1131 }
1132
1133 DEFUN(show_ipv6_ospf6_area_spf_tree, show_ipv6_ospf6_area_spf_tree_cmd,
1134 "show ipv6 ospf6 [vrf <NAME|all>] area A.B.C.D spf tree",
1135 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1136 "All VRFs\n" OSPF6_AREA_STR OSPF6_AREA_ID_STR
1137 "Shortest Path First calculation\n"
1138 "Show SPF tree\n")
1139 {
1140 int idx_ipv4 = 4;
1141 uint32_t area_id;
1142 struct ospf6 *ospf6;
1143 struct listnode *node;
1144 const char *vrf_name = NULL;
1145 bool all_vrf = false;
1146 int idx_vrf = 0;
1147
1148 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1149 if (idx_vrf > 0)
1150 idx_ipv4 += 2;
1151
1152 if (inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id) != 1) {
1153 vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4]->arg);
1154 return CMD_SUCCESS;
1155 }
1156
1157 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1158 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1159 show_ospf6_area_spf_tree_common(vty, argv, ospf6,
1160 area_id, idx_ipv4);
1161 if (!all_vrf)
1162 break;
1163 }
1164 }
1165
1166 OSPF6_CMD_CHECK_VRF(false, all_vrf, ospf6);
1167
1168 return CMD_SUCCESS;
1169 }
1170
1171 static int
1172 show_ospf6_simulate_spf_tree_commen(struct vty *vty, struct cmd_token **argv,
1173 struct ospf6 *ospf6, uint32_t router_id,
1174 uint32_t area_id, struct prefix prefix,
1175 int idx_ipv4, int idx_ipv4_2)
1176 {
1177 struct ospf6_area *oa;
1178 struct ospf6_vertex *root;
1179 struct ospf6_route *route;
1180 struct ospf6_route_table *spf_table;
1181 unsigned char tmp_debug_ospf6_spf = 0;
1182
1183 oa = ospf6_area_lookup(area_id, ospf6);
1184 if (oa == NULL) {
1185 vty_out(vty, "No such Area: %s\n", argv[idx_ipv4_2]->arg);
1186 return CMD_SUCCESS;
1187 }
1188
1189 tmp_debug_ospf6_spf = conf_debug_ospf6_spf;
1190 conf_debug_ospf6_spf = 0;
1191
1192 spf_table = OSPF6_ROUTE_TABLE_CREATE(NONE, SPF_RESULTS);
1193 ospf6_spf_calculation(router_id, spf_table, oa);
1194
1195 conf_debug_ospf6_spf = tmp_debug_ospf6_spf;
1196
1197 route = ospf6_route_lookup(&prefix, spf_table);
1198 if (route == NULL) {
1199 ospf6_spf_table_finish(spf_table);
1200 ospf6_route_table_delete(spf_table);
1201 return CMD_SUCCESS;
1202 }
1203 root = (struct ospf6_vertex *)route->route_option;
1204 ospf6_spf_display_subtree(vty, "", 0, root, NULL, false);
1205
1206 ospf6_spf_table_finish(spf_table);
1207 ospf6_route_table_delete(spf_table);
1208
1209 return CMD_SUCCESS;
1210 }
1211
1212 DEFUN(show_ipv6_ospf6_simulate_spf_tree_root,
1213 show_ipv6_ospf6_simulate_spf_tree_root_cmd,
1214 "show ipv6 ospf6 [vrf <NAME|all>] simulate spf-tree A.B.C.D area A.B.C.D",
1215 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1216 "All VRFs\n"
1217 "Shortest Path First calculation\n"
1218 "Show SPF tree\n"
1219 "Specify root's router-id to calculate another router's SPF tree\n"
1220 "OSPF6 area parameters\n" OSPF6_AREA_ID_STR)
1221 {
1222 int idx_ipv4 = 5;
1223 int idx_ipv4_2 = 7;
1224 uint32_t area_id;
1225 struct prefix prefix;
1226 uint32_t router_id;
1227 struct ospf6 *ospf6;
1228 struct listnode *node;
1229 const char *vrf_name = NULL;
1230 bool all_vrf = false;
1231 int idx_vrf = 0;
1232
1233 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1234 if (idx_vrf > 0) {
1235 idx_ipv4 += 2;
1236 idx_ipv4_2 += 2;
1237 }
1238 inet_pton(AF_INET, argv[idx_ipv4]->arg, &router_id);
1239 ospf6_linkstate_prefix(router_id, htonl(0), &prefix);
1240
1241 if (inet_pton(AF_INET, argv[idx_ipv4_2]->arg, &area_id) != 1) {
1242 vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4_2]->arg);
1243 return CMD_SUCCESS;
1244 }
1245
1246 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1247 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1248 show_ospf6_simulate_spf_tree_commen(
1249 vty, argv, ospf6, router_id, area_id, prefix,
1250 idx_ipv4, idx_ipv4_2);
1251 if (!all_vrf)
1252 break;
1253 }
1254 }
1255
1256 OSPF6_CMD_CHECK_VRF(false, all_vrf, ospf6);
1257
1258 return CMD_SUCCESS;
1259 }
1260
1261 DEFUN (ospf6_area_stub,
1262 ospf6_area_stub_cmd,
1263 "area <A.B.C.D|(0-4294967295)> stub",
1264 "OSPF6 area parameters\n"
1265 "OSPF6 area ID in IP address format\n"
1266 "OSPF6 area ID as a decimal value\n"
1267 "Configure OSPF6 area as stub\n")
1268 {
1269 int idx_ipv4_number = 1;
1270 struct ospf6_area *area;
1271
1272 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1273
1274 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area, ospf6);
1275
1276 if (!ospf6_area_stub_set(ospf6, area)) {
1277 vty_out(vty,
1278 "First deconfigure all virtual link through this area\n");
1279 return CMD_WARNING_CONFIG_FAILED;
1280 }
1281
1282 ospf6_area_no_summary_unset(ospf6, area);
1283
1284 return CMD_SUCCESS;
1285 }
1286
1287 DEFUN (ospf6_area_stub_no_summary,
1288 ospf6_area_stub_no_summary_cmd,
1289 "area <A.B.C.D|(0-4294967295)> stub no-summary",
1290 "OSPF6 stub parameters\n"
1291 "OSPF6 area ID in IP address format\n"
1292 "OSPF6 area ID as a decimal value\n"
1293 "Configure OSPF6 area as stub\n"
1294 "Do not inject inter-area routes into stub\n")
1295 {
1296 int idx_ipv4_number = 1;
1297 struct ospf6_area *area;
1298
1299 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1300
1301 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area, ospf6);
1302
1303 if (!ospf6_area_stub_set(ospf6, area)) {
1304 vty_out(vty,
1305 "First deconfigure all virtual link through this area\n");
1306 return CMD_WARNING_CONFIG_FAILED;
1307 }
1308
1309 ospf6_area_no_summary_set(ospf6, area);
1310
1311 return CMD_SUCCESS;
1312 }
1313
1314 DEFUN (no_ospf6_area_stub,
1315 no_ospf6_area_stub_cmd,
1316 "no area <A.B.C.D|(0-4294967295)> stub",
1317 NO_STR
1318 "OSPF6 area parameters\n"
1319 "OSPF6 area ID in IP address format\n"
1320 "OSPF6 area ID as a decimal value\n"
1321 "Configure OSPF6 area as stub\n")
1322 {
1323 int idx_ipv4_number = 2;
1324 struct ospf6_area *area;
1325
1326 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1327
1328 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area, ospf6);
1329
1330 ospf6_area_stub_unset(ospf6, area);
1331 ospf6_area_no_summary_unset(ospf6, area);
1332
1333 return CMD_SUCCESS;
1334 }
1335
1336 DEFUN (no_ospf6_area_stub_no_summary,
1337 no_ospf6_area_stub_no_summary_cmd,
1338 "no area <A.B.C.D|(0-4294967295)> stub no-summary",
1339 NO_STR
1340 "OSPF6 area parameters\n"
1341 "OSPF6 area ID in IP address format\n"
1342 "OSPF6 area ID as a decimal value\n"
1343 "Configure OSPF6 area as stub\n"
1344 "Do not inject inter-area routes into area\n")
1345 {
1346 int idx_ipv4_number = 2;
1347 struct ospf6_area *area;
1348
1349 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1350
1351 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area, ospf6);
1352
1353 ospf6_area_stub_unset(ospf6, area);
1354 ospf6_area_no_summary_unset(ospf6, area);
1355
1356 return CMD_SUCCESS;
1357 }
1358
1359 DEFPY(ospf6_area_nssa, ospf6_area_nssa_cmd,
1360 "area <A.B.C.D|(0-4294967295)>$area_str nssa\
1361 [{\
1362 default-information-originate$dflt_originate [{metric (0-16777214)$mval|metric-type (1-2)$mtype}]\
1363 |no-summary$no_summary\
1364 }]",
1365 "OSPF6 area parameters\n"
1366 "OSPF6 area ID in IP address format\n"
1367 "OSPF6 area ID as a decimal value\n"
1368 "Configure OSPF6 area as nssa\n"
1369 "Originate Type 7 default into NSSA area\n"
1370 "OSPFv3 default metric\n"
1371 "OSPFv3 metric\n"
1372 "OSPFv3 metric type for default routes\n"
1373 "Set OSPFv3 External Type 1/2 metrics\n"
1374 "Do not inject inter-area routes into area\n")
1375 {
1376 struct ospf6_area *area;
1377
1378 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1379 OSPF6_CMD_AREA_GET(area_str, area, ospf6);
1380
1381 if (!ospf6_area_nssa_set(ospf6, area)) {
1382 vty_out(vty,
1383 "First deconfigure all virtual link through this area\n");
1384 return CMD_WARNING_CONFIG_FAILED;
1385 }
1386
1387 if (dflt_originate) {
1388 if (mval_str == NULL)
1389 mval = -1;
1390 if (mtype_str == NULL)
1391 mtype = DEFAULT_METRIC_TYPE;
1392 ospf6_nssa_default_originate_set(ospf6, area, mval, mtype);
1393 } else
1394 ospf6_nssa_default_originate_unset(ospf6, area);
1395
1396 if (no_summary)
1397 ospf6_area_no_summary_set(ospf6, area);
1398 else
1399 ospf6_area_no_summary_unset(ospf6, area);
1400
1401 if (ospf6_check_and_set_router_abr(ospf6)) {
1402 ospf6_abr_defaults_to_stub(ospf6);
1403 ospf6_abr_nssa_type_7_defaults(ospf6);
1404 }
1405
1406 return CMD_SUCCESS;
1407 }
1408
1409 DEFPY(no_ospf6_area_nssa, no_ospf6_area_nssa_cmd,
1410 "no area <A.B.C.D|(0-4294967295)>$area_str nssa\
1411 [{\
1412 default-information-originate [{metric (0-16777214)|metric-type (1-2)}]\
1413 |no-summary\
1414 }]",
1415 NO_STR
1416 "OSPF6 area parameters\n"
1417 "OSPF6 area ID in IP address format\n"
1418 "OSPF6 area ID as a decimal value\n"
1419 "Configure OSPF6 area as nssa\n"
1420 "Originate Type 7 default into NSSA area\n"
1421 "OSPFv3 default metric\n"
1422 "OSPFv3 metric\n"
1423 "OSPFv3 metric type for default routes\n"
1424 "Set OSPFv3 External Type 1/2 metrics\n"
1425 "Do not inject inter-area routes into area\n")
1426 {
1427 struct ospf6_area *area;
1428
1429 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1430 OSPF6_CMD_AREA_GET(area_str, area, ospf6);
1431
1432 ospf6_area_nssa_unset(ospf6, area);
1433 ospf6_area_no_summary_unset(ospf6, area);
1434 ospf6_nssa_default_originate_unset(ospf6, area);
1435
1436 return CMD_SUCCESS;
1437 }
1438
1439
1440 void ospf6_area_init(void)
1441 {
1442 install_element(VIEW_NODE, &show_ipv6_ospf6_spf_tree_cmd);
1443 install_element(VIEW_NODE, &show_ipv6_ospf6_area_spf_tree_cmd);
1444 install_element(VIEW_NODE, &show_ipv6_ospf6_simulate_spf_tree_root_cmd);
1445
1446 install_element(OSPF6_NODE, &area_range_cmd);
1447 install_element(OSPF6_NODE, &no_area_range_cmd);
1448 install_element(OSPF6_NODE, &ospf6_area_stub_no_summary_cmd);
1449 install_element(OSPF6_NODE, &ospf6_area_stub_cmd);
1450 install_element(OSPF6_NODE, &no_ospf6_area_stub_no_summary_cmd);
1451 install_element(OSPF6_NODE, &no_ospf6_area_stub_cmd);
1452
1453
1454 install_element(OSPF6_NODE, &area_import_list_cmd);
1455 install_element(OSPF6_NODE, &no_area_import_list_cmd);
1456 install_element(OSPF6_NODE, &area_export_list_cmd);
1457 install_element(OSPF6_NODE, &no_area_export_list_cmd);
1458
1459 install_element(OSPF6_NODE, &area_filter_list_cmd);
1460 install_element(OSPF6_NODE, &no_area_filter_list_cmd);
1461
1462 /* "area nssa" commands. */
1463 install_element(OSPF6_NODE, &ospf6_area_nssa_cmd);
1464 install_element(OSPF6_NODE, &no_ospf6_area_nssa_cmd);
1465 }
1466
1467 void ospf6_area_interface_delete(struct ospf6_interface *oi)
1468 {
1469 struct ospf6_area *oa;
1470 struct listnode *node, *nnode;
1471 struct ospf6 *ospf6;
1472
1473 for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6)) {
1474 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa))
1475 if (listnode_lookup(oa->if_list, oi))
1476 listnode_delete(oa->if_list, oi);
1477 }
1478 }