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