]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_top.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / ospf6d / ospf6_top.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (C) 2003 Yasuhiro Ohara
4 */
5
6 #include <zebra.h>
7
8 #include "log.h"
9 #include "memory.h"
10 #include "vty.h"
11 #include "linklist.h"
12 #include "prefix.h"
13 #include "table.h"
14 #include "thread.h"
15 #include "command.h"
16 #include "defaults.h"
17 #include "lib/json.h"
18 #include "lib_errors.h"
19
20 #include "ospf6_proto.h"
21 #include "ospf6_message.h"
22 #include "ospf6_lsa.h"
23 #include "ospf6_lsdb.h"
24 #include "ospf6_route.h"
25 #include "ospf6_zebra.h"
26
27 #include "ospf6_top.h"
28 #include "ospf6_area.h"
29 #include "ospf6_interface.h"
30 #include "ospf6_neighbor.h"
31 #include "ospf6_network.h"
32
33 #include "ospf6_flood.h"
34 #include "ospf6_asbr.h"
35 #include "ospf6_abr.h"
36 #include "ospf6_intra.h"
37 #include "ospf6_spf.h"
38 #include "ospf6d.h"
39 #include "ospf6_gr.h"
40 #include "lib/json.h"
41 #include "ospf6_nssa.h"
42 #include "ospf6_auth_trailer.h"
43
44 DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_TOP, "OSPF6 top");
45
46 DEFINE_QOBJ_TYPE(ospf6);
47
48 FRR_CFG_DEFAULT_BOOL(OSPF6_LOG_ADJACENCY_CHANGES,
49 { .val_bool = true, .match_profile = "datacenter", },
50 { .val_bool = false },
51 );
52
53 #include "ospf6d/ospf6_top_clippy.c"
54
55 /* global ospf6d variable */
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_add(struct ospf6 *ospf6)
62 {
63 listnode_add(om6->ospf6, ospf6);
64 }
65
66 static void ospf6_del(struct ospf6 *ospf6)
67 {
68 listnode_delete(om6->ospf6, ospf6);
69 }
70
71 const char *ospf6_vrf_id_to_name(vrf_id_t vrf_id)
72 {
73 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
74
75 return vrf ? vrf->name : "NIL";
76 }
77
78 /* Link OSPF instance to VRF. */
79 void ospf6_vrf_link(struct ospf6 *ospf6, struct vrf *vrf)
80 {
81 ospf6->vrf_id = vrf->vrf_id;
82 if (vrf->info != (void *)ospf6)
83 vrf->info = (void *)ospf6;
84 }
85
86 /* Unlink OSPF instance from VRF. */
87 void ospf6_vrf_unlink(struct ospf6 *ospf6, struct vrf *vrf)
88 {
89 if (vrf->info == (void *)ospf6)
90 vrf->info = NULL;
91 ospf6->vrf_id = VRF_UNKNOWN;
92 }
93
94 struct ospf6 *ospf6_lookup_by_vrf_id(vrf_id_t vrf_id)
95 {
96 struct vrf *vrf = NULL;
97
98 vrf = vrf_lookup_by_id(vrf_id);
99 if (!vrf)
100 return NULL;
101 return (vrf->info) ? (struct ospf6 *)vrf->info : NULL;
102 }
103
104 struct ospf6 *ospf6_lookup_by_vrf_name(const char *name)
105 {
106 struct ospf6 *o = NULL;
107 struct listnode *node, *nnode;
108
109 for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, o)) {
110 if (((o->name == NULL && name == NULL)
111 || (o->name && name && strcmp(o->name, name) == 0)))
112 return o;
113 }
114 return NULL;
115 }
116
117 /* This is hook function for vrf create called as part of vrf_init */
118 static int ospf6_vrf_new(struct vrf *vrf)
119 {
120 return 0;
121 }
122
123 /* This is hook function for vrf delete call as part of vrf_init */
124 static int ospf6_vrf_delete(struct vrf *vrf)
125 {
126 return 0;
127 }
128
129 static void ospf6_set_redist_vrf_bitmaps(struct ospf6 *ospf6, bool set)
130 {
131 int type;
132 struct list *red_list;
133
134 for (type = 0; type < ZEBRA_ROUTE_MAX; type++) {
135 red_list = ospf6->redist[type];
136 if (!red_list)
137 continue;
138 if (IS_OSPF6_DEBUG_ZEBRA(RECV))
139 zlog_debug(
140 "%s: setting redist vrf %d bitmap for type %d",
141 __func__, ospf6->vrf_id, type);
142 if (set)
143 vrf_bitmap_set(zclient->redist[AFI_IP6][type],
144 ospf6->vrf_id);
145 else
146 vrf_bitmap_unset(zclient->redist[AFI_IP6][type],
147 ospf6->vrf_id);
148 }
149
150 red_list = ospf6->redist[DEFAULT_ROUTE];
151 if (red_list) {
152 if (set)
153 vrf_bitmap_set(zclient->default_information[AFI_IP6],
154 ospf6->vrf_id);
155 else
156 vrf_bitmap_unset(zclient->default_information[AFI_IP6],
157 ospf6->vrf_id);
158 }
159 }
160
161 /* Disable OSPF6 VRF instance */
162 static int ospf6_vrf_disable(struct vrf *vrf)
163 {
164 struct ospf6 *ospf6 = NULL;
165
166 if (vrf->vrf_id == VRF_DEFAULT)
167 return 0;
168
169 ospf6 = ospf6_lookup_by_vrf_name(vrf->name);
170 if (ospf6) {
171 ospf6_zebra_vrf_deregister(ospf6);
172
173 ospf6_set_redist_vrf_bitmaps(ospf6, false);
174
175 /* We have instance configured, unlink
176 * from VRF and make it "down".
177 */
178 ospf6_vrf_unlink(ospf6, vrf);
179 thread_cancel(&ospf6->t_ospf6_receive);
180 close(ospf6->fd);
181 ospf6->fd = -1;
182 }
183
184 /* Note: This is a callback, the VRF will be deleted by the caller. */
185 return 0;
186 }
187
188 /* Enable OSPF6 VRF instance */
189 static int ospf6_vrf_enable(struct vrf *vrf)
190 {
191 struct ospf6 *ospf6 = NULL;
192 vrf_id_t old_vrf_id;
193 int ret = 0;
194
195 ospf6 = ospf6_lookup_by_vrf_name(vrf->name);
196 if (ospf6) {
197 old_vrf_id = ospf6->vrf_id;
198 /* We have instance configured, link to VRF and make it "up". */
199 ospf6_vrf_link(ospf6, vrf);
200
201 if (old_vrf_id != ospf6->vrf_id) {
202 ospf6_set_redist_vrf_bitmaps(ospf6, true);
203
204 /* start zebra redist to us for new vrf */
205 ospf6_zebra_vrf_register(ospf6);
206
207 ret = ospf6_serv_sock(ospf6);
208 if (ret < 0 || ospf6->fd <= 0)
209 return 0;
210 thread_add_read(master, ospf6_receive, ospf6, ospf6->fd,
211 &ospf6->t_ospf6_receive);
212
213 ospf6_router_id_update(ospf6, true);
214 }
215 }
216
217 return 0;
218 }
219
220 void ospf6_vrf_init(void)
221 {
222 vrf_init(ospf6_vrf_new, ospf6_vrf_enable, ospf6_vrf_disable,
223 ospf6_vrf_delete);
224
225 vrf_cmd_init(NULL);
226 }
227
228 static void ospf6_top_lsdb_hook_add(struct ospf6_lsa *lsa)
229 {
230 switch (ntohs(lsa->header->type)) {
231 case OSPF6_LSTYPE_AS_EXTERNAL:
232 ospf6_asbr_lsa_add(lsa);
233 break;
234
235 default:
236 break;
237 }
238 }
239
240 static void ospf6_top_lsdb_hook_remove(struct ospf6_lsa *lsa)
241 {
242 switch (ntohs(lsa->header->type)) {
243 case OSPF6_LSTYPE_AS_EXTERNAL:
244 ospf6_asbr_lsa_remove(lsa, NULL);
245 break;
246
247 default:
248 break;
249 }
250 }
251
252 static void ospf6_top_route_hook_add(struct ospf6_route *route)
253 {
254 struct ospf6 *ospf6 = NULL;
255 struct ospf6_area *oa = NULL;
256
257 if (route->table->scope_type == OSPF6_SCOPE_TYPE_GLOBAL)
258 ospf6 = route->table->scope;
259 else if (route->table->scope_type == OSPF6_SCOPE_TYPE_AREA) {
260 oa = (struct ospf6_area *)route->table->scope;
261 ospf6 = oa->ospf6;
262 } else {
263 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)
264 || IS_OSPF6_DEBUG_BROUTER)
265 zlog_debug(
266 "%s: Route is not GLOBAL or scope is not of TYPE_AREA: %pFX",
267 __func__, &route->prefix);
268 return;
269 }
270
271 ospf6_abr_originate_summary(route, ospf6);
272 ospf6_zebra_route_update_add(route, ospf6);
273 }
274
275 static void ospf6_top_route_hook_remove(struct ospf6_route *route)
276 {
277 struct ospf6 *ospf6 = NULL;
278 struct ospf6_area *oa = NULL;
279
280 if (route->table->scope_type == OSPF6_SCOPE_TYPE_GLOBAL)
281 ospf6 = route->table->scope;
282 else if (route->table->scope_type == OSPF6_SCOPE_TYPE_AREA) {
283 oa = (struct ospf6_area *)route->table->scope;
284 ospf6 = oa->ospf6;
285 } else {
286 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)
287 || IS_OSPF6_DEBUG_BROUTER)
288 zlog_debug(
289 "%s: Route is not GLOBAL or scope is not of TYPE_AREA: %pFX",
290 __func__, &route->prefix);
291 return;
292 }
293
294 route->flag |= OSPF6_ROUTE_REMOVE;
295 ospf6_abr_originate_summary(route, ospf6);
296 ospf6_zebra_route_update_remove(route, ospf6);
297 }
298
299 static void ospf6_top_brouter_hook_add(struct ospf6_route *route)
300 {
301 struct ospf6 *ospf6 = route->table->scope;
302
303 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL) ||
304 IS_OSPF6_DEBUG_BROUTER) {
305 uint32_t brouter_id;
306 char brouter_name[16];
307
308 brouter_id = ADV_ROUTER_IN_PREFIX(&route->prefix);
309 inet_ntop(AF_INET, &brouter_id, brouter_name,
310 sizeof(brouter_name));
311 zlog_debug("%s: brouter %s add with adv router %x nh count %u",
312 __func__, brouter_name,
313 route->path.origin.adv_router,
314 listcount(route->nh_list));
315 }
316 ospf6_abr_examin_brouter(ADV_ROUTER_IN_PREFIX(&route->prefix), route,
317 ospf6);
318 ospf6_asbr_lsentry_add(route, ospf6);
319 ospf6_abr_originate_summary(route, ospf6);
320 }
321
322 static void ospf6_top_brouter_hook_remove(struct ospf6_route *route)
323 {
324 struct ospf6 *ospf6 = route->table->scope;
325
326 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL) ||
327 IS_OSPF6_DEBUG_BROUTER) {
328 uint32_t brouter_id;
329 char brouter_name[16];
330
331 brouter_id = ADV_ROUTER_IN_PREFIX(&route->prefix);
332 inet_ntop(AF_INET, &brouter_id, brouter_name,
333 sizeof(brouter_name));
334 zlog_debug("%s: brouter %p %s del with adv router %x nh %u",
335 __func__, (void *)route, brouter_name,
336 route->path.origin.adv_router,
337 listcount(route->nh_list));
338 }
339 route->flag |= OSPF6_ROUTE_REMOVE;
340 ospf6_abr_examin_brouter(ADV_ROUTER_IN_PREFIX(&route->prefix), route,
341 ospf6);
342 ospf6_asbr_lsentry_remove(route, ospf6);
343 ospf6_abr_originate_summary(route, ospf6);
344 }
345
346 static struct ospf6 *ospf6_create(const char *name)
347 {
348 struct ospf6 *o;
349 struct vrf *vrf = NULL;
350
351 o = XCALLOC(MTYPE_OSPF6_TOP, sizeof(struct ospf6));
352
353 vrf = vrf_lookup_by_name(name);
354 if (vrf) {
355 o->vrf_id = vrf->vrf_id;
356 } else
357 o->vrf_id = VRF_UNKNOWN;
358
359 /* Freed in ospf6_delete */
360 o->name = XSTRDUP(MTYPE_OSPF6_TOP, name);
361 if (vrf)
362 ospf6_vrf_link(o, vrf);
363
364 ospf6_zebra_vrf_register(o);
365
366 /* initialize */
367 monotime(&o->starttime);
368 o->area_list = list_new();
369 o->area_list->cmp = ospf6_area_cmp;
370 o->lsdb = ospf6_lsdb_create(o);
371 o->lsdb_self = ospf6_lsdb_create(o);
372 o->lsdb->hook_add = ospf6_top_lsdb_hook_add;
373 o->lsdb->hook_remove = ospf6_top_lsdb_hook_remove;
374
375 o->spf_delay = OSPF_SPF_DELAY_DEFAULT;
376 o->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
377 o->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT;
378 o->spf_hold_multiplier = 1;
379
380 o->default_originate = DEFAULT_ORIGINATE_NONE;
381 o->redistribute = 0;
382 /* LSA timers value init */
383 o->lsa_minarrival = OSPF_MIN_LS_ARRIVAL;
384
385 o->route_table = OSPF6_ROUTE_TABLE_CREATE(GLOBAL, ROUTES);
386 o->route_table->scope = o;
387 o->route_table->hook_add = ospf6_top_route_hook_add;
388 o->route_table->hook_remove = ospf6_top_route_hook_remove;
389
390 o->brouter_table = OSPF6_ROUTE_TABLE_CREATE(GLOBAL, BORDER_ROUTERS);
391 o->brouter_table->scope = o;
392 o->brouter_table->hook_add = ospf6_top_brouter_hook_add;
393 o->brouter_table->hook_remove = ospf6_top_brouter_hook_remove;
394
395 o->external_table = OSPF6_ROUTE_TABLE_CREATE(GLOBAL, EXTERNAL_ROUTES);
396 o->external_table->scope = o;
397 /* Setting this to 1, so that the LS ID 0 can be considered as invalid
398 * for self originated external LSAs. This helps in differentiating if
399 * an LSA is originated for any route or not in the route data.
400 * rt->route_option->id is by default 0
401 * Consider a route having id as 0 and prefix as 1::1, an external LSA
402 * is originated with ID 0.0.0.0. Now consider another route 2::2
403 * and for this LSA was not originated because of some configuration
404 * but the ID field rt->route_option->id is still 0.Consider now this
405 * 2::2 is being deleted, it will search LSA with LS ID as 0 and it
406 * will find the LSA and hence delete it but the LSA belonged to prefix
407 * 1::1, this happened because of LS ID 0.
408 */
409 o->external_id = OSPF6_EXT_INIT_LS_ID;
410
411 o->write_oi_count = OSPF6_WRITE_INTERFACE_COUNT_DEFAULT;
412 o->ref_bandwidth = OSPF6_REFERENCE_BANDWIDTH;
413
414 o->distance_table = route_table_init();
415
416 o->rt_aggr_tbl = route_table_init();
417 o->aggr_delay_interval = OSPF6_EXTL_AGGR_DEFAULT_DELAY;
418 o->aggr_action = OSPF6_ROUTE_AGGR_NONE;
419
420 o->fd = -1;
421
422 o->max_multipath = MULTIPATH_NUM;
423
424 o->oi_write_q = list_new();
425
426 ospf6_gr_helper_init(o);
427 QOBJ_REG(o, ospf6);
428
429 /* Make ospf protocol socket. */
430 ospf6_serv_sock(o);
431
432 /* If sequence number is stored in persistent storage, read it.
433 */
434 if (ospf6_auth_nvm_file_exist() == OSPF6_AUTH_FILE_EXIST) {
435 ospf6_auth_seqno_nvm_read(o);
436 o->seqnum_h = o->seqnum_h + 1;
437 ospf6_auth_seqno_nvm_update(o);
438 } else {
439 o->seqnum_l = o->seqnum_h = 0;
440 ospf6_auth_seqno_nvm_update(o);
441 }
442
443 return o;
444 }
445
446 struct ospf6 *ospf6_instance_create(const char *name)
447 {
448 struct ospf6 *ospf6;
449 struct vrf *vrf;
450 struct interface *ifp;
451
452 ospf6 = ospf6_create(name);
453 if (DFLT_OSPF6_LOG_ADJACENCY_CHANGES)
454 SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
455 if (ospf6->router_id == 0)
456 ospf6_router_id_update(ospf6, true);
457 ospf6_add(ospf6);
458 if (ospf6->vrf_id != VRF_UNKNOWN) {
459 vrf = vrf_lookup_by_id(ospf6->vrf_id);
460 FOR_ALL_INTERFACES (vrf, ifp) {
461 if (ifp->info)
462 ospf6_interface_start(ifp->info);
463 }
464 }
465 if (ospf6->fd < 0)
466 return ospf6;
467
468 /*
469 * Read from non-volatile memory whether this instance is performing a
470 * graceful restart or not.
471 */
472 ospf6_gr_nvm_read(ospf6);
473
474 thread_add_read(master, ospf6_receive, ospf6, ospf6->fd,
475 &ospf6->t_ospf6_receive);
476
477 return ospf6;
478 }
479
480 void ospf6_delete(struct ospf6 *o)
481 {
482 struct listnode *node, *nnode;
483 struct route_node *rn = NULL;
484 struct ospf6_area *oa;
485 struct vrf *vrf;
486 struct ospf6_external_aggr_rt *aggr;
487
488 QOBJ_UNREG(o);
489
490 ospf6_gr_helper_deinit(o);
491 if (!o->gr_info.prepare_in_progress)
492 ospf6_flush_self_originated_lsas_now(o);
493 ospf6_disable(o);
494 ospf6_del(o);
495
496 ospf6_zebra_vrf_deregister(o);
497
498 ospf6_serv_close(&o->fd);
499
500 for (ALL_LIST_ELEMENTS(o->area_list, node, nnode, oa))
501 ospf6_area_delete(oa);
502
503
504 list_delete(&o->area_list);
505
506 ospf6_lsdb_delete(o->lsdb);
507 ospf6_lsdb_delete(o->lsdb_self);
508
509 ospf6_route_table_delete(o->route_table);
510 ospf6_route_table_delete(o->brouter_table);
511
512 ospf6_route_table_delete(o->external_table);
513
514 ospf6_distance_reset(o);
515 route_table_finish(o->distance_table);
516 list_delete(&o->oi_write_q);
517
518 if (o->vrf_id != VRF_UNKNOWN) {
519 vrf = vrf_lookup_by_id(o->vrf_id);
520 if (vrf)
521 ospf6_vrf_unlink(o, vrf);
522 }
523
524 for (rn = route_top(o->rt_aggr_tbl); rn; rn = route_next(rn))
525 if (rn->info) {
526 aggr = rn->info;
527 ospf6_asbr_summary_config_delete(o, rn);
528 ospf6_external_aggregator_free(aggr);
529 }
530 route_table_finish(o->rt_aggr_tbl);
531
532 XFREE(MTYPE_OSPF6_TOP, o->name);
533 XFREE(MTYPE_OSPF6_TOP, o);
534 }
535
536 static void ospf6_disable(struct ospf6 *o)
537 {
538 struct listnode *node, *nnode;
539 struct ospf6_area *oa;
540
541 if (!CHECK_FLAG(o->flag, OSPF6_DISABLED)) {
542 SET_FLAG(o->flag, OSPF6_DISABLED);
543
544 for (ALL_LIST_ELEMENTS(o->area_list, node, nnode, oa))
545 ospf6_area_disable(oa);
546
547 /* XXX: This also changes persistent settings */
548 /* Unregister redistribution */
549 ospf6_asbr_redistribute_disable(o);
550
551 ospf6_lsdb_remove_all(o->lsdb);
552 ospf6_route_remove_all(o->route_table);
553 ospf6_route_remove_all(o->brouter_table);
554
555 THREAD_OFF(o->maxage_remover);
556 THREAD_OFF(o->t_spf_calc);
557 THREAD_OFF(o->t_ase_calc);
558 THREAD_OFF(o->t_distribute_update);
559 THREAD_OFF(o->t_ospf6_receive);
560 THREAD_OFF(o->t_external_aggr);
561 THREAD_OFF(o->gr_info.t_grace_period);
562 THREAD_OFF(o->t_write);
563 THREAD_OFF(o->t_abr_task);
564 }
565 }
566
567 void ospf6_master_init(struct thread_master *master)
568 {
569 memset(&ospf6_master, 0, sizeof(ospf6_master));
570
571 om6 = &ospf6_master;
572 om6->ospf6 = list_new();
573 om6->master = master;
574 }
575
576 static void ospf6_maxage_remover(struct thread *thread)
577 {
578 struct ospf6 *o = (struct ospf6 *)THREAD_ARG(thread);
579 struct ospf6_area *oa;
580 struct ospf6_interface *oi;
581 struct ospf6_neighbor *on;
582 struct listnode *i, *j, *k;
583 int reschedule = 0;
584
585 for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) {
586 for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) {
587 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, k, on)) {
588 if (on->state != OSPF6_NEIGHBOR_EXCHANGE
589 && on->state != OSPF6_NEIGHBOR_LOADING)
590 continue;
591
592 ospf6_maxage_remove(o);
593 return;
594 }
595 }
596 }
597
598 for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) {
599 for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) {
600 if (ospf6_lsdb_maxage_remover(oi->lsdb)) {
601 reschedule = 1;
602 }
603 }
604
605 if (ospf6_lsdb_maxage_remover(oa->lsdb)) {
606 reschedule = 1;
607 }
608 }
609
610 if (ospf6_lsdb_maxage_remover(o->lsdb)) {
611 reschedule = 1;
612 }
613
614 if (reschedule) {
615 ospf6_maxage_remove(o);
616 }
617 }
618
619 void ospf6_maxage_remove(struct ospf6 *o)
620 {
621 if (o)
622 thread_add_timer(master, ospf6_maxage_remover, o,
623 OSPF_LSA_MAXAGE_REMOVE_DELAY_DEFAULT,
624 &o->maxage_remover);
625 }
626
627 bool ospf6_router_id_update(struct ospf6 *ospf6, bool init)
628 {
629 in_addr_t new_router_id;
630 struct listnode *node;
631 struct ospf6_area *oa;
632
633 if (!ospf6)
634 return true;
635
636 if (ospf6->router_id_static != 0)
637 new_router_id = ospf6->router_id_static;
638 else
639 new_router_id = ospf6->router_id_zebra;
640
641 if (ospf6->router_id == new_router_id)
642 return true;
643
644 if (!init)
645 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
646 if (oa->full_nbrs) {
647 zlog_err(
648 "%s: cannot update router-id. Run the \"clear ipv6 ospf6 process\" command",
649 __func__);
650 return false;
651 }
652 }
653
654 ospf6->router_id = new_router_id;
655 return true;
656 }
657
658 /* start ospf6 */
659 DEFUN_NOSH(router_ospf6, router_ospf6_cmd, "router ospf6 [vrf NAME]",
660 ROUTER_STR OSPF6_STR VRF_CMD_HELP_STR)
661 {
662 struct ospf6 *ospf6;
663 const char *vrf_name = VRF_DEFAULT_NAME;
664 int idx_vrf = 0;
665
666 if (argv_find(argv, argc, "vrf", &idx_vrf)) {
667 vrf_name = argv[idx_vrf + 1]->arg;
668 }
669
670 ospf6 = ospf6_lookup_by_vrf_name(vrf_name);
671 if (ospf6 == NULL)
672 ospf6 = ospf6_instance_create(vrf_name);
673
674 /* set current ospf point. */
675 VTY_PUSH_CONTEXT(OSPF6_NODE, ospf6);
676
677 return CMD_SUCCESS;
678 }
679
680 /* stop ospf6 */
681 DEFUN(no_router_ospf6, no_router_ospf6_cmd, "no router ospf6 [vrf NAME]",
682 NO_STR ROUTER_STR OSPF6_STR VRF_CMD_HELP_STR)
683 {
684 struct ospf6 *ospf6;
685 const char *vrf_name = VRF_DEFAULT_NAME;
686 int idx_vrf = 0;
687
688 if (argv_find(argv, argc, "vrf", &idx_vrf)) {
689 vrf_name = argv[idx_vrf + 1]->arg;
690 }
691
692 ospf6 = ospf6_lookup_by_vrf_name(vrf_name);
693 if (ospf6 == NULL)
694 vty_out(vty, "OSPFv3 is not configured\n");
695 else {
696 ospf6_delete(ospf6);
697 ospf6 = NULL;
698 }
699
700 /* return to config node . */
701 VTY_PUSH_CONTEXT_NULL(CONFIG_NODE);
702
703 return CMD_SUCCESS;
704 }
705
706 static void ospf6_db_clear(struct ospf6 *ospf6)
707 {
708 struct ospf6_interface *oi;
709 struct interface *ifp;
710 struct vrf *vrf = vrf_lookup_by_id(ospf6->vrf_id);
711 struct listnode *node, *nnode;
712 struct ospf6_area *oa;
713
714 FOR_ALL_INTERFACES (vrf, ifp) {
715 if (if_is_operative(ifp) && ifp->info != NULL) {
716 oi = (struct ospf6_interface *)ifp->info;
717 ospf6_lsdb_remove_all(oi->lsdb);
718 ospf6_lsdb_remove_all(oi->lsdb_self);
719 ospf6_lsdb_remove_all(oi->lsupdate_list);
720 ospf6_lsdb_remove_all(oi->lsack_list);
721 }
722 }
723
724 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) {
725 ospf6_lsdb_remove_all(oa->lsdb);
726 ospf6_lsdb_remove_all(oa->lsdb_self);
727
728 ospf6_spf_table_finish(oa->spf_table);
729 ospf6_route_remove_all(oa->route_table);
730 }
731
732 ospf6_lsdb_remove_all(ospf6->lsdb);
733 ospf6_lsdb_remove_all(ospf6->lsdb_self);
734 ospf6_route_remove_all(ospf6->route_table);
735 ospf6_route_remove_all(ospf6->brouter_table);
736 }
737
738 static void ospf6_process_reset(struct ospf6 *ospf6)
739 {
740 struct interface *ifp;
741 struct vrf *vrf = vrf_lookup_by_id(ospf6->vrf_id);
742
743 ospf6_unset_all_aggr_flag(ospf6);
744 ospf6_flush_self_originated_lsas_now(ospf6);
745 ospf6->inst_shutdown = 0;
746 ospf6_db_clear(ospf6);
747
748 ospf6_asbr_redistribute_reset(ospf6);
749 FOR_ALL_INTERFACES (vrf, ifp)
750 ospf6_interface_clear(ifp);
751 }
752
753 DEFPY (clear_router_ospf6,
754 clear_router_ospf6_cmd,
755 "clear ipv6 ospf6 process [vrf NAME$name]",
756 CLEAR_STR
757 IP6_STR
758 OSPF6_STR
759 "Reset OSPF Process\n"
760 VRF_CMD_HELP_STR)
761 {
762 struct ospf6 *ospf6;
763 const char *vrf_name = VRF_DEFAULT_NAME;
764
765 if (name != NULL)
766 vrf_name = name;
767
768 ospf6 = ospf6_lookup_by_vrf_name(vrf_name);
769 if (ospf6 == NULL) {
770 vty_out(vty, "OSPFv3 is not configured\n");
771 } else {
772 ospf6_router_id_update(ospf6, true);
773 ospf6_process_reset(ospf6);
774 }
775
776 return CMD_SUCCESS;
777 }
778
779 /* change Router_ID commands. */
780 DEFUN(ospf6_router_id,
781 ospf6_router_id_cmd,
782 "ospf6 router-id A.B.C.D",
783 OSPF6_STR
784 "Configure OSPF6 Router-ID\n"
785 V4NOTATION_STR)
786 {
787 VTY_DECLVAR_CONTEXT(ospf6, o);
788 int idx = 0;
789 int ret;
790 const char *router_id_str;
791 uint32_t router_id;
792
793 argv_find(argv, argc, "A.B.C.D", &idx);
794 router_id_str = argv[idx]->arg;
795
796 ret = inet_pton(AF_INET, router_id_str, &router_id);
797 if (ret == 0) {
798 vty_out(vty, "malformed OSPF Router-ID: %s\n", router_id_str);
799 return CMD_SUCCESS;
800 }
801
802 o->router_id_static = router_id;
803
804 if (ospf6_router_id_update(o, false))
805 ospf6_process_reset(o);
806 else
807 vty_out(vty,
808 "For this router-id change to take effect run the \"clear ipv6 ospf6 process\" command\n");
809
810 return CMD_SUCCESS;
811 }
812
813 DEFUN(no_ospf6_router_id,
814 no_ospf6_router_id_cmd,
815 "no ospf6 router-id [A.B.C.D]",
816 NO_STR OSPF6_STR
817 "Configure OSPF6 Router-ID\n"
818 V4NOTATION_STR)
819 {
820 VTY_DECLVAR_CONTEXT(ospf6, o);
821
822 o->router_id_static = 0;
823
824
825 if (ospf6_router_id_update(o, false))
826 ospf6_process_reset(o);
827 else
828 vty_out(vty,
829 "For this router-id change to take effect run the \"clear ipv6 ospf6 process\" command\n");
830
831 return CMD_SUCCESS;
832 }
833
834 DEFUN (ospf6_log_adjacency_changes,
835 ospf6_log_adjacency_changes_cmd,
836 "log-adjacency-changes",
837 "Log changes in adjacency state\n")
838 {
839 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
840
841 SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
842 UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
843 return CMD_SUCCESS;
844 }
845
846 DEFUN (ospf6_log_adjacency_changes_detail,
847 ospf6_log_adjacency_changes_detail_cmd,
848 "log-adjacency-changes detail",
849 "Log changes in adjacency state\n"
850 "Log all state changes\n")
851 {
852 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
853
854 SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
855 SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
856 return CMD_SUCCESS;
857 }
858
859 DEFUN (no_ospf6_log_adjacency_changes,
860 no_ospf6_log_adjacency_changes_cmd,
861 "no log-adjacency-changes",
862 NO_STR
863 "Log changes in adjacency state\n")
864 {
865 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
866
867 UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
868 UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
869 return CMD_SUCCESS;
870 }
871
872 DEFUN (no_ospf6_log_adjacency_changes_detail,
873 no_ospf6_log_adjacency_changes_detail_cmd,
874 "no log-adjacency-changes detail",
875 NO_STR
876 "Log changes in adjacency state\n"
877 "Log all state changes\n")
878 {
879 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
880
881 UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
882 return CMD_SUCCESS;
883 }
884
885 static void ospf6_reinstall_routes(struct ospf6 *ospf6)
886 {
887 struct ospf6_route *route;
888
889 for (route = ospf6_route_head(ospf6->route_table); route;
890 route = ospf6_route_next(route))
891 ospf6_zebra_route_update_add(route, ospf6);
892 }
893
894 DEFPY (ospf6_send_extra_data,
895 ospf6_send_extra_data_cmd,
896 "[no] ospf6 send-extra-data zebra",
897 NO_STR
898 OSPF6_STR
899 "Extra data to Zebra for display/use\n"
900 "To zebra\n")
901 {
902 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
903
904 if (no
905 && CHECK_FLAG(ospf6->config_flags,
906 OSPF6_SEND_EXTRA_DATA_TO_ZEBRA)) {
907 UNSET_FLAG(ospf6->config_flags, OSPF6_SEND_EXTRA_DATA_TO_ZEBRA);
908 ospf6_reinstall_routes(ospf6);
909 } else if (!CHECK_FLAG(ospf6->config_flags,
910 OSPF6_SEND_EXTRA_DATA_TO_ZEBRA)) {
911 SET_FLAG(ospf6->config_flags, OSPF6_SEND_EXTRA_DATA_TO_ZEBRA);
912 ospf6_reinstall_routes(ospf6);
913 }
914
915 return CMD_SUCCESS;
916 }
917
918 DEFUN (ospf6_timers_lsa,
919 ospf6_timers_lsa_cmd,
920 "timers lsa min-arrival (0-600000)",
921 "Adjust routing timers\n"
922 "OSPF6 LSA timers\n"
923 "Minimum delay in receiving new version of a LSA\n"
924 "Delay in milliseconds\n")
925 {
926 VTY_DECLVAR_CONTEXT(ospf6, ospf);
927 int idx_number = 3;
928 unsigned int minarrival;
929
930 minarrival = strtoul(argv[idx_number]->arg, NULL, 10);
931 ospf->lsa_minarrival = minarrival;
932
933 return CMD_SUCCESS;
934 }
935
936 DEFUN (no_ospf6_timers_lsa,
937 no_ospf6_timers_lsa_cmd,
938 "no timers lsa min-arrival [(0-600000)]",
939 NO_STR
940 "Adjust routing timers\n"
941 "OSPF6 LSA timers\n"
942 "Minimum delay in receiving new version of a LSA\n"
943 "Delay in milliseconds\n")
944 {
945 VTY_DECLVAR_CONTEXT(ospf6, ospf);
946 int idx_number = 4;
947 unsigned int minarrival;
948
949 if (argc == 5) {
950 minarrival = strtoul(argv[idx_number]->arg, NULL, 10);
951
952 if (ospf->lsa_minarrival != minarrival
953 || minarrival == OSPF_MIN_LS_ARRIVAL)
954 return CMD_SUCCESS;
955 }
956
957 ospf->lsa_minarrival = OSPF_MIN_LS_ARRIVAL;
958
959 return CMD_SUCCESS;
960 }
961
962
963 DEFUN (ospf6_distance,
964 ospf6_distance_cmd,
965 "distance (1-255)",
966 "Administrative distance\n"
967 "OSPF6 Administrative distance\n")
968 {
969 VTY_DECLVAR_CONTEXT(ospf6, o);
970 uint8_t distance;
971
972 distance = atoi(argv[1]->arg);
973 if (o->distance_all != distance) {
974 o->distance_all = distance;
975 ospf6_restart_spf(o);
976 }
977
978 return CMD_SUCCESS;
979 }
980
981 DEFUN (no_ospf6_distance,
982 no_ospf6_distance_cmd,
983 "no distance (1-255)",
984 NO_STR
985 "Administrative distance\n"
986 "OSPF6 Administrative distance\n")
987 {
988 VTY_DECLVAR_CONTEXT(ospf6, o);
989
990 if (o->distance_all) {
991 o->distance_all = 0;
992 ospf6_restart_spf(o);
993 }
994 return CMD_SUCCESS;
995 }
996
997 DEFUN (ospf6_distance_ospf6,
998 ospf6_distance_ospf6_cmd,
999 "distance ospf6 {intra-area (1-255)|inter-area (1-255)|external (1-255)}",
1000 "Administrative distance\n"
1001 "OSPF6 administrative distance\n"
1002 "Intra-area routes\n"
1003 "Distance for intra-area routes\n"
1004 "Inter-area routes\n"
1005 "Distance for inter-area routes\n"
1006 "External routes\n"
1007 "Distance for external routes\n")
1008 {
1009 VTY_DECLVAR_CONTEXT(ospf6, o);
1010 int idx = 0;
1011
1012 o->distance_intra = 0;
1013 o->distance_inter = 0;
1014 o->distance_external = 0;
1015
1016 if (argv_find(argv, argc, "intra-area", &idx))
1017 o->distance_intra = atoi(argv[idx + 1]->arg);
1018 idx = 0;
1019 if (argv_find(argv, argc, "inter-area", &idx))
1020 o->distance_inter = atoi(argv[idx + 1]->arg);
1021 idx = 0;
1022 if (argv_find(argv, argc, "external", &idx))
1023 o->distance_external = atoi(argv[idx + 1]->arg);
1024
1025 return CMD_SUCCESS;
1026 }
1027
1028 DEFUN (no_ospf6_distance_ospf6,
1029 no_ospf6_distance_ospf6_cmd,
1030 "no distance ospf6 [{intra-area [(1-255)]|inter-area [(1-255)]|external [(1-255)]}]",
1031 NO_STR
1032 "Administrative distance\n"
1033 "OSPF6 distance\n"
1034 "Intra-area routes\n"
1035 "Distance for intra-area routes\n"
1036 "Inter-area routes\n"
1037 "Distance for inter-area routes\n"
1038 "External routes\n"
1039 "Distance for external routes\n")
1040 {
1041 VTY_DECLVAR_CONTEXT(ospf6, o);
1042 int idx = 0;
1043
1044 if (argv_find(argv, argc, "intra-area", &idx) || argc == 3)
1045 idx = o->distance_intra = 0;
1046 if (argv_find(argv, argc, "inter-area", &idx) || argc == 3)
1047 idx = o->distance_inter = 0;
1048 if (argv_find(argv, argc, "external", &idx) || argc == 3)
1049 o->distance_external = 0;
1050
1051 return CMD_SUCCESS;
1052 }
1053
1054 DEFUN_HIDDEN (ospf6_interface_area,
1055 ospf6_interface_area_cmd,
1056 "interface IFNAME area <A.B.C.D|(0-4294967295)>",
1057 "Enable routing on an IPv6 interface\n"
1058 IFNAME_STR
1059 "Specify the OSPF6 area ID\n"
1060 "OSPF6 area ID in IPv4 address notation\n"
1061 "OSPF6 area ID in decimal notation\n"
1062 )
1063 {
1064 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1065 int idx_ifname = 1;
1066 int idx_ipv4 = 3;
1067 struct ospf6_area *oa;
1068 struct ospf6_interface *oi;
1069 struct interface *ifp;
1070 uint32_t area_id;
1071 int format;
1072
1073 vty_out(vty,
1074 "This command is deprecated, because it is not VRF-aware.\n");
1075 vty_out(vty,
1076 "Please, use \"ipv6 ospf6 area\" on an interface instead.\n");
1077
1078 /* find/create ospf6 interface */
1079 ifp = if_get_by_name(argv[idx_ifname]->arg, ospf6->vrf_id, ospf6->name);
1080 oi = (struct ospf6_interface *)ifp->info;
1081 if (oi == NULL)
1082 oi = ospf6_interface_create(ifp);
1083 if (oi->area) {
1084 vty_out(vty, "%s already attached to Area %s\n",
1085 oi->interface->name, oi->area->name);
1086 return CMD_SUCCESS;
1087 }
1088
1089 if (str2area_id(argv[idx_ipv4]->arg, &area_id, &format)) {
1090 vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4]->arg);
1091 return CMD_WARNING_CONFIG_FAILED;
1092 }
1093
1094 oi->area_id = area_id;
1095 oi->area_id_format = format;
1096
1097 oa = ospf6_area_lookup(area_id, ospf6);
1098 if (oa == NULL)
1099 oa = ospf6_area_create(area_id, ospf6, format);
1100
1101 /* attach interface to area */
1102 listnode_add(oa->if_list, oi); /* sort ?? */
1103 oi->area = oa;
1104
1105 SET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
1106
1107 /* ospf6 process is currently disabled, not much more to do */
1108 if (CHECK_FLAG(ospf6->flag, OSPF6_DISABLED))
1109 return CMD_SUCCESS;
1110
1111 /* start up */
1112 ospf6_interface_enable(oi);
1113
1114 /* If the router is ABR, originate summary routes */
1115 if (ospf6_check_and_set_router_abr(ospf6)) {
1116 ospf6_abr_enable_area(oa);
1117 ospf6_schedule_abr_task(oa->ospf6);
1118 }
1119
1120 return CMD_SUCCESS;
1121 }
1122
1123 DEFUN_HIDDEN (no_ospf6_interface_area,
1124 no_ospf6_interface_area_cmd,
1125 "no interface IFNAME area <A.B.C.D|(0-4294967295)>",
1126 NO_STR
1127 "Disable routing on an IPv6 interface\n"
1128 IFNAME_STR
1129 "Specify the OSPF6 area ID\n"
1130 "OSPF6 area ID in IPv4 address notation\n"
1131 "OSPF6 area ID in decimal notation\n"
1132 )
1133 {
1134 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1135 int idx_ifname = 2;
1136 int idx_ipv4 = 4;
1137 struct ospf6_interface *oi;
1138 struct ospf6_area *oa;
1139 struct interface *ifp;
1140 uint32_t area_id;
1141
1142 vty_out(vty,
1143 "This command is deprecated, because it is not VRF-aware.\n");
1144 vty_out(vty,
1145 "Please, use \"no ipv6 ospf6 area\" on an interface instead.\n");
1146
1147 /* find/create ospf6 interface */
1148 ifp = if_get_by_name(argv[idx_ifname]->arg, ospf6->vrf_id, ospf6->name);
1149
1150 if (ifp == NULL) {
1151 vty_out(vty, "No such interface %s\n", argv[idx_ifname]->arg);
1152 return CMD_SUCCESS;
1153 }
1154
1155 oi = (struct ospf6_interface *)ifp->info;
1156 if (oi == NULL) {
1157 vty_out(vty, "Interface %s not enabled\n", ifp->name);
1158 return CMD_SUCCESS;
1159 }
1160
1161 /* parse Area-ID */
1162 if (inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id) != 1)
1163 area_id = htonl(strtoul(argv[idx_ipv4]->arg, NULL, 10));
1164
1165 /* Verify Area */
1166 if (oi->area == NULL) {
1167 vty_out(vty, "%s not attached to area %s\n",
1168 oi->interface->name, argv[idx_ipv4]->arg);
1169 return CMD_SUCCESS;
1170 }
1171
1172 if (oi->area->area_id != area_id) {
1173 vty_out(vty, "Wrong Area-ID: %s is attached to area %s\n",
1174 oi->interface->name, oi->area->name);
1175 return CMD_SUCCESS;
1176 }
1177
1178 ospf6_interface_disable(oi);
1179
1180 oa = oi->area;
1181 listnode_delete(oi->area->if_list, oi);
1182 oi->area = (struct ospf6_area *)NULL;
1183
1184 /* Withdraw inter-area routes from this area, if necessary */
1185 if (oa->if_list->count == 0) {
1186 UNSET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
1187 ospf6_abr_disable_area(oa);
1188 }
1189
1190 oi->area_id = 0;
1191 oi->area_id_format = OSPF6_AREA_FMT_UNSET;
1192
1193 return CMD_SUCCESS;
1194 }
1195
1196 DEFUN (ospf6_stub_router_admin,
1197 ospf6_stub_router_admin_cmd,
1198 "stub-router administrative",
1199 "Make router a stub router\n"
1200 "Administratively applied, for an indefinite period\n")
1201 {
1202 struct listnode *node;
1203 struct ospf6_area *oa;
1204
1205 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1206
1207 if (!CHECK_FLAG(ospf6->flag, OSPF6_STUB_ROUTER)) {
1208 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
1209 OSPF6_OPT_CLEAR(oa->options, OSPF6_OPT_V6);
1210 OSPF6_OPT_CLEAR(oa->options, OSPF6_OPT_R);
1211 OSPF6_ROUTER_LSA_SCHEDULE(oa);
1212 }
1213 SET_FLAG(ospf6->flag, OSPF6_STUB_ROUTER);
1214 }
1215
1216 return CMD_SUCCESS;
1217 }
1218
1219 DEFUN (no_ospf6_stub_router_admin,
1220 no_ospf6_stub_router_admin_cmd,
1221 "no stub-router administrative",
1222 NO_STR
1223 "Make router a stub router\n"
1224 "Administratively applied, for an indefinite period\n")
1225 {
1226 struct listnode *node;
1227 struct ospf6_area *oa;
1228
1229 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1230 if (CHECK_FLAG(ospf6->flag, OSPF6_STUB_ROUTER)) {
1231 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
1232 OSPF6_OPT_SET(oa->options, OSPF6_OPT_V6);
1233 OSPF6_OPT_SET(oa->options, OSPF6_OPT_R);
1234 OSPF6_ROUTER_LSA_SCHEDULE(oa);
1235 }
1236 UNSET_FLAG(ospf6->flag, OSPF6_STUB_ROUTER);
1237 }
1238
1239 return CMD_SUCCESS;
1240 }
1241
1242 /* Restart OSPF SPF algorithm*/
1243 void ospf6_restart_spf(struct ospf6 *ospf6)
1244 {
1245 ospf6_route_remove_all(ospf6->route_table);
1246 ospf6_route_remove_all(ospf6->brouter_table);
1247
1248 /* Trigger SPF */
1249 ospf6_spf_schedule(ospf6, OSPF6_SPF_FLAGS_CONFIG_CHANGE);
1250 }
1251
1252 /* Set the max paths */
1253 static void ospf6_maxpath_set(struct ospf6 *ospf6, uint16_t paths)
1254 {
1255 if (ospf6->max_multipath == paths)
1256 return;
1257
1258 ospf6->max_multipath = paths;
1259
1260 /* Send deletion to zebra to delete all
1261 * ospf specific routes and reinitiate
1262 * SPF to reflect the new max multipath.
1263 */
1264 ospf6_restart_spf(ospf6);
1265 }
1266
1267 /* Ospf Maximum-paths config support */
1268 DEFUN(ospf6_max_multipath,
1269 ospf6_max_multipath_cmd,
1270 "maximum-paths " CMD_RANGE_STR(1, MULTIPATH_NUM),
1271 "Max no of multiple paths for ECMP support\n"
1272 "Number of paths\n")
1273 {
1274 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1275 int idx_number = 1;
1276 int maximum_paths = strtol(argv[idx_number]->arg, NULL, 10);
1277
1278 ospf6_maxpath_set(ospf6, maximum_paths);
1279
1280 return CMD_SUCCESS;
1281 }
1282
1283 DEFUN(no_ospf6_max_multipath,
1284 no_ospf6_max_multipath_cmd,
1285 "no maximum-paths [" CMD_RANGE_STR(1, MULTIPATH_NUM)"]",
1286 NO_STR
1287 "Max no of multiple paths for ECMP support\n"
1288 "Number of paths\n")
1289 {
1290 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1291
1292 ospf6_maxpath_set(ospf6, MULTIPATH_NUM);
1293
1294 return CMD_SUCCESS;
1295 }
1296
1297 static void ospf6_show(struct vty *vty, struct ospf6 *o, json_object *json,
1298 bool use_json)
1299 {
1300 struct listnode *n;
1301 struct ospf6_area *oa;
1302 char router_id[16], duration[32];
1303 struct timeval now, running, result;
1304 char buf[32], rbuf[32];
1305 json_object *json_areas = NULL;
1306 const char *adjacency;
1307
1308 if (use_json) {
1309 json_areas = json_object_new_object();
1310
1311 /* process id, router id */
1312 inet_ntop(AF_INET, &o->router_id, router_id, sizeof(router_id));
1313 json_object_string_add(json, "routerId", router_id);
1314
1315 /* running time */
1316 monotime(&now);
1317 timersub(&now, &o->starttime, &running);
1318 timerstring(&running, duration, sizeof(duration));
1319 json_object_string_add(json, "running", duration);
1320
1321 /* Redistribute configuration */
1322 /* XXX */
1323 json_object_int_add(json, "lsaMinimumArrivalMsecs",
1324 o->lsa_minarrival);
1325
1326 /* Show SPF parameters */
1327 json_object_int_add(json, "spfScheduleDelayMsecs",
1328 o->spf_delay);
1329 json_object_int_add(json, "holdTimeMinMsecs", o->spf_holdtime);
1330 json_object_int_add(json, "holdTimeMaxMsecs",
1331 o->spf_max_holdtime);
1332 json_object_int_add(json, "holdTimeMultiplier",
1333 o->spf_hold_multiplier);
1334
1335 json_object_int_add(json, "maximumPaths", o->max_multipath);
1336 json_object_int_add(json, "preference",
1337 o->distance_all
1338 ? o->distance_all
1339 : ZEBRA_OSPF6_DISTANCE_DEFAULT);
1340
1341 if (o->ts_spf.tv_sec || o->ts_spf.tv_usec) {
1342 timersub(&now, &o->ts_spf, &result);
1343 timerstring(&result, buf, sizeof(buf));
1344 ospf6_spf_reason_string(o->last_spf_reason, rbuf,
1345 sizeof(rbuf));
1346 json_object_boolean_true_add(json, "spfHasRun");
1347 json_object_string_add(json, "spfLastExecutedMsecs",
1348 buf);
1349 json_object_string_add(json, "spfLastExecutedReason",
1350 rbuf);
1351
1352 json_object_int_add(
1353 json, "spfLastDurationSecs",
1354 (long long)o->ts_spf_duration.tv_sec);
1355
1356 json_object_int_add(
1357 json, "spfLastDurationMsecs",
1358 (long long)o->ts_spf_duration.tv_usec);
1359 } else
1360 json_object_boolean_false_add(json, "spfHasRun");
1361
1362 if (thread_is_scheduled(o->t_spf_calc)) {
1363 long time_store;
1364
1365 json_object_boolean_true_add(json, "spfTimerActive");
1366 time_store =
1367 monotime_until(&o->t_spf_calc->u.sands, NULL)
1368 / 1000LL;
1369 json_object_int_add(json, "spfTimerDueInMsecs",
1370 time_store);
1371 } else
1372 json_object_boolean_false_add(json, "spfTimerActive");
1373
1374 json_object_boolean_add(json, "routerIsStubRouter",
1375 CHECK_FLAG(o->flag, OSPF6_STUB_ROUTER));
1376
1377 /* LSAs */
1378 json_object_int_add(json, "numberOfAsScopedLsa",
1379 o->lsdb->count);
1380 /* Areas */
1381 json_object_int_add(json, "numberOfAreaInRouter",
1382 listcount(o->area_list));
1383
1384 json_object_int_add(json, "AuthTrailerHigherSeqNo",
1385 o->seqnum_h);
1386 json_object_int_add(json, "AuthTrailerLowerSeqNo", o->seqnum_l);
1387
1388 if (CHECK_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES)) {
1389 if (CHECK_FLAG(o->config_flags,
1390 OSPF6_LOG_ADJACENCY_DETAIL))
1391 adjacency = "LoggedAll";
1392 else
1393 adjacency = "Logged";
1394 } else
1395 adjacency = "NotLogged";
1396 json_object_string_add(json, "adjacencyChanges", adjacency);
1397
1398 for (ALL_LIST_ELEMENTS_RO(o->area_list, n, oa))
1399 ospf6_area_show(vty, oa, json_areas, use_json);
1400
1401 json_object_object_add(json, "areas", json_areas);
1402
1403 vty_out(vty, "%s\n",
1404 json_object_to_json_string_ext(
1405 json, JSON_C_TO_STRING_PRETTY));
1406
1407 } else {
1408 /* process id, router id */
1409 inet_ntop(AF_INET, &o->router_id, router_id, sizeof(router_id));
1410 vty_out(vty, " OSPFv3 Routing Process (0) with Router-ID %s\n",
1411 router_id);
1412
1413 /* running time */
1414 monotime(&now);
1415 timersub(&now, &o->starttime, &running);
1416 timerstring(&running, duration, sizeof(duration));
1417 vty_out(vty, " Running %s\n", duration);
1418
1419 /* Redistribute configuration */
1420 /* XXX */
1421 vty_out(vty, " LSA minimum arrival %d msecs\n",
1422 o->lsa_minarrival);
1423
1424 vty_out(vty, " Maximum-paths %u\n", o->max_multipath);
1425 vty_out(vty, " Administrative distance %u\n",
1426 o->distance_all ? o->distance_all
1427 : ZEBRA_OSPF6_DISTANCE_DEFAULT);
1428
1429 /* Show SPF parameters */
1430 vty_out(vty,
1431 " Initial SPF scheduling delay %d millisec(s)\n"
1432 " Minimum hold time between consecutive SPFs %d millsecond(s)\n"
1433 " Maximum hold time between consecutive SPFs %d millsecond(s)\n"
1434 " Hold time multiplier is currently %d\n",
1435 o->spf_delay, o->spf_holdtime, o->spf_max_holdtime,
1436 o->spf_hold_multiplier);
1437
1438
1439 vty_out(vty, " SPF algorithm ");
1440 if (o->ts_spf.tv_sec || o->ts_spf.tv_usec) {
1441 timersub(&now, &o->ts_spf, &result);
1442 timerstring(&result, buf, sizeof(buf));
1443 ospf6_spf_reason_string(o->last_spf_reason, rbuf,
1444 sizeof(rbuf));
1445 vty_out(vty, "last executed %s ago, reason %s\n", buf,
1446 rbuf);
1447 vty_out(vty, " Last SPF duration %lld sec %lld usec\n",
1448 (long long)o->ts_spf_duration.tv_sec,
1449 (long long)o->ts_spf_duration.tv_usec);
1450 } else
1451 vty_out(vty, "has not been run\n");
1452
1453 threadtimer_string(now, o->t_spf_calc, buf, sizeof(buf));
1454 vty_out(vty, " SPF timer %s%s\n",
1455 (thread_is_scheduled(o->t_spf_calc) ? "due in "
1456 : "is "),
1457 buf);
1458
1459 if (CHECK_FLAG(o->flag, OSPF6_STUB_ROUTER))
1460 vty_out(vty, " Router Is Stub Router\n");
1461
1462 /* LSAs */
1463 vty_out(vty, " Number of AS scoped LSAs is %u\n",
1464 o->lsdb->count);
1465
1466 /* Areas */
1467 vty_out(vty, " Number of areas in this router is %u\n",
1468 listcount(o->area_list));
1469
1470 vty_out(vty, " Authentication Sequence number info\n");
1471 vty_out(vty, " Higher sequence no %u, Lower sequence no %u\n",
1472 o->seqnum_h, o->seqnum_l);
1473
1474 if (CHECK_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES)) {
1475 if (CHECK_FLAG(o->config_flags,
1476 OSPF6_LOG_ADJACENCY_DETAIL))
1477 vty_out(vty,
1478 " All adjacency changes are logged\n");
1479 else
1480 vty_out(vty, " Adjacency changes are logged\n");
1481 }
1482
1483
1484 vty_out(vty, "\n");
1485
1486 for (ALL_LIST_ELEMENTS_RO(o->area_list, n, oa))
1487 ospf6_area_show(vty, oa, json_areas, use_json);
1488 }
1489 }
1490
1491 DEFUN(show_ipv6_ospf6_vrfs, show_ipv6_ospf6_vrfs_cmd,
1492 "show ipv6 ospf6 vrfs [json]",
1493 SHOW_STR IP6_STR OSPF6_STR "Show OSPF6 VRFs \n" JSON_STR)
1494 {
1495 bool uj = use_json(argc, argv);
1496 json_object *json = NULL;
1497 json_object *json_vrfs = NULL;
1498 struct ospf6 *ospf6 = NULL;
1499 struct listnode *node = NULL;
1500 int count = 0;
1501 char buf[PREFIX_STRLEN];
1502 static const char header[] =
1503 "Name Id RouterId ";
1504
1505 if (uj) {
1506 json = json_object_new_object();
1507 json_vrfs = json_object_new_object();
1508 }
1509
1510 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1511 json_object *json_vrf = NULL;
1512 const char *name = NULL;
1513 int64_t vrf_id_ui = 0;
1514 struct in_addr router_id;
1515
1516 router_id.s_addr = ospf6->router_id;
1517 count++;
1518
1519 if (!uj && count == 1)
1520 vty_out(vty, "%s\n", header);
1521 if (uj)
1522 json_vrf = json_object_new_object();
1523
1524 if (ospf6->vrf_id == VRF_DEFAULT)
1525 name = VRF_DEFAULT_NAME;
1526 else
1527 name = ospf6->name;
1528
1529 vrf_id_ui = (ospf6->vrf_id == VRF_UNKNOWN)
1530 ? -1
1531 : (int64_t)ospf6->vrf_id;
1532
1533 if (uj) {
1534 json_object_int_add(json_vrf, "vrfId", vrf_id_ui);
1535 json_object_string_addf(json_vrf, "routerId", "%pI4",
1536 &router_id);
1537 json_object_object_add(json_vrfs, name, json_vrf);
1538
1539 } else {
1540 vty_out(vty, "%-25s %-5d %-16s \n", name,
1541 ospf6->vrf_id,
1542 inet_ntop(AF_INET, &router_id, buf,
1543 sizeof(buf)));
1544 }
1545 }
1546
1547 if (uj) {
1548 json_object_object_add(json, "vrfs", json_vrfs);
1549 json_object_int_add(json, "totalVrfs", count);
1550
1551 vty_json(vty, json);
1552 } else {
1553 if (count)
1554 vty_out(vty, "\nTotal number of OSPF VRFs: %d\n",
1555 count);
1556 }
1557
1558 return CMD_SUCCESS;
1559 }
1560
1561 /* show top level structures */
1562 DEFUN(show_ipv6_ospf6, show_ipv6_ospf6_cmd,
1563 "show ipv6 ospf6 [vrf <NAME|all>] [json]",
1564 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR "All VRFs\n" JSON_STR)
1565 {
1566 struct ospf6 *ospf6;
1567 struct listnode *node;
1568 const char *vrf_name = NULL;
1569 bool all_vrf = false;
1570 int idx_vrf = 0;
1571
1572 bool uj = use_json(argc, argv);
1573 json_object *json = NULL;
1574
1575 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1576
1577 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1578 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1579 if (uj)
1580 json = json_object_new_object();
1581 ospf6_show(vty, ospf6, json, uj);
1582
1583 if (!all_vrf)
1584 break;
1585 }
1586 }
1587
1588 if (uj)
1589 json_object_free(json);
1590
1591 OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
1592
1593 return CMD_SUCCESS;
1594 }
1595
1596 DEFUN(show_ipv6_ospf6_route, show_ipv6_ospf6_route_cmd,
1597 "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]",
1598 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1599 "All VRFs\n" ROUTE_STR
1600 "Display Intra-Area routes\n"
1601 "Display Inter-Area routes\n"
1602 "Display Type-1 External routes\n"
1603 "Display Type-2 External routes\n"
1604 "Specify IPv6 address\n"
1605 "Specify IPv6 prefix\n"
1606 "Detailed information\n"
1607 "Summary of route table\n" JSON_STR)
1608 {
1609 struct ospf6 *ospf6;
1610 struct listnode *node;
1611 const char *vrf_name = NULL;
1612 bool all_vrf = false;
1613 int idx_vrf = 0;
1614 int idx_arg_start = 4;
1615 bool uj = use_json(argc, argv);
1616
1617 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1618 if (idx_vrf > 0)
1619 idx_arg_start += 2;
1620
1621 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1622 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1623 ospf6_route_table_show(vty, idx_arg_start, argc, argv,
1624 ospf6->route_table, uj);
1625
1626 if (!all_vrf)
1627 break;
1628 }
1629 }
1630
1631 OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
1632
1633 return CMD_SUCCESS;
1634 }
1635
1636 DEFUN(show_ipv6_ospf6_route_match, show_ipv6_ospf6_route_match_cmd,
1637 "show ipv6 ospf6 [vrf <NAME|all>] route X:X::X:X/M <match|longer> [json]",
1638 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1639 "All VRFs\n" ROUTE_STR
1640 "Specify IPv6 prefix\n"
1641 "Display routes which match the specified route\n"
1642 "Display routes longer than the specified route\n" JSON_STR)
1643 {
1644 struct ospf6 *ospf6;
1645 struct listnode *node;
1646 const char *vrf_name = NULL;
1647 bool all_vrf = false;
1648 int idx_vrf = 0;
1649 int idx_start_arg = 4;
1650 bool uj = use_json(argc, argv);
1651
1652 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1653 if (idx_vrf > 0)
1654 idx_start_arg += 2;
1655
1656 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1657 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1658 ospf6_route_table_show(vty, idx_start_arg, argc, argv,
1659 ospf6->route_table, uj);
1660
1661 if (!all_vrf)
1662 break;
1663 }
1664 }
1665
1666 OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
1667
1668 return CMD_SUCCESS;
1669 }
1670
1671 DEFUN(show_ipv6_ospf6_route_match_detail,
1672 show_ipv6_ospf6_route_match_detail_cmd,
1673 "show ipv6 ospf6 [vrf <NAME|all>] route X:X::X:X/M match detail [json]",
1674 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1675 "All VRFs\n" ROUTE_STR
1676 "Specify IPv6 prefix\n"
1677 "Display routes which match the specified route\n"
1678 "Detailed information\n" JSON_STR)
1679 {
1680 struct ospf6 *ospf6;
1681 struct listnode *node;
1682 const char *vrf_name = NULL;
1683 bool all_vrf = false;
1684 int idx_vrf = 0;
1685 int idx_start_arg = 4;
1686 bool uj = use_json(argc, argv);
1687
1688 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1689 if (idx_vrf > 0)
1690 idx_start_arg += 2;
1691
1692 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1693 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1694 ospf6_route_table_show(vty, idx_start_arg, argc, argv,
1695 ospf6->route_table, uj);
1696
1697 if (!all_vrf)
1698 break;
1699 }
1700 }
1701
1702 OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
1703
1704 return CMD_SUCCESS;
1705 }
1706
1707 DEFUN(show_ipv6_ospf6_route_type_detail, show_ipv6_ospf6_route_type_detail_cmd,
1708 "show ipv6 ospf6 [vrf <NAME|all>] route <intra-area|inter-area|external-1|external-2> detail [json]",
1709 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1710 "All VRFs\n" ROUTE_STR
1711 "Display Intra-Area routes\n"
1712 "Display Inter-Area routes\n"
1713 "Display Type-1 External routes\n"
1714 "Display Type-2 External routes\n"
1715 "Detailed information\n" JSON_STR)
1716 {
1717 struct ospf6 *ospf6;
1718 struct listnode *node;
1719 const char *vrf_name = NULL;
1720 bool all_vrf = false;
1721 int idx_vrf = 0;
1722 int idx_start_arg = 4;
1723 bool uj = use_json(argc, argv);
1724
1725 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1726 if (idx_vrf > 0)
1727 idx_start_arg += 2;
1728
1729 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1730 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1731 ospf6_route_table_show(vty, idx_start_arg, argc, argv,
1732 ospf6->route_table, uj);
1733
1734 if (!all_vrf)
1735 break;
1736 }
1737 }
1738
1739 OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
1740
1741 return CMD_SUCCESS;
1742 }
1743
1744 bool ospf6_is_valid_summary_addr(struct vty *vty, struct prefix *p)
1745 {
1746 /* Default prefix validation*/
1747 if (is_default_prefix(p)) {
1748 vty_out(vty,
1749 "Default address should not be configured as summary address.\n");
1750 return false;
1751 }
1752
1753 /* Host route should not be configured as summary address */
1754 if (p->prefixlen == IPV6_MAX_BITLEN) {
1755 vty_out(vty, "Host route should not be configured as summary address.\n");
1756 return false;
1757 }
1758
1759 return true;
1760 }
1761
1762 /* External Route Aggregation */
1763 DEFPY (ospf6_external_route_aggregation,
1764 ospf6_external_route_aggregation_cmd,
1765 "summary-address X:X::X:X/M$prefix [tag (1-4294967295)] [{metric (0-16777215) | metric-type (1-2)$mtype}]",
1766 "External summary address\n"
1767 "Specify IPv6 prefix\n"
1768 "Router tag \n"
1769 "Router tag value\n"
1770 "Metric \n"
1771 "Advertised metric for this route\n"
1772 "OSPFv3 exterior metric type for summarised routes\n"
1773 "Set OSPFv3 External Type 1/2 metrics\n")
1774 {
1775 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1776
1777 struct prefix p;
1778 int ret = CMD_SUCCESS;
1779
1780 p.family = AF_INET6;
1781 ret = str2prefix(prefix_str, &p);
1782 if (ret == 0) {
1783 vty_out(vty, "Malformed prefix\n");
1784 return CMD_WARNING_CONFIG_FAILED;
1785 }
1786
1787 /* Apply mask for given prefix. */
1788 apply_mask(&p);
1789
1790 if (!ospf6_is_valid_summary_addr(vty, &p))
1791 return CMD_WARNING_CONFIG_FAILED;
1792
1793 if (!tag_str)
1794 tag = 0;
1795
1796 if (!metric_str)
1797 metric = -1;
1798
1799 if (!mtype_str)
1800 mtype = DEFAULT_METRIC_TYPE;
1801
1802 ret = ospf6_external_aggr_config_set(ospf6, &p, tag, metric, mtype);
1803 if (ret == OSPF6_FAILURE) {
1804 vty_out(vty, "Invalid configuration!!\n");
1805 return CMD_WARNING_CONFIG_FAILED;
1806 }
1807
1808 return CMD_SUCCESS;
1809 }
1810
1811 DEFPY(no_ospf6_external_route_aggregation,
1812 no_ospf6_external_route_aggregation_cmd,
1813 "no summary-address X:X::X:X/M$prefix [tag (1-4294967295)] [{metric (0-16777215) | metric-type (1-2)}]",
1814 NO_STR
1815 "External summary address\n"
1816 "Specify IPv6 prefix\n"
1817 "Router tag\n"
1818 "Router tag value\n"
1819 "Metric \n"
1820 "Advertised metric for this route\n"
1821 "OSPFv3 exterior metric type for summarised routes\n"
1822 "Set OSPFv3 External Type 1/2 metrics\n")
1823 {
1824 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1825
1826 struct prefix p;
1827 int ret = CMD_SUCCESS;
1828
1829 ret = str2prefix(prefix_str, &p);
1830 if (ret == 0) {
1831 vty_out(vty, "Malformed prefix\n");
1832 return CMD_WARNING_CONFIG_FAILED;
1833 }
1834
1835 /* Apply mask for given prefix. */
1836 apply_mask(&p);
1837
1838 if (!ospf6_is_valid_summary_addr(vty, &p))
1839 return CMD_WARNING_CONFIG_FAILED;
1840
1841 ret = ospf6_external_aggr_config_unset(ospf6, &p);
1842 if (ret == OSPF6_INVALID)
1843 vty_out(vty, "Invalid configuration!!\n");
1844
1845 return CMD_SUCCESS;
1846 }
1847
1848 DEFPY (ospf6_external_route_aggregation_no_advertise,
1849 ospf6_external_route_aggregation_no_advertise_cmd,
1850 "summary-address X:X::X:X/M$prefix no-advertise",
1851 "External summary address\n"
1852 "Specify IPv6 prefix\n"
1853 "Don't advertise summary route \n")
1854 {
1855 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1856
1857 struct prefix p;
1858 int ret = CMD_SUCCESS;
1859
1860 ret = str2prefix(prefix_str, &p);
1861 if (ret == 0) {
1862 vty_out(vty, "Malformed prefix\n");
1863 return CMD_WARNING_CONFIG_FAILED;
1864 }
1865
1866 /* Apply mask for given prefix. */
1867 apply_mask(&p);
1868
1869 if (!ospf6_is_valid_summary_addr(vty, &p))
1870 return CMD_WARNING_CONFIG_FAILED;
1871
1872 ret = ospf6_asbr_external_rt_no_advertise(ospf6, &p);
1873 if (ret == OSPF6_INVALID)
1874 vty_out(vty, "!!Invalid configuration\n");
1875
1876 return CMD_SUCCESS;
1877 }
1878
1879 DEFPY (no_ospf6_external_route_aggregation_no_advertise,
1880 no_ospf6_external_route_aggregation_no_advertise_cmd,
1881 "no summary-address X:X::X:X/M$prefix no-advertise",
1882 NO_STR
1883 "External summary address\n"
1884 "Specify IPv6 prefix\n"
1885 "Adverise summary route to the AS \n")
1886 {
1887 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1888
1889 struct prefix p;
1890 int ret = CMD_SUCCESS;
1891
1892 ret = str2prefix(prefix_str, &p);
1893 if (ret == 0) {
1894 vty_out(vty, "Malformed prefix\n");
1895 return CMD_WARNING_CONFIG_FAILED;
1896 }
1897
1898 /* Apply mask for given prefix. */
1899 apply_mask(&p);
1900
1901 if (!ospf6_is_valid_summary_addr(vty, &p))
1902 return CMD_WARNING_CONFIG_FAILED;
1903
1904 ret = ospf6_asbr_external_rt_advertise(ospf6, &p);
1905 if (ret == OSPF6_INVALID)
1906 vty_out(vty, "!!Invalid configuration\n");
1907
1908 return CMD_SUCCESS;
1909 }
1910
1911 DEFPY (ospf6_route_aggregation_timer,
1912 ospf6_route_aggregation_timer_cmd,
1913 "aggregation timer (5-1800)",
1914 "External route aggregation\n"
1915 "Delay timer (in seconds)\n"
1916 "Timer interval(in seconds)\n")
1917 {
1918 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1919
1920 ospf6_external_aggr_delay_timer_set(ospf6, timer);
1921
1922 return CMD_SUCCESS;
1923 }
1924
1925 DEFPY (no_ospf6_route_aggregation_timer,
1926 no_ospf6_route_aggregation_timer_cmd,
1927 "no aggregation timer [5-1800]",
1928 NO_STR
1929 "External route aggregation\n"
1930 "Delay timer\n"
1931 "Timer interval(in seconds)\n")
1932 {
1933 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1934
1935 ospf6_external_aggr_delay_timer_set(ospf6,
1936 OSPF6_EXTL_AGGR_DEFAULT_DELAY);
1937 return CMD_SUCCESS;
1938 }
1939
1940 static int
1941 ospf6_print_vty_external_routes_walkcb(struct hash_bucket *bucket, void *arg)
1942 {
1943 struct ospf6_route *rt = bucket->data;
1944 struct vty *vty = (struct vty *)arg;
1945 static unsigned int count;
1946
1947 vty_out(vty, "%pFX ", &rt->prefix);
1948
1949 count++;
1950
1951 if (count%5 == 0)
1952 vty_out(vty, "\n");
1953
1954 if (OSPF6_EXTERNAL_RT_COUNT(rt->aggr_route) == count)
1955 count = 0;
1956
1957 return HASHWALK_CONTINUE;
1958 }
1959
1960 static int
1961 ospf6_print_json_external_routes_walkcb(struct hash_bucket *bucket, void *arg)
1962 {
1963 struct ospf6_route *rt = bucket->data;
1964 struct json_object *json = (struct json_object *)arg;
1965 char buf[PREFIX2STR_BUFFER];
1966 char exnalbuf[20];
1967 static unsigned int count;
1968
1969 prefix2str(&rt->prefix, buf, sizeof(buf));
1970
1971 snprintf(exnalbuf, sizeof(exnalbuf), "Exnl Addr-%d", count);
1972
1973 json_object_string_add(json, exnalbuf, buf);
1974
1975 count++;
1976
1977 if (OSPF6_EXTERNAL_RT_COUNT(rt->aggr_route) == count)
1978 count = 0;
1979
1980 return HASHWALK_CONTINUE;
1981 }
1982
1983 static void
1984 ospf6_show_vrf_name(struct vty *vty, struct ospf6 *ospf6,
1985 json_object *json)
1986 {
1987 if (json) {
1988 if (ospf6->vrf_id == VRF_DEFAULT)
1989 json_object_string_add(json, "vrfName",
1990 "default");
1991 else
1992 json_object_string_add(json, "vrfName",
1993 ospf6->name);
1994 json_object_int_add(json, "vrfId", ospf6->vrf_id);
1995 } else {
1996 if (ospf6->vrf_id == VRF_DEFAULT)
1997 vty_out(vty, "VRF Name: %s\n", "default");
1998 else if (ospf6->name)
1999 vty_out(vty, "VRF Name: %s\n", ospf6->name);
2000 }
2001 }
2002
2003 static int
2004 ospf6_show_summary_address(struct vty *vty, struct ospf6 *ospf6,
2005 json_object *json,
2006 bool uj, const char *detail)
2007 {
2008 struct route_node *rn;
2009 static const char header[] = "Summary-address Metric-type Metric Tag External_Rt_count\n";
2010 json_object *json_vrf = NULL;
2011
2012 if (!uj) {
2013 ospf6_show_vrf_name(vty, ospf6, json_vrf);
2014 vty_out(vty, "aggregation delay interval :%u(in seconds)\n\n",
2015 ospf6->aggr_delay_interval);
2016 vty_out(vty, "%s\n", header);
2017 } else {
2018 json_vrf = json_object_new_object();
2019
2020 ospf6_show_vrf_name(vty, ospf6, json_vrf);
2021
2022 json_object_int_add(json_vrf, "aggregationDelayInterval",
2023 ospf6->aggr_delay_interval);
2024 }
2025
2026
2027 for (rn = route_top(ospf6->rt_aggr_tbl); rn; rn = route_next(rn)) {
2028 if (!rn->info)
2029 continue;
2030
2031 struct ospf6_external_aggr_rt *aggr = rn->info;
2032 json_object *json_aggr = NULL;
2033 char buf[PREFIX2STR_BUFFER];
2034
2035 prefix2str(&aggr->p, buf, sizeof(buf));
2036
2037 if (uj) {
2038
2039 json_aggr = json_object_new_object();
2040
2041 json_object_object_add(json_vrf,
2042 buf,
2043 json_aggr);
2044
2045 json_object_string_add(json_aggr, "summaryAddress",
2046 buf);
2047
2048 json_object_string_add(
2049 json_aggr, "metricType",
2050 (aggr->mtype == DEFAULT_METRIC_TYPE) ? "E2"
2051 : "E1");
2052
2053 json_object_int_add(json_aggr, "Metric",
2054 (aggr->metric != -1)
2055 ? aggr->metric
2056 : DEFAULT_DEFAULT_METRIC);
2057
2058 json_object_int_add(json_aggr, "Tag",
2059 aggr->tag);
2060
2061 json_object_int_add(json_aggr, "externalRouteCount",
2062 OSPF6_EXTERNAL_RT_COUNT(aggr));
2063
2064 if (OSPF6_EXTERNAL_RT_COUNT(aggr) && detail) {
2065 json_object_int_add(json_aggr, "ID",
2066 aggr->id);
2067 json_object_int_add(json_aggr, "Flags",
2068 aggr->aggrflags);
2069 hash_walk(aggr->match_extnl_hash,
2070 ospf6_print_json_external_routes_walkcb,
2071 json_aggr);
2072 }
2073
2074 } else {
2075 vty_out(vty, "%-22s", buf);
2076
2077 (aggr->mtype == DEFAULT_METRIC_TYPE)
2078 ? vty_out(vty, "%-16s", "E2")
2079 : vty_out(vty, "%-16s", "E1");
2080 vty_out(vty, "%-11d", (aggr->metric != -1)
2081 ? aggr->metric
2082 : DEFAULT_DEFAULT_METRIC);
2083
2084 vty_out(vty, "%-12u", aggr->tag);
2085
2086 vty_out(vty, "%-5ld\n",
2087 OSPF6_EXTERNAL_RT_COUNT(aggr));
2088
2089 if (OSPF6_EXTERNAL_RT_COUNT(aggr) && detail) {
2090 vty_out(vty,
2091 "Matched External routes:\n");
2092 hash_walk(aggr->match_extnl_hash,
2093 ospf6_print_vty_external_routes_walkcb,
2094 vty);
2095 vty_out(vty, "\n");
2096 }
2097
2098 vty_out(vty, "\n");
2099 }
2100 }
2101
2102 if (uj)
2103 json_object_object_add(json, ospf6->name,
2104 json_vrf);
2105
2106 return CMD_SUCCESS;
2107 }
2108
2109 DEFPY (show_ipv6_ospf6_external_aggregator,
2110 show_ipv6_ospf6_external_aggregator_cmd,
2111 "show ipv6 ospf6 [vrf <NAME|all>] summary-address [detail$detail] [json]",
2112 SHOW_STR
2113 IP6_STR
2114 OSPF6_STR
2115 VRF_CMD_HELP_STR
2116 "All VRFs\n"
2117 "Show external summary addresses\n"
2118 "detailed information\n"
2119 JSON_STR)
2120 {
2121 bool uj = use_json(argc, argv);
2122 struct ospf6 *ospf6 = NULL;
2123 json_object *json = NULL;
2124 const char *vrf_name = NULL;
2125 struct listnode *node;
2126 bool all_vrf = false;
2127 int idx_vrf = 0;
2128
2129 if (uj)
2130 json = json_object_new_object();
2131
2132 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
2133
2134 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
2135 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
2136
2137 ospf6_show_summary_address(vty, ospf6, json, uj,
2138 detail);
2139
2140 if (!all_vrf)
2141 break;
2142 }
2143 }
2144
2145 if (uj) {
2146 vty_json(vty, json);
2147 }
2148
2149 OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
2150
2151 return CMD_SUCCESS;
2152 }
2153
2154 static void ospf6_stub_router_config_write(struct vty *vty, struct ospf6 *ospf6)
2155 {
2156 if (CHECK_FLAG(ospf6->flag, OSPF6_STUB_ROUTER))
2157 vty_out(vty, " stub-router administrative\n");
2158 return;
2159 }
2160
2161 static int ospf6_distance_config_write(struct vty *vty, struct ospf6 *ospf6)
2162 {
2163 struct route_node *rn;
2164 struct ospf6_distance *odistance;
2165
2166 if (ospf6->distance_all)
2167 vty_out(vty, " distance %u\n", ospf6->distance_all);
2168
2169 if (ospf6->distance_intra || ospf6->distance_inter
2170 || ospf6->distance_external) {
2171 vty_out(vty, " distance ospf6");
2172
2173 if (ospf6->distance_intra)
2174 vty_out(vty, " intra-area %u", ospf6->distance_intra);
2175 if (ospf6->distance_inter)
2176 vty_out(vty, " inter-area %u", ospf6->distance_inter);
2177 if (ospf6->distance_external)
2178 vty_out(vty, " external %u", ospf6->distance_external);
2179
2180 vty_out(vty, "\n");
2181 }
2182
2183 for (rn = route_top(ospf6->distance_table); rn; rn = route_next(rn))
2184 if ((odistance = rn->info) != NULL)
2185 vty_out(vty, " distance %u %pFX %s\n",
2186 odistance->distance, &rn->p,
2187 odistance->access_list ? odistance->access_list
2188 : "");
2189 return 0;
2190 }
2191
2192 static int ospf6_asbr_summary_config_write(struct vty *vty, struct ospf6 *ospf6)
2193 {
2194 struct route_node *rn;
2195 struct ospf6_external_aggr_rt *aggr;
2196 char buf[PREFIX2STR_BUFFER];
2197
2198 if (ospf6->aggr_delay_interval != OSPF6_EXTL_AGGR_DEFAULT_DELAY)
2199 vty_out(vty, " aggregation timer %u\n",
2200 ospf6->aggr_delay_interval);
2201
2202 /* print 'summary-address A:B::C:D/M' */
2203 for (rn = route_top(ospf6->rt_aggr_tbl); rn; rn = route_next(rn)) {
2204 if (!rn->info)
2205 continue;
2206
2207 aggr = rn->info;
2208
2209 prefix2str(&aggr->p, buf, sizeof(buf));
2210 vty_out(vty, " summary-address %s", buf);
2211 if (aggr->tag)
2212 vty_out(vty, " tag %u", aggr->tag);
2213
2214 if (aggr->metric != -1)
2215 vty_out(vty, " metric %d", aggr->metric);
2216
2217 if (aggr->mtype != DEFAULT_METRIC_TYPE)
2218 vty_out(vty, " metric-type %d", aggr->mtype);
2219
2220 if (CHECK_FLAG(aggr->aggrflags,
2221 OSPF6_EXTERNAL_AGGRT_NO_ADVERTISE))
2222 vty_out(vty, " no-advertise");
2223
2224 vty_out(vty, "\n");
2225 }
2226
2227 return 0;
2228 }
2229
2230 /* OSPF configuration write function. */
2231 static int config_write_ospf6(struct vty *vty)
2232 {
2233 struct ospf6 *ospf6;
2234 struct listnode *node, *nnode;
2235
2236 /* OSPFv3 configuration. */
2237 if (om6 == NULL)
2238 return CMD_SUCCESS;
2239
2240 for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6)) {
2241 if (ospf6->name && strcmp(ospf6->name, VRF_DEFAULT_NAME))
2242 vty_out(vty, "router ospf6 vrf %s\n", ospf6->name);
2243 else
2244 vty_out(vty, "router ospf6\n");
2245
2246 if (ospf6->router_id_static != 0)
2247 vty_out(vty, " ospf6 router-id %pI4\n",
2248 &ospf6->router_id_static);
2249
2250 if (CHECK_FLAG(ospf6->config_flags,
2251 OSPF6_SEND_EXTRA_DATA_TO_ZEBRA))
2252 vty_out(vty, " ospf6 send-extra-data zebra\n");
2253
2254 /* log-adjacency-changes flag print. */
2255 if (CHECK_FLAG(ospf6->config_flags,
2256 OSPF6_LOG_ADJACENCY_CHANGES)) {
2257 if (CHECK_FLAG(ospf6->config_flags,
2258 OSPF6_LOG_ADJACENCY_DETAIL))
2259 vty_out(vty, " log-adjacency-changes detail\n");
2260 else if (!SAVE_OSPF6_LOG_ADJACENCY_CHANGES)
2261 vty_out(vty, " log-adjacency-changes\n");
2262 } else if (SAVE_OSPF6_LOG_ADJACENCY_CHANGES) {
2263 vty_out(vty, " no log-adjacency-changes\n");
2264 }
2265
2266 if (ospf6->ref_bandwidth != OSPF6_REFERENCE_BANDWIDTH)
2267 vty_out(vty, " auto-cost reference-bandwidth %d\n",
2268 ospf6->ref_bandwidth);
2269
2270 if (ospf6->write_oi_count
2271 != OSPF6_WRITE_INTERFACE_COUNT_DEFAULT)
2272 vty_out(vty, " write-multiplier %d\n",
2273 ospf6->write_oi_count);
2274
2275 /* LSA timers print. */
2276 if (ospf6->lsa_minarrival != OSPF_MIN_LS_ARRIVAL)
2277 vty_out(vty, " timers lsa min-arrival %d\n",
2278 ospf6->lsa_minarrival);
2279
2280 /* ECMP max path config */
2281 if (ospf6->max_multipath != MULTIPATH_NUM)
2282 vty_out(vty, " maximum-paths %d\n",
2283 ospf6->max_multipath);
2284
2285 ospf6_stub_router_config_write(vty, ospf6);
2286 ospf6_redistribute_config_write(vty, ospf6);
2287 ospf6_area_config_write(vty, ospf6);
2288 ospf6_spf_config_write(vty, ospf6);
2289 ospf6_distance_config_write(vty, ospf6);
2290 ospf6_distribute_config_write(vty, ospf6);
2291 ospf6_asbr_summary_config_write(vty, ospf6);
2292 config_write_ospf6_gr(vty, ospf6);
2293 config_write_ospf6_gr_helper(vty, ospf6);
2294
2295 vty_out(vty, "exit\n");
2296 vty_out(vty, "!\n");
2297 }
2298 return 0;
2299 }
2300
2301 static int config_write_ospf6(struct vty *vty);
2302 /* OSPF6 node structure. */
2303 static struct cmd_node ospf6_node = {
2304 .name = "ospf6",
2305 .node = OSPF6_NODE,
2306 .parent_node = CONFIG_NODE,
2307 .prompt = "%s(config-ospf6)# ",
2308 .config_write = config_write_ospf6,
2309 };
2310
2311 void install_element_ospf6_clear_process(void)
2312 {
2313 install_element(ENABLE_NODE, &clear_router_ospf6_cmd);
2314 }
2315
2316 /* Install ospf related commands. */
2317 void ospf6_top_init(void)
2318 {
2319 /* Install ospf6 top node. */
2320 install_node(&ospf6_node);
2321
2322 install_element(VIEW_NODE, &show_ipv6_ospf6_cmd);
2323 install_element(VIEW_NODE, &show_ipv6_ospf6_vrfs_cmd);
2324 install_element(CONFIG_NODE, &router_ospf6_cmd);
2325 install_element(CONFIG_NODE, &no_router_ospf6_cmd);
2326
2327 install_element(VIEW_NODE, &show_ipv6_ospf6_route_cmd);
2328 install_element(VIEW_NODE, &show_ipv6_ospf6_route_match_cmd);
2329 install_element(VIEW_NODE, &show_ipv6_ospf6_route_match_detail_cmd);
2330 install_element(VIEW_NODE, &show_ipv6_ospf6_route_type_detail_cmd);
2331
2332 install_default(OSPF6_NODE);
2333 install_element(OSPF6_NODE, &ospf6_router_id_cmd);
2334 install_element(OSPF6_NODE, &no_ospf6_router_id_cmd);
2335 install_element(OSPF6_NODE, &ospf6_log_adjacency_changes_cmd);
2336 install_element(OSPF6_NODE, &ospf6_log_adjacency_changes_detail_cmd);
2337 install_element(OSPF6_NODE, &no_ospf6_log_adjacency_changes_cmd);
2338 install_element(OSPF6_NODE, &no_ospf6_log_adjacency_changes_detail_cmd);
2339 install_element(OSPF6_NODE, &ospf6_send_extra_data_cmd);
2340
2341 /* LSA timers commands */
2342 install_element(OSPF6_NODE, &ospf6_timers_lsa_cmd);
2343 install_element(OSPF6_NODE, &no_ospf6_timers_lsa_cmd);
2344
2345 install_element(OSPF6_NODE, &ospf6_interface_area_cmd);
2346 install_element(OSPF6_NODE, &no_ospf6_interface_area_cmd);
2347 install_element(OSPF6_NODE, &ospf6_stub_router_admin_cmd);
2348 install_element(OSPF6_NODE, &no_ospf6_stub_router_admin_cmd);
2349
2350 /* maximum-paths command */
2351 install_element(OSPF6_NODE, &ospf6_max_multipath_cmd);
2352 install_element(OSPF6_NODE, &no_ospf6_max_multipath_cmd);
2353
2354 /* ASBR Summarisation */
2355 install_element(OSPF6_NODE, &ospf6_external_route_aggregation_cmd);
2356 install_element(OSPF6_NODE, &no_ospf6_external_route_aggregation_cmd);
2357 install_element(OSPF6_NODE,
2358 &ospf6_external_route_aggregation_no_advertise_cmd);
2359 install_element(OSPF6_NODE,
2360 &no_ospf6_external_route_aggregation_no_advertise_cmd);
2361 install_element(OSPF6_NODE, &ospf6_route_aggregation_timer_cmd);
2362 install_element(OSPF6_NODE, &no_ospf6_route_aggregation_timer_cmd);
2363 install_element(VIEW_NODE, &show_ipv6_ospf6_external_aggregator_cmd);
2364
2365 install_element(OSPF6_NODE, &ospf6_distance_cmd);
2366 install_element(OSPF6_NODE, &no_ospf6_distance_cmd);
2367 install_element(OSPF6_NODE, &ospf6_distance_ospf6_cmd);
2368 install_element(OSPF6_NODE, &no_ospf6_distance_ospf6_cmd);
2369 }