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