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