]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_area.c
eigrpd: eigrp usage of uint32_t to struct in_addr for router_id data
[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|(0-4294967295)> filter-list prefix WORD <in|out>",
571 "OSPF6 area parameters\n"
572 "OSPF6 area ID in IP address format\n"
573 "OSPF6 area ID as a decimal value\n"
574 "Filter networks between OSPF6 areas\n"
575 "Filter prefixes between OSPF6 areas\n"
576 "Name of an IPv6 prefix-list\n"
577 "Filter networks sent to this area\n"
578 "Filter networks sent from this area\n")
579 {
580 char *inout = argv[argc - 1]->text;
581 char *areaid = argv[1]->arg;
582 char *plistname = argv[4]->arg;
583
584 struct ospf6_area *area;
585 struct prefix_list *plist;
586
587 OSPF6_CMD_AREA_GET(areaid, area);
588
589 plist = prefix_list_lookup(AFI_IP6, plistname);
590 if (strmatch(inout, "in")) {
591 PREFIX_LIST_IN(area) = plist;
592 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
593 PREFIX_NAME_IN(area) =
594 XSTRDUP(MTYPE_OSPF6_PLISTNAME, plistname);
595 ospf6_abr_reimport(area);
596 } else {
597 PREFIX_LIST_OUT(area) = plist;
598 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
599 PREFIX_NAME_OUT(area) =
600 XSTRDUP(MTYPE_OSPF6_PLISTNAME, plistname);
601 ospf6_abr_enable_area(area);
602 }
603
604 return CMD_SUCCESS;
605 }
606
607 DEFUN (no_area_filter_list,
608 no_area_filter_list_cmd,
609 "no area <A.B.C.D|(0-4294967295)> filter-list prefix WORD <in|out>",
610 NO_STR
611 "OSPF6 area parameters\n"
612 "OSPF6 area ID in IP address format\n"
613 "OSPF6 area ID as a decimal value\n"
614 "Filter networks between OSPF6 areas\n"
615 "Filter prefixes between OSPF6 areas\n"
616 "Name of an IPv6 prefix-list\n"
617 "Filter networks sent to this area\n"
618 "Filter networks sent from this area\n")
619 {
620 char *inout = argv[argc - 1]->text;
621 char *areaid = argv[2]->arg;
622 char *plistname = argv[5]->arg;
623
624 struct ospf6_area *area;
625
626 OSPF6_CMD_AREA_GET(areaid, area);
627
628 if (strmatch(inout, "in")) {
629 if (PREFIX_NAME_IN(area))
630 if (!strmatch(PREFIX_NAME_IN(area), plistname))
631 return CMD_SUCCESS;
632
633 PREFIX_LIST_IN(area) = NULL;
634 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
635 ospf6_abr_reimport(area);
636 } else {
637 if (PREFIX_NAME_OUT(area))
638 if (!strmatch(PREFIX_NAME_OUT(area), plistname))
639 return CMD_SUCCESS;
640
641 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
642 ospf6_abr_enable_area(area);
643 }
644
645 return CMD_SUCCESS;
646 }
647
648 void ospf6_area_plist_update(struct prefix_list *plist, int add)
649 {
650 struct ospf6_area *oa;
651 struct listnode *n;
652 const char *name = prefix_list_name(plist);
653
654 if (!ospf6)
655 return;
656
657 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa)) {
658 if (PREFIX_NAME_IN(oa) && !strcmp(PREFIX_NAME_IN(oa), name))
659 PREFIX_LIST_IN(oa) = add ? plist : NULL;
660 if (PREFIX_NAME_OUT(oa) && !strcmp(PREFIX_NAME_OUT(oa), name))
661 PREFIX_LIST_OUT(oa) = add ? plist : NULL;
662 }
663 }
664
665 DEFUN (area_import_list,
666 area_import_list_cmd,
667 "area <A.B.C.D|(0-4294967295)> import-list NAME",
668 "OSPF6 area parameters\n"
669 "OSPF6 area ID in IP address format\n"
670 "OSPF6 area ID as a decimal value\n"
671 "Set the filter for networks from other areas announced to the specified one\n"
672 "Name of the acess-list\n")
673 {
674 int idx_ipv4 = 1;
675 int idx_name = 3;
676 struct ospf6_area *area;
677 struct access_list *list;
678
679 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
680
681 list = access_list_lookup(AFI_IP6, argv[idx_name]->arg);
682
683 IMPORT_LIST(area) = list;
684
685 if (IMPORT_NAME(area))
686 free(IMPORT_NAME(area));
687
688 IMPORT_NAME(area) = strdup(argv[idx_name]->arg);
689 ospf6_abr_reimport(area);
690
691 return CMD_SUCCESS;
692 }
693
694 DEFUN (no_area_import_list,
695 no_area_import_list_cmd,
696 "no area <A.B.C.D|(0-4294967295)> import-list NAME",
697 NO_STR
698 "OSPF6 area parameters\n"
699 "OSPF6 area ID in IP address format\n"
700 "OSPF6 area ID as a decimal value\n"
701 "Unset the filter for networks announced to other areas\n"
702 "Name of the access-list\n")
703 {
704 int idx_ipv4 = 2;
705 struct ospf6_area *area;
706
707 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
708
709 IMPORT_LIST(area) = 0;
710
711 if (IMPORT_NAME(area))
712 free(IMPORT_NAME(area));
713
714 IMPORT_NAME(area) = NULL;
715 ospf6_abr_reimport(area);
716
717 return CMD_SUCCESS;
718 }
719
720 DEFUN (area_export_list,
721 area_export_list_cmd,
722 "area <A.B.C.D|(0-4294967295)> export-list NAME",
723 "OSPF6 area parameters\n"
724 "OSPF6 area ID in IP address format\n"
725 "OSPF6 area ID as a decimal value\n"
726 "Set the filter for networks announced to other areas\n"
727 "Name of the acess-list\n")
728 {
729 int idx_ipv4 = 1;
730 int idx_name = 3;
731 struct ospf6_area *area;
732 struct access_list *list;
733
734 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
735
736 list = access_list_lookup(AFI_IP6, argv[idx_name]->arg);
737
738 EXPORT_LIST(area) = list;
739
740 if (EXPORT_NAME(area))
741 free(EXPORT_NAME(area));
742
743 EXPORT_NAME(area) = strdup(argv[idx_name]->arg);
744 ospf6_abr_enable_area(area);
745
746 return CMD_SUCCESS;
747 }
748
749 DEFUN (no_area_export_list,
750 no_area_export_list_cmd,
751 "no area <A.B.C.D|(0-4294967295)> export-list NAME",
752 NO_STR
753 "OSPF6 area parameters\n"
754 "OSPF6 area ID in IP address format\n"
755 "OSPF6 area ID as a decimal value\n"
756 "Unset the filter for networks announced to other areas\n"
757 "Name of the access-list\n")
758 {
759 int idx_ipv4 = 2;
760 struct ospf6_area *area;
761
762 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
763
764 EXPORT_LIST(area) = 0;
765
766 if (EXPORT_NAME(area))
767 free(EXPORT_NAME(area));
768
769 EXPORT_NAME(area) = NULL;
770 ospf6_abr_enable_area(area);
771
772 return CMD_SUCCESS;
773 }
774
775 DEFUN (show_ipv6_ospf6_spf_tree,
776 show_ipv6_ospf6_spf_tree_cmd,
777 "show ipv6 ospf6 spf tree",
778 SHOW_STR
779 IP6_STR
780 OSPF6_STR
781 "Shortest Path First calculation\n"
782 "Show SPF tree\n")
783 {
784 struct listnode *node;
785 struct ospf6_area *oa;
786 struct ospf6_vertex *root;
787 struct ospf6_route *route;
788 struct prefix prefix;
789
790 OSPF6_CMD_CHECK_RUNNING();
791
792 ospf6_linkstate_prefix(ospf6->router_id, htonl(0), &prefix);
793
794 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
795 route = ospf6_route_lookup(&prefix, oa->spf_table);
796 if (route == NULL) {
797 vty_out(vty, "LS entry for root not found in area %s\n",
798 oa->name);
799 continue;
800 }
801 root = (struct ospf6_vertex *)route->route_option;
802 ospf6_spf_display_subtree(vty, "", 0, root);
803 }
804
805 return CMD_SUCCESS;
806 }
807
808 DEFUN (show_ipv6_ospf6_area_spf_tree,
809 show_ipv6_ospf6_area_spf_tree_cmd,
810 "show ipv6 ospf6 area A.B.C.D spf tree",
811 SHOW_STR
812 IP6_STR
813 OSPF6_STR
814 OSPF6_AREA_STR
815 OSPF6_AREA_ID_STR
816 "Shortest Path First calculation\n"
817 "Show SPF tree\n")
818 {
819 int idx_ipv4 = 4;
820 uint32_t area_id;
821 struct ospf6_area *oa;
822 struct ospf6_vertex *root;
823 struct ospf6_route *route;
824 struct prefix prefix;
825
826 OSPF6_CMD_CHECK_RUNNING();
827
828 ospf6_linkstate_prefix(ospf6->router_id, htonl(0), &prefix);
829
830 if (inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id) != 1) {
831 vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4]->arg);
832 return CMD_SUCCESS;
833 }
834 oa = ospf6_area_lookup(area_id, ospf6);
835 if (oa == NULL) {
836 vty_out(vty, "No such Area: %s\n", argv[idx_ipv4]->arg);
837 return CMD_SUCCESS;
838 }
839
840 route = ospf6_route_lookup(&prefix, oa->spf_table);
841 if (route == NULL) {
842 vty_out(vty, "LS entry for root not found in area %s\n",
843 oa->name);
844 return CMD_SUCCESS;
845 }
846 root = (struct ospf6_vertex *)route->route_option;
847 ospf6_spf_display_subtree(vty, "", 0, root);
848
849 return CMD_SUCCESS;
850 }
851
852 DEFUN (show_ipv6_ospf6_simulate_spf_tree_root,
853 show_ipv6_ospf6_simulate_spf_tree_root_cmd,
854 "show ipv6 ospf6 simulate spf-tree A.B.C.D area A.B.C.D",
855 SHOW_STR
856 IP6_STR
857 OSPF6_STR
858 "Shortest Path First calculation\n"
859 "Show SPF tree\n"
860 "Specify root's router-id to calculate another router's SPF tree\n"
861 "OSPF6 area parameters\n"
862 OSPF6_AREA_ID_STR)
863 {
864 int idx_ipv4 = 5;
865 int idx_ipv4_2 = 7;
866 uint32_t area_id;
867 struct ospf6_area *oa;
868 struct ospf6_vertex *root;
869 struct ospf6_route *route;
870 struct prefix prefix;
871 uint32_t router_id;
872 struct ospf6_route_table *spf_table;
873 unsigned char tmp_debug_ospf6_spf = 0;
874
875 OSPF6_CMD_CHECK_RUNNING();
876
877 inet_pton(AF_INET, argv[idx_ipv4]->arg, &router_id);
878 ospf6_linkstate_prefix(router_id, htonl(0), &prefix);
879
880 if (inet_pton(AF_INET, argv[idx_ipv4_2]->arg, &area_id) != 1) {
881 vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4_2]->arg);
882 return CMD_SUCCESS;
883 }
884 oa = ospf6_area_lookup(area_id, ospf6);
885 if (oa == NULL) {
886 vty_out(vty, "No such Area: %s\n", argv[idx_ipv4_2]->arg);
887 return CMD_SUCCESS;
888 }
889
890 tmp_debug_ospf6_spf = conf_debug_ospf6_spf;
891 conf_debug_ospf6_spf = 0;
892
893 spf_table = OSPF6_ROUTE_TABLE_CREATE(NONE, SPF_RESULTS);
894 ospf6_spf_calculation(router_id, spf_table, oa);
895
896 conf_debug_ospf6_spf = tmp_debug_ospf6_spf;
897
898 route = ospf6_route_lookup(&prefix, spf_table);
899 if (route == NULL) {
900 ospf6_spf_table_finish(spf_table);
901 ospf6_route_table_delete(spf_table);
902 return CMD_SUCCESS;
903 }
904 root = (struct ospf6_vertex *)route->route_option;
905 ospf6_spf_display_subtree(vty, "", 0, root);
906
907 ospf6_spf_table_finish(spf_table);
908 ospf6_route_table_delete(spf_table);
909
910 return CMD_SUCCESS;
911 }
912
913 DEFUN (ospf6_area_stub,
914 ospf6_area_stub_cmd,
915 "area <A.B.C.D|(0-4294967295)> stub",
916 "OSPF6 area parameters\n"
917 "OSPF6 area ID in IP address format\n"
918 "OSPF6 area ID as a decimal value\n"
919 "Configure OSPF6 area as stub\n")
920 {
921 int idx_ipv4_number = 1;
922 struct ospf6_area *area;
923
924 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
925
926 if (!ospf6_area_stub_set(ospf6, area)) {
927 vty_out(vty,
928 "First deconfigure all virtual link through this area\n");
929 return CMD_WARNING_CONFIG_FAILED;
930 }
931
932 ospf6_area_no_summary_unset(ospf6, area);
933
934 return CMD_SUCCESS;
935 }
936
937 DEFUN (ospf6_area_stub_no_summary,
938 ospf6_area_stub_no_summary_cmd,
939 "area <A.B.C.D|(0-4294967295)> stub no-summary",
940 "OSPF6 stub parameters\n"
941 "OSPF6 area ID in IP address format\n"
942 "OSPF6 area ID as a decimal value\n"
943 "Configure OSPF6 area as stub\n"
944 "Do not inject inter-area routes into stub\n")
945 {
946 int idx_ipv4_number = 1;
947 struct ospf6_area *area;
948
949 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
950
951 if (!ospf6_area_stub_set(ospf6, area)) {
952 vty_out(vty,
953 "First deconfigure all virtual link through this area\n");
954 return CMD_WARNING_CONFIG_FAILED;
955 }
956
957 ospf6_area_no_summary_set(ospf6, area);
958
959 return CMD_SUCCESS;
960 }
961
962 DEFUN (no_ospf6_area_stub,
963 no_ospf6_area_stub_cmd,
964 "no area <A.B.C.D|(0-4294967295)> stub",
965 NO_STR
966 "OSPF6 area parameters\n"
967 "OSPF6 area ID in IP address format\n"
968 "OSPF6 area ID as a decimal value\n"
969 "Configure OSPF6 area as stub\n")
970 {
971 int idx_ipv4_number = 2;
972 struct ospf6_area *area;
973
974 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
975
976 ospf6_area_stub_unset(ospf6, area);
977 ospf6_area_no_summary_unset(ospf6, area);
978
979 return CMD_SUCCESS;
980 }
981
982 DEFUN (no_ospf6_area_stub_no_summary,
983 no_ospf6_area_stub_no_summary_cmd,
984 "no area <A.B.C.D|(0-4294967295)> stub no-summary",
985 NO_STR
986 "OSPF6 area parameters\n"
987 "OSPF6 area ID in IP address format\n"
988 "OSPF6 area ID as a decimal value\n"
989 "Configure OSPF6 area as stub\n"
990 "Do not inject inter-area routes into area\n")
991 {
992 int idx_ipv4_number = 2;
993 struct ospf6_area *area;
994
995 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
996
997 ospf6_area_stub_unset(ospf6, area);
998 ospf6_area_no_summary_unset(ospf6, area);
999
1000 return CMD_SUCCESS;
1001 }
1002
1003 void ospf6_area_init(void)
1004 {
1005 install_element(VIEW_NODE, &show_ipv6_ospf6_spf_tree_cmd);
1006 install_element(VIEW_NODE, &show_ipv6_ospf6_area_spf_tree_cmd);
1007 install_element(VIEW_NODE, &show_ipv6_ospf6_simulate_spf_tree_root_cmd);
1008
1009 install_element(OSPF6_NODE, &area_range_cmd);
1010 install_element(OSPF6_NODE, &no_area_range_cmd);
1011 install_element(OSPF6_NODE, &ospf6_area_stub_no_summary_cmd);
1012 install_element(OSPF6_NODE, &ospf6_area_stub_cmd);
1013 install_element(OSPF6_NODE, &no_ospf6_area_stub_no_summary_cmd);
1014 install_element(OSPF6_NODE, &no_ospf6_area_stub_cmd);
1015
1016
1017 install_element(OSPF6_NODE, &area_import_list_cmd);
1018 install_element(OSPF6_NODE, &no_area_import_list_cmd);
1019 install_element(OSPF6_NODE, &area_export_list_cmd);
1020 install_element(OSPF6_NODE, &no_area_export_list_cmd);
1021
1022 install_element(OSPF6_NODE, &area_filter_list_cmd);
1023 install_element(OSPF6_NODE, &no_area_filter_list_cmd);
1024 }