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