]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_top.c
Merge pull request #8909 from idryzhov/isis-conf
[mirror_frr.git] / ospf6d / ospf6_top.c
CommitLineData
718e3744 1/*
508e53e2 2 * Copyright (C) 2003 Yasuhiro Ohara
718e3744 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 *
896014f4
DL
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
718e3744 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"
8efe88ea 31#include "defaults.h"
35a45dea 32#include "lib/json.h"
7df1f362 33#include "lib_errors.h"
718e3744 34
718e3744 35#include "ospf6_proto.h"
508e53e2 36#include "ospf6_message.h"
718e3744 37#include "ospf6_lsa.h"
38#include "ospf6_lsdb.h"
718e3744 39#include "ospf6_route.h"
40#include "ospf6_zebra.h"
41
508e53e2 42#include "ospf6_top.h"
43#include "ospf6_area.h"
44#include "ospf6_interface.h"
45#include "ospf6_neighbor.h"
7df1f362 46#include "ospf6_network.h"
718e3744 47
6452df09 48#include "ospf6_flood.h"
508e53e2 49#include "ospf6_asbr.h"
049207c3 50#include "ospf6_abr.h"
6452df09 51#include "ospf6_intra.h"
3810e06e 52#include "ospf6_spf.h"
049207c3 53#include "ospf6d.h"
eacd0828 54#include "lib/json.h"
ad500b22 55#include "ospf6_nssa.h"
718e3744 56
30043e4c
DL
57DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_TOP, "OSPF6 top");
58
96244aca 59DEFINE_QOBJ_TYPE(ospf6);
ae19c240 60
c572fbfe 61FRR_CFG_DEFAULT_BOOL(OSPF6_LOG_ADJACENCY_CHANGES,
4c1458b5
DL
62 { .val_bool = true, .match_profile = "datacenter", },
63 { .val_bool = false },
67b0f40c 64);
c572fbfe 65
718e3744 66/* global ospf6d variable */
78c6ba61
CS
67static struct ospf6_master ospf6_master;
68struct ospf6_master *om6;
718e3744 69
d62a17ae 70static void ospf6_disable(struct ospf6 *o);
ae2254aa 71
beadc736 72static void ospf6_add(struct ospf6 *ospf6)
73{
74 listnode_add(om6->ospf6, ospf6);
75}
76
77static void ospf6_del(struct ospf6 *ospf6)
78{
79 listnode_delete(om6->ospf6, ospf6);
80}
81
82const char *ospf6_vrf_id_to_name(vrf_id_t vrf_id)
83{
84 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
85
86 return vrf ? vrf->name : "NIL";
87}
88
89/* Link OSPF instance to VRF. */
90void ospf6_vrf_link(struct ospf6 *ospf6, struct vrf *vrf)
91{
92 ospf6->vrf_id = vrf->vrf_id;
93 if (vrf->info != (void *)ospf6)
94 vrf->info = (void *)ospf6;
95}
96
97/* Unlink OSPF instance from VRF. */
98void ospf6_vrf_unlink(struct ospf6 *ospf6, struct vrf *vrf)
99{
100 if (vrf->info == (void *)ospf6)
101 vrf->info = NULL;
102 ospf6->vrf_id = VRF_UNKNOWN;
103}
104
105struct ospf6 *ospf6_lookup_by_vrf_id(vrf_id_t vrf_id)
106{
107 struct vrf *vrf = NULL;
108
109 vrf = vrf_lookup_by_id(vrf_id);
110 if (!vrf)
111 return NULL;
112 return (vrf->info) ? (struct ospf6 *)vrf->info : NULL;
113}
114
115struct ospf6 *ospf6_lookup_by_vrf_name(const char *name)
116{
117 struct ospf6 *o = NULL;
118 struct listnode *node, *nnode;
119
120 for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, o)) {
121 if (((o->name == NULL && name == NULL)
122 || (o->name && name && strcmp(o->name, name) == 0)))
123 return o;
124 }
125 return NULL;
126}
127
4e8ccd92 128/* This is hook function for vrf create called as part of vrf_init */
129static int ospf6_vrf_new(struct vrf *vrf)
130{
131 return 0;
132}
133
134/* This is hook function for vrf delete call as part of vrf_init */
135static int ospf6_vrf_delete(struct vrf *vrf)
136{
137 return 0;
138}
139
140static void ospf6_set_redist_vrf_bitmaps(struct ospf6 *ospf6, bool set)
141{
142 int type;
143 struct list *red_list;
144
145 for (type = 0; type < ZEBRA_ROUTE_MAX; type++) {
146 red_list = ospf6->redist[type];
147 if (!red_list)
148 continue;
149 if (IS_OSPF6_DEBUG_ZEBRA(RECV))
150 zlog_debug(
151 "%s: setting redist vrf %d bitmap for type %d",
152 __func__, ospf6->vrf_id, type);
153 if (set)
154 vrf_bitmap_set(zclient->redist[AFI_IP6][type],
155 ospf6->vrf_id);
156 else
157 vrf_bitmap_unset(zclient->redist[AFI_IP6][type],
158 ospf6->vrf_id);
159 }
82bc4b8a
IR
160
161 red_list = ospf6->redist[DEFAULT_ROUTE];
162 if (red_list) {
163 if (set)
164 vrf_bitmap_set(zclient->default_information[AFI_IP6],
165 ospf6->vrf_id);
166 else
167 vrf_bitmap_unset(zclient->default_information[AFI_IP6],
168 ospf6->vrf_id);
169 }
4e8ccd92 170}
171
172/* Disable OSPF6 VRF instance */
173static int ospf6_vrf_disable(struct vrf *vrf)
174{
175 struct ospf6 *ospf6 = NULL;
176
177 if (vrf->vrf_id == VRF_DEFAULT)
178 return 0;
179
180 ospf6 = ospf6_lookup_by_vrf_name(vrf->name);
181 if (ospf6) {
182 ospf6_zebra_vrf_deregister(ospf6);
183
184 ospf6_set_redist_vrf_bitmaps(ospf6, false);
185
186 /* We have instance configured, unlink
187 * from VRF and make it "down".
188 */
189 ospf6_vrf_unlink(ospf6, vrf);
190 thread_cancel(&ospf6->t_ospf6_receive);
191 close(ospf6->fd);
192 ospf6->fd = -1;
193 }
194
195 /* Note: This is a callback, the VRF will be deleted by the caller. */
196 return 0;
197}
198
199/* Enable OSPF6 VRF instance */
200static int ospf6_vrf_enable(struct vrf *vrf)
201{
202 struct ospf6 *ospf6 = NULL;
203 vrf_id_t old_vrf_id;
204 int ret = 0;
205
206 ospf6 = ospf6_lookup_by_vrf_name(vrf->name);
207 if (ospf6) {
208 old_vrf_id = ospf6->vrf_id;
209 /* We have instance configured, link to VRF and make it "up". */
210 ospf6_vrf_link(ospf6, vrf);
211
212 if (old_vrf_id != ospf6->vrf_id) {
213 ospf6_set_redist_vrf_bitmaps(ospf6, true);
214
215 /* start zebra redist to us for new vrf */
216 ospf6_zebra_vrf_register(ospf6);
217
218 ret = ospf6_serv_sock(ospf6);
219 if (ret < 0 || ospf6->fd <= 0)
220 return 0;
221 thread_add_read(master, ospf6_receive, ospf6, ospf6->fd,
222 &ospf6->t_ospf6_receive);
223
224 ospf6_router_id_update(ospf6);
225 }
226 }
227
228 return 0;
229}
230
231void ospf6_vrf_init(void)
232{
233 vrf_init(ospf6_vrf_new, ospf6_vrf_enable, ospf6_vrf_disable,
234 ospf6_vrf_delete, ospf6_vrf_enable);
f5eef2d5
IR
235
236 vrf_cmd_init(NULL, &ospf6d_privs);
4e8ccd92 237}
beadc736 238
d62a17ae 239static void ospf6_top_lsdb_hook_add(struct ospf6_lsa *lsa)
718e3744 240{
d62a17ae 241 switch (ntohs(lsa->header->type)) {
242 case OSPF6_LSTYPE_AS_EXTERNAL:
f5f26b8f 243 ospf6_asbr_lsa_add(lsa);
d62a17ae 244 break;
245
246 default:
247 break;
248 }
718e3744 249}
250
d62a17ae 251static void ospf6_top_lsdb_hook_remove(struct ospf6_lsa *lsa)
718e3744 252{
d62a17ae 253 switch (ntohs(lsa->header->type)) {
254 case OSPF6_LSTYPE_AS_EXTERNAL:
07b37f93 255 ospf6_asbr_lsa_remove(lsa, NULL);
d62a17ae 256 break;
257
258 default:
259 break;
260 }
718e3744 261}
262
e285b70d 263static void ospf6_top_route_hook_add(struct ospf6_route *route)
049207c3 264{
ad500b22
K
265 struct ospf6 *ospf6 = NULL;
266 struct ospf6_area *oa = NULL;
267
268 if (route->table->scope_type == OSPF6_SCOPE_TYPE_GLOBAL)
269 ospf6 = route->table->scope;
270 else if (route->table->scope_type == OSPF6_SCOPE_TYPE_AREA) {
271 oa = (struct ospf6_area *)route->table->scope;
272 ospf6 = oa->ospf6;
0d882ec7
DS
273 } else {
274 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)
275 || IS_OSPF6_DEBUG_BROUTER)
276 zlog_debug(
277 "%s: Route is not GLOBAL or scope is not of TYPE_AREA: %pFX",
278 __func__, &route->prefix);
279 return;
ad500b22 280 }
e285b70d 281
beadc736 282 ospf6_abr_originate_summary(route, ospf6);
283 ospf6_zebra_route_update_add(route, ospf6);
049207c3 284}
285
e285b70d 286static void ospf6_top_route_hook_remove(struct ospf6_route *route)
049207c3 287{
ad500b22
K
288 struct ospf6 *ospf6 = NULL;
289 struct ospf6_area *oa = NULL;
290
291 if (route->table->scope_type == OSPF6_SCOPE_TYPE_GLOBAL)
292 ospf6 = route->table->scope;
293 else if (route->table->scope_type == OSPF6_SCOPE_TYPE_AREA) {
294 oa = (struct ospf6_area *)route->table->scope;
295 ospf6 = oa->ospf6;
0d882ec7
DS
296 } else {
297 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)
298 || IS_OSPF6_DEBUG_BROUTER)
299 zlog_debug(
300 "%s: Route is not GLOBAL or scope is not of TYPE_AREA: %pFX",
301 __func__, &route->prefix);
302 return;
ad500b22 303 }
e285b70d 304
d62a17ae 305 route->flag |= OSPF6_ROUTE_REMOVE;
beadc736 306 ospf6_abr_originate_summary(route, ospf6);
307 ospf6_zebra_route_update_remove(route, ospf6);
049207c3 308}
309
e285b70d 310static void ospf6_top_brouter_hook_add(struct ospf6_route *route)
6452df09 311{
e285b70d
IR
312 struct ospf6 *ospf6 = route->table->scope;
313
99ab28cb
CS
314 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL) ||
315 IS_OSPF6_DEBUG_BROUTER) {
07b37f93
CS
316 uint32_t brouter_id;
317 char brouter_name[16];
318
319 brouter_id = ADV_ROUTER_IN_PREFIX(&route->prefix);
320 inet_ntop(AF_INET, &brouter_id, brouter_name,
321 sizeof(brouter_name));
322 zlog_debug("%s: brouter %s add with adv router %x nh count %u",
15569c58 323 __func__, brouter_name,
07b37f93
CS
324 route->path.origin.adv_router,
325 listcount(route->nh_list));
064d4355 326 }
beadc736 327 ospf6_abr_examin_brouter(ADV_ROUTER_IN_PREFIX(&route->prefix), route,
328 ospf6);
329 ospf6_asbr_lsentry_add(route, ospf6);
330 ospf6_abr_originate_summary(route, ospf6);
6452df09 331}
332
e285b70d 333static void ospf6_top_brouter_hook_remove(struct ospf6_route *route)
6452df09 334{
e285b70d
IR
335 struct ospf6 *ospf6 = route->table->scope;
336
99ab28cb
CS
337 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL) ||
338 IS_OSPF6_DEBUG_BROUTER) {
07b37f93
CS
339 uint32_t brouter_id;
340 char brouter_name[16];
064d4355 341
07b37f93
CS
342 brouter_id = ADV_ROUTER_IN_PREFIX(&route->prefix);
343 inet_ntop(AF_INET, &brouter_id, brouter_name,
344 sizeof(brouter_name));
99ab28cb 345 zlog_debug("%s: brouter %p %s del with adv router %x nh %u",
15569c58 346 __func__, (void *)route, brouter_name,
99ab28cb 347 route->path.origin.adv_router,
07b37f93 348 listcount(route->nh_list));
064d4355 349 }
d62a17ae 350 route->flag |= OSPF6_ROUTE_REMOVE;
beadc736 351 ospf6_abr_examin_brouter(ADV_ROUTER_IN_PREFIX(&route->prefix), route,
352 ospf6);
353 ospf6_asbr_lsentry_remove(route, ospf6);
354 ospf6_abr_originate_summary(route, ospf6);
6452df09 355}
356
7df1f362 357static struct ospf6 *ospf6_create(const char *name)
718e3744 358{
d62a17ae 359 struct ospf6 *o;
7df1f362 360 struct vrf *vrf = NULL;
718e3744 361
d62a17ae 362 o = XCALLOC(MTYPE_OSPF6_TOP, sizeof(struct ospf6));
718e3744 363
7df1f362
K
364 vrf = vrf_lookup_by_name(name);
365 if (vrf) {
366 o->vrf_id = vrf->vrf_id;
beadc736 367 } else
368 o->vrf_id = VRF_UNKNOWN;
369
370 /* Freed in ospf6_delete */
371 o->name = XSTRDUP(MTYPE_OSPF6_TOP, name);
372 if (vrf)
373 ospf6_vrf_link(o, vrf);
374
375 ospf6_zebra_vrf_register(o);
376
d62a17ae 377 /* initialize */
378 monotime(&o->starttime);
379 o->area_list = list_new();
380 o->area_list->cmp = ospf6_area_cmp;
381 o->lsdb = ospf6_lsdb_create(o);
382 o->lsdb_self = ospf6_lsdb_create(o);
383 o->lsdb->hook_add = ospf6_top_lsdb_hook_add;
384 o->lsdb->hook_remove = ospf6_top_lsdb_hook_remove;
718e3744 385
d62a17ae 386 o->spf_delay = OSPF_SPF_DELAY_DEFAULT;
387 o->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
388 o->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT;
389 o->spf_hold_multiplier = 1;
3810e06e 390
b19502d3 391 o->default_originate = DEFAULT_ORIGINATE_NONE;
b8212e03 392 o->redistribute = 0;
d62a17ae 393 /* LSA timers value init */
394 o->lsa_minarrival = OSPF_MIN_LS_ARRIVAL;
b6927875 395
d62a17ae 396 o->route_table = OSPF6_ROUTE_TABLE_CREATE(GLOBAL, ROUTES);
397 o->route_table->scope = o;
398 o->route_table->hook_add = ospf6_top_route_hook_add;
399 o->route_table->hook_remove = ospf6_top_route_hook_remove;
718e3744 400
d62a17ae 401 o->brouter_table = OSPF6_ROUTE_TABLE_CREATE(GLOBAL, BORDER_ROUTERS);
402 o->brouter_table->scope = o;
403 o->brouter_table->hook_add = ospf6_top_brouter_hook_add;
404 o->brouter_table->hook_remove = ospf6_top_brouter_hook_remove;
049207c3 405
d62a17ae 406 o->external_table = OSPF6_ROUTE_TABLE_CREATE(GLOBAL, EXTERNAL_ROUTES);
407 o->external_table->scope = o;
cf1ce250 408
d62a17ae 409 o->external_id_table = route_table_init();
718e3744 410
78156066 411 o->write_oi_count = OSPF6_WRITE_INTERFACE_COUNT_DEFAULT;
d62a17ae 412 o->ref_bandwidth = OSPF6_REFERENCE_BANDWIDTH;
fd500689 413
d62a17ae 414 o->distance_table = route_table_init();
7df1f362 415 o->fd = -1;
baff583e 416
1958143e
MR
417 o->max_multipath = MULTIPATH_NUM;
418
4f7bf1ab
PR
419 o->oi_write_q = list_new();
420
d62a17ae 421 QOBJ_REG(o, ospf6);
692c7954 422
7df1f362
K
423 /* Make ospf protocol socket. */
424 ospf6_serv_sock(o);
425
d62a17ae 426 return o;
718e3744 427}
428
beadc736 429struct ospf6 *ospf6_instance_create(const char *name)
7df1f362 430{
beadc736 431 struct ospf6 *ospf6;
42cabc55
IR
432 struct vrf *vrf;
433 struct interface *ifp;
beadc736 434
7df1f362
K
435 ospf6 = ospf6_create(name);
436 if (DFLT_OSPF6_LOG_ADJACENCY_CHANGES)
437 SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
438 if (ospf6->router_id == 0)
beadc736 439 ospf6_router_id_update(ospf6);
440 ospf6_add(ospf6);
42cabc55
IR
441 if (ospf6->vrf_id != VRF_UNKNOWN) {
442 vrf = vrf_lookup_by_id(ospf6->vrf_id);
443 FOR_ALL_INTERFACES (vrf, ifp) {
444 if (ifp->info)
445 ospf6_interface_start(ifp->info);
446 }
447 }
4e8ccd92 448 if (ospf6->fd < 0)
449 return ospf6;
450
7df1f362
K
451 thread_add_read(master, ospf6_receive, ospf6, ospf6->fd,
452 &ospf6->t_ospf6_receive);
beadc736 453
454 return ospf6;
7df1f362
K
455}
456
d62a17ae 457void ospf6_delete(struct ospf6 *o)
718e3744 458{
d62a17ae 459 struct listnode *node, *nnode;
460 struct ospf6_area *oa;
92699b9b 461 struct vrf *vrf;
718e3744 462
d62a17ae 463 QOBJ_UNREG(o);
76249532 464
beadc736 465 ospf6_flush_self_originated_lsas_now(o);
466 ospf6_disable(o);
467 ospf6_del(o);
ae2254aa 468
4e8ccd92 469 ospf6_zebra_vrf_deregister(o);
470
d3136990
IR
471 ospf6_serv_close(&o->fd);
472
d62a17ae 473 for (ALL_LIST_ELEMENTS(o->area_list, node, nnode, oa))
474 ospf6_area_delete(oa);
d9628728
CF
475
476
6a154c88 477 list_delete(&o->area_list);
718e3744 478
d62a17ae 479 ospf6_lsdb_delete(o->lsdb);
480 ospf6_lsdb_delete(o->lsdb_self);
718e3744 481
e285b70d
IR
482 ospf6_route_table_delete(o->route_table);
483 ospf6_route_table_delete(o->brouter_table);
718e3744 484
e285b70d 485 ospf6_route_table_delete(o->external_table);
d62a17ae 486 route_table_finish(o->external_id_table);
718e3744 487
d62a17ae 488 ospf6_distance_reset(o);
489 route_table_finish(o->distance_table);
4f7bf1ab 490 list_delete(&o->oi_write_q);
baff583e 491
92699b9b
IR
492 if (o->vrf_id != VRF_UNKNOWN) {
493 vrf = vrf_lookup_by_id(o->vrf_id);
494 if (vrf)
495 ospf6_vrf_unlink(o, vrf);
496 }
497
7df1f362 498 XFREE(MTYPE_OSPF6_TOP, o->name);
d62a17ae 499 XFREE(MTYPE_OSPF6_TOP, o);
508e53e2 500}
718e3744 501
d62a17ae 502static void ospf6_disable(struct ospf6 *o)
718e3744 503{
d62a17ae 504 struct listnode *node, *nnode;
505 struct ospf6_area *oa;
506
507 if (!CHECK_FLAG(o->flag, OSPF6_DISABLED)) {
508 SET_FLAG(o->flag, OSPF6_DISABLED);
509
510 for (ALL_LIST_ELEMENTS(o->area_list, node, nnode, oa))
511 ospf6_area_disable(oa);
512
513 /* XXX: This also changes persistent settings */
a069482f
K
514 /* Unregister redistribution */
515 ospf6_asbr_redistribute_reset(o);
d62a17ae 516
517 ospf6_lsdb_remove_all(o->lsdb);
e285b70d
IR
518 ospf6_route_remove_all(o->route_table);
519 ospf6_route_remove_all(o->brouter_table);
d62a17ae 520
521 THREAD_OFF(o->maxage_remover);
522 THREAD_OFF(o->t_spf_calc);
523 THREAD_OFF(o->t_ase_calc);
856ae1eb 524 THREAD_OFF(o->t_distribute_update);
7df1f362 525 THREAD_OFF(o->t_ospf6_receive);
d62a17ae 526 }
508e53e2 527}
718e3744 528
beadc736 529void ospf6_master_init(struct thread_master *master)
78c6ba61
CS
530{
531 memset(&ospf6_master, 0, sizeof(struct ospf6_master));
532
533 om6 = &ospf6_master;
beadc736 534 om6->ospf6 = list_new();
535 om6->master = master;
78c6ba61
CS
536}
537
d62a17ae 538static int ospf6_maxage_remover(struct thread *thread)
508e53e2 539{
d62a17ae 540 struct ospf6 *o = (struct ospf6 *)THREAD_ARG(thread);
541 struct ospf6_area *oa;
542 struct ospf6_interface *oi;
543 struct ospf6_neighbor *on;
544 struct listnode *i, *j, *k;
545 int reschedule = 0;
546
547 o->maxage_remover = (struct thread *)NULL;
548
549 for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) {
550 for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) {
551 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, k, on)) {
552 if (on->state != OSPF6_NEIGHBOR_EXCHANGE
553 && on->state != OSPF6_NEIGHBOR_LOADING)
554 continue;
555
556 ospf6_maxage_remove(o);
557 return 0;
558 }
559 }
2449fcd6 560 }
d62a17ae 561
562 for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) {
563 for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) {
564 if (ospf6_lsdb_maxage_remover(oi->lsdb)) {
565 reschedule = 1;
566 }
567 }
568
569 if (ospf6_lsdb_maxage_remover(oa->lsdb)) {
570 reschedule = 1;
571 }
2449fcd6 572 }
2449fcd6 573
d62a17ae 574 if (ospf6_lsdb_maxage_remover(o->lsdb)) {
575 reschedule = 1;
576 }
2449fcd6 577
d62a17ae 578 if (reschedule) {
579 ospf6_maxage_remove(o);
580 }
508e53e2 581
d62a17ae 582 return 0;
718e3744 583}
584
d62a17ae 585void ospf6_maxage_remove(struct ospf6 *o)
718e3744 586{
d62a17ae 587 if (o)
588 thread_add_timer(master, ospf6_maxage_remover, o,
589 OSPF_LSA_MAXAGE_REMOVE_DELAY_DEFAULT,
590 &o->maxage_remover);
718e3744 591}
592
beadc736 593void ospf6_router_id_update(struct ospf6 *ospf6)
78c6ba61
CS
594{
595 if (!ospf6)
596 return;
597
598 if (ospf6->router_id_static != 0)
599 ospf6->router_id = ospf6->router_id_static;
600 else
601 ospf6->router_id = om6->zebra_router_id;
602}
603
508e53e2 604/* start ospf6 */
d48ef099 605DEFUN_NOSH(router_ospf6, router_ospf6_cmd, "router ospf6 [vrf NAME]",
606 ROUTER_STR OSPF6_STR VRF_CMD_HELP_STR)
718e3744 607{
beadc736 608 struct ospf6 *ospf6;
d48ef099 609 const char *vrf_name = VRF_DEFAULT_NAME;
610 int idx_vrf = 0;
beadc736 611
d48ef099 612 if (argv_find(argv, argc, "vrf", &idx_vrf)) {
613 vrf_name = argv[idx_vrf + 1]->arg;
614 }
615
616 ospf6 = ospf6_lookup_by_vrf_name(vrf_name);
7df1f362 617 if (ospf6 == NULL)
d48ef099 618 ospf6 = ospf6_instance_create(vrf_name);
7df1f362 619
d62a17ae 620 /* set current ospf point. */
621 VTY_PUSH_CONTEXT(OSPF6_NODE, ospf6);
508e53e2 622
d62a17ae 623 return CMD_SUCCESS;
718e3744 624}
625
508e53e2 626/* stop ospf6 */
d48ef099 627DEFUN(no_router_ospf6, no_router_ospf6_cmd, "no router ospf6 [vrf NAME]",
628 NO_STR ROUTER_STR OSPF6_STR VRF_CMD_HELP_STR)
718e3744 629{
beadc736 630 struct ospf6 *ospf6;
d48ef099 631 const char *vrf_name = VRF_DEFAULT_NAME;
632 int idx_vrf = 0;
beadc736 633
d48ef099 634 if (argv_find(argv, argc, "vrf", &idx_vrf)) {
635 vrf_name = argv[idx_vrf + 1]->arg;
636 }
637
638 ospf6 = ospf6_lookup_by_vrf_name(vrf_name);
d62a17ae 639 if (ospf6 == NULL)
640 vty_out(vty, "OSPFv3 is not configured\n");
641 else {
642 ospf6_delete(ospf6);
643 ospf6 = NULL;
644 }
34288970 645
d62a17ae 646 /* return to config node . */
647 VTY_PUSH_CONTEXT_NULL(CONFIG_NODE);
508e53e2 648
d62a17ae 649 return CMD_SUCCESS;
718e3744 650}
651
508e53e2 652/* change Router_ID commands. */
60466a63
QY
653DEFUN(ospf6_router_id,
654 ospf6_router_id_cmd,
655 "ospf6 router-id A.B.C.D",
656 OSPF6_STR
657 "Configure OSPF6 Router-ID\n"
658 V4NOTATION_STR)
718e3744 659{
d62a17ae 660 VTY_DECLVAR_CONTEXT(ospf6, o);
5d1a2ee8 661 int idx = 0;
d62a17ae 662 int ret;
5d1a2ee8 663 const char *router_id_str;
d7c0a89a 664 uint32_t router_id;
d6927cf3
CS
665 struct ospf6_area *oa;
666 struct listnode *node;
d62a17ae 667
5d1a2ee8
QY
668 argv_find(argv, argc, "A.B.C.D", &idx);
669 router_id_str = argv[idx]->arg;
670
671 ret = inet_pton(AF_INET, router_id_str, &router_id);
d62a17ae 672 if (ret == 0) {
60466a63 673 vty_out(vty, "malformed OSPF Router-ID: %s\n", router_id_str);
d62a17ae 674 return CMD_SUCCESS;
675 }
508e53e2 676
d62a17ae 677 o->router_id_static = router_id;
d6927cf3
CS
678
679 for (ALL_LIST_ELEMENTS_RO(o->area_list, node, oa)) {
680 if (oa->full_nbrs) {
681 vty_out(vty,
3efd0893 682 "For this router-id change to take effect, save config and restart ospf6d\n");
d6927cf3
CS
683 return CMD_SUCCESS;
684 }
685 }
686
687 o->router_id = router_id;
c8a440ec 688
d62a17ae 689 return CMD_SUCCESS;
718e3744 690}
691
60466a63
QY
692DEFUN(no_ospf6_router_id,
693 no_ospf6_router_id_cmd,
694 "no ospf6 router-id [A.B.C.D]",
695 NO_STR OSPF6_STR
696 "Configure OSPF6 Router-ID\n"
697 V4NOTATION_STR)
5d1a2ee8
QY
698{
699 VTY_DECLVAR_CONTEXT(ospf6, o);
d6927cf3
CS
700 struct ospf6_area *oa;
701 struct listnode *node;
702
5d1a2ee8 703 o->router_id_static = 0;
d6927cf3
CS
704
705 for (ALL_LIST_ELEMENTS_RO(o->area_list, node, oa)) {
706 if (oa->full_nbrs) {
707 vty_out(vty,
3efd0893 708 "For this router-id change to take effect, save config and restart ospf6d\n");
d6927cf3
CS
709 return CMD_SUCCESS;
710 }
711 }
5d1a2ee8 712 o->router_id = 0;
d6927cf3
CS
713 if (o->router_id_zebra.s_addr)
714 o->router_id = (uint32_t)o->router_id_zebra.s_addr;
5d1a2ee8
QY
715
716 return CMD_SUCCESS;
717}
718
3d35ca48
DD
719DEFUN (ospf6_log_adjacency_changes,
720 ospf6_log_adjacency_changes_cmd,
721 "log-adjacency-changes",
722 "Log changes in adjacency state\n")
723{
d62a17ae 724 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
3d35ca48 725
d62a17ae 726 SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
727 UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
728 return CMD_SUCCESS;
3d35ca48
DD
729}
730
731DEFUN (ospf6_log_adjacency_changes_detail,
732 ospf6_log_adjacency_changes_detail_cmd,
733 "log-adjacency-changes detail",
692c7954 734 "Log changes in adjacency state\n"
3d35ca48
DD
735 "Log all state changes\n")
736{
d62a17ae 737 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
3d35ca48 738
d62a17ae 739 SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
740 SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
741 return CMD_SUCCESS;
3d35ca48
DD
742}
743
744DEFUN (no_ospf6_log_adjacency_changes,
745 no_ospf6_log_adjacency_changes_cmd,
746 "no log-adjacency-changes",
692c7954 747 NO_STR
3d35ca48
DD
748 "Log changes in adjacency state\n")
749{
d62a17ae 750 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
3d35ca48 751
d62a17ae 752 UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
753 UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
754 return CMD_SUCCESS;
3d35ca48
DD
755}
756
757DEFUN (no_ospf6_log_adjacency_changes_detail,
758 no_ospf6_log_adjacency_changes_detail_cmd,
759 "no log-adjacency-changes detail",
692c7954
DW
760 NO_STR
761 "Log changes in adjacency state\n"
3d35ca48
DD
762 "Log all state changes\n")
763{
d62a17ae 764 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
3d35ca48 765
d62a17ae 766 UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
767 return CMD_SUCCESS;
3d35ca48
DD
768}
769
b6927875
DS
770DEFUN (ospf6_timers_lsa,
771 ospf6_timers_lsa_cmd,
6147e2c6 772 "timers lsa min-arrival (0-600000)",
b6927875
DS
773 "Adjust routing timers\n"
774 "OSPF6 LSA timers\n"
775 "Minimum delay in receiving new version of a LSA\n"
776 "Delay in milliseconds\n")
777{
d62a17ae 778 VTY_DECLVAR_CONTEXT(ospf6, ospf);
779 int idx_number = 3;
780 unsigned int minarrival;
b6927875 781
d62a17ae 782 minarrival = strtoul(argv[idx_number]->arg, NULL, 10);
783 ospf->lsa_minarrival = minarrival;
b6927875 784
d62a17ae 785 return CMD_SUCCESS;
b6927875
DS
786}
787
788DEFUN (no_ospf6_timers_lsa,
789 no_ospf6_timers_lsa_cmd,
1d68dbfe 790 "no timers lsa min-arrival [(0-600000)]",
b6927875
DS
791 NO_STR
792 "Adjust routing timers\n"
793 "OSPF6 LSA timers\n"
3a2d747c
QY
794 "Minimum delay in receiving new version of a LSA\n"
795 "Delay in milliseconds\n")
b6927875 796{
d62a17ae 797 VTY_DECLVAR_CONTEXT(ospf6, ospf);
798 int idx_number = 4;
799 unsigned int minarrival;
b6927875 800
d62a17ae 801 if (argc == 5) {
802 minarrival = strtoul(argv[idx_number]->arg, NULL, 10);
b6927875 803
d62a17ae 804 if (ospf->lsa_minarrival != minarrival
805 || minarrival == OSPF_MIN_LS_ARRIVAL)
806 return CMD_SUCCESS;
807 }
b6927875 808
d62a17ae 809 ospf->lsa_minarrival = OSPF_MIN_LS_ARRIVAL;
b6927875 810
d62a17ae 811 return CMD_SUCCESS;
b6927875
DS
812}
813
b6927875 814
baff583e
MZ
815DEFUN (ospf6_distance,
816 ospf6_distance_cmd,
39e92c06 817 "distance (1-255)",
baff583e
MZ
818 "Administrative distance\n"
819 "OSPF6 Administrative distance\n")
820{
d62a17ae 821 VTY_DECLVAR_CONTEXT(ospf6, o);
baff583e 822
d62a17ae 823 o->distance_all = atoi(argv[1]->arg);
baff583e 824
d62a17ae 825 return CMD_SUCCESS;
baff583e
MZ
826}
827
828DEFUN (no_ospf6_distance,
829 no_ospf6_distance_cmd,
39e92c06 830 "no distance (1-255)",
baff583e
MZ
831 NO_STR
832 "Administrative distance\n"
833 "OSPF6 Administrative distance\n")
834{
d62a17ae 835 VTY_DECLVAR_CONTEXT(ospf6, o);
baff583e 836
d62a17ae 837 o->distance_all = 0;
baff583e 838
d62a17ae 839 return CMD_SUCCESS;
baff583e
MZ
840}
841
842DEFUN (ospf6_distance_ospf6,
843 ospf6_distance_ospf6_cmd,
eaa1ae0d 844 "distance ospf6 {intra-area (1-255)|inter-area (1-255)|external (1-255)}",
baff583e 845 "Administrative distance\n"
eaa1ae0d 846 "OSPF6 administrative distance\n"
39e92c06
QY
847 "Intra-area routes\n"
848 "Distance for intra-area routes\n"
849 "Inter-area routes\n"
850 "Distance for inter-area routes\n"
851 "External routes\n"
baff583e
MZ
852 "Distance for external routes\n")
853{
d62a17ae 854 VTY_DECLVAR_CONTEXT(ospf6, o);
855 int idx = 0;
856
f89a449b
CS
857 o->distance_intra = 0;
858 o->distance_inter = 0;
859 o->distance_external = 0;
860
d62a17ae 861 if (argv_find(argv, argc, "intra-area", &idx))
862 o->distance_intra = atoi(argv[idx + 1]->arg);
863 idx = 0;
864 if (argv_find(argv, argc, "inter-area", &idx))
865 o->distance_inter = atoi(argv[idx + 1]->arg);
866 idx = 0;
867 if (argv_find(argv, argc, "external", &idx))
868 o->distance_external = atoi(argv[idx + 1]->arg);
39e92c06 869
d62a17ae 870 return CMD_SUCCESS;
baff583e
MZ
871}
872
873DEFUN (no_ospf6_distance_ospf6,
874 no_ospf6_distance_ospf6_cmd,
eaa1ae0d 875 "no distance ospf6 [{intra-area [(1-255)]|inter-area [(1-255)]|external [(1-255)]}]",
baff583e
MZ
876 NO_STR
877 "Administrative distance\n"
878 "OSPF6 distance\n"
879 "Intra-area routes\n"
880 "Distance for intra-area routes\n"
881 "Inter-area routes\n"
882 "Distance for inter-area routes\n"
883 "External routes\n"
884 "Distance for external routes\n")
885{
d62a17ae 886 VTY_DECLVAR_CONTEXT(ospf6, o);
887 int idx = 0;
baff583e 888
d62a17ae 889 if (argv_find(argv, argc, "intra-area", &idx) || argc == 3)
890 idx = o->distance_intra = 0;
891 if (argv_find(argv, argc, "inter-area", &idx) || argc == 3)
892 idx = o->distance_inter = 0;
893 if (argv_find(argv, argc, "external", &idx) || argc == 3)
894 o->distance_external = 0;
baff583e 895
d62a17ae 896 return CMD_SUCCESS;
baff583e
MZ
897}
898
42cabc55 899DEFUN_HIDDEN (ospf6_interface_area,
508e53e2 900 ospf6_interface_area_cmd,
de842255 901 "interface IFNAME area <A.B.C.D|(0-4294967295)>",
508e53e2 902 "Enable routing on an IPv6 interface\n"
903 IFNAME_STR
904 "Specify the OSPF6 area ID\n"
905 "OSPF6 area ID in IPv4 address notation\n"
de842255 906 "OSPF6 area ID in decimal notation\n"
508e53e2 907 )
718e3744 908{
d48ef099 909 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
d62a17ae 910 int idx_ifname = 1;
911 int idx_ipv4 = 3;
912 struct ospf6_area *oa;
913 struct ospf6_interface *oi;
914 struct interface *ifp;
d48ef099 915 vrf_id_t vrf_id = VRF_DEFAULT;
f85b7619 916 int ipv6_count = 0;
42cabc55
IR
917 uint32_t area_id;
918 int format;
919
920 vty_out(vty,
921 "This command is deprecated, because it is not VRF-aware.\n");
922 vty_out(vty,
923 "Please, use \"ipv6 ospf6 area\" on an interface instead.\n");
d62a17ae 924
d48ef099 925 if (ospf6->vrf_id != VRF_UNKNOWN)
926 vrf_id = ospf6->vrf_id;
beadc736 927
d62a17ae 928 /* find/create ospf6 interface */
d48ef099 929 ifp = if_get_by_name(argv[idx_ifname]->arg, vrf_id);
d62a17ae 930 oi = (struct ospf6_interface *)ifp->info;
931 if (oi == NULL)
932 oi = ospf6_interface_create(ifp);
933 if (oi->area) {
934 vty_out(vty, "%s already attached to Area %s\n",
935 oi->interface->name, oi->area->name);
936 return CMD_SUCCESS;
937 }
6452df09 938
f85b7619 939 /* if more than OSPF6_MAX_IF_ADDRS are configured on this interface
940 * then don't allow ospfv3 to be configured
941 */
942 ipv6_count = connected_count_by_family(ifp, AF_INET6);
943 if (oi->ifmtu == OSPF6_DEFAULT_MTU && ipv6_count > OSPF6_MAX_IF_ADDRS) {
944 vty_out(vty,
945 "can not configure OSPFv3 on if %s, must have less than %d interface addresses but has %d addresses\n",
946 ifp->name, OSPF6_MAX_IF_ADDRS, ipv6_count);
947 return CMD_WARNING_CONFIG_FAILED;
948 } else if (oi->ifmtu >= OSPF6_JUMBO_MTU
949 && ipv6_count > OSPF6_MAX_IF_ADDRS_JUMBO) {
950 vty_out(vty,
951 "can not configure OSPFv3 on if %s, must have less than %d interface addresses but has %d addresses\n",
952 ifp->name, OSPF6_MAX_IF_ADDRS_JUMBO, ipv6_count);
953 return CMD_WARNING_CONFIG_FAILED;
954 }
955
42cabc55
IR
956 if (str2area_id(argv[idx_ipv4]->arg, &area_id, &format)) {
957 vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4]->arg);
958 return CMD_WARNING_CONFIG_FAILED;
959 }
960
961 oi->area_id = area_id;
962 oi->area_id_format = format;
963
964 oa = ospf6_area_lookup(area_id, ospf6);
965 if (oa == NULL)
966 oa = ospf6_area_create(area_id, ospf6, format);
d62a17ae 967
968 /* attach interface to area */
969 listnode_add(oa->if_list, oi); /* sort ?? */
970 oi->area = oa;
971
972 SET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
973
974 /* ospf6 process is currently disabled, not much more to do */
beadc736 975 if (CHECK_FLAG(ospf6->flag, OSPF6_DISABLED))
d62a17ae 976 return CMD_SUCCESS;
977
978 /* start up */
979 ospf6_interface_enable(oi);
980
981 /* If the router is ABR, originate summary routes */
95b3f03d 982 if (ospf6_check_and_set_router_abr(ospf6)) {
d62a17ae 983 ospf6_abr_enable_area(oa);
ad500b22
K
984 ospf6_schedule_abr_task(oa->ospf6);
985 }
d62a17ae 986
987 return CMD_SUCCESS;
718e3744 988}
989
42cabc55 990DEFUN_HIDDEN (no_ospf6_interface_area,
508e53e2 991 no_ospf6_interface_area_cmd,
de842255 992 "no interface IFNAME area <A.B.C.D|(0-4294967295)>",
508e53e2 993 NO_STR
994 "Disable routing on an IPv6 interface\n"
995 IFNAME_STR
996 "Specify the OSPF6 area ID\n"
997 "OSPF6 area ID in IPv4 address notation\n"
de842255 998 "OSPF6 area ID in decimal notation\n"
508e53e2 999 )
718e3744 1000{
d48ef099 1001 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
d62a17ae 1002 int idx_ifname = 2;
1003 int idx_ipv4 = 4;
1004 struct ospf6_interface *oi;
1005 struct ospf6_area *oa;
1006 struct interface *ifp;
d7c0a89a 1007 uint32_t area_id;
d48ef099 1008 vrf_id_t vrf_id = VRF_DEFAULT;
1009
42cabc55
IR
1010 vty_out(vty,
1011 "This command is deprecated, because it is not VRF-aware.\n");
1012 vty_out(vty,
1013 "Please, use \"no ipv6 ospf6 area\" on an interface instead.\n");
1014
d48ef099 1015 if (ospf6->vrf_id != VRF_UNKNOWN)
1016 vrf_id = ospf6->vrf_id;
1017
1018 /* find/create ospf6 interface */
1019 ifp = if_get_by_name(argv[idx_ifname]->arg, vrf_id);
d62a17ae 1020
d62a17ae 1021 if (ifp == NULL) {
1022 vty_out(vty, "No such interface %s\n", argv[idx_ifname]->arg);
1023 return CMD_SUCCESS;
1024 }
6452df09 1025
d62a17ae 1026 oi = (struct ospf6_interface *)ifp->info;
1027 if (oi == NULL) {
1028 vty_out(vty, "Interface %s not enabled\n", ifp->name);
1029 return CMD_SUCCESS;
1030 }
1031
1032 /* parse Area-ID */
de842255
PR
1033 if (inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id) != 1)
1034 area_id = htonl(strtoul(argv[idx_ipv4]->arg, NULL, 10));
d62a17ae 1035
1036 /* Verify Area */
1037 if (oi->area == NULL) {
800cc918 1038 vty_out(vty, "%s not attached to area %s\n",
f85a4112 1039 oi->interface->name, argv[idx_ipv4]->arg);
d62a17ae 1040 return CMD_SUCCESS;
1041 }
1042
1043 if (oi->area->area_id != area_id) {
1044 vty_out(vty, "Wrong Area-ID: %s is attached to area %s\n",
1045 oi->interface->name, oi->area->name);
1046 return CMD_SUCCESS;
1047 }
1048
4a30f056 1049 ospf6_interface_disable(oi);
d62a17ae 1050
1051 oa = oi->area;
1052 listnode_delete(oi->area->if_list, oi);
1053 oi->area = (struct ospf6_area *)NULL;
1054
1055 /* Withdraw inter-area routes from this area, if necessary */
1056 if (oa->if_list->count == 0) {
1057 UNSET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
1058 ospf6_abr_disable_area(oa);
1059 }
1060
42cabc55
IR
1061 oi->area_id = 0;
1062 oi->area_id_format = OSPF6_AREA_FMT_UNSET;
1063
d62a17ae 1064 return CMD_SUCCESS;
718e3744 1065}
1066
f41b4a02
DD
1067DEFUN (ospf6_stub_router_admin,
1068 ospf6_stub_router_admin_cmd,
1069 "stub-router administrative",
1070 "Make router a stub router\n"
f41b4a02
DD
1071 "Administratively applied, for an indefinite period\n")
1072{
d62a17ae 1073 struct listnode *node;
1074 struct ospf6_area *oa;
1075
beadc736 1076 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1077
d62a17ae 1078 if (!CHECK_FLAG(ospf6->flag, OSPF6_STUB_ROUTER)) {
1079 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
1080 OSPF6_OPT_CLEAR(oa->options, OSPF6_OPT_V6);
1081 OSPF6_OPT_CLEAR(oa->options, OSPF6_OPT_R);
1082 OSPF6_ROUTER_LSA_SCHEDULE(oa);
1083 }
1084 SET_FLAG(ospf6->flag, OSPF6_STUB_ROUTER);
f41b4a02 1085 }
f41b4a02 1086
d62a17ae 1087 return CMD_SUCCESS;
f41b4a02
DD
1088}
1089
1090DEFUN (no_ospf6_stub_router_admin,
1091 no_ospf6_stub_router_admin_cmd,
1092 "no stub-router administrative",
1093 NO_STR
1094 "Make router a stub router\n"
f41b4a02
DD
1095 "Administratively applied, for an indefinite period\n")
1096{
d62a17ae 1097 struct listnode *node;
1098 struct ospf6_area *oa;
1099
beadc736 1100 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
d62a17ae 1101 if (CHECK_FLAG(ospf6->flag, OSPF6_STUB_ROUTER)) {
1102 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
1103 OSPF6_OPT_SET(oa->options, OSPF6_OPT_V6);
1104 OSPF6_OPT_SET(oa->options, OSPF6_OPT_R);
1105 OSPF6_ROUTER_LSA_SCHEDULE(oa);
1106 }
1107 UNSET_FLAG(ospf6->flag, OSPF6_STUB_ROUTER);
f41b4a02 1108 }
f41b4a02 1109
d62a17ae 1110 return CMD_SUCCESS;
f41b4a02
DD
1111}
1112
1958143e
MR
1113/* Restart OSPF SPF algorithm*/
1114static void ospf6_restart_spf(struct ospf6 *ospf6)
1115{
1116 ospf6_route_remove_all(ospf6->route_table);
1117 ospf6_route_remove_all(ospf6->brouter_table);
1958143e
MR
1118
1119 /* Trigger SPF */
1120 ospf6_spf_schedule(ospf6, OSPF6_SPF_FLAGS_CONFIG_CHANGE);
1121}
1122
1123/* Set the max paths */
1124static void ospf6_maxpath_set(struct ospf6 *ospf6, uint16_t paths)
1125{
1126 if (ospf6->max_multipath == paths)
1127 return;
1128
1129 ospf6->max_multipath = paths;
1130
1131 /* Send deletion to zebra to delete all
1132 * ospf specific routes and reinitiate
1133 * SPF to reflect the new max multipath.
1134 */
1135 ospf6_restart_spf(ospf6);
1136}
1137
1138/* Ospf Maximum-paths config support */
1139DEFUN(ospf6_max_multipath,
1140 ospf6_max_multipath_cmd,
1141 "maximum-paths " CMD_RANGE_STR(1, MULTIPATH_NUM),
1142 "Max no of multiple paths for ECMP support\n"
1143 "Number of paths\n")
1144{
1145 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1146 int idx_number = 1;
1147 int maximum_paths = strtol(argv[idx_number]->arg, NULL, 10);
1148
1149 ospf6_maxpath_set(ospf6, maximum_paths);
1150
1151 return CMD_SUCCESS;
1152}
1153
1154DEFUN(no_ospf6_max_multipath,
1155 no_ospf6_max_multipath_cmd,
1156 "no maximum-paths [" CMD_RANGE_STR(1, MULTIPATH_NUM)"]",
1157 NO_STR
1158 "Max no of multiple paths for ECMP support\n"
1159 "Number of paths\n")
1160{
1161 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1162
1163 ospf6_maxpath_set(ospf6, MULTIPATH_NUM);
1164
1165 return CMD_SUCCESS;
1166}
1167
35a45dea 1168static void ospf6_show(struct vty *vty, struct ospf6 *o, json_object *json,
1169 bool use_json)
718e3744 1170{
d62a17ae 1171 struct listnode *n;
1172 struct ospf6_area *oa;
1173 char router_id[16], duration[32];
1174 struct timeval now, running, result;
1175 char buf[32], rbuf[32];
35a45dea 1176 json_object *json_areas = NULL;
1177 const char *adjacency;
1178
1179 if (use_json) {
1180 json_areas = json_object_new_object();
1181
1182 /* process id, router id */
1183 inet_ntop(AF_INET, &o->router_id, router_id, sizeof(router_id));
1184 json_object_string_add(json, "routerId", router_id);
1185
1186 /* running time */
1187 monotime(&now);
1188 timersub(&now, &o->starttime, &running);
1189 timerstring(&running, duration, sizeof(duration));
1190 json_object_string_add(json, "running", duration);
1191
1192 /* Redistribute configuration */
1193 /* XXX */
1194 json_object_int_add(json, "lsaMinimumArrivalMsecs",
1195 o->lsa_minarrival);
1196
1197 /* Show SPF parameters */
1198 json_object_int_add(json, "spfScheduleDelayMsecs",
1199 o->spf_delay);
1200 json_object_int_add(json, "holdTimeMinMsecs", o->spf_holdtime);
1201 json_object_int_add(json, "holdTimeMaxMsecs",
1202 o->spf_max_holdtime);
1203 json_object_int_add(json, "holdTimeMultiplier",
1204 o->spf_hold_multiplier);
1205
1958143e 1206 json_object_int_add(json, "maximumPaths", o->max_multipath);
35a45dea 1207
1208 if (o->ts_spf.tv_sec || o->ts_spf.tv_usec) {
1209 timersub(&now, &o->ts_spf, &result);
1210 timerstring(&result, buf, sizeof(buf));
1211 ospf6_spf_reason_string(o->last_spf_reason, rbuf,
1212 sizeof(rbuf));
1213 json_object_boolean_true_add(json, "spfHasRun");
1214 json_object_string_add(json, "spfLastExecutedMsecs",
1215 buf);
1216 json_object_string_add(json, "spfLastExecutedReason",
1217 rbuf);
1218
1219 json_object_int_add(
1220 json, "spfLastDurationSecs",
1221 (long long)o->ts_spf_duration.tv_sec);
1222
1223 json_object_int_add(
1224 json, "spfLastDurationMsecs",
1225 (long long)o->ts_spf_duration.tv_usec);
1226 } else
1227 json_object_boolean_false_add(json, "spfHasRun");
1228
1229
1230 threadtimer_string(now, o->t_spf_calc, buf, sizeof(buf));
1231 if (o->t_spf_calc) {
1232 long time_store;
1233
1234 json_object_boolean_true_add(json, "spfTimerActive");
1235 time_store =
1236 monotime_until(&o->t_spf_calc->u.sands, NULL)
1237 / 1000LL;
1238 json_object_int_add(json, "spfTimerDueInMsecs",
1239 time_store);
1240 } else
1241 json_object_boolean_false_add(json, "spfTimerActive");
1242
1243 json_object_boolean_add(json, "routerIsStubRouter",
1244 CHECK_FLAG(o->flag, OSPF6_STUB_ROUTER));
1245
1246 /* LSAs */
1247 json_object_int_add(json, "numberOfAsScopedLsa",
1248 o->lsdb->count);
1249 /* Areas */
1250 json_object_int_add(json, "numberOfAreaInRouter",
1251 listcount(o->area_list));
1252
1253 if (CHECK_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES)) {
1254 if (CHECK_FLAG(o->config_flags,
1255 OSPF6_LOG_ADJACENCY_DETAIL))
1256 adjacency = "LoggedAll";
1257 else
1258 adjacency = "Logged";
1259 } else
1260 adjacency = "NotLogged";
1261 json_object_string_add(json, "adjacencyChanges", adjacency);
1262
1263 for (ALL_LIST_ELEMENTS_RO(o->area_list, n, oa))
1264 ospf6_area_show(vty, oa, json_areas, use_json);
1265
1266 json_object_object_add(json, "areas", json_areas);
1267
1268 vty_out(vty, "%s\n",
1269 json_object_to_json_string_ext(
1270 json, JSON_C_TO_STRING_PRETTY));
1271
1272 } else {
1273 /* process id, router id */
1274 inet_ntop(AF_INET, &o->router_id, router_id, sizeof(router_id));
1275 vty_out(vty, " OSPFv3 Routing Process (0) with Router-ID %s\n",
1276 router_id);
1277
1278 /* running time */
1279 monotime(&now);
1280 timersub(&now, &o->starttime, &running);
1281 timerstring(&running, duration, sizeof(duration));
1282 vty_out(vty, " Running %s\n", duration);
1283
1284 /* Redistribute configuration */
1285 /* XXX */
1286 vty_out(vty, " LSA minimum arrival %d msecs\n",
1287 o->lsa_minarrival);
1288
1958143e 1289 vty_out(vty, " Maximum-paths %u\n", o->max_multipath);
35a45dea 1290
1291 /* Show SPF parameters */
1292 vty_out(vty,
1293 " Initial SPF scheduling delay %d millisec(s)\n"
1294 " Minimum hold time between consecutive SPFs %d millsecond(s)\n"
1295 " Maximum hold time between consecutive SPFs %d millsecond(s)\n"
1296 " Hold time multiplier is currently %d\n",
1297 o->spf_delay, o->spf_holdtime, o->spf_max_holdtime,
1298 o->spf_hold_multiplier);
1299
1300
1301 vty_out(vty, " SPF algorithm ");
1302 if (o->ts_spf.tv_sec || o->ts_spf.tv_usec) {
1303 timersub(&now, &o->ts_spf, &result);
1304 timerstring(&result, buf, sizeof(buf));
1305 ospf6_spf_reason_string(o->last_spf_reason, rbuf,
1306 sizeof(rbuf));
1307 vty_out(vty, "last executed %s ago, reason %s\n", buf,
1308 rbuf);
1309 vty_out(vty, " Last SPF duration %lld sec %lld usec\n",
1310 (long long)o->ts_spf_duration.tv_sec,
1311 (long long)o->ts_spf_duration.tv_usec);
1312 } else
1313 vty_out(vty, "has not been run\n");
1314
1315 threadtimer_string(now, o->t_spf_calc, buf, sizeof(buf));
1316 vty_out(vty, " SPF timer %s%s\n",
1317 (o->t_spf_calc ? "due in " : "is "), buf);
1318
1319 if (CHECK_FLAG(o->flag, OSPF6_STUB_ROUTER))
1320 vty_out(vty, " Router Is Stub Router\n");
1321
1322 /* LSAs */
1323 vty_out(vty, " Number of AS scoped LSAs is %u\n",
1324 o->lsdb->count);
1325
1326 /* Areas */
1327 vty_out(vty, " Number of areas in this router is %u\n",
1328 listcount(o->area_list));
1329
1330 if (CHECK_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES)) {
1331 if (CHECK_FLAG(o->config_flags,
1332 OSPF6_LOG_ADJACENCY_DETAIL))
1333 vty_out(vty,
1334 " All adjacency changes are logged\n");
1335 else
1336 vty_out(vty, " Adjacency changes are logged\n");
1337 }
d62a17ae 1338
d62a17ae 1339
35a45dea 1340 vty_out(vty, "\n");
d62a17ae 1341
35a45dea 1342 for (ALL_LIST_ELEMENTS_RO(o->area_list, n, oa))
1343 ospf6_area_show(vty, oa, json_areas, use_json);
1344 }
718e3744 1345}
1346
dd7fb1db
PG
1347DEFUN(show_ipv6_ospf6_vrfs, show_ipv6_ospf6_vrfs_cmd,
1348 "show ipv6 ospf6 vrfs [json]",
1349 SHOW_STR IP6_STR OSPF6_STR "Show OSPF6 VRFs \n" JSON_STR)
1350{
1351 bool uj = use_json(argc, argv);
1352 json_object *json = NULL;
1353 json_object *json_vrfs = NULL;
1354 struct ospf6 *ospf6 = NULL;
1355 struct listnode *node = NULL;
1356 int count = 0;
1357 char buf[PREFIX_STRLEN];
1358 static const char header[] =
1359 "Name Id RouterId ";
1360
1361 if (uj) {
1362 json = json_object_new_object();
1363 json_vrfs = json_object_new_object();
1364 }
1365
1366 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1367 json_object *json_vrf = NULL;
1368 const char *name = NULL;
1369 int64_t vrf_id_ui = 0;
1370 struct in_addr router_id;
1371
1372 router_id.s_addr = ospf6->router_id;
1373 count++;
1374
1375 if (!uj && count == 1)
1376 vty_out(vty, "%s\n", header);
1377 if (uj)
1378 json_vrf = json_object_new_object();
1379
1380 if (ospf6->vrf_id == VRF_DEFAULT)
1381 name = VRF_DEFAULT_NAME;
1382 else
1383 name = ospf6->name;
1384
1385 vrf_id_ui = (ospf6->vrf_id == VRF_UNKNOWN)
1386 ? -1
1387 : (int64_t)ospf6->vrf_id;
1388
1389 if (uj) {
1390 json_object_int_add(json_vrf, "vrfId", vrf_id_ui);
1391 json_object_string_add(json_vrf, "routerId",
1392 inet_ntop(AF_INET, &router_id,
1393 buf, sizeof(buf)));
1394 json_object_object_add(json_vrfs, name, json_vrf);
1395
1396 } else {
1397 vty_out(vty, "%-25s %-5d %-16s \n", name,
1398 ospf6->vrf_id,
1399 inet_ntop(AF_INET, &router_id, buf,
1400 sizeof(buf)));
1401 }
1402 }
1403
1404 if (uj) {
1405 json_object_object_add(json, "vrfs", json_vrfs);
1406 json_object_int_add(json, "totalVrfs", count);
1407
1408 vty_out(vty, "%s\n",
1409 json_object_to_json_string_ext(
1410 json, JSON_C_TO_STRING_PRETTY));
1411 json_object_free(json);
1412 } else {
1413 if (count)
1414 vty_out(vty, "\nTotal number of OSPF VRFs: %d\n",
1415 count);
1416 }
1417
1418 return CMD_SUCCESS;
1419}
1420
508e53e2 1421/* show top level structures */
d48ef099 1422DEFUN(show_ipv6_ospf6, show_ipv6_ospf6_cmd,
1423 "show ipv6 ospf6 [vrf <NAME|all>] [json]",
1424 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR "All VRFs\n" JSON_STR)
718e3744 1425{
beadc736 1426 struct ospf6 *ospf6;
d48ef099 1427 struct listnode *node;
1428 const char *vrf_name = NULL;
1429 bool all_vrf = false;
1430 int idx_vrf = 0;
1431
35a45dea 1432 bool uj = use_json(argc, argv);
1433 json_object *json = NULL;
508e53e2 1434
d48ef099 1435 OSPF6_CMD_CHECK_RUNNING();
1436 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
35a45dea 1437
d48ef099 1438 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1439 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1440 if (uj)
1441 json = json_object_new_object();
1442 ospf6_show(vty, ospf6, json, uj);
35a45dea 1443
d48ef099 1444 if (!all_vrf)
1445 break;
1446 }
1447 }
35a45dea 1448
1449 if (uj)
1450 json_object_free(json);
d48ef099 1451
d62a17ae 1452 return CMD_SUCCESS;
718e3744 1453}
1454
d48ef099 1455DEFUN(show_ipv6_ospf6_route, show_ipv6_ospf6_route_cmd,
1456 "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]",
1457 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1458 "All VRFs\n" ROUTE_STR
1459 "Display Intra-Area routes\n"
1460 "Display Inter-Area routes\n"
1461 "Display Type-1 External routes\n"
1462 "Display Type-2 External routes\n"
1463 "Specify IPv6 address\n"
1464 "Specify IPv6 prefix\n"
1465 "Detailed information\n"
1466 "Summary of route table\n" JSON_STR)
718e3744 1467{
beadc736 1468 struct ospf6 *ospf6;
d48ef099 1469 struct listnode *node;
1470 const char *vrf_name = NULL;
1471 bool all_vrf = false;
1472 int idx_vrf = 0;
1473 int idx_arg_start = 4;
eacd0828 1474 bool uj = use_json(argc, argv);
beadc736 1475
d48ef099 1476 OSPF6_CMD_CHECK_RUNNING();
1477 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1478 if (idx_vrf > 0)
1479 idx_arg_start += 2;
1480
1481 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1482 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1483 ospf6_route_table_show(vty, idx_arg_start, argc, argv,
1484 ospf6->route_table, uj);
1485
1486 if (!all_vrf)
1487 break;
1488 }
1489 }
b52a8a52 1490
d62a17ae 1491 return CMD_SUCCESS;
718e3744 1492}
1493
d48ef099 1494DEFUN(show_ipv6_ospf6_route_match, show_ipv6_ospf6_route_match_cmd,
1495 "show ipv6 ospf6 [vrf <NAME|all>] route X:X::X:X/M <match|longer> [json]",
1496 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1497 "All VRFs\n" ROUTE_STR
1498 "Specify IPv6 prefix\n"
1499 "Display routes which match the specified route\n"
1500 "Display routes longer than the specified route\n" JSON_STR)
718e3744 1501{
beadc736 1502 struct ospf6 *ospf6;
d48ef099 1503 struct listnode *node;
1504 const char *vrf_name = NULL;
1505 bool all_vrf = false;
1506 int idx_vrf = 0;
1507 int idx_start_arg = 4;
eacd0828 1508 bool uj = use_json(argc, argv);
beadc736 1509
d48ef099 1510 OSPF6_CMD_CHECK_RUNNING();
1511 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1512 if (idx_vrf > 0)
1513 idx_start_arg += 2;
1514
1515 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1516 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1517 ospf6_route_table_show(vty, idx_start_arg, argc, argv,
1518 ospf6->route_table, uj);
1519
1520 if (!all_vrf)
1521 break;
1522 }
1523 }
b52a8a52 1524
d62a17ae 1525 return CMD_SUCCESS;
718e3744 1526}
1527
d48ef099 1528DEFUN(show_ipv6_ospf6_route_match_detail,
1529 show_ipv6_ospf6_route_match_detail_cmd,
1530 "show ipv6 ospf6 [vrf <NAME|all>] route X:X::X:X/M match detail [json]",
1531 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1532 "All VRFs\n" ROUTE_STR
1533 "Specify IPv6 prefix\n"
1534 "Display routes which match the specified route\n"
1535 "Detailed information\n" JSON_STR)
508e53e2 1536{
beadc736 1537 struct ospf6 *ospf6;
d48ef099 1538 struct listnode *node;
1539 const char *vrf_name = NULL;
1540 bool all_vrf = false;
1541 int idx_vrf = 0;
1542 int idx_start_arg = 4;
eacd0828 1543 bool uj = use_json(argc, argv);
beadc736 1544
d48ef099 1545 OSPF6_CMD_CHECK_RUNNING();
1546 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1547 if (idx_vrf > 0)
1548 idx_start_arg += 2;
1549
1550 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1551 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1552 ospf6_route_table_show(vty, idx_start_arg, argc, argv,
1553 ospf6->route_table, uj);
1554
1555 if (!all_vrf)
1556 break;
1557 }
1558 }
b52a8a52 1559
d62a17ae 1560 return CMD_SUCCESS;
508e53e2 1561}
718e3744 1562
d48ef099 1563DEFUN(show_ipv6_ospf6_route_type_detail, show_ipv6_ospf6_route_type_detail_cmd,
1564 "show ipv6 ospf6 [vrf <NAME|all>] route <intra-area|inter-area|external-1|external-2> detail [json]",
1565 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1566 "All VRFs\n" ROUTE_STR
1567 "Display Intra-Area routes\n"
1568 "Display Inter-Area routes\n"
1569 "Display Type-1 External routes\n"
1570 "Display Type-2 External routes\n"
1571 "Detailed information\n" JSON_STR)
4846ef64 1572{
beadc736 1573 struct ospf6 *ospf6;
d48ef099 1574 struct listnode *node;
1575 const char *vrf_name = NULL;
1576 bool all_vrf = false;
1577 int idx_vrf = 0;
1578 int idx_start_arg = 4;
eacd0828 1579 bool uj = use_json(argc, argv);
beadc736 1580
d48ef099 1581 OSPF6_CMD_CHECK_RUNNING();
1582 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1583 if (idx_vrf > 0)
1584 idx_start_arg += 2;
1585
1586 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1587 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1588 ospf6_route_table_show(vty, idx_start_arg, argc, argv,
1589 ospf6->route_table, uj);
1590
1591 if (!all_vrf)
1592 break;
1593 }
1594 }
b52a8a52 1595
d62a17ae 1596 return CMD_SUCCESS;
4846ef64 1597}
718e3744 1598
beadc736 1599static void ospf6_stub_router_config_write(struct vty *vty, struct ospf6 *ospf6)
f41b4a02 1600{
d62a17ae 1601 if (CHECK_FLAG(ospf6->flag, OSPF6_STUB_ROUTER)) {
1602 vty_out(vty, " stub-router administrative\n");
1603 }
1604 return;
f41b4a02
DD
1605}
1606
beadc736 1607static int ospf6_distance_config_write(struct vty *vty, struct ospf6 *ospf6)
baff583e 1608{
d62a17ae 1609 struct route_node *rn;
1610 struct ospf6_distance *odistance;
1611
1612 if (ospf6->distance_all)
1613 vty_out(vty, " distance %u\n", ospf6->distance_all);
1614
1615 if (ospf6->distance_intra || ospf6->distance_inter
1616 || ospf6->distance_external) {
1617 vty_out(vty, " distance ospf6");
1618
1619 if (ospf6->distance_intra)
1620 vty_out(vty, " intra-area %u", ospf6->distance_intra);
1621 if (ospf6->distance_inter)
1622 vty_out(vty, " inter-area %u", ospf6->distance_inter);
1623 if (ospf6->distance_external)
1624 vty_out(vty, " external %u", ospf6->distance_external);
1625
1626 vty_out(vty, "\n");
1627 }
1628
1629 for (rn = route_top(ospf6->distance_table); rn; rn = route_next(rn))
2dbe669b
DA
1630 if ((odistance = rn->info) != NULL)
1631 vty_out(vty, " distance %u %pFX %s\n",
1632 odistance->distance, &rn->p,
d62a17ae 1633 odistance->access_list ? odistance->access_list
1634 : "");
d62a17ae 1635 return 0;
baff583e
MZ
1636}
1637
508e53e2 1638/* OSPF configuration write function. */
d62a17ae 1639static int config_write_ospf6(struct vty *vty)
508e53e2 1640{
beadc736 1641 struct ospf6 *ospf6;
1642 struct listnode *node, *nnode;
d62a17ae 1643
1644 /* OSPFv3 configuration. */
beadc736 1645 if (om6 == NULL)
d62a17ae 1646 return CMD_SUCCESS;
1647
beadc736 1648 for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6)) {
d48ef099 1649 if (ospf6->name && strcmp(ospf6->name, VRF_DEFAULT_NAME))
1650 vty_out(vty, "router ospf6 vrf %s\n", ospf6->name);
1651 else
1652 vty_out(vty, "router ospf6\n");
1653
beadc736 1654 if (ospf6->router_id_static != 0)
1655 vty_out(vty, " ospf6 router-id %pI4\n",
1656 &ospf6->router_id_static);
1657
1658 /* log-adjacency-changes flag print. */
1659 if (CHECK_FLAG(ospf6->config_flags,
1660 OSPF6_LOG_ADJACENCY_CHANGES)) {
1661 if (CHECK_FLAG(ospf6->config_flags,
1662 OSPF6_LOG_ADJACENCY_DETAIL))
1663 vty_out(vty, " log-adjacency-changes detail\n");
1664 else if (!SAVE_OSPF6_LOG_ADJACENCY_CHANGES)
1665 vty_out(vty, " log-adjacency-changes\n");
1666 } else if (SAVE_OSPF6_LOG_ADJACENCY_CHANGES) {
1667 vty_out(vty, " no log-adjacency-changes\n");
1668 }
d62a17ae 1669
beadc736 1670 if (ospf6->ref_bandwidth != OSPF6_REFERENCE_BANDWIDTH)
1671 vty_out(vty, " auto-cost reference-bandwidth %d\n",
1672 ospf6->ref_bandwidth);
1673
78156066
PR
1674 if (ospf6->write_oi_count
1675 != OSPF6_WRITE_INTERFACE_COUNT_DEFAULT)
1676 vty_out(vty, " write-multiplier %d\n",
1677 ospf6->write_oi_count);
1678
beadc736 1679 /* LSA timers print. */
1680 if (ospf6->lsa_minarrival != OSPF_MIN_LS_ARRIVAL)
1681 vty_out(vty, " timers lsa min-arrival %d\n",
1682 ospf6->lsa_minarrival);
1683
1958143e
MR
1684 /* ECMP max path config */
1685 if (ospf6->max_multipath != MULTIPATH_NUM)
1686 vty_out(vty, " maximum-paths %d\n",
1687 ospf6->max_multipath);
1688
beadc736 1689 ospf6_stub_router_config_write(vty, ospf6);
1690 ospf6_redistribute_config_write(vty, ospf6);
1691 ospf6_area_config_write(vty, ospf6);
1692 ospf6_spf_config_write(vty, ospf6);
1693 ospf6_distance_config_write(vty, ospf6);
b19502d3 1694 ospf6_distribute_config_write(vty, ospf6);
beadc736 1695
beadc736 1696 vty_out(vty, "!\n");
d62a17ae 1697 }
d62a17ae 1698 return 0;
508e53e2 1699}
1700
612c2c15 1701static int config_write_ospf6(struct vty *vty);
508e53e2 1702/* OSPF6 node structure. */
d62a17ae 1703static struct cmd_node ospf6_node = {
f4b8291f 1704 .name = "ospf6",
62b346ee 1705 .node = OSPF6_NODE,
24389580 1706 .parent_node = CONFIG_NODE,
62b346ee 1707 .prompt = "%s(config-ospf6)# ",
612c2c15 1708 .config_write = config_write_ospf6,
508e53e2 1709};
1710
1711/* Install ospf related commands. */
d62a17ae 1712void ospf6_top_init(void)
718e3744 1713{
d62a17ae 1714 /* Install ospf6 top node. */
612c2c15 1715 install_node(&ospf6_node);
d62a17ae 1716
1717 install_element(VIEW_NODE, &show_ipv6_ospf6_cmd);
dd7fb1db 1718 install_element(VIEW_NODE, &show_ipv6_ospf6_vrfs_cmd);
d62a17ae 1719 install_element(CONFIG_NODE, &router_ospf6_cmd);
1720 install_element(CONFIG_NODE, &no_router_ospf6_cmd);
1721
1722 install_element(VIEW_NODE, &show_ipv6_ospf6_route_cmd);
1723 install_element(VIEW_NODE, &show_ipv6_ospf6_route_match_cmd);
1724 install_element(VIEW_NODE, &show_ipv6_ospf6_route_match_detail_cmd);
1725 install_element(VIEW_NODE, &show_ipv6_ospf6_route_type_detail_cmd);
1726
1727 install_default(OSPF6_NODE);
1728 install_element(OSPF6_NODE, &ospf6_router_id_cmd);
5d1a2ee8 1729 install_element(OSPF6_NODE, &no_ospf6_router_id_cmd);
d62a17ae 1730 install_element(OSPF6_NODE, &ospf6_log_adjacency_changes_cmd);
1731 install_element(OSPF6_NODE, &ospf6_log_adjacency_changes_detail_cmd);
1732 install_element(OSPF6_NODE, &no_ospf6_log_adjacency_changes_cmd);
1733 install_element(OSPF6_NODE, &no_ospf6_log_adjacency_changes_detail_cmd);
1734
1735 /* LSA timers commands */
1736 install_element(OSPF6_NODE, &ospf6_timers_lsa_cmd);
1737 install_element(OSPF6_NODE, &no_ospf6_timers_lsa_cmd);
1738
1739 install_element(OSPF6_NODE, &ospf6_interface_area_cmd);
1740 install_element(OSPF6_NODE, &no_ospf6_interface_area_cmd);
1741 install_element(OSPF6_NODE, &ospf6_stub_router_admin_cmd);
1742 install_element(OSPF6_NODE, &no_ospf6_stub_router_admin_cmd);
508e53e2 1743
1958143e
MR
1744 /* maximum-paths command */
1745 install_element(OSPF6_NODE, &ospf6_max_multipath_cmd);
1746 install_element(OSPF6_NODE, &no_ospf6_max_multipath_cmd);
1747
d62a17ae 1748 install_element(OSPF6_NODE, &ospf6_distance_cmd);
1749 install_element(OSPF6_NODE, &no_ospf6_distance_cmd);
1750 install_element(OSPF6_NODE, &ospf6_distance_ospf6_cmd);
1751 install_element(OSPF6_NODE, &no_ospf6_distance_ospf6_cmd);
718e3744 1752}