]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_area.c
Merge pull request #5081 from pguibert6WIND/show_brief_doc
[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"
049207c3 46#include "ospf6d.h"
718e3744 47
427f8e61
DL
48DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_PLISTNAME, "Prefix list name")
49
d62a17ae 50int ospf6_area_cmp(void *va, void *vb)
508e53e2 51{
d62a17ae 52 struct ospf6_area *oa = (struct ospf6_area *)va;
53 struct ospf6_area *ob = (struct ospf6_area *)vb;
54 return (ntohl(oa->area_id) < ntohl(ob->area_id) ? -1 : 1);
508e53e2 55}
718e3744 56
508e53e2 57/* schedule routing table recalculation */
d62a17ae 58static void ospf6_area_lsdb_hook_add(struct ospf6_lsa *lsa)
59{
60 switch (ntohs(lsa->header->type)) {
61 case OSPF6_LSTYPE_ROUTER:
62 case OSPF6_LSTYPE_NETWORK:
63 if (IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa->header->type)) {
996c9314
LB
64 zlog_debug("%s Examin LSA %s", __PRETTY_FUNCTION__,
65 lsa->name);
26e14616 66 zlog_debug(" Schedule SPF Calculation for %s",
d62a17ae 67 OSPF6_AREA(lsa->lsdb->data)->name);
68 }
69 ospf6_spf_schedule(
70 OSPF6_PROCESS(OSPF6_AREA(lsa->lsdb->data)->ospf6),
71 ospf6_lsadd_to_spf_reason(lsa));
72 break;
73
74 case OSPF6_LSTYPE_INTRA_PREFIX:
75 ospf6_intra_prefix_lsa_add(lsa);
76 break;
77
78 case OSPF6_LSTYPE_INTER_PREFIX:
79 case OSPF6_LSTYPE_INTER_ROUTER:
80 ospf6_abr_examin_summary(lsa,
81 (struct ospf6_area *)lsa->lsdb->data);
82 break;
83
84 default:
85 break;
86 }
718e3744 87}
88
d62a17ae 89static void ospf6_area_lsdb_hook_remove(struct ospf6_lsa *lsa)
90{
91 switch (ntohs(lsa->header->type)) {
92 case OSPF6_LSTYPE_ROUTER:
93 case OSPF6_LSTYPE_NETWORK:
94 if (IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa->header->type)) {
95 zlog_debug("LSA disappearing: %s", lsa->name);
96 zlog_debug("Schedule SPF Calculation for %s",
97 OSPF6_AREA(lsa->lsdb->data)->name);
98 }
99 ospf6_spf_schedule(
100 OSPF6_PROCESS(OSPF6_AREA(lsa->lsdb->data)->ospf6),
101 ospf6_lsremove_to_spf_reason(lsa));
102 break;
103
104 case OSPF6_LSTYPE_INTRA_PREFIX:
105 ospf6_intra_prefix_lsa_remove(lsa);
106 break;
107
108 case OSPF6_LSTYPE_INTER_PREFIX:
109 case OSPF6_LSTYPE_INTER_ROUTER:
110 ospf6_abr_examin_summary(lsa,
111 (struct ospf6_area *)lsa->lsdb->data);
112 break;
113
114 default:
115 break;
116 }
718e3744 117}
118
d62a17ae 119static void ospf6_area_route_hook_add(struct ospf6_route *route)
718e3744 120{
064d4355
CS
121 struct ospf6_route *copy;
122
123 copy = ospf6_route_copy(route);
d62a17ae 124 ospf6_route_add(copy, ospf6->route_table);
718e3744 125}
126
d62a17ae 127static void ospf6_area_route_hook_remove(struct ospf6_route *route)
718e3744 128{
d62a17ae 129 struct ospf6_route *copy;
718e3744 130
d62a17ae 131 copy = ospf6_route_lookup_identical(route, ospf6->route_table);
132 if (copy)
133 ospf6_route_remove(copy, ospf6->route_table);
718e3744 134}
135
d62a17ae 136static void ospf6_area_stub_update(struct ospf6_area *area)
ca1f4309
DS
137{
138
d62a17ae 139 if (IS_AREA_STUB(area)) {
140 if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER))
9165c5f5 141 zlog_debug("Stubbing out area for if %s", area->name);
d62a17ae 142 OSPF6_OPT_CLEAR(area->options, OSPF6_OPT_E);
143 } else if (IS_AREA_ENABLED(area)) {
144 if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER))
9165c5f5 145 zlog_debug("Normal area for if %s", area->name);
d62a17ae 146 OSPF6_OPT_SET(area->options, OSPF6_OPT_E);
147 ospf6_asbr_send_externals_to_area(area);
148 }
149
150 OSPF6_ROUTER_LSA_SCHEDULE(area);
ca1f4309
DS
151}
152
d62a17ae 153static int ospf6_area_stub_set(struct ospf6 *ospf6, struct ospf6_area *area)
ca1f4309 154{
d62a17ae 155 if (!IS_AREA_STUB(area)) {
156 SET_FLAG(area->flag, OSPF6_AREA_STUB);
157 ospf6_area_stub_update(area);
158 }
ca1f4309 159
d62a17ae 160 return (1);
ca1f4309
DS
161}
162
d62a17ae 163static void ospf6_area_stub_unset(struct ospf6 *ospf6, struct ospf6_area *area)
ca1f4309 164{
d62a17ae 165 if (IS_AREA_STUB(area)) {
166 UNSET_FLAG(area->flag, OSPF6_AREA_STUB);
167 ospf6_area_stub_update(area);
168 }
ca1f4309
DS
169}
170
d62a17ae 171static void ospf6_area_no_summary_set(struct ospf6 *ospf6,
172 struct ospf6_area *area)
ca1f4309 173{
d62a17ae 174 if (area) {
175 if (!area->no_summary) {
176 area->no_summary = 1;
177 ospf6_abr_range_reset_cost(ospf6);
178 ospf6_abr_prefix_resummarize(ospf6);
179 }
ca1f4309 180 }
ca1f4309
DS
181}
182
d62a17ae 183static void ospf6_area_no_summary_unset(struct ospf6 *ospf6,
184 struct ospf6_area *area)
ca1f4309 185{
d62a17ae 186 if (area) {
187 if (area->no_summary) {
188 area->no_summary = 0;
189 ospf6_abr_range_reset_cost(ospf6);
190 ospf6_abr_prefix_resummarize(ospf6);
191 }
ca1f4309 192 }
ca1f4309
DS
193}
194
79c3f4f4
QY
195/**
196 * Make new area structure.
197 *
198 * @param area_id - ospf6 area ID
199 * @param o - ospf6 instance
200 * @param df - display format for area ID
201 */
d7c0a89a 202struct ospf6_area *ospf6_area_create(uint32_t area_id, struct ospf6 *o, int df)
718e3744 203{
d62a17ae 204 struct ospf6_area *oa;
205
206 oa = XCALLOC(MTYPE_OSPF6_AREA, sizeof(struct ospf6_area));
207
208 switch (df) {
209 case OSPF6_AREA_FMT_DECIMAL:
210 snprintf(oa->name, sizeof(oa->name), "%u", ntohl(area_id));
211 break;
212 default:
213 case OSPF6_AREA_FMT_DOTTEDQUAD:
214 inet_ntop(AF_INET, &area_id, oa->name, sizeof(oa->name));
215 break;
216 }
217
218 oa->area_id = area_id;
219 oa->if_list = list_new();
220
221 oa->lsdb = ospf6_lsdb_create(oa);
222 oa->lsdb->hook_add = ospf6_area_lsdb_hook_add;
223 oa->lsdb->hook_remove = ospf6_area_lsdb_hook_remove;
224 oa->lsdb_self = ospf6_lsdb_create(oa);
da086a3b 225 oa->temp_router_lsa_lsdb = ospf6_lsdb_create(oa);
d62a17ae 226
227 oa->spf_table = OSPF6_ROUTE_TABLE_CREATE(AREA, SPF_RESULTS);
228 oa->spf_table->scope = oa;
229 oa->route_table = OSPF6_ROUTE_TABLE_CREATE(AREA, ROUTES);
230 oa->route_table->scope = oa;
231 oa->route_table->hook_add = ospf6_area_route_hook_add;
232 oa->route_table->hook_remove = ospf6_area_route_hook_remove;
233
234 oa->range_table = OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES);
235 oa->range_table->scope = oa;
236 bf_init(oa->range_table->idspace, 32);
237 oa->summary_prefix = OSPF6_ROUTE_TABLE_CREATE(AREA, SUMMARY_PREFIXES);
238 oa->summary_prefix->scope = oa;
239 oa->summary_router = OSPF6_ROUTE_TABLE_CREATE(AREA, SUMMARY_ROUTERS);
240 oa->summary_router->scope = oa;
9a703f8d 241 oa->router_lsa_size_limit = 1024 + 256;
d62a17ae 242
243 /* set default options */
244 if (CHECK_FLAG(o->flag, OSPF6_STUB_ROUTER)) {
245 OSPF6_OPT_CLEAR(oa->options, OSPF6_OPT_V6);
246 OSPF6_OPT_CLEAR(oa->options, OSPF6_OPT_R);
247 } else {
248 OSPF6_OPT_SET(oa->options, OSPF6_OPT_V6);
249 OSPF6_OPT_SET(oa->options, OSPF6_OPT_R);
250 }
251
252 OSPF6_OPT_SET(oa->options, OSPF6_OPT_E);
253
254 SET_FLAG(oa->flag, OSPF6_AREA_ACTIVE);
255 SET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
256
257 oa->ospf6 = o;
258 listnode_add_sort(o->area_list, oa);
259
260 if (area_id == OSPF_AREA_BACKBONE) {
261 o->backbone = oa;
262 }
263
264 return oa;
718e3744 265}
266
d62a17ae 267void ospf6_area_delete(struct ospf6_area *oa)
718e3744 268{
d62a17ae 269 struct listnode *n;
270 struct ospf6_interface *oi;
718e3744 271
d62a17ae 272 /* The ospf6_interface structs store configuration
273 * information which should not be lost/reset when
274 * deleting an area.
275 * So just detach the interface from the area and
276 * keep it around. */
277 for (ALL_LIST_ELEMENTS_RO(oa->if_list, n, oi))
278 oi->area = NULL;
d9628728 279
6a154c88 280 list_delete(&oa->if_list);
718e3744 281
d62a17ae 282 ospf6_lsdb_delete(oa->lsdb);
283 ospf6_lsdb_delete(oa->lsdb_self);
da086a3b 284 ospf6_lsdb_delete(oa->temp_router_lsa_lsdb);
6452df09 285
d62a17ae 286 ospf6_spf_table_finish(oa->spf_table);
287 ospf6_route_table_delete(oa->spf_table);
288 ospf6_route_table_delete(oa->route_table);
508e53e2 289
d62a17ae 290 ospf6_route_table_delete(oa->range_table);
291 ospf6_route_table_delete(oa->summary_prefix);
292 ospf6_route_table_delete(oa->summary_router);
508e53e2 293
d62a17ae 294 listnode_delete(oa->ospf6->area_list, oa);
295 oa->ospf6 = NULL;
508e53e2 296
d62a17ae 297 /* free area */
298 XFREE(MTYPE_OSPF6_AREA, oa);
508e53e2 299}
300
d7c0a89a 301struct ospf6_area *ospf6_area_lookup(uint32_t area_id, struct ospf6 *ospf6)
718e3744 302{
d62a17ae 303 struct ospf6_area *oa;
304 struct listnode *n;
718e3744 305
d62a17ae 306 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa))
307 if (oa->area_id == area_id)
308 return oa;
718e3744 309
d62a17ae 310 return (struct ospf6_area *)NULL;
718e3744 311}
312
d62a17ae 313void ospf6_area_enable(struct ospf6_area *oa)
718e3744 314{
d62a17ae 315 struct listnode *node, *nnode;
316 struct ospf6_interface *oi;
718e3744 317
d62a17ae 318 SET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
508e53e2 319
d62a17ae 320 for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi))
321 ospf6_interface_enable(oi);
322 ospf6_abr_enable_area(oa);
718e3744 323}
324
d62a17ae 325void ospf6_area_disable(struct ospf6_area *oa)
718e3744 326{
d62a17ae 327 struct listnode *node, *nnode;
328 struct ospf6_interface *oi;
718e3744 329
d62a17ae 330 UNSET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
718e3744 331
d62a17ae 332 for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi))
333 ospf6_interface_disable(oi);
d9628728 334
d62a17ae 335 ospf6_abr_disable_area(oa);
336 ospf6_lsdb_remove_all(oa->lsdb);
337 ospf6_lsdb_remove_all(oa->lsdb_self);
d9628728 338
d62a17ae 339 ospf6_spf_table_finish(oa->spf_table);
340 ospf6_route_remove_all(oa->route_table);
d9628728 341
d62a17ae 342 THREAD_OFF(oa->thread_router_lsa);
343 THREAD_OFF(oa->thread_intra_prefix_lsa);
508e53e2 344}
718e3744 345
6b0655a2 346
d62a17ae 347void ospf6_area_show(struct vty *vty, struct ospf6_area *oa)
508e53e2 348{
d62a17ae 349 struct listnode *i;
350 struct ospf6_interface *oi;
351 unsigned long result;
352
353 if (!IS_AREA_STUB(oa))
354 vty_out(vty, " Area %s\n", oa->name);
355 else {
356 if (oa->no_summary) {
357 vty_out(vty, " Area %s[Stub, No Summary]\n", oa->name);
358 } else {
359 vty_out(vty, " Area %s[Stub]\n", oa->name);
360 }
ca1f4309 361 }
d62a17ae 362 vty_out(vty, " Number of Area scoped LSAs is %u\n",
363 oa->lsdb->count);
364
365 vty_out(vty, " Interface attached to this area:");
366 for (ALL_LIST_ELEMENTS_RO(oa->if_list, i, oi))
367 vty_out(vty, " %s", oi->interface->name);
368 vty_out(vty, "\n");
369
370 if (oa->ts_spf.tv_sec || oa->ts_spf.tv_usec) {
371 result = monotime_since(&oa->ts_spf, NULL);
372 if (result / TIMER_SECOND_MICRO > 0) {
373 vty_out(vty, "SPF last executed %ld.%lds ago\n",
374 result / TIMER_SECOND_MICRO,
375 result % TIMER_SECOND_MICRO);
376 } else {
377 vty_out(vty, "SPF last executed %ldus ago\n", result);
378 }
379 } else
380 vty_out(vty, "SPF has not been run\n");
381}
382
383
384#define OSPF6_CMD_AREA_GET(str, oa) \
385 { \
386 char *ep; \
d7c0a89a 387 uint32_t area_id = htonl(strtoul(str, &ep, 10)); \
d62a17ae 388 if (*ep && inet_pton(AF_INET, str, &area_id) != 1) { \
389 vty_out(vty, "Malformed Area-ID: %s\n", str); \
390 return CMD_SUCCESS; \
391 } \
392 int format = !*ep ? OSPF6_AREA_FMT_DECIMAL \
393 : OSPF6_AREA_FMT_DOTTEDQUAD; \
394 oa = ospf6_area_lookup(area_id, ospf6); \
395 if (oa == NULL) \
396 oa = ospf6_area_create(area_id, ospf6, format); \
ca1f4309 397 }
6452df09 398
399DEFUN (area_range,
400 area_range_cmd,
6de69f83 401 "area <A.B.C.D|(0-4294967295)> range X:X::X:X/M [<advertise|not-advertise|cost (0-16777215)>]",
6fbde29d
RW
402 "OSPF6 area parameters\n"
403 "OSPF6 area ID in IP address format\n"
404 "OSPF6 area ID as a decimal value\n"
6452df09 405 "Configured address range\n"
406 "Specify IPv6 prefix\n"
093d7a3a
DW
407 "Advertise\n"
408 "Do not advertise\n"
409 "User specified metric for this range\n"
410 "Advertised metric for this range\n")
6452df09 411{
d62a17ae 412 int idx_ipv4 = 1;
413 int idx_ipv6_prefixlen = 3;
414 int idx_type = 4;
415 int ret;
416 struct ospf6_area *oa;
417 struct prefix prefix;
418 struct ospf6_route *range;
d7c0a89a 419 uint32_t cost = OSPF_AREA_RANGE_COST_UNSPEC;
d62a17ae 420
421 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, oa);
422
423 ret = str2prefix(argv[idx_ipv6_prefixlen]->arg, &prefix);
424 if (ret != 1 || prefix.family != AF_INET6) {
425 vty_out(vty, "Malformed argument: %s\n",
426 argv[idx_ipv6_prefixlen]->arg);
427 return CMD_SUCCESS;
c3c0ac83 428 }
d62a17ae 429
430 range = ospf6_route_lookup(&prefix, oa->range_table);
431 if (range == NULL) {
432 range = ospf6_route_create();
433 range->type = OSPF6_DEST_TYPE_RANGE;
434 range->prefix = prefix;
435 range->path.area_id = oa->area_id;
436 range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC;
c3c0ac83 437 }
d62a17ae 438
439 if (argc > idx_type) {
440 if (strmatch(argv[idx_type]->text, "not-advertise")) {
441 SET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
442 } else if (strmatch(argv[idx_type]->text, "advertise")) {
443 UNSET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
990baca0 444 cost = range->path.u.cost_config;
d62a17ae 445 } else {
446 cost = strtoul(argv[5]->arg, NULL, 10);
447 UNSET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
448 }
c3c0ac83 449 }
6452df09 450
d62a17ae 451 range->path.u.cost_config = cost;
c3c0ac83 452
9165c5f5 453 zlog_debug("%s: for prefix %s, flag = %x", __func__,
d62a17ae 454 argv[idx_ipv6_prefixlen]->arg, range->flag);
455 if (range->rnode == NULL) {
456 ospf6_route_add(range, oa->range_table);
457 }
c3c0ac83 458
d62a17ae 459 if (ospf6_is_router_abr(ospf6)) {
460 /* Redo summaries if required */
461 ospf6_abr_prefix_resummarize(ospf6);
462 }
86f9e5a7 463
d62a17ae 464 return CMD_SUCCESS;
6452df09 465}
466
6452df09 467DEFUN (no_area_range,
468 no_area_range_cmd,
3a2d747c 469 "no area <A.B.C.D|(0-4294967295)> range X:X::X:X/M [<advertise|not-advertise|cost (0-16777215)>]",
813d4307 470 NO_STR
6fbde29d 471 "OSPF6 area parameters\n"
3a2d747c
QY
472 "OSPF6 area ID in IP address format\n"
473 "OSPF6 area ID as a decimal value\n"
6452df09 474 "Configured address range\n"
3a2d747c
QY
475 "Specify IPv6 prefix\n"
476 "Advertise\n"
477 "Do not advertise\n"
478 "User specified metric for this range\n"
479 "Advertised metric for this range\n")
6452df09 480{
d62a17ae 481 int idx_ipv4 = 2;
482 int idx_ipv6 = 4;
483 int ret;
484 struct ospf6_area *oa;
485 struct prefix prefix;
486 struct ospf6_route *range, *route;
6452df09 487
d62a17ae 488 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, oa);
489
490 ret = str2prefix(argv[idx_ipv6]->arg, &prefix);
491 if (ret != 1 || prefix.family != AF_INET6) {
492 vty_out(vty, "Malformed argument: %s\n", argv[idx_ipv6]->arg);
493 return CMD_SUCCESS;
494 }
495
496 range = ospf6_route_lookup(&prefix, oa->range_table);
497 if (range == NULL) {
498 vty_out(vty, "Range %s does not exists.\n",
499 argv[idx_ipv6]->arg);
500 return CMD_SUCCESS;
501 }
502
503 if (ospf6_is_router_abr(oa->ospf6)) {
504 /* Blow away the aggregated LSA and route */
505 SET_FLAG(range->flag, OSPF6_ROUTE_REMOVE);
506
507 /* Redo summaries if required */
508 for (route = ospf6_route_head(ospf6->route_table); route;
509 route = ospf6_route_next(route))
510 ospf6_abr_originate_summary(route);
511
512 /* purge the old aggregated summary LSA */
513 ospf6_abr_originate_summary(range);
514 }
515 ospf6_route_remove(range, oa->range_table);
516
517 return CMD_SUCCESS;
518}
519
520void ospf6_area_config_write(struct vty *vty)
521{
522 struct listnode *node;
523 struct ospf6_area *oa;
524 struct ospf6_route *range;
525 char buf[PREFIX2STR_BUFFER];
526
527 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
528 for (range = ospf6_route_head(oa->range_table); range;
529 range = ospf6_route_next(range)) {
530 prefix2str(&range->prefix, buf, sizeof(buf));
531 vty_out(vty, " area %s range %s", oa->name, buf);
532
533 if (CHECK_FLAG(range->flag,
534 OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
535 vty_out(vty, " not-advertise");
536 } else {
537 // "advertise" is the default so we do not
538 // display it
539 if (range->path.u.cost_config
540 != OSPF_AREA_RANGE_COST_UNSPEC)
541 vty_out(vty, " cost %d",
542 range->path.u.cost_config);
543 }
544 vty_out(vty, "\n");
545 }
546 if (IS_AREA_STUB(oa)) {
547 if (oa->no_summary)
548 vty_out(vty, " area %s stub no-summary\n",
549 oa->name);
550 else
551 vty_out(vty, " area %s stub\n", oa->name);
552 }
553 if (PREFIX_NAME_IN(oa))
554 vty_out(vty, " area %s filter-list prefix %s in\n",
555 oa->name, PREFIX_NAME_IN(oa));
556 if (PREFIX_NAME_OUT(oa))
557 vty_out(vty, " area %s filter-list prefix %s out\n",
558 oa->name, PREFIX_NAME_OUT(oa));
559 if (IMPORT_NAME(oa))
560 vty_out(vty, " area %s import-list %s\n", oa->name,
561 IMPORT_NAME(oa));
562 if (EXPORT_NAME(oa))
563 vty_out(vty, " area %s export-list %s\n", oa->name,
564 EXPORT_NAME(oa));
ca1f4309 565 }
6452df09 566}
567
34956b31 568DEFUN (area_filter_list,
569 area_filter_list_cmd,
dd3ff9d8 570 "area <A.B.C.D|(0-4294967295)> filter-list prefix WORD <in|out>",
b2d4d039
RW
571 "OSPF6 area parameters\n"
572 "OSPF6 area ID in IP address format\n"
dd3ff9d8 573 "OSPF6 area ID as a decimal value\n"
b2d4d039
RW
574 "Filter networks between OSPF6 areas\n"
575 "Filter prefixes between OSPF6 areas\n"
34956b31 576 "Name of an IPv6 prefix-list\n"
577 "Filter networks sent to this area\n"
578 "Filter networks sent from this area\n")
579{
d62a17ae 580 char *inout = argv[argc - 1]->text;
581 char *areaid = argv[1]->arg;
582 char *plistname = argv[4]->arg;
583
584 struct ospf6_area *area;
585 struct prefix_list *plist;
586
587 OSPF6_CMD_AREA_GET(areaid, area);
588
589 plist = prefix_list_lookup(AFI_IP6, plistname);
590 if (strmatch(inout, "in")) {
591 PREFIX_LIST_IN(area) = plist;
427f8e61 592 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
996c9314
LB
593 PREFIX_NAME_IN(area) =
594 XSTRDUP(MTYPE_OSPF6_PLISTNAME, plistname);
d62a17ae 595 ospf6_abr_reimport(area);
596 } else {
597 PREFIX_LIST_OUT(area) = plist;
427f8e61 598 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
996c9314
LB
599 PREFIX_NAME_OUT(area) =
600 XSTRDUP(MTYPE_OSPF6_PLISTNAME, plistname);
d62a17ae 601 ospf6_abr_enable_area(area);
602 }
603
604 return CMD_SUCCESS;
34956b31 605}
d62a17ae 606
34956b31 607DEFUN (no_area_filter_list,
608 no_area_filter_list_cmd,
dd3ff9d8 609 "no area <A.B.C.D|(0-4294967295)> filter-list prefix WORD <in|out>",
34956b31 610 NO_STR
b2d4d039
RW
611 "OSPF6 area parameters\n"
612 "OSPF6 area ID in IP address format\n"
dd3ff9d8 613 "OSPF6 area ID as a decimal value\n"
b2d4d039
RW
614 "Filter networks between OSPF6 areas\n"
615 "Filter prefixes between OSPF6 areas\n"
34956b31 616 "Name of an IPv6 prefix-list\n"
617 "Filter networks sent to this area\n"
618 "Filter networks sent from this area\n")
619{
d62a17ae 620 char *inout = argv[argc - 1]->text;
621 char *areaid = argv[2]->arg;
622 char *plistname = argv[5]->arg;
623
624 struct ospf6_area *area;
625
626 OSPF6_CMD_AREA_GET(areaid, area);
627
628 if (strmatch(inout, "in")) {
629 if (PREFIX_NAME_IN(area))
630 if (!strmatch(PREFIX_NAME_IN(area), plistname))
631 return CMD_SUCCESS;
632
633 PREFIX_LIST_IN(area) = NULL;
427f8e61 634 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
d62a17ae 635 ospf6_abr_reimport(area);
636 } else {
637 if (PREFIX_NAME_OUT(area))
638 if (!strmatch(PREFIX_NAME_OUT(area), plistname))
639 return CMD_SUCCESS;
640
427f8e61 641 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
d62a17ae 642 ospf6_abr_enable_area(area);
643 }
644
645 return CMD_SUCCESS;
34956b31 646}
647
427f8e61
DL
648void ospf6_area_plist_update(struct prefix_list *plist, int add)
649{
650 struct ospf6_area *oa;
651 struct listnode *n;
652 const char *name = prefix_list_name(plist);
653
e017797b
DS
654 if (!ospf6)
655 return;
656
427f8e61 657 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa)) {
ff6bda17 658 if (PREFIX_NAME_IN(oa) && !strcmp(PREFIX_NAME_IN(oa), name))
427f8e61 659 PREFIX_LIST_IN(oa) = add ? plist : NULL;
ff6bda17 660 if (PREFIX_NAME_OUT(oa) && !strcmp(PREFIX_NAME_OUT(oa), name))
427f8e61
DL
661 PREFIX_LIST_OUT(oa) = add ? plist : NULL;
662 }
663}
664
34956b31 665DEFUN (area_import_list,
666 area_import_list_cmd,
dd3ff9d8 667 "area <A.B.C.D|(0-4294967295)> import-list NAME",
b2d4d039
RW
668 "OSPF6 area parameters\n"
669 "OSPF6 area ID in IP address format\n"
dd3ff9d8 670 "OSPF6 area ID as a decimal value\n"
34956b31 671 "Set the filter for networks from other areas announced to the specified one\n"
672 "Name of the acess-list\n")
673{
d62a17ae 674 int idx_ipv4 = 1;
675 int idx_name = 3;
676 struct ospf6_area *area;
677 struct access_list *list;
34956b31 678
d62a17ae 679 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
34956b31 680
d62a17ae 681 list = access_list_lookup(AFI_IP6, argv[idx_name]->arg);
34956b31 682
d62a17ae 683 IMPORT_LIST(area) = list;
34956b31 684
d62a17ae 685 if (IMPORT_NAME(area))
686 free(IMPORT_NAME(area));
34956b31 687
d62a17ae 688 IMPORT_NAME(area) = strdup(argv[idx_name]->arg);
689 ospf6_abr_reimport(area);
34956b31 690
d62a17ae 691 return CMD_SUCCESS;
34956b31 692}
693
694DEFUN (no_area_import_list,
695 no_area_import_list_cmd,
dd3ff9d8 696 "no area <A.B.C.D|(0-4294967295)> import-list NAME",
6fbde29d 697 NO_STR
b2d4d039
RW
698 "OSPF6 area parameters\n"
699 "OSPF6 area ID in IP address format\n"
dd3ff9d8 700 "OSPF6 area ID as a decimal value\n"
34956b31 701 "Unset the filter for networks announced to other areas\n"
6fbde29d 702 "Name of the access-list\n")
34956b31 703{
d62a17ae 704 int idx_ipv4 = 2;
705 struct ospf6_area *area;
34956b31 706
d62a17ae 707 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
34956b31 708
d62a17ae 709 IMPORT_LIST(area) = 0;
34956b31 710
d62a17ae 711 if (IMPORT_NAME(area))
712 free(IMPORT_NAME(area));
34956b31 713
d62a17ae 714 IMPORT_NAME(area) = NULL;
715 ospf6_abr_reimport(area);
34956b31 716
d62a17ae 717 return CMD_SUCCESS;
34956b31 718}
719
720DEFUN (area_export_list,
721 area_export_list_cmd,
dd3ff9d8 722 "area <A.B.C.D|(0-4294967295)> export-list NAME",
b2d4d039
RW
723 "OSPF6 area parameters\n"
724 "OSPF6 area ID in IP address format\n"
dd3ff9d8 725 "OSPF6 area ID as a decimal value\n"
34956b31 726 "Set the filter for networks announced to other areas\n"
727 "Name of the acess-list\n")
728{
d62a17ae 729 int idx_ipv4 = 1;
730 int idx_name = 3;
731 struct ospf6_area *area;
732 struct access_list *list;
34956b31 733
d62a17ae 734 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
34956b31 735
d62a17ae 736 list = access_list_lookup(AFI_IP6, argv[idx_name]->arg);
34956b31 737
d62a17ae 738 EXPORT_LIST(area) = list;
34956b31 739
d62a17ae 740 if (EXPORT_NAME(area))
741 free(EXPORT_NAME(area));
34956b31 742
d62a17ae 743 EXPORT_NAME(area) = strdup(argv[idx_name]->arg);
744 ospf6_abr_enable_area(area);
34956b31 745
d62a17ae 746 return CMD_SUCCESS;
34956b31 747}
748
749DEFUN (no_area_export_list,
750 no_area_export_list_cmd,
dd3ff9d8 751 "no area <A.B.C.D|(0-4294967295)> export-list NAME",
6fbde29d 752 NO_STR
b2d4d039
RW
753 "OSPF6 area parameters\n"
754 "OSPF6 area ID in IP address format\n"
dd3ff9d8 755 "OSPF6 area ID as a decimal value\n"
34956b31 756 "Unset the filter for networks announced to other areas\n"
757 "Name of the access-list\n")
758{
d62a17ae 759 int idx_ipv4 = 2;
760 struct ospf6_area *area;
34956b31 761
d62a17ae 762 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
34956b31 763
d62a17ae 764 EXPORT_LIST(area) = 0;
34956b31 765
d62a17ae 766 if (EXPORT_NAME(area))
767 free(EXPORT_NAME(area));
34956b31 768
d62a17ae 769 EXPORT_NAME(area) = NULL;
770 ospf6_abr_enable_area(area);
34956b31 771
d62a17ae 772 return CMD_SUCCESS;
34956b31 773}
774
508e53e2 775DEFUN (show_ipv6_ospf6_spf_tree,
776 show_ipv6_ospf6_spf_tree_cmd,
777 "show ipv6 ospf6 spf tree",
778 SHOW_STR
779 IP6_STR
780 OSPF6_STR
0437e105 781 "Shortest Path First calculation\n"
508e53e2 782 "Show SPF tree\n")
718e3744 783{
d62a17ae 784 struct listnode *node;
785 struct ospf6_area *oa;
786 struct ospf6_vertex *root;
787 struct ospf6_route *route;
788 struct prefix prefix;
789
790 OSPF6_CMD_CHECK_RUNNING();
791
792 ospf6_linkstate_prefix(ospf6->router_id, htonl(0), &prefix);
793
794 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
795 route = ospf6_route_lookup(&prefix, oa->spf_table);
796 if (route == NULL) {
797 vty_out(vty, "LS entry for root not found in area %s\n",
798 oa->name);
799 continue;
800 }
801 root = (struct ospf6_vertex *)route->route_option;
802 ospf6_spf_display_subtree(vty, "", 0, root);
803 }
804
805 return CMD_SUCCESS;
508e53e2 806}
807
808DEFUN (show_ipv6_ospf6_area_spf_tree,
809 show_ipv6_ospf6_area_spf_tree_cmd,
810 "show ipv6 ospf6 area A.B.C.D spf tree",
811 SHOW_STR
812 IP6_STR
813 OSPF6_STR
814 OSPF6_AREA_STR
815 OSPF6_AREA_ID_STR
0437e105 816 "Shortest Path First calculation\n"
508e53e2 817 "Show SPF tree\n")
818{
d62a17ae 819 int idx_ipv4 = 4;
d7c0a89a 820 uint32_t area_id;
d62a17ae 821 struct ospf6_area *oa;
822 struct ospf6_vertex *root;
823 struct ospf6_route *route;
824 struct prefix prefix;
825
826 OSPF6_CMD_CHECK_RUNNING();
827
828 ospf6_linkstate_prefix(ospf6->router_id, htonl(0), &prefix);
829
830 if (inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id) != 1) {
831 vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4]->arg);
832 return CMD_SUCCESS;
833 }
834 oa = ospf6_area_lookup(area_id, ospf6);
835 if (oa == NULL) {
836 vty_out(vty, "No such Area: %s\n", argv[idx_ipv4]->arg);
837 return CMD_SUCCESS;
838 }
839
840 route = ospf6_route_lookup(&prefix, oa->spf_table);
841 if (route == NULL) {
842 vty_out(vty, "LS entry for root not found in area %s\n",
843 oa->name);
844 return CMD_SUCCESS;
845 }
846 root = (struct ospf6_vertex *)route->route_option;
847 ospf6_spf_display_subtree(vty, "", 0, root);
848
849 return CMD_SUCCESS;
718e3744 850}
851
508e53e2 852DEFUN (show_ipv6_ospf6_simulate_spf_tree_root,
853 show_ipv6_ospf6_simulate_spf_tree_root_cmd,
854 "show ipv6 ospf6 simulate spf-tree A.B.C.D area A.B.C.D",
855 SHOW_STR
856 IP6_STR
857 OSPF6_STR
d7fa34c1 858 "Shortest Path First calculation\n"
508e53e2 859 "Show SPF tree\n"
d7fa34c1
QY
860 "Specify root's router-id to calculate another router's SPF tree\n"
861 "OSPF6 area parameters\n"
862 OSPF6_AREA_ID_STR)
508e53e2 863{
d62a17ae 864 int idx_ipv4 = 5;
865 int idx_ipv4_2 = 7;
d7c0a89a 866 uint32_t area_id;
d62a17ae 867 struct ospf6_area *oa;
868 struct ospf6_vertex *root;
869 struct ospf6_route *route;
870 struct prefix prefix;
d7c0a89a 871 uint32_t router_id;
d62a17ae 872 struct ospf6_route_table *spf_table;
873 unsigned char tmp_debug_ospf6_spf = 0;
874
875 OSPF6_CMD_CHECK_RUNNING();
876
877 inet_pton(AF_INET, argv[idx_ipv4]->arg, &router_id);
878 ospf6_linkstate_prefix(router_id, htonl(0), &prefix);
879
880 if (inet_pton(AF_INET, argv[idx_ipv4_2]->arg, &area_id) != 1) {
881 vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4_2]->arg);
882 return CMD_SUCCESS;
883 }
884 oa = ospf6_area_lookup(area_id, ospf6);
885 if (oa == NULL) {
886 vty_out(vty, "No such Area: %s\n", argv[idx_ipv4_2]->arg);
887 return CMD_SUCCESS;
888 }
889
890 tmp_debug_ospf6_spf = conf_debug_ospf6_spf;
891 conf_debug_ospf6_spf = 0;
892
893 spf_table = OSPF6_ROUTE_TABLE_CREATE(NONE, SPF_RESULTS);
894 ospf6_spf_calculation(router_id, spf_table, oa);
895
896 conf_debug_ospf6_spf = tmp_debug_ospf6_spf;
897
898 route = ospf6_route_lookup(&prefix, spf_table);
899 if (route == NULL) {
900 ospf6_spf_table_finish(spf_table);
901 ospf6_route_table_delete(spf_table);
902 return CMD_SUCCESS;
903 }
904 root = (struct ospf6_vertex *)route->route_option;
905 ospf6_spf_display_subtree(vty, "", 0, root);
906
907 ospf6_spf_table_finish(spf_table);
908 ospf6_route_table_delete(spf_table);
909
910 return CMD_SUCCESS;
508e53e2 911}
912
ca1f4309
DS
913DEFUN (ospf6_area_stub,
914 ospf6_area_stub_cmd,
6147e2c6 915 "area <A.B.C.D|(0-4294967295)> stub",
ca1f4309
DS
916 "OSPF6 area parameters\n"
917 "OSPF6 area ID in IP address format\n"
918 "OSPF6 area ID as a decimal value\n"
919 "Configure OSPF6 area as stub\n")
920{
d62a17ae 921 int idx_ipv4_number = 1;
922 struct ospf6_area *area;
ca1f4309 923
d62a17ae 924 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
ca1f4309 925
d62a17ae 926 if (!ospf6_area_stub_set(ospf6, area)) {
927 vty_out(vty,
928 "First deconfigure all virtual link through this area\n");
929 return CMD_WARNING_CONFIG_FAILED;
930 }
ca1f4309 931
d62a17ae 932 ospf6_area_no_summary_unset(ospf6, area);
ca1f4309 933
d62a17ae 934 return CMD_SUCCESS;
ca1f4309
DS
935}
936
937DEFUN (ospf6_area_stub_no_summary,
938 ospf6_area_stub_no_summary_cmd,
6147e2c6 939 "area <A.B.C.D|(0-4294967295)> stub no-summary",
ca1f4309
DS
940 "OSPF6 stub parameters\n"
941 "OSPF6 area ID in IP address format\n"
942 "OSPF6 area ID as a decimal value\n"
943 "Configure OSPF6 area as stub\n"
944 "Do not inject inter-area routes into stub\n")
945{
d62a17ae 946 int idx_ipv4_number = 1;
947 struct ospf6_area *area;
ca1f4309 948
d62a17ae 949 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
ca1f4309 950
d62a17ae 951 if (!ospf6_area_stub_set(ospf6, area)) {
952 vty_out(vty,
953 "First deconfigure all virtual link through this area\n");
954 return CMD_WARNING_CONFIG_FAILED;
955 }
ca1f4309 956
d62a17ae 957 ospf6_area_no_summary_set(ospf6, area);
ca1f4309 958
d62a17ae 959 return CMD_SUCCESS;
ca1f4309
DS
960}
961
962DEFUN (no_ospf6_area_stub,
963 no_ospf6_area_stub_cmd,
6147e2c6 964 "no area <A.B.C.D|(0-4294967295)> stub",
ca1f4309
DS
965 NO_STR
966 "OSPF6 area parameters\n"
967 "OSPF6 area ID in IP address format\n"
968 "OSPF6 area ID as a decimal value\n"
969 "Configure OSPF6 area as stub\n")
970{
d62a17ae 971 int idx_ipv4_number = 2;
972 struct ospf6_area *area;
ca1f4309 973
d62a17ae 974 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
ca1f4309 975
d62a17ae 976 ospf6_area_stub_unset(ospf6, area);
977 ospf6_area_no_summary_unset(ospf6, area);
ca1f4309 978
d62a17ae 979 return CMD_SUCCESS;
ca1f4309
DS
980}
981
982DEFUN (no_ospf6_area_stub_no_summary,
983 no_ospf6_area_stub_no_summary_cmd,
6147e2c6 984 "no area <A.B.C.D|(0-4294967295)> stub no-summary",
ca1f4309
DS
985 NO_STR
986 "OSPF6 area parameters\n"
987 "OSPF6 area ID in IP address format\n"
988 "OSPF6 area ID as a decimal value\n"
989 "Configure OSPF6 area as stub\n"
990 "Do not inject inter-area routes into area\n")
991{
d62a17ae 992 int idx_ipv4_number = 2;
993 struct ospf6_area *area;
ca1f4309 994
d62a17ae 995 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
ca1f4309 996
d62a17ae 997 ospf6_area_stub_unset(ospf6, area);
998 ospf6_area_no_summary_unset(ospf6, area);
ca1f4309 999
d62a17ae 1000 return CMD_SUCCESS;
ca1f4309
DS
1001}
1002
d62a17ae 1003void ospf6_area_init(void)
508e53e2 1004{
d62a17ae 1005 install_element(VIEW_NODE, &show_ipv6_ospf6_spf_tree_cmd);
1006 install_element(VIEW_NODE, &show_ipv6_ospf6_area_spf_tree_cmd);
1007 install_element(VIEW_NODE, &show_ipv6_ospf6_simulate_spf_tree_root_cmd);
ca1f4309 1008
d62a17ae 1009 install_element(OSPF6_NODE, &area_range_cmd);
1010 install_element(OSPF6_NODE, &no_area_range_cmd);
1011 install_element(OSPF6_NODE, &ospf6_area_stub_no_summary_cmd);
1012 install_element(OSPF6_NODE, &ospf6_area_stub_cmd);
1013 install_element(OSPF6_NODE, &no_ospf6_area_stub_no_summary_cmd);
1014 install_element(OSPF6_NODE, &no_ospf6_area_stub_cmd);
34956b31 1015
34956b31 1016
d62a17ae 1017 install_element(OSPF6_NODE, &area_import_list_cmd);
1018 install_element(OSPF6_NODE, &no_area_import_list_cmd);
1019 install_element(OSPF6_NODE, &area_export_list_cmd);
1020 install_element(OSPF6_NODE, &no_area_export_list_cmd);
34956b31 1021
d62a17ae 1022 install_element(OSPF6_NODE, &area_filter_list_cmd);
1023 install_element(OSPF6_NODE, &no_area_filter_list_cmd);
508e53e2 1024}
22b982df
PG
1025
1026void ospf6_area_interface_delete(struct ospf6_interface *oi)
1027{
1028 struct ospf6_area *oa;
1029 struct listnode *node, *nnode;
1030
1031 if (!ospf6)
1032 return;
1033 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa))
1034 if(listnode_lookup(oa->if_list, oi))
1035 listnode_delete(oa->if_list, oi);
1036
1037}