]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_area.c
Merge pull request #1031 from opensourcerouting/small-bits
[mirror_frr.git] / ospf6d / ospf6_area.c
1 /*
2 * Copyright (C) 2003 Yasuhiro Ohara
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 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
19 */
20
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"
32 #include "plist.h"
33 #include "filter.h"
34
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"
44 #include "ospf6_abr.h"
45 #include "ospf6_asbr.h"
46 #include "ospf6d.h"
47
48 DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_PLISTNAME, "Prefix list name")
49
50 int ospf6_area_cmp(void *va, void *vb)
51 {
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);
55 }
56
57 /* schedule routing table recalculation */
58 static 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 }
86 }
87
88 static 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 }
116 }
117
118 static void ospf6_area_route_hook_add(struct ospf6_route *route)
119 {
120 struct ospf6_route *copy = ospf6_route_copy(route);
121 ospf6_route_add(copy, ospf6->route_table);
122 }
123
124 static void ospf6_area_route_hook_remove(struct ospf6_route *route)
125 {
126 struct ospf6_route *copy;
127
128 copy = ospf6_route_lookup_identical(route, ospf6->route_table);
129 if (copy)
130 ospf6_route_remove(copy, ospf6->route_table);
131 }
132
133 static void ospf6_area_stub_update(struct ospf6_area *area)
134 {
135
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);
148 }
149
150 static int ospf6_area_stub_set(struct ospf6 *ospf6, struct ospf6_area *area)
151 {
152 if (!IS_AREA_STUB(area)) {
153 SET_FLAG(area->flag, OSPF6_AREA_STUB);
154 ospf6_area_stub_update(area);
155 }
156
157 return (1);
158 }
159
160 static void ospf6_area_stub_unset(struct ospf6 *ospf6, struct ospf6_area *area)
161 {
162 if (IS_AREA_STUB(area)) {
163 UNSET_FLAG(area->flag, OSPF6_AREA_STUB);
164 ospf6_area_stub_update(area);
165 }
166 }
167
168 static void ospf6_area_no_summary_set(struct ospf6 *ospf6,
169 struct ospf6_area *area)
170 {
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 }
177 }
178 }
179
180 static void ospf6_area_no_summary_unset(struct ospf6 *ospf6,
181 struct ospf6_area *area)
182 {
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 }
189 }
190 }
191
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 */
199 struct ospf6_area *ospf6_area_create(u_int32_t area_id, struct ospf6 *o, int df)
200 {
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;
260 }
261
262 void ospf6_area_delete(struct ospf6_area *oa)
263 {
264 struct listnode *n;
265 struct ospf6_interface *oi;
266
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;
274
275 list_delete(oa->if_list);
276
277 ospf6_lsdb_delete(oa->lsdb);
278 ospf6_lsdb_delete(oa->lsdb_self);
279
280 ospf6_spf_table_finish(oa->spf_table);
281 ospf6_route_table_delete(oa->spf_table);
282 ospf6_route_table_delete(oa->route_table);
283
284 ospf6_route_table_delete(oa->range_table);
285 ospf6_route_table_delete(oa->summary_prefix);
286 ospf6_route_table_delete(oa->summary_router);
287
288 listnode_delete(oa->ospf6->area_list, oa);
289 oa->ospf6 = NULL;
290
291 /* free area */
292 XFREE(MTYPE_OSPF6_AREA, oa);
293 }
294
295 struct ospf6_area *ospf6_area_lookup(u_int32_t area_id, struct ospf6 *ospf6)
296 {
297 struct ospf6_area *oa;
298 struct listnode *n;
299
300 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa))
301 if (oa->area_id == area_id)
302 return oa;
303
304 return (struct ospf6_area *)NULL;
305 }
306
307 void ospf6_area_enable(struct ospf6_area *oa)
308 {
309 struct listnode *node, *nnode;
310 struct ospf6_interface *oi;
311
312 SET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
313
314 for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi))
315 ospf6_interface_enable(oi);
316 ospf6_abr_enable_area(oa);
317 }
318
319 void ospf6_area_disable(struct ospf6_area *oa)
320 {
321 struct listnode *node, *nnode;
322 struct ospf6_interface *oi;
323
324 UNSET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
325
326 for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi))
327 ospf6_interface_disable(oi);
328
329 ospf6_abr_disable_area(oa);
330 ospf6_lsdb_remove_all(oa->lsdb);
331 ospf6_lsdb_remove_all(oa->lsdb_self);
332
333 ospf6_spf_table_finish(oa->spf_table);
334 ospf6_route_remove_all(oa->route_table);
335
336 THREAD_OFF(oa->thread_router_lsa);
337 THREAD_OFF(oa->thread_intra_prefix_lsa);
338 }
339
340
341 void ospf6_area_show(struct vty *vty, struct ospf6_area *oa)
342 {
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 }
355 }
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); \
391 }
392
393 DEFUN (area_range,
394 area_range_cmd,
395 "area <A.B.C.D|(0-4294967295)> range X:X::X:X/M [<advertise|not-advertise|cost (0-16777215)>]",
396 "OSPF6 area parameters\n"
397 "OSPF6 area ID in IP address format\n"
398 "OSPF6 area ID as a decimal value\n"
399 "Configured address range\n"
400 "Specify IPv6 prefix\n"
401 "Advertise\n"
402 "Do not advertise\n"
403 "User specified metric for this range\n"
404 "Advertised metric for this range\n")
405 {
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;
422 }
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;
431 }
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 }
442 }
443
444 range->path.u.cost_config = cost;
445
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 }
451
452 if (ospf6_is_router_abr(ospf6)) {
453 /* Redo summaries if required */
454 ospf6_abr_prefix_resummarize(ospf6);
455 }
456
457 return CMD_SUCCESS;
458 }
459
460 DEFUN (no_area_range,
461 no_area_range_cmd,
462 "no area <A.B.C.D|(0-4294967295)> range X:X::X:X/M [<advertise|not-advertise|cost (0-16777215)>]",
463 NO_STR
464 "OSPF6 area parameters\n"
465 "OSPF6 area ID in IP address format\n"
466 "OSPF6 area ID as a decimal value\n"
467 "Configured address range\n"
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")
473 {
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;
480
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
513 void 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));
558 }
559 }
560
561 DEFUN (area_filter_list,
562 area_filter_list_cmd,
563 "area A.B.C.D filter-list prefix WORD <in|out>",
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"
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 {
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;
584 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
585 PREFIX_NAME_IN(area) = XSTRDUP(MTYPE_OSPF6_PLISTNAME,
586 plistname);
587 ospf6_abr_reimport(area);
588 } else {
589 PREFIX_LIST_OUT(area) = plist;
590 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
591 PREFIX_NAME_OUT(area) = XSTRDUP(MTYPE_OSPF6_PLISTNAME,
592 plistname);
593 ospf6_abr_enable_area(area);
594 }
595
596 return CMD_SUCCESS;
597 }
598
599 DEFUN (no_area_filter_list,
600 no_area_filter_list_cmd,
601 "no area A.B.C.D filter-list prefix WORD <in|out>",
602 NO_STR
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"
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 {
611 char *inout = argv[argc - 1]->text;
612 char *areaid = argv[2]->arg;
613 char *plistname = argv[5]->arg;
614
615 struct ospf6_area *area;
616
617 OSPF6_CMD_AREA_GET(areaid, area);
618
619 if (strmatch(inout, "in")) {
620 if (PREFIX_NAME_IN(area))
621 if (!strmatch(PREFIX_NAME_IN(area), plistname))
622 return CMD_SUCCESS;
623
624 PREFIX_LIST_IN(area) = NULL;
625 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
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
632 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
633 ospf6_abr_enable_area(area);
634 }
635
636 return CMD_SUCCESS;
637 }
638
639 void 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
645 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa)) {
646 if (!strcmp(PREFIX_NAME_IN(oa), name))
647 PREFIX_LIST_IN(oa) = add ? plist : NULL;
648 if (!strcmp(PREFIX_NAME_OUT(oa), name))
649 PREFIX_LIST_OUT(oa) = add ? plist : NULL;
650 }
651 }
652
653 DEFUN (area_import_list,
654 area_import_list_cmd,
655 "area A.B.C.D import-list NAME",
656 "OSPF6 area parameters\n"
657 "OSPF6 area ID in IP address format\n"
658 "Set the filter for networks from other areas announced to the specified one\n"
659 "Name of the acess-list\n")
660 {
661 int idx_ipv4 = 1;
662 int idx_name = 3;
663 struct ospf6_area *area;
664 struct access_list *list;
665
666 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
667
668 list = access_list_lookup(AFI_IP6, argv[idx_name]->arg);
669
670 IMPORT_LIST(area) = list;
671
672 if (IMPORT_NAME(area))
673 free(IMPORT_NAME(area));
674
675 IMPORT_NAME(area) = strdup(argv[idx_name]->arg);
676 ospf6_abr_reimport(area);
677
678 return CMD_SUCCESS;
679 }
680
681 DEFUN (no_area_import_list,
682 no_area_import_list_cmd,
683 "no area A.B.C.D import-list NAME",
684 NO_STR
685 "OSPF6 area parameters\n"
686 "OSPF6 area ID in IP address format\n"
687 "Unset the filter for networks announced to other areas\n"
688 "Name of the access-list\n")
689 {
690 int idx_ipv4 = 2;
691 struct ospf6_area *area;
692
693 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
694
695 IMPORT_LIST(area) = 0;
696
697 if (IMPORT_NAME(area))
698 free(IMPORT_NAME(area));
699
700 IMPORT_NAME(area) = NULL;
701 ospf6_abr_reimport(area);
702
703 return CMD_SUCCESS;
704 }
705
706 DEFUN (area_export_list,
707 area_export_list_cmd,
708 "area A.B.C.D export-list NAME",
709 "OSPF6 area parameters\n"
710 "OSPF6 area ID in IP address format\n"
711 "Set the filter for networks announced to other areas\n"
712 "Name of the acess-list\n")
713 {
714 int idx_ipv4 = 1;
715 int idx_name = 3;
716 struct ospf6_area *area;
717 struct access_list *list;
718
719 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
720
721 list = access_list_lookup(AFI_IP6, argv[idx_name]->arg);
722
723 EXPORT_LIST(area) = list;
724
725 if (EXPORT_NAME(area))
726 free(EXPORT_NAME(area));
727
728 EXPORT_NAME(area) = strdup(argv[idx_name]->arg);
729 ospf6_abr_enable_area(area);
730
731 return CMD_SUCCESS;
732 }
733
734 DEFUN (no_area_export_list,
735 no_area_export_list_cmd,
736 "no area A.B.C.D export-list NAME",
737 NO_STR
738 "OSPF6 area parameters\n"
739 "OSPF6 area ID in IP address format\n"
740 "Unset the filter for networks announced to other areas\n"
741 "Name of the access-list\n")
742 {
743 int idx_ipv4 = 2;
744 struct ospf6_area *area;
745
746 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
747
748 EXPORT_LIST(area) = 0;
749
750 if (EXPORT_NAME(area))
751 free(EXPORT_NAME(area));
752
753 EXPORT_NAME(area) = NULL;
754 ospf6_abr_enable_area(area);
755
756 return CMD_SUCCESS;
757 }
758
759 DEFUN (show_ipv6_ospf6_spf_tree,
760 show_ipv6_ospf6_spf_tree_cmd,
761 "show ipv6 ospf6 spf tree",
762 SHOW_STR
763 IP6_STR
764 OSPF6_STR
765 "Shortest Path First caculation\n"
766 "Show SPF tree\n")
767 {
768 struct listnode *node;
769 struct ospf6_area *oa;
770 struct ospf6_vertex *root;
771 struct ospf6_route *route;
772 struct prefix prefix;
773
774 OSPF6_CMD_CHECK_RUNNING();
775
776 ospf6_linkstate_prefix(ospf6->router_id, htonl(0), &prefix);
777
778 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
779 route = ospf6_route_lookup(&prefix, oa->spf_table);
780 if (route == NULL) {
781 vty_out(vty, "LS entry for root not found in area %s\n",
782 oa->name);
783 continue;
784 }
785 root = (struct ospf6_vertex *)route->route_option;
786 ospf6_spf_display_subtree(vty, "", 0, root);
787 }
788
789 return CMD_SUCCESS;
790 }
791
792 DEFUN (show_ipv6_ospf6_area_spf_tree,
793 show_ipv6_ospf6_area_spf_tree_cmd,
794 "show ipv6 ospf6 area A.B.C.D spf tree",
795 SHOW_STR
796 IP6_STR
797 OSPF6_STR
798 OSPF6_AREA_STR
799 OSPF6_AREA_ID_STR
800 "Shortest Path First caculation\n"
801 "Show SPF tree\n")
802 {
803 int idx_ipv4 = 4;
804 u_int32_t area_id;
805 struct ospf6_area *oa;
806 struct ospf6_vertex *root;
807 struct ospf6_route *route;
808 struct prefix prefix;
809
810 OSPF6_CMD_CHECK_RUNNING();
811
812 ospf6_linkstate_prefix(ospf6->router_id, htonl(0), &prefix);
813
814 if (inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id) != 1) {
815 vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4]->arg);
816 return CMD_SUCCESS;
817 }
818 oa = ospf6_area_lookup(area_id, ospf6);
819 if (oa == NULL) {
820 vty_out(vty, "No such Area: %s\n", argv[idx_ipv4]->arg);
821 return CMD_SUCCESS;
822 }
823
824 route = ospf6_route_lookup(&prefix, oa->spf_table);
825 if (route == NULL) {
826 vty_out(vty, "LS entry for root not found in area %s\n",
827 oa->name);
828 return CMD_SUCCESS;
829 }
830 root = (struct ospf6_vertex *)route->route_option;
831 ospf6_spf_display_subtree(vty, "", 0, root);
832
833 return CMD_SUCCESS;
834 }
835
836 DEFUN (show_ipv6_ospf6_simulate_spf_tree_root,
837 show_ipv6_ospf6_simulate_spf_tree_root_cmd,
838 "show ipv6 ospf6 simulate spf-tree A.B.C.D area A.B.C.D",
839 SHOW_STR
840 IP6_STR
841 OSPF6_STR
842 "Shortest Path First calculation\n"
843 "Show SPF tree\n"
844 "Specify root's router-id to calculate another router's SPF tree\n"
845 "OSPF6 area parameters\n"
846 OSPF6_AREA_ID_STR)
847 {
848 int idx_ipv4 = 5;
849 int idx_ipv4_2 = 7;
850 u_int32_t area_id;
851 struct ospf6_area *oa;
852 struct ospf6_vertex *root;
853 struct ospf6_route *route;
854 struct prefix prefix;
855 u_int32_t router_id;
856 struct ospf6_route_table *spf_table;
857 unsigned char tmp_debug_ospf6_spf = 0;
858
859 OSPF6_CMD_CHECK_RUNNING();
860
861 inet_pton(AF_INET, argv[idx_ipv4]->arg, &router_id);
862 ospf6_linkstate_prefix(router_id, htonl(0), &prefix);
863
864 if (inet_pton(AF_INET, argv[idx_ipv4_2]->arg, &area_id) != 1) {
865 vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4_2]->arg);
866 return CMD_SUCCESS;
867 }
868 oa = ospf6_area_lookup(area_id, ospf6);
869 if (oa == NULL) {
870 vty_out(vty, "No such Area: %s\n", argv[idx_ipv4_2]->arg);
871 return CMD_SUCCESS;
872 }
873
874 tmp_debug_ospf6_spf = conf_debug_ospf6_spf;
875 conf_debug_ospf6_spf = 0;
876
877 spf_table = OSPF6_ROUTE_TABLE_CREATE(NONE, SPF_RESULTS);
878 ospf6_spf_calculation(router_id, spf_table, oa);
879
880 conf_debug_ospf6_spf = tmp_debug_ospf6_spf;
881
882 route = ospf6_route_lookup(&prefix, spf_table);
883 if (route == NULL) {
884 ospf6_spf_table_finish(spf_table);
885 ospf6_route_table_delete(spf_table);
886 return CMD_SUCCESS;
887 }
888 root = (struct ospf6_vertex *)route->route_option;
889 ospf6_spf_display_subtree(vty, "", 0, root);
890
891 ospf6_spf_table_finish(spf_table);
892 ospf6_route_table_delete(spf_table);
893
894 return CMD_SUCCESS;
895 }
896
897 DEFUN (ospf6_area_stub,
898 ospf6_area_stub_cmd,
899 "area <A.B.C.D|(0-4294967295)> stub",
900 "OSPF6 area parameters\n"
901 "OSPF6 area ID in IP address format\n"
902 "OSPF6 area ID as a decimal value\n"
903 "Configure OSPF6 area as stub\n")
904 {
905 int idx_ipv4_number = 1;
906 struct ospf6_area *area;
907
908 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
909
910 if (!ospf6_area_stub_set(ospf6, area)) {
911 vty_out(vty,
912 "First deconfigure all virtual link through this area\n");
913 return CMD_WARNING_CONFIG_FAILED;
914 }
915
916 ospf6_area_no_summary_unset(ospf6, area);
917
918 return CMD_SUCCESS;
919 }
920
921 DEFUN (ospf6_area_stub_no_summary,
922 ospf6_area_stub_no_summary_cmd,
923 "area <A.B.C.D|(0-4294967295)> stub no-summary",
924 "OSPF6 stub parameters\n"
925 "OSPF6 area ID in IP address format\n"
926 "OSPF6 area ID as a decimal value\n"
927 "Configure OSPF6 area as stub\n"
928 "Do not inject inter-area routes into stub\n")
929 {
930 int idx_ipv4_number = 1;
931 struct ospf6_area *area;
932
933 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
934
935 if (!ospf6_area_stub_set(ospf6, area)) {
936 vty_out(vty,
937 "First deconfigure all virtual link through this area\n");
938 return CMD_WARNING_CONFIG_FAILED;
939 }
940
941 ospf6_area_no_summary_set(ospf6, area);
942
943 return CMD_SUCCESS;
944 }
945
946 DEFUN (no_ospf6_area_stub,
947 no_ospf6_area_stub_cmd,
948 "no area <A.B.C.D|(0-4294967295)> stub",
949 NO_STR
950 "OSPF6 area parameters\n"
951 "OSPF6 area ID in IP address format\n"
952 "OSPF6 area ID as a decimal value\n"
953 "Configure OSPF6 area as stub\n")
954 {
955 int idx_ipv4_number = 2;
956 struct ospf6_area *area;
957
958 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
959
960 ospf6_area_stub_unset(ospf6, area);
961 ospf6_area_no_summary_unset(ospf6, area);
962
963 return CMD_SUCCESS;
964 }
965
966 DEFUN (no_ospf6_area_stub_no_summary,
967 no_ospf6_area_stub_no_summary_cmd,
968 "no area <A.B.C.D|(0-4294967295)> stub no-summary",
969 NO_STR
970 "OSPF6 area parameters\n"
971 "OSPF6 area ID in IP address format\n"
972 "OSPF6 area ID as a decimal value\n"
973 "Configure OSPF6 area as stub\n"
974 "Do not inject inter-area routes into area\n")
975 {
976 int idx_ipv4_number = 2;
977 struct ospf6_area *area;
978
979 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
980
981 ospf6_area_stub_unset(ospf6, area);
982 ospf6_area_no_summary_unset(ospf6, area);
983
984 return CMD_SUCCESS;
985 }
986
987 void ospf6_area_init(void)
988 {
989 install_element(VIEW_NODE, &show_ipv6_ospf6_spf_tree_cmd);
990 install_element(VIEW_NODE, &show_ipv6_ospf6_area_spf_tree_cmd);
991 install_element(VIEW_NODE, &show_ipv6_ospf6_simulate_spf_tree_root_cmd);
992
993 install_element(OSPF6_NODE, &area_range_cmd);
994 install_element(OSPF6_NODE, &no_area_range_cmd);
995 install_element(OSPF6_NODE, &ospf6_area_stub_no_summary_cmd);
996 install_element(OSPF6_NODE, &ospf6_area_stub_cmd);
997 install_element(OSPF6_NODE, &no_ospf6_area_stub_no_summary_cmd);
998 install_element(OSPF6_NODE, &no_ospf6_area_stub_cmd);
999
1000
1001 install_element(OSPF6_NODE, &area_import_list_cmd);
1002 install_element(OSPF6_NODE, &no_area_import_list_cmd);
1003 install_element(OSPF6_NODE, &area_export_list_cmd);
1004 install_element(OSPF6_NODE, &no_area_export_list_cmd);
1005
1006 install_element(OSPF6_NODE, &area_filter_list_cmd);
1007 install_element(OSPF6_NODE, &no_area_filter_list_cmd);
1008 }