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