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