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