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