]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_area.c
Merge pull request #1647 from chiragshah6/ospf_vrf_dev
[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;
121
122 copy = ospf6_route_copy(route);
123 ospf6_route_add(copy, ospf6->route_table);
124 }
125
126 static void ospf6_area_route_hook_remove(struct ospf6_route *route)
127 {
128 struct ospf6_route *copy;
129
130 copy = ospf6_route_lookup_identical(route, ospf6->route_table);
131 if (copy)
132 ospf6_route_remove(copy, ospf6->route_table);
133 }
134
135 static void ospf6_area_stub_update(struct ospf6_area *area)
136 {
137
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);
150 }
151
152 static int ospf6_area_stub_set(struct ospf6 *ospf6, struct ospf6_area *area)
153 {
154 if (!IS_AREA_STUB(area)) {
155 SET_FLAG(area->flag, OSPF6_AREA_STUB);
156 ospf6_area_stub_update(area);
157 }
158
159 return (1);
160 }
161
162 static void ospf6_area_stub_unset(struct ospf6 *ospf6, struct ospf6_area *area)
163 {
164 if (IS_AREA_STUB(area)) {
165 UNSET_FLAG(area->flag, OSPF6_AREA_STUB);
166 ospf6_area_stub_update(area);
167 }
168 }
169
170 static void ospf6_area_no_summary_set(struct ospf6 *ospf6,
171 struct ospf6_area *area)
172 {
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 }
179 }
180 }
181
182 static void ospf6_area_no_summary_unset(struct ospf6 *ospf6,
183 struct ospf6_area *area)
184 {
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 }
191 }
192 }
193
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 */
201 struct ospf6_area *ospf6_area_create(u_int32_t area_id, struct ospf6 *o, int df)
202 {
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;
239 oa->router_lsa_size_limit = 1024 + 256;
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;
263 }
264
265 void ospf6_area_delete(struct ospf6_area *oa)
266 {
267 struct listnode *n;
268 struct ospf6_interface *oi;
269
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;
277
278 list_delete_and_null(&oa->if_list);
279
280 ospf6_lsdb_delete(oa->lsdb);
281 ospf6_lsdb_delete(oa->lsdb_self);
282
283 ospf6_spf_table_finish(oa->spf_table);
284 ospf6_route_table_delete(oa->spf_table);
285 ospf6_route_table_delete(oa->route_table);
286
287 ospf6_route_table_delete(oa->range_table);
288 ospf6_route_table_delete(oa->summary_prefix);
289 ospf6_route_table_delete(oa->summary_router);
290
291 listnode_delete(oa->ospf6->area_list, oa);
292 oa->ospf6 = NULL;
293
294 /* free area */
295 XFREE(MTYPE_OSPF6_AREA, oa);
296 }
297
298 struct ospf6_area *ospf6_area_lookup(u_int32_t area_id, struct ospf6 *ospf6)
299 {
300 struct ospf6_area *oa;
301 struct listnode *n;
302
303 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa))
304 if (oa->area_id == area_id)
305 return oa;
306
307 return (struct ospf6_area *)NULL;
308 }
309
310 void ospf6_area_enable(struct ospf6_area *oa)
311 {
312 struct listnode *node, *nnode;
313 struct ospf6_interface *oi;
314
315 SET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
316
317 for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi))
318 ospf6_interface_enable(oi);
319 ospf6_abr_enable_area(oa);
320 }
321
322 void ospf6_area_disable(struct ospf6_area *oa)
323 {
324 struct listnode *node, *nnode;
325 struct ospf6_interface *oi;
326
327 UNSET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
328
329 for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi))
330 ospf6_interface_disable(oi);
331
332 ospf6_abr_disable_area(oa);
333 ospf6_lsdb_remove_all(oa->lsdb);
334 ospf6_lsdb_remove_all(oa->lsdb_self);
335
336 ospf6_spf_table_finish(oa->spf_table);
337 ospf6_route_remove_all(oa->route_table);
338
339 THREAD_OFF(oa->thread_router_lsa);
340 THREAD_OFF(oa->thread_intra_prefix_lsa);
341 }
342
343
344 void ospf6_area_show(struct vty *vty, struct ospf6_area *oa)
345 {
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 }
358 }
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); \
394 }
395
396 DEFUN (area_range,
397 area_range_cmd,
398 "area <A.B.C.D|(0-4294967295)> range X:X::X:X/M [<advertise|not-advertise|cost (0-16777215)>]",
399 "OSPF6 area parameters\n"
400 "OSPF6 area ID in IP address format\n"
401 "OSPF6 area ID as a decimal value\n"
402 "Configured address range\n"
403 "Specify IPv6 prefix\n"
404 "Advertise\n"
405 "Do not advertise\n"
406 "User specified metric for this range\n"
407 "Advertised metric for this range\n")
408 {
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;
425 }
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;
434 }
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 }
445 }
446
447 range->path.u.cost_config = cost;
448
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 }
454
455 if (ospf6_is_router_abr(ospf6)) {
456 /* Redo summaries if required */
457 ospf6_abr_prefix_resummarize(ospf6);
458 }
459
460 return CMD_SUCCESS;
461 }
462
463 DEFUN (no_area_range,
464 no_area_range_cmd,
465 "no area <A.B.C.D|(0-4294967295)> range X:X::X:X/M [<advertise|not-advertise|cost (0-16777215)>]",
466 NO_STR
467 "OSPF6 area parameters\n"
468 "OSPF6 area ID in IP address format\n"
469 "OSPF6 area ID as a decimal value\n"
470 "Configured address range\n"
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")
476 {
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;
483
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
516 void 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));
561 }
562 }
563
564 DEFUN (area_filter_list,
565 area_filter_list_cmd,
566 "area A.B.C.D filter-list prefix WORD <in|out>",
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"
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 {
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;
587 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
588 PREFIX_NAME_IN(area) = XSTRDUP(MTYPE_OSPF6_PLISTNAME,
589 plistname);
590 ospf6_abr_reimport(area);
591 } else {
592 PREFIX_LIST_OUT(area) = plist;
593 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
594 PREFIX_NAME_OUT(area) = XSTRDUP(MTYPE_OSPF6_PLISTNAME,
595 plistname);
596 ospf6_abr_enable_area(area);
597 }
598
599 return CMD_SUCCESS;
600 }
601
602 DEFUN (no_area_filter_list,
603 no_area_filter_list_cmd,
604 "no area A.B.C.D filter-list prefix WORD <in|out>",
605 NO_STR
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"
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 {
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;
628 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
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
635 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
636 ospf6_abr_enable_area(area);
637 }
638
639 return CMD_SUCCESS;
640 }
641
642 void 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
648 if (!ospf6)
649 return;
650
651 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa)) {
652 if (PREFIX_NAME_IN(oa) && !strcmp(PREFIX_NAME_IN(oa), name))
653 PREFIX_LIST_IN(oa) = add ? plist : NULL;
654 if (PREFIX_NAME_OUT(oa) && !strcmp(PREFIX_NAME_OUT(oa), name))
655 PREFIX_LIST_OUT(oa) = add ? plist : NULL;
656 }
657 }
658
659 DEFUN (area_import_list,
660 area_import_list_cmd,
661 "area A.B.C.D import-list NAME",
662 "OSPF6 area parameters\n"
663 "OSPF6 area ID in IP address format\n"
664 "Set the filter for networks from other areas announced to the specified one\n"
665 "Name of the acess-list\n")
666 {
667 int idx_ipv4 = 1;
668 int idx_name = 3;
669 struct ospf6_area *area;
670 struct access_list *list;
671
672 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
673
674 list = access_list_lookup(AFI_IP6, argv[idx_name]->arg);
675
676 IMPORT_LIST(area) = list;
677
678 if (IMPORT_NAME(area))
679 free(IMPORT_NAME(area));
680
681 IMPORT_NAME(area) = strdup(argv[idx_name]->arg);
682 ospf6_abr_reimport(area);
683
684 return CMD_SUCCESS;
685 }
686
687 DEFUN (no_area_import_list,
688 no_area_import_list_cmd,
689 "no area A.B.C.D import-list NAME",
690 NO_STR
691 "OSPF6 area parameters\n"
692 "OSPF6 area ID in IP address format\n"
693 "Unset the filter for networks announced to other areas\n"
694 "Name of the access-list\n")
695 {
696 int idx_ipv4 = 2;
697 struct ospf6_area *area;
698
699 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
700
701 IMPORT_LIST(area) = 0;
702
703 if (IMPORT_NAME(area))
704 free(IMPORT_NAME(area));
705
706 IMPORT_NAME(area) = NULL;
707 ospf6_abr_reimport(area);
708
709 return CMD_SUCCESS;
710 }
711
712 DEFUN (area_export_list,
713 area_export_list_cmd,
714 "area A.B.C.D export-list NAME",
715 "OSPF6 area parameters\n"
716 "OSPF6 area ID in IP address format\n"
717 "Set the filter for networks announced to other areas\n"
718 "Name of the acess-list\n")
719 {
720 int idx_ipv4 = 1;
721 int idx_name = 3;
722 struct ospf6_area *area;
723 struct access_list *list;
724
725 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
726
727 list = access_list_lookup(AFI_IP6, argv[idx_name]->arg);
728
729 EXPORT_LIST(area) = list;
730
731 if (EXPORT_NAME(area))
732 free(EXPORT_NAME(area));
733
734 EXPORT_NAME(area) = strdup(argv[idx_name]->arg);
735 ospf6_abr_enable_area(area);
736
737 return CMD_SUCCESS;
738 }
739
740 DEFUN (no_area_export_list,
741 no_area_export_list_cmd,
742 "no area A.B.C.D export-list NAME",
743 NO_STR
744 "OSPF6 area parameters\n"
745 "OSPF6 area ID in IP address format\n"
746 "Unset the filter for networks announced to other areas\n"
747 "Name of the access-list\n")
748 {
749 int idx_ipv4 = 2;
750 struct ospf6_area *area;
751
752 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
753
754 EXPORT_LIST(area) = 0;
755
756 if (EXPORT_NAME(area))
757 free(EXPORT_NAME(area));
758
759 EXPORT_NAME(area) = NULL;
760 ospf6_abr_enable_area(area);
761
762 return CMD_SUCCESS;
763 }
764
765 DEFUN (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")
773 {
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;
796 }
797
798 DEFUN (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 {
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;
840 }
841
842 DEFUN (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
848 "Shortest Path First calculation\n"
849 "Show SPF tree\n"
850 "Specify root's router-id to calculate another router's SPF tree\n"
851 "OSPF6 area parameters\n"
852 OSPF6_AREA_ID_STR)
853 {
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;
901 }
902
903 DEFUN (ospf6_area_stub,
904 ospf6_area_stub_cmd,
905 "area <A.B.C.D|(0-4294967295)> stub",
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 {
911 int idx_ipv4_number = 1;
912 struct ospf6_area *area;
913
914 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
915
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 }
921
922 ospf6_area_no_summary_unset(ospf6, area);
923
924 return CMD_SUCCESS;
925 }
926
927 DEFUN (ospf6_area_stub_no_summary,
928 ospf6_area_stub_no_summary_cmd,
929 "area <A.B.C.D|(0-4294967295)> stub no-summary",
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 {
936 int idx_ipv4_number = 1;
937 struct ospf6_area *area;
938
939 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
940
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 }
946
947 ospf6_area_no_summary_set(ospf6, area);
948
949 return CMD_SUCCESS;
950 }
951
952 DEFUN (no_ospf6_area_stub,
953 no_ospf6_area_stub_cmd,
954 "no area <A.B.C.D|(0-4294967295)> stub",
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 {
961 int idx_ipv4_number = 2;
962 struct ospf6_area *area;
963
964 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
965
966 ospf6_area_stub_unset(ospf6, area);
967 ospf6_area_no_summary_unset(ospf6, area);
968
969 return CMD_SUCCESS;
970 }
971
972 DEFUN (no_ospf6_area_stub_no_summary,
973 no_ospf6_area_stub_no_summary_cmd,
974 "no area <A.B.C.D|(0-4294967295)> stub no-summary",
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 {
982 int idx_ipv4_number = 2;
983 struct ospf6_area *area;
984
985 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
986
987 ospf6_area_stub_unset(ospf6, area);
988 ospf6_area_no_summary_unset(ospf6, area);
989
990 return CMD_SUCCESS;
991 }
992
993 void ospf6_area_init(void)
994 {
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);
998
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);
1005
1006
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);
1011
1012 install_element(OSPF6_NODE, &area_filter_list_cmd);
1013 install_element(OSPF6_NODE, &no_area_filter_list_cmd);
1014 }