]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_top.c
lib: Remove unnecessary comparison, for linked list
[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(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 if (thread_is_scheduled(o->t_spf_calc)) {
1376 long time_store;
1377
1378 json_object_boolean_true_add(json, "spfTimerActive");
1379 time_store =
1380 monotime_until(&o->t_spf_calc->u.sands, NULL)
1381 / 1000LL;
1382 json_object_int_add(json, "spfTimerDueInMsecs",
1383 time_store);
1384 } else
1385 json_object_boolean_false_add(json, "spfTimerActive");
1386
1387 json_object_boolean_add(json, "routerIsStubRouter",
1388 CHECK_FLAG(o->flag, OSPF6_STUB_ROUTER));
1389
1390 /* LSAs */
1391 json_object_int_add(json, "numberOfAsScopedLsa",
1392 o->lsdb->count);
1393 /* Areas */
1394 json_object_int_add(json, "numberOfAreaInRouter",
1395 listcount(o->area_list));
1396
1397 json_object_int_add(json, "AuthTrailerHigherSeqNo",
1398 o->seqnum_h);
1399 json_object_int_add(json, "AuthTrailerLowerSeqNo", o->seqnum_l);
1400
1401 if (CHECK_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES)) {
1402 if (CHECK_FLAG(o->config_flags,
1403 OSPF6_LOG_ADJACENCY_DETAIL))
1404 adjacency = "LoggedAll";
1405 else
1406 adjacency = "Logged";
1407 } else
1408 adjacency = "NotLogged";
1409 json_object_string_add(json, "adjacencyChanges", adjacency);
1410
1411 for (ALL_LIST_ELEMENTS_RO(o->area_list, n, oa))
1412 ospf6_area_show(vty, oa, json_areas, use_json);
1413
1414 json_object_object_add(json, "areas", json_areas);
1415
1416 vty_out(vty, "%s\n",
1417 json_object_to_json_string_ext(
1418 json, JSON_C_TO_STRING_PRETTY));
1419
1420 } else {
1421 /* process id, router id */
1422 inet_ntop(AF_INET, &o->router_id, router_id, sizeof(router_id));
1423 vty_out(vty, " OSPFv3 Routing Process (0) with Router-ID %s\n",
1424 router_id);
1425
1426 /* running time */
1427 monotime(&now);
1428 timersub(&now, &o->starttime, &running);
1429 timerstring(&running, duration, sizeof(duration));
1430 vty_out(vty, " Running %s\n", duration);
1431
1432 /* Redistribute configuration */
1433 /* XXX */
1434 vty_out(vty, " LSA minimum arrival %d msecs\n",
1435 o->lsa_minarrival);
1436
1437 vty_out(vty, " Maximum-paths %u\n", o->max_multipath);
1438 vty_out(vty, " Administrative distance %u\n",
1439 o->distance_all ? o->distance_all
1440 : ZEBRA_OSPF6_DISTANCE_DEFAULT);
1441
1442 /* Show SPF parameters */
1443 vty_out(vty,
1444 " Initial SPF scheduling delay %d millisec(s)\n"
1445 " Minimum hold time between consecutive SPFs %d millsecond(s)\n"
1446 " Maximum hold time between consecutive SPFs %d millsecond(s)\n"
1447 " Hold time multiplier is currently %d\n",
1448 o->spf_delay, o->spf_holdtime, o->spf_max_holdtime,
1449 o->spf_hold_multiplier);
1450
1451
1452 vty_out(vty, " SPF algorithm ");
1453 if (o->ts_spf.tv_sec || o->ts_spf.tv_usec) {
1454 timersub(&now, &o->ts_spf, &result);
1455 timerstring(&result, buf, sizeof(buf));
1456 ospf6_spf_reason_string(o->last_spf_reason, rbuf,
1457 sizeof(rbuf));
1458 vty_out(vty, "last executed %s ago, reason %s\n", buf,
1459 rbuf);
1460 vty_out(vty, " Last SPF duration %lld sec %lld usec\n",
1461 (long long)o->ts_spf_duration.tv_sec,
1462 (long long)o->ts_spf_duration.tv_usec);
1463 } else
1464 vty_out(vty, "has not been run\n");
1465
1466 threadtimer_string(now, o->t_spf_calc, buf, sizeof(buf));
1467 vty_out(vty, " SPF timer %s%s\n",
1468 (thread_is_scheduled(o->t_spf_calc) ? "due in "
1469 : "is "),
1470 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 /* Default prefix validation*/
1760 if (is_default_prefix(p)) {
1761 vty_out(vty,
1762 "Default address should not be configured as summary address.\n");
1763 return false;
1764 }
1765
1766 /* Host route should not be configured as summary address */
1767 if (p->prefixlen == IPV6_MAX_BITLEN) {
1768 vty_out(vty, "Host route should not be configured as summary address.\n");
1769 return false;
1770 }
1771
1772 return true;
1773 }
1774
1775 /* External Route Aggregation */
1776 DEFPY (ospf6_external_route_aggregation,
1777 ospf6_external_route_aggregation_cmd,
1778 "summary-address X:X::X:X/M$prefix [tag (1-4294967295)] [{metric (0-16777215) | metric-type (1-2)$mtype}]",
1779 "External summary address\n"
1780 "Specify IPv6 prefix\n"
1781 "Router tag \n"
1782 "Router tag value\n"
1783 "Metric \n"
1784 "Advertised metric for this route\n"
1785 "OSPFv3 exterior metric type for summarised routes\n"
1786 "Set OSPFv3 External Type 1/2 metrics\n")
1787 {
1788 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1789
1790 struct prefix p;
1791 int ret = CMD_SUCCESS;
1792
1793 p.family = AF_INET6;
1794 ret = str2prefix(prefix_str, &p);
1795 if (ret == 0) {
1796 vty_out(vty, "Malformed prefix\n");
1797 return CMD_WARNING_CONFIG_FAILED;
1798 }
1799
1800 /* Apply mask for given prefix. */
1801 apply_mask(&p);
1802
1803 if (!ospf6_is_valid_summary_addr(vty, &p))
1804 return CMD_WARNING_CONFIG_FAILED;
1805
1806 if (!tag_str)
1807 tag = 0;
1808
1809 if (!metric_str)
1810 metric = -1;
1811
1812 if (!mtype_str)
1813 mtype = DEFAULT_METRIC_TYPE;
1814
1815 ret = ospf6_external_aggr_config_set(ospf6, &p, tag, metric, mtype);
1816 if (ret == OSPF6_FAILURE) {
1817 vty_out(vty, "Invalid configuration!!\n");
1818 return CMD_WARNING_CONFIG_FAILED;
1819 }
1820
1821 return CMD_SUCCESS;
1822 }
1823
1824 DEFPY(no_ospf6_external_route_aggregation,
1825 no_ospf6_external_route_aggregation_cmd,
1826 "no summary-address X:X::X:X/M$prefix [tag (1-4294967295)] [{metric (0-16777215) | metric-type (1-2)}]",
1827 NO_STR
1828 "External summary address\n"
1829 "Specify IPv6 prefix\n"
1830 "Router tag\n"
1831 "Router tag value\n"
1832 "Metric \n"
1833 "Advertised metric for this route\n"
1834 "OSPFv3 exterior metric type for summarised routes\n"
1835 "Set OSPFv3 External Type 1/2 metrics\n")
1836 {
1837 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1838
1839 struct prefix p;
1840 int ret = CMD_SUCCESS;
1841
1842 ret = str2prefix(prefix_str, &p);
1843 if (ret == 0) {
1844 vty_out(vty, "Malformed prefix\n");
1845 return CMD_WARNING_CONFIG_FAILED;
1846 }
1847
1848 /* Apply mask for given prefix. */
1849 apply_mask(&p);
1850
1851 if (!ospf6_is_valid_summary_addr(vty, &p))
1852 return CMD_WARNING_CONFIG_FAILED;
1853
1854 ret = ospf6_external_aggr_config_unset(ospf6, &p);
1855 if (ret == OSPF6_INVALID)
1856 vty_out(vty, "Invalid configuration!!\n");
1857
1858 return CMD_SUCCESS;
1859 }
1860
1861 DEFPY (ospf6_external_route_aggregation_no_advertise,
1862 ospf6_external_route_aggregation_no_advertise_cmd,
1863 "summary-address X:X::X:X/M$prefix no-advertise",
1864 "External summary address\n"
1865 "Specify IPv6 prefix\n"
1866 "Don't advertise summary route \n")
1867 {
1868 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1869
1870 struct prefix p;
1871 int ret = CMD_SUCCESS;
1872
1873 ret = str2prefix(prefix_str, &p);
1874 if (ret == 0) {
1875 vty_out(vty, "Malformed prefix\n");
1876 return CMD_WARNING_CONFIG_FAILED;
1877 }
1878
1879 /* Apply mask for given prefix. */
1880 apply_mask(&p);
1881
1882 if (!ospf6_is_valid_summary_addr(vty, &p))
1883 return CMD_WARNING_CONFIG_FAILED;
1884
1885 ret = ospf6_asbr_external_rt_no_advertise(ospf6, &p);
1886 if (ret == OSPF6_INVALID)
1887 vty_out(vty, "!!Invalid configuration\n");
1888
1889 return CMD_SUCCESS;
1890 }
1891
1892 DEFPY (no_ospf6_external_route_aggregation_no_advertise,
1893 no_ospf6_external_route_aggregation_no_advertise_cmd,
1894 "no summary-address X:X::X:X/M$prefix no-advertise",
1895 NO_STR
1896 "External summary address\n"
1897 "Specify IPv6 prefix\n"
1898 "Adverise summary route to the AS \n")
1899 {
1900 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1901
1902 struct prefix p;
1903 int ret = CMD_SUCCESS;
1904
1905 ret = str2prefix(prefix_str, &p);
1906 if (ret == 0) {
1907 vty_out(vty, "Malformed prefix\n");
1908 return CMD_WARNING_CONFIG_FAILED;
1909 }
1910
1911 /* Apply mask for given prefix. */
1912 apply_mask(&p);
1913
1914 if (!ospf6_is_valid_summary_addr(vty, &p))
1915 return CMD_WARNING_CONFIG_FAILED;
1916
1917 ret = ospf6_asbr_external_rt_advertise(ospf6, &p);
1918 if (ret == OSPF6_INVALID)
1919 vty_out(vty, "!!Invalid configuration\n");
1920
1921 return CMD_SUCCESS;
1922 }
1923
1924 DEFPY (ospf6_route_aggregation_timer,
1925 ospf6_route_aggregation_timer_cmd,
1926 "aggregation timer (5-1800)",
1927 "External route aggregation\n"
1928 "Delay timer (in seconds)\n"
1929 "Timer interval(in seconds)\n")
1930 {
1931 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1932
1933 ospf6_external_aggr_delay_timer_set(ospf6, timer);
1934
1935 return CMD_SUCCESS;
1936 }
1937
1938 DEFPY (no_ospf6_route_aggregation_timer,
1939 no_ospf6_route_aggregation_timer_cmd,
1940 "no aggregation timer [5-1800]",
1941 NO_STR
1942 "External route aggregation\n"
1943 "Delay timer\n"
1944 "Timer interval(in seconds)\n")
1945 {
1946 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1947
1948 ospf6_external_aggr_delay_timer_set(ospf6,
1949 OSPF6_EXTL_AGGR_DEFAULT_DELAY);
1950 return CMD_SUCCESS;
1951 }
1952
1953 static int
1954 ospf6_print_vty_external_routes_walkcb(struct hash_bucket *bucket, void *arg)
1955 {
1956 struct ospf6_route *rt = bucket->data;
1957 struct vty *vty = (struct vty *)arg;
1958 static unsigned int count;
1959
1960 vty_out(vty, "%pFX ", &rt->prefix);
1961
1962 count++;
1963
1964 if (count%5 == 0)
1965 vty_out(vty, "\n");
1966
1967 if (OSPF6_EXTERNAL_RT_COUNT(rt->aggr_route) == count)
1968 count = 0;
1969
1970 return HASHWALK_CONTINUE;
1971 }
1972
1973 static int
1974 ospf6_print_json_external_routes_walkcb(struct hash_bucket *bucket, void *arg)
1975 {
1976 struct ospf6_route *rt = bucket->data;
1977 struct json_object *json = (struct json_object *)arg;
1978 char buf[PREFIX2STR_BUFFER];
1979 char exnalbuf[20];
1980 static unsigned int count;
1981
1982 prefix2str(&rt->prefix, buf, sizeof(buf));
1983
1984 snprintf(exnalbuf, sizeof(exnalbuf), "Exnl Addr-%d", count);
1985
1986 json_object_string_add(json, exnalbuf, buf);
1987
1988 count++;
1989
1990 if (OSPF6_EXTERNAL_RT_COUNT(rt->aggr_route) == count)
1991 count = 0;
1992
1993 return HASHWALK_CONTINUE;
1994 }
1995
1996 static void
1997 ospf6_show_vrf_name(struct vty *vty, struct ospf6 *ospf6,
1998 json_object *json)
1999 {
2000 if (json) {
2001 if (ospf6->vrf_id == VRF_DEFAULT)
2002 json_object_string_add(json, "vrfName",
2003 "default");
2004 else
2005 json_object_string_add(json, "vrfName",
2006 ospf6->name);
2007 json_object_int_add(json, "vrfId", ospf6->vrf_id);
2008 } else {
2009 if (ospf6->vrf_id == VRF_DEFAULT)
2010 vty_out(vty, "VRF Name: %s\n", "default");
2011 else if (ospf6->name)
2012 vty_out(vty, "VRF Name: %s\n", ospf6->name);
2013 }
2014 }
2015
2016 #if CONFDATE > 20230131
2017 CPP_NOTICE("Remove JSON object commands with keys containing whitespaces")
2018 #endif
2019 static int
2020 ospf6_show_summary_address(struct vty *vty, struct ospf6 *ospf6,
2021 json_object *json,
2022 bool uj, const char *detail)
2023 {
2024 struct route_node *rn;
2025 static const char header[] = "Summary-address Metric-type Metric Tag External_Rt_count\n";
2026 json_object *json_vrf = NULL;
2027
2028 if (!uj) {
2029 ospf6_show_vrf_name(vty, ospf6, json_vrf);
2030 vty_out(vty, "aggregation delay interval :%u(in seconds)\n\n",
2031 ospf6->aggr_delay_interval);
2032 vty_out(vty, "%s\n", header);
2033 } else {
2034 json_vrf = json_object_new_object();
2035
2036 ospf6_show_vrf_name(vty, ospf6, json_vrf);
2037
2038 json_object_int_add(json_vrf, "aggregation delay interval",
2039 ospf6->aggr_delay_interval);
2040 json_object_int_add(json_vrf, "aggregationDelayInterval",
2041 ospf6->aggr_delay_interval);
2042 }
2043
2044
2045 for (rn = route_top(ospf6->rt_aggr_tbl); rn; rn = route_next(rn)) {
2046 if (!rn->info)
2047 continue;
2048
2049 struct ospf6_external_aggr_rt *aggr = rn->info;
2050 json_object *json_aggr = NULL;
2051 char buf[PREFIX2STR_BUFFER];
2052
2053 prefix2str(&aggr->p, buf, sizeof(buf));
2054
2055 if (uj) {
2056
2057 json_aggr = json_object_new_object();
2058
2059 json_object_object_add(json_vrf,
2060 buf,
2061 json_aggr);
2062
2063 json_object_string_add(json_aggr,
2064 "Summary address",
2065 buf);
2066 json_object_string_add(json_aggr, "summaryAddress",
2067 buf);
2068
2069 json_object_string_add(
2070 json_aggr, "Metric-type",
2071 (aggr->mtype == DEFAULT_METRIC_TYPE)
2072 ? "E2"
2073 : "E1");
2074 json_object_string_add(
2075 json_aggr, "metricType",
2076 (aggr->mtype == DEFAULT_METRIC_TYPE) ? "E2"
2077 : "E1");
2078
2079 json_object_int_add(json_aggr, "Metric",
2080 (aggr->metric != -1)
2081 ? aggr->metric
2082 : DEFAULT_DEFAULT_METRIC);
2083
2084 json_object_int_add(json_aggr, "Tag",
2085 aggr->tag);
2086
2087 json_object_int_add(json_aggr,
2088 "External route count",
2089 OSPF6_EXTERNAL_RT_COUNT(aggr));
2090 json_object_int_add(json_aggr, "externalRouteCount",
2091 OSPF6_EXTERNAL_RT_COUNT(aggr));
2092
2093 if (OSPF6_EXTERNAL_RT_COUNT(aggr) && detail) {
2094 json_object_int_add(json_aggr, "ID",
2095 aggr->id);
2096 json_object_int_add(json_aggr, "Flags",
2097 aggr->aggrflags);
2098 hash_walk(aggr->match_extnl_hash,
2099 ospf6_print_json_external_routes_walkcb,
2100 json_aggr);
2101 }
2102
2103 } else {
2104 vty_out(vty, "%-22s", buf);
2105
2106 (aggr->mtype == DEFAULT_METRIC_TYPE)
2107 ? vty_out(vty, "%-16s", "E2")
2108 : vty_out(vty, "%-16s", "E1");
2109 vty_out(vty, "%-11d", (aggr->metric != -1)
2110 ? aggr->metric
2111 : DEFAULT_DEFAULT_METRIC);
2112
2113 vty_out(vty, "%-12u", aggr->tag);
2114
2115 vty_out(vty, "%-5ld\n",
2116 OSPF6_EXTERNAL_RT_COUNT(aggr));
2117
2118 if (OSPF6_EXTERNAL_RT_COUNT(aggr) && detail) {
2119 vty_out(vty,
2120 "Matched External routes:\n");
2121 hash_walk(aggr->match_extnl_hash,
2122 ospf6_print_vty_external_routes_walkcb,
2123 vty);
2124 vty_out(vty, "\n");
2125 }
2126
2127 vty_out(vty, "\n");
2128 }
2129 }
2130
2131 if (uj)
2132 json_object_object_add(json, ospf6->name,
2133 json_vrf);
2134
2135 return CMD_SUCCESS;
2136 }
2137
2138 DEFPY (show_ipv6_ospf6_external_aggregator,
2139 show_ipv6_ospf6_external_aggregator_cmd,
2140 "show ipv6 ospf6 [vrf <NAME|all>] summary-address [detail$detail] [json]",
2141 SHOW_STR
2142 IP6_STR
2143 OSPF6_STR
2144 VRF_CMD_HELP_STR
2145 "All VRFs\n"
2146 "Show external summary addresses\n"
2147 "detailed information\n"
2148 JSON_STR)
2149 {
2150 bool uj = use_json(argc, argv);
2151 struct ospf6 *ospf6 = NULL;
2152 json_object *json = NULL;
2153 const char *vrf_name = NULL;
2154 struct listnode *node;
2155 bool all_vrf = false;
2156 int idx_vrf = 0;
2157
2158 if (uj)
2159 json = json_object_new_object();
2160
2161 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
2162
2163 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
2164 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
2165
2166 ospf6_show_summary_address(vty, ospf6, json, uj,
2167 detail);
2168
2169 if (!all_vrf)
2170 break;
2171 }
2172 }
2173
2174 if (uj) {
2175 vty_json(vty, json);
2176 }
2177
2178 OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
2179
2180 return CMD_SUCCESS;
2181 }
2182
2183 static void ospf6_stub_router_config_write(struct vty *vty, struct ospf6 *ospf6)
2184 {
2185 if (CHECK_FLAG(ospf6->flag, OSPF6_STUB_ROUTER))
2186 vty_out(vty, " stub-router administrative\n");
2187 return;
2188 }
2189
2190 static int ospf6_distance_config_write(struct vty *vty, struct ospf6 *ospf6)
2191 {
2192 struct route_node *rn;
2193 struct ospf6_distance *odistance;
2194
2195 if (ospf6->distance_all)
2196 vty_out(vty, " distance %u\n", ospf6->distance_all);
2197
2198 if (ospf6->distance_intra || ospf6->distance_inter
2199 || ospf6->distance_external) {
2200 vty_out(vty, " distance ospf6");
2201
2202 if (ospf6->distance_intra)
2203 vty_out(vty, " intra-area %u", ospf6->distance_intra);
2204 if (ospf6->distance_inter)
2205 vty_out(vty, " inter-area %u", ospf6->distance_inter);
2206 if (ospf6->distance_external)
2207 vty_out(vty, " external %u", ospf6->distance_external);
2208
2209 vty_out(vty, "\n");
2210 }
2211
2212 for (rn = route_top(ospf6->distance_table); rn; rn = route_next(rn))
2213 if ((odistance = rn->info) != NULL)
2214 vty_out(vty, " distance %u %pFX %s\n",
2215 odistance->distance, &rn->p,
2216 odistance->access_list ? odistance->access_list
2217 : "");
2218 return 0;
2219 }
2220
2221 static int ospf6_asbr_summary_config_write(struct vty *vty, struct ospf6 *ospf6)
2222 {
2223 struct route_node *rn;
2224 struct ospf6_external_aggr_rt *aggr;
2225 char buf[PREFIX2STR_BUFFER];
2226
2227 if (ospf6->aggr_delay_interval != OSPF6_EXTL_AGGR_DEFAULT_DELAY)
2228 vty_out(vty, " aggregation timer %u\n",
2229 ospf6->aggr_delay_interval);
2230
2231 /* print 'summary-address A:B::C:D/M' */
2232 for (rn = route_top(ospf6->rt_aggr_tbl); rn; rn = route_next(rn)) {
2233 if (!rn->info)
2234 continue;
2235
2236 aggr = rn->info;
2237
2238 prefix2str(&aggr->p, buf, sizeof(buf));
2239 vty_out(vty, " summary-address %s", buf);
2240 if (aggr->tag)
2241 vty_out(vty, " tag %u", aggr->tag);
2242
2243 if (aggr->metric != -1)
2244 vty_out(vty, " metric %d", aggr->metric);
2245
2246 if (aggr->mtype != DEFAULT_METRIC_TYPE)
2247 vty_out(vty, " metric-type %d", aggr->mtype);
2248
2249 if (CHECK_FLAG(aggr->aggrflags,
2250 OSPF6_EXTERNAL_AGGRT_NO_ADVERTISE))
2251 vty_out(vty, " no-advertise");
2252
2253 vty_out(vty, "\n");
2254 }
2255
2256 return 0;
2257 }
2258
2259 /* OSPF configuration write function. */
2260 static int config_write_ospf6(struct vty *vty)
2261 {
2262 struct ospf6 *ospf6;
2263 struct listnode *node, *nnode;
2264
2265 /* OSPFv3 configuration. */
2266 if (om6 == NULL)
2267 return CMD_SUCCESS;
2268
2269 for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6)) {
2270 if (ospf6->name && strcmp(ospf6->name, VRF_DEFAULT_NAME))
2271 vty_out(vty, "router ospf6 vrf %s\n", ospf6->name);
2272 else
2273 vty_out(vty, "router ospf6\n");
2274
2275 if (ospf6->router_id_static != 0)
2276 vty_out(vty, " ospf6 router-id %pI4\n",
2277 &ospf6->router_id_static);
2278
2279 if (CHECK_FLAG(ospf6->config_flags,
2280 OSPF6_SEND_EXTRA_DATA_TO_ZEBRA))
2281 vty_out(vty, " ospf6 send-extra-data zebra\n");
2282
2283 /* log-adjacency-changes flag print. */
2284 if (CHECK_FLAG(ospf6->config_flags,
2285 OSPF6_LOG_ADJACENCY_CHANGES)) {
2286 if (CHECK_FLAG(ospf6->config_flags,
2287 OSPF6_LOG_ADJACENCY_DETAIL))
2288 vty_out(vty, " log-adjacency-changes detail\n");
2289 else if (!SAVE_OSPF6_LOG_ADJACENCY_CHANGES)
2290 vty_out(vty, " log-adjacency-changes\n");
2291 } else if (SAVE_OSPF6_LOG_ADJACENCY_CHANGES) {
2292 vty_out(vty, " no log-adjacency-changes\n");
2293 }
2294
2295 if (ospf6->ref_bandwidth != OSPF6_REFERENCE_BANDWIDTH)
2296 vty_out(vty, " auto-cost reference-bandwidth %d\n",
2297 ospf6->ref_bandwidth);
2298
2299 if (ospf6->write_oi_count
2300 != OSPF6_WRITE_INTERFACE_COUNT_DEFAULT)
2301 vty_out(vty, " write-multiplier %d\n",
2302 ospf6->write_oi_count);
2303
2304 /* LSA timers print. */
2305 if (ospf6->lsa_minarrival != OSPF_MIN_LS_ARRIVAL)
2306 vty_out(vty, " timers lsa min-arrival %d\n",
2307 ospf6->lsa_minarrival);
2308
2309 /* ECMP max path config */
2310 if (ospf6->max_multipath != MULTIPATH_NUM)
2311 vty_out(vty, " maximum-paths %d\n",
2312 ospf6->max_multipath);
2313
2314 ospf6_stub_router_config_write(vty, ospf6);
2315 ospf6_redistribute_config_write(vty, ospf6);
2316 ospf6_area_config_write(vty, ospf6);
2317 ospf6_spf_config_write(vty, ospf6);
2318 ospf6_distance_config_write(vty, ospf6);
2319 ospf6_distribute_config_write(vty, ospf6);
2320 ospf6_asbr_summary_config_write(vty, ospf6);
2321 config_write_ospf6_gr(vty, ospf6);
2322 config_write_ospf6_gr_helper(vty, ospf6);
2323
2324 vty_out(vty, "exit\n");
2325 vty_out(vty, "!\n");
2326 }
2327 return 0;
2328 }
2329
2330 static int config_write_ospf6(struct vty *vty);
2331 /* OSPF6 node structure. */
2332 static struct cmd_node ospf6_node = {
2333 .name = "ospf6",
2334 .node = OSPF6_NODE,
2335 .parent_node = CONFIG_NODE,
2336 .prompt = "%s(config-ospf6)# ",
2337 .config_write = config_write_ospf6,
2338 };
2339
2340 void install_element_ospf6_clear_process(void)
2341 {
2342 install_element(ENABLE_NODE, &clear_router_ospf6_cmd);
2343 }
2344
2345 /* Install ospf related commands. */
2346 void ospf6_top_init(void)
2347 {
2348 /* Install ospf6 top node. */
2349 install_node(&ospf6_node);
2350
2351 install_element(VIEW_NODE, &show_ipv6_ospf6_cmd);
2352 install_element(VIEW_NODE, &show_ipv6_ospf6_vrfs_cmd);
2353 install_element(CONFIG_NODE, &router_ospf6_cmd);
2354 install_element(CONFIG_NODE, &no_router_ospf6_cmd);
2355
2356 install_element(VIEW_NODE, &show_ipv6_ospf6_route_cmd);
2357 install_element(VIEW_NODE, &show_ipv6_ospf6_route_match_cmd);
2358 install_element(VIEW_NODE, &show_ipv6_ospf6_route_match_detail_cmd);
2359 install_element(VIEW_NODE, &show_ipv6_ospf6_route_type_detail_cmd);
2360
2361 install_default(OSPF6_NODE);
2362 install_element(OSPF6_NODE, &ospf6_router_id_cmd);
2363 install_element(OSPF6_NODE, &no_ospf6_router_id_cmd);
2364 install_element(OSPF6_NODE, &ospf6_log_adjacency_changes_cmd);
2365 install_element(OSPF6_NODE, &ospf6_log_adjacency_changes_detail_cmd);
2366 install_element(OSPF6_NODE, &no_ospf6_log_adjacency_changes_cmd);
2367 install_element(OSPF6_NODE, &no_ospf6_log_adjacency_changes_detail_cmd);
2368 install_element(OSPF6_NODE, &ospf6_send_extra_data_cmd);
2369
2370 /* LSA timers commands */
2371 install_element(OSPF6_NODE, &ospf6_timers_lsa_cmd);
2372 install_element(OSPF6_NODE, &no_ospf6_timers_lsa_cmd);
2373
2374 install_element(OSPF6_NODE, &ospf6_interface_area_cmd);
2375 install_element(OSPF6_NODE, &no_ospf6_interface_area_cmd);
2376 install_element(OSPF6_NODE, &ospf6_stub_router_admin_cmd);
2377 install_element(OSPF6_NODE, &no_ospf6_stub_router_admin_cmd);
2378
2379 /* maximum-paths command */
2380 install_element(OSPF6_NODE, &ospf6_max_multipath_cmd);
2381 install_element(OSPF6_NODE, &no_ospf6_max_multipath_cmd);
2382
2383 /* ASBR Summarisation */
2384 install_element(OSPF6_NODE, &ospf6_external_route_aggregation_cmd);
2385 install_element(OSPF6_NODE, &no_ospf6_external_route_aggregation_cmd);
2386 install_element(OSPF6_NODE,
2387 &ospf6_external_route_aggregation_no_advertise_cmd);
2388 install_element(OSPF6_NODE,
2389 &no_ospf6_external_route_aggregation_no_advertise_cmd);
2390 install_element(OSPF6_NODE, &ospf6_route_aggregation_timer_cmd);
2391 install_element(OSPF6_NODE, &no_ospf6_route_aggregation_timer_cmd);
2392 install_element(VIEW_NODE, &show_ipv6_ospf6_external_aggregator_cmd);
2393
2394 install_element(OSPF6_NODE, &ospf6_distance_cmd);
2395 install_element(OSPF6_NODE, &no_ospf6_distance_cmd);
2396 install_element(OSPF6_NODE, &ospf6_distance_ospf6_cmd);
2397 install_element(OSPF6_NODE, &no_ospf6_distance_ospf6_cmd);
2398 }