]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_area.c
ospf6d: add support for unplanned graceful restart
[mirror_frr.git] / ospf6d / ospf6_area.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (C) 2003 Yasuhiro Ohara
4 */
5
6 #include <zebra.h>
7
8 #include "log.h"
9 #include "memory.h"
10 #include "linklist.h"
11 #include "frrevent.h"
12 #include "vty.h"
13 #include "command.h"
14 #include "if.h"
15 #include "prefix.h"
16 #include "table.h"
17 #include "plist.h"
18 #include "filter.h"
19
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"
27 #include "ospf6_message.h"
28 #include "ospf6_neighbor.h"
29 #include "ospf6_interface.h"
30 #include "ospf6_intra.h"
31 #include "ospf6_abr.h"
32 #include "ospf6_asbr.h"
33 #include "ospf6_zebra.h"
34 #include "ospf6d.h"
35 #include "lib/json.h"
36 #include "ospf6_nssa.h"
37 #include "ospf6d/ospf6_area_clippy.c"
38
39 DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_AREA, "OSPF6 area");
40 DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_PLISTNAME, "Prefix list name");
41
42 int str2area_id(const char *str, uint32_t *area_id, int *area_id_fmt)
43 {
44 char *ep;
45
46 *area_id = htonl(strtoul(str, &ep, 10));
47 if (*ep && inet_pton(AF_INET, str, area_id) != 1)
48 return -1;
49
50 *area_id_fmt =
51 !*ep ? OSPF6_AREA_FMT_DECIMAL : OSPF6_AREA_FMT_DOTTEDQUAD;
52
53 return 0;
54 }
55
56 void 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
64 int ospf6_area_cmp(void *va, void *vb)
65 {
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);
69 }
70
71 /* schedule routing table recalculation */
72 static void ospf6_area_lsdb_hook_add(struct ospf6_lsa *lsa)
73 {
74 switch (ntohs(lsa->header->type)) {
75
76 case OSPF6_LSTYPE_ROUTER:
77 case OSPF6_LSTYPE_NETWORK:
78 if (IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa->header->type)) {
79 zlog_debug("%s Examin LSA %s", __func__, lsa->name);
80 zlog_debug(" Schedule SPF Calculation for %s",
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
98 case OSPF6_LSTYPE_TYPE_7:
99 ospf6_asbr_lsa_add(lsa);
100 break;
101
102 default:
103 break;
104 }
105 }
106
107 static 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;
131 case OSPF6_LSTYPE_TYPE_7:
132 ospf6_asbr_lsa_remove(lsa, NULL);
133 break;
134 default:
135 break;
136 }
137 }
138
139 static void ospf6_area_route_hook_add(struct ospf6_route *route)
140 {
141 struct ospf6_area *oa = route->table->scope;
142 struct ospf6 *ospf6 = oa->ospf6;
143 struct ospf6_route *copy;
144
145 copy = ospf6_route_copy(route);
146 ospf6_route_add(copy, ospf6->route_table);
147 }
148
149 static void ospf6_area_route_hook_remove(struct ospf6_route *route)
150 {
151 struct ospf6_area *oa = route->table->scope;
152 struct ospf6 *ospf6 = oa->ospf6;
153 struct ospf6_route *copy;
154
155 copy = ospf6_route_lookup_identical(route, ospf6->route_table);
156 if (copy)
157 ospf6_route_remove(copy, ospf6->route_table);
158 }
159
160 static void ospf6_area_stub_update(struct ospf6_area *area)
161 {
162
163 if (IS_AREA_STUB(area)) {
164 if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER))
165 zlog_debug("Stubbing out area for area %s", area->name);
166 OSPF6_OPT_CLEAR(area->options, OSPF6_OPT_E);
167 ospf6_asbr_remove_externals_from_area(area);
168 } else if (IS_AREA_ENABLED(area)) {
169 if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER))
170 zlog_debug("Normal area for area %s", area->name);
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);
176 }
177
178 static int ospf6_area_stub_set(struct ospf6 *ospf6, struct ospf6_area *area)
179 {
180 if (!IS_AREA_STUB(area)) {
181 /* Disable NSSA first. */
182 ospf6_area_nssa_unset(ospf6, area);
183
184 SET_FLAG(area->flag, OSPF6_AREA_STUB);
185 ospf6_area_stub_update(area);
186 }
187
188 return 1;
189 }
190
191 void ospf6_area_stub_unset(struct ospf6 *ospf6, struct ospf6_area *area)
192 {
193 if (IS_AREA_STUB(area)) {
194 UNSET_FLAG(area->flag, OSPF6_AREA_STUB);
195 ospf6_area_stub_update(area);
196 }
197 }
198
199 static void ospf6_area_no_summary_set(struct ospf6 *ospf6,
200 struct ospf6_area *area)
201 {
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 }
208 }
209 }
210
211 static void ospf6_area_no_summary_unset(struct ospf6 *ospf6,
212 struct ospf6_area *area)
213 {
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 }
220 }
221 }
222
223 static 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
239 static 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
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 */
260 struct ospf6_area *ospf6_area_create(uint32_t area_id, struct ospf6 *o, int df)
261 {
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);
283 oa->temp_router_lsa_lsdb = ospf6_lsdb_create(oa);
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;
294 oa->nssa_range_table = OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES);
295 oa->nssa_range_table->scope = oa;
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;
300 oa->router_lsa_size_limit = 1024 + 256;
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;
324 }
325
326 void ospf6_area_delete(struct ospf6_area *oa)
327 {
328 struct listnode *n;
329 struct ospf6_interface *oi;
330
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. */
336 for (ALL_LIST_ELEMENTS_RO(oa->if_list, n, oi)) {
337 oi->area = NULL;
338
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
347 list_delete(&oa->if_list);
348
349 ospf6_lsdb_delete(oa->lsdb);
350 ospf6_lsdb_delete(oa->lsdb_self);
351 ospf6_lsdb_delete(oa->temp_router_lsa_lsdb);
352
353 ospf6_spf_table_finish(oa->spf_table);
354 ospf6_route_table_delete(oa->spf_table);
355 ospf6_route_table_delete(oa->route_table);
356
357 ospf6_route_table_delete(oa->range_table);
358 ospf6_route_table_delete(oa->nssa_range_table);
359 ospf6_route_table_delete(oa->summary_prefix);
360 ospf6_route_table_delete(oa->summary_router);
361
362 listnode_delete(oa->ospf6->area_list, oa);
363 oa->ospf6 = NULL;
364
365 /* free area */
366 XFREE(MTYPE_OSPF6_AREA, oa);
367 }
368
369 struct 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
383 struct ospf6_area *ospf6_area_lookup(uint32_t area_id, struct ospf6 *ospf6)
384 {
385 struct ospf6_area *oa;
386 struct listnode *n;
387
388 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa))
389 if (oa->area_id == area_id)
390 return oa;
391
392 return (struct ospf6_area *)NULL;
393 }
394
395 void ospf6_area_enable(struct ospf6_area *oa)
396 {
397 struct listnode *node, *nnode;
398 struct ospf6_interface *oi;
399
400 SET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
401
402 for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi))
403 ospf6_interface_enable(oi);
404 ospf6_abr_enable_area(oa);
405 }
406
407 void ospf6_area_disable(struct ospf6_area *oa)
408 {
409 struct listnode *node, *nnode;
410 struct ospf6_interface *oi;
411
412 UNSET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
413
414 for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi))
415 ospf6_interface_disable(oi);
416
417 ospf6_abr_disable_area(oa);
418 ospf6_lsdb_remove_all(oa->lsdb);
419 ospf6_lsdb_remove_all(oa->lsdb_self);
420
421 ospf6_spf_table_finish(oa->spf_table);
422 ospf6_route_remove_all(oa->route_table);
423
424 EVENT_OFF(oa->thread_router_lsa);
425 EVENT_OFF(oa->thread_intra_prefix_lsa);
426 }
427
428
429 void ospf6_area_show(struct vty *vty, struct ospf6_area *oa,
430 json_object *json_areas, bool use_json)
431 {
432 struct listnode *i;
433 struct ospf6_interface *oi;
434 unsigned long result;
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));
442 json_object_boolean_add(json_area, "areaIsNSSA",
443 IS_AREA_NSSA(oa));
444 if (IS_AREA_STUB(oa) || IS_AREA_NSSA(oa)) {
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);
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));
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);
490
491 } else {
492
493 if (!IS_AREA_STUB(oa) && !IS_AREA_NSSA(oa))
494 vty_out(vty, " Area %s\n", oa->name);
495 else {
496 if (oa->no_summary) {
497 vty_out(vty, " Area %s[%s, No Summary]\n",
498 oa->name,
499 IS_AREA_STUB(oa) ? "Stub" : "NSSA");
500 } else {
501 vty_out(vty, " Area %s[%s]\n", oa->name,
502 IS_AREA_STUB(oa) ? "Stub" : "NSSA");
503 }
504 }
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) {
516 vty_out(vty,
517 " SPF last executed %ld.%lds ago\n",
518 result / TIMER_SECOND_MICRO,
519 result % TIMER_SECOND_MICRO);
520 } else {
521 vty_out(vty,
522 " SPF last executed %ldus ago\n",
523 result);
524 }
525 } else
526 vty_out(vty, "SPF has not been run\n");
527 }
528 }
529
530 DEFUN (area_range,
531 area_range_cmd,
532 "area <A.B.C.D|(0-4294967295)> range X:X::X:X/M [<advertise|not-advertise|cost (0-16777215)>]",
533 "OSPF6 area parameters\n"
534 "OSPF6 area ID in IP address format\n"
535 "OSPF6 area ID as a decimal value\n"
536 "Configured address range\n"
537 "Specify IPv6 prefix\n"
538 "Advertise\n"
539 "Do not advertise\n"
540 "User specified metric for this range\n"
541 "Advertised metric for this range\n")
542 {
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;
550 uint32_t cost;
551
552 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
553
554 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, oa, ospf6);
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;
561 }
562
563 range = ospf6_route_lookup(&prefix, oa->range_table);
564 if (range == NULL) {
565 range = ospf6_route_create(ospf6);
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;
570 }
571
572 /* default settings */
573 cost = OSPF_AREA_RANGE_COST_UNSPEC;
574 UNSET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
575
576 if (argc > idx_type) {
577 if (strmatch(argv[idx_type]->text, "not-advertise"))
578 SET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
579 else if (strmatch(argv[idx_type]->text, "cost"))
580 cost = strtoul(argv[5]->arg, NULL, 10);
581 }
582
583 range->path.u.cost_config = cost;
584
585 if (range->rnode == NULL) {
586 ospf6_route_add(range, oa->range_table);
587 }
588
589 if (ospf6_check_and_set_router_abr(ospf6)) {
590 /* Redo summaries if required */
591 ospf6_abr_prefix_resummarize(ospf6);
592 }
593
594 return CMD_SUCCESS;
595 }
596
597 DEFUN (no_area_range,
598 no_area_range_cmd,
599 "no area <A.B.C.D|(0-4294967295)> range X:X::X:X/M [<advertise|not-advertise|cost (0-16777215)>]",
600 NO_STR
601 "OSPF6 area parameters\n"
602 "OSPF6 area ID in IP address format\n"
603 "OSPF6 area ID as a decimal value\n"
604 "Configured address range\n"
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")
610 {
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;
617
618 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
619
620 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, oa, ospf6);
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
635 if (ospf6_check_and_set_router_abr(oa->ospf6)) {
636 /* Blow away the aggregated LSA and route */
637 SET_FLAG(range->flag, OSPF6_ROUTE_REMOVE);
638
639 /* Redo summaries if required */
640 for (route = ospf6_route_head(oa->ospf6->route_table); route;
641 route = ospf6_route_next(route))
642 ospf6_abr_originate_summary(route, oa->ospf6);
643
644 /* purge the old aggregated summary LSA */
645 ospf6_abr_originate_summary(range, oa->ospf6);
646 }
647 ospf6_route_remove(range, oa->range_table);
648
649 return CMD_SUCCESS;
650 }
651
652 void ospf6_area_config_write(struct vty *vty, struct ospf6 *ospf6)
653 {
654 struct listnode *node;
655 struct ospf6_area *oa;
656 struct ospf6_route *range;
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)) {
661 vty_out(vty, " area %s range %pFX", oa->name,
662 &range->prefix);
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 }
684 if (IS_AREA_NSSA(oa)) {
685 vty_out(vty, " area %s nssa", oa->name);
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 }
697 if (oa->no_summary)
698 vty_out(vty, " no-summary");
699 vty_out(vty, "\n");
700 }
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 }
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));
729 }
730 }
731
732 DEFUN (area_filter_list,
733 area_filter_list_cmd,
734 "area <A.B.C.D|(0-4294967295)> filter-list prefix PREFIXLIST_NAME <in|out>",
735 "OSPF6 area parameters\n"
736 "OSPF6 area ID in IP address format\n"
737 "OSPF6 area ID as a decimal value\n"
738 "Filter networks between OSPF6 areas\n"
739 "Filter prefixes between OSPF6 areas\n"
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 {
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
751 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
752
753 OSPF6_CMD_AREA_GET(areaid, area, ospf6);
754
755 plist = prefix_list_lookup(AFI_IP6, plistname);
756 if (strmatch(inout, "in")) {
757 PREFIX_LIST_IN(area) = plist;
758 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
759 PREFIX_NAME_IN(area) =
760 XSTRDUP(MTYPE_OSPF6_PLISTNAME, plistname);
761 } else {
762 PREFIX_LIST_OUT(area) = plist;
763 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
764 PREFIX_NAME_OUT(area) =
765 XSTRDUP(MTYPE_OSPF6_PLISTNAME, plistname);
766 }
767
768 /* Redo summaries if required */
769 if (ospf6_check_and_set_router_abr(area->ospf6))
770 ospf6_schedule_abr_task(ospf6);
771
772 return CMD_SUCCESS;
773 }
774
775 DEFUN (no_area_filter_list,
776 no_area_filter_list_cmd,
777 "no area <A.B.C.D|(0-4294967295)> filter-list prefix PREFIXLIST_NAME <in|out>",
778 NO_STR
779 "OSPF6 area parameters\n"
780 "OSPF6 area ID in IP address format\n"
781 "OSPF6 area ID as a decimal value\n"
782 "Filter networks between OSPF6 areas\n"
783 "Filter prefixes between OSPF6 areas\n"
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 {
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
794 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
795 OSPF6_CMD_AREA_GET(areaid, area, ospf6);
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;
803 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
804 } else {
805 if (PREFIX_NAME_OUT(area))
806 if (!strmatch(PREFIX_NAME_OUT(area), plistname))
807 return CMD_SUCCESS;
808
809 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
810 PREFIX_LIST_OUT(area) = NULL;
811 }
812
813 /* Redo summaries if required */
814 if (ospf6_check_and_set_router_abr(area->ospf6))
815 ospf6_schedule_abr_task(ospf6);
816
817 return CMD_SUCCESS;
818 }
819
820 void 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)) {
827 bool update = false;
828
829 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa)) {
830 if (IMPORT_NAME(oa)
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 }
836
837 if (EXPORT_NAME(oa)
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 }
843 }
844
845 if (update && ospf6_check_and_set_router_abr(ospf6))
846 ospf6_schedule_abr_task(ospf6);
847 }
848 }
849
850 void ospf6_plist_update(struct prefix_list *plist)
851 {
852 struct listnode *node, *nnode;
853 struct ospf6_area *oa;
854 struct listnode *n;
855 const char *name = prefix_list_name(plist);
856 struct ospf6 *ospf6 = NULL;
857
858 if (prefix_list_afi(plist) != AFI_IP6)
859 return;
860
861 for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6)) {
862 bool update = false;
863
864 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa)) {
865 if (PREFIX_NAME_IN(oa)
866 && !strcmp(PREFIX_NAME_IN(oa), name)) {
867 PREFIX_LIST_IN(oa) = prefix_list_lookup(
868 AFI_IP6, PREFIX_NAME_IN(oa));
869 update = true;
870 }
871 if (PREFIX_NAME_OUT(oa)
872 && !strcmp(PREFIX_NAME_OUT(oa), name)) {
873 PREFIX_LIST_OUT(oa) = prefix_list_lookup(
874 AFI_IP6, PREFIX_NAME_OUT(oa));
875 update = true;
876 }
877 }
878
879 if (update && ospf6_check_and_set_router_abr(ospf6))
880 ospf6_schedule_abr_task(ospf6);
881 }
882 }
883
884 DEFUN (area_import_list,
885 area_import_list_cmd,
886 "area <A.B.C.D|(0-4294967295)> import-list ACCESSLIST6_NAME",
887 "OSPF6 area parameters\n"
888 "OSPF6 area ID in IP address format\n"
889 "OSPF6 area ID as a decimal value\n"
890 "Set the filter for networks from other areas announced to the specified one\n"
891 "Name of the access-list\n")
892 {
893 int idx_ipv4 = 1;
894 int idx_name = 3;
895 struct ospf6_area *area;
896 struct access_list *list;
897
898 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
899
900 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area, ospf6);
901
902 list = access_list_lookup(AFI_IP6, argv[idx_name]->arg);
903
904 IMPORT_LIST(area) = list;
905
906 if (IMPORT_NAME(area))
907 free(IMPORT_NAME(area));
908
909 IMPORT_NAME(area) = strdup(argv[idx_name]->arg);
910 if (ospf6_check_and_set_router_abr(area->ospf6))
911 ospf6_schedule_abr_task(ospf6);
912
913 return CMD_SUCCESS;
914 }
915
916 DEFUN (no_area_import_list,
917 no_area_import_list_cmd,
918 "no area <A.B.C.D|(0-4294967295)> import-list ACCESSLIST6_NAME",
919 NO_STR
920 "OSPF6 area parameters\n"
921 "OSPF6 area ID in IP address format\n"
922 "OSPF6 area ID as a decimal value\n"
923 "Unset the filter for networks announced to other areas\n"
924 "Name of the access-list\n")
925 {
926 int idx_ipv4 = 2;
927 struct ospf6_area *area;
928
929 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
930
931 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area, ospf6);
932
933 IMPORT_LIST(area) = NULL;
934
935 if (IMPORT_NAME(area))
936 free(IMPORT_NAME(area));
937
938 IMPORT_NAME(area) = NULL;
939 if (ospf6_check_and_set_router_abr(area->ospf6))
940 ospf6_schedule_abr_task(ospf6);
941
942 return CMD_SUCCESS;
943 }
944
945 DEFUN (area_export_list,
946 area_export_list_cmd,
947 "area <A.B.C.D|(0-4294967295)> export-list ACCESSLIST6_NAME",
948 "OSPF6 area parameters\n"
949 "OSPF6 area ID in IP address format\n"
950 "OSPF6 area ID as a decimal value\n"
951 "Set the filter for networks announced to other areas\n"
952 "Name of the access-list\n")
953 {
954 int idx_ipv4 = 1;
955 int idx_name = 3;
956 struct ospf6_area *area;
957 struct access_list *list;
958
959 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
960
961 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area, ospf6);
962
963 list = access_list_lookup(AFI_IP6, argv[idx_name]->arg);
964
965 EXPORT_LIST(area) = list;
966
967 if (EXPORT_NAME(area))
968 free(EXPORT_NAME(area));
969
970 EXPORT_NAME(area) = strdup(argv[idx_name]->arg);
971
972 /* Redo summaries if required */
973 if (ospf6_check_and_set_router_abr(area->ospf6))
974 ospf6_schedule_abr_task(ospf6);
975
976 return CMD_SUCCESS;
977 }
978
979 DEFUN (no_area_export_list,
980 no_area_export_list_cmd,
981 "no area <A.B.C.D|(0-4294967295)> export-list ACCESSLIST6_NAME",
982 NO_STR
983 "OSPF6 area parameters\n"
984 "OSPF6 area ID in IP address format\n"
985 "OSPF6 area ID as a decimal value\n"
986 "Unset the filter for networks announced to other areas\n"
987 "Name of the access-list\n")
988 {
989 int idx_ipv4 = 2;
990 struct ospf6_area *area;
991
992 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
993
994 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area, ospf6);
995
996 EXPORT_LIST(area) = NULL;
997
998 if (EXPORT_NAME(area))
999 free(EXPORT_NAME(area));
1000
1001 EXPORT_NAME(area) = NULL;
1002 if (ospf6_check_and_set_router_abr(area->ospf6))
1003 ospf6_schedule_abr_task(ospf6);
1004
1005 return CMD_SUCCESS;
1006 }
1007
1008 static int ipv6_ospf6_spf_tree_common(struct vty *vty, struct ospf6 *ospf6,
1009 bool uj)
1010 {
1011 struct listnode *node;
1012 struct ospf6_area *oa;
1013 struct prefix prefix;
1014 struct ospf6_vertex *root;
1015 struct ospf6_route *route;
1016 json_object *json = NULL;
1017 json_object *json_area = NULL;
1018 json_object *json_head = NULL;
1019
1020 if (uj)
1021 json = json_object_new_object();
1022 ospf6_linkstate_prefix(ospf6->router_id, htonl(0), &prefix);
1023 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
1024 if (uj) {
1025 json_area = json_object_new_object();
1026 json_head = json_object_new_object();
1027 }
1028 route = ospf6_route_lookup(&prefix, oa->spf_table);
1029 if (route == NULL) {
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);
1040 continue;
1041 }
1042 root = (struct ospf6_vertex *)route->route_option;
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
1052 if (uj)
1053 vty_json(vty, json);
1054
1055 return CMD_SUCCESS;
1056 }
1057
1058 DEFUN(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)
1064 {
1065 struct listnode *node;
1066 struct ospf6 *ospf6;
1067 const char *vrf_name = NULL;
1068 bool all_vrf = false;
1069 int idx_vrf = 0;
1070 bool uj = use_json(argc, argv);
1071
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
1082 OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
1083
1084 return CMD_SUCCESS;
1085 }
1086
1087 static 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 {
1092
1093 struct ospf6_area *oa;
1094 struct prefix prefix;
1095 struct ospf6_vertex *root;
1096 struct ospf6_route *route;
1097
1098 ospf6_linkstate_prefix(ospf6->router_id, htonl(0), &prefix);
1099
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;
1113 ospf6_spf_display_subtree(vty, "", 0, root, NULL, false);
1114
1115 return CMD_SUCCESS;
1116 }
1117
1118 DEFUN(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")
1124 {
1125 int idx_ipv4 = 4;
1126 uint32_t area_id;
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
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
1151 OSPF6_CMD_CHECK_VRF(false, all_vrf, ospf6);
1152
1153 return CMD_SUCCESS;
1154 }
1155
1156 static int
1157 show_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 {
1162 struct ospf6_area *oa;
1163 struct ospf6_vertex *root;
1164 struct ospf6_route *route;
1165 struct ospf6_route_table *spf_table;
1166 unsigned char tmp_debug_ospf6_spf = 0;
1167
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) {
1184 ospf6_spf_table_finish(spf_table);
1185 ospf6_route_table_delete(spf_table);
1186 return CMD_SUCCESS;
1187 }
1188 root = (struct ospf6_vertex *)route->route_option;
1189 ospf6_spf_display_subtree(vty, "", 0, root, NULL, false);
1190
1191 ospf6_spf_table_finish(spf_table);
1192 ospf6_route_table_delete(spf_table);
1193
1194 return CMD_SUCCESS;
1195 }
1196
1197 DEFUN(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
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
1241 OSPF6_CMD_CHECK_VRF(false, all_vrf, ospf6);
1242
1243 return CMD_SUCCESS;
1244 }
1245
1246 DEFUN (ospf6_area_stub,
1247 ospf6_area_stub_cmd,
1248 "area <A.B.C.D|(0-4294967295)> stub",
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 {
1254 int idx_ipv4_number = 1;
1255 struct ospf6_area *area;
1256
1257 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1258
1259 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area, ospf6);
1260
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 }
1266
1267 ospf6_area_no_summary_unset(ospf6, area);
1268
1269 return CMD_SUCCESS;
1270 }
1271
1272 DEFUN (ospf6_area_stub_no_summary,
1273 ospf6_area_stub_no_summary_cmd,
1274 "area <A.B.C.D|(0-4294967295)> stub no-summary",
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 {
1281 int idx_ipv4_number = 1;
1282 struct ospf6_area *area;
1283
1284 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1285
1286 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area, ospf6);
1287
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 }
1293
1294 ospf6_area_no_summary_set(ospf6, area);
1295
1296 return CMD_SUCCESS;
1297 }
1298
1299 DEFUN (no_ospf6_area_stub,
1300 no_ospf6_area_stub_cmd,
1301 "no area <A.B.C.D|(0-4294967295)> stub",
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 {
1308 int idx_ipv4_number = 2;
1309 struct ospf6_area *area;
1310
1311 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1312
1313 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area, ospf6);
1314
1315 ospf6_area_stub_unset(ospf6, area);
1316 ospf6_area_no_summary_unset(ospf6, area);
1317
1318 return CMD_SUCCESS;
1319 }
1320
1321 DEFUN (no_ospf6_area_stub_no_summary,
1322 no_ospf6_area_stub_no_summary_cmd,
1323 "no area <A.B.C.D|(0-4294967295)> stub no-summary",
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 {
1331 int idx_ipv4_number = 2;
1332 struct ospf6_area *area;
1333
1334 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1335
1336 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area, ospf6);
1337
1338 ospf6_area_stub_unset(ospf6, area);
1339 ospf6_area_no_summary_unset(ospf6, area);
1340
1341 return CMD_SUCCESS;
1342 }
1343
1344 DEFPY(ospf6_area_nssa, ospf6_area_nssa_cmd,
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 }]",
1350 "OSPF6 area parameters\n"
1351 "OSPF6 area ID in IP address format\n"
1352 "OSPF6 area ID as a decimal value\n"
1353 "Configure OSPF6 area as nssa\n"
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"
1359 "Do not inject inter-area routes into area\n")
1360 {
1361 struct ospf6_area *area;
1362
1363 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1364 OSPF6_CMD_AREA_GET(area_str, area, ospf6);
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
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
1381 if (no_summary)
1382 ospf6_area_no_summary_set(ospf6, area);
1383 else
1384 ospf6_area_no_summary_unset(ospf6, area);
1385
1386 if (ospf6_check_and_set_router_abr(ospf6)) {
1387 ospf6_abr_defaults_to_stub(ospf6);
1388 ospf6_abr_nssa_type_7_defaults(ospf6);
1389 }
1390
1391 return CMD_SUCCESS;
1392 }
1393
1394 DEFPY(no_ospf6_area_nssa, no_ospf6_area_nssa_cmd,
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 }]",
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"
1404 "Configure OSPF6 area as nssa\n"
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"
1410 "Do not inject inter-area routes into area\n")
1411 {
1412 struct ospf6_area *area;
1413
1414 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1415 OSPF6_CMD_AREA_GET(area_str, area, ospf6);
1416
1417 ospf6_area_nssa_unset(ospf6, area);
1418 ospf6_area_no_summary_unset(ospf6, area);
1419 ospf6_nssa_default_originate_unset(ospf6, area);
1420
1421 return CMD_SUCCESS;
1422 }
1423
1424
1425 void ospf6_area_init(void)
1426 {
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);
1430
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);
1437
1438
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);
1443
1444 install_element(OSPF6_NODE, &area_filter_list_cmd);
1445 install_element(OSPF6_NODE, &no_area_filter_list_cmd);
1446
1447 /* "area nssa" commands. */
1448 install_element(OSPF6_NODE, &ospf6_area_nssa_cmd);
1449 install_element(OSPF6_NODE, &no_ospf6_area_nssa_cmd);
1450 }
1451
1452 void ospf6_area_interface_delete(struct ospf6_interface *oi)
1453 {
1454 struct ospf6_area *oa;
1455 struct listnode *node, *nnode;
1456 struct ospf6 *ospf6;
1457
1458 for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6)) {
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);
1462 }
1463 }