]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_area.c
tools: improve explanation of 'wrap' options
[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));
cfc5d474 449 json_object_boolean_add(json_area, "areaIsNSSA",
450 IS_AREA_NSSA(oa));
451 if (IS_AREA_STUB(oa) || IS_AREA_NSSA(oa)) {
35a45dea 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);
0b11b56a
DS
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));
35a45dea 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);
d62a17ae 497
35a45dea 498 } else {
499
cfc5d474 500 if (!IS_AREA_STUB(oa) && !IS_AREA_NSSA(oa))
35a45dea 501 vty_out(vty, " Area %s\n", oa->name);
502 else {
503 if (oa->no_summary) {
cfc5d474 504 vty_out(vty, " Area %s[%s, No Summary]\n",
505 oa->name,
506 IS_AREA_STUB(oa) ? "Stub" : "NSSA");
35a45dea 507 } else {
cfc5d474 508 vty_out(vty, " Area %s[%s]\n", oa->name,
509 IS_AREA_STUB(oa) ? "Stub" : "NSSA");
35a45dea 510 }
d62a17ae 511 }
35a45dea 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) {
fb5a450f 523 vty_out(vty,
524 " SPF last executed %ld.%lds ago\n",
35a45dea 525 result / TIMER_SECOND_MICRO,
526 result % TIMER_SECOND_MICRO);
527 } else {
fb5a450f 528 vty_out(vty,
529 " SPF last executed %ldus ago\n",
35a45dea 530 result);
531 }
532 } else
533 vty_out(vty, "SPF has not been run\n");
ca1f4309 534 }
d62a17ae 535}
536
6452df09 537DEFUN (area_range,
538 area_range_cmd,
6de69f83 539 "area <A.B.C.D|(0-4294967295)> range X:X::X:X/M [<advertise|not-advertise|cost (0-16777215)>]",
6fbde29d
RW
540 "OSPF6 area parameters\n"
541 "OSPF6 area ID in IP address format\n"
542 "OSPF6 area ID as a decimal value\n"
6452df09 543 "Configured address range\n"
544 "Specify IPv6 prefix\n"
093d7a3a
DW
545 "Advertise\n"
546 "Do not advertise\n"
547 "User specified metric for this range\n"
548 "Advertised metric for this range\n")
6452df09 549{
d62a17ae 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;
848db95c 557 uint32_t cost;
d62a17ae 558
beadc736 559 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
560
561 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, oa, ospf6);
d62a17ae 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;
c3c0ac83 568 }
d62a17ae 569
570 range = ospf6_route_lookup(&prefix, oa->range_table);
571 if (range == NULL) {
22813fdb 572 range = ospf6_route_create(ospf6);
d62a17ae 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;
c3c0ac83 577 }
d62a17ae 578
848db95c
RW
579 /* default settings */
580 cost = OSPF_AREA_RANGE_COST_UNSPEC;
581 UNSET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
582
d62a17ae 583 if (argc > idx_type) {
848db95c 584 if (strmatch(argv[idx_type]->text, "not-advertise"))
d62a17ae 585 SET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
848db95c 586 else if (strmatch(argv[idx_type]->text, "cost"))
d62a17ae 587 cost = strtoul(argv[5]->arg, NULL, 10);
c3c0ac83 588 }
6452df09 589
d62a17ae 590 range->path.u.cost_config = cost;
c3c0ac83 591
d62a17ae 592 if (range->rnode == NULL) {
e285b70d 593 ospf6_route_add(range, oa->range_table);
d62a17ae 594 }
c3c0ac83 595
95b3f03d 596 if (ospf6_check_and_set_router_abr(ospf6)) {
d62a17ae 597 /* Redo summaries if required */
598 ospf6_abr_prefix_resummarize(ospf6);
599 }
86f9e5a7 600
d62a17ae 601 return CMD_SUCCESS;
6452df09 602}
603
6452df09 604DEFUN (no_area_range,
605 no_area_range_cmd,
3a2d747c 606 "no area <A.B.C.D|(0-4294967295)> range X:X::X:X/M [<advertise|not-advertise|cost (0-16777215)>]",
813d4307 607 NO_STR
6fbde29d 608 "OSPF6 area parameters\n"
3a2d747c
QY
609 "OSPF6 area ID in IP address format\n"
610 "OSPF6 area ID as a decimal value\n"
6452df09 611 "Configured address range\n"
3a2d747c
QY
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")
6452df09 617{
d62a17ae 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;
6452df09 624
beadc736 625 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
626
627 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, oa, ospf6);
d62a17ae 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
95b3f03d 642 if (ospf6_check_and_set_router_abr(oa->ospf6)) {
d62a17ae 643 /* Blow away the aggregated LSA and route */
644 SET_FLAG(range->flag, OSPF6_ROUTE_REMOVE);
645
646 /* Redo summaries if required */
beadc736 647 for (route = ospf6_route_head(oa->ospf6->route_table); route;
d62a17ae 648 route = ospf6_route_next(route))
beadc736 649 ospf6_abr_originate_summary(route, oa->ospf6);
d62a17ae 650
651 /* purge the old aggregated summary LSA */
beadc736 652 ospf6_abr_originate_summary(range, oa->ospf6);
d62a17ae 653 }
e285b70d 654 ospf6_route_remove(range, oa->range_table);
d62a17ae 655
656 return CMD_SUCCESS;
657}
658
beadc736 659void ospf6_area_config_write(struct vty *vty, struct ospf6 *ospf6)
d62a17ae 660{
661 struct listnode *node;
662 struct ospf6_area *oa;
663 struct ospf6_route *range;
d62a17ae 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)) {
2dbe669b
DA
668 vty_out(vty, " area %s range %pFX", oa->name,
669 &range->prefix);
d62a17ae 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 }
8a60820f
RW
691 if (IS_AREA_NSSA(oa)) {
692 vty_out(vty, " area %s nssa", oa->name);
6735622c
RW
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 }
8a60820f
RW
704 if (oa->no_summary)
705 vty_out(vty, " no-summary");
706 vty_out(vty, "\n");
707 }
3c77bc80
RW
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 }
d62a17ae 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));
ca1f4309 736 }
6452df09 737}
738
34956b31 739DEFUN (area_filter_list,
740 area_filter_list_cmd,
23599e77 741 "area <A.B.C.D|(0-4294967295)> filter-list prefix PREFIXLIST_NAME <in|out>",
b2d4d039
RW
742 "OSPF6 area parameters\n"
743 "OSPF6 area ID in IP address format\n"
dd3ff9d8 744 "OSPF6 area ID as a decimal value\n"
b2d4d039
RW
745 "Filter networks between OSPF6 areas\n"
746 "Filter prefixes between OSPF6 areas\n"
34956b31 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{
d62a17ae 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
beadc736 758 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
759
760 OSPF6_CMD_AREA_GET(areaid, area, ospf6);
d62a17ae 761
762 plist = prefix_list_lookup(AFI_IP6, plistname);
763 if (strmatch(inout, "in")) {
764 PREFIX_LIST_IN(area) = plist;
427f8e61 765 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
996c9314
LB
766 PREFIX_NAME_IN(area) =
767 XSTRDUP(MTYPE_OSPF6_PLISTNAME, plistname);
d62a17ae 768 } else {
769 PREFIX_LIST_OUT(area) = plist;
427f8e61 770 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
996c9314
LB
771 PREFIX_NAME_OUT(area) =
772 XSTRDUP(MTYPE_OSPF6_PLISTNAME, plistname);
d62a17ae 773 }
774
f4f0098c
RW
775 /* Redo summaries if required */
776 if (ospf6_check_and_set_router_abr(area->ospf6))
777 ospf6_schedule_abr_task(ospf6);
778
d62a17ae 779 return CMD_SUCCESS;
34956b31 780}
d62a17ae 781
34956b31 782DEFUN (no_area_filter_list,
783 no_area_filter_list_cmd,
23599e77 784 "no area <A.B.C.D|(0-4294967295)> filter-list prefix PREFIXLIST_NAME <in|out>",
34956b31 785 NO_STR
b2d4d039
RW
786 "OSPF6 area parameters\n"
787 "OSPF6 area ID in IP address format\n"
dd3ff9d8 788 "OSPF6 area ID as a decimal value\n"
b2d4d039
RW
789 "Filter networks between OSPF6 areas\n"
790 "Filter prefixes between OSPF6 areas\n"
34956b31 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{
d62a17ae 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
beadc736 801 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
802 OSPF6_CMD_AREA_GET(areaid, area, ospf6);
d62a17ae 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;
427f8e61 810 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
d62a17ae 811 } else {
812 if (PREFIX_NAME_OUT(area))
813 if (!strmatch(PREFIX_NAME_OUT(area), plistname))
814 return CMD_SUCCESS;
815
427f8e61 816 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
f6c5f2e0 817 PREFIX_LIST_OUT(area) = NULL;
d62a17ae 818 }
819
f4f0098c
RW
820 /* Redo summaries if required */
821 if (ospf6_check_and_set_router_abr(area->ospf6))
822 ospf6_schedule_abr_task(ospf6);
823
d62a17ae 824 return CMD_SUCCESS;
34956b31 825}
826
f6c5f2e0 827void 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)) {
f4f0098c
RW
834 bool update = false;
835
f6c5f2e0 836 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa)) {
837 if (IMPORT_NAME(oa)
f4f0098c
RW
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 }
f6c5f2e0 843
844 if (EXPORT_NAME(oa)
f4f0098c
RW
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 }
f6c5f2e0 850 }
f4f0098c
RW
851
852 if (update && ospf6_check_and_set_router_abr(ospf6))
853 ospf6_schedule_abr_task(ospf6);
f6c5f2e0 854 }
855}
856
f4f0098c 857void ospf6_plist_update(struct prefix_list *plist)
427f8e61 858{
beadc736 859 struct listnode *node, *nnode;
427f8e61
DL
860 struct ospf6_area *oa;
861 struct listnode *n;
862 const char *name = prefix_list_name(plist);
beadc736 863 struct ospf6 *ospf6 = NULL;
864
f4f0098c
RW
865 if (prefix_list_afi(plist) != AFI_IP6)
866 return;
867
beadc736 868 for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6)) {
f4f0098c
RW
869 bool update = false;
870
beadc736 871 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa)) {
872 if (PREFIX_NAME_IN(oa)
f6c5f2e0 873 && !strcmp(PREFIX_NAME_IN(oa), name)) {
f4f0098c
RW
874 PREFIX_LIST_IN(oa) = prefix_list_lookup(
875 AFI_IP6, PREFIX_NAME_IN(oa));
876 update = true;
f6c5f2e0 877 }
beadc736 878 if (PREFIX_NAME_OUT(oa)
f6c5f2e0 879 && !strcmp(PREFIX_NAME_OUT(oa), name)) {
f4f0098c
RW
880 PREFIX_LIST_OUT(oa) = prefix_list_lookup(
881 AFI_IP6, PREFIX_NAME_OUT(oa));
882 update = true;
f6c5f2e0 883 }
beadc736 884 }
f4f0098c
RW
885
886 if (update && ospf6_check_and_set_router_abr(ospf6))
887 ospf6_schedule_abr_task(ospf6);
427f8e61
DL
888 }
889}
890
34956b31 891DEFUN (area_import_list,
892 area_import_list_cmd,
c60dec36 893 "area <A.B.C.D|(0-4294967295)> import-list ACCESSLIST6_NAME",
b2d4d039
RW
894 "OSPF6 area parameters\n"
895 "OSPF6 area ID in IP address format\n"
dd3ff9d8 896 "OSPF6 area ID as a decimal value\n"
34956b31 897 "Set the filter for networks from other areas announced to the specified one\n"
c60dec36 898 "Name of the access-list\n")
34956b31 899{
d62a17ae 900 int idx_ipv4 = 1;
901 int idx_name = 3;
902 struct ospf6_area *area;
903 struct access_list *list;
34956b31 904
beadc736 905 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
906
907 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area, ospf6);
34956b31 908
d62a17ae 909 list = access_list_lookup(AFI_IP6, argv[idx_name]->arg);
34956b31 910
d62a17ae 911 IMPORT_LIST(area) = list;
34956b31 912
d62a17ae 913 if (IMPORT_NAME(area))
914 free(IMPORT_NAME(area));
34956b31 915
d62a17ae 916 IMPORT_NAME(area) = strdup(argv[idx_name]->arg);
f4f0098c
RW
917 if (ospf6_check_and_set_router_abr(area->ospf6))
918 ospf6_schedule_abr_task(ospf6);
34956b31 919
d62a17ae 920 return CMD_SUCCESS;
34956b31 921}
922
923DEFUN (no_area_import_list,
924 no_area_import_list_cmd,
c60dec36 925 "no area <A.B.C.D|(0-4294967295)> import-list ACCESSLIST6_NAME",
6fbde29d 926 NO_STR
b2d4d039
RW
927 "OSPF6 area parameters\n"
928 "OSPF6 area ID in IP address format\n"
dd3ff9d8 929 "OSPF6 area ID as a decimal value\n"
34956b31 930 "Unset the filter for networks announced to other areas\n"
6fbde29d 931 "Name of the access-list\n")
34956b31 932{
d62a17ae 933 int idx_ipv4 = 2;
934 struct ospf6_area *area;
34956b31 935
beadc736 936 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
937
938 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area, ospf6);
34956b31 939
f4f0098c 940 IMPORT_LIST(area) = NULL;
34956b31 941
d62a17ae 942 if (IMPORT_NAME(area))
943 free(IMPORT_NAME(area));
34956b31 944
d62a17ae 945 IMPORT_NAME(area) = NULL;
f4f0098c
RW
946 if (ospf6_check_and_set_router_abr(area->ospf6))
947 ospf6_schedule_abr_task(ospf6);
34956b31 948
d62a17ae 949 return CMD_SUCCESS;
34956b31 950}
951
952DEFUN (area_export_list,
953 area_export_list_cmd,
c60dec36 954 "area <A.B.C.D|(0-4294967295)> export-list ACCESSLIST6_NAME",
b2d4d039
RW
955 "OSPF6 area parameters\n"
956 "OSPF6 area ID in IP address format\n"
dd3ff9d8 957 "OSPF6 area ID as a decimal value\n"
34956b31 958 "Set the filter for networks announced to other areas\n"
c60dec36 959 "Name of the access-list\n")
34956b31 960{
d62a17ae 961 int idx_ipv4 = 1;
962 int idx_name = 3;
963 struct ospf6_area *area;
964 struct access_list *list;
34956b31 965
beadc736 966 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
967
968 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area, ospf6);
34956b31 969
d62a17ae 970 list = access_list_lookup(AFI_IP6, argv[idx_name]->arg);
34956b31 971
d62a17ae 972 EXPORT_LIST(area) = list;
34956b31 973
d62a17ae 974 if (EXPORT_NAME(area))
975 free(EXPORT_NAME(area));
34956b31 976
d62a17ae 977 EXPORT_NAME(area) = strdup(argv[idx_name]->arg);
f6c5f2e0 978
979 /* Redo summaries if required */
f4f0098c
RW
980 if (ospf6_check_and_set_router_abr(area->ospf6))
981 ospf6_schedule_abr_task(ospf6);
34956b31 982
d62a17ae 983 return CMD_SUCCESS;
34956b31 984}
985
986DEFUN (no_area_export_list,
987 no_area_export_list_cmd,
c60dec36 988 "no area <A.B.C.D|(0-4294967295)> export-list ACCESSLIST6_NAME",
6fbde29d 989 NO_STR
b2d4d039
RW
990 "OSPF6 area parameters\n"
991 "OSPF6 area ID in IP address format\n"
dd3ff9d8 992 "OSPF6 area ID as a decimal value\n"
34956b31 993 "Unset the filter for networks announced to other areas\n"
994 "Name of the access-list\n")
995{
d62a17ae 996 int idx_ipv4 = 2;
997 struct ospf6_area *area;
34956b31 998
beadc736 999 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1000
1001 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area, ospf6);
34956b31 1002
f4f0098c 1003 EXPORT_LIST(area) = NULL;
34956b31 1004
d62a17ae 1005 if (EXPORT_NAME(area))
1006 free(EXPORT_NAME(area));
34956b31 1007
d62a17ae 1008 EXPORT_NAME(area) = NULL;
f4f0098c
RW
1009 if (ospf6_check_and_set_router_abr(area->ospf6))
1010 ospf6_schedule_abr_task(ospf6);
34956b31 1011
d62a17ae 1012 return CMD_SUCCESS;
34956b31 1013}
1014
d48ef099 1015static int ipv6_ospf6_spf_tree_common(struct vty *vty, struct ospf6 *ospf6,
1016 bool uj)
718e3744 1017{
d62a17ae 1018 struct listnode *node;
1019 struct ospf6_area *oa;
d48ef099 1020 struct prefix prefix;
d62a17ae 1021 struct ospf6_vertex *root;
1022 struct ospf6_route *route;
305b639b
YR
1023 json_object *json = NULL;
1024 json_object *json_area = NULL;
1025 json_object *json_head = NULL;
305b639b
YR
1026
1027 if (uj)
1028 json = json_object_new_object();
d62a17ae 1029 ospf6_linkstate_prefix(ospf6->router_id, htonl(0), &prefix);
d62a17ae 1030 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
305b639b
YR
1031 if (uj) {
1032 json_area = json_object_new_object();
1033 json_head = json_object_new_object();
1034 }
d62a17ae 1035 route = ospf6_route_lookup(&prefix, oa->spf_table);
1036 if (route == NULL) {
305b639b
YR
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);
d62a17ae 1047 continue;
1048 }
1049 root = (struct ospf6_vertex *)route->route_option;
305b639b
YR
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
c48349e3 1059 if (uj)
5a6c232b 1060 vty_json(vty, json);
d62a17ae 1061
1062 return CMD_SUCCESS;
508e53e2 1063}
1064
d48ef099 1065DEFUN(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)
508e53e2 1071{
d48ef099 1072 struct listnode *node;
beadc736 1073 struct ospf6 *ospf6;
d48ef099 1074 const char *vrf_name = NULL;
1075 bool all_vrf = false;
1076 int idx_vrf = 0;
1077 bool uj = use_json(argc, argv);
beadc736 1078
d48ef099 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
d6b901ac 1089 OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
1090
d48ef099 1091 return CMD_SUCCESS;
1092}
1093
1094static 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{
d62a17ae 1099
d48ef099 1100 struct ospf6_area *oa;
1101 struct prefix prefix;
1102 struct ospf6_vertex *root;
1103 struct ospf6_route *route;
d62a17ae 1104
1105 ospf6_linkstate_prefix(ospf6->router_id, htonl(0), &prefix);
1106
d62a17ae 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;
305b639b 1120 ospf6_spf_display_subtree(vty, "", 0, root, NULL, false);
d62a17ae 1121
1122 return CMD_SUCCESS;
718e3744 1123}
1124
d48ef099 1125DEFUN(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")
508e53e2 1131{
d48ef099 1132 int idx_ipv4 = 4;
d7c0a89a 1133 uint32_t area_id;
d48ef099 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
d48ef099 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
d6b901ac 1158 OSPF6_CMD_CHECK_VRF(false, all_vrf, ospf6);
1159
d48ef099 1160 return CMD_SUCCESS;
1161}
1162
1163static int
1164show_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{
d62a17ae 1169 struct ospf6_area *oa;
1170 struct ospf6_vertex *root;
1171 struct ospf6_route *route;
d62a17ae 1172 struct ospf6_route_table *spf_table;
1173 unsigned char tmp_debug_ospf6_spf = 0;
d62a17ae 1174
d62a17ae 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) {
e285b70d
IR
1191 ospf6_spf_table_finish(spf_table);
1192 ospf6_route_table_delete(spf_table);
d62a17ae 1193 return CMD_SUCCESS;
1194 }
1195 root = (struct ospf6_vertex *)route->route_option;
305b639b 1196 ospf6_spf_display_subtree(vty, "", 0, root, NULL, false);
d62a17ae 1197
e285b70d
IR
1198 ospf6_spf_table_finish(spf_table);
1199 ospf6_route_table_delete(spf_table);
d62a17ae 1200
1201 return CMD_SUCCESS;
508e53e2 1202}
1203
d48ef099 1204DEFUN(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
d48ef099 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
d6b901ac 1248 OSPF6_CMD_CHECK_VRF(false, all_vrf, ospf6);
1249
d48ef099 1250 return CMD_SUCCESS;
1251}
1252
ca1f4309
DS
1253DEFUN (ospf6_area_stub,
1254 ospf6_area_stub_cmd,
6147e2c6 1255 "area <A.B.C.D|(0-4294967295)> stub",
ca1f4309
DS
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{
d62a17ae 1261 int idx_ipv4_number = 1;
1262 struct ospf6_area *area;
ca1f4309 1263
beadc736 1264 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1265
1266 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area, ospf6);
ca1f4309 1267
d62a17ae 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 }
ca1f4309 1273
d62a17ae 1274 ospf6_area_no_summary_unset(ospf6, area);
ca1f4309 1275
d62a17ae 1276 return CMD_SUCCESS;
ca1f4309
DS
1277}
1278
1279DEFUN (ospf6_area_stub_no_summary,
1280 ospf6_area_stub_no_summary_cmd,
6147e2c6 1281 "area <A.B.C.D|(0-4294967295)> stub no-summary",
ca1f4309
DS
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{
d62a17ae 1288 int idx_ipv4_number = 1;
1289 struct ospf6_area *area;
ca1f4309 1290
beadc736 1291 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1292
1293 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area, ospf6);
ca1f4309 1294
d62a17ae 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 }
ca1f4309 1300
d62a17ae 1301 ospf6_area_no_summary_set(ospf6, area);
ca1f4309 1302
d62a17ae 1303 return CMD_SUCCESS;
ca1f4309
DS
1304}
1305
1306DEFUN (no_ospf6_area_stub,
1307 no_ospf6_area_stub_cmd,
6147e2c6 1308 "no area <A.B.C.D|(0-4294967295)> stub",
ca1f4309
DS
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{
d62a17ae 1315 int idx_ipv4_number = 2;
1316 struct ospf6_area *area;
ca1f4309 1317
beadc736 1318 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1319
1320 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area, ospf6);
ca1f4309 1321
d62a17ae 1322 ospf6_area_stub_unset(ospf6, area);
1323 ospf6_area_no_summary_unset(ospf6, area);
ca1f4309 1324
d62a17ae 1325 return CMD_SUCCESS;
ca1f4309
DS
1326}
1327
1328DEFUN (no_ospf6_area_stub_no_summary,
1329 no_ospf6_area_stub_no_summary_cmd,
6147e2c6 1330 "no area <A.B.C.D|(0-4294967295)> stub no-summary",
ca1f4309
DS
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{
d62a17ae 1338 int idx_ipv4_number = 2;
1339 struct ospf6_area *area;
ca1f4309 1340
beadc736 1341 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1342
1343 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area, ospf6);
ca1f4309 1344
d62a17ae 1345 ospf6_area_stub_unset(ospf6, area);
1346 ospf6_area_no_summary_unset(ospf6, area);
ca1f4309 1347
d62a17ae 1348 return CMD_SUCCESS;
ca1f4309
DS
1349}
1350
8a60820f 1351DEFPY(ospf6_area_nssa, ospf6_area_nssa_cmd,
6735622c
RW
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 }]",
ad500b22
K
1357 "OSPF6 area parameters\n"
1358 "OSPF6 area ID in IP address format\n"
1359 "OSPF6 area ID as a decimal value\n"
8a60820f 1360 "Configure OSPF6 area as nssa\n"
6735622c
RW
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"
8a60820f 1366 "Do not inject inter-area routes into area\n")
ad500b22 1367{
ad500b22
K
1368 struct ospf6_area *area;
1369
1370 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
8a60820f 1371 OSPF6_CMD_AREA_GET(area_str, area, ospf6);
ad500b22
K
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
6735622c
RW
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
8a60820f
RW
1388 if (no_summary)
1389 ospf6_area_no_summary_set(ospf6, area);
1390 else
1391 ospf6_area_no_summary_unset(ospf6, area);
6735622c
RW
1392
1393 if (ospf6_check_and_set_router_abr(ospf6)) {
8a60820f 1394 ospf6_abr_defaults_to_stub(ospf6);
6735622c
RW
1395 ospf6_abr_nssa_type_7_defaults(ospf6);
1396 }
0c293b92 1397
ad500b22
K
1398 return CMD_SUCCESS;
1399}
1400
8a60820f 1401DEFPY(no_ospf6_area_nssa, no_ospf6_area_nssa_cmd,
6735622c
RW
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 }]",
ad500b22
K
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"
8a60820f 1411 "Configure OSPF6 area as nssa\n"
6735622c
RW
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"
8a60820f 1417 "Do not inject inter-area routes into area\n")
ad500b22 1418{
ad500b22
K
1419 struct ospf6_area *area;
1420
1421 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
8a60820f 1422 OSPF6_CMD_AREA_GET(area_str, area, ospf6);
ad500b22
K
1423
1424 ospf6_area_nssa_unset(ospf6, area);
8a60820f 1425 ospf6_area_no_summary_unset(ospf6, area);
6735622c 1426 ospf6_nssa_default_originate_unset(ospf6, area);
ad500b22
K
1427
1428 return CMD_SUCCESS;
1429}
1430
1431
d62a17ae 1432void ospf6_area_init(void)
508e53e2 1433{
d62a17ae 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);
ca1f4309 1437
d62a17ae 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);
34956b31 1444
34956b31 1445
d62a17ae 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);
34956b31 1450
d62a17ae 1451 install_element(OSPF6_NODE, &area_filter_list_cmd);
1452 install_element(OSPF6_NODE, &no_area_filter_list_cmd);
ad500b22
K
1453
1454 /* "area nssa" commands. */
1455 install_element(OSPF6_NODE, &ospf6_area_nssa_cmd);
1456 install_element(OSPF6_NODE, &no_ospf6_area_nssa_cmd);
508e53e2 1457}
22b982df
PG
1458
1459void ospf6_area_interface_delete(struct ospf6_interface *oi)
1460{
1461 struct ospf6_area *oa;
1462 struct listnode *node, *nnode;
beadc736 1463 struct ospf6 *ospf6;
22b982df 1464
d48ef099 1465 for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6)) {
beadc736 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);
d48ef099 1469 }
22b982df 1470}