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