]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_area.c
Merge pull request #3162 from pguibert6WIND/vpn_route_map_issue
[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(uint32_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(&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(uint32_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 uint32_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 uint32_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 cost = range->path.u.cost_config;
445 } else {
446 cost = strtoul(argv[5]->arg, NULL, 10);
447 UNSET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
448 }
449 }
450
451 range->path.u.cost_config = cost;
452
453 zlog_debug("%s: for prefix %s, flag = %x\n", __func__,
454 argv[idx_ipv6_prefixlen]->arg, range->flag);
455 if (range->rnode == NULL) {
456 ospf6_route_add(range, oa->range_table);
457 }
458
459 if (ospf6_is_router_abr(ospf6)) {
460 /* Redo summaries if required */
461 ospf6_abr_prefix_resummarize(ospf6);
462 }
463
464 return CMD_SUCCESS;
465 }
466
467 DEFUN (no_area_range,
468 no_area_range_cmd,
469 "no area <A.B.C.D|(0-4294967295)> range X:X::X:X/M [<advertise|not-advertise|cost (0-16777215)>]",
470 NO_STR
471 "OSPF6 area parameters\n"
472 "OSPF6 area ID in IP address format\n"
473 "OSPF6 area ID as a decimal value\n"
474 "Configured address range\n"
475 "Specify IPv6 prefix\n"
476 "Advertise\n"
477 "Do not advertise\n"
478 "User specified metric for this range\n"
479 "Advertised metric for this range\n")
480 {
481 int idx_ipv4 = 2;
482 int idx_ipv6 = 4;
483 int ret;
484 struct ospf6_area *oa;
485 struct prefix prefix;
486 struct ospf6_route *range, *route;
487
488 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, oa);
489
490 ret = str2prefix(argv[idx_ipv6]->arg, &prefix);
491 if (ret != 1 || prefix.family != AF_INET6) {
492 vty_out(vty, "Malformed argument: %s\n", argv[idx_ipv6]->arg);
493 return CMD_SUCCESS;
494 }
495
496 range = ospf6_route_lookup(&prefix, oa->range_table);
497 if (range == NULL) {
498 vty_out(vty, "Range %s does not exists.\n",
499 argv[idx_ipv6]->arg);
500 return CMD_SUCCESS;
501 }
502
503 if (ospf6_is_router_abr(oa->ospf6)) {
504 /* Blow away the aggregated LSA and route */
505 SET_FLAG(range->flag, OSPF6_ROUTE_REMOVE);
506
507 /* Redo summaries if required */
508 for (route = ospf6_route_head(ospf6->route_table); route;
509 route = ospf6_route_next(route))
510 ospf6_abr_originate_summary(route);
511
512 /* purge the old aggregated summary LSA */
513 ospf6_abr_originate_summary(range);
514 }
515 ospf6_route_remove(range, oa->range_table);
516
517 return CMD_SUCCESS;
518 }
519
520 void ospf6_area_config_write(struct vty *vty)
521 {
522 struct listnode *node;
523 struct ospf6_area *oa;
524 struct ospf6_route *range;
525 char buf[PREFIX2STR_BUFFER];
526
527 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
528 for (range = ospf6_route_head(oa->range_table); range;
529 range = ospf6_route_next(range)) {
530 prefix2str(&range->prefix, buf, sizeof(buf));
531 vty_out(vty, " area %s range %s", oa->name, buf);
532
533 if (CHECK_FLAG(range->flag,
534 OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
535 vty_out(vty, " not-advertise");
536 } else {
537 // "advertise" is the default so we do not
538 // display it
539 if (range->path.u.cost_config
540 != OSPF_AREA_RANGE_COST_UNSPEC)
541 vty_out(vty, " cost %d",
542 range->path.u.cost_config);
543 }
544 vty_out(vty, "\n");
545 }
546 if (IS_AREA_STUB(oa)) {
547 if (oa->no_summary)
548 vty_out(vty, " area %s stub no-summary\n",
549 oa->name);
550 else
551 vty_out(vty, " area %s stub\n", oa->name);
552 }
553 if (PREFIX_NAME_IN(oa))
554 vty_out(vty, " area %s filter-list prefix %s in\n",
555 oa->name, PREFIX_NAME_IN(oa));
556 if (PREFIX_NAME_OUT(oa))
557 vty_out(vty, " area %s filter-list prefix %s out\n",
558 oa->name, PREFIX_NAME_OUT(oa));
559 if (IMPORT_NAME(oa))
560 vty_out(vty, " area %s import-list %s\n", oa->name,
561 IMPORT_NAME(oa));
562 if (EXPORT_NAME(oa))
563 vty_out(vty, " area %s export-list %s\n", oa->name,
564 EXPORT_NAME(oa));
565 }
566 }
567
568 DEFUN (area_filter_list,
569 area_filter_list_cmd,
570 "area A.B.C.D filter-list prefix WORD <in|out>",
571 "OSPF6 area parameters\n"
572 "OSPF6 area ID in IP address format\n"
573 "Filter networks between OSPF6 areas\n"
574 "Filter prefixes between OSPF6 areas\n"
575 "Name of an IPv6 prefix-list\n"
576 "Filter networks sent to this area\n"
577 "Filter networks sent from this area\n")
578 {
579 char *inout = argv[argc - 1]->text;
580 char *areaid = argv[1]->arg;
581 char *plistname = argv[4]->arg;
582
583 struct ospf6_area *area;
584 struct prefix_list *plist;
585
586 OSPF6_CMD_AREA_GET(areaid, area);
587
588 plist = prefix_list_lookup(AFI_IP6, plistname);
589 if (strmatch(inout, "in")) {
590 PREFIX_LIST_IN(area) = plist;
591 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
592 PREFIX_NAME_IN(area) =
593 XSTRDUP(MTYPE_OSPF6_PLISTNAME, plistname);
594 ospf6_abr_reimport(area);
595 } else {
596 PREFIX_LIST_OUT(area) = plist;
597 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
598 PREFIX_NAME_OUT(area) =
599 XSTRDUP(MTYPE_OSPF6_PLISTNAME, plistname);
600 ospf6_abr_enable_area(area);
601 }
602
603 return CMD_SUCCESS;
604 }
605
606 DEFUN (no_area_filter_list,
607 no_area_filter_list_cmd,
608 "no area A.B.C.D filter-list prefix WORD <in|out>",
609 NO_STR
610 "OSPF6 area parameters\n"
611 "OSPF6 area ID in IP address format\n"
612 "Filter networks between OSPF6 areas\n"
613 "Filter prefixes between OSPF6 areas\n"
614 "Name of an IPv6 prefix-list\n"
615 "Filter networks sent to this area\n"
616 "Filter networks sent from this area\n")
617 {
618 char *inout = argv[argc - 1]->text;
619 char *areaid = argv[2]->arg;
620 char *plistname = argv[5]->arg;
621
622 struct ospf6_area *area;
623
624 OSPF6_CMD_AREA_GET(areaid, area);
625
626 if (strmatch(inout, "in")) {
627 if (PREFIX_NAME_IN(area))
628 if (!strmatch(PREFIX_NAME_IN(area), plistname))
629 return CMD_SUCCESS;
630
631 PREFIX_LIST_IN(area) = NULL;
632 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
633 ospf6_abr_reimport(area);
634 } else {
635 if (PREFIX_NAME_OUT(area))
636 if (!strmatch(PREFIX_NAME_OUT(area), plistname))
637 return CMD_SUCCESS;
638
639 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
640 ospf6_abr_enable_area(area);
641 }
642
643 return CMD_SUCCESS;
644 }
645
646 void ospf6_area_plist_update(struct prefix_list *plist, int add)
647 {
648 struct ospf6_area *oa;
649 struct listnode *n;
650 const char *name = prefix_list_name(plist);
651
652 if (!ospf6)
653 return;
654
655 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa)) {
656 if (PREFIX_NAME_IN(oa) && !strcmp(PREFIX_NAME_IN(oa), name))
657 PREFIX_LIST_IN(oa) = add ? plist : NULL;
658 if (PREFIX_NAME_OUT(oa) && !strcmp(PREFIX_NAME_OUT(oa), name))
659 PREFIX_LIST_OUT(oa) = add ? plist : NULL;
660 }
661 }
662
663 DEFUN (area_import_list,
664 area_import_list_cmd,
665 "area A.B.C.D import-list NAME",
666 "OSPF6 area parameters\n"
667 "OSPF6 area ID in IP address format\n"
668 "Set the filter for networks from other areas announced to the specified one\n"
669 "Name of the acess-list\n")
670 {
671 int idx_ipv4 = 1;
672 int idx_name = 3;
673 struct ospf6_area *area;
674 struct access_list *list;
675
676 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
677
678 list = access_list_lookup(AFI_IP6, argv[idx_name]->arg);
679
680 IMPORT_LIST(area) = list;
681
682 if (IMPORT_NAME(area))
683 free(IMPORT_NAME(area));
684
685 IMPORT_NAME(area) = strdup(argv[idx_name]->arg);
686 ospf6_abr_reimport(area);
687
688 return CMD_SUCCESS;
689 }
690
691 DEFUN (no_area_import_list,
692 no_area_import_list_cmd,
693 "no area A.B.C.D import-list NAME",
694 NO_STR
695 "OSPF6 area parameters\n"
696 "OSPF6 area ID in IP address format\n"
697 "Unset the filter for networks announced to other areas\n"
698 "Name of the access-list\n")
699 {
700 int idx_ipv4 = 2;
701 struct ospf6_area *area;
702
703 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
704
705 IMPORT_LIST(area) = 0;
706
707 if (IMPORT_NAME(area))
708 free(IMPORT_NAME(area));
709
710 IMPORT_NAME(area) = NULL;
711 ospf6_abr_reimport(area);
712
713 return CMD_SUCCESS;
714 }
715
716 DEFUN (area_export_list,
717 area_export_list_cmd,
718 "area A.B.C.D export-list NAME",
719 "OSPF6 area parameters\n"
720 "OSPF6 area ID in IP address format\n"
721 "Set the filter for networks announced to other areas\n"
722 "Name of the acess-list\n")
723 {
724 int idx_ipv4 = 1;
725 int idx_name = 3;
726 struct ospf6_area *area;
727 struct access_list *list;
728
729 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
730
731 list = access_list_lookup(AFI_IP6, argv[idx_name]->arg);
732
733 EXPORT_LIST(area) = list;
734
735 if (EXPORT_NAME(area))
736 free(EXPORT_NAME(area));
737
738 EXPORT_NAME(area) = strdup(argv[idx_name]->arg);
739 ospf6_abr_enable_area(area);
740
741 return CMD_SUCCESS;
742 }
743
744 DEFUN (no_area_export_list,
745 no_area_export_list_cmd,
746 "no area A.B.C.D export-list NAME",
747 NO_STR
748 "OSPF6 area parameters\n"
749 "OSPF6 area ID in IP address format\n"
750 "Unset the filter for networks announced to other areas\n"
751 "Name of the access-list\n")
752 {
753 int idx_ipv4 = 2;
754 struct ospf6_area *area;
755
756 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
757
758 EXPORT_LIST(area) = 0;
759
760 if (EXPORT_NAME(area))
761 free(EXPORT_NAME(area));
762
763 EXPORT_NAME(area) = NULL;
764 ospf6_abr_enable_area(area);
765
766 return CMD_SUCCESS;
767 }
768
769 DEFUN (show_ipv6_ospf6_spf_tree,
770 show_ipv6_ospf6_spf_tree_cmd,
771 "show ipv6 ospf6 spf tree",
772 SHOW_STR
773 IP6_STR
774 OSPF6_STR
775 "Shortest Path First calculation\n"
776 "Show SPF tree\n")
777 {
778 struct listnode *node;
779 struct ospf6_area *oa;
780 struct ospf6_vertex *root;
781 struct ospf6_route *route;
782 struct prefix prefix;
783
784 OSPF6_CMD_CHECK_RUNNING();
785
786 ospf6_linkstate_prefix(ospf6->router_id, htonl(0), &prefix);
787
788 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
789 route = ospf6_route_lookup(&prefix, oa->spf_table);
790 if (route == NULL) {
791 vty_out(vty, "LS entry for root not found in area %s\n",
792 oa->name);
793 continue;
794 }
795 root = (struct ospf6_vertex *)route->route_option;
796 ospf6_spf_display_subtree(vty, "", 0, root);
797 }
798
799 return CMD_SUCCESS;
800 }
801
802 DEFUN (show_ipv6_ospf6_area_spf_tree,
803 show_ipv6_ospf6_area_spf_tree_cmd,
804 "show ipv6 ospf6 area A.B.C.D spf tree",
805 SHOW_STR
806 IP6_STR
807 OSPF6_STR
808 OSPF6_AREA_STR
809 OSPF6_AREA_ID_STR
810 "Shortest Path First calculation\n"
811 "Show SPF tree\n")
812 {
813 int idx_ipv4 = 4;
814 uint32_t area_id;
815 struct ospf6_area *oa;
816 struct ospf6_vertex *root;
817 struct ospf6_route *route;
818 struct prefix prefix;
819
820 OSPF6_CMD_CHECK_RUNNING();
821
822 ospf6_linkstate_prefix(ospf6->router_id, htonl(0), &prefix);
823
824 if (inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id) != 1) {
825 vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4]->arg);
826 return CMD_SUCCESS;
827 }
828 oa = ospf6_area_lookup(area_id, ospf6);
829 if (oa == NULL) {
830 vty_out(vty, "No such Area: %s\n", argv[idx_ipv4]->arg);
831 return CMD_SUCCESS;
832 }
833
834 route = ospf6_route_lookup(&prefix, oa->spf_table);
835 if (route == NULL) {
836 vty_out(vty, "LS entry for root not found in area %s\n",
837 oa->name);
838 return CMD_SUCCESS;
839 }
840 root = (struct ospf6_vertex *)route->route_option;
841 ospf6_spf_display_subtree(vty, "", 0, root);
842
843 return CMD_SUCCESS;
844 }
845
846 DEFUN (show_ipv6_ospf6_simulate_spf_tree_root,
847 show_ipv6_ospf6_simulate_spf_tree_root_cmd,
848 "show ipv6 ospf6 simulate spf-tree A.B.C.D area A.B.C.D",
849 SHOW_STR
850 IP6_STR
851 OSPF6_STR
852 "Shortest Path First calculation\n"
853 "Show SPF tree\n"
854 "Specify root's router-id to calculate another router's SPF tree\n"
855 "OSPF6 area parameters\n"
856 OSPF6_AREA_ID_STR)
857 {
858 int idx_ipv4 = 5;
859 int idx_ipv4_2 = 7;
860 uint32_t area_id;
861 struct ospf6_area *oa;
862 struct ospf6_vertex *root;
863 struct ospf6_route *route;
864 struct prefix prefix;
865 uint32_t router_id;
866 struct ospf6_route_table *spf_table;
867 unsigned char tmp_debug_ospf6_spf = 0;
868
869 OSPF6_CMD_CHECK_RUNNING();
870
871 inet_pton(AF_INET, argv[idx_ipv4]->arg, &router_id);
872 ospf6_linkstate_prefix(router_id, htonl(0), &prefix);
873
874 if (inet_pton(AF_INET, argv[idx_ipv4_2]->arg, &area_id) != 1) {
875 vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4_2]->arg);
876 return CMD_SUCCESS;
877 }
878 oa = ospf6_area_lookup(area_id, ospf6);
879 if (oa == NULL) {
880 vty_out(vty, "No such Area: %s\n", argv[idx_ipv4_2]->arg);
881 return CMD_SUCCESS;
882 }
883
884 tmp_debug_ospf6_spf = conf_debug_ospf6_spf;
885 conf_debug_ospf6_spf = 0;
886
887 spf_table = OSPF6_ROUTE_TABLE_CREATE(NONE, SPF_RESULTS);
888 ospf6_spf_calculation(router_id, spf_table, oa);
889
890 conf_debug_ospf6_spf = tmp_debug_ospf6_spf;
891
892 route = ospf6_route_lookup(&prefix, spf_table);
893 if (route == NULL) {
894 ospf6_spf_table_finish(spf_table);
895 ospf6_route_table_delete(spf_table);
896 return CMD_SUCCESS;
897 }
898 root = (struct ospf6_vertex *)route->route_option;
899 ospf6_spf_display_subtree(vty, "", 0, root);
900
901 ospf6_spf_table_finish(spf_table);
902 ospf6_route_table_delete(spf_table);
903
904 return CMD_SUCCESS;
905 }
906
907 DEFUN (ospf6_area_stub,
908 ospf6_area_stub_cmd,
909 "area <A.B.C.D|(0-4294967295)> stub",
910 "OSPF6 area parameters\n"
911 "OSPF6 area ID in IP address format\n"
912 "OSPF6 area ID as a decimal value\n"
913 "Configure OSPF6 area as stub\n")
914 {
915 int idx_ipv4_number = 1;
916 struct ospf6_area *area;
917
918 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
919
920 if (!ospf6_area_stub_set(ospf6, area)) {
921 vty_out(vty,
922 "First deconfigure all virtual link through this area\n");
923 return CMD_WARNING_CONFIG_FAILED;
924 }
925
926 ospf6_area_no_summary_unset(ospf6, area);
927
928 return CMD_SUCCESS;
929 }
930
931 DEFUN (ospf6_area_stub_no_summary,
932 ospf6_area_stub_no_summary_cmd,
933 "area <A.B.C.D|(0-4294967295)> stub no-summary",
934 "OSPF6 stub parameters\n"
935 "OSPF6 area ID in IP address format\n"
936 "OSPF6 area ID as a decimal value\n"
937 "Configure OSPF6 area as stub\n"
938 "Do not inject inter-area routes into stub\n")
939 {
940 int idx_ipv4_number = 1;
941 struct ospf6_area *area;
942
943 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
944
945 if (!ospf6_area_stub_set(ospf6, area)) {
946 vty_out(vty,
947 "First deconfigure all virtual link through this area\n");
948 return CMD_WARNING_CONFIG_FAILED;
949 }
950
951 ospf6_area_no_summary_set(ospf6, area);
952
953 return CMD_SUCCESS;
954 }
955
956 DEFUN (no_ospf6_area_stub,
957 no_ospf6_area_stub_cmd,
958 "no area <A.B.C.D|(0-4294967295)> stub",
959 NO_STR
960 "OSPF6 area parameters\n"
961 "OSPF6 area ID in IP address format\n"
962 "OSPF6 area ID as a decimal value\n"
963 "Configure OSPF6 area as stub\n")
964 {
965 int idx_ipv4_number = 2;
966 struct ospf6_area *area;
967
968 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
969
970 ospf6_area_stub_unset(ospf6, area);
971 ospf6_area_no_summary_unset(ospf6, area);
972
973 return CMD_SUCCESS;
974 }
975
976 DEFUN (no_ospf6_area_stub_no_summary,
977 no_ospf6_area_stub_no_summary_cmd,
978 "no area <A.B.C.D|(0-4294967295)> stub no-summary",
979 NO_STR
980 "OSPF6 area parameters\n"
981 "OSPF6 area ID in IP address format\n"
982 "OSPF6 area ID as a decimal value\n"
983 "Configure OSPF6 area as stub\n"
984 "Do not inject inter-area routes into area\n")
985 {
986 int idx_ipv4_number = 2;
987 struct ospf6_area *area;
988
989 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
990
991 ospf6_area_stub_unset(ospf6, area);
992 ospf6_area_no_summary_unset(ospf6, area);
993
994 return CMD_SUCCESS;
995 }
996
997 void ospf6_area_init(void)
998 {
999 install_element(VIEW_NODE, &show_ipv6_ospf6_spf_tree_cmd);
1000 install_element(VIEW_NODE, &show_ipv6_ospf6_area_spf_tree_cmd);
1001 install_element(VIEW_NODE, &show_ipv6_ospf6_simulate_spf_tree_root_cmd);
1002
1003 install_element(OSPF6_NODE, &area_range_cmd);
1004 install_element(OSPF6_NODE, &no_area_range_cmd);
1005 install_element(OSPF6_NODE, &ospf6_area_stub_no_summary_cmd);
1006 install_element(OSPF6_NODE, &ospf6_area_stub_cmd);
1007 install_element(OSPF6_NODE, &no_ospf6_area_stub_no_summary_cmd);
1008 install_element(OSPF6_NODE, &no_ospf6_area_stub_cmd);
1009
1010
1011 install_element(OSPF6_NODE, &area_import_list_cmd);
1012 install_element(OSPF6_NODE, &no_area_import_list_cmd);
1013 install_element(OSPF6_NODE, &area_export_list_cmd);
1014 install_element(OSPF6_NODE, &no_area_export_list_cmd);
1015
1016 install_element(OSPF6_NODE, &area_filter_list_cmd);
1017 install_element(OSPF6_NODE, &no_area_filter_list_cmd);
1018 }