2 * Copyright (C) 2003 Yasuhiro Ohara
4 * This file is part of GNU Zebra.
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
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.
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
32 #include "ospf6_lsa.h"
33 #include "ospf6_lsdb.h"
34 #include "ospf6_top.h"
35 #include "ospf6_network.h"
36 #include "ospf6_message.h"
37 #include "ospf6_route.h"
38 #include "ospf6_area.h"
39 #include "ospf6_abr.h"
40 #include "ospf6_interface.h"
41 #include "ospf6_neighbor.h"
42 #include "ospf6_intra.h"
43 #include "ospf6_spf.h"
45 #include "ospf6_bfd.h"
46 #include "ospf6_zebra.h"
50 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_IF
, "OSPF6 interface");
51 DEFINE_MTYPE_STATIC(OSPF6D
, CFG_PLIST_NAME
, "configured prefix list names");
52 DEFINE_QOBJ_TYPE(ospf6_interface
);
53 DEFINE_HOOK(ospf6_interface_change
,
54 (struct ospf6_interface
* oi
, int state
, int old_state
),
55 (oi
, state
, old_state
));
57 unsigned char conf_debug_ospf6_interface
= 0;
59 const char *const ospf6_interface_state_str
[] = {
60 "None", "Down", "Loopback", "Waiting", "PointToPoint",
61 "DROther", "BDR", "DR", NULL
};
63 int ospf6_interface_neighbor_count(struct ospf6_interface
*oi
)
66 struct ospf6_neighbor
*nbr
= NULL
;
67 struct listnode
*node
;
69 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, node
, nbr
)) {
70 /* Down state is not shown. */
71 if (nbr
->state
== OSPF6_NEIGHBOR_DOWN
)
79 struct ospf6_interface
*ospf6_interface_lookup_by_ifindex(ifindex_t ifindex
,
82 struct ospf6_interface
*oi
;
83 struct interface
*ifp
;
85 ifp
= if_lookup_by_index(ifindex
, vrf_id
);
87 return (struct ospf6_interface
*)NULL
;
89 oi
= (struct ospf6_interface
*)ifp
->info
;
93 /* schedule routing table recalculation */
94 static void ospf6_interface_lsdb_hook(struct ospf6_lsa
*lsa
,
97 struct ospf6_interface
*oi
;
102 oi
= lsa
->lsdb
->data
;
103 switch (ntohs(lsa
->header
->type
)) {
104 case OSPF6_LSTYPE_LINK
:
105 if (oi
->state
== OSPF6_INTERFACE_DR
)
106 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi
);
108 ospf6_spf_schedule(oi
->area
->ospf6
, reason
);
116 static void ospf6_interface_lsdb_hook_add(struct ospf6_lsa
*lsa
)
118 ospf6_interface_lsdb_hook(lsa
, ospf6_lsadd_to_spf_reason(lsa
));
121 static void ospf6_interface_lsdb_hook_remove(struct ospf6_lsa
*lsa
)
123 ospf6_interface_lsdb_hook(lsa
, ospf6_lsremove_to_spf_reason(lsa
));
126 static uint8_t ospf6_default_iftype(struct interface
*ifp
)
128 if (if_is_pointopoint(ifp
))
129 return OSPF_IFTYPE_POINTOPOINT
;
130 else if (if_is_loopback(ifp
))
131 return OSPF_IFTYPE_LOOPBACK
;
133 return OSPF_IFTYPE_BROADCAST
;
136 static uint32_t ospf6_interface_get_cost(struct ospf6_interface
*oi
)
138 /* If all else fails, use default OSPF cost */
142 /* interface speed and bw can be 0 in some platforms,
143 * use ospf default bw. If bw is configured then it would
146 if (!oi
->interface
->bandwidth
&& oi
->interface
->speed
) {
147 bw
= oi
->interface
->speed
;
149 bw
= oi
->interface
->bandwidth
? oi
->interface
->bandwidth
150 : OSPF6_INTERFACE_BANDWIDTH
;
153 ospf6
= oi
->interface
->vrf
->info
;
154 refbw
= ospf6
? ospf6
->ref_bandwidth
: OSPF6_REFERENCE_BANDWIDTH
;
156 /* A specifed ip ospf cost overrides a calculated one. */
157 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_NOAUTOCOST
))
160 cost
= (uint32_t)((double)refbw
/ (double)bw
+ (double)0.5);
163 else if (cost
> UINT32_MAX
)
170 static void ospf6_interface_force_recalculate_cost(struct ospf6_interface
*oi
)
172 /* update cost held in route_connected list in ospf6_interface */
173 ospf6_interface_connected_route_update(oi
->interface
);
175 /* execute LSA hooks */
177 OSPF6_LINK_LSA_SCHEDULE(oi
);
178 OSPF6_ROUTER_LSA_SCHEDULE(oi
->area
);
179 OSPF6_NETWORK_LSA_SCHEDULE(oi
);
180 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi
);
181 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi
->area
);
185 static void ospf6_interface_recalculate_cost(struct ospf6_interface
*oi
)
189 newcost
= ospf6_interface_get_cost(oi
);
190 if (newcost
== oi
->cost
)
194 ospf6_interface_force_recalculate_cost(oi
);
197 /* Create new ospf6 interface structure */
198 struct ospf6_interface
*ospf6_interface_create(struct interface
*ifp
)
200 struct ospf6_interface
*oi
;
201 unsigned int iobuflen
;
203 oi
= XCALLOC(MTYPE_OSPF6_IF
, sizeof(struct ospf6_interface
));
205 oi
->obuf
= ospf6_fifo_new();
207 oi
->area
= (struct ospf6_area
*)NULL
;
208 oi
->neighbor_list
= list_new();
209 oi
->neighbor_list
->cmp
= ospf6_neighbor_cmp
;
210 oi
->linklocal_addr
= (struct in6_addr
*)NULL
;
211 oi
->instance_id
= OSPF6_INTERFACE_INSTANCE_ID
;
212 oi
->transdelay
= OSPF6_INTERFACE_TRANSDELAY
;
213 oi
->priority
= OSPF6_INTERFACE_PRIORITY
;
215 oi
->hello_interval
= OSPF_HELLO_INTERVAL_DEFAULT
;
216 oi
->dead_interval
= OSPF_ROUTER_DEAD_INTERVAL_DEFAULT
;
217 oi
->rxmt_interval
= OSPF_RETRANSMIT_INTERVAL_DEFAULT
;
218 oi
->type
= ospf6_default_iftype(ifp
);
219 oi
->state
= OSPF6_INTERFACE_DOWN
;
224 /* Try to adjust I/O buffer size with IfMtu */
225 oi
->ifmtu
= ifp
->mtu6
;
226 iobuflen
= ospf6_iobuf_size(ifp
->mtu6
);
227 if (oi
->ifmtu
> iobuflen
) {
228 if (IS_OSPF6_DEBUG_INTERFACE
)
230 "Interface %s: IfMtu is adjusted to I/O buffer size: %d.",
231 ifp
->name
, iobuflen
);
232 oi
->ifmtu
= iobuflen
;
235 QOBJ_REG(oi
, ospf6_interface
);
237 oi
->lsupdate_list
= ospf6_lsdb_create(oi
);
238 oi
->lsack_list
= ospf6_lsdb_create(oi
);
239 oi
->lsdb
= ospf6_lsdb_create(oi
);
240 oi
->lsdb
->hook_add
= ospf6_interface_lsdb_hook_add
;
241 oi
->lsdb
->hook_remove
= ospf6_interface_lsdb_hook_remove
;
242 oi
->lsdb_self
= ospf6_lsdb_create(oi
);
244 oi
->route_connected
=
245 OSPF6_ROUTE_TABLE_CREATE(INTERFACE
, CONNECTED_ROUTES
);
246 oi
->route_connected
->scope
= oi
;
253 oi
->cost
= ospf6_interface_get_cost(oi
);
258 void ospf6_interface_delete(struct ospf6_interface
*oi
)
260 struct listnode
*node
, *nnode
;
261 struct ospf6_neighbor
*on
;
265 ospf6_fifo_free(oi
->obuf
);
267 for (ALL_LIST_ELEMENTS(oi
->neighbor_list
, node
, nnode
, on
))
268 ospf6_neighbor_delete(on
);
270 list_delete(&oi
->neighbor_list
);
272 THREAD_OFF(oi
->thread_send_hello
);
273 THREAD_OFF(oi
->thread_send_lsupdate
);
274 THREAD_OFF(oi
->thread_send_lsack
);
275 THREAD_OFF(oi
->thread_sso
);
276 THREAD_OFF(oi
->thread_wait_timer
);
278 ospf6_lsdb_remove_all(oi
->lsdb
);
279 ospf6_lsdb_remove_all(oi
->lsupdate_list
);
280 ospf6_lsdb_remove_all(oi
->lsack_list
);
282 ospf6_lsdb_delete(oi
->lsdb
);
283 ospf6_lsdb_delete(oi
->lsdb_self
);
285 ospf6_lsdb_delete(oi
->lsupdate_list
);
286 ospf6_lsdb_delete(oi
->lsack_list
);
288 ospf6_route_table_delete(oi
->route_connected
);
291 oi
->interface
->info
= NULL
;
295 XFREE(MTYPE_CFG_PLIST_NAME
, oi
->plist_name
);
297 /* disable from area list if possible */
298 ospf6_area_interface_delete(oi
);
300 /* Free BFD allocated data. */
301 XFREE(MTYPE_TMP
, oi
->bfd_config
.profile
);
303 XFREE(MTYPE_OSPF6_IF
, oi
);
306 void ospf6_interface_enable(struct ospf6_interface
*oi
)
308 UNSET_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
);
309 ospf6_interface_state_update(oi
->interface
);
312 void ospf6_interface_disable(struct ospf6_interface
*oi
)
314 SET_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
);
316 thread_execute(master
, interface_down
, oi
, 0);
318 ospf6_lsdb_remove_all(oi
->lsdb
);
319 ospf6_lsdb_remove_all(oi
->lsdb_self
);
320 ospf6_lsdb_remove_all(oi
->lsupdate_list
);
321 ospf6_lsdb_remove_all(oi
->lsack_list
);
323 THREAD_OFF(oi
->thread_send_hello
);
324 THREAD_OFF(oi
->thread_send_lsupdate
);
325 THREAD_OFF(oi
->thread_send_lsack
);
326 THREAD_OFF(oi
->thread_sso
);
328 THREAD_OFF(oi
->thread_network_lsa
);
329 THREAD_OFF(oi
->thread_link_lsa
);
330 THREAD_OFF(oi
->thread_intra_prefix_lsa
);
331 THREAD_OFF(oi
->thread_as_extern_lsa
);
332 THREAD_OFF(oi
->thread_wait_timer
);
335 static struct in6_addr
*
336 ospf6_interface_get_linklocal_address(struct interface
*ifp
)
340 struct in6_addr
*l
= (struct in6_addr
*)NULL
;
342 /* for each connected address */
343 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, n
, c
)) {
344 /* if family not AF_INET6, ignore */
345 if (c
->address
->family
!= AF_INET6
)
348 /* linklocal scope check */
349 if (IN6_IS_ADDR_LINKLOCAL(&c
->address
->u
.prefix6
))
350 l
= &c
->address
->u
.prefix6
;
355 void ospf6_interface_state_update(struct interface
*ifp
)
357 struct ospf6_interface
*oi
;
358 unsigned int iobuflen
;
360 oi
= (struct ospf6_interface
*)ifp
->info
;
363 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
))
366 /* Adjust the mtu values if the kernel told us something new */
367 if (ifp
->mtu6
!= oi
->ifmtu
) {
368 /* If nothing configured, accept it and check for buffer size */
370 oi
->ifmtu
= ifp
->mtu6
;
371 iobuflen
= ospf6_iobuf_size(ifp
->mtu6
);
372 if (oi
->ifmtu
> iobuflen
) {
373 if (IS_OSPF6_DEBUG_INTERFACE
)
375 "Interface %s: IfMtu is adjusted to I/O buffer size: %d.",
376 ifp
->name
, iobuflen
);
377 oi
->ifmtu
= iobuflen
;
379 } else if (oi
->c_ifmtu
> ifp
->mtu6
) {
380 oi
->ifmtu
= ifp
->mtu6
;
382 "Configured mtu %u on %s overridden by kernel %u",
383 oi
->c_ifmtu
, ifp
->name
, ifp
->mtu6
);
385 oi
->ifmtu
= oi
->c_ifmtu
;
388 if (if_is_operative(ifp
)
389 && (ospf6_interface_get_linklocal_address(oi
->interface
)
390 || if_is_loopback(oi
->interface
)))
391 thread_execute(master
, interface_up
, oi
, 0);
393 thread_execute(master
, interface_down
, oi
, 0);
398 void ospf6_interface_connected_route_update(struct interface
*ifp
)
400 struct ospf6_interface
*oi
;
401 struct ospf6_route
*route
;
403 struct listnode
*node
, *nnode
;
404 struct in6_addr nh_addr
;
406 oi
= (struct ospf6_interface
*)ifp
->info
;
410 /* reset linklocal pointer */
411 oi
->linklocal_addr
= ospf6_interface_get_linklocal_address(ifp
);
413 /* if area is null, do not make connected-route list */
414 if (oi
->area
== NULL
)
417 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
))
420 /* update "route to advertise" interface route table */
421 ospf6_route_remove_all(oi
->route_connected
);
423 for (ALL_LIST_ELEMENTS(oi
->interface
->connected
, node
, nnode
, c
)) {
424 if (c
->address
->family
!= AF_INET6
)
427 CONTINUE_IF_ADDRESS_LINKLOCAL(IS_OSPF6_DEBUG_INTERFACE
,
429 CONTINUE_IF_ADDRESS_UNSPECIFIED(IS_OSPF6_DEBUG_INTERFACE
,
431 CONTINUE_IF_ADDRESS_LOOPBACK(IS_OSPF6_DEBUG_INTERFACE
,
433 CONTINUE_IF_ADDRESS_V4COMPAT(IS_OSPF6_DEBUG_INTERFACE
,
435 CONTINUE_IF_ADDRESS_V4MAPPED(IS_OSPF6_DEBUG_INTERFACE
,
439 if (oi
->plist_name
) {
440 struct prefix_list
*plist
;
441 enum prefix_list_type ret
;
443 plist
= prefix_list_lookup(AFI_IP6
, oi
->plist_name
);
444 ret
= prefix_list_apply(plist
, (void *)c
->address
);
445 if (ret
== PREFIX_DENY
) {
446 if (IS_OSPF6_DEBUG_INTERFACE
)
448 "%pFX on %s filtered by prefix-list %s ",
449 c
->address
, oi
->interface
->name
,
455 route
= ospf6_route_create(oi
->area
->ospf6
);
456 memcpy(&route
->prefix
, c
->address
, sizeof(struct prefix
));
457 apply_mask(&route
->prefix
);
458 route
->type
= OSPF6_DEST_TYPE_NETWORK
;
459 route
->path
.area_id
= oi
->area
->area_id
;
460 route
->path
.type
= OSPF6_PATH_TYPE_INTRA
;
461 route
->path
.cost
= oi
->cost
;
462 inet_pton(AF_INET6
, "::1", &nh_addr
);
463 ospf6_route_add_nexthop(route
, oi
->interface
->ifindex
,
465 ospf6_route_add(route
, oi
->route_connected
);
468 /* create new Link-LSA */
469 OSPF6_LINK_LSA_SCHEDULE(oi
);
470 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi
);
471 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi
->area
);
474 static int ospf6_interface_state_change(uint8_t next_state
,
475 struct ospf6_interface
*oi
)
480 prev_state
= oi
->state
;
481 oi
->state
= next_state
;
483 if (prev_state
== next_state
)
490 if (IS_OSPF6_DEBUG_INTERFACE
) {
491 zlog_debug("Interface state change %s: %s -> %s",
493 ospf6_interface_state_str
[prev_state
],
494 ospf6_interface_state_str
[next_state
]);
498 ospf6
= oi
->area
->ospf6
;
500 if ((prev_state
== OSPF6_INTERFACE_DR
501 || prev_state
== OSPF6_INTERFACE_BDR
)
502 && (next_state
!= OSPF6_INTERFACE_DR
503 && next_state
!= OSPF6_INTERFACE_BDR
))
504 ospf6_sso(oi
->interface
->ifindex
, &alldrouters6
,
505 IPV6_LEAVE_GROUP
, ospf6
->fd
);
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
,
512 IPV6_JOIN_GROUP
, ospf6
->fd
);
514 OSPF6_ROUTER_LSA_SCHEDULE(oi
->area
);
515 OSPF6_LINK_LSA_SCHEDULE(oi
);
516 if (next_state
== OSPF6_INTERFACE_DOWN
) {
517 OSPF6_NETWORK_LSA_EXECUTE(oi
);
518 OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(oi
);
519 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi
->area
);
520 OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(oi
);
521 } else if (prev_state
== OSPF6_INTERFACE_DR
522 || next_state
== OSPF6_INTERFACE_DR
) {
523 OSPF6_NETWORK_LSA_SCHEDULE(oi
);
524 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi
);
525 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi
->area
);
528 hook_call(ospf6_interface_change
, oi
, next_state
, prev_state
);
534 /* DR Election, RFC2328 section 9.4 */
536 #define IS_ELIGIBLE(n) \
537 ((n)->state >= OSPF6_NEIGHBOR_TWOWAY && (n)->priority != 0)
539 static struct ospf6_neighbor
*better_bdrouter(struct ospf6_neighbor
*a
,
540 struct ospf6_neighbor
*b
)
542 if ((a
== NULL
|| !IS_ELIGIBLE(a
) || a
->drouter
== a
->router_id
)
543 && (b
== NULL
|| !IS_ELIGIBLE(b
) || b
->drouter
== b
->router_id
))
545 else if (a
== NULL
|| !IS_ELIGIBLE(a
) || a
->drouter
== a
->router_id
)
547 else if (b
== NULL
|| !IS_ELIGIBLE(b
) || b
->drouter
== b
->router_id
)
550 if (a
->bdrouter
== a
->router_id
&& b
->bdrouter
!= b
->router_id
)
552 if (a
->bdrouter
!= a
->router_id
&& b
->bdrouter
== b
->router_id
)
555 if (a
->priority
> b
->priority
)
557 if (a
->priority
< b
->priority
)
560 if (ntohl(a
->router_id
) > ntohl(b
->router_id
))
562 if (ntohl(a
->router_id
) < ntohl(b
->router_id
))
565 zlog_warn("Router-ID duplicate ?");
569 static struct ospf6_neighbor
*better_drouter(struct ospf6_neighbor
*a
,
570 struct ospf6_neighbor
*b
)
572 if ((a
== NULL
|| !IS_ELIGIBLE(a
) || a
->drouter
!= a
->router_id
)
573 && (b
== NULL
|| !IS_ELIGIBLE(b
) || b
->drouter
!= b
->router_id
))
575 else if (a
== NULL
|| !IS_ELIGIBLE(a
) || a
->drouter
!= a
->router_id
)
577 else if (b
== NULL
|| !IS_ELIGIBLE(b
) || b
->drouter
!= b
->router_id
)
580 if (a
->drouter
== a
->router_id
&& b
->drouter
!= b
->router_id
)
582 if (a
->drouter
!= a
->router_id
&& b
->drouter
== b
->router_id
)
585 if (a
->priority
> b
->priority
)
587 if (a
->priority
< b
->priority
)
590 if (ntohl(a
->router_id
) > ntohl(b
->router_id
))
592 if (ntohl(a
->router_id
) < ntohl(b
->router_id
))
595 zlog_warn("Router-ID duplicate ?");
599 uint8_t dr_election(struct ospf6_interface
*oi
)
601 struct listnode
*node
, *nnode
;
602 struct ospf6_neighbor
*on
, *drouter
, *bdrouter
, myself
;
603 struct ospf6_neighbor
*best_drouter
, *best_bdrouter
;
604 uint8_t next_state
= 0;
606 drouter
= bdrouter
= NULL
;
607 best_drouter
= best_bdrouter
= NULL
;
609 /* pseudo neighbor myself, including noting current DR/BDR (1) */
610 memset(&myself
, 0, sizeof(myself
));
611 inet_ntop(AF_INET
, &oi
->area
->ospf6
->router_id
, myself
.name
,
612 sizeof(myself
.name
));
613 myself
.state
= OSPF6_NEIGHBOR_TWOWAY
;
614 myself
.drouter
= oi
->drouter
;
615 myself
.bdrouter
= oi
->bdrouter
;
616 myself
.priority
= oi
->priority
;
617 myself
.router_id
= oi
->area
->ospf6
->router_id
;
619 /* Electing BDR (2) */
620 for (ALL_LIST_ELEMENTS(oi
->neighbor_list
, node
, nnode
, on
))
621 bdrouter
= better_bdrouter(bdrouter
, on
);
623 best_bdrouter
= bdrouter
;
624 bdrouter
= better_bdrouter(best_bdrouter
, &myself
);
626 /* Electing DR (3) */
627 for (ALL_LIST_ELEMENTS(oi
->neighbor_list
, node
, nnode
, on
))
628 drouter
= better_drouter(drouter
, on
);
630 best_drouter
= drouter
;
631 drouter
= better_drouter(best_drouter
, &myself
);
635 /* the router itself is newly/no longer DR/BDR (4) */
636 if ((drouter
== &myself
&& myself
.drouter
!= myself
.router_id
)
637 || (drouter
!= &myself
&& myself
.drouter
== myself
.router_id
)
638 || (bdrouter
== &myself
&& myself
.bdrouter
!= myself
.router_id
)
639 || (bdrouter
!= &myself
&& myself
.bdrouter
== myself
.router_id
)) {
640 myself
.drouter
= (drouter
? drouter
->router_id
: htonl(0));
641 myself
.bdrouter
= (bdrouter
? bdrouter
->router_id
: htonl(0));
643 /* compatible to Electing BDR (2) */
644 bdrouter
= better_bdrouter(best_bdrouter
, &myself
);
646 /* compatible to Electing DR (3) */
647 drouter
= better_drouter(best_drouter
, &myself
);
652 /* Set interface state accordingly (5) */
653 if (drouter
&& drouter
== &myself
)
654 next_state
= OSPF6_INTERFACE_DR
;
655 else if (bdrouter
&& bdrouter
== &myself
)
656 next_state
= OSPF6_INTERFACE_BDR
;
658 next_state
= OSPF6_INTERFACE_DROTHER
;
660 /* If NBMA, schedule Start for each neighbor having priority of 0 (6) */
663 /* If DR or BDR change, invoke AdjOK? for each neighbor (7) */
664 /* RFC 2328 section 12.4. Originating LSAs (3) will be handled
665 accordingly after AdjOK */
666 if (oi
->drouter
!= (drouter
? drouter
->router_id
: htonl(0))
667 || oi
->bdrouter
!= (bdrouter
? bdrouter
->router_id
: htonl(0))) {
668 if (IS_OSPF6_DEBUG_INTERFACE
)
669 zlog_debug("DR Election on %s: DR: %s BDR: %s",
671 (drouter
? drouter
->name
: "0.0.0.0"),
672 (bdrouter
? bdrouter
->name
: "0.0.0.0"));
674 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, node
, on
)) {
675 if (on
->state
< OSPF6_NEIGHBOR_TWOWAY
)
677 /* Schedule AdjOK. */
678 thread_add_event(master
, adj_ok
, on
, 0,
683 oi
->drouter
= (drouter
? drouter
->router_id
: htonl(0));
684 oi
->bdrouter
= (bdrouter
? bdrouter
->router_id
: htonl(0));
692 static bool ifmaddr_check(ifindex_t ifindex
, struct in6_addr
*addr
)
694 struct ifmaddrs
*ifmap
, *ifma
;
695 struct sockaddr_dl
*sdl
;
696 struct sockaddr_in6
*sin6
;
699 if (getifmaddrs(&ifmap
) != 0)
702 for (ifma
= ifmap
; ifma
; ifma
= ifma
->ifma_next
) {
703 if (ifma
->ifma_name
== NULL
|| ifma
->ifma_addr
== NULL
)
705 if (ifma
->ifma_name
->sa_family
!= AF_LINK
)
707 if (ifma
->ifma_addr
->sa_family
!= AF_INET6
)
709 sdl
= (struct sockaddr_dl
*)ifma
->ifma_name
;
710 sin6
= (struct sockaddr_in6
*)ifma
->ifma_addr
;
711 if (sdl
->sdl_index
== ifindex
712 && memcmp(&sin6
->sin6_addr
, addr
, IPV6_MAX_BYTELEN
) == 0) {
724 #endif /* __FreeBSD__ */
726 /* Interface State Machine */
727 int interface_up(struct thread
*thread
)
729 struct ospf6_interface
*oi
;
732 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
733 assert(oi
&& oi
->interface
);
736 oi
->type
= ospf6_default_iftype(oi
->interface
);
738 thread_cancel(&oi
->thread_sso
);
740 if (IS_OSPF6_DEBUG_INTERFACE
)
741 zlog_debug("Interface Event %s: [InterfaceUp]",
742 oi
->interface
->name
);
744 /* check physical interface is up */
745 if (!if_is_operative(oi
->interface
)) {
746 zlog_warn("Interface %s is down, can't execute [InterfaceUp]",
747 oi
->interface
->name
);
751 /* check interface has a link-local address */
752 if (!(ospf6_interface_get_linklocal_address(oi
->interface
)
753 || if_is_loopback(oi
->interface
))) {
755 "Interface %s has no link local address, can't execute [InterfaceUp]",
756 oi
->interface
->name
);
761 ospf6_interface_recalculate_cost(oi
);
763 /* if already enabled, do nothing */
764 if (oi
->state
> OSPF6_INTERFACE_DOWN
) {
765 if (IS_OSPF6_DEBUG_INTERFACE
)
766 zlog_debug("Interface %s already enabled",
767 oi
->interface
->name
);
771 /* If no area assigned, return */
772 if (oi
->area
== NULL
) {
774 "%s: Not scheduling Hello for %s as there is no area assigned yet",
775 __func__
, oi
->interface
->name
);
781 * There's a delay in FreeBSD between issuing a command to leave a
782 * multicast group and an actual leave. If we execute "no router ospf6"
783 * and "router ospf6" fast enough, we can end up in a situation when OS
784 * performs the leave later than it performs the join and the interface
785 * remains without a multicast group. We have to do the join only after
786 * the interface actually left the group.
788 if (ifmaddr_check(oi
->interface
->ifindex
, &allspfrouters6
)) {
790 "Interface %s is still in all routers group, rescheduling for SSO",
791 oi
->interface
->name
);
792 thread_add_timer(master
, interface_up
, oi
,
793 OSPF6_INTERFACE_SSO_RETRY_INT
,
797 #endif /* __FreeBSD__ */
799 ospf6
= oi
->area
->ospf6
;
801 /* Join AllSPFRouters */
802 if (ospf6_sso(oi
->interface
->ifindex
, &allspfrouters6
, IPV6_JOIN_GROUP
,
805 if (oi
->sso_try_cnt
++ < OSPF6_INTERFACE_SSO_RETRY_MAX
) {
807 "Scheduling %s for sso retry, trial count: %d",
808 oi
->interface
->name
, oi
->sso_try_cnt
);
809 thread_add_timer(master
, interface_up
, oi
,
810 OSPF6_INTERFACE_SSO_RETRY_INT
,
815 oi
->sso_try_cnt
= 0; /* Reset on success */
817 /* Update interface route */
818 ospf6_interface_connected_route_update(oi
->interface
);
821 if (!CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_PASSIVE
)
822 && !if_is_loopback(oi
->interface
)) {
823 thread_add_event(master
, ospf6_hello_send
, oi
, 0,
824 &oi
->thread_send_hello
);
827 /* decide next interface state */
828 if (oi
->type
== OSPF_IFTYPE_LOOPBACK
) {
829 ospf6_interface_state_change(OSPF6_INTERFACE_LOOPBACK
, oi
);
830 } else if (oi
->type
== OSPF_IFTYPE_POINTOPOINT
) {
831 ospf6_interface_state_change(OSPF6_INTERFACE_POINTTOPOINT
, oi
);
832 } else if (oi
->priority
== 0)
833 ospf6_interface_state_change(OSPF6_INTERFACE_DROTHER
, oi
);
835 ospf6_interface_state_change(OSPF6_INTERFACE_WAITING
, oi
);
836 thread_add_timer(master
, wait_timer
, oi
, oi
->dead_interval
,
837 &oi
->thread_wait_timer
);
843 int wait_timer(struct thread
*thread
)
845 struct ospf6_interface
*oi
;
847 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
848 assert(oi
&& oi
->interface
);
850 if (IS_OSPF6_DEBUG_INTERFACE
)
851 zlog_debug("Interface Event %s: [WaitTimer]",
852 oi
->interface
->name
);
854 if (oi
->state
== OSPF6_INTERFACE_WAITING
)
855 ospf6_interface_state_change(dr_election(oi
), oi
);
860 int backup_seen(struct thread
*thread
)
862 struct ospf6_interface
*oi
;
864 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
865 assert(oi
&& oi
->interface
);
867 if (IS_OSPF6_DEBUG_INTERFACE
)
868 zlog_debug("Interface Event %s: [BackupSeen]",
869 oi
->interface
->name
);
871 if (oi
->state
== OSPF6_INTERFACE_WAITING
)
872 ospf6_interface_state_change(dr_election(oi
), oi
);
877 int neighbor_change(struct thread
*thread
)
879 struct ospf6_interface
*oi
;
881 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
882 assert(oi
&& oi
->interface
);
884 if (IS_OSPF6_DEBUG_INTERFACE
)
885 zlog_debug("Interface Event %s: [NeighborChange]",
886 oi
->interface
->name
);
888 if (oi
->state
== OSPF6_INTERFACE_DROTHER
889 || oi
->state
== OSPF6_INTERFACE_BDR
890 || oi
->state
== OSPF6_INTERFACE_DR
)
891 ospf6_interface_state_change(dr_election(oi
), oi
);
896 int interface_down(struct thread
*thread
)
898 struct ospf6_interface
*oi
;
899 struct listnode
*node
, *nnode
;
900 struct ospf6_neighbor
*on
;
903 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
904 assert(oi
&& oi
->interface
);
906 if (IS_OSPF6_DEBUG_INTERFACE
)
907 zlog_debug("Interface Event %s: [InterfaceDown]",
908 oi
->interface
->name
);
911 THREAD_OFF(oi
->thread_send_hello
);
913 /* Stop trying to set socket options. */
914 THREAD_OFF(oi
->thread_sso
);
916 /* Cease the HELPER role for all the neighbours
919 if (ospf6_interface_neighbor_count(oi
)) {
921 struct ospf6_neighbor
*nbr
= NULL
;
923 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, ln
, nbr
))
924 ospf6_gr_helper_exit(nbr
, OSPF6_GR_HELPER_TOPO_CHG
);
927 for (ALL_LIST_ELEMENTS(oi
->neighbor_list
, node
, nnode
, on
))
928 ospf6_neighbor_delete(on
);
930 list_delete_all_node(oi
->neighbor_list
);
932 /* When interface state is reset, also reset information about
933 * DR election, as it is no longer valid. */
934 oi
->drouter
= oi
->prev_drouter
= htonl(0);
935 oi
->bdrouter
= oi
->prev_bdrouter
= htonl(0);
937 if (oi
->area
== NULL
)
940 ospf6
= oi
->area
->ospf6
;
941 /* Leave AllSPFRouters */
942 if (oi
->state
> OSPF6_INTERFACE_DOWN
)
943 ospf6_sso(oi
->interface
->ifindex
, &allspfrouters6
,
944 IPV6_LEAVE_GROUP
, ospf6
->fd
);
946 /* deal with write fifo */
947 ospf6_fifo_flush(oi
->obuf
);
948 if (oi
->on_write_q
) {
949 listnode_delete(ospf6
->oi_write_q
, oi
);
950 if (list_isempty(ospf6
->oi_write_q
))
951 thread_cancel(&ospf6
->t_write
);
955 ospf6_interface_state_change(OSPF6_INTERFACE_DOWN
, oi
);
961 static const char *ospf6_iftype_str(uint8_t iftype
)
964 case OSPF_IFTYPE_LOOPBACK
:
966 case OSPF_IFTYPE_BROADCAST
:
968 case OSPF_IFTYPE_POINTOPOINT
:
969 return "POINTOPOINT";
974 #if CONFDATE > 20220709
975 CPP_NOTICE("Time to remove ospf6Enabled from JSON output")
978 /* show specified interface structure */
979 static int ospf6_interface_show(struct vty
*vty
, struct interface
*ifp
,
980 json_object
*json_obj
, bool use_json
)
982 struct ospf6_interface
*oi
;
986 char strbuf
[PREFIX2STR_BUFFER
], drouter
[32], bdrouter
[32];
987 uint8_t default_iftype
;
988 struct timeval res
, now
;
990 struct ospf6_lsa
*lsa
, *lsanext
;
991 json_object
*json_arr
;
992 json_object
*json_addr
;
994 default_iftype
= ospf6_default_iftype(ifp
);
997 json_object_string_add(json_obj
, "status",
998 (if_is_operative(ifp
) ? "up" : "down"));
999 json_object_string_add(json_obj
, "type",
1000 ospf6_iftype_str(default_iftype
));
1001 json_object_int_add(json_obj
, "interfaceId", ifp
->ifindex
);
1003 if (ifp
->info
== NULL
) {
1004 json_object_boolean_false_add(json_obj
, "ospf6Enabled");
1007 json_object_boolean_true_add(json_obj
, "ospf6Enabled");
1009 oi
= (struct ospf6_interface
*)ifp
->info
;
1011 if (if_is_operative(ifp
) && oi
->type
!= default_iftype
)
1012 json_object_string_add(json_obj
, "operatingAsType",
1013 ospf6_iftype_str(oi
->type
));
1016 vty_out(vty
, "%s is %s, type %s\n", ifp
->name
,
1017 (if_is_operative(ifp
) ? "up" : "down"),
1018 ospf6_iftype_str(default_iftype
));
1019 vty_out(vty
, " Interface ID: %d\n", ifp
->ifindex
);
1021 if (ifp
->info
== NULL
) {
1022 vty_out(vty
, " OSPF not enabled on this interface\n");
1025 oi
= (struct ospf6_interface
*)ifp
->info
;
1027 if (if_is_operative(ifp
) && oi
->type
!= default_iftype
)
1028 vty_out(vty
, " Operating as type %s\n",
1029 ospf6_iftype_str(oi
->type
));
1033 json_arr
= json_object_new_array();
1034 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, i
, c
)) {
1035 json_addr
= json_object_new_object();
1037 prefix2str(p
, strbuf
, sizeof(strbuf
));
1038 switch (p
->family
) {
1040 json_object_string_add(json_addr
, "type",
1042 json_object_string_add(json_addr
, "address",
1044 json_object_array_add(json_arr
, json_addr
);
1047 json_object_string_add(json_addr
, "type",
1049 json_object_string_add(json_addr
, "address",
1051 json_object_array_add(json_arr
, json_addr
);
1054 json_object_string_add(json_addr
, "type",
1056 json_object_string_add(json_addr
, "address",
1058 json_object_array_add(json_arr
, json_addr
);
1062 json_object_object_add(json_obj
, "internetAddress", json_arr
);
1064 vty_out(vty
, " Internet Address:\n");
1066 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, i
, c
)) {
1068 prefix2str(p
, strbuf
, sizeof(strbuf
));
1069 switch (p
->family
) {
1071 vty_out(vty
, " inet : %pFX\n", p
);
1074 vty_out(vty
, " inet6: %pFX\n", p
);
1077 vty_out(vty
, " ??? : %pFX\n", p
);
1085 json_object_boolean_true_add(json_obj
,
1087 json_object_int_add(json_obj
, "instanceId",
1089 json_object_int_add(json_obj
, "interfaceMtu",
1091 json_object_int_add(json_obj
, "autoDetect", ifp
->mtu6
);
1092 json_object_string_add(json_obj
, "mtuMismatchDetection",
1093 oi
->mtu_ignore
? "disabled"
1095 inet_ntop(AF_INET
, &oi
->area
->area_id
, strbuf
,
1097 json_object_string_add(json_obj
, "areaId", strbuf
);
1098 json_object_int_add(json_obj
, "cost", oi
->cost
);
1100 json_object_boolean_false_add(json_obj
,
1106 " Instance ID %d, Interface MTU %d (autodetect: %d)\n",
1107 oi
->instance_id
, oi
->ifmtu
, ifp
->mtu6
);
1108 vty_out(vty
, " MTU mismatch detection: %s\n",
1109 oi
->mtu_ignore
? "disabled" : "enabled");
1110 inet_ntop(AF_INET
, &oi
->area
->area_id
, strbuf
,
1112 vty_out(vty
, " Area ID %s, Cost %u\n", strbuf
,
1115 vty_out(vty
, " Not Attached to Area\n");
1119 json_object_string_add(json_obj
, "ospf6InterfaceState",
1120 ospf6_interface_state_str
[oi
->state
]);
1121 json_object_int_add(json_obj
, "transmitDelaySec",
1123 json_object_int_add(json_obj
, "priority", oi
->priority
);
1124 json_object_int_add(json_obj
, "timerIntervalsConfigHello",
1125 oi
->hello_interval
);
1126 json_object_int_add(json_obj
, "timerIntervalsConfigDead",
1128 json_object_int_add(json_obj
, "timerIntervalsConfigRetransmit",
1131 vty_out(vty
, " State %s, Transmit Delay %d sec, Priority %d\n",
1132 ospf6_interface_state_str
[oi
->state
], oi
->transdelay
,
1134 vty_out(vty
, " Timer intervals configured:\n");
1135 vty_out(vty
, " Hello %d, Dead %d, Retransmit %d\n",
1136 oi
->hello_interval
, oi
->dead_interval
,
1140 inet_ntop(AF_INET
, &oi
->drouter
, drouter
, sizeof(drouter
));
1141 inet_ntop(AF_INET
, &oi
->bdrouter
, bdrouter
, sizeof(bdrouter
));
1143 json_object_string_add(json_obj
, "dr", drouter
);
1144 json_object_string_add(json_obj
, "bdr", bdrouter
);
1145 json_object_int_add(json_obj
, "numberOfInterfaceScopedLsa",
1148 vty_out(vty
, " DR: %s BDR: %s\n", drouter
, bdrouter
);
1149 vty_out(vty
, " Number of I/F scoped LSAs is %u\n",
1157 if (oi
->thread_send_lsupdate
)
1158 timersub(&oi
->thread_send_lsupdate
->u
.sands
, &now
,
1160 timerstring(&res
, duration
, sizeof(duration
));
1161 json_object_int_add(json_obj
, "pendingLsaLsUpdateCount",
1162 oi
->lsupdate_list
->count
);
1163 json_object_string_add(json_obj
, "pendingLsaLsUpdateTime",
1165 json_object_string_add(
1166 json_obj
, "lsUpdateSendThread",
1167 (oi
->thread_send_lsupdate
? "on" : "off"));
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",
1177 if (oi
->thread_send_lsack
)
1178 timersub(&oi
->thread_send_lsack
->u
.sands
, &now
, &res
);
1179 timerstring(&res
, duration
, sizeof(duration
));
1181 json_object_int_add(json_obj
, "pendingLsaLsAckCount",
1182 oi
->lsack_list
->count
);
1183 json_object_string_add(json_obj
, "pendingLsaLsAckTime",
1185 json_object_string_add(json_obj
, "lsAckSendThread",
1186 (oi
->thread_send_lsack
? "on" : "off"));
1188 json_arr
= json_object_new_array();
1189 for (ALL_LSDB(oi
->lsack_list
, lsa
, lsanext
))
1190 json_object_array_add(
1191 json_arr
, json_object_new_string(lsa
->name
));
1192 json_object_object_add(json_obj
, "pendingLsaLsAck", json_arr
);
1196 if (oi
->thread_send_lsupdate
)
1197 timersub(&oi
->thread_send_lsupdate
->u
.sands
, &now
,
1199 timerstring(&res
, duration
, sizeof(duration
));
1201 " %d Pending LSAs for LSUpdate in Time %s [thread %s]\n",
1202 oi
->lsupdate_list
->count
, duration
,
1203 (oi
->thread_send_lsupdate
? "on" : "off"));
1204 for (ALL_LSDB(oi
->lsupdate_list
, lsa
, lsanext
))
1205 vty_out(vty
, " %s\n", lsa
->name
);
1208 if (oi
->thread_send_lsack
)
1209 timersub(&oi
->thread_send_lsack
->u
.sands
, &now
, &res
);
1210 timerstring(&res
, duration
, sizeof(duration
));
1212 " %d Pending LSAs for LSAck in Time %s [thread %s]\n",
1213 oi
->lsack_list
->count
, duration
,
1214 (oi
->thread_send_lsack
? "on" : "off"));
1215 for (ALL_LSDB(oi
->lsack_list
, lsa
, lsanext
))
1216 vty_out(vty
, " %s\n", lsa
->name
);
1220 if (oi
->bfd_config
.enabled
) {
1222 struct json_object
*json_bfd
= json_object_new_object();
1224 json_object_int_add(
1225 json_bfd
, "detectMultiplier",
1226 oi
->bfd_config
.detection_multiplier
);
1227 json_object_int_add(json_bfd
, "rxMinInterval",
1228 oi
->bfd_config
.min_rx
);
1229 json_object_int_add(json_bfd
, "txMinInterval",
1230 oi
->bfd_config
.min_tx
);
1231 json_object_object_add(json_obj
, "peerBfdInfo",
1235 " BFD: Detect Multiplier: %d, Min Rx interval: %d, Min Tx interval: %d\n",
1236 oi
->bfd_config
.detection_multiplier
,
1237 oi
->bfd_config
.min_rx
, oi
->bfd_config
.min_tx
);
1244 /* Find the global address to be used as a forwarding address in NSSA LSA.*/
1245 struct in6_addr
*ospf6_interface_get_global_address(struct interface
*ifp
)
1248 struct connected
*c
;
1250 /* for each connected address */
1251 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, n
, c
)) {
1252 /* if family not AF_INET6, ignore */
1253 if (c
->address
->family
!= AF_INET6
)
1256 if (!IN6_IS_ADDR_LINKLOCAL(&c
->address
->u
.prefix6
))
1257 return &c
->address
->u
.prefix6
;
1264 static int show_ospf6_interface_common(struct vty
*vty
, vrf_id_t vrf_id
,
1265 int argc
, struct cmd_token
**argv
,
1266 int idx_ifname
, int intf_idx
,
1267 int json_idx
, bool uj
)
1270 struct vrf
*vrf
= vrf_lookup_by_id(vrf_id
);
1271 struct interface
*ifp
;
1273 json_object
*json_int
;
1276 json
= json_object_new_object();
1277 if (argc
== json_idx
) {
1278 ifp
= if_lookup_by_name(argv
[idx_ifname
]->arg
, vrf_id
);
1279 json_int
= json_object_new_object();
1281 json_object_string_add(json
, "noSuchInterface",
1282 argv
[idx_ifname
]->arg
);
1283 vty_json(vty
, json
);
1284 json_object_free(json_int
);
1287 ospf6_interface_show(vty
, ifp
, json_int
, uj
);
1288 json_object_object_add(json
, ifp
->name
, json_int
);
1290 FOR_ALL_INTERFACES (vrf
, ifp
) {
1291 json_int
= json_object_new_object();
1292 ospf6_interface_show(vty
, ifp
, json_int
, uj
);
1293 json_object_object_add(json
, ifp
->name
,
1297 vty_json(vty
, json
);
1299 if (argc
== intf_idx
) {
1300 ifp
= if_lookup_by_name(argv
[idx_ifname
]->arg
, vrf_id
);
1302 vty_out(vty
, "No such Interface: %s\n",
1303 argv
[idx_ifname
]->arg
);
1306 ospf6_interface_show(vty
, ifp
, NULL
, uj
);
1308 FOR_ALL_INTERFACES (vrf
, ifp
)
1309 ospf6_interface_show(vty
, ifp
, NULL
, uj
);
1315 /* show interface */
1316 DEFUN(show_ipv6_ospf6_interface
, show_ipv6_ospf6_interface_ifname_cmd
,
1317 "show ipv6 ospf6 [vrf <NAME|all>] interface [IFNAME] [json]",
1318 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1319 "All VRFs\n" INTERFACE_STR IFNAME_STR JSON_STR
)
1324 struct listnode
*node
;
1325 struct ospf6
*ospf6
;
1326 const char *vrf_name
= NULL
;
1327 bool all_vrf
= false;
1329 bool uj
= use_json(argc
, argv
);
1331 OSPF6_FIND_VRF_ARGS(argv
, argc
, idx_vrf
, vrf_name
, all_vrf
);
1338 for (ALL_LIST_ELEMENTS_RO(om6
->ospf6
, node
, ospf6
)) {
1339 if (all_vrf
|| strcmp(ospf6
->name
, vrf_name
) == 0) {
1340 show_ospf6_interface_common(vty
, ospf6
->vrf_id
, argc
,
1341 argv
, idx_ifname
, intf_idx
,
1349 OSPF6_CMD_CHECK_VRF(uj
, all_vrf
, ospf6
);
1354 static int ospf6_interface_show_traffic(struct vty
*vty
,
1355 struct interface
*intf_ifp
,
1356 int display_once
, json_object
*json
,
1357 bool use_json
, vrf_id_t vrf_id
)
1359 struct interface
*ifp
;
1360 struct vrf
*vrf
= NULL
;
1361 struct ospf6_interface
*oi
= NULL
;
1362 json_object
*json_interface
;
1364 if (!display_once
&& !use_json
) {
1366 vty_out(vty
, "%-12s%-17s%-17s%-17s%-17s%-17s\n", "Interface",
1367 " HELLO", " DB-Desc", " LS-Req", " LS-Update",
1369 vty_out(vty
, "%-10s%-18s%-18s%-17s%-17s%-17s\n", "",
1370 " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx",
1373 "--------------------------------------------------------------------------------------------\n");
1376 if (intf_ifp
== NULL
) {
1377 vrf
= vrf_lookup_by_id(vrf_id
);
1378 FOR_ALL_INTERFACES (vrf
, ifp
) {
1380 oi
= (struct ospf6_interface
*)ifp
->info
;
1385 json_interface
= json_object_new_object();
1386 json_object_int_add(json_interface
, "helloRx",
1388 json_object_int_add(json_interface
, "helloTx",
1390 json_object_int_add(json_interface
, "dbDescRx",
1392 json_object_int_add(json_interface
, "dbDescTx",
1394 json_object_int_add(json_interface
, "lsReqRx",
1396 json_object_int_add(json_interface
, "lsReqTx",
1398 json_object_int_add(json_interface
,
1401 json_object_int_add(json_interface
,
1404 json_object_int_add(json_interface
, "lsAckRx",
1406 json_object_int_add(json_interface
, "lsAckTx",
1409 json_object_object_add(json
,
1410 oi
->interface
->name
,
1414 "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u\n",
1415 oi
->interface
->name
, oi
->hello_in
,
1416 oi
->hello_out
, oi
->db_desc_in
,
1417 oi
->db_desc_out
, oi
->ls_req_in
,
1418 oi
->ls_req_out
, oi
->ls_upd_in
,
1419 oi
->ls_upd_out
, oi
->ls_ack_in
,
1423 oi
= intf_ifp
->info
;
1428 json_interface
= json_object_new_object();
1429 json_object_int_add(json_interface
, "helloRx",
1431 json_object_int_add(json_interface
, "helloTx",
1433 json_object_int_add(json_interface
, "dbDescRx",
1435 json_object_int_add(json_interface
, "dbDescTx",
1437 json_object_int_add(json_interface
, "lsReqRx",
1439 json_object_int_add(json_interface
, "lsReqTx",
1441 json_object_int_add(json_interface
, "lsUpdateRx",
1443 json_object_int_add(json_interface
, "lsUpdateTx",
1445 json_object_int_add(json_interface
, "lsAckRx",
1447 json_object_int_add(json_interface
, "lsAckTx",
1450 json_object_object_add(json
, oi
->interface
->name
,
1454 "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u\n",
1455 oi
->interface
->name
, oi
->hello_in
,
1456 oi
->hello_out
, oi
->db_desc_in
, oi
->db_desc_out
,
1457 oi
->ls_req_in
, oi
->ls_req_out
, oi
->ls_upd_in
,
1458 oi
->ls_upd_out
, oi
->ls_ack_in
, oi
->ls_ack_out
);
1464 static int ospf6_interface_show_traffic_common(struct vty
*vty
, int argc
,
1465 struct cmd_token
**argv
,
1466 vrf_id_t vrf_id
, bool uj
)
1469 int display_once
= 0;
1470 char *intf_name
= NULL
;
1471 struct interface
*ifp
= NULL
;
1472 json_object
*json
= NULL
;
1475 json
= json_object_new_object();
1477 if (argv_find(argv
, argc
, "IFNAME", &idx_ifname
)) {
1478 intf_name
= argv
[idx_ifname
]->arg
;
1479 ifp
= if_lookup_by_name(intf_name
, vrf_id
);
1482 json_object_string_add(json
, "status",
1483 "No Such Interface");
1484 json_object_string_add(json
, "interface",
1486 vty_json(vty
, json
);
1489 if (ifp
->info
== NULL
) {
1490 json_object_string_add(
1492 "OSPF not enabled on this interface");
1493 json_object_string_add(json
, "interface",
1495 vty_json(vty
, json
);
1500 vty_out(vty
, "No such Interface: %s\n",
1504 if (ifp
->info
== NULL
) {
1506 " OSPF not enabled on this interface %s\n",
1513 ospf6_interface_show_traffic(vty
, ifp
, display_once
, json
, uj
, vrf_id
);
1516 vty_json(vty
, json
);
1521 /* show interface */
1522 DEFUN(show_ipv6_ospf6_interface_traffic
, show_ipv6_ospf6_interface_traffic_cmd
,
1523 "show ipv6 ospf6 [vrf <NAME|all>] interface traffic [IFNAME] [json]",
1524 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1525 "All VRFs\n" INTERFACE_STR
1526 "Protocol Packet counters\n" IFNAME_STR JSON_STR
)
1528 struct ospf6
*ospf6
;
1529 struct listnode
*node
;
1530 const char *vrf_name
= NULL
;
1531 bool all_vrf
= false;
1533 bool uj
= use_json(argc
, argv
);
1535 OSPF6_FIND_VRF_ARGS(argv
, argc
, idx_vrf
, vrf_name
, all_vrf
);
1537 for (ALL_LIST_ELEMENTS_RO(om6
->ospf6
, node
, ospf6
)) {
1538 if (all_vrf
|| strcmp(ospf6
->name
, vrf_name
) == 0) {
1539 ospf6_interface_show_traffic_common(vty
, argc
, argv
,
1547 OSPF6_CMD_CHECK_VRF(uj
, all_vrf
, ospf6
);
1553 DEFUN(show_ipv6_ospf6_interface_ifname_prefix
,
1554 show_ipv6_ospf6_interface_ifname_prefix_cmd
,
1555 "show ipv6 ospf6 [vrf <NAME|all>] interface IFNAME prefix\
1558 |<X:X::X:X|X:X::X:X/M> [<match|detail>]\
1560 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1561 "All VRFs\n" INTERFACE_STR IFNAME_STR
1562 "Display connected prefixes to advertise\n"
1563 "Display details of the prefixes\n" OSPF6_ROUTE_ADDRESS_STR
1564 OSPF6_ROUTE_PREFIX_STR OSPF6_ROUTE_MATCH_STR
1565 "Display details of the prefixes\n" JSON_STR
)
1569 struct ospf6_interface
*oi
;
1570 bool uj
= use_json(argc
, argv
);
1572 struct ospf6
*ospf6
;
1573 struct listnode
*node
;
1574 struct interface
*ifp
;
1575 const char *vrf_name
= NULL
;
1576 bool all_vrf
= false;
1579 OSPF6_FIND_VRF_ARGS(argv
, argc
, idx_vrf
, vrf_name
, all_vrf
);
1585 for (ALL_LIST_ELEMENTS_RO(om6
->ospf6
, node
, ospf6
)) {
1586 if (all_vrf
|| strcmp(ospf6
->name
, vrf_name
) == 0) {
1587 ifp
= if_lookup_by_name(argv
[idx_ifname
]->arg
,
1590 vty_out(vty
, "No such Interface: %s\n",
1591 argv
[idx_ifname
]->arg
);
1597 || CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
)) {
1599 "Interface %s not attached to area\n",
1600 argv
[idx_ifname
]->arg
);
1604 ospf6_route_table_show(vty
, idx_prefix
, argc
, argv
,
1605 oi
->route_connected
, uj
);
1612 OSPF6_CMD_CHECK_VRF(uj
, all_vrf
, ospf6
);
1617 DEFUN(show_ipv6_ospf6_interface_prefix
, show_ipv6_ospf6_interface_prefix_cmd
,
1618 "show ipv6 ospf6 [vrf <NAME|all>] interface prefix\
1621 |<X:X::X:X|X:X::X:X/M> [<match|detail>]\
1623 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1624 "All VRFs\n" INTERFACE_STR
1625 "Display connected prefixes to advertise\n"
1626 "Display details of the prefixes\n" OSPF6_ROUTE_ADDRESS_STR
1627 OSPF6_ROUTE_PREFIX_STR OSPF6_ROUTE_MATCH_STR
1628 "Display details of the prefixes\n" JSON_STR
)
1630 struct vrf
*vrf
= NULL
;
1632 struct ospf6_interface
*oi
;
1633 struct interface
*ifp
;
1634 bool uj
= use_json(argc
, argv
);
1635 struct listnode
*node
;
1636 struct ospf6
*ospf6
;
1637 const char *vrf_name
= NULL
;
1638 bool all_vrf
= false;
1641 OSPF6_FIND_VRF_ARGS(argv
, argc
, idx_vrf
, vrf_name
, all_vrf
);
1645 for (ALL_LIST_ELEMENTS_RO(om6
->ospf6
, node
, ospf6
)) {
1646 if (all_vrf
|| strcmp(ospf6
->name
, vrf_name
) == 0) {
1647 vrf
= vrf_lookup_by_id(ospf6
->vrf_id
);
1648 FOR_ALL_INTERFACES (vrf
, ifp
) {
1649 oi
= (struct ospf6_interface
*)ifp
->info
;
1651 || CHECK_FLAG(oi
->flag
,
1652 OSPF6_INTERFACE_DISABLE
))
1655 ospf6_route_table_show(vty
, idx_prefix
, argc
,
1657 oi
->route_connected
, uj
);
1664 OSPF6_CMD_CHECK_VRF(uj
, all_vrf
, ospf6
);
1669 void ospf6_interface_start(struct ospf6_interface
*oi
)
1671 struct ospf6
*ospf6
;
1672 struct ospf6_area
*oa
;
1674 if (oi
->area_id_format
== OSPF6_AREA_FMT_UNSET
)
1680 ospf6
= oi
->interface
->vrf
->info
;
1684 oa
= ospf6_area_lookup(oi
->area_id
, ospf6
);
1686 oa
= ospf6_area_create(oi
->area_id
, ospf6
, oi
->area_id_format
);
1688 /* attach interface to area */
1689 listnode_add(oa
->if_list
, oi
);
1692 SET_FLAG(oa
->flag
, OSPF6_AREA_ENABLE
);
1695 ospf6_interface_enable(oi
);
1697 /* If the router is ABR, originate summary routes */
1698 if (ospf6_check_and_set_router_abr(ospf6
))
1699 ospf6_abr_enable_area(oa
);
1702 void ospf6_interface_stop(struct ospf6_interface
*oi
)
1704 struct ospf6_area
*oa
;
1710 ospf6_interface_disable(oi
);
1712 listnode_delete(oa
->if_list
, oi
);
1715 if (oa
->if_list
->count
== 0) {
1716 UNSET_FLAG(oa
->flag
, OSPF6_AREA_ENABLE
);
1717 ospf6_abr_disable_area(oa
);
1721 /* interface variable set command */
1722 DEFUN (ipv6_ospf6_area
,
1723 ipv6_ospf6_area_cmd
,
1724 "ipv6 ospf6 area <A.B.C.D|(0-4294967295)>",
1727 "Specify the OSPF6 area ID\n"
1728 "OSPF6 area ID in IPv4 address notation\n"
1729 "OSPF6 area ID in decimal notation\n")
1731 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1732 struct ospf6_interface
*oi
;
1739 oi
= (struct ospf6_interface
*)ifp
->info
;
1741 oi
= ospf6_interface_create(ifp
);
1745 vty_out(vty
, "%s already attached to Area %s\n",
1746 oi
->interface
->name
, oi
->area
->name
);
1750 if (str2area_id(argv
[idx_ipv4
]->arg
, &area_id
, &format
)) {
1751 vty_out(vty
, "Malformed Area-ID: %s\n", argv
[idx_ipv4
]->arg
);
1752 return CMD_WARNING_CONFIG_FAILED
;
1755 oi
->area_id
= area_id
;
1756 oi
->area_id_format
= format
;
1758 ospf6_interface_start(oi
);
1763 DEFUN (no_ipv6_ospf6_area
,
1764 no_ipv6_ospf6_area_cmd
,
1765 "no ipv6 ospf6 area [<A.B.C.D|(0-4294967295)>]",
1769 "Specify the OSPF6 area ID\n"
1770 "OSPF6 area ID in IPv4 address notation\n"
1771 "OSPF6 area ID in decimal notation\n")
1773 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1774 struct ospf6_interface
*oi
;
1778 oi
= (struct ospf6_interface
*)ifp
->info
;
1780 oi
= ospf6_interface_create(ifp
);
1783 ospf6_interface_stop(oi
);
1786 oi
->area_id_format
= OSPF6_AREA_FMT_UNSET
;
1791 DEFUN (ipv6_ospf6_ifmtu
,
1792 ipv6_ospf6_ifmtu_cmd
,
1793 "ipv6 ospf6 ifmtu (1-65535)",
1797 "OSPFv3 Interface MTU\n"
1800 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1802 struct ospf6_interface
*oi
;
1803 unsigned int ifmtu
, iobuflen
;
1804 struct listnode
*node
, *nnode
;
1805 struct ospf6_neighbor
*on
;
1809 oi
= (struct ospf6_interface
*)ifp
->info
;
1811 oi
= ospf6_interface_create(ifp
);
1814 ifmtu
= strtol(argv
[idx_number
]->arg
, NULL
, 10);
1816 if (oi
->c_ifmtu
== ifmtu
)
1819 if (ifp
->mtu6
!= 0 && ifp
->mtu6
< ifmtu
) {
1821 "%s's ospf6 ifmtu cannot go beyond physical mtu (%d)\n",
1822 ifp
->name
, ifp
->mtu6
);
1823 return CMD_WARNING_CONFIG_FAILED
;
1826 if (oi
->ifmtu
< ifmtu
) {
1827 iobuflen
= ospf6_iobuf_size(ifmtu
);
1828 if (iobuflen
< ifmtu
) {
1830 "%s's ifmtu is adjusted to I/O buffer size (%d).\n",
1831 ifp
->name
, iobuflen
);
1832 oi
->ifmtu
= oi
->c_ifmtu
= iobuflen
;
1834 oi
->ifmtu
= oi
->c_ifmtu
= ifmtu
;
1836 oi
->ifmtu
= oi
->c_ifmtu
= ifmtu
;
1838 /* re-establish adjacencies */
1839 for (ALL_LIST_ELEMENTS(oi
->neighbor_list
, node
, nnode
, on
)) {
1840 THREAD_OFF(on
->inactivity_timer
);
1841 thread_add_event(master
, inactivity_timer
, on
, 0, NULL
);
1847 DEFUN (no_ipv6_ospf6_ifmtu
,
1848 no_ipv6_ospf6_ifmtu_cmd
,
1849 "no ipv6 ospf6 ifmtu [(1-65535)]",
1854 "OSPFv3 Interface MTU\n"
1857 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1858 struct ospf6_interface
*oi
;
1859 unsigned int iobuflen
;
1860 struct listnode
*node
, *nnode
;
1861 struct ospf6_neighbor
*on
;
1865 oi
= (struct ospf6_interface
*)ifp
->info
;
1867 oi
= ospf6_interface_create(ifp
);
1870 if (oi
->ifmtu
< ifp
->mtu
) {
1871 iobuflen
= ospf6_iobuf_size(ifp
->mtu
);
1872 if (iobuflen
< ifp
->mtu
) {
1874 "%s's ifmtu is adjusted to I/O buffer size (%d).\n",
1875 ifp
->name
, iobuflen
);
1876 oi
->ifmtu
= iobuflen
;
1878 oi
->ifmtu
= ifp
->mtu
;
1880 oi
->ifmtu
= ifp
->mtu
;
1884 /* re-establish adjacencies */
1885 for (ALL_LIST_ELEMENTS(oi
->neighbor_list
, node
, nnode
, on
)) {
1886 THREAD_OFF(on
->inactivity_timer
);
1887 thread_add_event(master
, inactivity_timer
, on
, 0, NULL
);
1893 DEFUN (ipv6_ospf6_cost
,
1894 ipv6_ospf6_cost_cmd
,
1895 "ipv6 ospf6 cost (1-65535)",
1899 "Outgoing metric of this interface\n")
1901 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1903 struct ospf6_interface
*oi
;
1904 unsigned long int lcost
;
1908 oi
= (struct ospf6_interface
*)ifp
->info
;
1910 oi
= ospf6_interface_create(ifp
);
1913 lcost
= strtol(argv
[idx_number
]->arg
, NULL
, 10);
1915 if (lcost
> UINT32_MAX
) {
1916 vty_out(vty
, "Cost %ld is out of range\n", lcost
);
1917 return CMD_WARNING_CONFIG_FAILED
;
1920 SET_FLAG(oi
->flag
, OSPF6_INTERFACE_NOAUTOCOST
);
1921 if (oi
->cost
== lcost
)
1925 ospf6_interface_force_recalculate_cost(oi
);
1930 DEFUN (no_ipv6_ospf6_cost
,
1931 no_ipv6_ospf6_cost_cmd
,
1932 "no ipv6 ospf6 cost [(1-65535)]",
1936 "Calculate interface cost from bandwidth\n"
1937 "Outgoing metric of this interface\n")
1939 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1940 struct ospf6_interface
*oi
;
1943 oi
= (struct ospf6_interface
*)ifp
->info
;
1945 oi
= ospf6_interface_create(ifp
);
1948 UNSET_FLAG(oi
->flag
, OSPF6_INTERFACE_NOAUTOCOST
);
1950 ospf6_interface_recalculate_cost(oi
);
1955 DEFUN (auto_cost_reference_bandwidth
,
1956 auto_cost_reference_bandwidth_cmd
,
1957 "auto-cost reference-bandwidth (1-4294967)",
1958 "Calculate OSPF interface cost according to bandwidth\n"
1959 "Use reference bandwidth method to assign OSPF cost\n"
1960 "The reference bandwidth in terms of Mbits per second\n")
1962 VTY_DECLVAR_CONTEXT(ospf6
, o
);
1964 struct ospf6_area
*oa
;
1965 struct ospf6_interface
*oi
;
1966 struct listnode
*i
, *j
;
1969 refbw
= strtol(argv
[idx_number
]->arg
, NULL
, 10);
1970 if (refbw
< 1 || refbw
> 4294967) {
1971 vty_out(vty
, "reference-bandwidth value is invalid\n");
1972 return CMD_WARNING_CONFIG_FAILED
;
1975 /* If reference bandwidth is changed. */
1976 if ((refbw
) == o
->ref_bandwidth
)
1979 o
->ref_bandwidth
= refbw
;
1980 for (ALL_LIST_ELEMENTS_RO(o
->area_list
, i
, oa
))
1981 for (ALL_LIST_ELEMENTS_RO(oa
->if_list
, j
, oi
))
1982 ospf6_interface_recalculate_cost(oi
);
1987 DEFUN (no_auto_cost_reference_bandwidth
,
1988 no_auto_cost_reference_bandwidth_cmd
,
1989 "no auto-cost reference-bandwidth [(1-4294967)]",
1991 "Calculate OSPF interface cost according to bandwidth\n"
1992 "Use reference bandwidth method to assign OSPF cost\n"
1993 "The reference bandwidth in terms of Mbits per second\n")
1995 VTY_DECLVAR_CONTEXT(ospf6
, o
);
1996 struct ospf6_area
*oa
;
1997 struct ospf6_interface
*oi
;
1998 struct listnode
*i
, *j
;
2000 if (o
->ref_bandwidth
== OSPF6_REFERENCE_BANDWIDTH
)
2003 o
->ref_bandwidth
= OSPF6_REFERENCE_BANDWIDTH
;
2004 for (ALL_LIST_ELEMENTS_RO(o
->area_list
, i
, oa
))
2005 for (ALL_LIST_ELEMENTS_RO(oa
->if_list
, j
, oi
))
2006 ospf6_interface_recalculate_cost(oi
);
2012 DEFUN (ospf6_write_multiplier
,
2013 ospf6_write_multiplier_cmd
,
2014 "write-multiplier (1-100)",
2015 "Write multiplier\n"
2016 "Maximum number of interface serviced per write\n")
2018 VTY_DECLVAR_CONTEXT(ospf6
, o
);
2019 uint32_t write_oi_count
;
2021 write_oi_count
= strtol(argv
[1]->arg
, NULL
, 10);
2022 if (write_oi_count
< 1 || write_oi_count
> 100) {
2023 vty_out(vty
, "write-multiplier value is invalid\n");
2024 return CMD_WARNING_CONFIG_FAILED
;
2027 o
->write_oi_count
= write_oi_count
;
2031 DEFUN (no_ospf6_write_multiplier
,
2032 no_ospf6_write_multiplier_cmd
,
2033 "no write-multiplier (1-100)",
2035 "Write multiplier\n"
2036 "Maximum number of interface serviced per write\n")
2038 VTY_DECLVAR_CONTEXT(ospf6
, o
);
2040 o
->write_oi_count
= OSPF6_WRITE_INTERFACE_COUNT_DEFAULT
;
2044 DEFUN (ipv6_ospf6_hellointerval
,
2045 ipv6_ospf6_hellointerval_cmd
,
2046 "ipv6 ospf6 hello-interval (1-65535)",
2049 "Time between HELLO packets\n"
2052 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2054 struct ospf6_interface
*oi
;
2057 oi
= (struct ospf6_interface
*)ifp
->info
;
2059 oi
= ospf6_interface_create(ifp
);
2062 oi
->hello_interval
= strmatch(argv
[0]->text
, "no")
2063 ? OSPF_HELLO_INTERVAL_DEFAULT
2064 : strtoul(argv
[idx_number
]->arg
, NULL
, 10);
2068 ALIAS (ipv6_ospf6_hellointerval
,
2069 no_ipv6_ospf6_hellointerval_cmd
,
2070 "no ipv6 ospf6 hello-interval [(1-65535)]",
2074 "Time between HELLO packets\n"
2077 /* interface variable set command */
2078 DEFUN (ipv6_ospf6_deadinterval
,
2079 ipv6_ospf6_deadinterval_cmd
,
2080 "ipv6 ospf6 dead-interval (1-65535)",
2083 "Interval time after which a neighbor is declared down\n"
2086 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2088 struct ospf6_interface
*oi
;
2091 oi
= (struct ospf6_interface
*)ifp
->info
;
2093 oi
= ospf6_interface_create(ifp
);
2096 oi
->dead_interval
= strmatch(argv
[0]->arg
, "no")
2097 ? OSPF_ROUTER_DEAD_INTERVAL_DEFAULT
2098 : strtoul(argv
[idx_number
]->arg
, NULL
, 10);
2102 ALIAS (ipv6_ospf6_deadinterval
,
2103 no_ipv6_ospf6_deadinterval_cmd
,
2104 "no ipv6 ospf6 dead-interval [(1-65535)]",
2108 "Interval time after which a neighbor is declared down\n"
2111 /* interface variable set command */
2112 DEFUN (ipv6_ospf6_transmitdelay
,
2113 ipv6_ospf6_transmitdelay_cmd
,
2114 "ipv6 ospf6 transmit-delay (1-3600)",
2117 "Link state transmit delay\n"
2120 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2122 struct ospf6_interface
*oi
;
2125 oi
= (struct ospf6_interface
*)ifp
->info
;
2127 oi
= ospf6_interface_create(ifp
);
2130 oi
->transdelay
= strmatch(argv
[0]->text
, "no")
2131 ? OSPF6_INTERFACE_TRANSDELAY
2132 : strtoul(argv
[idx_number
]->arg
, NULL
, 10);
2136 ALIAS (ipv6_ospf6_transmitdelay
,
2137 no_ipv6_ospf6_transmitdelay_cmd
,
2138 "no ipv6 ospf6 transmit-delay [(1-3600)]",
2142 "Link state transmit delay\n"
2145 /* interface variable set command */
2146 DEFUN (ipv6_ospf6_retransmitinterval
,
2147 ipv6_ospf6_retransmitinterval_cmd
,
2148 "ipv6 ospf6 retransmit-interval (1-65535)",
2151 "Time between retransmitting lost link state advertisements\n"
2154 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2156 struct ospf6_interface
*oi
;
2159 oi
= (struct ospf6_interface
*)ifp
->info
;
2161 oi
= ospf6_interface_create(ifp
);
2164 oi
->rxmt_interval
= strmatch(argv
[0]->text
, "no")
2165 ? OSPF_RETRANSMIT_INTERVAL_DEFAULT
2166 : strtoul(argv
[idx_number
]->arg
, NULL
, 10);
2170 ALIAS (ipv6_ospf6_retransmitinterval
,
2171 no_ipv6_ospf6_retransmitinterval_cmd
,
2172 "no ipv6 ospf6 retransmit-interval [(1-65535)]",
2176 "Time between retransmitting lost link state advertisements\n"
2179 /* interface variable set command */
2180 DEFUN (ipv6_ospf6_priority
,
2181 ipv6_ospf6_priority_cmd
,
2182 "ipv6 ospf6 priority (0-255)",
2188 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2190 struct ospf6_interface
*oi
;
2193 oi
= (struct ospf6_interface
*)ifp
->info
;
2195 oi
= ospf6_interface_create(ifp
);
2198 oi
->priority
= strmatch(argv
[0]->text
, "no")
2199 ? OSPF6_INTERFACE_PRIORITY
2200 : strtoul(argv
[idx_number
]->arg
, NULL
, 10);
2203 && (oi
->state
== OSPF6_INTERFACE_DROTHER
2204 || oi
->state
== OSPF6_INTERFACE_BDR
2205 || oi
->state
== OSPF6_INTERFACE_DR
)) {
2206 if (ospf6_interface_state_change(dr_election(oi
), oi
) == -1)
2207 OSPF6_LINK_LSA_SCHEDULE(oi
);
2213 ALIAS (ipv6_ospf6_priority
,
2214 no_ipv6_ospf6_priority_cmd
,
2215 "no ipv6 ospf6 priority [(0-255)]",
2222 DEFUN (ipv6_ospf6_instance
,
2223 ipv6_ospf6_instance_cmd
,
2224 "ipv6 ospf6 instance-id (0-255)",
2227 "Instance ID for this interface\n"
2228 "Instance ID value\n")
2230 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2232 struct ospf6_interface
*oi
;
2235 oi
= (struct ospf6_interface
*)ifp
->info
;
2237 oi
= ospf6_interface_create(ifp
);
2240 oi
->instance_id
= strmatch(argv
[0]->text
, "no")
2241 ? OSPF6_INTERFACE_INSTANCE_ID
2242 : strtoul(argv
[idx_number
]->arg
, NULL
, 10);
2246 ALIAS (ipv6_ospf6_instance
,
2247 no_ipv6_ospf6_instance_cmd
,
2248 "no ipv6 ospf6 instance-id [(0-255)]",
2252 "Instance ID for this interface\n"
2253 "Instance ID value\n")
2255 DEFUN (ipv6_ospf6_passive
,
2256 ipv6_ospf6_passive_cmd
,
2257 "ipv6 ospf6 passive",
2260 "Passive interface; no adjacency will be formed on this interface\n"
2263 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2264 struct ospf6_interface
*oi
;
2265 struct listnode
*node
, *nnode
;
2266 struct ospf6_neighbor
*on
;
2270 oi
= (struct ospf6_interface
*)ifp
->info
;
2272 oi
= ospf6_interface_create(ifp
);
2275 SET_FLAG(oi
->flag
, OSPF6_INTERFACE_PASSIVE
);
2276 THREAD_OFF(oi
->thread_send_hello
);
2277 THREAD_OFF(oi
->thread_sso
);
2279 for (ALL_LIST_ELEMENTS(oi
->neighbor_list
, node
, nnode
, on
)) {
2280 THREAD_OFF(on
->inactivity_timer
);
2281 thread_add_event(master
, inactivity_timer
, on
, 0, NULL
);
2287 DEFUN (no_ipv6_ospf6_passive
,
2288 no_ipv6_ospf6_passive_cmd
,
2289 "no ipv6 ospf6 passive",
2293 "passive interface: No Adjacency will be formed on this I/F\n"
2296 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2297 struct ospf6_interface
*oi
;
2300 oi
= (struct ospf6_interface
*)ifp
->info
;
2302 oi
= ospf6_interface_create(ifp
);
2305 UNSET_FLAG(oi
->flag
, OSPF6_INTERFACE_PASSIVE
);
2306 THREAD_OFF(oi
->thread_send_hello
);
2307 THREAD_OFF(oi
->thread_sso
);
2309 /* don't send hellos over loopback interface */
2310 if (!if_is_loopback(oi
->interface
))
2311 thread_add_event(master
, ospf6_hello_send
, oi
, 0,
2312 &oi
->thread_send_hello
);
2317 DEFUN (ipv6_ospf6_mtu_ignore
,
2318 ipv6_ospf6_mtu_ignore_cmd
,
2319 "ipv6 ospf6 mtu-ignore",
2322 "Disable MTU mismatch detection on this interface\n"
2325 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2326 struct ospf6_interface
*oi
;
2329 oi
= (struct ospf6_interface
*)ifp
->info
;
2331 oi
= ospf6_interface_create(ifp
);
2339 DEFUN (no_ipv6_ospf6_mtu_ignore
,
2340 no_ipv6_ospf6_mtu_ignore_cmd
,
2341 "no ipv6 ospf6 mtu-ignore",
2345 "Disable MTU mismatch detection on this interface\n"
2348 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2349 struct ospf6_interface
*oi
;
2352 oi
= (struct ospf6_interface
*)ifp
->info
;
2354 oi
= ospf6_interface_create(ifp
);
2362 DEFUN (ipv6_ospf6_advertise_prefix_list
,
2363 ipv6_ospf6_advertise_prefix_list_cmd
,
2364 "ipv6 ospf6 advertise prefix-list WORD",
2367 "Advertising options\n"
2368 "Filter prefix using prefix-list\n"
2369 "Prefix list name\n"
2372 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2374 struct ospf6_interface
*oi
;
2377 oi
= (struct ospf6_interface
*)ifp
->info
;
2379 oi
= ospf6_interface_create(ifp
);
2383 XFREE(MTYPE_CFG_PLIST_NAME
, oi
->plist_name
);
2384 oi
->plist_name
= XSTRDUP(MTYPE_CFG_PLIST_NAME
, argv
[idx_word
]->arg
);
2386 ospf6_interface_connected_route_update(oi
->interface
);
2389 OSPF6_LINK_LSA_SCHEDULE(oi
);
2390 if (oi
->state
== OSPF6_INTERFACE_DR
) {
2391 OSPF6_NETWORK_LSA_SCHEDULE(oi
);
2392 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi
);
2394 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi
->area
);
2400 DEFUN (no_ipv6_ospf6_advertise_prefix_list
,
2401 no_ipv6_ospf6_advertise_prefix_list_cmd
,
2402 "no ipv6 ospf6 advertise prefix-list [WORD]",
2406 "Advertising options\n"
2407 "Filter prefix using prefix-list\n"
2408 "Prefix list name\n")
2410 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2411 struct ospf6_interface
*oi
;
2414 oi
= (struct ospf6_interface
*)ifp
->info
;
2416 oi
= ospf6_interface_create(ifp
);
2420 XFREE(MTYPE_CFG_PLIST_NAME
, oi
->plist_name
);
2422 ospf6_interface_connected_route_update(oi
->interface
);
2425 OSPF6_LINK_LSA_SCHEDULE(oi
);
2426 if (oi
->state
== OSPF6_INTERFACE_DR
) {
2427 OSPF6_NETWORK_LSA_SCHEDULE(oi
);
2428 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi
);
2430 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi
->area
);
2436 DEFUN (ipv6_ospf6_network
,
2437 ipv6_ospf6_network_cmd
,
2438 "ipv6 ospf6 network <broadcast|point-to-point>",
2442 "Specify OSPF6 broadcast network\n"
2443 "Specify OSPF6 point-to-point network\n"
2446 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2447 int idx_network
= 3;
2448 struct ospf6_interface
*oi
;
2451 oi
= (struct ospf6_interface
*)ifp
->info
;
2453 oi
= ospf6_interface_create(ifp
);
2457 oi
->type_cfg
= true;
2459 if (strncmp(argv
[idx_network
]->arg
, "b", 1) == 0) {
2460 if (oi
->type
== OSPF_IFTYPE_BROADCAST
)
2463 oi
->type
= OSPF_IFTYPE_BROADCAST
;
2464 } else if (strncmp(argv
[idx_network
]->arg
, "point-to-p", 10) == 0) {
2465 if (oi
->type
== OSPF_IFTYPE_POINTOPOINT
) {
2468 oi
->type
= OSPF_IFTYPE_POINTOPOINT
;
2471 /* Reset the interface */
2472 thread_execute(master
, interface_down
, oi
, 0);
2473 thread_execute(master
, interface_up
, oi
, 0);
2478 DEFUN (no_ipv6_ospf6_network
,
2479 no_ipv6_ospf6_network_cmd
,
2480 "no ipv6 ospf6 network [<broadcast|point-to-point>]",
2484 "Set default network type\n"
2485 "Specify OSPF6 broadcast network\n"
2486 "Specify OSPF6 point-to-point network\n")
2488 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2489 struct ospf6_interface
*oi
;
2494 oi
= (struct ospf6_interface
*)ifp
->info
;
2499 oi
->type_cfg
= false;
2501 type
= ospf6_default_iftype(ifp
);
2502 if (oi
->type
== type
) {
2507 /* Reset the interface */
2508 thread_execute(master
, interface_down
, oi
, 0);
2509 thread_execute(master
, interface_up
, oi
, 0);
2514 static int config_write_ospf6_interface(struct vty
*vty
, struct vrf
*vrf
)
2516 struct ospf6_interface
*oi
;
2517 struct interface
*ifp
;
2518 char buf
[INET_ADDRSTRLEN
];
2520 FOR_ALL_INTERFACES (vrf
, ifp
) {
2521 oi
= (struct ospf6_interface
*)ifp
->info
;
2525 if_vty_config_start(vty
, ifp
);
2528 vty_out(vty
, " description %s\n", ifp
->desc
);
2529 if (oi
->area_id_format
!= OSPF6_AREA_FMT_UNSET
) {
2530 area_id2str(buf
, sizeof(buf
), oi
->area_id
,
2531 oi
->area_id_format
);
2532 vty_out(vty
, " ipv6 ospf6 area %s\n", buf
);
2535 vty_out(vty
, " ipv6 ospf6 ifmtu %d\n", oi
->c_ifmtu
);
2537 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_NOAUTOCOST
))
2538 vty_out(vty
, " ipv6 ospf6 cost %d\n", oi
->cost
);
2540 if (oi
->hello_interval
!= OSPF6_INTERFACE_HELLO_INTERVAL
)
2541 vty_out(vty
, " ipv6 ospf6 hello-interval %d\n",
2542 oi
->hello_interval
);
2544 if (oi
->dead_interval
!= OSPF6_INTERFACE_DEAD_INTERVAL
)
2545 vty_out(vty
, " ipv6 ospf6 dead-interval %d\n",
2548 if (oi
->rxmt_interval
!= OSPF6_INTERFACE_RXMT_INTERVAL
)
2549 vty_out(vty
, " ipv6 ospf6 retransmit-interval %d\n",
2552 if (oi
->priority
!= OSPF6_INTERFACE_PRIORITY
)
2553 vty_out(vty
, " ipv6 ospf6 priority %d\n", oi
->priority
);
2555 if (oi
->transdelay
!= OSPF6_INTERFACE_TRANSDELAY
)
2556 vty_out(vty
, " ipv6 ospf6 transmit-delay %d\n",
2559 if (oi
->instance_id
!= OSPF6_INTERFACE_INSTANCE_ID
)
2560 vty_out(vty
, " ipv6 ospf6 instance-id %d\n",
2564 vty_out(vty
, " ipv6 ospf6 advertise prefix-list %s\n",
2567 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_PASSIVE
))
2568 vty_out(vty
, " ipv6 ospf6 passive\n");
2571 vty_out(vty
, " ipv6 ospf6 mtu-ignore\n");
2573 if (oi
->type_cfg
&& oi
->type
== OSPF_IFTYPE_POINTOPOINT
)
2574 vty_out(vty
, " ipv6 ospf6 network point-to-point\n");
2575 else if (oi
->type_cfg
&& oi
->type
== OSPF_IFTYPE_BROADCAST
)
2576 vty_out(vty
, " ipv6 ospf6 network broadcast\n");
2578 ospf6_bfd_write_config(vty
, oi
);
2580 if_vty_config_end(vty
);
2585 /* Configuration write function for ospfd. */
2586 static int config_write_interface(struct vty
*vty
)
2589 struct vrf
*vrf
= NULL
;
2591 /* Display all VRF aware OSPF interface configuration */
2592 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2593 write
+= config_write_ospf6_interface(vty
, vrf
);
2599 static int ospf6_ifp_create(struct interface
*ifp
)
2601 if (IS_OSPF6_DEBUG_ZEBRA(RECV
))
2602 zlog_debug("Zebra Interface add: %s index %d mtu %d", ifp
->name
,
2603 ifp
->ifindex
, ifp
->mtu6
);
2606 ospf6_interface_start(ifp
->info
);
2611 static int ospf6_ifp_up(struct interface
*ifp
)
2613 if (IS_OSPF6_DEBUG_ZEBRA(RECV
))
2615 "Zebra Interface state change: %s index %d flags %llx metric %d mtu %d bandwidth %d",
2616 ifp
->name
, ifp
->ifindex
, (unsigned long long)ifp
->flags
,
2617 ifp
->metric
, ifp
->mtu6
, ifp
->bandwidth
);
2619 ospf6_interface_state_update(ifp
);
2624 static int ospf6_ifp_down(struct interface
*ifp
)
2626 if (IS_OSPF6_DEBUG_ZEBRA(RECV
))
2628 "Zebra Interface state change: %s index %d flags %llx metric %d mtu %d bandwidth %d",
2629 ifp
->name
, ifp
->ifindex
, (unsigned long long)ifp
->flags
,
2630 ifp
->metric
, ifp
->mtu6
, ifp
->bandwidth
);
2632 ospf6_interface_state_update(ifp
);
2637 static int ospf6_ifp_destroy(struct interface
*ifp
)
2640 zlog_warn("Zebra: got delete of %s, but interface is still up",
2643 if (IS_OSPF6_DEBUG_ZEBRA(RECV
))
2644 zlog_debug("Zebra Interface delete: %s index %d mtu %d",
2645 ifp
->name
, ifp
->ifindex
, ifp
->mtu6
);
2648 ospf6_interface_stop(ifp
->info
);
2653 void ospf6_interface_init(void)
2655 /* Install interface node. */
2656 if_cmd_init(config_write_interface
);
2657 if_zapi_callbacks(ospf6_ifp_create
, ospf6_ifp_up
,
2658 ospf6_ifp_down
, ospf6_ifp_destroy
);
2660 install_element(VIEW_NODE
, &show_ipv6_ospf6_interface_prefix_cmd
);
2661 install_element(VIEW_NODE
, &show_ipv6_ospf6_interface_ifname_cmd
);
2662 install_element(VIEW_NODE
,
2663 &show_ipv6_ospf6_interface_ifname_prefix_cmd
);
2664 install_element(VIEW_NODE
, &show_ipv6_ospf6_interface_traffic_cmd
);
2666 install_element(INTERFACE_NODE
, &ipv6_ospf6_area_cmd
);
2667 install_element(INTERFACE_NODE
, &no_ipv6_ospf6_area_cmd
);
2668 install_element(INTERFACE_NODE
, &ipv6_ospf6_cost_cmd
);
2669 install_element(INTERFACE_NODE
, &no_ipv6_ospf6_cost_cmd
);
2670 install_element(INTERFACE_NODE
, &ipv6_ospf6_ifmtu_cmd
);
2671 install_element(INTERFACE_NODE
, &no_ipv6_ospf6_ifmtu_cmd
);
2673 install_element(INTERFACE_NODE
, &ipv6_ospf6_deadinterval_cmd
);
2674 install_element(INTERFACE_NODE
, &ipv6_ospf6_hellointerval_cmd
);
2675 install_element(INTERFACE_NODE
, &ipv6_ospf6_priority_cmd
);
2676 install_element(INTERFACE_NODE
, &ipv6_ospf6_retransmitinterval_cmd
);
2677 install_element(INTERFACE_NODE
, &ipv6_ospf6_transmitdelay_cmd
);
2678 install_element(INTERFACE_NODE
, &ipv6_ospf6_instance_cmd
);
2679 install_element(INTERFACE_NODE
, &no_ipv6_ospf6_deadinterval_cmd
);
2680 install_element(INTERFACE_NODE
, &no_ipv6_ospf6_hellointerval_cmd
);
2681 install_element(INTERFACE_NODE
, &no_ipv6_ospf6_priority_cmd
);
2682 install_element(INTERFACE_NODE
, &no_ipv6_ospf6_retransmitinterval_cmd
);
2683 install_element(INTERFACE_NODE
, &no_ipv6_ospf6_transmitdelay_cmd
);
2684 install_element(INTERFACE_NODE
, &no_ipv6_ospf6_instance_cmd
);
2686 install_element(INTERFACE_NODE
, &ipv6_ospf6_passive_cmd
);
2687 install_element(INTERFACE_NODE
, &no_ipv6_ospf6_passive_cmd
);
2689 install_element(INTERFACE_NODE
, &ipv6_ospf6_mtu_ignore_cmd
);
2690 install_element(INTERFACE_NODE
, &no_ipv6_ospf6_mtu_ignore_cmd
);
2692 install_element(INTERFACE_NODE
, &ipv6_ospf6_advertise_prefix_list_cmd
);
2693 install_element(INTERFACE_NODE
,
2694 &no_ipv6_ospf6_advertise_prefix_list_cmd
);
2696 install_element(INTERFACE_NODE
, &ipv6_ospf6_network_cmd
);
2697 install_element(INTERFACE_NODE
, &no_ipv6_ospf6_network_cmd
);
2699 /* reference bandwidth commands */
2700 install_element(OSPF6_NODE
, &auto_cost_reference_bandwidth_cmd
);
2701 install_element(OSPF6_NODE
, &no_auto_cost_reference_bandwidth_cmd
);
2702 /* write-multiplier commands */
2703 install_element(OSPF6_NODE
, &ospf6_write_multiplier_cmd
);
2704 install_element(OSPF6_NODE
, &no_ospf6_write_multiplier_cmd
);
2707 /* Clear the specified interface structure */
2708 void ospf6_interface_clear(struct interface
*ifp
)
2710 struct ospf6_interface
*oi
;
2712 if (!if_is_operative(ifp
))
2715 if (ifp
->info
== NULL
)
2718 oi
= (struct ospf6_interface
*)ifp
->info
;
2720 if (IS_OSPF6_DEBUG_INTERFACE
)
2721 zlog_debug("Interface %s: clear by reset", ifp
->name
);
2723 /* Reset the interface */
2724 thread_execute(master
, interface_down
, oi
, 0);
2725 thread_execute(master
, interface_up
, oi
, 0);
2728 /* Clear interface */
2729 DEFUN (clear_ipv6_ospf6_interface
,
2730 clear_ipv6_ospf6_interface_cmd
,
2731 "clear ipv6 ospf6 [vrf NAME] interface [IFNAME]",
2743 struct interface
*ifp
;
2744 const char *vrf_name
;
2746 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
2747 vrf_name
= argv
[idx_vrf
+ 1]->arg
;
2749 vrf_name
= VRF_DEFAULT_NAME
;
2750 vrf
= vrf_lookup_by_name(vrf_name
);
2752 vty_out(vty
, "%% VRF %s not found\n", vrf_name
);
2756 if (!argv_find(argv
, argc
, "IFNAME", &idx_ifname
)) {
2757 /* Clear all the ospfv3 interfaces. */
2758 FOR_ALL_INTERFACES (vrf
, ifp
)
2759 ospf6_interface_clear(ifp
);
2761 /* Interface name is specified. */
2762 ifp
= if_lookup_by_name_vrf(argv
[idx_ifname
]->arg
, vrf
);
2764 vty_out(vty
, "No such Interface: %s\n",
2765 argv
[idx_ifname
]->arg
);
2768 ospf6_interface_clear(ifp
);
2774 void install_element_ospf6_clear_interface(void)
2776 install_element(ENABLE_NODE
, &clear_ipv6_ospf6_interface_cmd
);
2779 DEFUN (debug_ospf6_interface
,
2780 debug_ospf6_interface_cmd
,
2781 "debug ospf6 interface",
2784 "Debug OSPFv3 Interface\n"
2787 OSPF6_DEBUG_INTERFACE_ON();
2791 DEFUN (no_debug_ospf6_interface
,
2792 no_debug_ospf6_interface_cmd
,
2793 "no debug ospf6 interface",
2797 "Debug OSPFv3 Interface\n"
2800 OSPF6_DEBUG_INTERFACE_OFF();
2804 int config_write_ospf6_debug_interface(struct vty
*vty
)
2806 if (IS_OSPF6_DEBUG_INTERFACE
)
2807 vty_out(vty
, "debug ospf6 interface\n");
2811 void install_element_ospf6_debug_interface(void)
2813 install_element(ENABLE_NODE
, &debug_ospf6_interface_cmd
);
2814 install_element(ENABLE_NODE
, &no_debug_ospf6_interface_cmd
);
2815 install_element(CONFIG_NODE
, &debug_ospf6_interface_cmd
);
2816 install_element(CONFIG_NODE
, &no_debug_ospf6_interface_cmd
);