]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_interface.c
Merge pull request #13506 from anlancs/fix/bfdd-vrf-check
[mirror_frr.git] / ospf6d / ospf6_interface.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
718e3744 2/*
508e53e2 3 * Copyright (C) 2003 Yasuhiro Ohara
718e3744 4 */
5
508e53e2 6#include <zebra.h>
718e3744 7
508e53e2 8#include "memory.h"
718e3744 9#include "if.h"
10#include "log.h"
11#include "command.h"
24a58196 12#include "frrevent.h"
508e53e2 13#include "prefix.h"
14#include "plist.h"
88177fe3 15#include "zclient.h"
718e3744 16
508e53e2 17#include "ospf6_lsa.h"
718e3744 18#include "ospf6_lsdb.h"
c527acf1 19#include "ospf6_top.h"
508e53e2 20#include "ospf6_network.h"
21#include "ospf6_message.h"
22#include "ospf6_route.h"
718e3744 23#include "ospf6_area.h"
42cabc55 24#include "ospf6_abr.h"
a7c1a27f 25#include "ospf6_nssa.h"
718e3744 26#include "ospf6_interface.h"
508e53e2 27#include "ospf6_neighbor.h"
28#include "ospf6_intra.h"
29#include "ospf6_spf.h"
049207c3 30#include "ospf6d.h"
7f342629 31#include "ospf6_bfd.h"
ef7bd2a3 32#include "ospf6_zebra.h"
9a06f23d 33#include "ospf6_gr.h"
f16ae8cf 34#include "lib/json.h"
1a5607ea
AR
35#include "ospf6_proto.h"
36#include "lib/keychain.h"
37#include "ospf6_auth_trailer.h"
0c05ceae 38#include "ospf6d/ospf6_interface_clippy.c"
718e3744 39
9a06f23d 40DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_IF, "OSPF6 interface");
1a5607ea
AR
41DEFINE_MTYPE(OSPF6D, OSPF6_AUTH_KEYCHAIN, "OSPF6 auth keychain");
42DEFINE_MTYPE(OSPF6D, OSPF6_AUTH_MANUAL_KEY, "OSPF6 auth key");
bf8d3d6a 43DEFINE_MTYPE_STATIC(OSPF6D, CFG_PLIST_NAME, "configured prefix list names");
96244aca 44DEFINE_QOBJ_TYPE(ospf6_interface);
3012671f 45DEFINE_HOOK(ospf6_interface_change,
d62a17ae 46 (struct ospf6_interface * oi, int state, int old_state),
8451921b 47 (oi, state, old_state));
4a1ab8e4 48
508e53e2 49unsigned char conf_debug_ospf6_interface = 0;
50
2b64873d 51const char *const ospf6_interface_state_str[] = {
d62a17ae 52 "None", "Down", "Loopback", "Waiting", "PointToPoint",
53 "DROther", "BDR", "DR", NULL};
718e3744 54
9a06f23d 55int ospf6_interface_neighbor_count(struct ospf6_interface *oi)
56{
57 int count = 0;
58 struct ospf6_neighbor *nbr = NULL;
59 struct listnode *node;
60
61 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, node, nbr)) {
62 /* Down state is not shown. */
63 if (nbr->state == OSPF6_NEIGHBOR_DOWN)
64 continue;
65 count++;
66 }
67
68 return count;
69}
70
c5d28568
K
71struct ospf6_interface *ospf6_interface_lookup_by_ifindex(ifindex_t ifindex,
72 vrf_id_t vrf_id)
718e3744 73{
d62a17ae 74 struct ospf6_interface *oi;
75 struct interface *ifp;
718e3744 76
c5d28568 77 ifp = if_lookup_by_index(ifindex, vrf_id);
d62a17ae 78 if (ifp == NULL)
79 return (struct ospf6_interface *)NULL;
508e53e2 80
d62a17ae 81 oi = (struct ospf6_interface *)ifp->info;
82 return oi;
718e3744 83}
84
508e53e2 85/* schedule routing table recalculation */
d62a17ae 86static void ospf6_interface_lsdb_hook(struct ospf6_lsa *lsa,
87 unsigned int reason)
718e3744 88{
d62a17ae 89 struct ospf6_interface *oi;
90
91 if (lsa == NULL)
92 return;
93
94 oi = lsa->lsdb->data;
95 switch (ntohs(lsa->header->type)) {
96 case OSPF6_LSTYPE_LINK:
97 if (oi->state == OSPF6_INTERFACE_DR)
98 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi);
99 if (oi->area)
100 ospf6_spf_schedule(oi->area->ospf6, reason);
101 break;
102
103 default:
104 break;
105 }
718e3744 106}
107
d62a17ae 108static void ospf6_interface_lsdb_hook_add(struct ospf6_lsa *lsa)
a0edf674 109{
d62a17ae 110 ospf6_interface_lsdb_hook(lsa, ospf6_lsadd_to_spf_reason(lsa));
a0edf674
DD
111}
112
d62a17ae 113static void ospf6_interface_lsdb_hook_remove(struct ospf6_lsa *lsa)
a0edf674 114{
d62a17ae 115 ospf6_interface_lsdb_hook(lsa, ospf6_lsremove_to_spf_reason(lsa));
a0edf674
DD
116}
117
d7c0a89a 118static uint8_t ospf6_default_iftype(struct interface *ifp)
c5926a92 119{
d62a17ae 120 if (if_is_pointopoint(ifp))
121 return OSPF_IFTYPE_POINTOPOINT;
608c8870 122 else if (if_is_loopback(ifp))
d62a17ae 123 return OSPF_IFTYPE_LOOPBACK;
124 else
125 return OSPF_IFTYPE_BROADCAST;
c5926a92
DD
126}
127
d7c0a89a 128static uint32_t ospf6_interface_get_cost(struct ospf6_interface *oi)
c19543b2 129{
d62a17ae 130 /* If all else fails, use default OSPF cost */
d7c0a89a
QY
131 uint32_t cost;
132 uint32_t bw, refbw;
beadc736 133 struct ospf6 *ospf6;
27ae9bcd
CS
134 /* interface speed and bw can be 0 in some platforms,
135 * use ospf default bw. If bw is configured then it would
136 * be used.
137 */
138 if (!oi->interface->bandwidth && oi->interface->speed) {
139 bw = oi->interface->speed;
140 } else {
141 bw = oi->interface->bandwidth ? oi->interface->bandwidth
996c9314 142 : OSPF6_INTERFACE_BANDWIDTH;
27ae9bcd
CS
143 }
144
096f7609 145 ospf6 = oi->interface->vrf->info;
d62a17ae 146 refbw = ospf6 ? ospf6->ref_bandwidth : OSPF6_REFERENCE_BANDWIDTH;
147
bd4f51b1 148 /* A specified ip ospf cost overrides a calculated one. */
d62a17ae 149 if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_NOAUTOCOST))
150 cost = oi->cost;
151 else {
d7c0a89a 152 cost = (uint32_t)((double)refbw / (double)bw + (double)0.5);
d62a17ae 153 if (cost < 1)
154 cost = 1;
d62a17ae 155 }
156
157 return cost;
c19543b2
VB
158}
159
0db8196a 160static void ospf6_interface_force_recalculate_cost(struct ospf6_interface *oi)
c19543b2 161{
d62a17ae 162 /* update cost held in route_connected list in ospf6_interface */
163 ospf6_interface_connected_route_update(oi->interface);
164
165 /* execute LSA hooks */
166 if (oi->area) {
167 OSPF6_LINK_LSA_SCHEDULE(oi);
168 OSPF6_ROUTER_LSA_SCHEDULE(oi->area);
169 OSPF6_NETWORK_LSA_SCHEDULE(oi);
170 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi);
171 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area);
172 }
c19543b2
VB
173}
174
0db8196a
JK
175static void ospf6_interface_recalculate_cost(struct ospf6_interface *oi)
176{
d7c0a89a 177 uint32_t newcost;
0db8196a
JK
178
179 newcost = ospf6_interface_get_cost(oi);
180 if (newcost == oi->cost)
181 return;
182 oi->cost = newcost;
183
184 ospf6_interface_force_recalculate_cost(oi);
185}
186
718e3744 187/* Create new ospf6 interface structure */
d62a17ae 188struct ospf6_interface *ospf6_interface_create(struct interface *ifp)
718e3744 189{
d62a17ae 190 struct ospf6_interface *oi;
191 unsigned int iobuflen;
192
9f5dc319 193 oi = XCALLOC(MTYPE_OSPF6_IF, sizeof(struct ospf6_interface));
d62a17ae 194
4f7bf1ab
PR
195 oi->obuf = ospf6_fifo_new();
196
d62a17ae 197 oi->area = (struct ospf6_area *)NULL;
198 oi->neighbor_list = list_new();
199 oi->neighbor_list->cmp = ospf6_neighbor_cmp;
200 oi->linklocal_addr = (struct in6_addr *)NULL;
201 oi->instance_id = OSPF6_INTERFACE_INSTANCE_ID;
202 oi->transdelay = OSPF6_INTERFACE_TRANSDELAY;
203 oi->priority = OSPF6_INTERFACE_PRIORITY;
204
205 oi->hello_interval = OSPF_HELLO_INTERVAL_DEFAULT;
0c05ceae 206 oi->gr.hello_delay.interval = OSPF_HELLO_DELAY_DEFAULT;
d62a17ae 207 oi->dead_interval = OSPF_ROUTER_DEAD_INTERVAL_DEFAULT;
208 oi->rxmt_interval = OSPF_RETRANSMIT_INTERVAL_DEFAULT;
209 oi->type = ospf6_default_iftype(ifp);
210 oi->state = OSPF6_INTERFACE_DOWN;
211 oi->flag = 0;
212 oi->mtu_ignore = 0;
213 oi->c_ifmtu = 0;
214
215 /* Try to adjust I/O buffer size with IfMtu */
216 oi->ifmtu = ifp->mtu6;
217 iobuflen = ospf6_iobuf_size(ifp->mtu6);
218 if (oi->ifmtu > iobuflen) {
219 if (IS_OSPF6_DEBUG_INTERFACE)
220 zlog_debug(
221 "Interface %s: IfMtu is adjusted to I/O buffer size: %d.",
222 ifp->name, iobuflen);
223 oi->ifmtu = iobuflen;
224 }
225
226 QOBJ_REG(oi, ospf6_interface);
227
228 oi->lsupdate_list = ospf6_lsdb_create(oi);
229 oi->lsack_list = ospf6_lsdb_create(oi);
230 oi->lsdb = ospf6_lsdb_create(oi);
231 oi->lsdb->hook_add = ospf6_interface_lsdb_hook_add;
232 oi->lsdb->hook_remove = ospf6_interface_lsdb_hook_remove;
233 oi->lsdb_self = ospf6_lsdb_create(oi);
234
235 oi->route_connected =
236 OSPF6_ROUTE_TABLE_CREATE(INTERFACE, CONNECTED_ROUTES);
237 oi->route_connected->scope = oi;
238
239 /* link both */
240 oi->interface = ifp;
241 ifp->info = oi;
242
243 /* Compute cost. */
244 oi->cost = ospf6_interface_get_cost(oi);
245
1a5607ea
AR
246 oi->at_data.flags = 0;
247
d62a17ae 248 return oi;
718e3744 249}
250
d62a17ae 251void ospf6_interface_delete(struct ospf6_interface *oi)
718e3744 252{
d62a17ae 253 struct listnode *node, *nnode;
254 struct ospf6_neighbor *on;
255
256 QOBJ_UNREG(oi);
718e3744 257
4f7bf1ab
PR
258 ospf6_fifo_free(oi->obuf);
259
d62a17ae 260 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on))
261 ospf6_neighbor_delete(on);
ae19c240 262
6a154c88 263 list_delete(&oi->neighbor_list);
718e3744 264
e16d030c
DS
265 EVENT_OFF(oi->thread_send_hello);
266 EVENT_OFF(oi->thread_send_lsupdate);
267 EVENT_OFF(oi->thread_send_lsack);
268 EVENT_OFF(oi->thread_sso);
269 EVENT_OFF(oi->thread_wait_timer);
508e53e2 270
d62a17ae 271 ospf6_lsdb_remove_all(oi->lsdb);
272 ospf6_lsdb_remove_all(oi->lsupdate_list);
273 ospf6_lsdb_remove_all(oi->lsack_list);
508e53e2 274
d62a17ae 275 ospf6_lsdb_delete(oi->lsdb);
276 ospf6_lsdb_delete(oi->lsdb_self);
6452df09 277
d62a17ae 278 ospf6_lsdb_delete(oi->lsupdate_list);
279 ospf6_lsdb_delete(oi->lsack_list);
718e3744 280
e285b70d 281 ospf6_route_table_delete(oi->route_connected);
718e3744 282
d62a17ae 283 /* cut link */
284 oi->interface->info = NULL;
718e3744 285
d62a17ae 286 /* plist_name */
287 if (oi->plist_name)
288 XFREE(MTYPE_CFG_PLIST_NAME, oi->plist_name);
508e53e2 289
22b982df
PG
290 /* disable from area list if possible */
291 ospf6_area_interface_delete(oi);
292
6354d635
DS
293 if (oi->at_data.auth_key)
294 XFREE(MTYPE_OSPF6_AUTH_MANUAL_KEY, oi->at_data.auth_key);
295
1f7be0d2
RZ
296 /* Free BFD allocated data. */
297 XFREE(MTYPE_TMP, oi->bfd_config.profile);
298
d62a17ae 299 XFREE(MTYPE_OSPF6_IF, oi);
508e53e2 300}
301
d62a17ae 302void ospf6_interface_enable(struct ospf6_interface *oi)
508e53e2 303{
d62a17ae 304 UNSET_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE);
305 ospf6_interface_state_update(oi->interface);
508e53e2 306}
307
d62a17ae 308void ospf6_interface_disable(struct ospf6_interface *oi)
508e53e2 309{
d62a17ae 310 SET_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE);
508e53e2 311
8c1186d3 312 event_execute(master, interface_down, oi, 0);
508e53e2 313
d62a17ae 314 ospf6_lsdb_remove_all(oi->lsdb);
315 ospf6_lsdb_remove_all(oi->lsdb_self);
316 ospf6_lsdb_remove_all(oi->lsupdate_list);
317 ospf6_lsdb_remove_all(oi->lsack_list);
508e53e2 318
e16d030c
DS
319 EVENT_OFF(oi->thread_send_hello);
320 EVENT_OFF(oi->thread_send_lsupdate);
321 EVENT_OFF(oi->thread_send_lsack);
322 EVENT_OFF(oi->thread_sso);
d9628728 323
e16d030c
DS
324 EVENT_OFF(oi->thread_network_lsa);
325 EVENT_OFF(oi->thread_link_lsa);
326 EVENT_OFF(oi->thread_intra_prefix_lsa);
327 EVENT_OFF(oi->thread_as_extern_lsa);
328 EVENT_OFF(oi->thread_wait_timer);
0c05ceae
RW
329
330 oi->gr.hello_delay.elapsed_seconds = 0;
331 EVENT_OFF(oi->gr.hello_delay.t_grace_send);
718e3744 332}
333
334static struct in6_addr *
d62a17ae 335ospf6_interface_get_linklocal_address(struct interface *ifp)
718e3744 336{
d62a17ae 337 struct listnode *n;
338 struct connected *c;
339 struct in6_addr *l = (struct in6_addr *)NULL;
340
341 /* for each connected address */
342 for (ALL_LIST_ELEMENTS_RO(ifp->connected, n, c)) {
343 /* if family not AF_INET6, ignore */
344 if (c->address->family != AF_INET6)
345 continue;
346
347 /* linklocal scope check */
348 if (IN6_IS_ADDR_LINKLOCAL(&c->address->u.prefix6))
349 l = &c->address->u.prefix6;
350 }
351 return l;
718e3744 352}
353
d62a17ae 354void ospf6_interface_state_update(struct interface *ifp)
718e3744 355{
d62a17ae 356 struct ospf6_interface *oi;
357 unsigned int iobuflen;
358
359 oi = (struct ospf6_interface *)ifp->info;
360 if (oi == NULL)
361 return;
d62a17ae 362 if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE))
363 return;
364
365 /* Adjust the mtu values if the kernel told us something new */
366 if (ifp->mtu6 != oi->ifmtu) {
367 /* If nothing configured, accept it and check for buffer size */
368 if (!oi->c_ifmtu) {
369 oi->ifmtu = ifp->mtu6;
370 iobuflen = ospf6_iobuf_size(ifp->mtu6);
371 if (oi->ifmtu > iobuflen) {
372 if (IS_OSPF6_DEBUG_INTERFACE)
373 zlog_debug(
374 "Interface %s: IfMtu is adjusted to I/O buffer size: %d.",
375 ifp->name, iobuflen);
376 oi->ifmtu = iobuflen;
377 }
378 } else if (oi->c_ifmtu > ifp->mtu6) {
379 oi->ifmtu = ifp->mtu6;
380 zlog_warn(
381 "Configured mtu %u on %s overridden by kernel %u",
382 oi->c_ifmtu, ifp->name, ifp->mtu6);
383 } else
384 oi->ifmtu = oi->c_ifmtu;
385 }
386
387 if (if_is_operative(ifp)
388 && (ospf6_interface_get_linklocal_address(oi->interface)
608c8870 389 || if_is_loopback(oi->interface)))
8c1186d3 390 event_execute(master, interface_up, oi, 0);
d62a17ae 391 else
8c1186d3 392 event_execute(master, interface_down, oi, 0);
d62a17ae 393
394 return;
718e3744 395}
396
d62a17ae 397void ospf6_interface_connected_route_update(struct interface *ifp)
718e3744 398{
d62a17ae 399 struct ospf6_interface *oi;
400 struct ospf6_route *route;
401 struct connected *c;
402 struct listnode *node, *nnode;
403 struct in6_addr nh_addr;
404
405 oi = (struct ospf6_interface *)ifp->info;
406 if (oi == NULL)
407 return;
408
409 /* reset linklocal pointer */
410 oi->linklocal_addr = ospf6_interface_get_linklocal_address(ifp);
411
412 /* if area is null, do not make connected-route list */
413 if (oi->area == NULL)
414 return;
415
416 if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE))
417 return;
418
419 /* update "route to advertise" interface route table */
e285b70d 420 ospf6_route_remove_all(oi->route_connected);
d62a17ae 421
422 for (ALL_LIST_ELEMENTS(oi->interface->connected, node, nnode, c)) {
423 if (c->address->family != AF_INET6)
424 continue;
425
426 CONTINUE_IF_ADDRESS_LINKLOCAL(IS_OSPF6_DEBUG_INTERFACE,
427 c->address);
428 CONTINUE_IF_ADDRESS_UNSPECIFIED(IS_OSPF6_DEBUG_INTERFACE,
429 c->address);
430 CONTINUE_IF_ADDRESS_LOOPBACK(IS_OSPF6_DEBUG_INTERFACE,
431 c->address);
432 CONTINUE_IF_ADDRESS_V4COMPAT(IS_OSPF6_DEBUG_INTERFACE,
433 c->address);
434 CONTINUE_IF_ADDRESS_V4MAPPED(IS_OSPF6_DEBUG_INTERFACE,
435 c->address);
436
437 /* apply filter */
438 if (oi->plist_name) {
439 struct prefix_list *plist;
440 enum prefix_list_type ret;
d62a17ae 441
d62a17ae 442 plist = prefix_list_lookup(AFI_IP6, oi->plist_name);
443 ret = prefix_list_apply(plist, (void *)c->address);
444 if (ret == PREFIX_DENY) {
445 if (IS_OSPF6_DEBUG_INTERFACE)
446 zlog_debug(
2dbe669b
DA
447 "%pFX on %s filtered by prefix-list %s ",
448 c->address, oi->interface->name,
d62a17ae 449 oi->plist_name);
450 continue;
451 }
452 }
453
22813fdb 454 route = ospf6_route_create(oi->area->ospf6);
d62a17ae 455 memcpy(&route->prefix, c->address, sizeof(struct prefix));
456 apply_mask(&route->prefix);
457 route->type = OSPF6_DEST_TYPE_NETWORK;
458 route->path.area_id = oi->area->area_id;
459 route->path.type = OSPF6_PATH_TYPE_INTRA;
460 route->path.cost = oi->cost;
461 inet_pton(AF_INET6, "::1", &nh_addr);
462 ospf6_route_add_nexthop(route, oi->interface->ifindex,
463 &nh_addr);
e285b70d 464 ospf6_route_add(route, oi->route_connected);
d62a17ae 465 }
466
467 /* create new Link-LSA */
468 OSPF6_LINK_LSA_SCHEDULE(oi);
469 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi);
470 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area);
718e3744 471}
472
17ab36c6
YR
473static int ospf6_interface_state_change(uint8_t next_state,
474 struct ospf6_interface *oi)
718e3744 475{
d7c0a89a 476 uint8_t prev_state;
beadc736 477 struct ospf6 *ospf6;
d62a17ae 478
479 prev_state = oi->state;
480 oi->state = next_state;
481
482 if (prev_state == next_state)
17ab36c6 483 return -1;
d62a17ae 484
b4b6bd00
IR
485 if (!oi->area)
486 return -1;
487
d62a17ae 488 /* log */
489 if (IS_OSPF6_DEBUG_INTERFACE) {
490 zlog_debug("Interface state change %s: %s -> %s",
491 oi->interface->name,
492 ospf6_interface_state_str[prev_state],
493 ospf6_interface_state_str[next_state]);
494 }
495 oi->state_change++;
b4b6bd00
IR
496
497 ospf6 = oi->area->ospf6;
d62a17ae 498
499 if ((prev_state == OSPF6_INTERFACE_DR
500 || prev_state == OSPF6_INTERFACE_BDR)
501 && (next_state != OSPF6_INTERFACE_DR
502 && next_state != OSPF6_INTERFACE_BDR))
503 ospf6_sso(oi->interface->ifindex, &alldrouters6,
beadc736 504 IPV6_LEAVE_GROUP, ospf6->fd);
d62a17ae 505
506 if ((prev_state != OSPF6_INTERFACE_DR
507 && prev_state != OSPF6_INTERFACE_BDR)
508 && (next_state == OSPF6_INTERFACE_DR
509 || next_state == OSPF6_INTERFACE_BDR))
510 ospf6_sso(oi->interface->ifindex, &alldrouters6,
beadc736 511 IPV6_JOIN_GROUP, ospf6->fd);
d62a17ae 512
513 OSPF6_ROUTER_LSA_SCHEDULE(oi->area);
bb4c5661 514 OSPF6_LINK_LSA_SCHEDULE(oi);
d62a17ae 515 if (next_state == OSPF6_INTERFACE_DOWN) {
516 OSPF6_NETWORK_LSA_EXECUTE(oi);
517 OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(oi);
518 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area);
76249532 519 OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(oi);
d62a17ae 520 } else if (prev_state == OSPF6_INTERFACE_DR
521 || next_state == OSPF6_INTERFACE_DR) {
522 OSPF6_NETWORK_LSA_SCHEDULE(oi);
523 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi);
524 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area);
525 }
526
527 hook_call(ospf6_interface_change, oi, next_state, prev_state);
17ab36c6
YR
528
529 return 0;
718e3744 530}
531
6b0655a2 532
508e53e2 533/* DR Election, RFC2328 section 9.4 */
718e3744 534
d62a17ae 535#define IS_ELIGIBLE(n) \
536 ((n)->state >= OSPF6_NEIGHBOR_TWOWAY && (n)->priority != 0)
718e3744 537
d62a17ae 538static struct ospf6_neighbor *better_bdrouter(struct ospf6_neighbor *a,
539 struct ospf6_neighbor *b)
508e53e2 540{
d62a17ae 541 if ((a == NULL || !IS_ELIGIBLE(a) || a->drouter == a->router_id)
542 && (b == NULL || !IS_ELIGIBLE(b) || b->drouter == b->router_id))
543 return NULL;
544 else if (a == NULL || !IS_ELIGIBLE(a) || a->drouter == a->router_id)
545 return b;
546 else if (b == NULL || !IS_ELIGIBLE(b) || b->drouter == b->router_id)
547 return a;
548
549 if (a->bdrouter == a->router_id && b->bdrouter != b->router_id)
550 return a;
551 if (a->bdrouter != a->router_id && b->bdrouter == b->router_id)
552 return b;
553
554 if (a->priority > b->priority)
555 return a;
556 if (a->priority < b->priority)
557 return b;
558
559 if (ntohl(a->router_id) > ntohl(b->router_id))
560 return a;
561 if (ntohl(a->router_id) < ntohl(b->router_id))
562 return b;
563
564 zlog_warn("Router-ID duplicate ?");
565 return a;
508e53e2 566}
718e3744 567
d62a17ae 568static struct ospf6_neighbor *better_drouter(struct ospf6_neighbor *a,
569 struct ospf6_neighbor *b)
508e53e2 570{
d62a17ae 571 if ((a == NULL || !IS_ELIGIBLE(a) || a->drouter != a->router_id)
572 && (b == NULL || !IS_ELIGIBLE(b) || b->drouter != b->router_id))
573 return NULL;
574 else if (a == NULL || !IS_ELIGIBLE(a) || a->drouter != a->router_id)
575 return b;
576 else if (b == NULL || !IS_ELIGIBLE(b) || b->drouter != b->router_id)
577 return a;
578
579 if (a->drouter == a->router_id && b->drouter != b->router_id)
580 return a;
581 if (a->drouter != a->router_id && b->drouter == b->router_id)
582 return b;
583
584 if (a->priority > b->priority)
585 return a;
586 if (a->priority < b->priority)
587 return b;
588
589 if (ntohl(a->router_id) > ntohl(b->router_id))
590 return a;
591 if (ntohl(a->router_id) < ntohl(b->router_id))
592 return b;
593
594 zlog_warn("Router-ID duplicate ?");
595 return a;
718e3744 596}
597
9a06f23d 598uint8_t dr_election(struct ospf6_interface *oi)
718e3744 599{
e23e5683 600 struct ospf6 *ospf6 = oi->area->ospf6;
d62a17ae 601 struct listnode *node, *nnode;
602 struct ospf6_neighbor *on, *drouter, *bdrouter, myself;
603 struct ospf6_neighbor *best_drouter, *best_bdrouter;
d7c0a89a 604 uint8_t next_state = 0;
d62a17ae 605
606 drouter = bdrouter = NULL;
607 best_drouter = best_bdrouter = NULL;
608
609 /* pseudo neighbor myself, including noting current DR/BDR (1) */
610 memset(&myself, 0, sizeof(myself));
e23e5683 611 inet_ntop(AF_INET, &ospf6->router_id, myself.name, sizeof(myself.name));
d62a17ae 612 myself.state = OSPF6_NEIGHBOR_TWOWAY;
613 myself.drouter = oi->drouter;
614 myself.bdrouter = oi->bdrouter;
615 myself.priority = oi->priority;
e23e5683 616 myself.router_id = ospf6->router_id;
d62a17ae 617
618 /* Electing BDR (2) */
619 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on))
620 bdrouter = better_bdrouter(bdrouter, on);
621
622 best_bdrouter = bdrouter;
623 bdrouter = better_bdrouter(best_bdrouter, &myself);
624
625 /* Electing DR (3) */
626 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on))
627 drouter = better_drouter(drouter, on);
628
629 best_drouter = drouter;
630 drouter = better_drouter(best_drouter, &myself);
631 if (drouter == NULL)
632 drouter = bdrouter;
633
634 /* the router itself is newly/no longer DR/BDR (4) */
635 if ((drouter == &myself && myself.drouter != myself.router_id)
636 || (drouter != &myself && myself.drouter == myself.router_id)
637 || (bdrouter == &myself && myself.bdrouter != myself.router_id)
638 || (bdrouter != &myself && myself.bdrouter == myself.router_id)) {
639 myself.drouter = (drouter ? drouter->router_id : htonl(0));
640 myself.bdrouter = (bdrouter ? bdrouter->router_id : htonl(0));
641
642 /* compatible to Electing BDR (2) */
643 bdrouter = better_bdrouter(best_bdrouter, &myself);
644
645 /* compatible to Electing DR (3) */
646 drouter = better_drouter(best_drouter, &myself);
647 if (drouter == NULL)
648 drouter = bdrouter;
649 }
650
651 /* Set interface state accordingly (5) */
652 if (drouter && drouter == &myself)
653 next_state = OSPF6_INTERFACE_DR;
654 else if (bdrouter && bdrouter == &myself)
655 next_state = OSPF6_INTERFACE_BDR;
656 else
657 next_state = OSPF6_INTERFACE_DROTHER;
658
659 /* If NBMA, schedule Start for each neighbor having priority of 0 (6) */
660 /* XXX */
661
662 /* If DR or BDR change, invoke AdjOK? for each neighbor (7) */
663 /* RFC 2328 section 12.4. Originating LSAs (3) will be handled
664 accordingly after AdjOK */
e23e5683
RW
665
666 if (oi->drouter != (drouter ? drouter->router_id : htonl(0)) ||
667 oi->bdrouter != (bdrouter ? bdrouter->router_id : htonl(0)) ||
668 ospf6->gr_info.restart_in_progress) {
d62a17ae 669 if (IS_OSPF6_DEBUG_INTERFACE)
670 zlog_debug("DR Election on %s: DR: %s BDR: %s",
671 oi->interface->name,
672 (drouter ? drouter->name : "0.0.0.0"),
673 (bdrouter ? bdrouter->name : "0.0.0.0"));
674
675 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, node, on)) {
676 if (on->state < OSPF6_NEIGHBOR_TWOWAY)
677 continue;
678 /* Schedule AdjOK. */
907a2395
DS
679 event_add_event(master, adj_ok, on, 0,
680 &on->thread_adj_ok);
d62a17ae 681 }
682 }
683
684 oi->drouter = (drouter ? drouter->router_id : htonl(0));
685 oi->bdrouter = (bdrouter ? bdrouter->router_id : htonl(0));
686 return next_state;
718e3744 687}
688
93828a99
IR
689#ifdef __FreeBSD__
690
691#include <ifaddrs.h>
692
693static bool ifmaddr_check(ifindex_t ifindex, struct in6_addr *addr)
694{
695 struct ifmaddrs *ifmap, *ifma;
696 struct sockaddr_dl *sdl;
697 struct sockaddr_in6 *sin6;
698 bool found = false;
699
700 if (getifmaddrs(&ifmap) != 0)
701 return false;
702
703 for (ifma = ifmap; ifma; ifma = ifma->ifma_next) {
704 if (ifma->ifma_name == NULL || ifma->ifma_addr == NULL)
705 continue;
706 if (ifma->ifma_name->sa_family != AF_LINK)
707 continue;
708 if (ifma->ifma_addr->sa_family != AF_INET6)
709 continue;
710 sdl = (struct sockaddr_dl *)ifma->ifma_name;
711 sin6 = (struct sockaddr_in6 *)ifma->ifma_addr;
712 if (sdl->sdl_index == ifindex
713 && memcmp(&sin6->sin6_addr, addr, IPV6_MAX_BYTELEN) == 0) {
714 found = true;
715 break;
716 }
717 }
718
719 if (ifmap)
720 freeifmaddrs(ifmap);
721
722 return found;
723}
724
725#endif /* __FreeBSD__ */
6b0655a2 726
508e53e2 727/* Interface State Machine */
e6685141 728void interface_up(struct event *thread)
718e3744 729{
d62a17ae 730 struct ospf6_interface *oi;
beadc736 731 struct ospf6 *ospf6;
d62a17ae 732
e16d030c 733 oi = (struct ospf6_interface *)EVENT_ARG(thread);
d62a17ae 734 assert(oi && oi->interface);
735
5aeb4f3c
DL
736 if (!oi->type_cfg)
737 oi->type = ospf6_default_iftype(oi->interface);
738
332beb64 739 event_cancel(&oi->thread_sso);
f80003b0 740
d62a17ae 741 if (IS_OSPF6_DEBUG_INTERFACE)
742 zlog_debug("Interface Event %s: [InterfaceUp]",
743 oi->interface->name);
744
745 /* check physical interface is up */
746 if (!if_is_operative(oi->interface)) {
1b1f7b4f 747 zlog_warn("Interface %s is down, can't execute [InterfaceUp]",
748 oi->interface->name);
cc9f21da 749 return;
d62a17ae 750 }
751
752 /* check interface has a link-local address */
753 if (!(ospf6_interface_get_linklocal_address(oi->interface)
608c8870 754 || if_is_loopback(oi->interface))) {
1b1f7b4f 755 zlog_warn(
756 "Interface %s has no link local address, can't execute [InterfaceUp]",
757 oi->interface->name);
cc9f21da 758 return;
d62a17ae 759 }
760
761 /* Recompute cost */
762 ospf6_interface_recalculate_cost(oi);
763
764 /* if already enabled, do nothing */
765 if (oi->state > OSPF6_INTERFACE_DOWN) {
766 if (IS_OSPF6_DEBUG_INTERFACE)
767 zlog_debug("Interface %s already enabled",
768 oi->interface->name);
cc9f21da 769 return;
d62a17ae 770 }
771
772 /* If no area assigned, return */
773 if (oi->area == NULL) {
1b1f7b4f 774 zlog_warn(
482467dc 775 "%s: Not scheduling Hello for %s as there is no area assigned yet",
d62a17ae 776 __func__, oi->interface->name);
cc9f21da 777 return;
d62a17ae 778 }
779
88b3d5e5
RW
780 /*
781 * RFC 3623 - Section 5 ("Unplanned Outages"):
782 * "The grace-LSAs are encapsulated in Link State Update Packets
783 * and sent out to all interfaces, even though the restarted
784 * router has no adjacencies and no knowledge of previous
785 * adjacencies".
786 */
787 if (oi->area->ospf6->gr_info.restart_in_progress &&
788 oi->area->ospf6->gr_info.reason == OSPF6_GR_UNKNOWN_RESTART)
789 ospf6_gr_unplanned_start_interface(oi);
790
bc482dc0
RZ
791#ifdef __FreeBSD__
792 /*
93828a99
IR
793 * There's a delay in FreeBSD between issuing a command to leave a
794 * multicast group and an actual leave. If we execute "no router ospf6"
795 * and "router ospf6" fast enough, we can end up in a situation when OS
796 * performs the leave later than it performs the join and the interface
797 * remains without a multicast group. We have to do the join only after
798 * the interface actually left the group.
bc482dc0 799 */
93828a99
IR
800 if (ifmaddr_check(oi->interface->ifindex, &allspfrouters6)) {
801 zlog_info(
802 "Interface %s is still in all routers group, rescheduling for SSO",
803 oi->interface->name);
907a2395
DS
804 event_add_timer(master, interface_up, oi,
805 OSPF6_INTERFACE_SSO_RETRY_INT, &oi->thread_sso);
cc9f21da 806 return;
bc482dc0
RZ
807 }
808#endif /* __FreeBSD__ */
b4b6bd00
IR
809
810 ospf6 = oi->area->ospf6;
bc482dc0 811
d62a17ae 812 /* Join AllSPFRouters */
beadc736 813 if (ospf6_sso(oi->interface->ifindex, &allspfrouters6, IPV6_JOIN_GROUP,
814 ospf6->fd)
d62a17ae 815 < 0) {
816 if (oi->sso_try_cnt++ < OSPF6_INTERFACE_SSO_RETRY_MAX) {
817 zlog_info(
818 "Scheduling %s for sso retry, trial count: %d",
819 oi->interface->name, oi->sso_try_cnt);
907a2395
DS
820 event_add_timer(master, interface_up, oi,
821 OSPF6_INTERFACE_SSO_RETRY_INT,
822 &oi->thread_sso);
d62a17ae 823 }
cc9f21da 824 return;
d62a17ae 825 }
826 oi->sso_try_cnt = 0; /* Reset on success */
827
828 /* Update interface route */
829 ospf6_interface_connected_route_update(oi->interface);
830
831 /* Schedule Hello */
832 if (!CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE)
608c8870 833 && !if_is_loopback(oi->interface)) {
907a2395
DS
834 event_add_timer(master, ospf6_hello_send, oi, 0,
835 &oi->thread_send_hello);
d62a17ae 836 }
837
838 /* decide next interface state */
621ee705
DL
839 if (oi->type == OSPF_IFTYPE_LOOPBACK) {
840 ospf6_interface_state_change(OSPF6_INTERFACE_LOOPBACK, oi);
841 } else if (oi->type == OSPF_IFTYPE_POINTOPOINT) {
d62a17ae 842 ospf6_interface_state_change(OSPF6_INTERFACE_POINTTOPOINT, oi);
843 } else if (oi->priority == 0)
844 ospf6_interface_state_change(OSPF6_INTERFACE_DROTHER, oi);
845 else {
846 ospf6_interface_state_change(OSPF6_INTERFACE_WAITING, oi);
907a2395
DS
847 event_add_timer(master, wait_timer, oi, oi->dead_interval,
848 &oi->thread_wait_timer);
d62a17ae 849 }
718e3744 850}
851
e6685141 852void wait_timer(struct event *thread)
718e3744 853{
d62a17ae 854 struct ospf6_interface *oi;
718e3744 855
e16d030c 856 oi = (struct ospf6_interface *)EVENT_ARG(thread);
d62a17ae 857 assert(oi && oi->interface);
718e3744 858
d62a17ae 859 if (IS_OSPF6_DEBUG_INTERFACE)
860 zlog_debug("Interface Event %s: [WaitTimer]",
861 oi->interface->name);
718e3744 862
d62a17ae 863 if (oi->state == OSPF6_INTERFACE_WAITING)
864 ospf6_interface_state_change(dr_election(oi), oi);
718e3744 865}
866
e6685141 867void backup_seen(struct event *thread)
508e53e2 868{
d62a17ae 869 struct ospf6_interface *oi;
508e53e2 870
e16d030c 871 oi = (struct ospf6_interface *)EVENT_ARG(thread);
d62a17ae 872 assert(oi && oi->interface);
508e53e2 873
d62a17ae 874 if (IS_OSPF6_DEBUG_INTERFACE)
875 zlog_debug("Interface Event %s: [BackupSeen]",
876 oi->interface->name);
508e53e2 877
d62a17ae 878 if (oi->state == OSPF6_INTERFACE_WAITING)
879 ospf6_interface_state_change(dr_election(oi), oi);
508e53e2 880}
881
e6685141 882void neighbor_change(struct event *thread)
718e3744 883{
d62a17ae 884 struct ospf6_interface *oi;
508e53e2 885
e16d030c 886 oi = (struct ospf6_interface *)EVENT_ARG(thread);
d62a17ae 887 assert(oi && oi->interface);
508e53e2 888
d62a17ae 889 if (IS_OSPF6_DEBUG_INTERFACE)
890 zlog_debug("Interface Event %s: [NeighborChange]",
891 oi->interface->name);
508e53e2 892
d62a17ae 893 if (oi->state == OSPF6_INTERFACE_DROTHER
894 || oi->state == OSPF6_INTERFACE_BDR
895 || oi->state == OSPF6_INTERFACE_DR)
896 ospf6_interface_state_change(dr_election(oi), oi);
718e3744 897}
898
e6685141 899void interface_down(struct event *thread)
718e3744 900{
d62a17ae 901 struct ospf6_interface *oi;
902 struct listnode *node, *nnode;
903 struct ospf6_neighbor *on;
beadc736 904 struct ospf6 *ospf6;
508e53e2 905
e16d030c 906 oi = (struct ospf6_interface *)EVENT_ARG(thread);
d62a17ae 907 assert(oi && oi->interface);
508e53e2 908
d62a17ae 909 if (IS_OSPF6_DEBUG_INTERFACE)
910 zlog_debug("Interface Event %s: [InterfaceDown]",
911 oi->interface->name);
508e53e2 912
d62a17ae 913 /* Stop Hellos */
e16d030c 914 EVENT_OFF(oi->thread_send_hello);
424cc3bd 915
f80003b0 916 /* Stop trying to set socket options. */
e16d030c 917 EVENT_OFF(oi->thread_sso);
508e53e2 918
9a06f23d 919 /* Cease the HELPER role for all the neighbours
920 * of this interface.
921 */
922 if (ospf6_interface_neighbor_count(oi)) {
923 struct listnode *ln;
924 struct ospf6_neighbor *nbr = NULL;
925
926 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, ln, nbr))
927 ospf6_gr_helper_exit(nbr, OSPF6_GR_HELPER_TOPO_CHG);
928 }
929
d62a17ae 930 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on))
931 ospf6_neighbor_delete(on);
508e53e2 932
d62a17ae 933 list_delete_all_node(oi->neighbor_list);
934
935 /* When interface state is reset, also reset information about
936 * DR election, as it is no longer valid. */
937 oi->drouter = oi->prev_drouter = htonl(0);
938 oi->bdrouter = oi->prev_bdrouter = htonl(0);
b4b6bd00
IR
939
940 if (oi->area == NULL)
cc9f21da 941 return;
b4b6bd00
IR
942
943 ospf6 = oi->area->ospf6;
944 /* Leave AllSPFRouters */
945 if (oi->state > OSPF6_INTERFACE_DOWN)
946 ospf6_sso(oi->interface->ifindex, &allspfrouters6,
947 IPV6_LEAVE_GROUP, ospf6->fd);
948
4f7bf1ab
PR
949 /* deal with write fifo */
950 ospf6_fifo_flush(oi->obuf);
951 if (oi->on_write_q) {
952 listnode_delete(ospf6->oi_write_q, oi);
953 if (list_isempty(ospf6->oi_write_q))
332beb64 954 event_cancel(&ospf6->t_write);
4f7bf1ab
PR
955 oi->on_write_q = 0;
956 }
957
b4b6bd00 958 ospf6_interface_state_change(OSPF6_INTERFACE_DOWN, oi);
718e3744 959}
960
6b0655a2 961
5aeb4f3c
DL
962static const char *ospf6_iftype_str(uint8_t iftype)
963{
964 switch (iftype) {
965 case OSPF_IFTYPE_LOOPBACK:
966 return "LOOPBACK";
967 case OSPF_IFTYPE_BROADCAST:
968 return "BROADCAST";
969 case OSPF_IFTYPE_POINTOPOINT:
970 return "POINTOPOINT";
971 }
972 return "UNKNOWN";
973}
974
718e3744 975/* show specified interface structure */
f16ae8cf 976static int ospf6_interface_show(struct vty *vty, struct interface *ifp,
977 json_object *json_obj, bool use_json)
718e3744 978{
d62a17ae 979 struct ospf6_interface *oi;
980 struct connected *c;
981 struct prefix *p;
982 struct listnode *i;
983 char strbuf[PREFIX2STR_BUFFER], drouter[32], bdrouter[32];
5aeb4f3c 984 uint8_t default_iftype;
d62a17ae 985 struct timeval res, now;
986 char duration[32];
2e37407f 987 struct ospf6_lsa *lsa, *lsanext;
f16ae8cf 988 json_object *json_arr;
989 json_object *json_addr;
1a5607ea 990 struct json_object *json_auth = NULL;
d62a17ae 991
5aeb4f3c 992 default_iftype = ospf6_default_iftype(ifp);
d62a17ae 993
f16ae8cf 994 if (use_json) {
995 json_object_string_add(json_obj, "status",
996 (if_is_operative(ifp) ? "up" : "down"));
997 json_object_string_add(json_obj, "type",
998 ospf6_iftype_str(default_iftype));
999 json_object_int_add(json_obj, "interfaceId", ifp->ifindex);
1000
97b4474d 1001 if (ifp->info == NULL)
f16ae8cf 1002 return 0;
d62a17ae 1003
d62a17ae 1004 oi = (struct ospf6_interface *)ifp->info;
1005
f16ae8cf 1006 if (if_is_operative(ifp) && oi->type != default_iftype)
1007 json_object_string_add(json_obj, "operatingAsType",
1008 ospf6_iftype_str(oi->type));
1009
1010 } else {
1011 vty_out(vty, "%s is %s, type %s\n", ifp->name,
1012 (if_is_operative(ifp) ? "up" : "down"),
1013 ospf6_iftype_str(default_iftype));
1014 vty_out(vty, " Interface ID: %d\n", ifp->ifindex);
1015
1016 if (ifp->info == NULL) {
1017 vty_out(vty, " OSPF not enabled on this interface\n");
1018 return 0;
d62a17ae 1019 }
f16ae8cf 1020 oi = (struct ospf6_interface *)ifp->info;
1021
1022 if (if_is_operative(ifp) && oi->type != default_iftype)
1023 vty_out(vty, " Operating as type %s\n",
1024 ospf6_iftype_str(oi->type));
d62a17ae 1025 }
1026
f16ae8cf 1027 if (use_json) {
1028 json_arr = json_object_new_array();
1029 for (ALL_LIST_ELEMENTS_RO(ifp->connected, i, c)) {
1030 json_addr = json_object_new_object();
1031 p = c->address;
1032 prefix2str(p, strbuf, sizeof(strbuf));
1033 switch (p->family) {
1034 case AF_INET:
1035 json_object_string_add(json_addr, "type",
1036 "inet");
1037 json_object_string_add(json_addr, "address",
1038 strbuf);
1039 json_object_array_add(json_arr, json_addr);
1040 break;
1041 case AF_INET6:
1042 json_object_string_add(json_addr, "type",
1043 "inet6");
1044 json_object_string_add(json_addr, "address",
1045 strbuf);
1046 json_object_array_add(json_arr, json_addr);
1047 break;
1048 default:
1049 json_object_string_add(json_addr, "type",
1050 "unknown");
1051 json_object_string_add(json_addr, "address",
1052 strbuf);
1053 json_object_array_add(json_arr, json_addr);
1054 break;
1055 }
1056 }
1057 json_object_object_add(json_obj, "internetAddress", json_arr);
1058 } else {
1059 vty_out(vty, " Internet Address:\n");
1060
1061 for (ALL_LIST_ELEMENTS_RO(ifp->connected, i, c)) {
1062 p = c->address;
1063 prefix2str(p, strbuf, sizeof(strbuf));
1064 switch (p->family) {
1065 case AF_INET:
1066 vty_out(vty, " inet : %pFX\n", p);
1067 break;
1068 case AF_INET6:
1069 vty_out(vty, " inet6: %pFX\n", p);
1070 break;
1071 default:
1072 vty_out(vty, " ??? : %pFX\n", p);
1073 break;
1074 }
1075 }
1076 }
1077
1078 if (use_json) {
1079 if (oi->area) {
1080 json_object_boolean_true_add(json_obj,
1081 "attachedToArea");
1082 json_object_int_add(json_obj, "instanceId",
1083 oi->instance_id);
1084 json_object_int_add(json_obj, "interfaceMtu",
1085 oi->ifmtu);
1086 json_object_int_add(json_obj, "autoDetect", ifp->mtu6);
1087 json_object_string_add(json_obj, "mtuMismatchDetection",
1088 oi->mtu_ignore ? "disabled"
1089 : "enabled");
1090 inet_ntop(AF_INET, &oi->area->area_id, strbuf,
1091 sizeof(strbuf));
1092 json_object_string_add(json_obj, "areaId", strbuf);
1093 json_object_int_add(json_obj, "cost", oi->cost);
1094 } else
1095 json_object_boolean_false_add(json_obj,
1096 "attachedToArea");
1097
1098 } else {
1099 if (oi->area) {
1100 vty_out(vty,
1101 " Instance ID %d, Interface MTU %d (autodetect: %d)\n",
1102 oi->instance_id, oi->ifmtu, ifp->mtu6);
1103 vty_out(vty, " MTU mismatch detection: %s\n",
1104 oi->mtu_ignore ? "disabled" : "enabled");
1105 inet_ntop(AF_INET, &oi->area->area_id, strbuf,
1106 sizeof(strbuf));
1107 vty_out(vty, " Area ID %s, Cost %u\n", strbuf,
1108 oi->cost);
1109 } else
1110 vty_out(vty, " Not Attached to Area\n");
1111 }
1112
1113 if (use_json) {
1114 json_object_string_add(json_obj, "ospf6InterfaceState",
1115 ospf6_interface_state_str[oi->state]);
1116 json_object_int_add(json_obj, "transmitDelaySec",
1117 oi->transdelay);
1118 json_object_int_add(json_obj, "priority", oi->priority);
1119 json_object_int_add(json_obj, "timerIntervalsConfigHello",
1120 oi->hello_interval);
1121 json_object_int_add(json_obj, "timerIntervalsConfigDead",
1122 oi->dead_interval);
1123 json_object_int_add(json_obj, "timerIntervalsConfigRetransmit",
1124 oi->rxmt_interval);
93bae5f8
DA
1125 json_object_boolean_add(
1126 json_obj, "timerPassiveIface",
1127 !!CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE));
f16ae8cf 1128 } else {
1129 vty_out(vty, " State %s, Transmit Delay %d sec, Priority %d\n",
1130 ospf6_interface_state_str[oi->state], oi->transdelay,
1131 oi->priority);
1132 vty_out(vty, " Timer intervals configured:\n");
93bae5f8
DA
1133 if (!CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE))
1134 vty_out(vty,
1135 " Hello %d(%pTHd), Dead %d, Retransmit %d\n",
1136 oi->hello_interval, oi->thread_send_hello,
1137 oi->dead_interval, oi->rxmt_interval);
1138 else
1139 vty_out(vty, " No Hellos (Passive interface)\n");
f16ae8cf 1140 }
d62a17ae 1141
1142 inet_ntop(AF_INET, &oi->drouter, drouter, sizeof(drouter));
1143 inet_ntop(AF_INET, &oi->bdrouter, bdrouter, sizeof(bdrouter));
f16ae8cf 1144 if (use_json) {
1145 json_object_string_add(json_obj, "dr", drouter);
1146 json_object_string_add(json_obj, "bdr", bdrouter);
1147 json_object_int_add(json_obj, "numberOfInterfaceScopedLsa",
1148 oi->lsdb->count);
1149 } else {
1150 vty_out(vty, " DR: %s BDR: %s\n", drouter, bdrouter);
1151 vty_out(vty, " Number of I/F scoped LSAs is %u\n",
1152 oi->lsdb->count);
1153 }
d62a17ae 1154
1155 monotime(&now);
1156
f16ae8cf 1157 if (use_json) {
1158 timerclear(&res);
5f6eaa9b 1159 if (event_is_scheduled(oi->thread_send_lsupdate))
f16ae8cf 1160 timersub(&oi->thread_send_lsupdate->u.sands, &now,
1161 &res);
1162 timerstring(&res, duration, sizeof(duration));
1163 json_object_int_add(json_obj, "pendingLsaLsUpdateCount",
1164 oi->lsupdate_list->count);
1165 json_object_string_add(json_obj, "pendingLsaLsUpdateTime",
1166 duration);
1167 json_object_string_add(
1168 json_obj, "lsUpdateSendThread",
5f6eaa9b
DS
1169 (event_is_scheduled(oi->thread_send_lsupdate) ? "on"
1170 : "off"));
f16ae8cf 1171
1172 json_arr = json_object_new_array();
1173 for (ALL_LSDB(oi->lsupdate_list, lsa, lsanext))
1174 json_object_array_add(
1175 json_arr, json_object_new_string(lsa->name));
1176 json_object_object_add(json_obj, "pendingLsaLsUpdate",
1177 json_arr);
1178
1179 timerclear(&res);
5f6eaa9b 1180 if (event_is_scheduled(oi->thread_send_lsack))
f16ae8cf 1181 timersub(&oi->thread_send_lsack->u.sands, &now, &res);
1182 timerstring(&res, duration, sizeof(duration));
1183
1184 json_object_int_add(json_obj, "pendingLsaLsAckCount",
1185 oi->lsack_list->count);
1186 json_object_string_add(json_obj, "pendingLsaLsAckTime",
1187 duration);
c905f04c
DS
1188 json_object_string_add(
1189 json_obj, "lsAckSendThread",
5f6eaa9b
DS
1190 (event_is_scheduled(oi->thread_send_lsack) ? "on"
1191 : "off"));
f16ae8cf 1192
1193 json_arr = json_object_new_array();
1194 for (ALL_LSDB(oi->lsack_list, lsa, lsanext))
1195 json_object_array_add(
1196 json_arr, json_object_new_string(lsa->name));
1197 json_object_object_add(json_obj, "pendingLsaLsAck", json_arr);
1198
0c05ceae
RW
1199 if (oi->gr.hello_delay.interval != 0)
1200 json_object_int_add(json_obj, "grHelloDelaySecs",
1201 oi->gr.hello_delay.interval);
f16ae8cf 1202 } else {
1203 timerclear(&res);
5f6eaa9b 1204 if (event_is_scheduled(oi->thread_send_lsupdate))
f16ae8cf 1205 timersub(&oi->thread_send_lsupdate->u.sands, &now,
1206 &res);
1207 timerstring(&res, duration, sizeof(duration));
1208 vty_out(vty,
1209 " %d Pending LSAs for LSUpdate in Time %s [thread %s]\n",
1210 oi->lsupdate_list->count, duration,
5f6eaa9b
DS
1211 (event_is_scheduled(oi->thread_send_lsupdate) ? "on"
1212 : "off"));
f16ae8cf 1213 for (ALL_LSDB(oi->lsupdate_list, lsa, lsanext))
1214 vty_out(vty, " %s\n", lsa->name);
1215
1216 timerclear(&res);
5f6eaa9b 1217 if (event_is_scheduled(oi->thread_send_lsack))
f16ae8cf 1218 timersub(&oi->thread_send_lsack->u.sands, &now, &res);
1219 timerstring(&res, duration, sizeof(duration));
1220 vty_out(vty,
1221 " %d Pending LSAs for LSAck in Time %s [thread %s]\n",
1222 oi->lsack_list->count, duration,
5f6eaa9b
DS
1223 (event_is_scheduled(oi->thread_send_lsack) ? "on"
1224 : "off"));
f16ae8cf 1225 for (ALL_LSDB(oi->lsack_list, lsa, lsanext))
1226 vty_out(vty, " %s\n", lsa->name);
0c05ceae
RW
1227
1228 if (oi->gr.hello_delay.interval != 0)
1229 vty_out(vty, " Graceful Restart hello delay: %us\n",
1230 oi->gr.hello_delay.interval);
f16ae8cf 1231 }
d06cc416
RZ
1232
1233 /* BFD specific. */
1234 if (oi->bfd_config.enabled) {
1235 if (use_json) {
1236 struct json_object *json_bfd = json_object_new_object();
1237
1238 json_object_int_add(
1239 json_bfd, "detectMultiplier",
1240 oi->bfd_config.detection_multiplier);
1241 json_object_int_add(json_bfd, "rxMinInterval",
1242 oi->bfd_config.min_rx);
1243 json_object_int_add(json_bfd, "txMinInterval",
1244 oi->bfd_config.min_tx);
1245 json_object_object_add(json_obj, "peerBfdInfo",
1246 json_bfd);
1247 } else {
1248 vty_out(vty,
1249 " BFD: Detect Multiplier: %d, Min Rx interval: %d, Min Tx interval: %d\n",
1250 oi->bfd_config.detection_multiplier,
1251 oi->bfd_config.min_rx, oi->bfd_config.min_tx);
1252 }
1253 }
1254
21c6569d
DS
1255 if (use_json)
1256 json_auth = json_object_new_object();
1a5607ea
AR
1257 if (oi->at_data.flags != 0) {
1258 if (use_json) {
1259 if (CHECK_FLAG(oi->at_data.flags,
1260 OSPF6_AUTH_TRAILER_KEYCHAIN)) {
1261 json_object_string_add(json_auth, "authType",
1262 "keychain");
1263 json_object_string_add(json_auth,
1264 "keychainName",
1265 oi->at_data.keychain);
1266 } else if (CHECK_FLAG(oi->at_data.flags,
1267 OSPF6_AUTH_TRAILER_MANUAL_KEY))
1268 json_object_string_add(json_auth, "authType",
1269 "manualkey");
1a5607ea
AR
1270 json_object_int_add(json_auth, "txPktDrop",
1271 oi->at_data.tx_drop);
1272 json_object_int_add(json_auth, "rxPktDrop",
1273 oi->at_data.rx_drop);
1274 } else {
1275 if (CHECK_FLAG(oi->at_data.flags,
1276 OSPF6_AUTH_TRAILER_KEYCHAIN))
1277 vty_out(vty,
1278 " Authentication Trailer is enabled with key-chain %s\n",
1279 oi->at_data.keychain);
1280 else if (CHECK_FLAG(oi->at_data.flags,
1281 OSPF6_AUTH_TRAILER_MANUAL_KEY))
1282 vty_out(vty,
1283 " Authentication trailer is enabled with manual key\n");
1a5607ea
AR
1284 vty_out(vty,
1285 " Packet drop Tx %u, Packet drop Rx %u\n",
1286 oi->at_data.tx_drop, oi->at_data.rx_drop);
1287 }
1288 } else {
6cb85350 1289 if (use_json)
1a5607ea 1290 json_object_string_add(json_auth, "authType", "NULL");
6cb85350 1291 else
1a5607ea 1292 vty_out(vty, " Authentication Trailer is disabled\n");
1a5607ea
AR
1293 }
1294
1295 if (use_json)
1296 json_object_object_add(json_obj, "authInfo", json_auth);
1297
d62a17ae 1298 return 0;
718e3744 1299}
1300
ad500b22
K
1301/* Find the global address to be used as a forwarding address in NSSA LSA.*/
1302struct in6_addr *ospf6_interface_get_global_address(struct interface *ifp)
1303{
1304 struct listnode *n;
1305 struct connected *c;
ad500b22
K
1306
1307 /* for each connected address */
1308 for (ALL_LIST_ELEMENTS_RO(ifp->connected, n, c)) {
1309 /* if family not AF_INET6, ignore */
1310 if (c->address->family != AF_INET6)
1311 continue;
1312
1313 if (!IN6_IS_ADDR_LINKLOCAL(&c->address->u.prefix6))
5f2fe4bb 1314 return &c->address->u.prefix6;
ad500b22 1315 }
5f2fe4bb
RW
1316
1317 return NULL;
ad500b22
K
1318}
1319
1320
d48ef099 1321static int show_ospf6_interface_common(struct vty *vty, vrf_id_t vrf_id,
1322 int argc, struct cmd_token **argv,
1323 int idx_ifname, int intf_idx,
d6b901ac 1324 int json_idx, bool uj)
718e3744 1325{
d48ef099 1326
1327 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
d62a17ae 1328 struct interface *ifp;
f16ae8cf 1329 json_object *json;
1330 json_object *json_int;
f16ae8cf 1331
1332 if (uj) {
1333 json = json_object_new_object();
d48ef099 1334 if (argc == json_idx) {
1335 ifp = if_lookup_by_name(argv[idx_ifname]->arg, vrf_id);
f16ae8cf 1336 json_int = json_object_new_object();
1337 if (ifp == NULL) {
1338 json_object_string_add(json, "noSuchInterface",
1339 argv[idx_ifname]->arg);
5a6c232b 1340 vty_json(vty, json);
f16ae8cf 1341 json_object_free(json_int);
1342 return CMD_WARNING;
1343 }
1344 ospf6_interface_show(vty, ifp, json_int, uj);
1345 json_object_object_add(json, ifp->name, json_int);
1346 } else {
1347 FOR_ALL_INTERFACES (vrf, ifp) {
1348 json_int = json_object_new_object();
1349 ospf6_interface_show(vty, ifp, json_int, uj);
1350 json_object_object_add(json, ifp->name,
1351 json_int);
1352 }
d62a17ae 1353 }
5a6c232b 1354 vty_json(vty, json);
d62a17ae 1355 } else {
d48ef099 1356 if (argc == intf_idx) {
1357 ifp = if_lookup_by_name(argv[idx_ifname]->arg, vrf_id);
f16ae8cf 1358 if (ifp == NULL) {
1359 vty_out(vty, "No such Interface: %s\n",
1360 argv[idx_ifname]->arg);
1361 return CMD_WARNING;
1362 }
1363 ospf6_interface_show(vty, ifp, NULL, uj);
1364 } else {
1365 FOR_ALL_INTERFACES (vrf, ifp)
1366 ospf6_interface_show(vty, ifp, NULL, uj);
1367 }
d62a17ae 1368 }
d48ef099 1369 return CMD_SUCCESS;
1370}
1371
1372/* show interface */
1373DEFUN(show_ipv6_ospf6_interface, show_ipv6_ospf6_interface_ifname_cmd,
1374 "show ipv6 ospf6 [vrf <NAME|all>] interface [IFNAME] [json]",
1375 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1376 "All VRFs\n" INTERFACE_STR IFNAME_STR JSON_STR)
1377{
1378 int idx_ifname = 4;
1379 int intf_idx = 5;
1380 int json_idx = 6;
1381 struct listnode *node;
1382 struct ospf6 *ospf6;
1383 const char *vrf_name = NULL;
1384 bool all_vrf = false;
1385 int idx_vrf = 0;
d6b901ac 1386 bool uj = use_json(argc, argv);
d48ef099 1387
d48ef099 1388 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1389 if (idx_vrf > 0) {
1390 idx_ifname += 2;
1391 intf_idx += 2;
1392 json_idx += 2;
1393 }
1394
1395 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1396 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1397 show_ospf6_interface_common(vty, ospf6->vrf_id, argc,
1398 argv, idx_ifname, intf_idx,
d6b901ac 1399 json_idx, uj);
d48ef099 1400
1401 if (!all_vrf)
1402 break;
1403 }
1404 }
d62a17ae 1405
d6b901ac 1406 OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
1407
d62a17ae 1408 return CMD_SUCCESS;
718e3744 1409}
1410
c5d28568 1411static int ospf6_interface_show_traffic(struct vty *vty,
43855e3d 1412 struct interface *intf_ifp,
ba30b376 1413 int display_once, json_object *json,
d48ef099 1414 bool use_json, vrf_id_t vrf_id)
43855e3d
CS
1415{
1416 struct interface *ifp;
1417 struct vrf *vrf = NULL;
1418 struct ospf6_interface *oi = NULL;
ba30b376 1419 json_object *json_interface;
43855e3d 1420
ba30b376 1421 if (!display_once && !use_json) {
43855e3d 1422 vty_out(vty, "\n");
996c9314
LB
1423 vty_out(vty, "%-12s%-17s%-17s%-17s%-17s%-17s\n", "Interface",
1424 " HELLO", " DB-Desc", " LS-Req", " LS-Update",
1425 " LS-Ack");
43855e3d 1426 vty_out(vty, "%-10s%-18s%-18s%-17s%-17s%-17s\n", "",
996c9314
LB
1427 " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx",
1428 " Rx/Tx");
43855e3d 1429 vty_out(vty,
996c9314 1430 "--------------------------------------------------------------------------------------------\n");
43855e3d
CS
1431 }
1432
1433 if (intf_ifp == NULL) {
096f7609 1434 vrf = vrf_lookup_by_id(vrf_id);
43855e3d
CS
1435 FOR_ALL_INTERFACES (vrf, ifp) {
1436 if (ifp->info)
1437 oi = (struct ospf6_interface *)ifp->info;
1438 else
1439 continue;
1440
ba30b376 1441 if (use_json) {
1442 json_interface = json_object_new_object();
1443 json_object_int_add(json_interface, "helloRx",
1444 oi->hello_in);
1445 json_object_int_add(json_interface, "helloTx",
1446 oi->hello_out);
1447 json_object_int_add(json_interface, "dbDescRx",
1448 oi->db_desc_in);
1449 json_object_int_add(json_interface, "dbDescTx",
1450 oi->db_desc_out);
1451 json_object_int_add(json_interface, "lsReqRx",
1452 oi->ls_req_in);
1453 json_object_int_add(json_interface, "lsReqTx",
1454 oi->ls_req_out);
1455 json_object_int_add(json_interface,
1456 "lsUpdateRx",
1457 oi->ls_upd_in);
1458 json_object_int_add(json_interface,
1459 "lsUpdateTx",
1460 oi->ls_upd_out);
1461 json_object_int_add(json_interface, "lsAckRx",
1462 oi->ls_ack_in);
1463 json_object_int_add(json_interface, "lsAckTx",
1464 oi->ls_ack_out);
1465
1466 json_object_object_add(json,
1467 oi->interface->name,
1468 json_interface);
1469 } else
1470 vty_out(vty,
1471 "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u\n",
1472 oi->interface->name, oi->hello_in,
1473 oi->hello_out, oi->db_desc_in,
1474 oi->db_desc_out, oi->ls_req_in,
1475 oi->ls_req_out, oi->ls_upd_in,
1476 oi->ls_upd_out, oi->ls_ack_in,
1477 oi->ls_ack_out);
43855e3d
CS
1478 }
1479 } else {
1480 oi = intf_ifp->info;
1481 if (oi == NULL)
1482 return CMD_WARNING;
1483
ba30b376 1484 if (use_json) {
1485 json_interface = json_object_new_object();
1486 json_object_int_add(json_interface, "helloRx",
1487 oi->hello_in);
1488 json_object_int_add(json_interface, "helloTx",
1489 oi->hello_out);
1490 json_object_int_add(json_interface, "dbDescRx",
1491 oi->db_desc_in);
1492 json_object_int_add(json_interface, "dbDescTx",
1493 oi->db_desc_out);
1494 json_object_int_add(json_interface, "lsReqRx",
1495 oi->ls_req_in);
1496 json_object_int_add(json_interface, "lsReqTx",
1497 oi->ls_req_out);
1498 json_object_int_add(json_interface, "lsUpdateRx",
1499 oi->ls_upd_in);
1500 json_object_int_add(json_interface, "lsUpdateTx",
1501 oi->ls_upd_out);
1502 json_object_int_add(json_interface, "lsAckRx",
1503 oi->ls_ack_in);
1504 json_object_int_add(json_interface, "lsAckTx",
1505 oi->ls_ack_out);
1506
1507 json_object_object_add(json, oi->interface->name,
1508 json_interface);
1509 } else
1510 vty_out(vty,
1511 "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u\n",
1512 oi->interface->name, oi->hello_in,
1513 oi->hello_out, oi->db_desc_in, oi->db_desc_out,
1514 oi->ls_req_in, oi->ls_req_out, oi->ls_upd_in,
1515 oi->ls_upd_out, oi->ls_ack_in, oi->ls_ack_out);
43855e3d
CS
1516 }
1517
1518 return CMD_SUCCESS;
1519}
1520
d48ef099 1521static int ospf6_interface_show_traffic_common(struct vty *vty, int argc,
1522 struct cmd_token **argv,
d6b901ac 1523 vrf_id_t vrf_id, bool uj)
43855e3d
CS
1524{
1525 int idx_ifname = 0;
1526 int display_once = 0;
1527 char *intf_name = NULL;
1528 struct interface *ifp = NULL;
ba30b376 1529 json_object *json = NULL;
ba30b376 1530
1531 if (uj)
1532 json = json_object_new_object();
43855e3d
CS
1533
1534 if (argv_find(argv, argc, "IFNAME", &idx_ifname)) {
1535 intf_name = argv[idx_ifname]->arg;
d48ef099 1536 ifp = if_lookup_by_name(intf_name, vrf_id);
ba30b376 1537 if (uj) {
1538 if (ifp == NULL) {
1539 json_object_string_add(json, "status",
1540 "No Such Interface");
1541 json_object_string_add(json, "interface",
1542 intf_name);
5a6c232b 1543 vty_json(vty, json);
ba30b376 1544 return CMD_WARNING;
1545 }
1546 if (ifp->info == NULL) {
1547 json_object_string_add(
1548 json, "status",
1549 "OSPF not enabled on this interface");
1550 json_object_string_add(json, "interface",
1551 intf_name);
5a6c232b 1552 vty_json(vty, json);
ba30b376 1553 return 0;
1554 }
1555 } else {
1556 if (ifp == NULL) {
1557 vty_out(vty, "No such Interface: %s\n",
1558 intf_name);
1559 return CMD_WARNING;
1560 }
1561 if (ifp->info == NULL) {
1562 vty_out(vty,
1563 " OSPF not enabled on this interface %s\n",
1564 intf_name);
1565 return 0;
1566 }
43855e3d
CS
1567 }
1568 }
1569
d48ef099 1570 ospf6_interface_show_traffic(vty, ifp, display_once, json, uj, vrf_id);
ba30b376 1571
c48349e3 1572 if (uj)
5a6c232b 1573 vty_json(vty, json);
43855e3d 1574
d48ef099 1575 return CMD_SUCCESS;
1576}
1577
1578/* show interface */
1579DEFUN(show_ipv6_ospf6_interface_traffic, show_ipv6_ospf6_interface_traffic_cmd,
1580 "show ipv6 ospf6 [vrf <NAME|all>] interface traffic [IFNAME] [json]",
1581 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1582 "All VRFs\n" INTERFACE_STR
1583 "Protocol Packet counters\n" IFNAME_STR JSON_STR)
1584{
1585 struct ospf6 *ospf6;
1586 struct listnode *node;
1587 const char *vrf_name = NULL;
1588 bool all_vrf = false;
1589 int idx_vrf = 0;
d6b901ac 1590 bool uj = use_json(argc, argv);
d48ef099 1591
d48ef099 1592 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1593
1594 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1595 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1596 ospf6_interface_show_traffic_common(vty, argc, argv,
d6b901ac 1597 ospf6->vrf_id, uj);
d48ef099 1598
1599 if (!all_vrf)
1600 break;
1601 }
1602 }
43855e3d 1603
d6b901ac 1604 OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
1605
43855e3d
CS
1606 return CMD_SUCCESS;
1607}
1608
1609
d48ef099 1610DEFUN(show_ipv6_ospf6_interface_ifname_prefix,
1611 show_ipv6_ospf6_interface_ifname_prefix_cmd,
1612 "show ipv6 ospf6 [vrf <NAME|all>] interface IFNAME prefix\
25ee05c9
RW
1613 [<\
1614 detail\
1615 |<X:X::X:X|X:X::X:X/M> [<match|detail>]\
35aeb295 1616 >] [json]",
d48ef099 1617 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1618 "All VRFs\n" INTERFACE_STR IFNAME_STR
1619 "Display connected prefixes to advertise\n"
1620 "Display details of the prefixes\n" OSPF6_ROUTE_ADDRESS_STR
1621 OSPF6_ROUTE_PREFIX_STR OSPF6_ROUTE_MATCH_STR
1622 "Display details of the prefixes\n" JSON_STR)
508e53e2 1623{
d62a17ae 1624 int idx_ifname = 4;
1625 int idx_prefix = 6;
d62a17ae 1626 struct ospf6_interface *oi;
35aeb295 1627 bool uj = use_json(argc, argv);
d62a17ae 1628
d48ef099 1629 struct ospf6 *ospf6;
1630 struct listnode *node;
1631 struct interface *ifp;
1632 const char *vrf_name = NULL;
1633 bool all_vrf = false;
1634 int idx_vrf = 0;
1635
d48ef099 1636 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1637 if (idx_vrf > 0) {
1638 idx_ifname += 2;
1639 idx_prefix += 2;
d62a17ae 1640 }
1641
d48ef099 1642 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1643 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1644 ifp = if_lookup_by_name(argv[idx_ifname]->arg,
1645 ospf6->vrf_id);
1646 if (ifp == NULL) {
1647 vty_out(vty, "No such Interface: %s\n",
1648 argv[idx_ifname]->arg);
1649 return CMD_WARNING;
1650 }
d62a17ae 1651
d48ef099 1652 oi = ifp->info;
1653 if (oi == NULL
1654 || CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) {
1655 vty_out(vty,
1656 "Interface %s not attached to area\n",
1657 argv[idx_ifname]->arg);
1658 return CMD_WARNING;
1659 }
d100d0b0 1660
d48ef099 1661 ospf6_route_table_show(vty, idx_prefix, argc, argv,
1662 oi->route_connected, uj);
1663
1664 if (!all_vrf)
1665 break;
1666 }
1667 }
d62a17ae 1668
d6b901ac 1669 OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
1670
d62a17ae 1671 return CMD_SUCCESS;
508e53e2 1672}
1673
d48ef099 1674DEFUN(show_ipv6_ospf6_interface_prefix, show_ipv6_ospf6_interface_prefix_cmd,
1675 "show ipv6 ospf6 [vrf <NAME|all>] interface prefix\
25ee05c9
RW
1676 [<\
1677 detail\
1678 |<X:X::X:X|X:X::X:X/M> [<match|detail>]\
35aeb295 1679 >] [json]",
d48ef099 1680 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1681 "All VRFs\n" INTERFACE_STR
1682 "Display connected prefixes to advertise\n"
1683 "Display details of the prefixes\n" OSPF6_ROUTE_ADDRESS_STR
1684 OSPF6_ROUTE_PREFIX_STR OSPF6_ROUTE_MATCH_STR
1685 "Display details of the prefixes\n" JSON_STR)
508e53e2 1686{
d48ef099 1687 struct vrf *vrf = NULL;
d62a17ae 1688 int idx_prefix = 5;
d62a17ae 1689 struct ospf6_interface *oi;
1690 struct interface *ifp;
35aeb295 1691 bool uj = use_json(argc, argv);
d48ef099 1692 struct listnode *node;
1693 struct ospf6 *ospf6;
1694 const char *vrf_name = NULL;
1695 bool all_vrf = false;
1696 int idx_vrf = 0;
1697
d48ef099 1698 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1699 if (idx_vrf > 0)
1700 idx_prefix += 2;
1701
1702 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1703 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1704 vrf = vrf_lookup_by_id(ospf6->vrf_id);
1705 FOR_ALL_INTERFACES (vrf, ifp) {
1706 oi = (struct ospf6_interface *)ifp->info;
1707 if (oi == NULL
1708 || CHECK_FLAG(oi->flag,
1709 OSPF6_INTERFACE_DISABLE))
1710 continue;
1711
1712 ospf6_route_table_show(vty, idx_prefix, argc,
1713 argv,
1714 oi->route_connected, uj);
1715 }
1716 if (!all_vrf)
1717 break;
1718 }
d62a17ae 1719 }
508e53e2 1720
d6b901ac 1721 OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
1722
d62a17ae 1723 return CMD_SUCCESS;
508e53e2 1724}
1725
42cabc55
IR
1726void ospf6_interface_start(struct ospf6_interface *oi)
1727{
1728 struct ospf6 *ospf6;
1729 struct ospf6_area *oa;
1730
1731 if (oi->area_id_format == OSPF6_AREA_FMT_UNSET)
1732 return;
1733
4f0d3f3e 1734 if (oi->area) {
1735 /* Recompute cost */
1736 ospf6_interface_recalculate_cost(oi);
40699728 1737 return;
4f0d3f3e 1738 }
40699728 1739
096f7609 1740 ospf6 = oi->interface->vrf->info;
42cabc55
IR
1741 if (!ospf6)
1742 return;
1743
1744 oa = ospf6_area_lookup(oi->area_id, ospf6);
1745 if (oa == NULL)
1746 oa = ospf6_area_create(oi->area_id, ospf6, oi->area_id_format);
1747
1748 /* attach interface to area */
1749 listnode_add(oa->if_list, oi);
1750 oi->area = oa;
1751
1752 SET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
1753
1754 /* start up */
1755 ospf6_interface_enable(oi);
1756
1757 /* If the router is ABR, originate summary routes */
a7c1a27f 1758 if (ospf6_check_and_set_router_abr(ospf6)) {
42cabc55 1759 ospf6_abr_enable_area(oa);
a7c1a27f
PK
1760 ospf6_schedule_abr_task(ospf6);
1761 }
42cabc55
IR
1762}
1763
1764void ospf6_interface_stop(struct ospf6_interface *oi)
1765{
1766 struct ospf6_area *oa;
1767
1768 oa = oi->area;
1769 if (!oa)
1770 return;
1771
1772 ospf6_interface_disable(oi);
1773
1774 listnode_delete(oa->if_list, oi);
1775 oi->area = NULL;
1776
1777 if (oa->if_list->count == 0) {
1778 UNSET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
1779 ospf6_abr_disable_area(oa);
1780 }
1781}
1782
718e3744 1783/* interface variable set command */
42cabc55
IR
1784DEFUN (ipv6_ospf6_area,
1785 ipv6_ospf6_area_cmd,
1786 "ipv6 ospf6 area <A.B.C.D|(0-4294967295)>",
1787 IP6_STR
1788 OSPF6_STR
1789 "Specify the OSPF6 area ID\n"
1790 "OSPF6 area ID in IPv4 address notation\n"
1791 "OSPF6 area ID in decimal notation\n")
1792{
1793 VTY_DECLVAR_CONTEXT(interface, ifp);
1794 struct ospf6_interface *oi;
1795 int idx_ipv4 = 3;
1796 uint32_t area_id;
1797 int format;
42cabc55
IR
1798
1799 assert(ifp);
1800
1801 oi = (struct ospf6_interface *)ifp->info;
1802 if (oi == NULL)
1803 oi = ospf6_interface_create(ifp);
1804 assert(oi);
1805
1806 if (oi->area) {
1807 vty_out(vty, "%s already attached to Area %s\n",
1808 oi->interface->name, oi->area->name);
1809 return CMD_SUCCESS;
1810 }
1811
42cabc55
IR
1812 if (str2area_id(argv[idx_ipv4]->arg, &area_id, &format)) {
1813 vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4]->arg);
1814 return CMD_WARNING_CONFIG_FAILED;
1815 }
1816
1817 oi->area_id = area_id;
1818 oi->area_id_format = format;
1819
1820 ospf6_interface_start(oi);
1821
1822 return CMD_SUCCESS;
1823}
1824
1825DEFUN (no_ipv6_ospf6_area,
1826 no_ipv6_ospf6_area_cmd,
1827 "no ipv6 ospf6 area [<A.B.C.D|(0-4294967295)>]",
1828 NO_STR
1829 IP6_STR
1830 OSPF6_STR
1831 "Specify the OSPF6 area ID\n"
1832 "OSPF6 area ID in IPv4 address notation\n"
1833 "OSPF6 area ID in decimal notation\n")
1834{
1835 VTY_DECLVAR_CONTEXT(interface, ifp);
1836 struct ospf6_interface *oi;
1837
1838 assert(ifp);
1839
1840 oi = (struct ospf6_interface *)ifp->info;
1841 if (oi == NULL)
1842 oi = ospf6_interface_create(ifp);
1843 assert(oi);
1844
1845 ospf6_interface_stop(oi);
1846
1847 oi->area_id = 0;
1848 oi->area_id_format = OSPF6_AREA_FMT_UNSET;
1849
1850 return CMD_SUCCESS;
1851}
1852
b596c71e 1853DEFUN (ipv6_ospf6_ifmtu,
1854 ipv6_ospf6_ifmtu_cmd,
6147e2c6 1855 "ipv6 ospf6 ifmtu (1-65535)",
b596c71e 1856 IP6_STR
1857 OSPF6_STR
1858 "Interface MTU\n"
1859 "OSPFv3 Interface MTU\n"
1860 )
1861{
d62a17ae 1862 VTY_DECLVAR_CONTEXT(interface, ifp);
1863 int idx_number = 3;
1864 struct ospf6_interface *oi;
1865 unsigned int ifmtu, iobuflen;
1866 struct listnode *node, *nnode;
1867 struct ospf6_neighbor *on;
1868
1869 assert(ifp);
1870
1871 oi = (struct ospf6_interface *)ifp->info;
1872 if (oi == NULL)
1873 oi = ospf6_interface_create(ifp);
1874 assert(oi);
1875
1876 ifmtu = strtol(argv[idx_number]->arg, NULL, 10);
1877
1878 if (oi->c_ifmtu == ifmtu)
1879 return CMD_SUCCESS;
1880
1881 if (ifp->mtu6 != 0 && ifp->mtu6 < ifmtu) {
1882 vty_out(vty,
1883 "%s's ospf6 ifmtu cannot go beyond physical mtu (%d)\n",
1884 ifp->name, ifp->mtu6);
1885 return CMD_WARNING_CONFIG_FAILED;
1886 }
1887
1888 if (oi->ifmtu < ifmtu) {
1889 iobuflen = ospf6_iobuf_size(ifmtu);
1890 if (iobuflen < ifmtu) {
1891 vty_out(vty,
1892 "%s's ifmtu is adjusted to I/O buffer size (%d).\n",
1893 ifp->name, iobuflen);
1894 oi->ifmtu = oi->c_ifmtu = iobuflen;
1895 } else
1896 oi->ifmtu = oi->c_ifmtu = ifmtu;
1897 } else
1898 oi->ifmtu = oi->c_ifmtu = ifmtu;
1899
1900 /* re-establish adjacencies */
1901 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) {
e16d030c 1902 EVENT_OFF(on->inactivity_timer);
907a2395 1903 event_add_event(master, inactivity_timer, on, 0, NULL);
d62a17ae 1904 }
1905
1906 return CMD_SUCCESS;
b596c71e 1907}
1908
049207c3 1909DEFUN (no_ipv6_ospf6_ifmtu,
1910 no_ipv6_ospf6_ifmtu_cmd,
0c7ef48a 1911 "no ipv6 ospf6 ifmtu [(1-65535)]",
049207c3 1912 NO_STR
1913 IP6_STR
1914 OSPF6_STR
1915 "Interface MTU\n"
0c7ef48a 1916 "OSPFv3 Interface MTU\n"
049207c3 1917 )
1918{
d62a17ae 1919 VTY_DECLVAR_CONTEXT(interface, ifp);
1920 struct ospf6_interface *oi;
1921 unsigned int iobuflen;
1922 struct listnode *node, *nnode;
1923 struct ospf6_neighbor *on;
1924
1925 assert(ifp);
1926
1927 oi = (struct ospf6_interface *)ifp->info;
1928 if (oi == NULL)
1929 oi = ospf6_interface_create(ifp);
1930 assert(oi);
1931
1932 if (oi->ifmtu < ifp->mtu) {
1933 iobuflen = ospf6_iobuf_size(ifp->mtu);
1934 if (iobuflen < ifp->mtu) {
1935 vty_out(vty,
1936 "%s's ifmtu is adjusted to I/O buffer size (%d).\n",
1937 ifp->name, iobuflen);
1938 oi->ifmtu = iobuflen;
1939 } else
1940 oi->ifmtu = ifp->mtu;
1941 } else
1942 oi->ifmtu = ifp->mtu;
1943
1944 oi->c_ifmtu = 0;
1945
1946 /* re-establish adjacencies */
1947 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) {
e16d030c 1948 EVENT_OFF(on->inactivity_timer);
907a2395 1949 event_add_event(master, inactivity_timer, on, 0, NULL);
d62a17ae 1950 }
1951
1952 return CMD_SUCCESS;
049207c3 1953}
1954
718e3744 1955DEFUN (ipv6_ospf6_cost,
1956 ipv6_ospf6_cost_cmd,
6147e2c6 1957 "ipv6 ospf6 cost (1-65535)",
718e3744 1958 IP6_STR
1959 OSPF6_STR
1960 "Interface cost\n"
32573073 1961 "Outgoing metric of this interface\n")
718e3744 1962{
d62a17ae 1963 VTY_DECLVAR_CONTEXT(interface, ifp);
1964 int idx_number = 3;
1965 struct ospf6_interface *oi;
1966 unsigned long int lcost;
1967
1968 assert(ifp);
1969
1970 oi = (struct ospf6_interface *)ifp->info;
1971 if (oi == NULL)
1972 oi = ospf6_interface_create(ifp);
1973 assert(oi);
1974
1975 lcost = strtol(argv[idx_number]->arg, NULL, 10);
1976
1977 if (lcost > UINT32_MAX) {
1978 vty_out(vty, "Cost %ld is out of range\n", lcost);
1979 return CMD_WARNING_CONFIG_FAILED;
1980 }
1981
7bfc5ae8 1982 SET_FLAG(oi->flag, OSPF6_INTERFACE_NOAUTOCOST);
d62a17ae 1983 if (oi->cost == lcost)
1984 return CMD_SUCCESS;
1985
1986 oi->cost = lcost;
0db8196a 1987 ospf6_interface_force_recalculate_cost(oi);
d62a17ae 1988
1989 return CMD_SUCCESS;
c19543b2
VB
1990}
1991
1992DEFUN (no_ipv6_ospf6_cost,
1993 no_ipv6_ospf6_cost_cmd,
32573073 1994 "no ipv6 ospf6 cost [(1-65535)]",
c19543b2
VB
1995 NO_STR
1996 IP6_STR
1997 OSPF6_STR
1998 "Calculate interface cost from bandwidth\n"
32573073 1999 "Outgoing metric of this interface\n")
c19543b2 2000{
d62a17ae 2001 VTY_DECLVAR_CONTEXT(interface, ifp);
2002 struct ospf6_interface *oi;
2003 assert(ifp);
c19543b2 2004
d62a17ae 2005 oi = (struct ospf6_interface *)ifp->info;
2006 if (oi == NULL)
2007 oi = ospf6_interface_create(ifp);
2008 assert(oi);
c19543b2 2009
d62a17ae 2010 UNSET_FLAG(oi->flag, OSPF6_INTERFACE_NOAUTOCOST);
c19543b2 2011
d62a17ae 2012 ospf6_interface_recalculate_cost(oi);
718e3744 2013
d62a17ae 2014 return CMD_SUCCESS;
718e3744 2015}
2016
fd500689
VB
2017DEFUN (auto_cost_reference_bandwidth,
2018 auto_cost_reference_bandwidth_cmd,
6147e2c6 2019 "auto-cost reference-bandwidth (1-4294967)",
fd500689
VB
2020 "Calculate OSPF interface cost according to bandwidth\n"
2021 "Use reference bandwidth method to assign OSPF cost\n"
2022 "The reference bandwidth in terms of Mbits per second\n")
2023{
d62a17ae 2024 VTY_DECLVAR_CONTEXT(ospf6, o);
2025 int idx_number = 2;
2026 struct ospf6_area *oa;
2027 struct ospf6_interface *oi;
2028 struct listnode *i, *j;
d7c0a89a 2029 uint32_t refbw;
d62a17ae 2030
2031 refbw = strtol(argv[idx_number]->arg, NULL, 10);
2032 if (refbw < 1 || refbw > 4294967) {
2033 vty_out(vty, "reference-bandwidth value is invalid\n");
2034 return CMD_WARNING_CONFIG_FAILED;
2035 }
2036
2037 /* If reference bandwidth is changed. */
2038 if ((refbw) == o->ref_bandwidth)
2039 return CMD_SUCCESS;
2040
2041 o->ref_bandwidth = refbw;
2042 for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa))
2043 for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi))
2044 ospf6_interface_recalculate_cost(oi);
2045
2046 return CMD_SUCCESS;
fd500689
VB
2047}
2048
2049DEFUN (no_auto_cost_reference_bandwidth,
2050 no_auto_cost_reference_bandwidth_cmd,
ccb8e0c7 2051 "no auto-cost reference-bandwidth [(1-4294967)]",
fd500689
VB
2052 NO_STR
2053 "Calculate OSPF interface cost according to bandwidth\n"
1d68dbfe
DW
2054 "Use reference bandwidth method to assign OSPF cost\n"
2055 "The reference bandwidth in terms of Mbits per second\n")
fd500689 2056{
d62a17ae 2057 VTY_DECLVAR_CONTEXT(ospf6, o);
2058 struct ospf6_area *oa;
2059 struct ospf6_interface *oi;
2060 struct listnode *i, *j;
fd500689 2061
d62a17ae 2062 if (o->ref_bandwidth == OSPF6_REFERENCE_BANDWIDTH)
2063 return CMD_SUCCESS;
fd500689 2064
d62a17ae 2065 o->ref_bandwidth = OSPF6_REFERENCE_BANDWIDTH;
2066 for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa))
2067 for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi))
2068 ospf6_interface_recalculate_cost(oi);
fd500689 2069
d62a17ae 2070 return CMD_SUCCESS;
fd500689
VB
2071}
2072
813d4307 2073
78156066
PR
2074DEFUN (ospf6_write_multiplier,
2075 ospf6_write_multiplier_cmd,
2076 "write-multiplier (1-100)",
2077 "Write multiplier\n"
2078 "Maximum number of interface serviced per write\n")
2079{
2080 VTY_DECLVAR_CONTEXT(ospf6, o);
2081 uint32_t write_oi_count;
2082
2083 write_oi_count = strtol(argv[1]->arg, NULL, 10);
2084 if (write_oi_count < 1 || write_oi_count > 100) {
2085 vty_out(vty, "write-multiplier value is invalid\n");
2086 return CMD_WARNING_CONFIG_FAILED;
2087 }
2088
2089 o->write_oi_count = write_oi_count;
2090 return CMD_SUCCESS;
2091}
2092
2093DEFUN (no_ospf6_write_multiplier,
2094 no_ospf6_write_multiplier_cmd,
2095 "no write-multiplier (1-100)",
2096 NO_STR
2097 "Write multiplier\n"
2098 "Maximum number of interface serviced per write\n")
2099{
2100 VTY_DECLVAR_CONTEXT(ospf6, o);
2101
2102 o->write_oi_count = OSPF6_WRITE_INTERFACE_COUNT_DEFAULT;
2103 return CMD_SUCCESS;
2104}
2105
718e3744 2106DEFUN (ipv6_ospf6_hellointerval,
2107 ipv6_ospf6_hellointerval_cmd,
6147e2c6 2108 "ipv6 ospf6 hello-interval (1-65535)",
718e3744 2109 IP6_STR
2110 OSPF6_STR
99a522c7 2111 "Time between HELLO packets\n"
d23d6de8 2112 SECONDS_STR)
718e3744 2113{
d62a17ae 2114 VTY_DECLVAR_CONTEXT(interface, ifp);
2115 int idx_number = 3;
2116 struct ospf6_interface *oi;
2117 assert(ifp);
2118
2119 oi = (struct ospf6_interface *)ifp->info;
2120 if (oi == NULL)
2121 oi = ospf6_interface_create(ifp);
2122 assert(oi);
2123
d23d6de8
QY
2124 oi->hello_interval = strmatch(argv[0]->text, "no")
2125 ? OSPF_HELLO_INTERVAL_DEFAULT
2126 : strtoul(argv[idx_number]->arg, NULL, 10);
578e092a
DS
2127
2128 /*
2129 * If the thread is scheduled, send the new hello now.
2130 */
5f6eaa9b 2131 if (event_is_scheduled(oi->thread_send_hello)) {
e16d030c 2132 EVENT_OFF(oi->thread_send_hello);
578e092a 2133
907a2395
DS
2134 event_add_timer(master, ospf6_hello_send, oi, 0,
2135 &oi->thread_send_hello);
578e092a 2136 }
d62a17ae 2137 return CMD_SUCCESS;
718e3744 2138}
2139
d23d6de8
QY
2140ALIAS (ipv6_ospf6_hellointerval,
2141 no_ipv6_ospf6_hellointerval_cmd,
2142 "no ipv6 ospf6 hello-interval [(1-65535)]",
2143 NO_STR
2144 IP6_STR
2145 OSPF6_STR
2146 "Time between HELLO packets\n"
2147 SECONDS_STR)
2148
718e3744 2149/* interface variable set command */
2150DEFUN (ipv6_ospf6_deadinterval,
2151 ipv6_ospf6_deadinterval_cmd,
6147e2c6 2152 "ipv6 ospf6 dead-interval (1-65535)",
718e3744 2153 IP6_STR
2154 OSPF6_STR
508e53e2 2155 "Interval time after which a neighbor is declared down\n"
d23d6de8 2156 SECONDS_STR)
718e3744 2157{
d62a17ae 2158 VTY_DECLVAR_CONTEXT(interface, ifp);
2159 int idx_number = 3;
2160 struct ospf6_interface *oi;
2161 assert(ifp);
2162
2163 oi = (struct ospf6_interface *)ifp->info;
2164 if (oi == NULL)
2165 oi = ospf6_interface_create(ifp);
2166 assert(oi);
2167
d23d6de8
QY
2168 oi->dead_interval = strmatch(argv[0]->arg, "no")
2169 ? OSPF_ROUTER_DEAD_INTERVAL_DEFAULT
2170 : strtoul(argv[idx_number]->arg, NULL, 10);
d62a17ae 2171 return CMD_SUCCESS;
718e3744 2172}
2173
d23d6de8
QY
2174ALIAS (ipv6_ospf6_deadinterval,
2175 no_ipv6_ospf6_deadinterval_cmd,
2176 "no ipv6 ospf6 dead-interval [(1-65535)]",
2177 NO_STR
2178 IP6_STR
2179 OSPF6_STR
2180 "Interval time after which a neighbor is declared down\n"
2181 SECONDS_STR)
2182
0c05ceae
RW
2183DEFPY(ipv6_ospf6_gr_hdelay, ipv6_ospf6_gr_hdelay_cmd,
2184 "ipv6 ospf6 graceful-restart hello-delay (1-1800)",
2185 IP6_STR
2186 OSPF6_STR
2187 "Graceful Restart parameters\n"
2188 "Delay the sending of the first hello packets.\n"
2189 "Delay in seconds\n")
2190{
2191 VTY_DECLVAR_CONTEXT(interface, ifp);
2192 struct ospf6_interface *oi;
2193
2194 oi = ifp->info;
2195 if (oi == NULL)
2196 oi = ospf6_interface_create(ifp);
2197
2198 /* Note: new or updated value won't affect ongoing graceful restart. */
2199 oi->gr.hello_delay.interval = hello_delay;
2200
2201 return CMD_SUCCESS;
2202}
2203
2204DEFPY(no_ipv6_ospf6_gr_hdelay, no_ipv6_ospf6_gr_hdelay_cmd,
2205 "no ipv6 ospf6 graceful-restart hello-delay [(1-1800)]",
2206 NO_STR
2207 IP6_STR
2208 OSPF6_STR
2209 "Graceful Restart parameters\n"
2210 "Delay the sending of the first hello packets.\n"
2211 "Delay in seconds\n")
2212{
2213 VTY_DECLVAR_CONTEXT(interface, ifp);
2214 struct ospf6_interface *oi;
2215
2216 oi = ifp->info;
2217 if (oi == NULL)
2218 oi = ospf6_interface_create(ifp);
2219
2220 oi->gr.hello_delay.interval = OSPF_HELLO_DELAY_DEFAULT;
2221 oi->gr.hello_delay.elapsed_seconds = 0;
2222 EVENT_OFF(oi->gr.hello_delay.t_grace_send);
2223
2224 return CMD_SUCCESS;
2225}
2226
718e3744 2227/* interface variable set command */
2228DEFUN (ipv6_ospf6_transmitdelay,
2229 ipv6_ospf6_transmitdelay_cmd,
6147e2c6 2230 "ipv6 ospf6 transmit-delay (1-3600)",
718e3744 2231 IP6_STR
2232 OSPF6_STR
99a522c7 2233 "Link state transmit delay\n"
98cfd06b 2234 SECONDS_STR)
718e3744 2235{
d62a17ae 2236 VTY_DECLVAR_CONTEXT(interface, ifp);
2237 int idx_number = 3;
2238 struct ospf6_interface *oi;
2239 assert(ifp);
2240
2241 oi = (struct ospf6_interface *)ifp->info;
2242 if (oi == NULL)
2243 oi = ospf6_interface_create(ifp);
2244 assert(oi);
2245
d23d6de8
QY
2246 oi->transdelay = strmatch(argv[0]->text, "no")
2247 ? OSPF6_INTERFACE_TRANSDELAY
2248 : strtoul(argv[idx_number]->arg, NULL, 10);
d62a17ae 2249 return CMD_SUCCESS;
718e3744 2250}
2251
d23d6de8
QY
2252ALIAS (ipv6_ospf6_transmitdelay,
2253 no_ipv6_ospf6_transmitdelay_cmd,
2254 "no ipv6 ospf6 transmit-delay [(1-3600)]",
2255 NO_STR
2256 IP6_STR
2257 OSPF6_STR
2258 "Link state transmit delay\n"
2259 SECONDS_STR)
2260
718e3744 2261/* interface variable set command */
2262DEFUN (ipv6_ospf6_retransmitinterval,
2263 ipv6_ospf6_retransmitinterval_cmd,
6147e2c6 2264 "ipv6 ospf6 retransmit-interval (1-65535)",
718e3744 2265 IP6_STR
2266 OSPF6_STR
2267 "Time between retransmitting lost link state advertisements\n"
d23d6de8 2268 SECONDS_STR)
718e3744 2269{
d62a17ae 2270 VTY_DECLVAR_CONTEXT(interface, ifp);
2271 int idx_number = 3;
2272 struct ospf6_interface *oi;
2273 assert(ifp);
2274
2275 oi = (struct ospf6_interface *)ifp->info;
2276 if (oi == NULL)
2277 oi = ospf6_interface_create(ifp);
2278 assert(oi);
2279
d23d6de8
QY
2280 oi->rxmt_interval = strmatch(argv[0]->text, "no")
2281 ? OSPF_RETRANSMIT_INTERVAL_DEFAULT
2282 : strtoul(argv[idx_number]->arg, NULL, 10);
d62a17ae 2283 return CMD_SUCCESS;
718e3744 2284}
2285
d23d6de8
QY
2286ALIAS (ipv6_ospf6_retransmitinterval,
2287 no_ipv6_ospf6_retransmitinterval_cmd,
2288 "no ipv6 ospf6 retransmit-interval [(1-65535)]",
2289 NO_STR
2290 IP6_STR
2291 OSPF6_STR
2292 "Time between retransmitting lost link state advertisements\n"
2293 SECONDS_STR)
2294
718e3744 2295/* interface variable set command */
2296DEFUN (ipv6_ospf6_priority,
2297 ipv6_ospf6_priority_cmd,
6147e2c6 2298 "ipv6 ospf6 priority (0-255)",
718e3744 2299 IP6_STR
2300 OSPF6_STR
2301 "Router priority\n"
d23d6de8 2302 "Priority value\n")
718e3744 2303{
d62a17ae 2304 VTY_DECLVAR_CONTEXT(interface, ifp);
2305 int idx_number = 3;
2306 struct ospf6_interface *oi;
2307 assert(ifp);
718e3744 2308
d62a17ae 2309 oi = (struct ospf6_interface *)ifp->info;
2310 if (oi == NULL)
2311 oi = ospf6_interface_create(ifp);
2312 assert(oi);
508e53e2 2313
d23d6de8
QY
2314 oi->priority = strmatch(argv[0]->text, "no")
2315 ? OSPF6_INTERFACE_PRIORITY
2316 : strtoul(argv[idx_number]->arg, NULL, 10);
718e3744 2317
17ab36c6
YR
2318 if (oi->area
2319 && (oi->state == OSPF6_INTERFACE_DROTHER
2320 || oi->state == OSPF6_INTERFACE_BDR
2321 || oi->state == OSPF6_INTERFACE_DR)) {
2322 if (ospf6_interface_state_change(dr_election(oi), oi) == -1)
2323 OSPF6_LINK_LSA_SCHEDULE(oi);
2324 }
718e3744 2325
d62a17ae 2326 return CMD_SUCCESS;
718e3744 2327}
2328
d23d6de8
QY
2329ALIAS (ipv6_ospf6_priority,
2330 no_ipv6_ospf6_priority_cmd,
2331 "no ipv6 ospf6 priority [(0-255)]",
2332 NO_STR
2333 IP6_STR
2334 OSPF6_STR
2335 "Router priority\n"
2336 "Priority value\n")
2337
718e3744 2338DEFUN (ipv6_ospf6_instance,
2339 ipv6_ospf6_instance_cmd,
6147e2c6 2340 "ipv6 ospf6 instance-id (0-255)",
718e3744 2341 IP6_STR
2342 OSPF6_STR
508e53e2 2343 "Instance ID for this interface\n"
d23d6de8 2344 "Instance ID value\n")
718e3744 2345{
d62a17ae 2346 VTY_DECLVAR_CONTEXT(interface, ifp);
2347 int idx_number = 3;
2348 struct ospf6_interface *oi;
2349 assert(ifp);
2350
2351 oi = (struct ospf6_interface *)ifp->info;
2352 if (oi == NULL)
2353 oi = ospf6_interface_create(ifp);
2354 assert(oi);
2355
d23d6de8
QY
2356 oi->instance_id = strmatch(argv[0]->text, "no")
2357 ? OSPF6_INTERFACE_INSTANCE_ID
2358 : strtoul(argv[idx_number]->arg, NULL, 10);
d62a17ae 2359 return CMD_SUCCESS;
718e3744 2360}
2361
d23d6de8
QY
2362ALIAS (ipv6_ospf6_instance,
2363 no_ipv6_ospf6_instance_cmd,
2364 "no ipv6 ospf6 instance-id [(0-255)]",
2365 NO_STR
2366 IP6_STR
2367 OSPF6_STR
2368 "Instance ID for this interface\n"
2369 "Instance ID value\n")
2370
718e3744 2371DEFUN (ipv6_ospf6_passive,
2372 ipv6_ospf6_passive_cmd,
2373 "ipv6 ospf6 passive",
2374 IP6_STR
2375 OSPF6_STR
99a522c7 2376 "Passive interface; no adjacency will be formed on this interface\n"
718e3744 2377 )
2378{
d62a17ae 2379 VTY_DECLVAR_CONTEXT(interface, ifp);
2380 struct ospf6_interface *oi;
2381 struct listnode *node, *nnode;
2382 struct ospf6_neighbor *on;
718e3744 2383
d62a17ae 2384 assert(ifp);
718e3744 2385
d62a17ae 2386 oi = (struct ospf6_interface *)ifp->info;
2387 if (oi == NULL)
2388 oi = ospf6_interface_create(ifp);
2389 assert(oi);
718e3744 2390
d62a17ae 2391 SET_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE);
e16d030c
DS
2392 EVENT_OFF(oi->thread_send_hello);
2393 EVENT_OFF(oi->thread_sso);
508e53e2 2394
d62a17ae 2395 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) {
e16d030c 2396 EVENT_OFF(on->inactivity_timer);
907a2395 2397 event_add_event(master, inactivity_timer, on, 0, NULL);
d62a17ae 2398 }
718e3744 2399
d62a17ae 2400 return CMD_SUCCESS;
718e3744 2401}
2402
2403DEFUN (no_ipv6_ospf6_passive,
2404 no_ipv6_ospf6_passive_cmd,
2405 "no ipv6 ospf6 passive",
2406 NO_STR
2407 IP6_STR
2408 OSPF6_STR
2409 "passive interface: No Adjacency will be formed on this I/F\n"
2410 )
2411{
d62a17ae 2412 VTY_DECLVAR_CONTEXT(interface, ifp);
2413 struct ospf6_interface *oi;
2414 assert(ifp);
718e3744 2415
d62a17ae 2416 oi = (struct ospf6_interface *)ifp->info;
2417 if (oi == NULL)
2418 oi = ospf6_interface_create(ifp);
2419 assert(oi);
718e3744 2420
d62a17ae 2421 UNSET_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE);
e16d030c
DS
2422 EVENT_OFF(oi->thread_send_hello);
2423 EVENT_OFF(oi->thread_sso);
cb978d68 2424
2425 /* don't send hellos over loopback interface */
608c8870 2426 if (!if_is_loopback(oi->interface))
907a2395
DS
2427 event_add_timer(master, ospf6_hello_send, oi, 0,
2428 &oi->thread_send_hello);
718e3744 2429
d62a17ae 2430 return CMD_SUCCESS;
718e3744 2431}
2432
d42306d9
DT
2433DEFUN (ipv6_ospf6_mtu_ignore,
2434 ipv6_ospf6_mtu_ignore_cmd,
2435 "ipv6 ospf6 mtu-ignore",
2436 IP6_STR
2437 OSPF6_STR
99a522c7 2438 "Disable MTU mismatch detection on this interface\n"
d42306d9
DT
2439 )
2440{
d62a17ae 2441 VTY_DECLVAR_CONTEXT(interface, ifp);
2442 struct ospf6_interface *oi;
2443 assert(ifp);
d42306d9 2444
d62a17ae 2445 oi = (struct ospf6_interface *)ifp->info;
2446 if (oi == NULL)
2447 oi = ospf6_interface_create(ifp);
2448 assert(oi);
d42306d9 2449
d62a17ae 2450 oi->mtu_ignore = 1;
d42306d9 2451
d62a17ae 2452 return CMD_SUCCESS;
d42306d9
DT
2453}
2454
2455DEFUN (no_ipv6_ospf6_mtu_ignore,
2456 no_ipv6_ospf6_mtu_ignore_cmd,
2457 "no ipv6 ospf6 mtu-ignore",
2458 NO_STR
2459 IP6_STR
2460 OSPF6_STR
99a522c7 2461 "Disable MTU mismatch detection on this interface\n"
d42306d9
DT
2462 )
2463{
d62a17ae 2464 VTY_DECLVAR_CONTEXT(interface, ifp);
2465 struct ospf6_interface *oi;
2466 assert(ifp);
d42306d9 2467
d62a17ae 2468 oi = (struct ospf6_interface *)ifp->info;
2469 if (oi == NULL)
2470 oi = ospf6_interface_create(ifp);
2471 assert(oi);
d42306d9 2472
d62a17ae 2473 oi->mtu_ignore = 0;
d42306d9 2474
d62a17ae 2475 return CMD_SUCCESS;
d42306d9
DT
2476}
2477
718e3744 2478DEFUN (ipv6_ospf6_advertise_prefix_list,
2479 ipv6_ospf6_advertise_prefix_list_cmd,
2480 "ipv6 ospf6 advertise prefix-list WORD",
2481 IP6_STR
2482 OSPF6_STR
2483 "Advertising options\n"
2484 "Filter prefix using prefix-list\n"
2485 "Prefix list name\n"
2486 )
2487{
d62a17ae 2488 VTY_DECLVAR_CONTEXT(interface, ifp);
2489 int idx_word = 4;
2490 struct ospf6_interface *oi;
2491 assert(ifp);
2492
2493 oi = (struct ospf6_interface *)ifp->info;
2494 if (oi == NULL)
2495 oi = ospf6_interface_create(ifp);
2496 assert(oi);
2497
2498 if (oi->plist_name)
2499 XFREE(MTYPE_CFG_PLIST_NAME, oi->plist_name);
2500 oi->plist_name = XSTRDUP(MTYPE_CFG_PLIST_NAME, argv[idx_word]->arg);
2501
2502 ospf6_interface_connected_route_update(oi->interface);
2503
2504 if (oi->area) {
2505 OSPF6_LINK_LSA_SCHEDULE(oi);
2506 if (oi->state == OSPF6_INTERFACE_DR) {
2507 OSPF6_NETWORK_LSA_SCHEDULE(oi);
2508 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi);
2509 }
2510 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area);
2511 }
2512
2513 return CMD_SUCCESS;
718e3744 2514}
2515
2516DEFUN (no_ipv6_ospf6_advertise_prefix_list,
2517 no_ipv6_ospf6_advertise_prefix_list_cmd,
d23d6de8 2518 "no ipv6 ospf6 advertise prefix-list [WORD]",
718e3744 2519 NO_STR
2520 IP6_STR
2521 OSPF6_STR
2522 "Advertising options\n"
2523 "Filter prefix using prefix-list\n"
d23d6de8 2524 "Prefix list name\n")
718e3744 2525{
d62a17ae 2526 VTY_DECLVAR_CONTEXT(interface, ifp);
2527 struct ospf6_interface *oi;
2528 assert(ifp);
2529
2530 oi = (struct ospf6_interface *)ifp->info;
2531 if (oi == NULL)
2532 oi = ospf6_interface_create(ifp);
2533 assert(oi);
2534
d23d6de8 2535 if (oi->plist_name)
d62a17ae 2536 XFREE(MTYPE_CFG_PLIST_NAME, oi->plist_name);
d62a17ae 2537
2538 ospf6_interface_connected_route_update(oi->interface);
2539
2540 if (oi->area) {
2541 OSPF6_LINK_LSA_SCHEDULE(oi);
2542 if (oi->state == OSPF6_INTERFACE_DR) {
2543 OSPF6_NETWORK_LSA_SCHEDULE(oi);
2544 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi);
2545 }
2546 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area);
2547 }
2548
2549 return CMD_SUCCESS;
718e3744 2550}
2551
c5926a92
DD
2552DEFUN (ipv6_ospf6_network,
2553 ipv6_ospf6_network_cmd,
6147e2c6 2554 "ipv6 ospf6 network <broadcast|point-to-point>",
c5926a92
DD
2555 IP6_STR
2556 OSPF6_STR
99a522c7 2557 "Network type\n"
b2d4d039 2558 "Specify OSPF6 broadcast network\n"
c5926a92
DD
2559 "Specify OSPF6 point-to-point network\n"
2560 )
2561{
d62a17ae 2562 VTY_DECLVAR_CONTEXT(interface, ifp);
2563 int idx_network = 3;
2564 struct ospf6_interface *oi;
2565 assert(ifp);
2566
2567 oi = (struct ospf6_interface *)ifp->info;
2568 if (oi == NULL) {
2569 oi = ospf6_interface_create(ifp);
2570 }
2571 assert(oi);
2572
5aeb4f3c
DL
2573 oi->type_cfg = true;
2574
d62a17ae 2575 if (strncmp(argv[idx_network]->arg, "b", 1) == 0) {
2576 if (oi->type == OSPF_IFTYPE_BROADCAST)
2577 return CMD_SUCCESS;
2578
2579 oi->type = OSPF_IFTYPE_BROADCAST;
2580 } else if (strncmp(argv[idx_network]->arg, "point-to-p", 10) == 0) {
2581 if (oi->type == OSPF_IFTYPE_POINTOPOINT) {
2582 return CMD_SUCCESS;
2583 }
2584 oi->type = OSPF_IFTYPE_POINTOPOINT;
c5926a92 2585 }
c5926a92 2586
d62a17ae 2587 /* Reset the interface */
8c1186d3
DS
2588 event_execute(master, interface_down, oi, 0);
2589 event_execute(master, interface_up, oi, 0);
c5926a92 2590
d62a17ae 2591 return CMD_SUCCESS;
c5926a92
DD
2592}
2593
2594DEFUN (no_ipv6_ospf6_network,
2595 no_ipv6_ospf6_network_cmd,
32573073 2596 "no ipv6 ospf6 network [<broadcast|point-to-point>]",
c5926a92
DD
2597 NO_STR
2598 IP6_STR
2599 OSPF6_STR
32573073
QY
2600 "Set default network type\n"
2601 "Specify OSPF6 broadcast network\n"
2602 "Specify OSPF6 point-to-point network\n")
c5926a92 2603{
d62a17ae 2604 VTY_DECLVAR_CONTEXT(interface, ifp);
2605 struct ospf6_interface *oi;
2606 int type;
c5926a92 2607
d62a17ae 2608 assert(ifp);
c5926a92 2609
d62a17ae 2610 oi = (struct ospf6_interface *)ifp->info;
2611 if (oi == NULL) {
2612 return CMD_SUCCESS;
2613 }
c5926a92 2614
5aeb4f3c
DL
2615 oi->type_cfg = false;
2616
d62a17ae 2617 type = ospf6_default_iftype(ifp);
2618 if (oi->type == type) {
2619 return CMD_SUCCESS;
2620 }
2621 oi->type = type;
c5926a92 2622
d62a17ae 2623 /* Reset the interface */
8c1186d3
DS
2624 event_execute(master, interface_down, oi, 0);
2625 event_execute(master, interface_up, oi, 0);
c5926a92 2626
d62a17ae 2627 return CMD_SUCCESS;
c5926a92
DD
2628}
2629
d48ef099 2630static int config_write_ospf6_interface(struct vty *vty, struct vrf *vrf)
718e3744 2631{
d62a17ae 2632 struct ospf6_interface *oi;
2633 struct interface *ifp;
42cabc55 2634 char buf[INET_ADDRSTRLEN];
d62a17ae 2635
451fda4f 2636 FOR_ALL_INTERFACES (vrf, ifp) {
d62a17ae 2637 oi = (struct ospf6_interface *)ifp->info;
2638 if (oi == NULL)
2639 continue;
2640
788a036f 2641 if_vty_config_start(vty, ifp);
d62a17ae 2642
2643 if (ifp->desc)
2644 vty_out(vty, " description %s\n", ifp->desc);
42cabc55
IR
2645 if (oi->area_id_format != OSPF6_AREA_FMT_UNSET) {
2646 area_id2str(buf, sizeof(buf), oi->area_id,
2647 oi->area_id_format);
2648 vty_out(vty, " ipv6 ospf6 area %s\n", buf);
2649 }
d62a17ae 2650 if (oi->c_ifmtu)
2651 vty_out(vty, " ipv6 ospf6 ifmtu %d\n", oi->c_ifmtu);
2652
2653 if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_NOAUTOCOST))
2654 vty_out(vty, " ipv6 ospf6 cost %d\n", oi->cost);
2655
2656 if (oi->hello_interval != OSPF6_INTERFACE_HELLO_INTERVAL)
2657 vty_out(vty, " ipv6 ospf6 hello-interval %d\n",
2658 oi->hello_interval);
2659
2660 if (oi->dead_interval != OSPF6_INTERFACE_DEAD_INTERVAL)
2661 vty_out(vty, " ipv6 ospf6 dead-interval %d\n",
2662 oi->dead_interval);
2663
2664 if (oi->rxmt_interval != OSPF6_INTERFACE_RXMT_INTERVAL)
2665 vty_out(vty, " ipv6 ospf6 retransmit-interval %d\n",
2666 oi->rxmt_interval);
2667
2668 if (oi->priority != OSPF6_INTERFACE_PRIORITY)
2669 vty_out(vty, " ipv6 ospf6 priority %d\n", oi->priority);
2670
2671 if (oi->transdelay != OSPF6_INTERFACE_TRANSDELAY)
2672 vty_out(vty, " ipv6 ospf6 transmit-delay %d\n",
2673 oi->transdelay);
2674
2675 if (oi->instance_id != OSPF6_INTERFACE_INSTANCE_ID)
2676 vty_out(vty, " ipv6 ospf6 instance-id %d\n",
2677 oi->instance_id);
2678
2679 if (oi->plist_name)
2680 vty_out(vty, " ipv6 ospf6 advertise prefix-list %s\n",
2681 oi->plist_name);
2682
2683 if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE))
2684 vty_out(vty, " ipv6 ospf6 passive\n");
2685
2686 if (oi->mtu_ignore)
2687 vty_out(vty, " ipv6 ospf6 mtu-ignore\n");
2688
5aeb4f3c
DL
2689 if (oi->type_cfg && oi->type == OSPF_IFTYPE_POINTOPOINT)
2690 vty_out(vty, " ipv6 ospf6 network point-to-point\n");
2691 else if (oi->type_cfg && oi->type == OSPF_IFTYPE_BROADCAST)
2692 vty_out(vty, " ipv6 ospf6 network broadcast\n");
d62a17ae 2693
0c05ceae
RW
2694 if (oi->gr.hello_delay.interval != OSPF_HELLO_DELAY_DEFAULT)
2695 vty_out(vty,
2696 " ipv6 ospf6 graceful-restart hello-delay %u\n",
2697 oi->gr.hello_delay.interval);
2698
d62a17ae 2699 ospf6_bfd_write_config(vty, oi);
2700
1a5607ea 2701 ospf6_auth_write_config(vty, &oi->at_data);
788a036f 2702 if_vty_config_end(vty);
d62a17ae 2703 }
2704 return 0;
718e3744 2705}
2706
d48ef099 2707/* Configuration write function for ospfd. */
2708static int config_write_interface(struct vty *vty)
2709{
2710 int write = 0;
2711 struct vrf *vrf = NULL;
2712
2713 /* Display all VRF aware OSPF interface configuration */
2714 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2715 write += config_write_ospf6_interface(vty, vrf);
2716 }
2717
2718 return write;
2719}
2720
138c5a74
DS
2721static int ospf6_ifp_create(struct interface *ifp)
2722{
ef7bd2a3
DS
2723 if (IS_OSPF6_DEBUG_ZEBRA(RECV))
2724 zlog_debug("Zebra Interface add: %s index %d mtu %d", ifp->name,
2725 ifp->ifindex, ifp->mtu6);
42cabc55
IR
2726
2727 if (ifp->info)
2728 ospf6_interface_start(ifp->info);
ef7bd2a3 2729
138c5a74
DS
2730 return 0;
2731}
2732
2733static int ospf6_ifp_up(struct interface *ifp)
2734{
ddbf3e60
DS
2735 if (IS_OSPF6_DEBUG_ZEBRA(RECV))
2736 zlog_debug(
3efd0893 2737 "Zebra Interface state change: %s index %d flags %llx metric %d mtu %d bandwidth %d",
ddbf3e60
DS
2738 ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
2739 ifp->metric, ifp->mtu6, ifp->bandwidth);
2740
2741 ospf6_interface_state_update(ifp);
2742
138c5a74
DS
2743 return 0;
2744}
2745
2746static int ospf6_ifp_down(struct interface *ifp)
2747{
b0b69e59
DS
2748 if (IS_OSPF6_DEBUG_ZEBRA(RECV))
2749 zlog_debug(
3efd0893 2750 "Zebra Interface state change: %s index %d flags %llx metric %d mtu %d bandwidth %d",
b0b69e59
DS
2751 ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
2752 ifp->metric, ifp->mtu6, ifp->bandwidth);
2753
2754 ospf6_interface_state_update(ifp);
2755
138c5a74
DS
2756 return 0;
2757}
2758
2759static int ospf6_ifp_destroy(struct interface *ifp)
2760{
3c3c3252
DS
2761 if (if_is_up(ifp))
2762 zlog_warn("Zebra: got delete of %s, but interface is still up",
2763 ifp->name);
2764
2765 if (IS_OSPF6_DEBUG_ZEBRA(RECV))
2766 zlog_debug("Zebra Interface delete: %s index %d mtu %d",
2767 ifp->name, ifp->ifindex, ifp->mtu6);
2768
42cabc55
IR
2769 if (ifp->info)
2770 ospf6_interface_stop(ifp->info);
2771
138c5a74
DS
2772 return 0;
2773}
2774
d62a17ae 2775void ospf6_interface_init(void)
718e3744 2776{
d62a17ae 2777 /* Install interface node. */
9da01b0b 2778 if_cmd_init(config_write_interface);
138c5a74
DS
2779 if_zapi_callbacks(ospf6_ifp_create, ospf6_ifp_up,
2780 ospf6_ifp_down, ospf6_ifp_destroy);
d62a17ae 2781
2782 install_element(VIEW_NODE, &show_ipv6_ospf6_interface_prefix_cmd);
2783 install_element(VIEW_NODE, &show_ipv6_ospf6_interface_ifname_cmd);
2784 install_element(VIEW_NODE,
2785 &show_ipv6_ospf6_interface_ifname_prefix_cmd);
996c9314 2786 install_element(VIEW_NODE, &show_ipv6_ospf6_interface_traffic_cmd);
d62a17ae 2787
42cabc55
IR
2788 install_element(INTERFACE_NODE, &ipv6_ospf6_area_cmd);
2789 install_element(INTERFACE_NODE, &no_ipv6_ospf6_area_cmd);
d62a17ae 2790 install_element(INTERFACE_NODE, &ipv6_ospf6_cost_cmd);
2791 install_element(INTERFACE_NODE, &no_ipv6_ospf6_cost_cmd);
2792 install_element(INTERFACE_NODE, &ipv6_ospf6_ifmtu_cmd);
2793 install_element(INTERFACE_NODE, &no_ipv6_ospf6_ifmtu_cmd);
d23d6de8 2794
d62a17ae 2795 install_element(INTERFACE_NODE, &ipv6_ospf6_deadinterval_cmd);
2796 install_element(INTERFACE_NODE, &ipv6_ospf6_hellointerval_cmd);
0c05ceae 2797 install_element(INTERFACE_NODE, &ipv6_ospf6_gr_hdelay_cmd);
d62a17ae 2798 install_element(INTERFACE_NODE, &ipv6_ospf6_priority_cmd);
2799 install_element(INTERFACE_NODE, &ipv6_ospf6_retransmitinterval_cmd);
2800 install_element(INTERFACE_NODE, &ipv6_ospf6_transmitdelay_cmd);
2801 install_element(INTERFACE_NODE, &ipv6_ospf6_instance_cmd);
d23d6de8
QY
2802 install_element(INTERFACE_NODE, &no_ipv6_ospf6_deadinterval_cmd);
2803 install_element(INTERFACE_NODE, &no_ipv6_ospf6_hellointerval_cmd);
0c05ceae 2804 install_element(INTERFACE_NODE, &no_ipv6_ospf6_gr_hdelay_cmd);
d23d6de8
QY
2805 install_element(INTERFACE_NODE, &no_ipv6_ospf6_priority_cmd);
2806 install_element(INTERFACE_NODE, &no_ipv6_ospf6_retransmitinterval_cmd);
2807 install_element(INTERFACE_NODE, &no_ipv6_ospf6_transmitdelay_cmd);
2808 install_element(INTERFACE_NODE, &no_ipv6_ospf6_instance_cmd);
d62a17ae 2809
2810 install_element(INTERFACE_NODE, &ipv6_ospf6_passive_cmd);
2811 install_element(INTERFACE_NODE, &no_ipv6_ospf6_passive_cmd);
2812
2813 install_element(INTERFACE_NODE, &ipv6_ospf6_mtu_ignore_cmd);
2814 install_element(INTERFACE_NODE, &no_ipv6_ospf6_mtu_ignore_cmd);
2815
2816 install_element(INTERFACE_NODE, &ipv6_ospf6_advertise_prefix_list_cmd);
2817 install_element(INTERFACE_NODE,
2818 &no_ipv6_ospf6_advertise_prefix_list_cmd);
2819
2820 install_element(INTERFACE_NODE, &ipv6_ospf6_network_cmd);
2821 install_element(INTERFACE_NODE, &no_ipv6_ospf6_network_cmd);
2822
2823 /* reference bandwidth commands */
2824 install_element(OSPF6_NODE, &auto_cost_reference_bandwidth_cmd);
2825 install_element(OSPF6_NODE, &no_auto_cost_reference_bandwidth_cmd);
78156066
PR
2826 /* write-multiplier commands */
2827 install_element(OSPF6_NODE, &ospf6_write_multiplier_cmd);
2828 install_element(OSPF6_NODE, &no_ospf6_write_multiplier_cmd);
508e53e2 2829}
2830
a1b11f9b 2831/* Clear the specified interface structure */
f71ed6df 2832void ospf6_interface_clear(struct interface *ifp)
a1b11f9b 2833{
d62a17ae 2834 struct ospf6_interface *oi;
a1b11f9b 2835
d62a17ae 2836 if (!if_is_operative(ifp))
2837 return;
a1b11f9b 2838
d62a17ae 2839 if (ifp->info == NULL)
2840 return;
a1b11f9b 2841
d62a17ae 2842 oi = (struct ospf6_interface *)ifp->info;
a1b11f9b 2843
d62a17ae 2844 if (IS_OSPF6_DEBUG_INTERFACE)
2845 zlog_debug("Interface %s: clear by reset", ifp->name);
a1b11f9b 2846
d62a17ae 2847 /* Reset the interface */
8c1186d3
DS
2848 event_execute(master, interface_down, oi, 0);
2849 event_execute(master, interface_up, oi, 0);
a1b11f9b
DS
2850}
2851
2852/* Clear interface */
2853DEFUN (clear_ipv6_ospf6_interface,
2854 clear_ipv6_ospf6_interface_cmd,
ad7e12b0 2855 "clear ipv6 ospf6 [vrf NAME] interface [IFNAME]",
a1b11f9b
DS
2856 CLEAR_STR
2857 IP6_STR
2858 OSPF6_STR
ad7e12b0 2859 VRF_CMD_HELP_STR
a1b11f9b
DS
2860 INTERFACE_STR
2861 IFNAME_STR
2862 )
2863{
ad7e12b0
IR
2864 struct vrf *vrf;
2865 int idx_vrf = 3;
d62a17ae 2866 int idx_ifname = 4;
2867 struct interface *ifp;
ad7e12b0 2868 const char *vrf_name;
d62a17ae 2869
ad7e12b0
IR
2870 if (argv_find(argv, argc, "vrf", &idx_vrf))
2871 vrf_name = argv[idx_vrf + 1]->arg;
2872 else
2873 vrf_name = VRF_DEFAULT_NAME;
2874 vrf = vrf_lookup_by_name(vrf_name);
2875 if (!vrf) {
2876 vty_out(vty, "%% VRF %s not found\n", vrf_name);
2877 return CMD_WARNING;
2878 }
2879
2880 if (!argv_find(argv, argc, "IFNAME", &idx_ifname)) {
2881 /* Clear all the ospfv3 interfaces. */
451fda4f 2882 FOR_ALL_INTERFACES (vrf, ifp)
f71ed6df 2883 ospf6_interface_clear(ifp);
ad7e12b0
IR
2884 } else {
2885 /* Interface name is specified. */
2886 ifp = if_lookup_by_name_vrf(argv[idx_ifname]->arg, vrf);
2887 if (!ifp) {
d62a17ae 2888 vty_out(vty, "No such Interface: %s\n",
2889 argv[idx_ifname]->arg);
2890 return CMD_WARNING;
2891 }
f71ed6df 2892 ospf6_interface_clear(ifp);
d62a17ae 2893 }
2894
2895 return CMD_SUCCESS;
a1b11f9b
DS
2896}
2897
d62a17ae 2898void install_element_ospf6_clear_interface(void)
a1b11f9b 2899{
d62a17ae 2900 install_element(ENABLE_NODE, &clear_ipv6_ospf6_interface_cmd);
a1b11f9b
DS
2901}
2902
508e53e2 2903DEFUN (debug_ospf6_interface,
2904 debug_ospf6_interface_cmd,
2905 "debug ospf6 interface",
2906 DEBUG_STR
2907 OSPF6_STR
2908 "Debug OSPFv3 Interface\n"
2909 )
2910{
d62a17ae 2911 OSPF6_DEBUG_INTERFACE_ON();
2912 return CMD_SUCCESS;
508e53e2 2913}
2914
2915DEFUN (no_debug_ospf6_interface,
2916 no_debug_ospf6_interface_cmd,
2917 "no debug ospf6 interface",
2918 NO_STR
2919 DEBUG_STR
2920 OSPF6_STR
2921 "Debug OSPFv3 Interface\n"
2922 )
2923{
d62a17ae 2924 OSPF6_DEBUG_INTERFACE_OFF();
2925 return CMD_SUCCESS;
508e53e2 2926}
2927
d62a17ae 2928int config_write_ospf6_debug_interface(struct vty *vty)
508e53e2 2929{
d62a17ae 2930 if (IS_OSPF6_DEBUG_INTERFACE)
2931 vty_out(vty, "debug ospf6 interface\n");
2932 return 0;
508e53e2 2933}
2934
d62a17ae 2935void install_element_ospf6_debug_interface(void)
508e53e2 2936{
d62a17ae 2937 install_element(ENABLE_NODE, &debug_ospf6_interface_cmd);
2938 install_element(ENABLE_NODE, &no_debug_ospf6_interface_cmd);
2939 install_element(CONFIG_NODE, &debug_ospf6_interface_cmd);
2940 install_element(CONFIG_NODE, &no_debug_ospf6_interface_cmd);
718e3744 2941}
1a5607ea
AR
2942
2943void ospf6_auth_write_config(struct vty *vty, struct ospf6_auth_data *at_data)
2944{
2945 if (CHECK_FLAG(at_data->flags, OSPF6_AUTH_TRAILER_KEYCHAIN))
2946 vty_out(vty, " ipv6 ospf6 authentication keychain %s\n",
2947 at_data->keychain);
2948 else if (CHECK_FLAG(at_data->flags, OSPF6_AUTH_TRAILER_MANUAL_KEY))
2949 vty_out(vty,
2950 " ipv6 ospf6 authentication key-id %d hash-algo %s key %s\n",
2951 at_data->key_id,
2952 keychain_get_algo_name_by_id(at_data->hash_algo),
2953 at_data->auth_key);
2954}
2955
2956DEFUN(ipv6_ospf6_intf_auth_trailer_keychain,
2957 ipv6_ospf6_intf_auth_trailer_keychain_cmd,
2958 "ipv6 ospf6 authentication keychain KEYCHAIN_NAME",
2959 IP6_STR OSPF6_STR
2960 "Enable authentication on this interface\n"
2961 "Keychain\n"
2962 "Keychain name\n")
2963{
2964 VTY_DECLVAR_CONTEXT(interface, ifp);
2965 int keychain_idx = 4;
2966 struct ospf6_interface *oi;
2967
2968 oi = (struct ospf6_interface *)ifp->info;
2969 if (oi == NULL)
2970 oi = ospf6_interface_create(ifp);
2971
2972 assert(oi);
2973 if (CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_MANUAL_KEY)) {
2974 vty_out(vty,
2975 "Manual key configured, unconfigure it before configuring key chain\n");
2976 return CMD_WARNING_CONFIG_FAILED;
2977 }
2978
2979 SET_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN);
2980 if (oi->at_data.keychain)
2981 XFREE(MTYPE_OSPF6_AUTH_KEYCHAIN, oi->at_data.keychain);
2982
2983 oi->at_data.keychain =
2984 XSTRDUP(MTYPE_OSPF6_AUTH_KEYCHAIN, argv[keychain_idx]->arg);
2985
2986 return CMD_SUCCESS;
2987}
2988
2989DEFUN(no_ipv6_ospf6_intf_auth_trailer_keychain,
2990 no_ipv6_ospf6_intf_auth_trailer_keychain_cmd,
2991 "no ipv6 ospf6 authentication keychain [KEYCHAIN_NAME]",
2992 NO_STR IP6_STR OSPF6_STR
2993 "Enable authentication on this interface\n"
2994 "Keychain\n"
2995 "Keychain name\n")
2996{
2997 VTY_DECLVAR_CONTEXT(interface, ifp);
2998 struct ospf6_interface *oi;
2999
3000 oi = (struct ospf6_interface *)ifp->info;
3001 if (oi == NULL)
3002 oi = ospf6_interface_create(ifp);
3003
3004 assert(oi);
3005 if (!CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN))
3006 return CMD_SUCCESS;
3007
3008 if (oi->at_data.keychain) {
3009 oi->at_data.flags = 0;
3010 XFREE(MTYPE_OSPF6_AUTH_KEYCHAIN, oi->at_data.keychain);
3011 oi->at_data.keychain = NULL;
3012 }
3013
3014 return CMD_SUCCESS;
3015}
3016
3017DEFUN(ipv6_ospf6_intf_auth_trailer_key, ipv6_ospf6_intf_auth_trailer_key_cmd,
3018 "ipv6 ospf6 authentication key-id (1-65535) hash-algo "
3019 "<md5|hmac-sha-1|hmac-sha-256|hmac-sha-384|hmac-sha-512> "
3020 "key WORD",
3021 IP6_STR OSPF6_STR
3022 "Authentication\n"
3023 "Key ID\n"
3024 "Key ID value\n"
3025 "Cryptographic-algorithm\n"
3026 "Use MD5 algorithm\n"
3027 "Use HMAC-SHA-1 algorithm\n"
3028 "Use HMAC-SHA-256 algorithm\n"
3029 "Use HMAC-SHA-384 algorithm\n"
3030 "Use HMAC-SHA-512 algorithm\n"
3031 "Password\n"
3032 "Password string (key)\n")
3033{
3034 VTY_DECLVAR_CONTEXT(interface, ifp);
3035 int key_id_idx = 4;
3036 int hash_algo_idx = 6;
3037 int password_idx = 8;
3038 struct ospf6_interface *oi;
3039 uint8_t hash_algo = KEYCHAIN_ALGO_NULL;
3040
3041 oi = (struct ospf6_interface *)ifp->info;
3042 if (oi == NULL)
3043 oi = ospf6_interface_create(ifp);
3044
3045 assert(oi);
3046 if (CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN)) {
3047 vty_out(vty,
3048 "key chain configured, unconfigure it before configuring manual key\n");
3049 return CMD_WARNING_CONFIG_FAILED;
3050 }
3051
3052 hash_algo = keychain_get_algo_id_by_name(argv[hash_algo_idx]->arg);
3053#ifndef CRYPTO_OPENSSL
3054 if (hash_algo == KEYCHAIN_ALGO_NULL) {
3055 vty_out(vty,
3056 "Hash algorithm not supported, compile with --with-crypto=openssl\n");
3057 return CMD_WARNING_CONFIG_FAILED;
3058 }
3059#endif /* CRYPTO_OPENSSL */
3060
3061 SET_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_MANUAL_KEY);
3062 oi->at_data.hash_algo = hash_algo;
3063 oi->at_data.key_id = (uint16_t)strtol(argv[key_id_idx]->arg, NULL, 10);
3064 if (oi->at_data.auth_key)
3065 XFREE(MTYPE_OSPF6_AUTH_MANUAL_KEY, oi->at_data.auth_key);
3066 oi->at_data.auth_key =
3067 XSTRDUP(MTYPE_OSPF6_AUTH_MANUAL_KEY, argv[password_idx]->arg);
3068
3069 return CMD_SUCCESS;
3070}
3071
3072DEFUN(no_ipv6_ospf6_intf_auth_trailer_key,
3073 no_ipv6_ospf6_intf_auth_trailer_key_cmd,
3074 "no ipv6 ospf6 authentication key-id [(1-65535) hash-algo "
3075 "<md5|hmac-sha-1|hmac-sha-256|hmac-sha-384|hmac-sha-512> "
3076 "key WORD]",
3077 NO_STR IP6_STR OSPF6_STR
3078 "Authentication\n"
3079 "Key ID\n"
3080 "Key ID value\n"
3081 "Cryptographic-algorithm\n"
3082 "Use MD5 algorithm\n"
3083 "Use HMAC-SHA-1 algorithm\n"
3084 "Use HMAC-SHA-256 algorithm\n"
3085 "Use HMAC-SHA-384 algorithm\n"
3086 "Use HMAC-SHA-512 algorithm\n"
3087 "Password\n"
3088 "Password string (key)\n")
3089{
3090 VTY_DECLVAR_CONTEXT(interface, ifp);
3091 struct ospf6_interface *oi;
3092#ifndef CRYPTO_OPENSSL
3093 int hash_algo_idx = 7;
3094 uint8_t hash_algo = KEYCHAIN_ALGO_NULL;
3095#endif /* CRYPTO_OPENSSL */
3096
3097 oi = (struct ospf6_interface *)ifp->info;
3098 if (oi == NULL)
3099 oi = ospf6_interface_create(ifp);
3100
3101 assert(oi);
3102 if (!CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_MANUAL_KEY))
3103 return CMD_SUCCESS;
3104
3105#ifndef CRYPTO_OPENSSL
3106 hash_algo = keychain_get_algo_id_by_name(argv[hash_algo_idx]->arg);
3107 if (hash_algo == KEYCHAIN_ALGO_NULL) {
3108 vty_out(vty,
3109 "Hash algorithm not supported, compile with --with-crypto=openssl\n");
3110 return CMD_WARNING_CONFIG_FAILED;
3111 }
3112#endif /* CRYPTO_OPENSSL */
3113
3114 if (oi->at_data.auth_key) {
3115 oi->at_data.flags = 0;
3116 XFREE(MTYPE_OSPF6_AUTH_MANUAL_KEY, oi->at_data.auth_key);
3117 oi->at_data.auth_key = NULL;
3118 }
3119
3120 return CMD_SUCCESS;
3121}
3122
3123void ospf6_interface_auth_trailer_cmd_init(void)
3124{
3125 /*Install OSPF6 auth trailer commands at interface level */
3126 install_element(INTERFACE_NODE,
3127 &ipv6_ospf6_intf_auth_trailer_keychain_cmd);
3128 install_element(INTERFACE_NODE,
3129 &no_ipv6_ospf6_intf_auth_trailer_keychain_cmd);
3130 install_element(INTERFACE_NODE, &ipv6_ospf6_intf_auth_trailer_key_cmd);
3131 install_element(INTERFACE_NODE,
3132 &no_ipv6_ospf6_intf_auth_trailer_key_cmd);
3133}