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