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