]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_area.c
tools: improve explanation of 'wrap' options
[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 "ospf6_zebra.h"
47 #include "ospf6d.h"
48 #include "lib/json.h"
49 #include "ospf6_nssa.h"
50 #ifndef VTYSH_EXTRACT_PL
51 #include "ospf6d/ospf6_area_clippy.c"
52 #endif
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 list_delete(&oa->if_list);
355
356 ospf6_lsdb_delete(oa->lsdb);
357 ospf6_lsdb_delete(oa->lsdb_self);
358 ospf6_lsdb_delete(oa->temp_router_lsa_lsdb);
359
360 ospf6_spf_table_finish(oa->spf_table);
361 ospf6_route_table_delete(oa->spf_table);
362 ospf6_route_table_delete(oa->route_table);
363
364 ospf6_route_table_delete(oa->range_table);
365 ospf6_route_table_delete(oa->nssa_range_table);
366 ospf6_route_table_delete(oa->summary_prefix);
367 ospf6_route_table_delete(oa->summary_router);
368
369 listnode_delete(oa->ospf6->area_list, oa);
370 oa->ospf6 = NULL;
371
372 /* free area */
373 XFREE(MTYPE_OSPF6_AREA, oa);
374 }
375
376 struct ospf6_area *ospf6_area_lookup_by_area_id(uint32_t area_id)
377 {
378 struct ospf6_area *oa;
379 struct listnode *n, *node, *nnode;
380 struct ospf6 *ospf6;
381
382 for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6)) {
383 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa))
384 if (oa->area_id == area_id)
385 return oa;
386 }
387 return (struct ospf6_area *)NULL;
388 }
389
390 struct ospf6_area *ospf6_area_lookup(uint32_t area_id, struct ospf6 *ospf6)
391 {
392 struct ospf6_area *oa;
393 struct listnode *n;
394
395 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa))
396 if (oa->area_id == area_id)
397 return oa;
398
399 return (struct ospf6_area *)NULL;
400 }
401
402 void ospf6_area_enable(struct ospf6_area *oa)
403 {
404 struct listnode *node, *nnode;
405 struct ospf6_interface *oi;
406
407 SET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
408
409 for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi))
410 ospf6_interface_enable(oi);
411 ospf6_abr_enable_area(oa);
412 }
413
414 void ospf6_area_disable(struct ospf6_area *oa)
415 {
416 struct listnode *node, *nnode;
417 struct ospf6_interface *oi;
418
419 UNSET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
420
421 for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi))
422 ospf6_interface_disable(oi);
423
424 ospf6_abr_disable_area(oa);
425 ospf6_lsdb_remove_all(oa->lsdb);
426 ospf6_lsdb_remove_all(oa->lsdb_self);
427
428 ospf6_spf_table_finish(oa->spf_table);
429 ospf6_route_remove_all(oa->route_table);
430
431 THREAD_OFF(oa->thread_router_lsa);
432 THREAD_OFF(oa->thread_intra_prefix_lsa);
433 }
434
435
436 void ospf6_area_show(struct vty *vty, struct ospf6_area *oa,
437 json_object *json_areas, bool use_json)
438 {
439 struct listnode *i;
440 struct ospf6_interface *oi;
441 unsigned long result;
442 json_object *json_area;
443 json_object *array_interfaces;
444
445 if (use_json) {
446 json_area = json_object_new_object();
447 json_object_boolean_add(json_area, "areaIsStub",
448 IS_AREA_STUB(oa));
449 json_object_boolean_add(json_area, "areaIsNSSA",
450 IS_AREA_NSSA(oa));
451 if (IS_AREA_STUB(oa) || IS_AREA_NSSA(oa)) {
452 json_object_boolean_add(json_area, "areaNoSummary",
453 oa->no_summary);
454 }
455
456 json_object_int_add(json_area, "numberOfAreaScopedLsa",
457 oa->lsdb->count);
458 json_object_object_add(
459 json_area, "lsaStatistics",
460 JSON_OBJECT_NEW_ARRAY(json_object_new_int,
461 oa->lsdb->stats,
462 OSPF6_LSTYPE_SIZE));
463
464 /* Interfaces Attached */
465 array_interfaces = json_object_new_array();
466 for (ALL_LIST_ELEMENTS_RO(oa->if_list, i, oi))
467 json_object_array_add(
468 array_interfaces,
469 json_object_new_string(oi->interface->name));
470
471 json_object_object_add(json_area, "interfacesAttachedToArea",
472 array_interfaces);
473
474 if (oa->ts_spf.tv_sec || oa->ts_spf.tv_usec) {
475 json_object_boolean_true_add(json_area, "spfHasRun");
476 result = monotime_since(&oa->ts_spf, NULL);
477 if (result / TIMER_SECOND_MICRO > 0) {
478 json_object_int_add(
479 json_area, "spfLastExecutedSecs",
480 result / TIMER_SECOND_MICRO);
481
482 json_object_int_add(
483 json_area, "spfLastExecutedMicroSecs",
484 result % TIMER_SECOND_MICRO);
485 } else {
486 json_object_int_add(json_area,
487 "spfLastExecutedSecs", 0);
488 json_object_int_add(json_area,
489 "spfLastExecutedMicroSecs",
490 result);
491 }
492 } else
493 json_object_boolean_false_add(json_area, "spfHasRun");
494
495
496 json_object_object_add(json_areas, oa->name, json_area);
497
498 } else {
499
500 if (!IS_AREA_STUB(oa) && !IS_AREA_NSSA(oa))
501 vty_out(vty, " Area %s\n", oa->name);
502 else {
503 if (oa->no_summary) {
504 vty_out(vty, " Area %s[%s, No Summary]\n",
505 oa->name,
506 IS_AREA_STUB(oa) ? "Stub" : "NSSA");
507 } else {
508 vty_out(vty, " Area %s[%s]\n", oa->name,
509 IS_AREA_STUB(oa) ? "Stub" : "NSSA");
510 }
511 }
512 vty_out(vty, " Number of Area scoped LSAs is %u\n",
513 oa->lsdb->count);
514
515 vty_out(vty, " Interface attached to this area:");
516 for (ALL_LIST_ELEMENTS_RO(oa->if_list, i, oi))
517 vty_out(vty, " %s", oi->interface->name);
518 vty_out(vty, "\n");
519
520 if (oa->ts_spf.tv_sec || oa->ts_spf.tv_usec) {
521 result = monotime_since(&oa->ts_spf, NULL);
522 if (result / TIMER_SECOND_MICRO > 0) {
523 vty_out(vty,
524 " SPF last executed %ld.%lds ago\n",
525 result / TIMER_SECOND_MICRO,
526 result % TIMER_SECOND_MICRO);
527 } else {
528 vty_out(vty,
529 " SPF last executed %ldus ago\n",
530 result);
531 }
532 } else
533 vty_out(vty, "SPF has not been run\n");
534 }
535 }
536
537 DEFUN (area_range,
538 area_range_cmd,
539 "area <A.B.C.D|(0-4294967295)> range X:X::X:X/M [<advertise|not-advertise|cost (0-16777215)>]",
540 "OSPF6 area parameters\n"
541 "OSPF6 area ID in IP address format\n"
542 "OSPF6 area ID as a decimal value\n"
543 "Configured address range\n"
544 "Specify IPv6 prefix\n"
545 "Advertise\n"
546 "Do not advertise\n"
547 "User specified metric for this range\n"
548 "Advertised metric for this range\n")
549 {
550 int idx_ipv4 = 1;
551 int idx_ipv6_prefixlen = 3;
552 int idx_type = 4;
553 int ret;
554 struct ospf6_area *oa;
555 struct prefix prefix;
556 struct ospf6_route *range;
557 uint32_t cost;
558
559 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
560
561 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, oa, ospf6);
562
563 ret = str2prefix(argv[idx_ipv6_prefixlen]->arg, &prefix);
564 if (ret != 1 || prefix.family != AF_INET6) {
565 vty_out(vty, "Malformed argument: %s\n",
566 argv[idx_ipv6_prefixlen]->arg);
567 return CMD_SUCCESS;
568 }
569
570 range = ospf6_route_lookup(&prefix, oa->range_table);
571 if (range == NULL) {
572 range = ospf6_route_create(ospf6);
573 range->type = OSPF6_DEST_TYPE_RANGE;
574 range->prefix = prefix;
575 range->path.area_id = oa->area_id;
576 range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC;
577 }
578
579 /* default settings */
580 cost = OSPF_AREA_RANGE_COST_UNSPEC;
581 UNSET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
582
583 if (argc > idx_type) {
584 if (strmatch(argv[idx_type]->text, "not-advertise"))
585 SET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
586 else if (strmatch(argv[idx_type]->text, "cost"))
587 cost = strtoul(argv[5]->arg, NULL, 10);
588 }
589
590 range->path.u.cost_config = cost;
591
592 if (range->rnode == NULL) {
593 ospf6_route_add(range, oa->range_table);
594 }
595
596 if (ospf6_check_and_set_router_abr(ospf6)) {
597 /* Redo summaries if required */
598 ospf6_abr_prefix_resummarize(ospf6);
599 }
600
601 return CMD_SUCCESS;
602 }
603
604 DEFUN (no_area_range,
605 no_area_range_cmd,
606 "no area <A.B.C.D|(0-4294967295)> range X:X::X:X/M [<advertise|not-advertise|cost (0-16777215)>]",
607 NO_STR
608 "OSPF6 area parameters\n"
609 "OSPF6 area ID in IP address format\n"
610 "OSPF6 area ID as a decimal value\n"
611 "Configured address range\n"
612 "Specify IPv6 prefix\n"
613 "Advertise\n"
614 "Do not advertise\n"
615 "User specified metric for this range\n"
616 "Advertised metric for this range\n")
617 {
618 int idx_ipv4 = 2;
619 int idx_ipv6 = 4;
620 int ret;
621 struct ospf6_area *oa;
622 struct prefix prefix;
623 struct ospf6_route *range, *route;
624
625 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
626
627 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, oa, ospf6);
628
629 ret = str2prefix(argv[idx_ipv6]->arg, &prefix);
630 if (ret != 1 || prefix.family != AF_INET6) {
631 vty_out(vty, "Malformed argument: %s\n", argv[idx_ipv6]->arg);
632 return CMD_SUCCESS;
633 }
634
635 range = ospf6_route_lookup(&prefix, oa->range_table);
636 if (range == NULL) {
637 vty_out(vty, "Range %s does not exists.\n",
638 argv[idx_ipv6]->arg);
639 return CMD_SUCCESS;
640 }
641
642 if (ospf6_check_and_set_router_abr(oa->ospf6)) {
643 /* Blow away the aggregated LSA and route */
644 SET_FLAG(range->flag, OSPF6_ROUTE_REMOVE);
645
646 /* Redo summaries if required */
647 for (route = ospf6_route_head(oa->ospf6->route_table); route;
648 route = ospf6_route_next(route))
649 ospf6_abr_originate_summary(route, oa->ospf6);
650
651 /* purge the old aggregated summary LSA */
652 ospf6_abr_originate_summary(range, oa->ospf6);
653 }
654 ospf6_route_remove(range, oa->range_table);
655
656 return CMD_SUCCESS;
657 }
658
659 void ospf6_area_config_write(struct vty *vty, struct ospf6 *ospf6)
660 {
661 struct listnode *node;
662 struct ospf6_area *oa;
663 struct ospf6_route *range;
664
665 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
666 for (range = ospf6_route_head(oa->range_table); range;
667 range = ospf6_route_next(range)) {
668 vty_out(vty, " area %s range %pFX", oa->name,
669 &range->prefix);
670
671 if (CHECK_FLAG(range->flag,
672 OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
673 vty_out(vty, " not-advertise");
674 } else {
675 // "advertise" is the default so we do not
676 // display it
677 if (range->path.u.cost_config
678 != OSPF_AREA_RANGE_COST_UNSPEC)
679 vty_out(vty, " cost %d",
680 range->path.u.cost_config);
681 }
682 vty_out(vty, "\n");
683 }
684 if (IS_AREA_STUB(oa)) {
685 if (oa->no_summary)
686 vty_out(vty, " area %s stub no-summary\n",
687 oa->name);
688 else
689 vty_out(vty, " area %s stub\n", oa->name);
690 }
691 if (IS_AREA_NSSA(oa)) {
692 vty_out(vty, " area %s nssa", oa->name);
693 if (oa->nssa_default_originate.enabled) {
694 vty_out(vty, " default-information-originate");
695 if (oa->nssa_default_originate.metric_value
696 != -1)
697 vty_out(vty, " metric %d",
698 oa->nssa_default_originate
699 .metric_value);
700 if (oa->nssa_default_originate.metric_type
701 != DEFAULT_METRIC_TYPE)
702 vty_out(vty, " metric-type 1");
703 }
704 if (oa->no_summary)
705 vty_out(vty, " no-summary");
706 vty_out(vty, "\n");
707 }
708 for (range = ospf6_route_head(oa->nssa_range_table); range;
709 range = ospf6_route_next(range)) {
710 vty_out(vty, " area %s nssa range %pFX", oa->name,
711 &range->prefix);
712
713 if (CHECK_FLAG(range->flag,
714 OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
715 vty_out(vty, " not-advertise");
716 } else {
717 if (range->path.u.cost_config
718 != OSPF_AREA_RANGE_COST_UNSPEC)
719 vty_out(vty, " cost %u",
720 range->path.u.cost_config);
721 }
722 vty_out(vty, "\n");
723 }
724 if (PREFIX_NAME_IN(oa))
725 vty_out(vty, " area %s filter-list prefix %s in\n",
726 oa->name, PREFIX_NAME_IN(oa));
727 if (PREFIX_NAME_OUT(oa))
728 vty_out(vty, " area %s filter-list prefix %s out\n",
729 oa->name, PREFIX_NAME_OUT(oa));
730 if (IMPORT_NAME(oa))
731 vty_out(vty, " area %s import-list %s\n", oa->name,
732 IMPORT_NAME(oa));
733 if (EXPORT_NAME(oa))
734 vty_out(vty, " area %s export-list %s\n", oa->name,
735 EXPORT_NAME(oa));
736 }
737 }
738
739 DEFUN (area_filter_list,
740 area_filter_list_cmd,
741 "area <A.B.C.D|(0-4294967295)> filter-list prefix PREFIXLIST_NAME <in|out>",
742 "OSPF6 area parameters\n"
743 "OSPF6 area ID in IP address format\n"
744 "OSPF6 area ID as a decimal value\n"
745 "Filter networks between OSPF6 areas\n"
746 "Filter prefixes between OSPF6 areas\n"
747 "Name of an IPv6 prefix-list\n"
748 "Filter networks sent to this area\n"
749 "Filter networks sent from this area\n")
750 {
751 char *inout = argv[argc - 1]->text;
752 char *areaid = argv[1]->arg;
753 char *plistname = argv[4]->arg;
754
755 struct ospf6_area *area;
756 struct prefix_list *plist;
757
758 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
759
760 OSPF6_CMD_AREA_GET(areaid, area, ospf6);
761
762 plist = prefix_list_lookup(AFI_IP6, plistname);
763 if (strmatch(inout, "in")) {
764 PREFIX_LIST_IN(area) = plist;
765 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
766 PREFIX_NAME_IN(area) =
767 XSTRDUP(MTYPE_OSPF6_PLISTNAME, plistname);
768 } else {
769 PREFIX_LIST_OUT(area) = plist;
770 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
771 PREFIX_NAME_OUT(area) =
772 XSTRDUP(MTYPE_OSPF6_PLISTNAME, plistname);
773 }
774
775 /* Redo summaries if required */
776 if (ospf6_check_and_set_router_abr(area->ospf6))
777 ospf6_schedule_abr_task(ospf6);
778
779 return CMD_SUCCESS;
780 }
781
782 DEFUN (no_area_filter_list,
783 no_area_filter_list_cmd,
784 "no area <A.B.C.D|(0-4294967295)> filter-list prefix PREFIXLIST_NAME <in|out>",
785 NO_STR
786 "OSPF6 area parameters\n"
787 "OSPF6 area ID in IP address format\n"
788 "OSPF6 area ID as a decimal value\n"
789 "Filter networks between OSPF6 areas\n"
790 "Filter prefixes between OSPF6 areas\n"
791 "Name of an IPv6 prefix-list\n"
792 "Filter networks sent to this area\n"
793 "Filter networks sent from this area\n")
794 {
795 char *inout = argv[argc - 1]->text;
796 char *areaid = argv[2]->arg;
797 char *plistname = argv[5]->arg;
798
799 struct ospf6_area *area;
800
801 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
802 OSPF6_CMD_AREA_GET(areaid, area, ospf6);
803
804 if (strmatch(inout, "in")) {
805 if (PREFIX_NAME_IN(area))
806 if (!strmatch(PREFIX_NAME_IN(area), plistname))
807 return CMD_SUCCESS;
808
809 PREFIX_LIST_IN(area) = NULL;
810 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
811 } else {
812 if (PREFIX_NAME_OUT(area))
813 if (!strmatch(PREFIX_NAME_OUT(area), plistname))
814 return CMD_SUCCESS;
815
816 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
817 PREFIX_LIST_OUT(area) = NULL;
818 }
819
820 /* Redo summaries if required */
821 if (ospf6_check_and_set_router_abr(area->ospf6))
822 ospf6_schedule_abr_task(ospf6);
823
824 return CMD_SUCCESS;
825 }
826
827 void ospf6_filter_update(struct access_list *access)
828 {
829 struct ospf6_area *oa;
830 struct listnode *n, *node, *nnode;
831 struct ospf6 *ospf6;
832
833 for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6)) {
834 bool update = false;
835
836 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa)) {
837 if (IMPORT_NAME(oa)
838 && strcmp(IMPORT_NAME(oa), access->name) == 0) {
839 IMPORT_LIST(oa) = access_list_lookup(
840 AFI_IP6, IMPORT_NAME(oa));
841 update = true;
842 }
843
844 if (EXPORT_NAME(oa)
845 && strcmp(EXPORT_NAME(oa), access->name) == 0) {
846 EXPORT_LIST(oa) = access_list_lookup(
847 AFI_IP6, EXPORT_NAME(oa));
848 update = true;
849 }
850 }
851
852 if (update && ospf6_check_and_set_router_abr(ospf6))
853 ospf6_schedule_abr_task(ospf6);
854 }
855 }
856
857 void ospf6_plist_update(struct prefix_list *plist)
858 {
859 struct listnode *node, *nnode;
860 struct ospf6_area *oa;
861 struct listnode *n;
862 const char *name = prefix_list_name(plist);
863 struct ospf6 *ospf6 = NULL;
864
865 if (prefix_list_afi(plist) != AFI_IP6)
866 return;
867
868 for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6)) {
869 bool update = false;
870
871 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa)) {
872 if (PREFIX_NAME_IN(oa)
873 && !strcmp(PREFIX_NAME_IN(oa), name)) {
874 PREFIX_LIST_IN(oa) = prefix_list_lookup(
875 AFI_IP6, PREFIX_NAME_IN(oa));
876 update = true;
877 }
878 if (PREFIX_NAME_OUT(oa)
879 && !strcmp(PREFIX_NAME_OUT(oa), name)) {
880 PREFIX_LIST_OUT(oa) = prefix_list_lookup(
881 AFI_IP6, PREFIX_NAME_OUT(oa));
882 update = true;
883 }
884 }
885
886 if (update && ospf6_check_and_set_router_abr(ospf6))
887 ospf6_schedule_abr_task(ospf6);
888 }
889 }
890
891 DEFUN (area_import_list,
892 area_import_list_cmd,
893 "area <A.B.C.D|(0-4294967295)> import-list ACCESSLIST6_NAME",
894 "OSPF6 area parameters\n"
895 "OSPF6 area ID in IP address format\n"
896 "OSPF6 area ID as a decimal value\n"
897 "Set the filter for networks from other areas announced to the specified one\n"
898 "Name of the access-list\n")
899 {
900 int idx_ipv4 = 1;
901 int idx_name = 3;
902 struct ospf6_area *area;
903 struct access_list *list;
904
905 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
906
907 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area, ospf6);
908
909 list = access_list_lookup(AFI_IP6, argv[idx_name]->arg);
910
911 IMPORT_LIST(area) = list;
912
913 if (IMPORT_NAME(area))
914 free(IMPORT_NAME(area));
915
916 IMPORT_NAME(area) = strdup(argv[idx_name]->arg);
917 if (ospf6_check_and_set_router_abr(area->ospf6))
918 ospf6_schedule_abr_task(ospf6);
919
920 return CMD_SUCCESS;
921 }
922
923 DEFUN (no_area_import_list,
924 no_area_import_list_cmd,
925 "no area <A.B.C.D|(0-4294967295)> import-list ACCESSLIST6_NAME",
926 NO_STR
927 "OSPF6 area parameters\n"
928 "OSPF6 area ID in IP address format\n"
929 "OSPF6 area ID as a decimal value\n"
930 "Unset the filter for networks announced to other areas\n"
931 "Name of the access-list\n")
932 {
933 int idx_ipv4 = 2;
934 struct ospf6_area *area;
935
936 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
937
938 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area, ospf6);
939
940 IMPORT_LIST(area) = NULL;
941
942 if (IMPORT_NAME(area))
943 free(IMPORT_NAME(area));
944
945 IMPORT_NAME(area) = NULL;
946 if (ospf6_check_and_set_router_abr(area->ospf6))
947 ospf6_schedule_abr_task(ospf6);
948
949 return CMD_SUCCESS;
950 }
951
952 DEFUN (area_export_list,
953 area_export_list_cmd,
954 "area <A.B.C.D|(0-4294967295)> export-list ACCESSLIST6_NAME",
955 "OSPF6 area parameters\n"
956 "OSPF6 area ID in IP address format\n"
957 "OSPF6 area ID as a decimal value\n"
958 "Set the filter for networks announced to other areas\n"
959 "Name of the access-list\n")
960 {
961 int idx_ipv4 = 1;
962 int idx_name = 3;
963 struct ospf6_area *area;
964 struct access_list *list;
965
966 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
967
968 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area, ospf6);
969
970 list = access_list_lookup(AFI_IP6, argv[idx_name]->arg);
971
972 EXPORT_LIST(area) = list;
973
974 if (EXPORT_NAME(area))
975 free(EXPORT_NAME(area));
976
977 EXPORT_NAME(area) = strdup(argv[idx_name]->arg);
978
979 /* Redo summaries if required */
980 if (ospf6_check_and_set_router_abr(area->ospf6))
981 ospf6_schedule_abr_task(ospf6);
982
983 return CMD_SUCCESS;
984 }
985
986 DEFUN (no_area_export_list,
987 no_area_export_list_cmd,
988 "no area <A.B.C.D|(0-4294967295)> export-list ACCESSLIST6_NAME",
989 NO_STR
990 "OSPF6 area parameters\n"
991 "OSPF6 area ID in IP address format\n"
992 "OSPF6 area ID as a decimal value\n"
993 "Unset the filter for networks announced to other areas\n"
994 "Name of the access-list\n")
995 {
996 int idx_ipv4 = 2;
997 struct ospf6_area *area;
998
999 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1000
1001 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area, ospf6);
1002
1003 EXPORT_LIST(area) = NULL;
1004
1005 if (EXPORT_NAME(area))
1006 free(EXPORT_NAME(area));
1007
1008 EXPORT_NAME(area) = NULL;
1009 if (ospf6_check_and_set_router_abr(area->ospf6))
1010 ospf6_schedule_abr_task(ospf6);
1011
1012 return CMD_SUCCESS;
1013 }
1014
1015 static int ipv6_ospf6_spf_tree_common(struct vty *vty, struct ospf6 *ospf6,
1016 bool uj)
1017 {
1018 struct listnode *node;
1019 struct ospf6_area *oa;
1020 struct prefix prefix;
1021 struct ospf6_vertex *root;
1022 struct ospf6_route *route;
1023 json_object *json = NULL;
1024 json_object *json_area = NULL;
1025 json_object *json_head = NULL;
1026
1027 if (uj)
1028 json = json_object_new_object();
1029 ospf6_linkstate_prefix(ospf6->router_id, htonl(0), &prefix);
1030 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
1031 if (uj) {
1032 json_area = json_object_new_object();
1033 json_head = json_object_new_object();
1034 }
1035 route = ospf6_route_lookup(&prefix, oa->spf_table);
1036 if (route == NULL) {
1037 if (uj) {
1038 json_object_string_add(
1039 json, oa->name,
1040 "LS entry for not not found");
1041 json_object_free(json_head);
1042 json_object_free(json_area);
1043 } else
1044 vty_out(vty,
1045 "LS entry for root not found in area %s\n",
1046 oa->name);
1047 continue;
1048 }
1049 root = (struct ospf6_vertex *)route->route_option;
1050 ospf6_spf_display_subtree(vty, "", 0, root, json_head, uj);
1051
1052 if (uj) {
1053 json_object_object_add(json_area, root->name,
1054 json_head);
1055 json_object_object_add(json, oa->name, json_area);
1056 }
1057 }
1058
1059 if (uj)
1060 vty_json(vty, json);
1061
1062 return CMD_SUCCESS;
1063 }
1064
1065 DEFUN(show_ipv6_ospf6_spf_tree, show_ipv6_ospf6_spf_tree_cmd,
1066 "show ipv6 ospf6 [vrf <NAME|all>] spf tree [json]",
1067 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1068 "All VRFs\n"
1069 "Shortest Path First calculation\n"
1070 "Show SPF tree\n" JSON_STR)
1071 {
1072 struct listnode *node;
1073 struct ospf6 *ospf6;
1074 const char *vrf_name = NULL;
1075 bool all_vrf = false;
1076 int idx_vrf = 0;
1077 bool uj = use_json(argc, argv);
1078
1079 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1080
1081 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1082 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1083 ipv6_ospf6_spf_tree_common(vty, ospf6, uj);
1084 if (!all_vrf)
1085 break;
1086 }
1087 }
1088
1089 OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
1090
1091 return CMD_SUCCESS;
1092 }
1093
1094 static int show_ospf6_area_spf_tree_common(struct vty *vty,
1095 struct cmd_token **argv,
1096 struct ospf6 *ospf6,
1097 uint32_t area_id, int idx_ipv4)
1098 {
1099
1100 struct ospf6_area *oa;
1101 struct prefix prefix;
1102 struct ospf6_vertex *root;
1103 struct ospf6_route *route;
1104
1105 ospf6_linkstate_prefix(ospf6->router_id, htonl(0), &prefix);
1106
1107 oa = ospf6_area_lookup(area_id, ospf6);
1108 if (oa == NULL) {
1109 vty_out(vty, "No such Area: %s\n", argv[idx_ipv4]->arg);
1110 return CMD_SUCCESS;
1111 }
1112
1113 route = ospf6_route_lookup(&prefix, oa->spf_table);
1114 if (route == NULL) {
1115 vty_out(vty, "LS entry for root not found in area %s\n",
1116 oa->name);
1117 return CMD_SUCCESS;
1118 }
1119 root = (struct ospf6_vertex *)route->route_option;
1120 ospf6_spf_display_subtree(vty, "", 0, root, NULL, false);
1121
1122 return CMD_SUCCESS;
1123 }
1124
1125 DEFUN(show_ipv6_ospf6_area_spf_tree, show_ipv6_ospf6_area_spf_tree_cmd,
1126 "show ipv6 ospf6 [vrf <NAME|all>] area A.B.C.D spf tree",
1127 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1128 "All VRFs\n" OSPF6_AREA_STR OSPF6_AREA_ID_STR
1129 "Shortest Path First calculation\n"
1130 "Show SPF tree\n")
1131 {
1132 int idx_ipv4 = 4;
1133 uint32_t area_id;
1134 struct ospf6 *ospf6;
1135 struct listnode *node;
1136 const char *vrf_name = NULL;
1137 bool all_vrf = false;
1138 int idx_vrf = 0;
1139
1140 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1141 if (idx_vrf > 0)
1142 idx_ipv4 += 2;
1143
1144 if (inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id) != 1) {
1145 vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4]->arg);
1146 return CMD_SUCCESS;
1147 }
1148
1149 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1150 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1151 show_ospf6_area_spf_tree_common(vty, argv, ospf6,
1152 area_id, idx_ipv4);
1153 if (!all_vrf)
1154 break;
1155 }
1156 }
1157
1158 OSPF6_CMD_CHECK_VRF(false, all_vrf, ospf6);
1159
1160 return CMD_SUCCESS;
1161 }
1162
1163 static int
1164 show_ospf6_simulate_spf_tree_commen(struct vty *vty, struct cmd_token **argv,
1165 struct ospf6 *ospf6, uint32_t router_id,
1166 uint32_t area_id, struct prefix prefix,
1167 int idx_ipv4, int idx_ipv4_2)
1168 {
1169 struct ospf6_area *oa;
1170 struct ospf6_vertex *root;
1171 struct ospf6_route *route;
1172 struct ospf6_route_table *spf_table;
1173 unsigned char tmp_debug_ospf6_spf = 0;
1174
1175 oa = ospf6_area_lookup(area_id, ospf6);
1176 if (oa == NULL) {
1177 vty_out(vty, "No such Area: %s\n", argv[idx_ipv4_2]->arg);
1178 return CMD_SUCCESS;
1179 }
1180
1181 tmp_debug_ospf6_spf = conf_debug_ospf6_spf;
1182 conf_debug_ospf6_spf = 0;
1183
1184 spf_table = OSPF6_ROUTE_TABLE_CREATE(NONE, SPF_RESULTS);
1185 ospf6_spf_calculation(router_id, spf_table, oa);
1186
1187 conf_debug_ospf6_spf = tmp_debug_ospf6_spf;
1188
1189 route = ospf6_route_lookup(&prefix, spf_table);
1190 if (route == NULL) {
1191 ospf6_spf_table_finish(spf_table);
1192 ospf6_route_table_delete(spf_table);
1193 return CMD_SUCCESS;
1194 }
1195 root = (struct ospf6_vertex *)route->route_option;
1196 ospf6_spf_display_subtree(vty, "", 0, root, NULL, false);
1197
1198 ospf6_spf_table_finish(spf_table);
1199 ospf6_route_table_delete(spf_table);
1200
1201 return CMD_SUCCESS;
1202 }
1203
1204 DEFUN(show_ipv6_ospf6_simulate_spf_tree_root,
1205 show_ipv6_ospf6_simulate_spf_tree_root_cmd,
1206 "show ipv6 ospf6 [vrf <NAME|all>] simulate spf-tree A.B.C.D area A.B.C.D",
1207 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1208 "All VRFs\n"
1209 "Shortest Path First calculation\n"
1210 "Show SPF tree\n"
1211 "Specify root's router-id to calculate another router's SPF tree\n"
1212 "OSPF6 area parameters\n" OSPF6_AREA_ID_STR)
1213 {
1214 int idx_ipv4 = 5;
1215 int idx_ipv4_2 = 7;
1216 uint32_t area_id;
1217 struct prefix prefix;
1218 uint32_t router_id;
1219 struct ospf6 *ospf6;
1220 struct listnode *node;
1221 const char *vrf_name = NULL;
1222 bool all_vrf = false;
1223 int idx_vrf = 0;
1224
1225 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1226 if (idx_vrf > 0) {
1227 idx_ipv4 += 2;
1228 idx_ipv4_2 += 2;
1229 }
1230 inet_pton(AF_INET, argv[idx_ipv4]->arg, &router_id);
1231 ospf6_linkstate_prefix(router_id, htonl(0), &prefix);
1232
1233 if (inet_pton(AF_INET, argv[idx_ipv4_2]->arg, &area_id) != 1) {
1234 vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4_2]->arg);
1235 return CMD_SUCCESS;
1236 }
1237
1238 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1239 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1240 show_ospf6_simulate_spf_tree_commen(
1241 vty, argv, ospf6, router_id, area_id, prefix,
1242 idx_ipv4, idx_ipv4_2);
1243 if (!all_vrf)
1244 break;
1245 }
1246 }
1247
1248 OSPF6_CMD_CHECK_VRF(false, all_vrf, ospf6);
1249
1250 return CMD_SUCCESS;
1251 }
1252
1253 DEFUN (ospf6_area_stub,
1254 ospf6_area_stub_cmd,
1255 "area <A.B.C.D|(0-4294967295)> stub",
1256 "OSPF6 area parameters\n"
1257 "OSPF6 area ID in IP address format\n"
1258 "OSPF6 area ID as a decimal value\n"
1259 "Configure OSPF6 area as stub\n")
1260 {
1261 int idx_ipv4_number = 1;
1262 struct ospf6_area *area;
1263
1264 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1265
1266 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area, ospf6);
1267
1268 if (!ospf6_area_stub_set(ospf6, area)) {
1269 vty_out(vty,
1270 "First deconfigure all virtual link through this area\n");
1271 return CMD_WARNING_CONFIG_FAILED;
1272 }
1273
1274 ospf6_area_no_summary_unset(ospf6, area);
1275
1276 return CMD_SUCCESS;
1277 }
1278
1279 DEFUN (ospf6_area_stub_no_summary,
1280 ospf6_area_stub_no_summary_cmd,
1281 "area <A.B.C.D|(0-4294967295)> stub no-summary",
1282 "OSPF6 stub parameters\n"
1283 "OSPF6 area ID in IP address format\n"
1284 "OSPF6 area ID as a decimal value\n"
1285 "Configure OSPF6 area as stub\n"
1286 "Do not inject inter-area routes into stub\n")
1287 {
1288 int idx_ipv4_number = 1;
1289 struct ospf6_area *area;
1290
1291 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1292
1293 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area, ospf6);
1294
1295 if (!ospf6_area_stub_set(ospf6, area)) {
1296 vty_out(vty,
1297 "First deconfigure all virtual link through this area\n");
1298 return CMD_WARNING_CONFIG_FAILED;
1299 }
1300
1301 ospf6_area_no_summary_set(ospf6, area);
1302
1303 return CMD_SUCCESS;
1304 }
1305
1306 DEFUN (no_ospf6_area_stub,
1307 no_ospf6_area_stub_cmd,
1308 "no area <A.B.C.D|(0-4294967295)> stub",
1309 NO_STR
1310 "OSPF6 area parameters\n"
1311 "OSPF6 area ID in IP address format\n"
1312 "OSPF6 area ID as a decimal value\n"
1313 "Configure OSPF6 area as stub\n")
1314 {
1315 int idx_ipv4_number = 2;
1316 struct ospf6_area *area;
1317
1318 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1319
1320 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area, ospf6);
1321
1322 ospf6_area_stub_unset(ospf6, area);
1323 ospf6_area_no_summary_unset(ospf6, area);
1324
1325 return CMD_SUCCESS;
1326 }
1327
1328 DEFUN (no_ospf6_area_stub_no_summary,
1329 no_ospf6_area_stub_no_summary_cmd,
1330 "no area <A.B.C.D|(0-4294967295)> stub no-summary",
1331 NO_STR
1332 "OSPF6 area parameters\n"
1333 "OSPF6 area ID in IP address format\n"
1334 "OSPF6 area ID as a decimal value\n"
1335 "Configure OSPF6 area as stub\n"
1336 "Do not inject inter-area routes into area\n")
1337 {
1338 int idx_ipv4_number = 2;
1339 struct ospf6_area *area;
1340
1341 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1342
1343 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area, ospf6);
1344
1345 ospf6_area_stub_unset(ospf6, area);
1346 ospf6_area_no_summary_unset(ospf6, area);
1347
1348 return CMD_SUCCESS;
1349 }
1350
1351 DEFPY(ospf6_area_nssa, ospf6_area_nssa_cmd,
1352 "area <A.B.C.D|(0-4294967295)>$area_str nssa\
1353 [{\
1354 default-information-originate$dflt_originate [{metric (0-16777214)$mval|metric-type (1-2)$mtype}]\
1355 |no-summary$no_summary\
1356 }]",
1357 "OSPF6 area parameters\n"
1358 "OSPF6 area ID in IP address format\n"
1359 "OSPF6 area ID as a decimal value\n"
1360 "Configure OSPF6 area as nssa\n"
1361 "Originate Type 7 default into NSSA area\n"
1362 "OSPFv3 default metric\n"
1363 "OSPFv3 metric\n"
1364 "OSPFv3 metric type for default routes\n"
1365 "Set OSPFv3 External Type 1/2 metrics\n"
1366 "Do not inject inter-area routes into area\n")
1367 {
1368 struct ospf6_area *area;
1369
1370 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1371 OSPF6_CMD_AREA_GET(area_str, area, ospf6);
1372
1373 if (!ospf6_area_nssa_set(ospf6, area)) {
1374 vty_out(vty,
1375 "First deconfigure all virtual link through this area\n");
1376 return CMD_WARNING_CONFIG_FAILED;
1377 }
1378
1379 if (dflt_originate) {
1380 if (mval_str == NULL)
1381 mval = -1;
1382 if (mtype_str == NULL)
1383 mtype = DEFAULT_METRIC_TYPE;
1384 ospf6_nssa_default_originate_set(ospf6, area, mval, mtype);
1385 } else
1386 ospf6_nssa_default_originate_unset(ospf6, area);
1387
1388 if (no_summary)
1389 ospf6_area_no_summary_set(ospf6, area);
1390 else
1391 ospf6_area_no_summary_unset(ospf6, area);
1392
1393 if (ospf6_check_and_set_router_abr(ospf6)) {
1394 ospf6_abr_defaults_to_stub(ospf6);
1395 ospf6_abr_nssa_type_7_defaults(ospf6);
1396 }
1397
1398 return CMD_SUCCESS;
1399 }
1400
1401 DEFPY(no_ospf6_area_nssa, no_ospf6_area_nssa_cmd,
1402 "no area <A.B.C.D|(0-4294967295)>$area_str nssa\
1403 [{\
1404 default-information-originate [{metric (0-16777214)|metric-type (1-2)}]\
1405 |no-summary\
1406 }]",
1407 NO_STR
1408 "OSPF6 area parameters\n"
1409 "OSPF6 area ID in IP address format\n"
1410 "OSPF6 area ID as a decimal value\n"
1411 "Configure OSPF6 area as nssa\n"
1412 "Originate Type 7 default into NSSA area\n"
1413 "OSPFv3 default metric\n"
1414 "OSPFv3 metric\n"
1415 "OSPFv3 metric type for default routes\n"
1416 "Set OSPFv3 External Type 1/2 metrics\n"
1417 "Do not inject inter-area routes into area\n")
1418 {
1419 struct ospf6_area *area;
1420
1421 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1422 OSPF6_CMD_AREA_GET(area_str, area, ospf6);
1423
1424 ospf6_area_nssa_unset(ospf6, area);
1425 ospf6_area_no_summary_unset(ospf6, area);
1426 ospf6_nssa_default_originate_unset(ospf6, area);
1427
1428 return CMD_SUCCESS;
1429 }
1430
1431
1432 void ospf6_area_init(void)
1433 {
1434 install_element(VIEW_NODE, &show_ipv6_ospf6_spf_tree_cmd);
1435 install_element(VIEW_NODE, &show_ipv6_ospf6_area_spf_tree_cmd);
1436 install_element(VIEW_NODE, &show_ipv6_ospf6_simulate_spf_tree_root_cmd);
1437
1438 install_element(OSPF6_NODE, &area_range_cmd);
1439 install_element(OSPF6_NODE, &no_area_range_cmd);
1440 install_element(OSPF6_NODE, &ospf6_area_stub_no_summary_cmd);
1441 install_element(OSPF6_NODE, &ospf6_area_stub_cmd);
1442 install_element(OSPF6_NODE, &no_ospf6_area_stub_no_summary_cmd);
1443 install_element(OSPF6_NODE, &no_ospf6_area_stub_cmd);
1444
1445
1446 install_element(OSPF6_NODE, &area_import_list_cmd);
1447 install_element(OSPF6_NODE, &no_area_import_list_cmd);
1448 install_element(OSPF6_NODE, &area_export_list_cmd);
1449 install_element(OSPF6_NODE, &no_area_export_list_cmd);
1450
1451 install_element(OSPF6_NODE, &area_filter_list_cmd);
1452 install_element(OSPF6_NODE, &no_area_filter_list_cmd);
1453
1454 /* "area nssa" commands. */
1455 install_element(OSPF6_NODE, &ospf6_area_nssa_cmd);
1456 install_element(OSPF6_NODE, &no_ospf6_area_nssa_cmd);
1457 }
1458
1459 void ospf6_area_interface_delete(struct ospf6_interface *oi)
1460 {
1461 struct ospf6_area *oa;
1462 struct listnode *node, *nnode;
1463 struct ospf6 *ospf6;
1464
1465 for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6)) {
1466 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa))
1467 if (listnode_lookup(oa->if_list, oi))
1468 listnode_delete(oa->if_list, oi);
1469 }
1470 }