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