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