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