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