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