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