]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_area.c
Merge pull request #2946 from mjstapp/dplane_2
[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))
141 zlog_debug("Stubbing out area for if %s\n", area->name);
142 OSPF6_OPT_CLEAR(area->options, OSPF6_OPT_E);
143 } else if (IS_AREA_ENABLED(area)) {
144 if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER))
145 zlog_debug("Normal area for if %s\n", area->name);
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
d62a17ae 453 zlog_debug("%s: for prefix %s, flag = %x\n", __func__,
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,
6147e2c6 570 "area A.B.C.D filter-list prefix WORD <in|out>",
b2d4d039
RW
571 "OSPF6 area parameters\n"
572 "OSPF6 area ID in IP address format\n"
573 "Filter networks between OSPF6 areas\n"
574 "Filter prefixes between OSPF6 areas\n"
34956b31 575 "Name of an IPv6 prefix-list\n"
576 "Filter networks sent to this area\n"
577 "Filter networks sent from this area\n")
578{
d62a17ae 579 char *inout = argv[argc - 1]->text;
580 char *areaid = argv[1]->arg;
581 char *plistname = argv[4]->arg;
582
583 struct ospf6_area *area;
584 struct prefix_list *plist;
585
586 OSPF6_CMD_AREA_GET(areaid, area);
587
588 plist = prefix_list_lookup(AFI_IP6, plistname);
589 if (strmatch(inout, "in")) {
590 PREFIX_LIST_IN(area) = plist;
427f8e61 591 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
996c9314
LB
592 PREFIX_NAME_IN(area) =
593 XSTRDUP(MTYPE_OSPF6_PLISTNAME, plistname);
d62a17ae 594 ospf6_abr_reimport(area);
595 } else {
596 PREFIX_LIST_OUT(area) = plist;
427f8e61 597 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
996c9314
LB
598 PREFIX_NAME_OUT(area) =
599 XSTRDUP(MTYPE_OSPF6_PLISTNAME, plistname);
d62a17ae 600 ospf6_abr_enable_area(area);
601 }
602
603 return CMD_SUCCESS;
34956b31 604}
d62a17ae 605
34956b31 606DEFUN (no_area_filter_list,
607 no_area_filter_list_cmd,
6147e2c6 608 "no area A.B.C.D filter-list prefix WORD <in|out>",
34956b31 609 NO_STR
b2d4d039
RW
610 "OSPF6 area parameters\n"
611 "OSPF6 area ID in IP address format\n"
612 "Filter networks between OSPF6 areas\n"
613 "Filter prefixes between OSPF6 areas\n"
34956b31 614 "Name of an IPv6 prefix-list\n"
615 "Filter networks sent to this area\n"
616 "Filter networks sent from this area\n")
617{
d62a17ae 618 char *inout = argv[argc - 1]->text;
619 char *areaid = argv[2]->arg;
620 char *plistname = argv[5]->arg;
621
622 struct ospf6_area *area;
623
624 OSPF6_CMD_AREA_GET(areaid, area);
625
626 if (strmatch(inout, "in")) {
627 if (PREFIX_NAME_IN(area))
628 if (!strmatch(PREFIX_NAME_IN(area), plistname))
629 return CMD_SUCCESS;
630
631 PREFIX_LIST_IN(area) = NULL;
427f8e61 632 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
d62a17ae 633 ospf6_abr_reimport(area);
634 } else {
635 if (PREFIX_NAME_OUT(area))
636 if (!strmatch(PREFIX_NAME_OUT(area), plistname))
637 return CMD_SUCCESS;
638
427f8e61 639 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
d62a17ae 640 ospf6_abr_enable_area(area);
641 }
642
643 return CMD_SUCCESS;
34956b31 644}
645
427f8e61
DL
646void ospf6_area_plist_update(struct prefix_list *plist, int add)
647{
648 struct ospf6_area *oa;
649 struct listnode *n;
650 const char *name = prefix_list_name(plist);
651
e017797b
DS
652 if (!ospf6)
653 return;
654
427f8e61 655 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa)) {
ff6bda17 656 if (PREFIX_NAME_IN(oa) && !strcmp(PREFIX_NAME_IN(oa), name))
427f8e61 657 PREFIX_LIST_IN(oa) = add ? plist : NULL;
ff6bda17 658 if (PREFIX_NAME_OUT(oa) && !strcmp(PREFIX_NAME_OUT(oa), name))
427f8e61
DL
659 PREFIX_LIST_OUT(oa) = add ? plist : NULL;
660 }
661}
662
34956b31 663DEFUN (area_import_list,
664 area_import_list_cmd,
665 "area A.B.C.D import-list NAME",
b2d4d039
RW
666 "OSPF6 area parameters\n"
667 "OSPF6 area ID in IP address format\n"
34956b31 668 "Set the filter for networks from other areas announced to the specified one\n"
669 "Name of the acess-list\n")
670{
d62a17ae 671 int idx_ipv4 = 1;
672 int idx_name = 3;
673 struct ospf6_area *area;
674 struct access_list *list;
34956b31 675
d62a17ae 676 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
34956b31 677
d62a17ae 678 list = access_list_lookup(AFI_IP6, argv[idx_name]->arg);
34956b31 679
d62a17ae 680 IMPORT_LIST(area) = list;
34956b31 681
d62a17ae 682 if (IMPORT_NAME(area))
683 free(IMPORT_NAME(area));
34956b31 684
d62a17ae 685 IMPORT_NAME(area) = strdup(argv[idx_name]->arg);
686 ospf6_abr_reimport(area);
34956b31 687
d62a17ae 688 return CMD_SUCCESS;
34956b31 689}
690
691DEFUN (no_area_import_list,
692 no_area_import_list_cmd,
693 "no area A.B.C.D import-list NAME",
6fbde29d 694 NO_STR
b2d4d039
RW
695 "OSPF6 area parameters\n"
696 "OSPF6 area ID in IP address format\n"
34956b31 697 "Unset the filter for networks announced to other areas\n"
6fbde29d 698 "Name of the access-list\n")
34956b31 699{
d62a17ae 700 int idx_ipv4 = 2;
701 struct ospf6_area *area;
34956b31 702
d62a17ae 703 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
34956b31 704
d62a17ae 705 IMPORT_LIST(area) = 0;
34956b31 706
d62a17ae 707 if (IMPORT_NAME(area))
708 free(IMPORT_NAME(area));
34956b31 709
d62a17ae 710 IMPORT_NAME(area) = NULL;
711 ospf6_abr_reimport(area);
34956b31 712
d62a17ae 713 return CMD_SUCCESS;
34956b31 714}
715
716DEFUN (area_export_list,
717 area_export_list_cmd,
718 "area A.B.C.D export-list NAME",
b2d4d039
RW
719 "OSPF6 area parameters\n"
720 "OSPF6 area ID in IP address format\n"
34956b31 721 "Set the filter for networks announced to other areas\n"
722 "Name of the acess-list\n")
723{
d62a17ae 724 int idx_ipv4 = 1;
725 int idx_name = 3;
726 struct ospf6_area *area;
727 struct access_list *list;
34956b31 728
d62a17ae 729 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
34956b31 730
d62a17ae 731 list = access_list_lookup(AFI_IP6, argv[idx_name]->arg);
34956b31 732
d62a17ae 733 EXPORT_LIST(area) = list;
34956b31 734
d62a17ae 735 if (EXPORT_NAME(area))
736 free(EXPORT_NAME(area));
34956b31 737
d62a17ae 738 EXPORT_NAME(area) = strdup(argv[idx_name]->arg);
739 ospf6_abr_enable_area(area);
34956b31 740
d62a17ae 741 return CMD_SUCCESS;
34956b31 742}
743
744DEFUN (no_area_export_list,
745 no_area_export_list_cmd,
746 "no area A.B.C.D export-list NAME",
6fbde29d 747 NO_STR
b2d4d039
RW
748 "OSPF6 area parameters\n"
749 "OSPF6 area ID in IP address format\n"
34956b31 750 "Unset the filter for networks announced to other areas\n"
751 "Name of the access-list\n")
752{
d62a17ae 753 int idx_ipv4 = 2;
754 struct ospf6_area *area;
34956b31 755
d62a17ae 756 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
34956b31 757
d62a17ae 758 EXPORT_LIST(area) = 0;
34956b31 759
d62a17ae 760 if (EXPORT_NAME(area))
761 free(EXPORT_NAME(area));
34956b31 762
d62a17ae 763 EXPORT_NAME(area) = NULL;
764 ospf6_abr_enable_area(area);
34956b31 765
d62a17ae 766 return CMD_SUCCESS;
34956b31 767}
768
508e53e2 769DEFUN (show_ipv6_ospf6_spf_tree,
770 show_ipv6_ospf6_spf_tree_cmd,
771 "show ipv6 ospf6 spf tree",
772 SHOW_STR
773 IP6_STR
774 OSPF6_STR
0437e105 775 "Shortest Path First calculation\n"
508e53e2 776 "Show SPF tree\n")
718e3744 777{
d62a17ae 778 struct listnode *node;
779 struct ospf6_area *oa;
780 struct ospf6_vertex *root;
781 struct ospf6_route *route;
782 struct prefix prefix;
783
784 OSPF6_CMD_CHECK_RUNNING();
785
786 ospf6_linkstate_prefix(ospf6->router_id, htonl(0), &prefix);
787
788 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
789 route = ospf6_route_lookup(&prefix, oa->spf_table);
790 if (route == NULL) {
791 vty_out(vty, "LS entry for root not found in area %s\n",
792 oa->name);
793 continue;
794 }
795 root = (struct ospf6_vertex *)route->route_option;
796 ospf6_spf_display_subtree(vty, "", 0, root);
797 }
798
799 return CMD_SUCCESS;
508e53e2 800}
801
802DEFUN (show_ipv6_ospf6_area_spf_tree,
803 show_ipv6_ospf6_area_spf_tree_cmd,
804 "show ipv6 ospf6 area A.B.C.D spf tree",
805 SHOW_STR
806 IP6_STR
807 OSPF6_STR
808 OSPF6_AREA_STR
809 OSPF6_AREA_ID_STR
0437e105 810 "Shortest Path First calculation\n"
508e53e2 811 "Show SPF tree\n")
812{
d62a17ae 813 int idx_ipv4 = 4;
d7c0a89a 814 uint32_t area_id;
d62a17ae 815 struct ospf6_area *oa;
816 struct ospf6_vertex *root;
817 struct ospf6_route *route;
818 struct prefix prefix;
819
820 OSPF6_CMD_CHECK_RUNNING();
821
822 ospf6_linkstate_prefix(ospf6->router_id, htonl(0), &prefix);
823
824 if (inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id) != 1) {
825 vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4]->arg);
826 return CMD_SUCCESS;
827 }
828 oa = ospf6_area_lookup(area_id, ospf6);
829 if (oa == NULL) {
830 vty_out(vty, "No such Area: %s\n", argv[idx_ipv4]->arg);
831 return CMD_SUCCESS;
832 }
833
834 route = ospf6_route_lookup(&prefix, oa->spf_table);
835 if (route == NULL) {
836 vty_out(vty, "LS entry for root not found in area %s\n",
837 oa->name);
838 return CMD_SUCCESS;
839 }
840 root = (struct ospf6_vertex *)route->route_option;
841 ospf6_spf_display_subtree(vty, "", 0, root);
842
843 return CMD_SUCCESS;
718e3744 844}
845
508e53e2 846DEFUN (show_ipv6_ospf6_simulate_spf_tree_root,
847 show_ipv6_ospf6_simulate_spf_tree_root_cmd,
848 "show ipv6 ospf6 simulate spf-tree A.B.C.D area A.B.C.D",
849 SHOW_STR
850 IP6_STR
851 OSPF6_STR
d7fa34c1 852 "Shortest Path First calculation\n"
508e53e2 853 "Show SPF tree\n"
d7fa34c1
QY
854 "Specify root's router-id to calculate another router's SPF tree\n"
855 "OSPF6 area parameters\n"
856 OSPF6_AREA_ID_STR)
508e53e2 857{
d62a17ae 858 int idx_ipv4 = 5;
859 int idx_ipv4_2 = 7;
d7c0a89a 860 uint32_t area_id;
d62a17ae 861 struct ospf6_area *oa;
862 struct ospf6_vertex *root;
863 struct ospf6_route *route;
864 struct prefix prefix;
d7c0a89a 865 uint32_t router_id;
d62a17ae 866 struct ospf6_route_table *spf_table;
867 unsigned char tmp_debug_ospf6_spf = 0;
868
869 OSPF6_CMD_CHECK_RUNNING();
870
871 inet_pton(AF_INET, argv[idx_ipv4]->arg, &router_id);
872 ospf6_linkstate_prefix(router_id, htonl(0), &prefix);
873
874 if (inet_pton(AF_INET, argv[idx_ipv4_2]->arg, &area_id) != 1) {
875 vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4_2]->arg);
876 return CMD_SUCCESS;
877 }
878 oa = ospf6_area_lookup(area_id, ospf6);
879 if (oa == NULL) {
880 vty_out(vty, "No such Area: %s\n", argv[idx_ipv4_2]->arg);
881 return CMD_SUCCESS;
882 }
883
884 tmp_debug_ospf6_spf = conf_debug_ospf6_spf;
885 conf_debug_ospf6_spf = 0;
886
887 spf_table = OSPF6_ROUTE_TABLE_CREATE(NONE, SPF_RESULTS);
888 ospf6_spf_calculation(router_id, spf_table, oa);
889
890 conf_debug_ospf6_spf = tmp_debug_ospf6_spf;
891
892 route = ospf6_route_lookup(&prefix, spf_table);
893 if (route == NULL) {
894 ospf6_spf_table_finish(spf_table);
895 ospf6_route_table_delete(spf_table);
896 return CMD_SUCCESS;
897 }
898 root = (struct ospf6_vertex *)route->route_option;
899 ospf6_spf_display_subtree(vty, "", 0, root);
900
901 ospf6_spf_table_finish(spf_table);
902 ospf6_route_table_delete(spf_table);
903
904 return CMD_SUCCESS;
508e53e2 905}
906
ca1f4309
DS
907DEFUN (ospf6_area_stub,
908 ospf6_area_stub_cmd,
6147e2c6 909 "area <A.B.C.D|(0-4294967295)> stub",
ca1f4309
DS
910 "OSPF6 area parameters\n"
911 "OSPF6 area ID in IP address format\n"
912 "OSPF6 area ID as a decimal value\n"
913 "Configure OSPF6 area as stub\n")
914{
d62a17ae 915 int idx_ipv4_number = 1;
916 struct ospf6_area *area;
ca1f4309 917
d62a17ae 918 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
ca1f4309 919
d62a17ae 920 if (!ospf6_area_stub_set(ospf6, area)) {
921 vty_out(vty,
922 "First deconfigure all virtual link through this area\n");
923 return CMD_WARNING_CONFIG_FAILED;
924 }
ca1f4309 925
d62a17ae 926 ospf6_area_no_summary_unset(ospf6, area);
ca1f4309 927
d62a17ae 928 return CMD_SUCCESS;
ca1f4309
DS
929}
930
931DEFUN (ospf6_area_stub_no_summary,
932 ospf6_area_stub_no_summary_cmd,
6147e2c6 933 "area <A.B.C.D|(0-4294967295)> stub no-summary",
ca1f4309
DS
934 "OSPF6 stub parameters\n"
935 "OSPF6 area ID in IP address format\n"
936 "OSPF6 area ID as a decimal value\n"
937 "Configure OSPF6 area as stub\n"
938 "Do not inject inter-area routes into stub\n")
939{
d62a17ae 940 int idx_ipv4_number = 1;
941 struct ospf6_area *area;
ca1f4309 942
d62a17ae 943 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
ca1f4309 944
d62a17ae 945 if (!ospf6_area_stub_set(ospf6, area)) {
946 vty_out(vty,
947 "First deconfigure all virtual link through this area\n");
948 return CMD_WARNING_CONFIG_FAILED;
949 }
ca1f4309 950
d62a17ae 951 ospf6_area_no_summary_set(ospf6, area);
ca1f4309 952
d62a17ae 953 return CMD_SUCCESS;
ca1f4309
DS
954}
955
956DEFUN (no_ospf6_area_stub,
957 no_ospf6_area_stub_cmd,
6147e2c6 958 "no area <A.B.C.D|(0-4294967295)> stub",
ca1f4309
DS
959 NO_STR
960 "OSPF6 area parameters\n"
961 "OSPF6 area ID in IP address format\n"
962 "OSPF6 area ID as a decimal value\n"
963 "Configure OSPF6 area as stub\n")
964{
d62a17ae 965 int idx_ipv4_number = 2;
966 struct ospf6_area *area;
ca1f4309 967
d62a17ae 968 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
ca1f4309 969
d62a17ae 970 ospf6_area_stub_unset(ospf6, area);
971 ospf6_area_no_summary_unset(ospf6, area);
ca1f4309 972
d62a17ae 973 return CMD_SUCCESS;
ca1f4309
DS
974}
975
976DEFUN (no_ospf6_area_stub_no_summary,
977 no_ospf6_area_stub_no_summary_cmd,
6147e2c6 978 "no area <A.B.C.D|(0-4294967295)> stub no-summary",
ca1f4309
DS
979 NO_STR
980 "OSPF6 area parameters\n"
981 "OSPF6 area ID in IP address format\n"
982 "OSPF6 area ID as a decimal value\n"
983 "Configure OSPF6 area as stub\n"
984 "Do not inject inter-area routes into area\n")
985{
d62a17ae 986 int idx_ipv4_number = 2;
987 struct ospf6_area *area;
ca1f4309 988
d62a17ae 989 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
ca1f4309 990
d62a17ae 991 ospf6_area_stub_unset(ospf6, area);
992 ospf6_area_no_summary_unset(ospf6, area);
ca1f4309 993
d62a17ae 994 return CMD_SUCCESS;
ca1f4309
DS
995}
996
d62a17ae 997void ospf6_area_init(void)
508e53e2 998{
d62a17ae 999 install_element(VIEW_NODE, &show_ipv6_ospf6_spf_tree_cmd);
1000 install_element(VIEW_NODE, &show_ipv6_ospf6_area_spf_tree_cmd);
1001 install_element(VIEW_NODE, &show_ipv6_ospf6_simulate_spf_tree_root_cmd);
ca1f4309 1002
d62a17ae 1003 install_element(OSPF6_NODE, &area_range_cmd);
1004 install_element(OSPF6_NODE, &no_area_range_cmd);
1005 install_element(OSPF6_NODE, &ospf6_area_stub_no_summary_cmd);
1006 install_element(OSPF6_NODE, &ospf6_area_stub_cmd);
1007 install_element(OSPF6_NODE, &no_ospf6_area_stub_no_summary_cmd);
1008 install_element(OSPF6_NODE, &no_ospf6_area_stub_cmd);
34956b31 1009
34956b31 1010
d62a17ae 1011 install_element(OSPF6_NODE, &area_import_list_cmd);
1012 install_element(OSPF6_NODE, &no_area_import_list_cmd);
1013 install_element(OSPF6_NODE, &area_export_list_cmd);
1014 install_element(OSPF6_NODE, &no_area_export_list_cmd);
34956b31 1015
d62a17ae 1016 install_element(OSPF6_NODE, &area_filter_list_cmd);
1017 install_element(OSPF6_NODE, &no_area_filter_list_cmd);
508e53e2 1018}