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