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