]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_top.c
Merge pull request #2946 from mjstapp/dplane_2
[mirror_frr.git] / ospf6d / ospf6_top.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 "vty.h"
26 #include "linklist.h"
27 #include "prefix.h"
28 #include "table.h"
29 #include "thread.h"
30 #include "command.h"
31 #include "defaults.h"
32
33 #include "ospf6_proto.h"
34 #include "ospf6_message.h"
35 #include "ospf6_lsa.h"
36 #include "ospf6_lsdb.h"
37 #include "ospf6_route.h"
38 #include "ospf6_zebra.h"
39
40 #include "ospf6_top.h"
41 #include "ospf6_area.h"
42 #include "ospf6_interface.h"
43 #include "ospf6_neighbor.h"
44
45 #include "ospf6_flood.h"
46 #include "ospf6_asbr.h"
47 #include "ospf6_abr.h"
48 #include "ospf6_intra.h"
49 #include "ospf6_spf.h"
50 #include "ospf6d.h"
51
52 DEFINE_QOBJ_TYPE(ospf6)
53
54 /* global ospf6d variable */
55 struct ospf6 *ospf6;
56 static struct ospf6_master ospf6_master;
57 struct ospf6_master *om6;
58
59 static void ospf6_disable(struct ospf6 *o);
60
61 static void ospf6_top_lsdb_hook_add(struct ospf6_lsa *lsa)
62 {
63 switch (ntohs(lsa->header->type)) {
64 case OSPF6_LSTYPE_AS_EXTERNAL:
65 ospf6_asbr_lsa_add(lsa);
66 break;
67
68 default:
69 break;
70 }
71 }
72
73 static void ospf6_top_lsdb_hook_remove(struct ospf6_lsa *lsa)
74 {
75 switch (ntohs(lsa->header->type)) {
76 case OSPF6_LSTYPE_AS_EXTERNAL:
77 ospf6_asbr_lsa_remove(lsa, NULL);
78 break;
79
80 default:
81 break;
82 }
83 }
84
85 static void ospf6_top_route_hook_add(struct ospf6_route *route)
86 {
87 ospf6_abr_originate_summary(route);
88 ospf6_zebra_route_update_add(route);
89 }
90
91 static void ospf6_top_route_hook_remove(struct ospf6_route *route)
92 {
93 route->flag |= OSPF6_ROUTE_REMOVE;
94 ospf6_abr_originate_summary(route);
95 ospf6_zebra_route_update_remove(route);
96 }
97
98 static void ospf6_top_brouter_hook_add(struct ospf6_route *route)
99 {
100 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL) ||
101 IS_OSPF6_DEBUG_BROUTER) {
102 uint32_t brouter_id;
103 char brouter_name[16];
104
105 brouter_id = ADV_ROUTER_IN_PREFIX(&route->prefix);
106 inet_ntop(AF_INET, &brouter_id, brouter_name,
107 sizeof(brouter_name));
108 zlog_debug("%s: brouter %s add with adv router %x nh count %u",
109 __PRETTY_FUNCTION__, brouter_name,
110 route->path.origin.adv_router,
111 listcount(route->nh_list));
112 }
113 ospf6_abr_examin_brouter(ADV_ROUTER_IN_PREFIX(&route->prefix));
114 ospf6_asbr_lsentry_add(route);
115 ospf6_abr_originate_summary(route);
116 }
117
118 static void ospf6_top_brouter_hook_remove(struct ospf6_route *route)
119 {
120 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL) ||
121 IS_OSPF6_DEBUG_BROUTER) {
122 uint32_t brouter_id;
123 char brouter_name[16];
124
125 brouter_id = ADV_ROUTER_IN_PREFIX(&route->prefix);
126 inet_ntop(AF_INET, &brouter_id, brouter_name,
127 sizeof(brouter_name));
128 zlog_debug("%s: brouter %p %s del with adv router %x nh %u",
129 __PRETTY_FUNCTION__, (void *)route, brouter_name,
130 route->path.origin.adv_router,
131 listcount(route->nh_list));
132 }
133 route->flag |= OSPF6_ROUTE_REMOVE;
134 ospf6_abr_examin_brouter(ADV_ROUTER_IN_PREFIX(&route->prefix));
135 ospf6_asbr_lsentry_remove(route);
136 ospf6_abr_originate_summary(route);
137 }
138
139 static struct ospf6 *ospf6_create(void)
140 {
141 struct ospf6 *o;
142
143 o = XCALLOC(MTYPE_OSPF6_TOP, sizeof(struct ospf6));
144
145 /* initialize */
146 monotime(&o->starttime);
147 o->area_list = list_new();
148 o->area_list->cmp = ospf6_area_cmp;
149 o->lsdb = ospf6_lsdb_create(o);
150 o->lsdb_self = ospf6_lsdb_create(o);
151 o->lsdb->hook_add = ospf6_top_lsdb_hook_add;
152 o->lsdb->hook_remove = ospf6_top_lsdb_hook_remove;
153
154 o->spf_delay = OSPF_SPF_DELAY_DEFAULT;
155 o->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
156 o->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT;
157 o->spf_hold_multiplier = 1;
158
159 /* LSA timers value init */
160 o->lsa_minarrival = OSPF_MIN_LS_ARRIVAL;
161
162 o->route_table = OSPF6_ROUTE_TABLE_CREATE(GLOBAL, ROUTES);
163 o->route_table->scope = o;
164 o->route_table->hook_add = ospf6_top_route_hook_add;
165 o->route_table->hook_remove = ospf6_top_route_hook_remove;
166
167 o->brouter_table = OSPF6_ROUTE_TABLE_CREATE(GLOBAL, BORDER_ROUTERS);
168 o->brouter_table->scope = o;
169 o->brouter_table->hook_add = ospf6_top_brouter_hook_add;
170 o->brouter_table->hook_remove = ospf6_top_brouter_hook_remove;
171
172 o->external_table = OSPF6_ROUTE_TABLE_CREATE(GLOBAL, EXTERNAL_ROUTES);
173 o->external_table->scope = o;
174
175 o->external_id_table = route_table_init();
176
177 o->ref_bandwidth = OSPF6_REFERENCE_BANDWIDTH;
178
179 o->distance_table = route_table_init();
180
181 /* Enable "log-adjacency-changes" */
182 #if DFLT_OSPF6_LOG_ADJACENCY_CHANGES
183 SET_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
184 #endif
185
186 QOBJ_REG(o, ospf6);
187
188 return o;
189 }
190
191 void ospf6_delete(struct ospf6 *o)
192 {
193 struct listnode *node, *nnode;
194 struct ospf6_area *oa;
195
196 QOBJ_UNREG(o);
197
198 ospf6_flush_self_originated_lsas_now();
199 ospf6_disable(ospf6);
200
201 for (ALL_LIST_ELEMENTS(o->area_list, node, nnode, oa))
202 ospf6_area_delete(oa);
203
204
205 list_delete(&o->area_list);
206
207 ospf6_lsdb_delete(o->lsdb);
208 ospf6_lsdb_delete(o->lsdb_self);
209
210 ospf6_route_table_delete(o->route_table);
211 ospf6_route_table_delete(o->brouter_table);
212
213 ospf6_route_table_delete(o->external_table);
214 route_table_finish(o->external_id_table);
215
216 ospf6_distance_reset(o);
217 route_table_finish(o->distance_table);
218
219 XFREE(MTYPE_OSPF6_TOP, o);
220 }
221
222 static void ospf6_disable(struct ospf6 *o)
223 {
224 struct listnode *node, *nnode;
225 struct ospf6_area *oa;
226
227 if (!CHECK_FLAG(o->flag, OSPF6_DISABLED)) {
228 SET_FLAG(o->flag, OSPF6_DISABLED);
229
230 for (ALL_LIST_ELEMENTS(o->area_list, node, nnode, oa))
231 ospf6_area_disable(oa);
232
233 /* XXX: This also changes persistent settings */
234 ospf6_asbr_redistribute_reset();
235
236 ospf6_lsdb_remove_all(o->lsdb);
237 ospf6_route_remove_all(o->route_table);
238 ospf6_route_remove_all(o->brouter_table);
239
240 THREAD_OFF(o->maxage_remover);
241 THREAD_OFF(o->t_spf_calc);
242 THREAD_OFF(o->t_ase_calc);
243 THREAD_OFF(o->t_distribute_update);
244 }
245 }
246
247 void ospf6_master_init(void)
248 {
249 memset(&ospf6_master, 0, sizeof(struct ospf6_master));
250
251 om6 = &ospf6_master;
252 }
253
254 static int ospf6_maxage_remover(struct thread *thread)
255 {
256 struct ospf6 *o = (struct ospf6 *)THREAD_ARG(thread);
257 struct ospf6_area *oa;
258 struct ospf6_interface *oi;
259 struct ospf6_neighbor *on;
260 struct listnode *i, *j, *k;
261 int reschedule = 0;
262
263 o->maxage_remover = (struct thread *)NULL;
264
265 for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) {
266 for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) {
267 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, k, on)) {
268 if (on->state != OSPF6_NEIGHBOR_EXCHANGE
269 && on->state != OSPF6_NEIGHBOR_LOADING)
270 continue;
271
272 ospf6_maxage_remove(o);
273 return 0;
274 }
275 }
276 }
277
278 for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) {
279 for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) {
280 if (ospf6_lsdb_maxage_remover(oi->lsdb)) {
281 reschedule = 1;
282 }
283 }
284
285 if (ospf6_lsdb_maxage_remover(oa->lsdb)) {
286 reschedule = 1;
287 }
288 }
289
290 if (ospf6_lsdb_maxage_remover(o->lsdb)) {
291 reschedule = 1;
292 }
293
294 if (reschedule) {
295 ospf6_maxage_remove(o);
296 }
297
298 return 0;
299 }
300
301 void ospf6_maxage_remove(struct ospf6 *o)
302 {
303 if (o)
304 thread_add_timer(master, ospf6_maxage_remover, o,
305 OSPF_LSA_MAXAGE_REMOVE_DELAY_DEFAULT,
306 &o->maxage_remover);
307 }
308
309 void ospf6_router_id_update(void)
310 {
311 if (!ospf6)
312 return;
313
314 if (ospf6->router_id_static != 0)
315 ospf6->router_id = ospf6->router_id_static;
316 else
317 ospf6->router_id = om6->zebra_router_id;
318 }
319
320 /* start ospf6 */
321 DEFUN_NOSH (router_ospf6,
322 router_ospf6_cmd,
323 "router ospf6",
324 ROUTER_STR
325 OSPF6_STR)
326 {
327 if (ospf6 == NULL) {
328 ospf6 = ospf6_create();
329 if (ospf6->router_id == 0)
330 ospf6_router_id_update();
331 }
332 /* set current ospf point. */
333 VTY_PUSH_CONTEXT(OSPF6_NODE, ospf6);
334
335 return CMD_SUCCESS;
336 }
337
338 /* stop ospf6 */
339 DEFUN (no_router_ospf6,
340 no_router_ospf6_cmd,
341 "no router ospf6",
342 NO_STR
343 ROUTER_STR
344 OSPF6_STR)
345 {
346 if (ospf6 == NULL)
347 vty_out(vty, "OSPFv3 is not configured\n");
348 else {
349 ospf6_delete(ospf6);
350 ospf6 = NULL;
351 }
352
353 /* return to config node . */
354 VTY_PUSH_CONTEXT_NULL(CONFIG_NODE);
355
356 return CMD_SUCCESS;
357 }
358
359 /* change Router_ID commands. */
360 DEFUN(ospf6_router_id,
361 ospf6_router_id_cmd,
362 "ospf6 router-id A.B.C.D",
363 OSPF6_STR
364 "Configure OSPF6 Router-ID\n"
365 V4NOTATION_STR)
366 {
367 VTY_DECLVAR_CONTEXT(ospf6, o);
368 int idx = 0;
369 int ret;
370 const char *router_id_str;
371 uint32_t router_id;
372 struct ospf6_area *oa;
373 struct listnode *node;
374
375 argv_find(argv, argc, "A.B.C.D", &idx);
376 router_id_str = argv[idx]->arg;
377
378 ret = inet_pton(AF_INET, router_id_str, &router_id);
379 if (ret == 0) {
380 vty_out(vty, "malformed OSPF Router-ID: %s\n", router_id_str);
381 return CMD_SUCCESS;
382 }
383
384 o->router_id_static = router_id;
385
386 for (ALL_LIST_ELEMENTS_RO(o->area_list, node, oa)) {
387 if (oa->full_nbrs) {
388 vty_out(vty,
389 "For this router-id change to take effect,"
390 " save config and restart ospf6d\n");
391 return CMD_SUCCESS;
392 }
393 }
394
395 o->router_id = router_id;
396
397 return CMD_SUCCESS;
398 }
399
400 DEFUN(no_ospf6_router_id,
401 no_ospf6_router_id_cmd,
402 "no ospf6 router-id [A.B.C.D]",
403 NO_STR OSPF6_STR
404 "Configure OSPF6 Router-ID\n"
405 V4NOTATION_STR)
406 {
407 VTY_DECLVAR_CONTEXT(ospf6, o);
408 struct ospf6_area *oa;
409 struct listnode *node;
410
411 o->router_id_static = 0;
412
413 for (ALL_LIST_ELEMENTS_RO(o->area_list, node, oa)) {
414 if (oa->full_nbrs) {
415 vty_out(vty,
416 "For this router-id change to take effect,"
417 " save config and restart ospf6d\n");
418 return CMD_SUCCESS;
419 }
420 }
421 o->router_id = 0;
422 if (o->router_id_zebra.s_addr)
423 o->router_id = (uint32_t)o->router_id_zebra.s_addr;
424
425 return CMD_SUCCESS;
426 }
427
428 DEFUN (ospf6_log_adjacency_changes,
429 ospf6_log_adjacency_changes_cmd,
430 "log-adjacency-changes",
431 "Log changes in adjacency state\n")
432 {
433 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
434
435 SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
436 UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
437 return CMD_SUCCESS;
438 }
439
440 DEFUN (ospf6_log_adjacency_changes_detail,
441 ospf6_log_adjacency_changes_detail_cmd,
442 "log-adjacency-changes detail",
443 "Log changes in adjacency state\n"
444 "Log all state changes\n")
445 {
446 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
447
448 SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
449 SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
450 return CMD_SUCCESS;
451 }
452
453 DEFUN (no_ospf6_log_adjacency_changes,
454 no_ospf6_log_adjacency_changes_cmd,
455 "no log-adjacency-changes",
456 NO_STR
457 "Log changes in adjacency state\n")
458 {
459 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
460
461 UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
462 UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
463 return CMD_SUCCESS;
464 }
465
466 DEFUN (no_ospf6_log_adjacency_changes_detail,
467 no_ospf6_log_adjacency_changes_detail_cmd,
468 "no log-adjacency-changes detail",
469 NO_STR
470 "Log changes in adjacency state\n"
471 "Log all state changes\n")
472 {
473 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
474
475 UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
476 return CMD_SUCCESS;
477 }
478
479 DEFUN (ospf6_timers_lsa,
480 ospf6_timers_lsa_cmd,
481 "timers lsa min-arrival (0-600000)",
482 "Adjust routing timers\n"
483 "OSPF6 LSA timers\n"
484 "Minimum delay in receiving new version of a LSA\n"
485 "Delay in milliseconds\n")
486 {
487 VTY_DECLVAR_CONTEXT(ospf6, ospf);
488 int idx_number = 3;
489 unsigned int minarrival;
490
491 minarrival = strtoul(argv[idx_number]->arg, NULL, 10);
492 ospf->lsa_minarrival = minarrival;
493
494 return CMD_SUCCESS;
495 }
496
497 DEFUN (no_ospf6_timers_lsa,
498 no_ospf6_timers_lsa_cmd,
499 "no timers lsa min-arrival [(0-600000)]",
500 NO_STR
501 "Adjust routing timers\n"
502 "OSPF6 LSA timers\n"
503 "Minimum delay in receiving new version of a LSA\n"
504 "Delay in milliseconds\n")
505 {
506 VTY_DECLVAR_CONTEXT(ospf6, ospf);
507 int idx_number = 4;
508 unsigned int minarrival;
509
510 if (argc == 5) {
511 minarrival = strtoul(argv[idx_number]->arg, NULL, 10);
512
513 if (ospf->lsa_minarrival != minarrival
514 || minarrival == OSPF_MIN_LS_ARRIVAL)
515 return CMD_SUCCESS;
516 }
517
518 ospf->lsa_minarrival = OSPF_MIN_LS_ARRIVAL;
519
520 return CMD_SUCCESS;
521 }
522
523
524 DEFUN (ospf6_distance,
525 ospf6_distance_cmd,
526 "distance (1-255)",
527 "Administrative distance\n"
528 "OSPF6 Administrative distance\n")
529 {
530 VTY_DECLVAR_CONTEXT(ospf6, o);
531
532 o->distance_all = atoi(argv[1]->arg);
533
534 return CMD_SUCCESS;
535 }
536
537 DEFUN (no_ospf6_distance,
538 no_ospf6_distance_cmd,
539 "no distance (1-255)",
540 NO_STR
541 "Administrative distance\n"
542 "OSPF6 Administrative distance\n")
543 {
544 VTY_DECLVAR_CONTEXT(ospf6, o);
545
546 o->distance_all = 0;
547
548 return CMD_SUCCESS;
549 }
550
551 DEFUN (ospf6_distance_ospf6,
552 ospf6_distance_ospf6_cmd,
553 "distance ospf6 {intra-area (1-255)|inter-area (1-255)|external (1-255)}",
554 "Administrative distance\n"
555 "OSPF6 administrative distance\n"
556 "Intra-area routes\n"
557 "Distance for intra-area routes\n"
558 "Inter-area routes\n"
559 "Distance for inter-area routes\n"
560 "External routes\n"
561 "Distance for external routes\n")
562 {
563 VTY_DECLVAR_CONTEXT(ospf6, o);
564 int idx = 0;
565
566 o->distance_intra = 0;
567 o->distance_inter = 0;
568 o->distance_external = 0;
569
570 if (argv_find(argv, argc, "intra-area", &idx))
571 o->distance_intra = atoi(argv[idx + 1]->arg);
572 idx = 0;
573 if (argv_find(argv, argc, "inter-area", &idx))
574 o->distance_inter = atoi(argv[idx + 1]->arg);
575 idx = 0;
576 if (argv_find(argv, argc, "external", &idx))
577 o->distance_external = atoi(argv[idx + 1]->arg);
578
579 return CMD_SUCCESS;
580 }
581
582 DEFUN (no_ospf6_distance_ospf6,
583 no_ospf6_distance_ospf6_cmd,
584 "no distance ospf6 [{intra-area [(1-255)]|inter-area [(1-255)]|external [(1-255)]}]",
585 NO_STR
586 "Administrative distance\n"
587 "OSPF6 distance\n"
588 "Intra-area routes\n"
589 "Distance for intra-area routes\n"
590 "Inter-area routes\n"
591 "Distance for inter-area routes\n"
592 "External routes\n"
593 "Distance for external routes\n")
594 {
595 VTY_DECLVAR_CONTEXT(ospf6, o);
596 int idx = 0;
597
598 if (argv_find(argv, argc, "intra-area", &idx) || argc == 3)
599 idx = o->distance_intra = 0;
600 if (argv_find(argv, argc, "inter-area", &idx) || argc == 3)
601 idx = o->distance_inter = 0;
602 if (argv_find(argv, argc, "external", &idx) || argc == 3)
603 o->distance_external = 0;
604
605 return CMD_SUCCESS;
606 }
607
608 #if 0
609 DEFUN (ospf6_distance_source,
610 ospf6_distance_source_cmd,
611 "distance (1-255) X:X::X:X/M [WORD]",
612 "Administrative distance\n"
613 "Distance value\n"
614 "IP source prefix\n"
615 "Access list name\n")
616 {
617 VTY_DECLVAR_CONTEXT(ospf6, o);
618 char *alname = (argc == 4) ? argv[3]->arg : NULL;
619 ospf6_distance_set (vty, o, argv[1]->arg, argv[2]->arg, alname);
620
621 return CMD_SUCCESS;
622 }
623
624 DEFUN (no_ospf6_distance_source,
625 no_ospf6_distance_source_cmd,
626 "no distance (1-255) X:X::X:X/M [WORD]",
627 NO_STR
628 "Administrative distance\n"
629 "Distance value\n"
630 "IP source prefix\n"
631 "Access list name\n")
632 {
633 VTY_DECLVAR_CONTEXT(ospf6, o);
634 char *alname = (argc == 5) ? argv[4]->arg : NULL;
635 ospf6_distance_unset (vty, o, argv[2]->arg, argv[3]->arg, alname);
636
637 return CMD_SUCCESS;
638 }
639 #endif
640
641 DEFUN (ospf6_interface_area,
642 ospf6_interface_area_cmd,
643 "interface IFNAME area A.B.C.D",
644 "Enable routing on an IPv6 interface\n"
645 IFNAME_STR
646 "Specify the OSPF6 area ID\n"
647 "OSPF6 area ID in IPv4 address notation\n"
648 )
649 {
650 VTY_DECLVAR_CONTEXT(ospf6, o);
651 int idx_ifname = 1;
652 int idx_ipv4 = 3;
653 struct ospf6_area *oa;
654 struct ospf6_interface *oi;
655 struct interface *ifp;
656 uint32_t area_id;
657
658 /* find/create ospf6 interface */
659 ifp = if_get_by_name(argv[idx_ifname]->arg, VRF_DEFAULT, 0);
660 oi = (struct ospf6_interface *)ifp->info;
661 if (oi == NULL)
662 oi = ospf6_interface_create(ifp);
663 if (oi->area) {
664 vty_out(vty, "%s already attached to Area %s\n",
665 oi->interface->name, oi->area->name);
666 return CMD_SUCCESS;
667 }
668
669 /* parse Area-ID */
670 if (inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id) != 1) {
671 vty_out(vty, "Invalid Area-ID: %s\n", argv[idx_ipv4]->arg);
672 return CMD_SUCCESS;
673 }
674
675 /* find/create ospf6 area */
676 oa = ospf6_area_lookup(area_id, o);
677 if (oa == NULL)
678 oa = ospf6_area_create(area_id, o, OSPF6_AREA_FMT_DOTTEDQUAD);
679
680 /* attach interface to area */
681 listnode_add(oa->if_list, oi); /* sort ?? */
682 oi->area = oa;
683
684 SET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
685
686 /* ospf6 process is currently disabled, not much more to do */
687 if (CHECK_FLAG(o->flag, OSPF6_DISABLED))
688 return CMD_SUCCESS;
689
690 /* start up */
691 ospf6_interface_enable(oi);
692
693 /* If the router is ABR, originate summary routes */
694 if (ospf6_is_router_abr(o))
695 ospf6_abr_enable_area(oa);
696
697 return CMD_SUCCESS;
698 }
699
700 DEFUN (no_ospf6_interface_area,
701 no_ospf6_interface_area_cmd,
702 "no interface IFNAME area A.B.C.D",
703 NO_STR
704 "Disable routing on an IPv6 interface\n"
705 IFNAME_STR
706 "Specify the OSPF6 area ID\n"
707 "OSPF6 area ID in IPv4 address notation\n"
708 )
709 {
710 int idx_ifname = 2;
711 int idx_ipv4 = 4;
712 struct ospf6_interface *oi;
713 struct ospf6_area *oa;
714 struct interface *ifp;
715 uint32_t area_id;
716
717 ifp = if_lookup_by_name(argv[idx_ifname]->arg, VRF_DEFAULT);
718 if (ifp == NULL) {
719 vty_out(vty, "No such interface %s\n", argv[idx_ifname]->arg);
720 return CMD_SUCCESS;
721 }
722
723 oi = (struct ospf6_interface *)ifp->info;
724 if (oi == NULL) {
725 vty_out(vty, "Interface %s not enabled\n", ifp->name);
726 return CMD_SUCCESS;
727 }
728
729 /* parse Area-ID */
730 if (inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id) != 1) {
731 vty_out(vty, "Invalid Area-ID: %s\n", argv[idx_ipv4]->arg);
732 return CMD_SUCCESS;
733 }
734
735 /* Verify Area */
736 if (oi->area == NULL) {
737 vty_out(vty, "No such Area-ID: %s\n", argv[idx_ipv4]->arg);
738 return CMD_SUCCESS;
739 }
740
741 if (oi->area->area_id != area_id) {
742 vty_out(vty, "Wrong Area-ID: %s is attached to area %s\n",
743 oi->interface->name, oi->area->name);
744 return CMD_SUCCESS;
745 }
746
747 thread_execute(master, interface_down, oi, 0);
748
749 oa = oi->area;
750 listnode_delete(oi->area->if_list, oi);
751 oi->area = (struct ospf6_area *)NULL;
752
753 /* Withdraw inter-area routes from this area, if necessary */
754 if (oa->if_list->count == 0) {
755 UNSET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
756 ospf6_abr_disable_area(oa);
757 }
758
759 return CMD_SUCCESS;
760 }
761
762 DEFUN (ospf6_stub_router_admin,
763 ospf6_stub_router_admin_cmd,
764 "stub-router administrative",
765 "Make router a stub router\n"
766 "Administratively applied, for an indefinite period\n")
767 {
768 struct listnode *node;
769 struct ospf6_area *oa;
770
771 if (!CHECK_FLAG(ospf6->flag, OSPF6_STUB_ROUTER)) {
772 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
773 OSPF6_OPT_CLEAR(oa->options, OSPF6_OPT_V6);
774 OSPF6_OPT_CLEAR(oa->options, OSPF6_OPT_R);
775 OSPF6_ROUTER_LSA_SCHEDULE(oa);
776 }
777 SET_FLAG(ospf6->flag, OSPF6_STUB_ROUTER);
778 }
779
780 return CMD_SUCCESS;
781 }
782
783 DEFUN (no_ospf6_stub_router_admin,
784 no_ospf6_stub_router_admin_cmd,
785 "no stub-router administrative",
786 NO_STR
787 "Make router a stub router\n"
788 "Administratively applied, for an indefinite period\n")
789 {
790 struct listnode *node;
791 struct ospf6_area *oa;
792
793 if (CHECK_FLAG(ospf6->flag, OSPF6_STUB_ROUTER)) {
794 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
795 OSPF6_OPT_SET(oa->options, OSPF6_OPT_V6);
796 OSPF6_OPT_SET(oa->options, OSPF6_OPT_R);
797 OSPF6_ROUTER_LSA_SCHEDULE(oa);
798 }
799 UNSET_FLAG(ospf6->flag, OSPF6_STUB_ROUTER);
800 }
801
802 return CMD_SUCCESS;
803 }
804
805 #if 0
806 DEFUN (ospf6_stub_router_startup,
807 ospf6_stub_router_startup_cmd,
808 "stub-router on-startup (5-86400)",
809 "Make router a stub router\n"
810 "Advertise inability to be a transit router\n"
811 "Automatically advertise as stub-router on startup of OSPF6\n"
812 "Time (seconds) to advertise self as stub-router\n")
813 {
814 return CMD_SUCCESS;
815 }
816
817 DEFUN (no_ospf6_stub_router_startup,
818 no_ospf6_stub_router_startup_cmd,
819 "no stub-router on-startup",
820 NO_STR
821 "Make router a stub router\n"
822 "Advertise inability to be a transit router\n"
823 "Automatically advertise as stub-router on startup of OSPF6\n"
824 "Time (seconds) to advertise self as stub-router\n")
825 {
826 return CMD_SUCCESS;
827 }
828
829 DEFUN (ospf6_stub_router_shutdown,
830 ospf6_stub_router_shutdown_cmd,
831 "stub-router on-shutdown (5-86400)",
832 "Make router a stub router\n"
833 "Advertise inability to be a transit router\n"
834 "Automatically advertise as stub-router before shutdown\n"
835 "Time (seconds) to advertise self as stub-router\n")
836 {
837 return CMD_SUCCESS;
838 }
839
840 DEFUN (no_ospf6_stub_router_shutdown,
841 no_ospf6_stub_router_shutdown_cmd,
842 "no stub-router on-shutdown",
843 NO_STR
844 "Make router a stub router\n"
845 "Advertise inability to be a transit router\n"
846 "Automatically advertise as stub-router before shutdown\n"
847 "Time (seconds) to advertise self as stub-router\n")
848 {
849 return CMD_SUCCESS;
850 }
851 #endif
852
853 static void ospf6_show(struct vty *vty, struct ospf6 *o)
854 {
855 struct listnode *n;
856 struct ospf6_area *oa;
857 char router_id[16], duration[32];
858 struct timeval now, running, result;
859 char buf[32], rbuf[32];
860
861 /* process id, router id */
862 inet_ntop(AF_INET, &o->router_id, router_id, sizeof(router_id));
863 vty_out(vty, " OSPFv3 Routing Process (0) with Router-ID %s\n",
864 router_id);
865
866 /* running time */
867 monotime(&now);
868 timersub(&now, &o->starttime, &running);
869 timerstring(&running, duration, sizeof(duration));
870 vty_out(vty, " Running %s\n", duration);
871
872 /* Redistribute configuration */
873 /* XXX */
874
875 vty_out(vty, " LSA minimum arrival %d msecs\n", o->lsa_minarrival);
876
877 /* Show SPF parameters */
878 vty_out(vty,
879 " Initial SPF scheduling delay %d millisec(s)\n"
880 " Minimum hold time between consecutive SPFs %d millsecond(s)\n"
881 " Maximum hold time between consecutive SPFs %d millsecond(s)\n"
882 " Hold time multiplier is currently %d\n",
883 o->spf_delay, o->spf_holdtime, o->spf_max_holdtime,
884 o->spf_hold_multiplier);
885
886 vty_out(vty, " SPF algorithm ");
887 if (o->ts_spf.tv_sec || o->ts_spf.tv_usec) {
888 timersub(&now, &o->ts_spf, &result);
889 timerstring(&result, buf, sizeof(buf));
890 ospf6_spf_reason_string(o->last_spf_reason, rbuf, sizeof(rbuf));
891 vty_out(vty, "last executed %s ago, reason %s\n", buf, rbuf);
892 vty_out(vty, " Last SPF duration %lld sec %lld usec\n",
893 (long long)o->ts_spf_duration.tv_sec,
894 (long long)o->ts_spf_duration.tv_usec);
895 } else
896 vty_out(vty, "has not been run\n");
897 threadtimer_string(now, o->t_spf_calc, buf, sizeof(buf));
898 vty_out(vty, " SPF timer %s%s\n", (o->t_spf_calc ? "due in " : "is "),
899 buf);
900
901 if (CHECK_FLAG(o->flag, OSPF6_STUB_ROUTER))
902 vty_out(vty, " Router Is Stub Router\n");
903
904 /* LSAs */
905 vty_out(vty, " Number of AS scoped LSAs is %u\n", o->lsdb->count);
906
907 /* Areas */
908 vty_out(vty, " Number of areas in this router is %u\n",
909 listcount(o->area_list));
910
911 if (CHECK_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES)) {
912 if (CHECK_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_DETAIL))
913 vty_out(vty, " All adjacency changes are logged\n");
914 else
915 vty_out(vty, " Adjacency changes are logged\n");
916 }
917
918 vty_out(vty, "\n");
919
920 for (ALL_LIST_ELEMENTS_RO(o->area_list, n, oa))
921 ospf6_area_show(vty, oa);
922 }
923
924 /* show top level structures */
925 DEFUN (show_ipv6_ospf6,
926 show_ipv6_ospf6_cmd,
927 "show ipv6 ospf6",
928 SHOW_STR
929 IP6_STR
930 OSPF6_STR)
931 {
932 OSPF6_CMD_CHECK_RUNNING();
933
934 ospf6_show(vty, ospf6);
935 return CMD_SUCCESS;
936 }
937
938 DEFUN (show_ipv6_ospf6_route,
939 show_ipv6_ospf6_route_cmd,
940 "show ipv6 ospf6 route [<intra-area|inter-area|external-1|external-2|X:X::X:X|X:X::X:X/M|detail|summary>]",
941 SHOW_STR
942 IP6_STR
943 OSPF6_STR
944 ROUTE_STR
945 "Display Intra-Area routes\n"
946 "Display Inter-Area routes\n"
947 "Display Type-1 External routes\n"
948 "Display Type-2 External routes\n"
949 "Specify IPv6 address\n"
950 "Specify IPv6 prefix\n"
951 "Detailed information\n"
952 "Summary of route table\n")
953 {
954 OSPF6_CMD_CHECK_RUNNING();
955
956 ospf6_route_table_show(vty, 4, argc, argv, ospf6->route_table);
957 return CMD_SUCCESS;
958 }
959
960 DEFUN (show_ipv6_ospf6_route_match,
961 show_ipv6_ospf6_route_match_cmd,
962 "show ipv6 ospf6 route X:X::X:X/M <match|longer>",
963 SHOW_STR
964 IP6_STR
965 OSPF6_STR
966 ROUTE_STR
967 "Specify IPv6 prefix\n"
968 "Display routes which match the specified route\n"
969 "Display routes longer than the specified route\n")
970 {
971 OSPF6_CMD_CHECK_RUNNING();
972
973 ospf6_route_table_show(vty, 4, argc, argv, ospf6->route_table);
974 return CMD_SUCCESS;
975 }
976
977 DEFUN (show_ipv6_ospf6_route_match_detail,
978 show_ipv6_ospf6_route_match_detail_cmd,
979 "show ipv6 ospf6 route X:X::X:X/M match detail",
980 SHOW_STR
981 IP6_STR
982 OSPF6_STR
983 ROUTE_STR
984 "Specify IPv6 prefix\n"
985 "Display routes which match the specified route\n"
986 "Detailed information\n"
987 )
988 {
989 OSPF6_CMD_CHECK_RUNNING();
990
991 ospf6_route_table_show(vty, 4, argc, argv, ospf6->route_table);
992 return CMD_SUCCESS;
993 }
994
995
996 DEFUN (show_ipv6_ospf6_route_type_detail,
997 show_ipv6_ospf6_route_type_detail_cmd,
998 "show ipv6 ospf6 route <intra-area|inter-area|external-1|external-2> detail",
999 SHOW_STR
1000 IP6_STR
1001 OSPF6_STR
1002 ROUTE_STR
1003 "Display Intra-Area routes\n"
1004 "Display Inter-Area routes\n"
1005 "Display Type-1 External routes\n"
1006 "Display Type-2 External routes\n"
1007 "Detailed information\n"
1008 )
1009 {
1010 OSPF6_CMD_CHECK_RUNNING();
1011
1012 ospf6_route_table_show(vty, 4, argc, argv, ospf6->route_table);
1013 return CMD_SUCCESS;
1014 }
1015
1016 static void ospf6_stub_router_config_write(struct vty *vty)
1017 {
1018 if (CHECK_FLAG(ospf6->flag, OSPF6_STUB_ROUTER)) {
1019 vty_out(vty, " stub-router administrative\n");
1020 }
1021 return;
1022 }
1023
1024 static int ospf6_distance_config_write(struct vty *vty)
1025 {
1026 struct route_node *rn;
1027 struct ospf6_distance *odistance;
1028
1029 if (ospf6->distance_all)
1030 vty_out(vty, " distance %u\n", ospf6->distance_all);
1031
1032 if (ospf6->distance_intra || ospf6->distance_inter
1033 || ospf6->distance_external) {
1034 vty_out(vty, " distance ospf6");
1035
1036 if (ospf6->distance_intra)
1037 vty_out(vty, " intra-area %u", ospf6->distance_intra);
1038 if (ospf6->distance_inter)
1039 vty_out(vty, " inter-area %u", ospf6->distance_inter);
1040 if (ospf6->distance_external)
1041 vty_out(vty, " external %u", ospf6->distance_external);
1042
1043 vty_out(vty, "\n");
1044 }
1045
1046 for (rn = route_top(ospf6->distance_table); rn; rn = route_next(rn))
1047 if ((odistance = rn->info) != NULL) {
1048 char buf[PREFIX_STRLEN];
1049
1050 vty_out(vty, " distance %u %s %s\n",
1051 odistance->distance,
1052 prefix2str(&rn->p, buf, sizeof(buf)),
1053 odistance->access_list ? odistance->access_list
1054 : "");
1055 }
1056 return 0;
1057 }
1058
1059 /* OSPF configuration write function. */
1060 static int config_write_ospf6(struct vty *vty)
1061 {
1062 char router_id[16];
1063 struct listnode *j, *k;
1064 struct ospf6_area *oa;
1065 struct ospf6_interface *oi;
1066
1067 /* OSPFv3 configuration. */
1068 if (ospf6 == NULL)
1069 return CMD_SUCCESS;
1070
1071 inet_ntop(AF_INET, &ospf6->router_id_static, router_id,
1072 sizeof(router_id));
1073 vty_out(vty, "router ospf6\n");
1074 if (ospf6->router_id_static != 0)
1075 vty_out(vty, " ospf6 router-id %s\n", router_id);
1076
1077 /* log-adjacency-changes flag print. */
1078 if (CHECK_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES)) {
1079 if (CHECK_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL))
1080 vty_out(vty, " log-adjacency-changes detail\n");
1081 else if (!DFLT_OSPF6_LOG_ADJACENCY_CHANGES)
1082 vty_out(vty, " log-adjacency-changes\n");
1083 } else if (DFLT_OSPF6_LOG_ADJACENCY_CHANGES) {
1084 vty_out(vty, " no log-adjacency-changes\n");
1085 }
1086
1087 if (ospf6->ref_bandwidth != OSPF6_REFERENCE_BANDWIDTH)
1088 vty_out(vty, " auto-cost reference-bandwidth %d\n",
1089 ospf6->ref_bandwidth);
1090
1091 /* LSA timers print. */
1092 if (ospf6->lsa_minarrival != OSPF_MIN_LS_ARRIVAL)
1093 vty_out(vty, " timers lsa min-arrival %d\n",
1094 ospf6->lsa_minarrival);
1095
1096 ospf6_stub_router_config_write(vty);
1097 ospf6_redistribute_config_write(vty);
1098 ospf6_area_config_write(vty);
1099 ospf6_spf_config_write(vty);
1100 ospf6_distance_config_write(vty);
1101
1102 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, j, oa)) {
1103 for (ALL_LIST_ELEMENTS_RO(oa->if_list, k, oi))
1104 vty_out(vty, " interface %s area %s\n",
1105 oi->interface->name, oa->name);
1106 }
1107 vty_out(vty, "!\n");
1108 return 0;
1109 }
1110
1111 /* OSPF6 node structure. */
1112 static struct cmd_node ospf6_node = {
1113 OSPF6_NODE, "%s(config-ospf6)# ", 1 /* VTYSH */
1114 };
1115
1116 /* Install ospf related commands. */
1117 void ospf6_top_init(void)
1118 {
1119 /* Install ospf6 top node. */
1120 install_node(&ospf6_node, config_write_ospf6);
1121
1122 install_element(VIEW_NODE, &show_ipv6_ospf6_cmd);
1123 install_element(CONFIG_NODE, &router_ospf6_cmd);
1124 install_element(CONFIG_NODE, &no_router_ospf6_cmd);
1125
1126 install_element(VIEW_NODE, &show_ipv6_ospf6_route_cmd);
1127 install_element(VIEW_NODE, &show_ipv6_ospf6_route_match_cmd);
1128 install_element(VIEW_NODE, &show_ipv6_ospf6_route_match_detail_cmd);
1129 install_element(VIEW_NODE, &show_ipv6_ospf6_route_type_detail_cmd);
1130
1131 install_default(OSPF6_NODE);
1132 install_element(OSPF6_NODE, &ospf6_router_id_cmd);
1133 install_element(OSPF6_NODE, &no_ospf6_router_id_cmd);
1134 install_element(OSPF6_NODE, &ospf6_log_adjacency_changes_cmd);
1135 install_element(OSPF6_NODE, &ospf6_log_adjacency_changes_detail_cmd);
1136 install_element(OSPF6_NODE, &no_ospf6_log_adjacency_changes_cmd);
1137 install_element(OSPF6_NODE, &no_ospf6_log_adjacency_changes_detail_cmd);
1138
1139 /* LSA timers commands */
1140 install_element(OSPF6_NODE, &ospf6_timers_lsa_cmd);
1141 install_element(OSPF6_NODE, &no_ospf6_timers_lsa_cmd);
1142
1143 install_element(OSPF6_NODE, &ospf6_interface_area_cmd);
1144 install_element(OSPF6_NODE, &no_ospf6_interface_area_cmd);
1145 install_element(OSPF6_NODE, &ospf6_stub_router_admin_cmd);
1146 install_element(OSPF6_NODE, &no_ospf6_stub_router_admin_cmd);
1147 /* For a later time */
1148 #if 0
1149 install_element (OSPF6_NODE, &ospf6_stub_router_startup_cmd);
1150 install_element (OSPF6_NODE, &no_ospf6_stub_router_startup_cmd);
1151 install_element (OSPF6_NODE, &ospf6_stub_router_shutdown_cmd);
1152 install_element (OSPF6_NODE, &no_ospf6_stub_router_shutdown_cmd);
1153 #endif
1154
1155 install_element(OSPF6_NODE, &ospf6_distance_cmd);
1156 install_element(OSPF6_NODE, &no_ospf6_distance_cmd);
1157 install_element(OSPF6_NODE, &ospf6_distance_ospf6_cmd);
1158 install_element(OSPF6_NODE, &no_ospf6_distance_ospf6_cmd);
1159 #if 0
1160 install_element (OSPF6_NODE, &ospf6_distance_source_cmd);
1161 install_element (OSPF6_NODE, &no_ospf6_distance_source_cmd);
1162 #endif
1163 }