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