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