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