]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_area.c
ospf6d: fix lookup of translated Type-5 LSA
[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;
d62a17ae 309 oa->summary_prefix = OSPF6_ROUTE_TABLE_CREATE(AREA, SUMMARY_PREFIXES);
310 oa->summary_prefix->scope = oa;
311 oa->summary_router = OSPF6_ROUTE_TABLE_CREATE(AREA, SUMMARY_ROUTERS);
312 oa->summary_router->scope = oa;
9a703f8d 313 oa->router_lsa_size_limit = 1024 + 256;
d62a17ae 314
315 /* set default options */
316 if (CHECK_FLAG(o->flag, OSPF6_STUB_ROUTER)) {
317 OSPF6_OPT_CLEAR(oa->options, OSPF6_OPT_V6);
318 OSPF6_OPT_CLEAR(oa->options, OSPF6_OPT_R);
319 } else {
320 OSPF6_OPT_SET(oa->options, OSPF6_OPT_V6);
321 OSPF6_OPT_SET(oa->options, OSPF6_OPT_R);
322 }
323
324 OSPF6_OPT_SET(oa->options, OSPF6_OPT_E);
325
326 SET_FLAG(oa->flag, OSPF6_AREA_ACTIVE);
327 SET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
328
329 oa->ospf6 = o;
330 listnode_add_sort(o->area_list, oa);
331
332 if (area_id == OSPF_AREA_BACKBONE) {
333 o->backbone = oa;
334 }
335
336 return oa;
718e3744 337}
338
d62a17ae 339void ospf6_area_delete(struct ospf6_area *oa)
718e3744 340{
d62a17ae 341 struct listnode *n;
342 struct ospf6_interface *oi;
718e3744 343
d62a17ae 344 /* The ospf6_interface structs store configuration
345 * information which should not be lost/reset when
346 * deleting an area.
347 * So just detach the interface from the area and
348 * keep it around. */
349 for (ALL_LIST_ELEMENTS_RO(oa->if_list, n, oi))
350 oi->area = NULL;
d9628728 351
6a154c88 352 list_delete(&oa->if_list);
718e3744 353
d62a17ae 354 ospf6_lsdb_delete(oa->lsdb);
355 ospf6_lsdb_delete(oa->lsdb_self);
da086a3b 356 ospf6_lsdb_delete(oa->temp_router_lsa_lsdb);
6452df09 357
e285b70d
IR
358 ospf6_spf_table_finish(oa->spf_table);
359 ospf6_route_table_delete(oa->spf_table);
360 ospf6_route_table_delete(oa->route_table);
508e53e2 361
e285b70d
IR
362 ospf6_route_table_delete(oa->range_table);
363 ospf6_route_table_delete(oa->summary_prefix);
364 ospf6_route_table_delete(oa->summary_router);
508e53e2 365
d62a17ae 366 listnode_delete(oa->ospf6->area_list, oa);
367 oa->ospf6 = NULL;
508e53e2 368
d62a17ae 369 /* free area */
370 XFREE(MTYPE_OSPF6_AREA, oa);
508e53e2 371}
372
beadc736 373struct ospf6_area *ospf6_area_lookup_by_area_id(uint32_t area_id)
374{
375 struct ospf6_area *oa;
376 struct listnode *n, *node, *nnode;
377 struct ospf6 *ospf6;
378
379 for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6)) {
380 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa))
381 if (oa->area_id == area_id)
382 return oa;
383 }
384 return (struct ospf6_area *)NULL;
385}
386
d7c0a89a 387struct ospf6_area *ospf6_area_lookup(uint32_t area_id, struct ospf6 *ospf6)
718e3744 388{
d62a17ae 389 struct ospf6_area *oa;
390 struct listnode *n;
718e3744 391
d62a17ae 392 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa))
393 if (oa->area_id == area_id)
394 return oa;
718e3744 395
d62a17ae 396 return (struct ospf6_area *)NULL;
718e3744 397}
398
d62a17ae 399void ospf6_area_enable(struct ospf6_area *oa)
718e3744 400{
d62a17ae 401 struct listnode *node, *nnode;
402 struct ospf6_interface *oi;
718e3744 403
d62a17ae 404 SET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
508e53e2 405
d62a17ae 406 for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi))
407 ospf6_interface_enable(oi);
408 ospf6_abr_enable_area(oa);
718e3744 409}
410
d62a17ae 411void ospf6_area_disable(struct ospf6_area *oa)
718e3744 412{
d62a17ae 413 struct listnode *node, *nnode;
414 struct ospf6_interface *oi;
718e3744 415
d62a17ae 416 UNSET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
718e3744 417
d62a17ae 418 for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi))
419 ospf6_interface_disable(oi);
d9628728 420
d62a17ae 421 ospf6_abr_disable_area(oa);
422 ospf6_lsdb_remove_all(oa->lsdb);
423 ospf6_lsdb_remove_all(oa->lsdb_self);
d9628728 424
e285b70d
IR
425 ospf6_spf_table_finish(oa->spf_table);
426 ospf6_route_remove_all(oa->route_table);
d9628728 427
d62a17ae 428 THREAD_OFF(oa->thread_router_lsa);
429 THREAD_OFF(oa->thread_intra_prefix_lsa);
508e53e2 430}
718e3744 431
6b0655a2 432
35a45dea 433void ospf6_area_show(struct vty *vty, struct ospf6_area *oa,
434 json_object *json_areas, bool use_json)
508e53e2 435{
d62a17ae 436 struct listnode *i;
437 struct ospf6_interface *oi;
438 unsigned long result;
35a45dea 439 json_object *json_area;
440 json_object *array_interfaces;
441
442 if (use_json) {
443 json_area = json_object_new_object();
444 json_object_boolean_add(json_area, "areaIsStub",
445 IS_AREA_STUB(oa));
446 if (IS_AREA_STUB(oa)) {
447 json_object_boolean_add(json_area, "areaNoSummary",
448 oa->no_summary);
449 }
450
451 json_object_int_add(json_area, "numberOfAreaScopedLsa",
452 oa->lsdb->count);
453
454 /* Interfaces Attached */
455 array_interfaces = json_object_new_array();
456 for (ALL_LIST_ELEMENTS_RO(oa->if_list, i, oi))
457 json_object_array_add(
458 array_interfaces,
459 json_object_new_string(oi->interface->name));
460
461 json_object_object_add(json_area, "interfacesAttachedToArea",
462 array_interfaces);
463
464 if (oa->ts_spf.tv_sec || oa->ts_spf.tv_usec) {
465 json_object_boolean_true_add(json_area, "spfHasRun");
466 result = monotime_since(&oa->ts_spf, NULL);
467 if (result / TIMER_SECOND_MICRO > 0) {
468 json_object_int_add(
469 json_area, "spfLastExecutedSecs",
470 result / TIMER_SECOND_MICRO);
471
472 json_object_int_add(
473 json_area, "spfLastExecutedMicroSecs",
474 result % TIMER_SECOND_MICRO);
475 } else {
476 json_object_int_add(json_area,
477 "spfLastExecutedSecs", 0);
478 json_object_int_add(json_area,
479 "spfLastExecutedMicroSecs",
480 result);
481 }
482 } else
483 json_object_boolean_false_add(json_area, "spfHasRun");
484
485
486 json_object_object_add(json_areas, oa->name, json_area);
d62a17ae 487
35a45dea 488 } else {
489
490 if (!IS_AREA_STUB(oa))
491 vty_out(vty, " Area %s\n", oa->name);
492 else {
493 if (oa->no_summary) {
494 vty_out(vty, " Area %s[Stub, No Summary]\n",
495 oa->name);
496 } else {
497 vty_out(vty, " Area %s[Stub]\n", oa->name);
498 }
d62a17ae 499 }
35a45dea 500 vty_out(vty, " Number of Area scoped LSAs is %u\n",
501 oa->lsdb->count);
502
503 vty_out(vty, " Interface attached to this area:");
504 for (ALL_LIST_ELEMENTS_RO(oa->if_list, i, oi))
505 vty_out(vty, " %s", oi->interface->name);
506 vty_out(vty, "\n");
507
508 if (oa->ts_spf.tv_sec || oa->ts_spf.tv_usec) {
509 result = monotime_since(&oa->ts_spf, NULL);
510 if (result / TIMER_SECOND_MICRO > 0) {
511 vty_out(vty, "SPF last executed %ld.%lds ago\n",
512 result / TIMER_SECOND_MICRO,
513 result % TIMER_SECOND_MICRO);
514 } else {
515 vty_out(vty, "SPF last executed %ldus ago\n",
516 result);
517 }
518 } else
519 vty_out(vty, "SPF has not been run\n");
ca1f4309 520 }
d62a17ae 521}
522
6452df09 523DEFUN (area_range,
524 area_range_cmd,
6de69f83 525 "area <A.B.C.D|(0-4294967295)> range X:X::X:X/M [<advertise|not-advertise|cost (0-16777215)>]",
6fbde29d
RW
526 "OSPF6 area parameters\n"
527 "OSPF6 area ID in IP address format\n"
528 "OSPF6 area ID as a decimal value\n"
6452df09 529 "Configured address range\n"
530 "Specify IPv6 prefix\n"
093d7a3a
DW
531 "Advertise\n"
532 "Do not advertise\n"
533 "User specified metric for this range\n"
534 "Advertised metric for this range\n")
6452df09 535{
d62a17ae 536 int idx_ipv4 = 1;
537 int idx_ipv6_prefixlen = 3;
538 int idx_type = 4;
539 int ret;
540 struct ospf6_area *oa;
541 struct prefix prefix;
542 struct ospf6_route *range;
848db95c 543 uint32_t cost;
d62a17ae 544
beadc736 545 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
546
547 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, oa, ospf6);
d62a17ae 548
549 ret = str2prefix(argv[idx_ipv6_prefixlen]->arg, &prefix);
550 if (ret != 1 || prefix.family != AF_INET6) {
551 vty_out(vty, "Malformed argument: %s\n",
552 argv[idx_ipv6_prefixlen]->arg);
553 return CMD_SUCCESS;
c3c0ac83 554 }
d62a17ae 555
556 range = ospf6_route_lookup(&prefix, oa->range_table);
557 if (range == NULL) {
22813fdb 558 range = ospf6_route_create(ospf6);
d62a17ae 559 range->type = OSPF6_DEST_TYPE_RANGE;
560 range->prefix = prefix;
561 range->path.area_id = oa->area_id;
562 range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC;
c3c0ac83 563 }
d62a17ae 564
848db95c
RW
565 /* default settings */
566 cost = OSPF_AREA_RANGE_COST_UNSPEC;
567 UNSET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
568
d62a17ae 569 if (argc > idx_type) {
848db95c 570 if (strmatch(argv[idx_type]->text, "not-advertise"))
d62a17ae 571 SET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
848db95c 572 else if (strmatch(argv[idx_type]->text, "cost"))
d62a17ae 573 cost = strtoul(argv[5]->arg, NULL, 10);
c3c0ac83 574 }
6452df09 575
d62a17ae 576 range->path.u.cost_config = cost;
c3c0ac83 577
d62a17ae 578 if (range->rnode == NULL) {
e285b70d 579 ospf6_route_add(range, oa->range_table);
d62a17ae 580 }
c3c0ac83 581
95b3f03d 582 if (ospf6_check_and_set_router_abr(ospf6)) {
d62a17ae 583 /* Redo summaries if required */
584 ospf6_abr_prefix_resummarize(ospf6);
585 }
86f9e5a7 586
d62a17ae 587 return CMD_SUCCESS;
6452df09 588}
589
6452df09 590DEFUN (no_area_range,
591 no_area_range_cmd,
3a2d747c 592 "no area <A.B.C.D|(0-4294967295)> range X:X::X:X/M [<advertise|not-advertise|cost (0-16777215)>]",
813d4307 593 NO_STR
6fbde29d 594 "OSPF6 area parameters\n"
3a2d747c
QY
595 "OSPF6 area ID in IP address format\n"
596 "OSPF6 area ID as a decimal value\n"
6452df09 597 "Configured address range\n"
3a2d747c
QY
598 "Specify IPv6 prefix\n"
599 "Advertise\n"
600 "Do not advertise\n"
601 "User specified metric for this range\n"
602 "Advertised metric for this range\n")
6452df09 603{
d62a17ae 604 int idx_ipv4 = 2;
605 int idx_ipv6 = 4;
606 int ret;
607 struct ospf6_area *oa;
608 struct prefix prefix;
609 struct ospf6_route *range, *route;
6452df09 610
beadc736 611 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
612
613 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, oa, ospf6);
d62a17ae 614
615 ret = str2prefix(argv[idx_ipv6]->arg, &prefix);
616 if (ret != 1 || prefix.family != AF_INET6) {
617 vty_out(vty, "Malformed argument: %s\n", argv[idx_ipv6]->arg);
618 return CMD_SUCCESS;
619 }
620
621 range = ospf6_route_lookup(&prefix, oa->range_table);
622 if (range == NULL) {
623 vty_out(vty, "Range %s does not exists.\n",
624 argv[idx_ipv6]->arg);
625 return CMD_SUCCESS;
626 }
627
95b3f03d 628 if (ospf6_check_and_set_router_abr(oa->ospf6)) {
d62a17ae 629 /* Blow away the aggregated LSA and route */
630 SET_FLAG(range->flag, OSPF6_ROUTE_REMOVE);
631
632 /* Redo summaries if required */
beadc736 633 for (route = ospf6_route_head(oa->ospf6->route_table); route;
d62a17ae 634 route = ospf6_route_next(route))
beadc736 635 ospf6_abr_originate_summary(route, oa->ospf6);
d62a17ae 636
637 /* purge the old aggregated summary LSA */
beadc736 638 ospf6_abr_originate_summary(range, oa->ospf6);
d62a17ae 639 }
e285b70d 640 ospf6_route_remove(range, oa->range_table);
d62a17ae 641
642 return CMD_SUCCESS;
643}
644
beadc736 645void ospf6_area_config_write(struct vty *vty, struct ospf6 *ospf6)
d62a17ae 646{
647 struct listnode *node;
648 struct ospf6_area *oa;
649 struct ospf6_route *range;
d62a17ae 650
651 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
652 for (range = ospf6_route_head(oa->range_table); range;
653 range = ospf6_route_next(range)) {
2dbe669b
DA
654 vty_out(vty, " area %s range %pFX", oa->name,
655 &range->prefix);
d62a17ae 656
657 if (CHECK_FLAG(range->flag,
658 OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
659 vty_out(vty, " not-advertise");
660 } else {
661 // "advertise" is the default so we do not
662 // display it
663 if (range->path.u.cost_config
664 != OSPF_AREA_RANGE_COST_UNSPEC)
665 vty_out(vty, " cost %d",
666 range->path.u.cost_config);
667 }
668 vty_out(vty, "\n");
669 }
670 if (IS_AREA_STUB(oa)) {
671 if (oa->no_summary)
672 vty_out(vty, " area %s stub no-summary\n",
673 oa->name);
674 else
675 vty_out(vty, " area %s stub\n", oa->name);
676 }
8a60820f
RW
677 if (IS_AREA_NSSA(oa)) {
678 vty_out(vty, " area %s nssa", oa->name);
6735622c
RW
679 if (oa->nssa_default_originate.enabled) {
680 vty_out(vty, " default-information-originate");
681 if (oa->nssa_default_originate.metric_value
682 != -1)
683 vty_out(vty, " metric %d",
684 oa->nssa_default_originate
685 .metric_value);
686 if (oa->nssa_default_originate.metric_type
687 != DEFAULT_METRIC_TYPE)
688 vty_out(vty, " metric-type 1");
689 }
8a60820f
RW
690 if (oa->no_summary)
691 vty_out(vty, " no-summary");
692 vty_out(vty, "\n");
693 }
d62a17ae 694 if (PREFIX_NAME_IN(oa))
695 vty_out(vty, " area %s filter-list prefix %s in\n",
696 oa->name, PREFIX_NAME_IN(oa));
697 if (PREFIX_NAME_OUT(oa))
698 vty_out(vty, " area %s filter-list prefix %s out\n",
699 oa->name, PREFIX_NAME_OUT(oa));
700 if (IMPORT_NAME(oa))
701 vty_out(vty, " area %s import-list %s\n", oa->name,
702 IMPORT_NAME(oa));
703 if (EXPORT_NAME(oa))
704 vty_out(vty, " area %s export-list %s\n", oa->name,
705 EXPORT_NAME(oa));
ca1f4309 706 }
6452df09 707}
708
34956b31 709DEFUN (area_filter_list,
710 area_filter_list_cmd,
dd3ff9d8 711 "area <A.B.C.D|(0-4294967295)> filter-list prefix WORD <in|out>",
b2d4d039
RW
712 "OSPF6 area parameters\n"
713 "OSPF6 area ID in IP address format\n"
dd3ff9d8 714 "OSPF6 area ID as a decimal value\n"
b2d4d039
RW
715 "Filter networks between OSPF6 areas\n"
716 "Filter prefixes between OSPF6 areas\n"
34956b31 717 "Name of an IPv6 prefix-list\n"
718 "Filter networks sent to this area\n"
719 "Filter networks sent from this area\n")
720{
d62a17ae 721 char *inout = argv[argc - 1]->text;
722 char *areaid = argv[1]->arg;
723 char *plistname = argv[4]->arg;
724
725 struct ospf6_area *area;
726 struct prefix_list *plist;
727
beadc736 728 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
729
730 OSPF6_CMD_AREA_GET(areaid, area, ospf6);
d62a17ae 731
732 plist = prefix_list_lookup(AFI_IP6, plistname);
733 if (strmatch(inout, "in")) {
734 PREFIX_LIST_IN(area) = plist;
427f8e61 735 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
996c9314
LB
736 PREFIX_NAME_IN(area) =
737 XSTRDUP(MTYPE_OSPF6_PLISTNAME, plistname);
d62a17ae 738 } else {
739 PREFIX_LIST_OUT(area) = plist;
427f8e61 740 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
996c9314
LB
741 PREFIX_NAME_OUT(area) =
742 XSTRDUP(MTYPE_OSPF6_PLISTNAME, plistname);
d62a17ae 743 }
744
f4f0098c
RW
745 /* Redo summaries if required */
746 if (ospf6_check_and_set_router_abr(area->ospf6))
747 ospf6_schedule_abr_task(ospf6);
748
d62a17ae 749 return CMD_SUCCESS;
34956b31 750}
d62a17ae 751
34956b31 752DEFUN (no_area_filter_list,
753 no_area_filter_list_cmd,
dd3ff9d8 754 "no area <A.B.C.D|(0-4294967295)> filter-list prefix WORD <in|out>",
34956b31 755 NO_STR
b2d4d039
RW
756 "OSPF6 area parameters\n"
757 "OSPF6 area ID in IP address format\n"
dd3ff9d8 758 "OSPF6 area ID as a decimal value\n"
b2d4d039
RW
759 "Filter networks between OSPF6 areas\n"
760 "Filter prefixes between OSPF6 areas\n"
34956b31 761 "Name of an IPv6 prefix-list\n"
762 "Filter networks sent to this area\n"
763 "Filter networks sent from this area\n")
764{
d62a17ae 765 char *inout = argv[argc - 1]->text;
766 char *areaid = argv[2]->arg;
767 char *plistname = argv[5]->arg;
768
769 struct ospf6_area *area;
770
beadc736 771 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
772 OSPF6_CMD_AREA_GET(areaid, area, ospf6);
d62a17ae 773
774 if (strmatch(inout, "in")) {
775 if (PREFIX_NAME_IN(area))
776 if (!strmatch(PREFIX_NAME_IN(area), plistname))
777 return CMD_SUCCESS;
778
779 PREFIX_LIST_IN(area) = NULL;
427f8e61 780 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
d62a17ae 781 } else {
782 if (PREFIX_NAME_OUT(area))
783 if (!strmatch(PREFIX_NAME_OUT(area), plistname))
784 return CMD_SUCCESS;
785
427f8e61 786 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
f6c5f2e0 787 PREFIX_LIST_OUT(area) = NULL;
d62a17ae 788 }
789
f4f0098c
RW
790 /* Redo summaries if required */
791 if (ospf6_check_and_set_router_abr(area->ospf6))
792 ospf6_schedule_abr_task(ospf6);
793
d62a17ae 794 return CMD_SUCCESS;
34956b31 795}
796
f6c5f2e0 797void ospf6_filter_update(struct access_list *access)
798{
799 struct ospf6_area *oa;
800 struct listnode *n, *node, *nnode;
801 struct ospf6 *ospf6;
802
803 for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6)) {
f4f0098c
RW
804 bool update = false;
805
f6c5f2e0 806 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa)) {
807 if (IMPORT_NAME(oa)
f4f0098c
RW
808 && strcmp(IMPORT_NAME(oa), access->name) == 0) {
809 IMPORT_LIST(oa) = access_list_lookup(
810 AFI_IP6, IMPORT_NAME(oa));
811 update = true;
812 }
f6c5f2e0 813
814 if (EXPORT_NAME(oa)
f4f0098c
RW
815 && strcmp(EXPORT_NAME(oa), access->name) == 0) {
816 EXPORT_LIST(oa) = access_list_lookup(
817 AFI_IP6, EXPORT_NAME(oa));
818 update = true;
819 }
f6c5f2e0 820 }
f4f0098c
RW
821
822 if (update && ospf6_check_and_set_router_abr(ospf6))
823 ospf6_schedule_abr_task(ospf6);
f6c5f2e0 824 }
825}
826
f4f0098c 827void ospf6_plist_update(struct prefix_list *plist)
427f8e61 828{
beadc736 829 struct listnode *node, *nnode;
427f8e61
DL
830 struct ospf6_area *oa;
831 struct listnode *n;
832 const char *name = prefix_list_name(plist);
beadc736 833 struct ospf6 *ospf6 = NULL;
834
f4f0098c
RW
835 if (prefix_list_afi(plist) != AFI_IP6)
836 return;
837
beadc736 838 for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6)) {
f4f0098c
RW
839 bool update = false;
840
beadc736 841 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa)) {
842 if (PREFIX_NAME_IN(oa)
f6c5f2e0 843 && !strcmp(PREFIX_NAME_IN(oa), name)) {
f4f0098c
RW
844 PREFIX_LIST_IN(oa) = prefix_list_lookup(
845 AFI_IP6, PREFIX_NAME_IN(oa));
846 update = true;
f6c5f2e0 847 }
beadc736 848 if (PREFIX_NAME_OUT(oa)
f6c5f2e0 849 && !strcmp(PREFIX_NAME_OUT(oa), name)) {
f4f0098c
RW
850 PREFIX_LIST_OUT(oa) = prefix_list_lookup(
851 AFI_IP6, PREFIX_NAME_OUT(oa));
852 update = true;
f6c5f2e0 853 }
beadc736 854 }
f4f0098c
RW
855
856 if (update && ospf6_check_and_set_router_abr(ospf6))
857 ospf6_schedule_abr_task(ospf6);
427f8e61
DL
858 }
859}
860
34956b31 861DEFUN (area_import_list,
862 area_import_list_cmd,
dd3ff9d8 863 "area <A.B.C.D|(0-4294967295)> import-list NAME",
b2d4d039
RW
864 "OSPF6 area parameters\n"
865 "OSPF6 area ID in IP address format\n"
dd3ff9d8 866 "OSPF6 area ID as a decimal value\n"
34956b31 867 "Set the filter for networks from other areas announced to the specified one\n"
868 "Name of the acess-list\n")
869{
d62a17ae 870 int idx_ipv4 = 1;
871 int idx_name = 3;
872 struct ospf6_area *area;
873 struct access_list *list;
34956b31 874
beadc736 875 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
876
877 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area, ospf6);
34956b31 878
d62a17ae 879 list = access_list_lookup(AFI_IP6, argv[idx_name]->arg);
34956b31 880
d62a17ae 881 IMPORT_LIST(area) = list;
34956b31 882
d62a17ae 883 if (IMPORT_NAME(area))
884 free(IMPORT_NAME(area));
34956b31 885
d62a17ae 886 IMPORT_NAME(area) = strdup(argv[idx_name]->arg);
f4f0098c
RW
887 if (ospf6_check_and_set_router_abr(area->ospf6))
888 ospf6_schedule_abr_task(ospf6);
34956b31 889
d62a17ae 890 return CMD_SUCCESS;
34956b31 891}
892
893DEFUN (no_area_import_list,
894 no_area_import_list_cmd,
dd3ff9d8 895 "no area <A.B.C.D|(0-4294967295)> import-list NAME",
6fbde29d 896 NO_STR
b2d4d039
RW
897 "OSPF6 area parameters\n"
898 "OSPF6 area ID in IP address format\n"
dd3ff9d8 899 "OSPF6 area ID as a decimal value\n"
34956b31 900 "Unset the filter for networks announced to other areas\n"
6fbde29d 901 "Name of the access-list\n")
34956b31 902{
d62a17ae 903 int idx_ipv4 = 2;
904 struct ospf6_area *area;
34956b31 905
beadc736 906 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
907
908 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area, ospf6);
34956b31 909
f4f0098c 910 IMPORT_LIST(area) = NULL;
34956b31 911
d62a17ae 912 if (IMPORT_NAME(area))
913 free(IMPORT_NAME(area));
34956b31 914
d62a17ae 915 IMPORT_NAME(area) = NULL;
f4f0098c
RW
916 if (ospf6_check_and_set_router_abr(area->ospf6))
917 ospf6_schedule_abr_task(ospf6);
34956b31 918
d62a17ae 919 return CMD_SUCCESS;
34956b31 920}
921
922DEFUN (area_export_list,
923 area_export_list_cmd,
dd3ff9d8 924 "area <A.B.C.D|(0-4294967295)> export-list NAME",
b2d4d039
RW
925 "OSPF6 area parameters\n"
926 "OSPF6 area ID in IP address format\n"
dd3ff9d8 927 "OSPF6 area ID as a decimal value\n"
34956b31 928 "Set the filter for networks announced to other areas\n"
929 "Name of the acess-list\n")
930{
d62a17ae 931 int idx_ipv4 = 1;
932 int idx_name = 3;
933 struct ospf6_area *area;
934 struct access_list *list;
34956b31 935
beadc736 936 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
937
938 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area, ospf6);
34956b31 939
d62a17ae 940 list = access_list_lookup(AFI_IP6, argv[idx_name]->arg);
34956b31 941
d62a17ae 942 EXPORT_LIST(area) = list;
34956b31 943
d62a17ae 944 if (EXPORT_NAME(area))
945 free(EXPORT_NAME(area));
34956b31 946
d62a17ae 947 EXPORT_NAME(area) = strdup(argv[idx_name]->arg);
f6c5f2e0 948
949 /* Redo summaries if required */
f4f0098c
RW
950 if (ospf6_check_and_set_router_abr(area->ospf6))
951 ospf6_schedule_abr_task(ospf6);
34956b31 952
d62a17ae 953 return CMD_SUCCESS;
34956b31 954}
955
956DEFUN (no_area_export_list,
957 no_area_export_list_cmd,
dd3ff9d8 958 "no area <A.B.C.D|(0-4294967295)> export-list NAME",
6fbde29d 959 NO_STR
b2d4d039
RW
960 "OSPF6 area parameters\n"
961 "OSPF6 area ID in IP address format\n"
dd3ff9d8 962 "OSPF6 area ID as a decimal value\n"
34956b31 963 "Unset the filter for networks announced to other areas\n"
964 "Name of the access-list\n")
965{
d62a17ae 966 int idx_ipv4 = 2;
967 struct ospf6_area *area;
34956b31 968
beadc736 969 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
970
971 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area, ospf6);
34956b31 972
f4f0098c 973 EXPORT_LIST(area) = NULL;
34956b31 974
d62a17ae 975 if (EXPORT_NAME(area))
976 free(EXPORT_NAME(area));
34956b31 977
d62a17ae 978 EXPORT_NAME(area) = NULL;
f4f0098c
RW
979 if (ospf6_check_and_set_router_abr(area->ospf6))
980 ospf6_schedule_abr_task(ospf6);
34956b31 981
d62a17ae 982 return CMD_SUCCESS;
34956b31 983}
984
d48ef099 985static int ipv6_ospf6_spf_tree_common(struct vty *vty, struct ospf6 *ospf6,
986 bool uj)
718e3744 987{
d62a17ae 988 struct listnode *node;
989 struct ospf6_area *oa;
d48ef099 990 struct prefix prefix;
d62a17ae 991 struct ospf6_vertex *root;
992 struct ospf6_route *route;
305b639b
YR
993 json_object *json = NULL;
994 json_object *json_area = NULL;
995 json_object *json_head = NULL;
305b639b
YR
996
997 if (uj)
998 json = json_object_new_object();
d62a17ae 999 ospf6_linkstate_prefix(ospf6->router_id, htonl(0), &prefix);
d62a17ae 1000 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
305b639b
YR
1001 if (uj) {
1002 json_area = json_object_new_object();
1003 json_head = json_object_new_object();
1004 }
d62a17ae 1005 route = ospf6_route_lookup(&prefix, oa->spf_table);
1006 if (route == NULL) {
305b639b
YR
1007 if (uj) {
1008 json_object_string_add(
1009 json, oa->name,
1010 "LS entry for not not found");
1011 json_object_free(json_head);
1012 json_object_free(json_area);
1013 } else
1014 vty_out(vty,
1015 "LS entry for root not found in area %s\n",
1016 oa->name);
d62a17ae 1017 continue;
1018 }
1019 root = (struct ospf6_vertex *)route->route_option;
305b639b
YR
1020 ospf6_spf_display_subtree(vty, "", 0, root, json_head, uj);
1021
1022 if (uj) {
1023 json_object_object_add(json_area, root->name,
1024 json_head);
1025 json_object_object_add(json, oa->name, json_area);
1026 }
1027 }
1028
1029 if (uj) {
1030 vty_out(vty, "%s\n",
1031 json_object_to_json_string_ext(
1032 json, JSON_C_TO_STRING_PRETTY));
1033 json_object_free(json);
d62a17ae 1034 }
1035
1036 return CMD_SUCCESS;
508e53e2 1037}
1038
d48ef099 1039DEFUN(show_ipv6_ospf6_spf_tree, show_ipv6_ospf6_spf_tree_cmd,
1040 "show ipv6 ospf6 [vrf <NAME|all>] spf tree [json]",
1041 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1042 "All VRFs\n"
1043 "Shortest Path First calculation\n"
1044 "Show SPF tree\n" JSON_STR)
508e53e2 1045{
d48ef099 1046 struct listnode *node;
beadc736 1047 struct ospf6 *ospf6;
d48ef099 1048 const char *vrf_name = NULL;
1049 bool all_vrf = false;
1050 int idx_vrf = 0;
1051 bool uj = use_json(argc, argv);
beadc736 1052
d48ef099 1053 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1054
1055 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1056 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1057 ipv6_ospf6_spf_tree_common(vty, ospf6, uj);
1058 if (!all_vrf)
1059 break;
1060 }
1061 }
1062
1063 return CMD_SUCCESS;
1064}
1065
1066static int show_ospf6_area_spf_tree_common(struct vty *vty,
1067 struct cmd_token **argv,
1068 struct ospf6 *ospf6,
1069 uint32_t area_id, int idx_ipv4)
1070{
d62a17ae 1071
d48ef099 1072 struct ospf6_area *oa;
1073 struct prefix prefix;
1074 struct ospf6_vertex *root;
1075 struct ospf6_route *route;
d62a17ae 1076
1077 ospf6_linkstate_prefix(ospf6->router_id, htonl(0), &prefix);
1078
d62a17ae 1079 oa = ospf6_area_lookup(area_id, ospf6);
1080 if (oa == NULL) {
1081 vty_out(vty, "No such Area: %s\n", argv[idx_ipv4]->arg);
1082 return CMD_SUCCESS;
1083 }
1084
1085 route = ospf6_route_lookup(&prefix, oa->spf_table);
1086 if (route == NULL) {
1087 vty_out(vty, "LS entry for root not found in area %s\n",
1088 oa->name);
1089 return CMD_SUCCESS;
1090 }
1091 root = (struct ospf6_vertex *)route->route_option;
305b639b 1092 ospf6_spf_display_subtree(vty, "", 0, root, NULL, false);
d62a17ae 1093
1094 return CMD_SUCCESS;
718e3744 1095}
1096
d48ef099 1097DEFUN(show_ipv6_ospf6_area_spf_tree, show_ipv6_ospf6_area_spf_tree_cmd,
1098 "show ipv6 ospf6 [vrf <NAME|all>] area A.B.C.D spf tree",
1099 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1100 "All VRFs\n" OSPF6_AREA_STR OSPF6_AREA_ID_STR
1101 "Shortest Path First calculation\n"
1102 "Show SPF tree\n")
508e53e2 1103{
d48ef099 1104 int idx_ipv4 = 4;
d7c0a89a 1105 uint32_t area_id;
d48ef099 1106 struct ospf6 *ospf6;
1107 struct listnode *node;
1108 const char *vrf_name = NULL;
1109 bool all_vrf = false;
1110 int idx_vrf = 0;
1111
d48ef099 1112 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1113 if (idx_vrf > 0)
1114 idx_ipv4 += 2;
1115
1116 if (inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id) != 1) {
1117 vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4]->arg);
1118 return CMD_SUCCESS;
1119 }
1120
1121 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1122 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1123 show_ospf6_area_spf_tree_common(vty, argv, ospf6,
1124 area_id, idx_ipv4);
1125 if (!all_vrf)
1126 break;
1127 }
1128 }
1129
1130 return CMD_SUCCESS;
1131}
1132
1133static int
1134show_ospf6_simulate_spf_tree_commen(struct vty *vty, struct cmd_token **argv,
1135 struct ospf6 *ospf6, uint32_t router_id,
1136 uint32_t area_id, struct prefix prefix,
1137 int idx_ipv4, int idx_ipv4_2)
1138{
d62a17ae 1139 struct ospf6_area *oa;
1140 struct ospf6_vertex *root;
1141 struct ospf6_route *route;
d62a17ae 1142 struct ospf6_route_table *spf_table;
1143 unsigned char tmp_debug_ospf6_spf = 0;
d62a17ae 1144
d62a17ae 1145 oa = ospf6_area_lookup(area_id, ospf6);
1146 if (oa == NULL) {
1147 vty_out(vty, "No such Area: %s\n", argv[idx_ipv4_2]->arg);
1148 return CMD_SUCCESS;
1149 }
1150
1151 tmp_debug_ospf6_spf = conf_debug_ospf6_spf;
1152 conf_debug_ospf6_spf = 0;
1153
1154 spf_table = OSPF6_ROUTE_TABLE_CREATE(NONE, SPF_RESULTS);
1155 ospf6_spf_calculation(router_id, spf_table, oa);
1156
1157 conf_debug_ospf6_spf = tmp_debug_ospf6_spf;
1158
1159 route = ospf6_route_lookup(&prefix, spf_table);
1160 if (route == NULL) {
e285b70d
IR
1161 ospf6_spf_table_finish(spf_table);
1162 ospf6_route_table_delete(spf_table);
d62a17ae 1163 return CMD_SUCCESS;
1164 }
1165 root = (struct ospf6_vertex *)route->route_option;
305b639b 1166 ospf6_spf_display_subtree(vty, "", 0, root, NULL, false);
d62a17ae 1167
e285b70d
IR
1168 ospf6_spf_table_finish(spf_table);
1169 ospf6_route_table_delete(spf_table);
d62a17ae 1170
1171 return CMD_SUCCESS;
508e53e2 1172}
1173
d48ef099 1174DEFUN(show_ipv6_ospf6_simulate_spf_tree_root,
1175 show_ipv6_ospf6_simulate_spf_tree_root_cmd,
1176 "show ipv6 ospf6 [vrf <NAME|all>] simulate spf-tree A.B.C.D area A.B.C.D",
1177 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1178 "All VRFs\n"
1179 "Shortest Path First calculation\n"
1180 "Show SPF tree\n"
1181 "Specify root's router-id to calculate another router's SPF tree\n"
1182 "OSPF6 area parameters\n" OSPF6_AREA_ID_STR)
1183{
1184 int idx_ipv4 = 5;
1185 int idx_ipv4_2 = 7;
1186 uint32_t area_id;
1187 struct prefix prefix;
1188 uint32_t router_id;
1189 struct ospf6 *ospf6;
1190 struct listnode *node;
1191 const char *vrf_name = NULL;
1192 bool all_vrf = false;
1193 int idx_vrf = 0;
1194
d48ef099 1195 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1196 if (idx_vrf > 0) {
1197 idx_ipv4 += 2;
1198 idx_ipv4_2 += 2;
1199 }
1200 inet_pton(AF_INET, argv[idx_ipv4]->arg, &router_id);
1201 ospf6_linkstate_prefix(router_id, htonl(0), &prefix);
1202
1203 if (inet_pton(AF_INET, argv[idx_ipv4_2]->arg, &area_id) != 1) {
1204 vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4_2]->arg);
1205 return CMD_SUCCESS;
1206 }
1207
1208 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1209 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1210 show_ospf6_simulate_spf_tree_commen(
1211 vty, argv, ospf6, router_id, area_id, prefix,
1212 idx_ipv4, idx_ipv4_2);
1213 if (!all_vrf)
1214 break;
1215 }
1216 }
1217
1218 return CMD_SUCCESS;
1219}
1220
ca1f4309
DS
1221DEFUN (ospf6_area_stub,
1222 ospf6_area_stub_cmd,
6147e2c6 1223 "area <A.B.C.D|(0-4294967295)> stub",
ca1f4309
DS
1224 "OSPF6 area parameters\n"
1225 "OSPF6 area ID in IP address format\n"
1226 "OSPF6 area ID as a decimal value\n"
1227 "Configure OSPF6 area as stub\n")
1228{
d62a17ae 1229 int idx_ipv4_number = 1;
1230 struct ospf6_area *area;
ca1f4309 1231
beadc736 1232 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1233
1234 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area, ospf6);
ca1f4309 1235
d62a17ae 1236 if (!ospf6_area_stub_set(ospf6, area)) {
1237 vty_out(vty,
1238 "First deconfigure all virtual link through this area\n");
1239 return CMD_WARNING_CONFIG_FAILED;
1240 }
ca1f4309 1241
d62a17ae 1242 ospf6_area_no_summary_unset(ospf6, area);
ca1f4309 1243
d62a17ae 1244 return CMD_SUCCESS;
ca1f4309
DS
1245}
1246
1247DEFUN (ospf6_area_stub_no_summary,
1248 ospf6_area_stub_no_summary_cmd,
6147e2c6 1249 "area <A.B.C.D|(0-4294967295)> stub no-summary",
ca1f4309
DS
1250 "OSPF6 stub parameters\n"
1251 "OSPF6 area ID in IP address format\n"
1252 "OSPF6 area ID as a decimal value\n"
1253 "Configure OSPF6 area as stub\n"
1254 "Do not inject inter-area routes into stub\n")
1255{
d62a17ae 1256 int idx_ipv4_number = 1;
1257 struct ospf6_area *area;
ca1f4309 1258
beadc736 1259 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1260
1261 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area, ospf6);
ca1f4309 1262
d62a17ae 1263 if (!ospf6_area_stub_set(ospf6, area)) {
1264 vty_out(vty,
1265 "First deconfigure all virtual link through this area\n");
1266 return CMD_WARNING_CONFIG_FAILED;
1267 }
ca1f4309 1268
d62a17ae 1269 ospf6_area_no_summary_set(ospf6, area);
ca1f4309 1270
d62a17ae 1271 return CMD_SUCCESS;
ca1f4309
DS
1272}
1273
1274DEFUN (no_ospf6_area_stub,
1275 no_ospf6_area_stub_cmd,
6147e2c6 1276 "no area <A.B.C.D|(0-4294967295)> stub",
ca1f4309
DS
1277 NO_STR
1278 "OSPF6 area parameters\n"
1279 "OSPF6 area ID in IP address format\n"
1280 "OSPF6 area ID as a decimal value\n"
1281 "Configure OSPF6 area as stub\n")
1282{
d62a17ae 1283 int idx_ipv4_number = 2;
1284 struct ospf6_area *area;
ca1f4309 1285
beadc736 1286 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1287
1288 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area, ospf6);
ca1f4309 1289
d62a17ae 1290 ospf6_area_stub_unset(ospf6, area);
1291 ospf6_area_no_summary_unset(ospf6, area);
ca1f4309 1292
d62a17ae 1293 return CMD_SUCCESS;
ca1f4309
DS
1294}
1295
1296DEFUN (no_ospf6_area_stub_no_summary,
1297 no_ospf6_area_stub_no_summary_cmd,
6147e2c6 1298 "no area <A.B.C.D|(0-4294967295)> stub no-summary",
ca1f4309
DS
1299 NO_STR
1300 "OSPF6 area parameters\n"
1301 "OSPF6 area ID in IP address format\n"
1302 "OSPF6 area ID as a decimal value\n"
1303 "Configure OSPF6 area as stub\n"
1304 "Do not inject inter-area routes into area\n")
1305{
d62a17ae 1306 int idx_ipv4_number = 2;
1307 struct ospf6_area *area;
ca1f4309 1308
beadc736 1309 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1310
1311 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area, ospf6);
ca1f4309 1312
d62a17ae 1313 ospf6_area_stub_unset(ospf6, area);
1314 ospf6_area_no_summary_unset(ospf6, area);
ca1f4309 1315
d62a17ae 1316 return CMD_SUCCESS;
ca1f4309
DS
1317}
1318
8a60820f 1319DEFPY(ospf6_area_nssa, ospf6_area_nssa_cmd,
6735622c
RW
1320 "area <A.B.C.D|(0-4294967295)>$area_str nssa\
1321 [{\
1322 default-information-originate$dflt_originate [{metric (0-16777214)$mval|metric-type (1-2)$mtype}]\
1323 |no-summary$no_summary\
1324 }]",
ad500b22
K
1325 "OSPF6 area parameters\n"
1326 "OSPF6 area ID in IP address format\n"
1327 "OSPF6 area ID as a decimal value\n"
8a60820f 1328 "Configure OSPF6 area as nssa\n"
6735622c
RW
1329 "Originate Type 7 default into NSSA area\n"
1330 "OSPFv3 default metric\n"
1331 "OSPFv3 metric\n"
1332 "OSPFv3 metric type for default routes\n"
1333 "Set OSPFv3 External Type 1/2 metrics\n"
8a60820f 1334 "Do not inject inter-area routes into area\n")
ad500b22 1335{
ad500b22
K
1336 struct ospf6_area *area;
1337
1338 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
8a60820f 1339 OSPF6_CMD_AREA_GET(area_str, area, ospf6);
ad500b22
K
1340
1341 if (!ospf6_area_nssa_set(ospf6, area)) {
1342 vty_out(vty,
1343 "First deconfigure all virtual link through this area\n");
1344 return CMD_WARNING_CONFIG_FAILED;
1345 }
1346
6735622c
RW
1347 if (dflt_originate) {
1348 if (mval_str == NULL)
1349 mval = -1;
1350 if (mtype_str == NULL)
1351 mtype = DEFAULT_METRIC_TYPE;
1352 ospf6_nssa_default_originate_set(ospf6, area, mval, mtype);
1353 } else
1354 ospf6_nssa_default_originate_unset(ospf6, area);
1355
8a60820f
RW
1356 if (no_summary)
1357 ospf6_area_no_summary_set(ospf6, area);
1358 else
1359 ospf6_area_no_summary_unset(ospf6, area);
6735622c
RW
1360
1361 if (ospf6_check_and_set_router_abr(ospf6)) {
8a60820f 1362 ospf6_abr_defaults_to_stub(ospf6);
6735622c
RW
1363 ospf6_abr_nssa_type_7_defaults(ospf6);
1364 }
0c293b92 1365
ad500b22
K
1366 return CMD_SUCCESS;
1367}
1368
8a60820f 1369DEFPY(no_ospf6_area_nssa, no_ospf6_area_nssa_cmd,
6735622c
RW
1370 "no area <A.B.C.D|(0-4294967295)>$area_str nssa\
1371 [{\
1372 default-information-originate [{metric (0-16777214)|metric-type (1-2)}]\
1373 |no-summary\
1374 }]",
ad500b22
K
1375 NO_STR
1376 "OSPF6 area parameters\n"
1377 "OSPF6 area ID in IP address format\n"
1378 "OSPF6 area ID as a decimal value\n"
8a60820f 1379 "Configure OSPF6 area as nssa\n"
6735622c
RW
1380 "Originate Type 7 default into NSSA area\n"
1381 "OSPFv3 default metric\n"
1382 "OSPFv3 metric\n"
1383 "OSPFv3 metric type for default routes\n"
1384 "Set OSPFv3 External Type 1/2 metrics\n"
8a60820f 1385 "Do not inject inter-area routes into area\n")
ad500b22 1386{
ad500b22
K
1387 struct ospf6_area *area;
1388
1389 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
8a60820f 1390 OSPF6_CMD_AREA_GET(area_str, area, ospf6);
ad500b22
K
1391
1392 ospf6_area_nssa_unset(ospf6, area);
8a60820f 1393 ospf6_area_no_summary_unset(ospf6, area);
6735622c 1394 ospf6_nssa_default_originate_unset(ospf6, area);
ad500b22
K
1395
1396 return CMD_SUCCESS;
1397}
1398
1399
d62a17ae 1400void ospf6_area_init(void)
508e53e2 1401{
d62a17ae 1402 install_element(VIEW_NODE, &show_ipv6_ospf6_spf_tree_cmd);
1403 install_element(VIEW_NODE, &show_ipv6_ospf6_area_spf_tree_cmd);
1404 install_element(VIEW_NODE, &show_ipv6_ospf6_simulate_spf_tree_root_cmd);
ca1f4309 1405
d62a17ae 1406 install_element(OSPF6_NODE, &area_range_cmd);
1407 install_element(OSPF6_NODE, &no_area_range_cmd);
1408 install_element(OSPF6_NODE, &ospf6_area_stub_no_summary_cmd);
1409 install_element(OSPF6_NODE, &ospf6_area_stub_cmd);
1410 install_element(OSPF6_NODE, &no_ospf6_area_stub_no_summary_cmd);
1411 install_element(OSPF6_NODE, &no_ospf6_area_stub_cmd);
34956b31 1412
34956b31 1413
d62a17ae 1414 install_element(OSPF6_NODE, &area_import_list_cmd);
1415 install_element(OSPF6_NODE, &no_area_import_list_cmd);
1416 install_element(OSPF6_NODE, &area_export_list_cmd);
1417 install_element(OSPF6_NODE, &no_area_export_list_cmd);
34956b31 1418
d62a17ae 1419 install_element(OSPF6_NODE, &area_filter_list_cmd);
1420 install_element(OSPF6_NODE, &no_area_filter_list_cmd);
ad500b22
K
1421
1422 /* "area nssa" commands. */
1423 install_element(OSPF6_NODE, &ospf6_area_nssa_cmd);
1424 install_element(OSPF6_NODE, &no_ospf6_area_nssa_cmd);
508e53e2 1425}
22b982df
PG
1426
1427void ospf6_area_interface_delete(struct ospf6_interface *oi)
1428{
1429 struct ospf6_area *oa;
1430 struct listnode *node, *nnode;
beadc736 1431 struct ospf6 *ospf6;
22b982df 1432
d48ef099 1433 for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6)) {
beadc736 1434 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa))
1435 if (listnode_lookup(oa->if_list, oi))
1436 listnode_delete(oa->if_list, oi);
d48ef099 1437 }
22b982df 1438}