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