]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_top.c
Merge pull request #9053 from opensourcerouting/ospfv3-debug-guard
[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 #include "lib/json.h"
33 #include "lib_errors.h"
34
35 #include "ospf6_proto.h"
36 #include "ospf6_message.h"
37 #include "ospf6_lsa.h"
38 #include "ospf6_lsdb.h"
39 #include "ospf6_route.h"
40 #include "ospf6_zebra.h"
41
42 #include "ospf6_top.h"
43 #include "ospf6_area.h"
44 #include "ospf6_interface.h"
45 #include "ospf6_neighbor.h"
46 #include "ospf6_network.h"
47
48 #include "ospf6_flood.h"
49 #include "ospf6_asbr.h"
50 #include "ospf6_abr.h"
51 #include "ospf6_intra.h"
52 #include "ospf6_spf.h"
53 #include "ospf6d.h"
54 #include "lib/json.h"
55 #include "ospf6_nssa.h"
56
57 DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_TOP, "OSPF6 top");
58
59 DEFINE_QOBJ_TYPE(ospf6);
60
61 FRR_CFG_DEFAULT_BOOL(OSPF6_LOG_ADJACENCY_CHANGES,
62 { .val_bool = true, .match_profile = "datacenter", },
63 { .val_bool = false },
64 );
65
66 #ifndef VTYSH_EXTRACT_PL
67 #include "ospf6d/ospf6_top_clippy.c"
68 #endif
69
70 /* global ospf6d variable */
71 static struct ospf6_master ospf6_master;
72 struct ospf6_master *om6;
73
74 static void ospf6_disable(struct ospf6 *o);
75
76 static void ospf6_add(struct ospf6 *ospf6)
77 {
78 listnode_add(om6->ospf6, ospf6);
79 }
80
81 static void ospf6_del(struct ospf6 *ospf6)
82 {
83 listnode_delete(om6->ospf6, ospf6);
84 }
85
86 const char *ospf6_vrf_id_to_name(vrf_id_t vrf_id)
87 {
88 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
89
90 return vrf ? vrf->name : "NIL";
91 }
92
93 /* Link OSPF instance to VRF. */
94 void ospf6_vrf_link(struct ospf6 *ospf6, struct vrf *vrf)
95 {
96 ospf6->vrf_id = vrf->vrf_id;
97 if (vrf->info != (void *)ospf6)
98 vrf->info = (void *)ospf6;
99 }
100
101 /* Unlink OSPF instance from VRF. */
102 void ospf6_vrf_unlink(struct ospf6 *ospf6, struct vrf *vrf)
103 {
104 if (vrf->info == (void *)ospf6)
105 vrf->info = NULL;
106 ospf6->vrf_id = VRF_UNKNOWN;
107 }
108
109 struct ospf6 *ospf6_lookup_by_vrf_id(vrf_id_t vrf_id)
110 {
111 struct vrf *vrf = NULL;
112
113 vrf = vrf_lookup_by_id(vrf_id);
114 if (!vrf)
115 return NULL;
116 return (vrf->info) ? (struct ospf6 *)vrf->info : NULL;
117 }
118
119 struct ospf6 *ospf6_lookup_by_vrf_name(const char *name)
120 {
121 struct ospf6 *o = NULL;
122 struct listnode *node, *nnode;
123
124 for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, o)) {
125 if (((o->name == NULL && name == NULL)
126 || (o->name && name && strcmp(o->name, name) == 0)))
127 return o;
128 }
129 return NULL;
130 }
131
132 /* This is hook function for vrf create called as part of vrf_init */
133 static int ospf6_vrf_new(struct vrf *vrf)
134 {
135 return 0;
136 }
137
138 /* This is hook function for vrf delete call as part of vrf_init */
139 static int ospf6_vrf_delete(struct vrf *vrf)
140 {
141 return 0;
142 }
143
144 static void ospf6_set_redist_vrf_bitmaps(struct ospf6 *ospf6, bool set)
145 {
146 int type;
147 struct list *red_list;
148
149 for (type = 0; type < ZEBRA_ROUTE_MAX; type++) {
150 red_list = ospf6->redist[type];
151 if (!red_list)
152 continue;
153 if (IS_OSPF6_DEBUG_ZEBRA(RECV))
154 zlog_debug(
155 "%s: setting redist vrf %d bitmap for type %d",
156 __func__, ospf6->vrf_id, type);
157 if (set)
158 vrf_bitmap_set(zclient->redist[AFI_IP6][type],
159 ospf6->vrf_id);
160 else
161 vrf_bitmap_unset(zclient->redist[AFI_IP6][type],
162 ospf6->vrf_id);
163 }
164
165 red_list = ospf6->redist[DEFAULT_ROUTE];
166 if (red_list) {
167 if (set)
168 vrf_bitmap_set(zclient->default_information[AFI_IP6],
169 ospf6->vrf_id);
170 else
171 vrf_bitmap_unset(zclient->default_information[AFI_IP6],
172 ospf6->vrf_id);
173 }
174 }
175
176 /* Disable OSPF6 VRF instance */
177 static int ospf6_vrf_disable(struct vrf *vrf)
178 {
179 struct ospf6 *ospf6 = NULL;
180
181 if (vrf->vrf_id == VRF_DEFAULT)
182 return 0;
183
184 ospf6 = ospf6_lookup_by_vrf_name(vrf->name);
185 if (ospf6) {
186 ospf6_zebra_vrf_deregister(ospf6);
187
188 ospf6_set_redist_vrf_bitmaps(ospf6, false);
189
190 /* We have instance configured, unlink
191 * from VRF and make it "down".
192 */
193 ospf6_vrf_unlink(ospf6, vrf);
194 thread_cancel(&ospf6->t_ospf6_receive);
195 close(ospf6->fd);
196 ospf6->fd = -1;
197 }
198
199 /* Note: This is a callback, the VRF will be deleted by the caller. */
200 return 0;
201 }
202
203 /* Enable OSPF6 VRF instance */
204 static int ospf6_vrf_enable(struct vrf *vrf)
205 {
206 struct ospf6 *ospf6 = NULL;
207 vrf_id_t old_vrf_id;
208 int ret = 0;
209
210 ospf6 = ospf6_lookup_by_vrf_name(vrf->name);
211 if (ospf6) {
212 old_vrf_id = ospf6->vrf_id;
213 /* We have instance configured, link to VRF and make it "up". */
214 ospf6_vrf_link(ospf6, vrf);
215
216 if (old_vrf_id != ospf6->vrf_id) {
217 ospf6_set_redist_vrf_bitmaps(ospf6, true);
218
219 /* start zebra redist to us for new vrf */
220 ospf6_zebra_vrf_register(ospf6);
221
222 ret = ospf6_serv_sock(ospf6);
223 if (ret < 0 || ospf6->fd <= 0)
224 return 0;
225 thread_add_read(master, ospf6_receive, ospf6, ospf6->fd,
226 &ospf6->t_ospf6_receive);
227
228 ospf6_router_id_update(ospf6);
229 }
230 }
231
232 return 0;
233 }
234
235 void ospf6_vrf_init(void)
236 {
237 vrf_init(ospf6_vrf_new, ospf6_vrf_enable, ospf6_vrf_disable,
238 ospf6_vrf_delete, ospf6_vrf_enable);
239
240 vrf_cmd_init(NULL, &ospf6d_privs);
241 }
242
243 static void ospf6_top_lsdb_hook_add(struct ospf6_lsa *lsa)
244 {
245 switch (ntohs(lsa->header->type)) {
246 case OSPF6_LSTYPE_AS_EXTERNAL:
247 ospf6_asbr_lsa_add(lsa);
248 break;
249
250 default:
251 break;
252 }
253 }
254
255 static void ospf6_top_lsdb_hook_remove(struct ospf6_lsa *lsa)
256 {
257 switch (ntohs(lsa->header->type)) {
258 case OSPF6_LSTYPE_AS_EXTERNAL:
259 ospf6_asbr_lsa_remove(lsa, NULL);
260 break;
261
262 default:
263 break;
264 }
265 }
266
267 static void ospf6_top_route_hook_add(struct ospf6_route *route)
268 {
269 struct ospf6 *ospf6 = NULL;
270 struct ospf6_area *oa = NULL;
271
272 if (route->table->scope_type == OSPF6_SCOPE_TYPE_GLOBAL)
273 ospf6 = route->table->scope;
274 else if (route->table->scope_type == OSPF6_SCOPE_TYPE_AREA) {
275 oa = (struct ospf6_area *)route->table->scope;
276 ospf6 = oa->ospf6;
277 } else {
278 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)
279 || IS_OSPF6_DEBUG_BROUTER)
280 zlog_debug(
281 "%s: Route is not GLOBAL or scope is not of TYPE_AREA: %pFX",
282 __func__, &route->prefix);
283 return;
284 }
285
286 ospf6_abr_originate_summary(route, ospf6);
287 ospf6_zebra_route_update_add(route, ospf6);
288 }
289
290 static void ospf6_top_route_hook_remove(struct ospf6_route *route)
291 {
292 struct ospf6 *ospf6 = NULL;
293 struct ospf6_area *oa = NULL;
294
295 if (route->table->scope_type == OSPF6_SCOPE_TYPE_GLOBAL)
296 ospf6 = route->table->scope;
297 else if (route->table->scope_type == OSPF6_SCOPE_TYPE_AREA) {
298 oa = (struct ospf6_area *)route->table->scope;
299 ospf6 = oa->ospf6;
300 } else {
301 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)
302 || IS_OSPF6_DEBUG_BROUTER)
303 zlog_debug(
304 "%s: Route is not GLOBAL or scope is not of TYPE_AREA: %pFX",
305 __func__, &route->prefix);
306 return;
307 }
308
309 route->flag |= OSPF6_ROUTE_REMOVE;
310 ospf6_abr_originate_summary(route, ospf6);
311 ospf6_zebra_route_update_remove(route, ospf6);
312 }
313
314 static void ospf6_top_brouter_hook_add(struct ospf6_route *route)
315 {
316 struct ospf6 *ospf6 = route->table->scope;
317
318 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL) ||
319 IS_OSPF6_DEBUG_BROUTER) {
320 uint32_t brouter_id;
321 char brouter_name[16];
322
323 brouter_id = ADV_ROUTER_IN_PREFIX(&route->prefix);
324 inet_ntop(AF_INET, &brouter_id, brouter_name,
325 sizeof(brouter_name));
326 zlog_debug("%s: brouter %s add with adv router %x nh count %u",
327 __func__, brouter_name,
328 route->path.origin.adv_router,
329 listcount(route->nh_list));
330 }
331 ospf6_abr_examin_brouter(ADV_ROUTER_IN_PREFIX(&route->prefix), route,
332 ospf6);
333 ospf6_asbr_lsentry_add(route, ospf6);
334 ospf6_abr_originate_summary(route, ospf6);
335 }
336
337 static void ospf6_top_brouter_hook_remove(struct ospf6_route *route)
338 {
339 struct ospf6 *ospf6 = route->table->scope;
340
341 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL) ||
342 IS_OSPF6_DEBUG_BROUTER) {
343 uint32_t brouter_id;
344 char brouter_name[16];
345
346 brouter_id = ADV_ROUTER_IN_PREFIX(&route->prefix);
347 inet_ntop(AF_INET, &brouter_id, brouter_name,
348 sizeof(brouter_name));
349 zlog_debug("%s: brouter %p %s del with adv router %x nh %u",
350 __func__, (void *)route, brouter_name,
351 route->path.origin.adv_router,
352 listcount(route->nh_list));
353 }
354 route->flag |= OSPF6_ROUTE_REMOVE;
355 ospf6_abr_examin_brouter(ADV_ROUTER_IN_PREFIX(&route->prefix), route,
356 ospf6);
357 ospf6_asbr_lsentry_remove(route, ospf6);
358 ospf6_abr_originate_summary(route, ospf6);
359 }
360
361 static struct ospf6 *ospf6_create(const char *name)
362 {
363 struct ospf6 *o;
364 struct vrf *vrf = NULL;
365
366 o = XCALLOC(MTYPE_OSPF6_TOP, sizeof(struct ospf6));
367
368 vrf = vrf_lookup_by_name(name);
369 if (vrf) {
370 o->vrf_id = vrf->vrf_id;
371 } else
372 o->vrf_id = VRF_UNKNOWN;
373
374 /* Freed in ospf6_delete */
375 o->name = XSTRDUP(MTYPE_OSPF6_TOP, name);
376 if (vrf)
377 ospf6_vrf_link(o, vrf);
378
379 ospf6_zebra_vrf_register(o);
380
381 /* initialize */
382 monotime(&o->starttime);
383 o->area_list = list_new();
384 o->area_list->cmp = ospf6_area_cmp;
385 o->lsdb = ospf6_lsdb_create(o);
386 o->lsdb_self = ospf6_lsdb_create(o);
387 o->lsdb->hook_add = ospf6_top_lsdb_hook_add;
388 o->lsdb->hook_remove = ospf6_top_lsdb_hook_remove;
389
390 o->spf_delay = OSPF_SPF_DELAY_DEFAULT;
391 o->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
392 o->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT;
393 o->spf_hold_multiplier = 1;
394
395 o->default_originate = DEFAULT_ORIGINATE_NONE;
396 o->redistribute = 0;
397 /* LSA timers value init */
398 o->lsa_minarrival = OSPF_MIN_LS_ARRIVAL;
399
400 o->route_table = OSPF6_ROUTE_TABLE_CREATE(GLOBAL, ROUTES);
401 o->route_table->scope = o;
402 o->route_table->hook_add = ospf6_top_route_hook_add;
403 o->route_table->hook_remove = ospf6_top_route_hook_remove;
404
405 o->brouter_table = OSPF6_ROUTE_TABLE_CREATE(GLOBAL, BORDER_ROUTERS);
406 o->brouter_table->scope = o;
407 o->brouter_table->hook_add = ospf6_top_brouter_hook_add;
408 o->brouter_table->hook_remove = ospf6_top_brouter_hook_remove;
409
410 o->external_table = OSPF6_ROUTE_TABLE_CREATE(GLOBAL, EXTERNAL_ROUTES);
411 o->external_table->scope = o;
412
413 o->external_id_table = route_table_init();
414
415 o->write_oi_count = OSPF6_WRITE_INTERFACE_COUNT_DEFAULT;
416 o->ref_bandwidth = OSPF6_REFERENCE_BANDWIDTH;
417
418 o->distance_table = route_table_init();
419 o->fd = -1;
420
421 o->max_multipath = MULTIPATH_NUM;
422
423 o->oi_write_q = list_new();
424
425 QOBJ_REG(o, ospf6);
426
427 /* Make ospf protocol socket. */
428 ospf6_serv_sock(o);
429
430 return o;
431 }
432
433 struct ospf6 *ospf6_instance_create(const char *name)
434 {
435 struct ospf6 *ospf6;
436 struct vrf *vrf;
437 struct interface *ifp;
438
439 ospf6 = ospf6_create(name);
440 if (DFLT_OSPF6_LOG_ADJACENCY_CHANGES)
441 SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
442 if (ospf6->router_id == 0)
443 ospf6_router_id_update(ospf6);
444 ospf6_add(ospf6);
445 if (ospf6->vrf_id != VRF_UNKNOWN) {
446 vrf = vrf_lookup_by_id(ospf6->vrf_id);
447 FOR_ALL_INTERFACES (vrf, ifp) {
448 if (ifp->info)
449 ospf6_interface_start(ifp->info);
450 }
451 }
452 if (ospf6->fd < 0)
453 return ospf6;
454
455 thread_add_read(master, ospf6_receive, ospf6, ospf6->fd,
456 &ospf6->t_ospf6_receive);
457
458 return ospf6;
459 }
460
461 void ospf6_delete(struct ospf6 *o)
462 {
463 struct listnode *node, *nnode;
464 struct ospf6_area *oa;
465 struct vrf *vrf;
466
467 QOBJ_UNREG(o);
468
469 ospf6_flush_self_originated_lsas_now(o);
470 ospf6_disable(o);
471 ospf6_del(o);
472
473 ospf6_zebra_vrf_deregister(o);
474
475 ospf6_serv_close(&o->fd);
476
477 for (ALL_LIST_ELEMENTS(o->area_list, node, nnode, oa))
478 ospf6_area_delete(oa);
479
480
481 list_delete(&o->area_list);
482
483 ospf6_lsdb_delete(o->lsdb);
484 ospf6_lsdb_delete(o->lsdb_self);
485
486 ospf6_route_table_delete(o->route_table);
487 ospf6_route_table_delete(o->brouter_table);
488
489 ospf6_route_table_delete(o->external_table);
490 route_table_finish(o->external_id_table);
491
492 ospf6_distance_reset(o);
493 route_table_finish(o->distance_table);
494 list_delete(&o->oi_write_q);
495
496 if (o->vrf_id != VRF_UNKNOWN) {
497 vrf = vrf_lookup_by_id(o->vrf_id);
498 if (vrf)
499 ospf6_vrf_unlink(o, vrf);
500 }
501
502 XFREE(MTYPE_OSPF6_TOP, o->name);
503 XFREE(MTYPE_OSPF6_TOP, o);
504 }
505
506 static void ospf6_disable(struct ospf6 *o)
507 {
508 struct listnode *node, *nnode;
509 struct ospf6_area *oa;
510
511 if (!CHECK_FLAG(o->flag, OSPF6_DISABLED)) {
512 SET_FLAG(o->flag, OSPF6_DISABLED);
513
514 for (ALL_LIST_ELEMENTS(o->area_list, node, nnode, oa))
515 ospf6_area_disable(oa);
516
517 /* XXX: This also changes persistent settings */
518 /* Unregister redistribution */
519 ospf6_asbr_redistribute_disable(o);
520
521 ospf6_lsdb_remove_all(o->lsdb);
522 ospf6_route_remove_all(o->route_table);
523 ospf6_route_remove_all(o->brouter_table);
524
525 THREAD_OFF(o->maxage_remover);
526 THREAD_OFF(o->t_spf_calc);
527 THREAD_OFF(o->t_ase_calc);
528 THREAD_OFF(o->t_distribute_update);
529 THREAD_OFF(o->t_ospf6_receive);
530 }
531 }
532
533 void ospf6_master_init(struct thread_master *master)
534 {
535 memset(&ospf6_master, 0, sizeof(struct ospf6_master));
536
537 om6 = &ospf6_master;
538 om6->ospf6 = list_new();
539 om6->master = master;
540 }
541
542 static int ospf6_maxage_remover(struct thread *thread)
543 {
544 struct ospf6 *o = (struct ospf6 *)THREAD_ARG(thread);
545 struct ospf6_area *oa;
546 struct ospf6_interface *oi;
547 struct ospf6_neighbor *on;
548 struct listnode *i, *j, *k;
549 int reschedule = 0;
550
551 o->maxage_remover = (struct thread *)NULL;
552
553 for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) {
554 for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) {
555 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, k, on)) {
556 if (on->state != OSPF6_NEIGHBOR_EXCHANGE
557 && on->state != OSPF6_NEIGHBOR_LOADING)
558 continue;
559
560 ospf6_maxage_remove(o);
561 return 0;
562 }
563 }
564 }
565
566 for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) {
567 for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) {
568 if (ospf6_lsdb_maxage_remover(oi->lsdb)) {
569 reschedule = 1;
570 }
571 }
572
573 if (ospf6_lsdb_maxage_remover(oa->lsdb)) {
574 reschedule = 1;
575 }
576 }
577
578 if (ospf6_lsdb_maxage_remover(o->lsdb)) {
579 reschedule = 1;
580 }
581
582 if (reschedule) {
583 ospf6_maxage_remove(o);
584 }
585
586 return 0;
587 }
588
589 void ospf6_maxage_remove(struct ospf6 *o)
590 {
591 if (o)
592 thread_add_timer(master, ospf6_maxage_remover, o,
593 OSPF_LSA_MAXAGE_REMOVE_DELAY_DEFAULT,
594 &o->maxage_remover);
595 }
596
597 void ospf6_router_id_update(struct ospf6 *ospf6)
598 {
599 if (!ospf6)
600 return;
601
602 if (ospf6->router_id_static != 0)
603 ospf6->router_id = ospf6->router_id_static;
604 else
605 ospf6->router_id = ospf6->router_id_zebra;
606 }
607
608 /* start ospf6 */
609 DEFUN_NOSH(router_ospf6, router_ospf6_cmd, "router ospf6 [vrf NAME]",
610 ROUTER_STR OSPF6_STR VRF_CMD_HELP_STR)
611 {
612 struct ospf6 *ospf6;
613 const char *vrf_name = VRF_DEFAULT_NAME;
614 int idx_vrf = 0;
615
616 if (argv_find(argv, argc, "vrf", &idx_vrf)) {
617 vrf_name = argv[idx_vrf + 1]->arg;
618 }
619
620 ospf6 = ospf6_lookup_by_vrf_name(vrf_name);
621 if (ospf6 == NULL)
622 ospf6 = ospf6_instance_create(vrf_name);
623
624 /* set current ospf point. */
625 VTY_PUSH_CONTEXT(OSPF6_NODE, ospf6);
626
627 return CMD_SUCCESS;
628 }
629
630 /* stop ospf6 */
631 DEFUN(no_router_ospf6, no_router_ospf6_cmd, "no router ospf6 [vrf NAME]",
632 NO_STR ROUTER_STR OSPF6_STR VRF_CMD_HELP_STR)
633 {
634 struct ospf6 *ospf6;
635 const char *vrf_name = VRF_DEFAULT_NAME;
636 int idx_vrf = 0;
637
638 if (argv_find(argv, argc, "vrf", &idx_vrf)) {
639 vrf_name = argv[idx_vrf + 1]->arg;
640 }
641
642 ospf6 = ospf6_lookup_by_vrf_name(vrf_name);
643 if (ospf6 == NULL)
644 vty_out(vty, "OSPFv3 is not configured\n");
645 else {
646 ospf6_delete(ospf6);
647 ospf6 = NULL;
648 }
649
650 /* return to config node . */
651 VTY_PUSH_CONTEXT_NULL(CONFIG_NODE);
652
653 return CMD_SUCCESS;
654 }
655
656 static void ospf6_db_clear(struct ospf6 *ospf6)
657 {
658 struct ospf6_interface *oi;
659 struct interface *ifp;
660 struct vrf *vrf = vrf_lookup_by_id(ospf6->vrf_id);
661 struct listnode *node, *nnode;
662 struct ospf6_area *oa;
663
664 FOR_ALL_INTERFACES (vrf, ifp) {
665 if (if_is_operative(ifp) && ifp->info != NULL) {
666 oi = (struct ospf6_interface *)ifp->info;
667 ospf6_lsdb_remove_all(oi->lsdb);
668 ospf6_lsdb_remove_all(oi->lsdb_self);
669 ospf6_lsdb_remove_all(oi->lsupdate_list);
670 ospf6_lsdb_remove_all(oi->lsack_list);
671 }
672 }
673
674 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) {
675 ospf6_lsdb_remove_all(oa->lsdb);
676 ospf6_lsdb_remove_all(oa->lsdb_self);
677
678 ospf6_spf_table_finish(oa->spf_table);
679 ospf6_route_remove_all(oa->route_table);
680 }
681
682 ospf6_lsdb_remove_all(ospf6->lsdb);
683 ospf6_lsdb_remove_all(ospf6->lsdb_self);
684 ospf6_route_remove_all(ospf6->route_table);
685 ospf6_route_remove_all(ospf6->brouter_table);
686 }
687
688 static void ospf6_process_reset(struct ospf6 *ospf6)
689 {
690 struct interface *ifp;
691 struct vrf *vrf = vrf_lookup_by_id(ospf6->vrf_id);
692
693 ospf6_flush_self_originated_lsas_now(ospf6);
694 ospf6->inst_shutdown = 0;
695 ospf6_db_clear(ospf6);
696
697 ospf6_router_id_update(ospf6);
698
699 ospf6_asbr_redistribute_reset(ospf6);
700 FOR_ALL_INTERFACES (vrf, ifp)
701 ospf6_interface_clear(ifp);
702 }
703
704 DEFPY (clear_router_ospf6,
705 clear_router_ospf6_cmd,
706 "clear ipv6 ospf6 process [vrf NAME$name]",
707 CLEAR_STR
708 IP6_STR
709 OSPF6_STR
710 "Reset OSPF Process\n"
711 VRF_CMD_HELP_STR)
712 {
713 struct ospf6 *ospf6;
714 const char *vrf_name = VRF_DEFAULT_NAME;
715
716 if (name != NULL)
717 vrf_name = name;
718
719 ospf6 = ospf6_lookup_by_vrf_name(vrf_name);
720 if (ospf6 == NULL)
721 vty_out(vty, "OSPFv3 is not configured\n");
722 else
723 ospf6_process_reset(ospf6);
724
725 return CMD_SUCCESS;
726 }
727
728 /* change Router_ID commands. */
729 DEFUN(ospf6_router_id,
730 ospf6_router_id_cmd,
731 "ospf6 router-id A.B.C.D",
732 OSPF6_STR
733 "Configure OSPF6 Router-ID\n"
734 V4NOTATION_STR)
735 {
736 VTY_DECLVAR_CONTEXT(ospf6, o);
737 int idx = 0;
738 int ret;
739 const char *router_id_str;
740 uint32_t router_id;
741 struct ospf6_area *oa;
742 struct listnode *node;
743
744 argv_find(argv, argc, "A.B.C.D", &idx);
745 router_id_str = argv[idx]->arg;
746
747 ret = inet_pton(AF_INET, router_id_str, &router_id);
748 if (ret == 0) {
749 vty_out(vty, "malformed OSPF Router-ID: %s\n", router_id_str);
750 return CMD_SUCCESS;
751 }
752
753 o->router_id_static = router_id;
754
755 for (ALL_LIST_ELEMENTS_RO(o->area_list, node, oa)) {
756 if (oa->full_nbrs) {
757 vty_out(vty,
758 "For this router-id change to take effect, run the \"clear ipv6 ospf6 process\" command\n");
759 return CMD_SUCCESS;
760 }
761 }
762
763 o->router_id = router_id;
764
765 return CMD_SUCCESS;
766 }
767
768 DEFUN(no_ospf6_router_id,
769 no_ospf6_router_id_cmd,
770 "no ospf6 router-id [A.B.C.D]",
771 NO_STR OSPF6_STR
772 "Configure OSPF6 Router-ID\n"
773 V4NOTATION_STR)
774 {
775 VTY_DECLVAR_CONTEXT(ospf6, o);
776 struct ospf6_area *oa;
777 struct listnode *node;
778
779 o->router_id_static = 0;
780
781 for (ALL_LIST_ELEMENTS_RO(o->area_list, node, oa)) {
782 if (oa->full_nbrs) {
783 vty_out(vty,
784 "For this router-id change to take effect, run the \"clear ipv6 ospf6 process\" command\n");
785 return CMD_SUCCESS;
786 }
787 }
788 o->router_id = 0;
789 if (o->router_id_zebra)
790 o->router_id = o->router_id_zebra;
791
792 return CMD_SUCCESS;
793 }
794
795 DEFUN (ospf6_log_adjacency_changes,
796 ospf6_log_adjacency_changes_cmd,
797 "log-adjacency-changes",
798 "Log changes in adjacency state\n")
799 {
800 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
801
802 SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
803 UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
804 return CMD_SUCCESS;
805 }
806
807 DEFUN (ospf6_log_adjacency_changes_detail,
808 ospf6_log_adjacency_changes_detail_cmd,
809 "log-adjacency-changes detail",
810 "Log changes in adjacency state\n"
811 "Log all state changes\n")
812 {
813 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
814
815 SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
816 SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
817 return CMD_SUCCESS;
818 }
819
820 DEFUN (no_ospf6_log_adjacency_changes,
821 no_ospf6_log_adjacency_changes_cmd,
822 "no log-adjacency-changes",
823 NO_STR
824 "Log changes in adjacency state\n")
825 {
826 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
827
828 UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
829 UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
830 return CMD_SUCCESS;
831 }
832
833 DEFUN (no_ospf6_log_adjacency_changes_detail,
834 no_ospf6_log_adjacency_changes_detail_cmd,
835 "no log-adjacency-changes detail",
836 NO_STR
837 "Log changes in adjacency state\n"
838 "Log all state changes\n")
839 {
840 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
841
842 UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
843 return CMD_SUCCESS;
844 }
845
846 DEFUN (ospf6_timers_lsa,
847 ospf6_timers_lsa_cmd,
848 "timers lsa min-arrival (0-600000)",
849 "Adjust routing timers\n"
850 "OSPF6 LSA timers\n"
851 "Minimum delay in receiving new version of a LSA\n"
852 "Delay in milliseconds\n")
853 {
854 VTY_DECLVAR_CONTEXT(ospf6, ospf);
855 int idx_number = 3;
856 unsigned int minarrival;
857
858 minarrival = strtoul(argv[idx_number]->arg, NULL, 10);
859 ospf->lsa_minarrival = minarrival;
860
861 return CMD_SUCCESS;
862 }
863
864 DEFUN (no_ospf6_timers_lsa,
865 no_ospf6_timers_lsa_cmd,
866 "no timers lsa min-arrival [(0-600000)]",
867 NO_STR
868 "Adjust routing timers\n"
869 "OSPF6 LSA timers\n"
870 "Minimum delay in receiving new version of a LSA\n"
871 "Delay in milliseconds\n")
872 {
873 VTY_DECLVAR_CONTEXT(ospf6, ospf);
874 int idx_number = 4;
875 unsigned int minarrival;
876
877 if (argc == 5) {
878 minarrival = strtoul(argv[idx_number]->arg, NULL, 10);
879
880 if (ospf->lsa_minarrival != minarrival
881 || minarrival == OSPF_MIN_LS_ARRIVAL)
882 return CMD_SUCCESS;
883 }
884
885 ospf->lsa_minarrival = OSPF_MIN_LS_ARRIVAL;
886
887 return CMD_SUCCESS;
888 }
889
890
891 DEFUN (ospf6_distance,
892 ospf6_distance_cmd,
893 "distance (1-255)",
894 "Administrative distance\n"
895 "OSPF6 Administrative distance\n")
896 {
897 VTY_DECLVAR_CONTEXT(ospf6, o);
898
899 o->distance_all = atoi(argv[1]->arg);
900
901 return CMD_SUCCESS;
902 }
903
904 DEFUN (no_ospf6_distance,
905 no_ospf6_distance_cmd,
906 "no distance (1-255)",
907 NO_STR
908 "Administrative distance\n"
909 "OSPF6 Administrative distance\n")
910 {
911 VTY_DECLVAR_CONTEXT(ospf6, o);
912
913 o->distance_all = 0;
914
915 return CMD_SUCCESS;
916 }
917
918 DEFUN (ospf6_distance_ospf6,
919 ospf6_distance_ospf6_cmd,
920 "distance ospf6 {intra-area (1-255)|inter-area (1-255)|external (1-255)}",
921 "Administrative distance\n"
922 "OSPF6 administrative distance\n"
923 "Intra-area routes\n"
924 "Distance for intra-area routes\n"
925 "Inter-area routes\n"
926 "Distance for inter-area routes\n"
927 "External routes\n"
928 "Distance for external routes\n")
929 {
930 VTY_DECLVAR_CONTEXT(ospf6, o);
931 int idx = 0;
932
933 o->distance_intra = 0;
934 o->distance_inter = 0;
935 o->distance_external = 0;
936
937 if (argv_find(argv, argc, "intra-area", &idx))
938 o->distance_intra = atoi(argv[idx + 1]->arg);
939 idx = 0;
940 if (argv_find(argv, argc, "inter-area", &idx))
941 o->distance_inter = atoi(argv[idx + 1]->arg);
942 idx = 0;
943 if (argv_find(argv, argc, "external", &idx))
944 o->distance_external = atoi(argv[idx + 1]->arg);
945
946 return CMD_SUCCESS;
947 }
948
949 DEFUN (no_ospf6_distance_ospf6,
950 no_ospf6_distance_ospf6_cmd,
951 "no distance ospf6 [{intra-area [(1-255)]|inter-area [(1-255)]|external [(1-255)]}]",
952 NO_STR
953 "Administrative distance\n"
954 "OSPF6 distance\n"
955 "Intra-area routes\n"
956 "Distance for intra-area routes\n"
957 "Inter-area routes\n"
958 "Distance for inter-area routes\n"
959 "External routes\n"
960 "Distance for external routes\n")
961 {
962 VTY_DECLVAR_CONTEXT(ospf6, o);
963 int idx = 0;
964
965 if (argv_find(argv, argc, "intra-area", &idx) || argc == 3)
966 idx = o->distance_intra = 0;
967 if (argv_find(argv, argc, "inter-area", &idx) || argc == 3)
968 idx = o->distance_inter = 0;
969 if (argv_find(argv, argc, "external", &idx) || argc == 3)
970 o->distance_external = 0;
971
972 return CMD_SUCCESS;
973 }
974
975 DEFUN_HIDDEN (ospf6_interface_area,
976 ospf6_interface_area_cmd,
977 "interface IFNAME area <A.B.C.D|(0-4294967295)>",
978 "Enable routing on an IPv6 interface\n"
979 IFNAME_STR
980 "Specify the OSPF6 area ID\n"
981 "OSPF6 area ID in IPv4 address notation\n"
982 "OSPF6 area ID in decimal notation\n"
983 )
984 {
985 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
986 int idx_ifname = 1;
987 int idx_ipv4 = 3;
988 struct ospf6_area *oa;
989 struct ospf6_interface *oi;
990 struct interface *ifp;
991 vrf_id_t vrf_id = VRF_DEFAULT;
992 int ipv6_count = 0;
993 uint32_t area_id;
994 int format;
995
996 vty_out(vty,
997 "This command is deprecated, because it is not VRF-aware.\n");
998 vty_out(vty,
999 "Please, use \"ipv6 ospf6 area\" on an interface instead.\n");
1000
1001 if (ospf6->vrf_id != VRF_UNKNOWN)
1002 vrf_id = ospf6->vrf_id;
1003
1004 /* find/create ospf6 interface */
1005 ifp = if_get_by_name(argv[idx_ifname]->arg, vrf_id);
1006 oi = (struct ospf6_interface *)ifp->info;
1007 if (oi == NULL)
1008 oi = ospf6_interface_create(ifp);
1009 if (oi->area) {
1010 vty_out(vty, "%s already attached to Area %s\n",
1011 oi->interface->name, oi->area->name);
1012 return CMD_SUCCESS;
1013 }
1014
1015 /* if more than OSPF6_MAX_IF_ADDRS are configured on this interface
1016 * then don't allow ospfv3 to be configured
1017 */
1018 ipv6_count = connected_count_by_family(ifp, AF_INET6);
1019 if (oi->ifmtu == OSPF6_DEFAULT_MTU && ipv6_count > OSPF6_MAX_IF_ADDRS) {
1020 vty_out(vty,
1021 "can not configure OSPFv3 on if %s, must have less than %d interface addresses but has %d addresses\n",
1022 ifp->name, OSPF6_MAX_IF_ADDRS, ipv6_count);
1023 return CMD_WARNING_CONFIG_FAILED;
1024 } else if (oi->ifmtu >= OSPF6_JUMBO_MTU
1025 && ipv6_count > OSPF6_MAX_IF_ADDRS_JUMBO) {
1026 vty_out(vty,
1027 "can not configure OSPFv3 on if %s, must have less than %d interface addresses but has %d addresses\n",
1028 ifp->name, OSPF6_MAX_IF_ADDRS_JUMBO, ipv6_count);
1029 return CMD_WARNING_CONFIG_FAILED;
1030 }
1031
1032 if (str2area_id(argv[idx_ipv4]->arg, &area_id, &format)) {
1033 vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4]->arg);
1034 return CMD_WARNING_CONFIG_FAILED;
1035 }
1036
1037 oi->area_id = area_id;
1038 oi->area_id_format = format;
1039
1040 oa = ospf6_area_lookup(area_id, ospf6);
1041 if (oa == NULL)
1042 oa = ospf6_area_create(area_id, ospf6, format);
1043
1044 /* attach interface to area */
1045 listnode_add(oa->if_list, oi); /* sort ?? */
1046 oi->area = oa;
1047
1048 SET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
1049
1050 /* ospf6 process is currently disabled, not much more to do */
1051 if (CHECK_FLAG(ospf6->flag, OSPF6_DISABLED))
1052 return CMD_SUCCESS;
1053
1054 /* start up */
1055 ospf6_interface_enable(oi);
1056
1057 /* If the router is ABR, originate summary routes */
1058 if (ospf6_check_and_set_router_abr(ospf6)) {
1059 ospf6_abr_enable_area(oa);
1060 ospf6_schedule_abr_task(oa->ospf6);
1061 }
1062
1063 return CMD_SUCCESS;
1064 }
1065
1066 DEFUN_HIDDEN (no_ospf6_interface_area,
1067 no_ospf6_interface_area_cmd,
1068 "no interface IFNAME area <A.B.C.D|(0-4294967295)>",
1069 NO_STR
1070 "Disable routing on an IPv6 interface\n"
1071 IFNAME_STR
1072 "Specify the OSPF6 area ID\n"
1073 "OSPF6 area ID in IPv4 address notation\n"
1074 "OSPF6 area ID in decimal notation\n"
1075 )
1076 {
1077 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1078 int idx_ifname = 2;
1079 int idx_ipv4 = 4;
1080 struct ospf6_interface *oi;
1081 struct ospf6_area *oa;
1082 struct interface *ifp;
1083 uint32_t area_id;
1084 vrf_id_t vrf_id = VRF_DEFAULT;
1085
1086 vty_out(vty,
1087 "This command is deprecated, because it is not VRF-aware.\n");
1088 vty_out(vty,
1089 "Please, use \"no ipv6 ospf6 area\" on an interface instead.\n");
1090
1091 if (ospf6->vrf_id != VRF_UNKNOWN)
1092 vrf_id = ospf6->vrf_id;
1093
1094 /* find/create ospf6 interface */
1095 ifp = if_get_by_name(argv[idx_ifname]->arg, vrf_id);
1096
1097 if (ifp == NULL) {
1098 vty_out(vty, "No such interface %s\n", argv[idx_ifname]->arg);
1099 return CMD_SUCCESS;
1100 }
1101
1102 oi = (struct ospf6_interface *)ifp->info;
1103 if (oi == NULL) {
1104 vty_out(vty, "Interface %s not enabled\n", ifp->name);
1105 return CMD_SUCCESS;
1106 }
1107
1108 /* parse Area-ID */
1109 if (inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id) != 1)
1110 area_id = htonl(strtoul(argv[idx_ipv4]->arg, NULL, 10));
1111
1112 /* Verify Area */
1113 if (oi->area == NULL) {
1114 vty_out(vty, "%s not attached to area %s\n",
1115 oi->interface->name, argv[idx_ipv4]->arg);
1116 return CMD_SUCCESS;
1117 }
1118
1119 if (oi->area->area_id != area_id) {
1120 vty_out(vty, "Wrong Area-ID: %s is attached to area %s\n",
1121 oi->interface->name, oi->area->name);
1122 return CMD_SUCCESS;
1123 }
1124
1125 ospf6_interface_disable(oi);
1126
1127 oa = oi->area;
1128 listnode_delete(oi->area->if_list, oi);
1129 oi->area = (struct ospf6_area *)NULL;
1130
1131 /* Withdraw inter-area routes from this area, if necessary */
1132 if (oa->if_list->count == 0) {
1133 UNSET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
1134 ospf6_abr_disable_area(oa);
1135 }
1136
1137 oi->area_id = 0;
1138 oi->area_id_format = OSPF6_AREA_FMT_UNSET;
1139
1140 return CMD_SUCCESS;
1141 }
1142
1143 DEFUN (ospf6_stub_router_admin,
1144 ospf6_stub_router_admin_cmd,
1145 "stub-router administrative",
1146 "Make router a stub router\n"
1147 "Administratively applied, for an indefinite period\n")
1148 {
1149 struct listnode *node;
1150 struct ospf6_area *oa;
1151
1152 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1153
1154 if (!CHECK_FLAG(ospf6->flag, OSPF6_STUB_ROUTER)) {
1155 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
1156 OSPF6_OPT_CLEAR(oa->options, OSPF6_OPT_V6);
1157 OSPF6_OPT_CLEAR(oa->options, OSPF6_OPT_R);
1158 OSPF6_ROUTER_LSA_SCHEDULE(oa);
1159 }
1160 SET_FLAG(ospf6->flag, OSPF6_STUB_ROUTER);
1161 }
1162
1163 return CMD_SUCCESS;
1164 }
1165
1166 DEFUN (no_ospf6_stub_router_admin,
1167 no_ospf6_stub_router_admin_cmd,
1168 "no stub-router administrative",
1169 NO_STR
1170 "Make router a stub router\n"
1171 "Administratively applied, for an indefinite period\n")
1172 {
1173 struct listnode *node;
1174 struct ospf6_area *oa;
1175
1176 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1177 if (CHECK_FLAG(ospf6->flag, OSPF6_STUB_ROUTER)) {
1178 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
1179 OSPF6_OPT_SET(oa->options, OSPF6_OPT_V6);
1180 OSPF6_OPT_SET(oa->options, OSPF6_OPT_R);
1181 OSPF6_ROUTER_LSA_SCHEDULE(oa);
1182 }
1183 UNSET_FLAG(ospf6->flag, OSPF6_STUB_ROUTER);
1184 }
1185
1186 return CMD_SUCCESS;
1187 }
1188
1189 /* Restart OSPF SPF algorithm*/
1190 static void ospf6_restart_spf(struct ospf6 *ospf6)
1191 {
1192 ospf6_route_remove_all(ospf6->route_table);
1193 ospf6_route_remove_all(ospf6->brouter_table);
1194
1195 /* Trigger SPF */
1196 ospf6_spf_schedule(ospf6, OSPF6_SPF_FLAGS_CONFIG_CHANGE);
1197 }
1198
1199 /* Set the max paths */
1200 static void ospf6_maxpath_set(struct ospf6 *ospf6, uint16_t paths)
1201 {
1202 if (ospf6->max_multipath == paths)
1203 return;
1204
1205 ospf6->max_multipath = paths;
1206
1207 /* Send deletion to zebra to delete all
1208 * ospf specific routes and reinitiate
1209 * SPF to reflect the new max multipath.
1210 */
1211 ospf6_restart_spf(ospf6);
1212 }
1213
1214 /* Ospf Maximum-paths config support */
1215 DEFUN(ospf6_max_multipath,
1216 ospf6_max_multipath_cmd,
1217 "maximum-paths " CMD_RANGE_STR(1, MULTIPATH_NUM),
1218 "Max no of multiple paths for ECMP support\n"
1219 "Number of paths\n")
1220 {
1221 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1222 int idx_number = 1;
1223 int maximum_paths = strtol(argv[idx_number]->arg, NULL, 10);
1224
1225 ospf6_maxpath_set(ospf6, maximum_paths);
1226
1227 return CMD_SUCCESS;
1228 }
1229
1230 DEFUN(no_ospf6_max_multipath,
1231 no_ospf6_max_multipath_cmd,
1232 "no maximum-paths [" CMD_RANGE_STR(1, MULTIPATH_NUM)"]",
1233 NO_STR
1234 "Max no of multiple paths for ECMP support\n"
1235 "Number of paths\n")
1236 {
1237 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1238
1239 ospf6_maxpath_set(ospf6, MULTIPATH_NUM);
1240
1241 return CMD_SUCCESS;
1242 }
1243
1244 static void ospf6_show(struct vty *vty, struct ospf6 *o, json_object *json,
1245 bool use_json)
1246 {
1247 struct listnode *n;
1248 struct ospf6_area *oa;
1249 char router_id[16], duration[32];
1250 struct timeval now, running, result;
1251 char buf[32], rbuf[32];
1252 json_object *json_areas = NULL;
1253 const char *adjacency;
1254
1255 if (use_json) {
1256 json_areas = json_object_new_object();
1257
1258 /* process id, router id */
1259 inet_ntop(AF_INET, &o->router_id, router_id, sizeof(router_id));
1260 json_object_string_add(json, "routerId", router_id);
1261
1262 /* running time */
1263 monotime(&now);
1264 timersub(&now, &o->starttime, &running);
1265 timerstring(&running, duration, sizeof(duration));
1266 json_object_string_add(json, "running", duration);
1267
1268 /* Redistribute configuration */
1269 /* XXX */
1270 json_object_int_add(json, "lsaMinimumArrivalMsecs",
1271 o->lsa_minarrival);
1272
1273 /* Show SPF parameters */
1274 json_object_int_add(json, "spfScheduleDelayMsecs",
1275 o->spf_delay);
1276 json_object_int_add(json, "holdTimeMinMsecs", o->spf_holdtime);
1277 json_object_int_add(json, "holdTimeMaxMsecs",
1278 o->spf_max_holdtime);
1279 json_object_int_add(json, "holdTimeMultiplier",
1280 o->spf_hold_multiplier);
1281
1282 json_object_int_add(json, "maximumPaths", o->max_multipath);
1283
1284 if (o->ts_spf.tv_sec || o->ts_spf.tv_usec) {
1285 timersub(&now, &o->ts_spf, &result);
1286 timerstring(&result, buf, sizeof(buf));
1287 ospf6_spf_reason_string(o->last_spf_reason, rbuf,
1288 sizeof(rbuf));
1289 json_object_boolean_true_add(json, "spfHasRun");
1290 json_object_string_add(json, "spfLastExecutedMsecs",
1291 buf);
1292 json_object_string_add(json, "spfLastExecutedReason",
1293 rbuf);
1294
1295 json_object_int_add(
1296 json, "spfLastDurationSecs",
1297 (long long)o->ts_spf_duration.tv_sec);
1298
1299 json_object_int_add(
1300 json, "spfLastDurationMsecs",
1301 (long long)o->ts_spf_duration.tv_usec);
1302 } else
1303 json_object_boolean_false_add(json, "spfHasRun");
1304
1305
1306 threadtimer_string(now, o->t_spf_calc, buf, sizeof(buf));
1307 if (o->t_spf_calc) {
1308 long time_store;
1309
1310 json_object_boolean_true_add(json, "spfTimerActive");
1311 time_store =
1312 monotime_until(&o->t_spf_calc->u.sands, NULL)
1313 / 1000LL;
1314 json_object_int_add(json, "spfTimerDueInMsecs",
1315 time_store);
1316 } else
1317 json_object_boolean_false_add(json, "spfTimerActive");
1318
1319 json_object_boolean_add(json, "routerIsStubRouter",
1320 CHECK_FLAG(o->flag, OSPF6_STUB_ROUTER));
1321
1322 /* LSAs */
1323 json_object_int_add(json, "numberOfAsScopedLsa",
1324 o->lsdb->count);
1325 /* Areas */
1326 json_object_int_add(json, "numberOfAreaInRouter",
1327 listcount(o->area_list));
1328
1329 if (CHECK_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES)) {
1330 if (CHECK_FLAG(o->config_flags,
1331 OSPF6_LOG_ADJACENCY_DETAIL))
1332 adjacency = "LoggedAll";
1333 else
1334 adjacency = "Logged";
1335 } else
1336 adjacency = "NotLogged";
1337 json_object_string_add(json, "adjacencyChanges", adjacency);
1338
1339 for (ALL_LIST_ELEMENTS_RO(o->area_list, n, oa))
1340 ospf6_area_show(vty, oa, json_areas, use_json);
1341
1342 json_object_object_add(json, "areas", json_areas);
1343
1344 vty_out(vty, "%s\n",
1345 json_object_to_json_string_ext(
1346 json, JSON_C_TO_STRING_PRETTY));
1347
1348 } else {
1349 /* process id, router id */
1350 inet_ntop(AF_INET, &o->router_id, router_id, sizeof(router_id));
1351 vty_out(vty, " OSPFv3 Routing Process (0) with Router-ID %s\n",
1352 router_id);
1353
1354 /* running time */
1355 monotime(&now);
1356 timersub(&now, &o->starttime, &running);
1357 timerstring(&running, duration, sizeof(duration));
1358 vty_out(vty, " Running %s\n", duration);
1359
1360 /* Redistribute configuration */
1361 /* XXX */
1362 vty_out(vty, " LSA minimum arrival %d msecs\n",
1363 o->lsa_minarrival);
1364
1365 vty_out(vty, " Maximum-paths %u\n", o->max_multipath);
1366
1367 /* Show SPF parameters */
1368 vty_out(vty,
1369 " Initial SPF scheduling delay %d millisec(s)\n"
1370 " Minimum hold time between consecutive SPFs %d millsecond(s)\n"
1371 " Maximum hold time between consecutive SPFs %d millsecond(s)\n"
1372 " Hold time multiplier is currently %d\n",
1373 o->spf_delay, o->spf_holdtime, o->spf_max_holdtime,
1374 o->spf_hold_multiplier);
1375
1376
1377 vty_out(vty, " SPF algorithm ");
1378 if (o->ts_spf.tv_sec || o->ts_spf.tv_usec) {
1379 timersub(&now, &o->ts_spf, &result);
1380 timerstring(&result, buf, sizeof(buf));
1381 ospf6_spf_reason_string(o->last_spf_reason, rbuf,
1382 sizeof(rbuf));
1383 vty_out(vty, "last executed %s ago, reason %s\n", buf,
1384 rbuf);
1385 vty_out(vty, " Last SPF duration %lld sec %lld usec\n",
1386 (long long)o->ts_spf_duration.tv_sec,
1387 (long long)o->ts_spf_duration.tv_usec);
1388 } else
1389 vty_out(vty, "has not been run\n");
1390
1391 threadtimer_string(now, o->t_spf_calc, buf, sizeof(buf));
1392 vty_out(vty, " SPF timer %s%s\n",
1393 (o->t_spf_calc ? "due in " : "is "), buf);
1394
1395 if (CHECK_FLAG(o->flag, OSPF6_STUB_ROUTER))
1396 vty_out(vty, " Router Is Stub Router\n");
1397
1398 /* LSAs */
1399 vty_out(vty, " Number of AS scoped LSAs is %u\n",
1400 o->lsdb->count);
1401
1402 /* Areas */
1403 vty_out(vty, " Number of areas in this router is %u\n",
1404 listcount(o->area_list));
1405
1406 if (CHECK_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES)) {
1407 if (CHECK_FLAG(o->config_flags,
1408 OSPF6_LOG_ADJACENCY_DETAIL))
1409 vty_out(vty,
1410 " All adjacency changes are logged\n");
1411 else
1412 vty_out(vty, " Adjacency changes are logged\n");
1413 }
1414
1415
1416 vty_out(vty, "\n");
1417
1418 for (ALL_LIST_ELEMENTS_RO(o->area_list, n, oa))
1419 ospf6_area_show(vty, oa, json_areas, use_json);
1420 }
1421 }
1422
1423 DEFUN(show_ipv6_ospf6_vrfs, show_ipv6_ospf6_vrfs_cmd,
1424 "show ipv6 ospf6 vrfs [json]",
1425 SHOW_STR IP6_STR OSPF6_STR "Show OSPF6 VRFs \n" JSON_STR)
1426 {
1427 bool uj = use_json(argc, argv);
1428 json_object *json = NULL;
1429 json_object *json_vrfs = NULL;
1430 struct ospf6 *ospf6 = NULL;
1431 struct listnode *node = NULL;
1432 int count = 0;
1433 char buf[PREFIX_STRLEN];
1434 static const char header[] =
1435 "Name Id RouterId ";
1436
1437 if (uj) {
1438 json = json_object_new_object();
1439 json_vrfs = json_object_new_object();
1440 }
1441
1442 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1443 json_object *json_vrf = NULL;
1444 const char *name = NULL;
1445 int64_t vrf_id_ui = 0;
1446 struct in_addr router_id;
1447
1448 router_id.s_addr = ospf6->router_id;
1449 count++;
1450
1451 if (!uj && count == 1)
1452 vty_out(vty, "%s\n", header);
1453 if (uj)
1454 json_vrf = json_object_new_object();
1455
1456 if (ospf6->vrf_id == VRF_DEFAULT)
1457 name = VRF_DEFAULT_NAME;
1458 else
1459 name = ospf6->name;
1460
1461 vrf_id_ui = (ospf6->vrf_id == VRF_UNKNOWN)
1462 ? -1
1463 : (int64_t)ospf6->vrf_id;
1464
1465 if (uj) {
1466 json_object_int_add(json_vrf, "vrfId", vrf_id_ui);
1467 json_object_string_add(json_vrf, "routerId",
1468 inet_ntop(AF_INET, &router_id,
1469 buf, sizeof(buf)));
1470 json_object_object_add(json_vrfs, name, json_vrf);
1471
1472 } else {
1473 vty_out(vty, "%-25s %-5d %-16s \n", name,
1474 ospf6->vrf_id,
1475 inet_ntop(AF_INET, &router_id, buf,
1476 sizeof(buf)));
1477 }
1478 }
1479
1480 if (uj) {
1481 json_object_object_add(json, "vrfs", json_vrfs);
1482 json_object_int_add(json, "totalVrfs", count);
1483
1484 vty_out(vty, "%s\n",
1485 json_object_to_json_string_ext(
1486 json, JSON_C_TO_STRING_PRETTY));
1487 json_object_free(json);
1488 } else {
1489 if (count)
1490 vty_out(vty, "\nTotal number of OSPF VRFs: %d\n",
1491 count);
1492 }
1493
1494 return CMD_SUCCESS;
1495 }
1496
1497 /* show top level structures */
1498 DEFUN(show_ipv6_ospf6, show_ipv6_ospf6_cmd,
1499 "show ipv6 ospf6 [vrf <NAME|all>] [json]",
1500 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR "All VRFs\n" JSON_STR)
1501 {
1502 struct ospf6 *ospf6;
1503 struct listnode *node;
1504 const char *vrf_name = NULL;
1505 bool all_vrf = false;
1506 int idx_vrf = 0;
1507
1508 bool uj = use_json(argc, argv);
1509 json_object *json = NULL;
1510
1511 OSPF6_CMD_CHECK_RUNNING();
1512 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1513
1514 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1515 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1516 if (uj)
1517 json = json_object_new_object();
1518 ospf6_show(vty, ospf6, json, uj);
1519
1520 if (!all_vrf)
1521 break;
1522 }
1523 }
1524
1525 if (uj)
1526 json_object_free(json);
1527
1528 return CMD_SUCCESS;
1529 }
1530
1531 DEFUN(show_ipv6_ospf6_route, show_ipv6_ospf6_route_cmd,
1532 "show ipv6 ospf6 [vrf <NAME|all>] route [<intra-area|inter-area|external-1|external-2|X:X::X:X|X:X::X:X/M|detail|summary>] [json]",
1533 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1534 "All VRFs\n" ROUTE_STR
1535 "Display Intra-Area routes\n"
1536 "Display Inter-Area routes\n"
1537 "Display Type-1 External routes\n"
1538 "Display Type-2 External routes\n"
1539 "Specify IPv6 address\n"
1540 "Specify IPv6 prefix\n"
1541 "Detailed information\n"
1542 "Summary of route table\n" JSON_STR)
1543 {
1544 struct ospf6 *ospf6;
1545 struct listnode *node;
1546 const char *vrf_name = NULL;
1547 bool all_vrf = false;
1548 int idx_vrf = 0;
1549 int idx_arg_start = 4;
1550 bool uj = use_json(argc, argv);
1551
1552 OSPF6_CMD_CHECK_RUNNING();
1553 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1554 if (idx_vrf > 0)
1555 idx_arg_start += 2;
1556
1557 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1558 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1559 ospf6_route_table_show(vty, idx_arg_start, argc, argv,
1560 ospf6->route_table, uj);
1561
1562 if (!all_vrf)
1563 break;
1564 }
1565 }
1566
1567 return CMD_SUCCESS;
1568 }
1569
1570 DEFUN(show_ipv6_ospf6_route_match, show_ipv6_ospf6_route_match_cmd,
1571 "show ipv6 ospf6 [vrf <NAME|all>] route X:X::X:X/M <match|longer> [json]",
1572 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1573 "All VRFs\n" ROUTE_STR
1574 "Specify IPv6 prefix\n"
1575 "Display routes which match the specified route\n"
1576 "Display routes longer than the specified route\n" JSON_STR)
1577 {
1578 struct ospf6 *ospf6;
1579 struct listnode *node;
1580 const char *vrf_name = NULL;
1581 bool all_vrf = false;
1582 int idx_vrf = 0;
1583 int idx_start_arg = 4;
1584 bool uj = use_json(argc, argv);
1585
1586 OSPF6_CMD_CHECK_RUNNING();
1587 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1588 if (idx_vrf > 0)
1589 idx_start_arg += 2;
1590
1591 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1592 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1593 ospf6_route_table_show(vty, idx_start_arg, argc, argv,
1594 ospf6->route_table, uj);
1595
1596 if (!all_vrf)
1597 break;
1598 }
1599 }
1600
1601 return CMD_SUCCESS;
1602 }
1603
1604 DEFUN(show_ipv6_ospf6_route_match_detail,
1605 show_ipv6_ospf6_route_match_detail_cmd,
1606 "show ipv6 ospf6 [vrf <NAME|all>] route X:X::X:X/M match detail [json]",
1607 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1608 "All VRFs\n" ROUTE_STR
1609 "Specify IPv6 prefix\n"
1610 "Display routes which match the specified route\n"
1611 "Detailed information\n" JSON_STR)
1612 {
1613 struct ospf6 *ospf6;
1614 struct listnode *node;
1615 const char *vrf_name = NULL;
1616 bool all_vrf = false;
1617 int idx_vrf = 0;
1618 int idx_start_arg = 4;
1619 bool uj = use_json(argc, argv);
1620
1621 OSPF6_CMD_CHECK_RUNNING();
1622 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1623 if (idx_vrf > 0)
1624 idx_start_arg += 2;
1625
1626 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1627 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1628 ospf6_route_table_show(vty, idx_start_arg, argc, argv,
1629 ospf6->route_table, uj);
1630
1631 if (!all_vrf)
1632 break;
1633 }
1634 }
1635
1636 return CMD_SUCCESS;
1637 }
1638
1639 DEFUN(show_ipv6_ospf6_route_type_detail, show_ipv6_ospf6_route_type_detail_cmd,
1640 "show ipv6 ospf6 [vrf <NAME|all>] route <intra-area|inter-area|external-1|external-2> detail [json]",
1641 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1642 "All VRFs\n" ROUTE_STR
1643 "Display Intra-Area routes\n"
1644 "Display Inter-Area routes\n"
1645 "Display Type-1 External routes\n"
1646 "Display Type-2 External routes\n"
1647 "Detailed information\n" JSON_STR)
1648 {
1649 struct ospf6 *ospf6;
1650 struct listnode *node;
1651 const char *vrf_name = NULL;
1652 bool all_vrf = false;
1653 int idx_vrf = 0;
1654 int idx_start_arg = 4;
1655 bool uj = use_json(argc, argv);
1656
1657 OSPF6_CMD_CHECK_RUNNING();
1658 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1659 if (idx_vrf > 0)
1660 idx_start_arg += 2;
1661
1662 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1663 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1664 ospf6_route_table_show(vty, idx_start_arg, argc, argv,
1665 ospf6->route_table, uj);
1666
1667 if (!all_vrf)
1668 break;
1669 }
1670 }
1671
1672 return CMD_SUCCESS;
1673 }
1674
1675 static void ospf6_stub_router_config_write(struct vty *vty, struct ospf6 *ospf6)
1676 {
1677 if (CHECK_FLAG(ospf6->flag, OSPF6_STUB_ROUTER)) {
1678 vty_out(vty, " stub-router administrative\n");
1679 }
1680 return;
1681 }
1682
1683 static int ospf6_distance_config_write(struct vty *vty, struct ospf6 *ospf6)
1684 {
1685 struct route_node *rn;
1686 struct ospf6_distance *odistance;
1687
1688 if (ospf6->distance_all)
1689 vty_out(vty, " distance %u\n", ospf6->distance_all);
1690
1691 if (ospf6->distance_intra || ospf6->distance_inter
1692 || ospf6->distance_external) {
1693 vty_out(vty, " distance ospf6");
1694
1695 if (ospf6->distance_intra)
1696 vty_out(vty, " intra-area %u", ospf6->distance_intra);
1697 if (ospf6->distance_inter)
1698 vty_out(vty, " inter-area %u", ospf6->distance_inter);
1699 if (ospf6->distance_external)
1700 vty_out(vty, " external %u", ospf6->distance_external);
1701
1702 vty_out(vty, "\n");
1703 }
1704
1705 for (rn = route_top(ospf6->distance_table); rn; rn = route_next(rn))
1706 if ((odistance = rn->info) != NULL)
1707 vty_out(vty, " distance %u %pFX %s\n",
1708 odistance->distance, &rn->p,
1709 odistance->access_list ? odistance->access_list
1710 : "");
1711 return 0;
1712 }
1713
1714 /* OSPF configuration write function. */
1715 static int config_write_ospf6(struct vty *vty)
1716 {
1717 struct ospf6 *ospf6;
1718 struct listnode *node, *nnode;
1719
1720 /* OSPFv3 configuration. */
1721 if (om6 == NULL)
1722 return CMD_SUCCESS;
1723
1724 for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6)) {
1725 if (ospf6->name && strcmp(ospf6->name, VRF_DEFAULT_NAME))
1726 vty_out(vty, "router ospf6 vrf %s\n", ospf6->name);
1727 else
1728 vty_out(vty, "router ospf6\n");
1729
1730 if (ospf6->router_id_static != 0)
1731 vty_out(vty, " ospf6 router-id %pI4\n",
1732 &ospf6->router_id_static);
1733
1734 /* log-adjacency-changes flag print. */
1735 if (CHECK_FLAG(ospf6->config_flags,
1736 OSPF6_LOG_ADJACENCY_CHANGES)) {
1737 if (CHECK_FLAG(ospf6->config_flags,
1738 OSPF6_LOG_ADJACENCY_DETAIL))
1739 vty_out(vty, " log-adjacency-changes detail\n");
1740 else if (!SAVE_OSPF6_LOG_ADJACENCY_CHANGES)
1741 vty_out(vty, " log-adjacency-changes\n");
1742 } else if (SAVE_OSPF6_LOG_ADJACENCY_CHANGES) {
1743 vty_out(vty, " no log-adjacency-changes\n");
1744 }
1745
1746 if (ospf6->ref_bandwidth != OSPF6_REFERENCE_BANDWIDTH)
1747 vty_out(vty, " auto-cost reference-bandwidth %d\n",
1748 ospf6->ref_bandwidth);
1749
1750 if (ospf6->write_oi_count
1751 != OSPF6_WRITE_INTERFACE_COUNT_DEFAULT)
1752 vty_out(vty, " write-multiplier %d\n",
1753 ospf6->write_oi_count);
1754
1755 /* LSA timers print. */
1756 if (ospf6->lsa_minarrival != OSPF_MIN_LS_ARRIVAL)
1757 vty_out(vty, " timers lsa min-arrival %d\n",
1758 ospf6->lsa_minarrival);
1759
1760 /* ECMP max path config */
1761 if (ospf6->max_multipath != MULTIPATH_NUM)
1762 vty_out(vty, " maximum-paths %d\n",
1763 ospf6->max_multipath);
1764
1765 ospf6_stub_router_config_write(vty, ospf6);
1766 ospf6_redistribute_config_write(vty, ospf6);
1767 ospf6_area_config_write(vty, ospf6);
1768 ospf6_spf_config_write(vty, ospf6);
1769 ospf6_distance_config_write(vty, ospf6);
1770 ospf6_distribute_config_write(vty, ospf6);
1771
1772 vty_out(vty, "!\n");
1773 }
1774 return 0;
1775 }
1776
1777 static int config_write_ospf6(struct vty *vty);
1778 /* OSPF6 node structure. */
1779 static struct cmd_node ospf6_node = {
1780 .name = "ospf6",
1781 .node = OSPF6_NODE,
1782 .parent_node = CONFIG_NODE,
1783 .prompt = "%s(config-ospf6)# ",
1784 .config_write = config_write_ospf6,
1785 };
1786
1787 void install_element_ospf6_clear_process(void)
1788 {
1789 install_element(ENABLE_NODE, &clear_router_ospf6_cmd);
1790 }
1791
1792 /* Install ospf related commands. */
1793 void ospf6_top_init(void)
1794 {
1795 /* Install ospf6 top node. */
1796 install_node(&ospf6_node);
1797
1798 install_element(VIEW_NODE, &show_ipv6_ospf6_cmd);
1799 install_element(VIEW_NODE, &show_ipv6_ospf6_vrfs_cmd);
1800 install_element(CONFIG_NODE, &router_ospf6_cmd);
1801 install_element(CONFIG_NODE, &no_router_ospf6_cmd);
1802
1803 install_element(VIEW_NODE, &show_ipv6_ospf6_route_cmd);
1804 install_element(VIEW_NODE, &show_ipv6_ospf6_route_match_cmd);
1805 install_element(VIEW_NODE, &show_ipv6_ospf6_route_match_detail_cmd);
1806 install_element(VIEW_NODE, &show_ipv6_ospf6_route_type_detail_cmd);
1807
1808 install_default(OSPF6_NODE);
1809 install_element(OSPF6_NODE, &ospf6_router_id_cmd);
1810 install_element(OSPF6_NODE, &no_ospf6_router_id_cmd);
1811 install_element(OSPF6_NODE, &ospf6_log_adjacency_changes_cmd);
1812 install_element(OSPF6_NODE, &ospf6_log_adjacency_changes_detail_cmd);
1813 install_element(OSPF6_NODE, &no_ospf6_log_adjacency_changes_cmd);
1814 install_element(OSPF6_NODE, &no_ospf6_log_adjacency_changes_detail_cmd);
1815
1816 /* LSA timers commands */
1817 install_element(OSPF6_NODE, &ospf6_timers_lsa_cmd);
1818 install_element(OSPF6_NODE, &no_ospf6_timers_lsa_cmd);
1819
1820 install_element(OSPF6_NODE, &ospf6_interface_area_cmd);
1821 install_element(OSPF6_NODE, &no_ospf6_interface_area_cmd);
1822 install_element(OSPF6_NODE, &ospf6_stub_router_admin_cmd);
1823 install_element(OSPF6_NODE, &no_ospf6_stub_router_admin_cmd);
1824
1825 /* maximum-paths command */
1826 install_element(OSPF6_NODE, &ospf6_max_multipath_cmd);
1827 install_element(OSPF6_NODE, &no_ospf6_max_multipath_cmd);
1828
1829 install_element(OSPF6_NODE, &ospf6_distance_cmd);
1830 install_element(OSPF6_NODE, &no_ospf6_distance_cmd);
1831 install_element(OSPF6_NODE, &ospf6_distance_ospf6_cmd);
1832 install_element(OSPF6_NODE, &no_ospf6_distance_ospf6_cmd);
1833 }