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_network.h"
35 #include "ospf6_message.h"
36 #include "ospf6_route.h"
37 #include "ospf6_top.h"
38 #include "ospf6_area.h"
39 #include "ospf6_interface.h"
40 #include "ospf6_neighbor.h"
41 #include "ospf6_intra.h"
42 #include "ospf6_spf.h"
44 #include "ospf6_bfd.h"
46 DEFINE_MTYPE_STATIC(OSPF6D
, CFG_PLIST_NAME
, "configured prefix list names")
47 DEFINE_QOBJ_TYPE(ospf6_interface
)
48 DEFINE_HOOK(ospf6_interface_change
,
49 (struct ospf6_interface
* oi
, int state
, int old_state
),
50 (oi
, state
, old_state
))
52 unsigned char conf_debug_ospf6_interface
= 0;
54 const char *ospf6_interface_state_str
[] = {
55 "None", "Down", "Loopback", "Waiting", "PointToPoint",
56 "DROther", "BDR", "DR", NULL
};
58 struct ospf6_interface
*ospf6_interface_lookup_by_ifindex(ifindex_t ifindex
)
60 struct ospf6_interface
*oi
;
61 struct interface
*ifp
;
63 ifp
= if_lookup_by_index(ifindex
, VRF_DEFAULT
);
65 return (struct ospf6_interface
*)NULL
;
67 oi
= (struct ospf6_interface
*)ifp
->info
;
71 /* schedule routing table recalculation */
72 static void ospf6_interface_lsdb_hook(struct ospf6_lsa
*lsa
,
75 struct ospf6_interface
*oi
;
81 switch (ntohs(lsa
->header
->type
)) {
82 case OSPF6_LSTYPE_LINK
:
83 if (oi
->state
== OSPF6_INTERFACE_DR
)
84 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi
);
86 ospf6_spf_schedule(oi
->area
->ospf6
, reason
);
94 static void ospf6_interface_lsdb_hook_add(struct ospf6_lsa
*lsa
)
96 ospf6_interface_lsdb_hook(lsa
, ospf6_lsadd_to_spf_reason(lsa
));
99 static void ospf6_interface_lsdb_hook_remove(struct ospf6_lsa
*lsa
)
101 ospf6_interface_lsdb_hook(lsa
, ospf6_lsremove_to_spf_reason(lsa
));
104 static uint8_t ospf6_default_iftype(struct interface
*ifp
)
106 if (if_is_pointopoint(ifp
))
107 return OSPF_IFTYPE_POINTOPOINT
;
108 else if (if_is_loopback(ifp
))
109 return OSPF_IFTYPE_LOOPBACK
;
111 return OSPF_IFTYPE_BROADCAST
;
114 static uint32_t ospf6_interface_get_cost(struct ospf6_interface
*oi
)
116 /* If all else fails, use default OSPF cost */
120 /* interface speed and bw can be 0 in some platforms,
121 * use ospf default bw. If bw is configured then it would
124 if (!oi
->interface
->bandwidth
&& oi
->interface
->speed
) {
125 bw
= oi
->interface
->speed
;
127 bw
= oi
->interface
->bandwidth
? oi
->interface
->bandwidth
128 : OSPF6_INTERFACE_BANDWIDTH
;
131 refbw
= ospf6
? ospf6
->ref_bandwidth
: OSPF6_REFERENCE_BANDWIDTH
;
133 /* A specifed ip ospf cost overrides a calculated one. */
134 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_NOAUTOCOST
))
137 cost
= (uint32_t)((double)refbw
/ (double)bw
+ (double)0.5);
140 else if (cost
> UINT32_MAX
)
147 static void ospf6_interface_force_recalculate_cost(struct ospf6_interface
*oi
)
149 /* update cost held in route_connected list in ospf6_interface */
150 ospf6_interface_connected_route_update(oi
->interface
);
152 /* execute LSA hooks */
154 OSPF6_LINK_LSA_SCHEDULE(oi
);
155 OSPF6_ROUTER_LSA_SCHEDULE(oi
->area
);
156 OSPF6_NETWORK_LSA_SCHEDULE(oi
);
157 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi
);
158 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi
->area
);
162 static void ospf6_interface_recalculate_cost(struct ospf6_interface
*oi
)
166 newcost
= ospf6_interface_get_cost(oi
);
167 if (newcost
== oi
->cost
)
171 ospf6_interface_force_recalculate_cost(oi
);
174 /* Create new ospf6 interface structure */
175 struct ospf6_interface
*ospf6_interface_create(struct interface
*ifp
)
177 struct ospf6_interface
*oi
;
178 unsigned int iobuflen
;
180 oi
= XCALLOC(MTYPE_OSPF6_IF
, sizeof(struct ospf6_interface
));
182 oi
->area
= (struct ospf6_area
*)NULL
;
183 oi
->neighbor_list
= list_new();
184 oi
->neighbor_list
->cmp
= ospf6_neighbor_cmp
;
185 oi
->linklocal_addr
= (struct in6_addr
*)NULL
;
186 oi
->instance_id
= OSPF6_INTERFACE_INSTANCE_ID
;
187 oi
->transdelay
= OSPF6_INTERFACE_TRANSDELAY
;
188 oi
->priority
= OSPF6_INTERFACE_PRIORITY
;
190 oi
->hello_interval
= OSPF_HELLO_INTERVAL_DEFAULT
;
191 oi
->dead_interval
= OSPF_ROUTER_DEAD_INTERVAL_DEFAULT
;
192 oi
->rxmt_interval
= OSPF_RETRANSMIT_INTERVAL_DEFAULT
;
193 oi
->type
= ospf6_default_iftype(ifp
);
194 oi
->state
= OSPF6_INTERFACE_DOWN
;
199 /* Try to adjust I/O buffer size with IfMtu */
200 oi
->ifmtu
= ifp
->mtu6
;
201 iobuflen
= ospf6_iobuf_size(ifp
->mtu6
);
202 if (oi
->ifmtu
> iobuflen
) {
203 if (IS_OSPF6_DEBUG_INTERFACE
)
205 "Interface %s: IfMtu is adjusted to I/O buffer size: %d.",
206 ifp
->name
, iobuflen
);
207 oi
->ifmtu
= iobuflen
;
210 QOBJ_REG(oi
, ospf6_interface
);
212 oi
->lsupdate_list
= ospf6_lsdb_create(oi
);
213 oi
->lsack_list
= ospf6_lsdb_create(oi
);
214 oi
->lsdb
= ospf6_lsdb_create(oi
);
215 oi
->lsdb
->hook_add
= ospf6_interface_lsdb_hook_add
;
216 oi
->lsdb
->hook_remove
= ospf6_interface_lsdb_hook_remove
;
217 oi
->lsdb_self
= ospf6_lsdb_create(oi
);
219 oi
->route_connected
=
220 OSPF6_ROUTE_TABLE_CREATE(INTERFACE
, CONNECTED_ROUTES
);
221 oi
->route_connected
->scope
= oi
;
228 oi
->cost
= ospf6_interface_get_cost(oi
);
233 void ospf6_interface_delete(struct ospf6_interface
*oi
)
235 struct listnode
*node
, *nnode
;
236 struct ospf6_neighbor
*on
;
240 for (ALL_LIST_ELEMENTS(oi
->neighbor_list
, node
, nnode
, on
))
241 ospf6_neighbor_delete(on
);
243 list_delete(&oi
->neighbor_list
);
245 THREAD_OFF(oi
->thread_send_hello
);
246 THREAD_OFF(oi
->thread_send_lsupdate
);
247 THREAD_OFF(oi
->thread_send_lsack
);
248 THREAD_OFF(oi
->thread_sso
);
250 ospf6_lsdb_remove_all(oi
->lsdb
);
251 ospf6_lsdb_remove_all(oi
->lsupdate_list
);
252 ospf6_lsdb_remove_all(oi
->lsack_list
);
254 ospf6_lsdb_delete(oi
->lsdb
);
255 ospf6_lsdb_delete(oi
->lsdb_self
);
257 ospf6_lsdb_delete(oi
->lsupdate_list
);
258 ospf6_lsdb_delete(oi
->lsack_list
);
260 ospf6_route_table_delete(oi
->route_connected
);
263 oi
->interface
->info
= NULL
;
267 XFREE(MTYPE_CFG_PLIST_NAME
, oi
->plist_name
);
269 ospf6_bfd_info_free(&(oi
->bfd_info
));
271 /* disable from area list if possible */
272 ospf6_area_interface_delete(oi
);
274 XFREE(MTYPE_OSPF6_IF
, oi
);
277 void ospf6_interface_enable(struct ospf6_interface
*oi
)
279 UNSET_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
);
280 ospf6_interface_state_update(oi
->interface
);
283 void ospf6_interface_disable(struct ospf6_interface
*oi
)
285 SET_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
);
287 thread_execute(master
, interface_down
, oi
, 0);
289 ospf6_lsdb_remove_all(oi
->lsdb
);
290 ospf6_lsdb_remove_all(oi
->lsdb_self
);
291 ospf6_lsdb_remove_all(oi
->lsupdate_list
);
292 ospf6_lsdb_remove_all(oi
->lsack_list
);
294 THREAD_OFF(oi
->thread_send_hello
);
295 THREAD_OFF(oi
->thread_send_lsupdate
);
296 THREAD_OFF(oi
->thread_send_lsack
);
297 THREAD_OFF(oi
->thread_sso
);
299 THREAD_OFF(oi
->thread_network_lsa
);
300 THREAD_OFF(oi
->thread_link_lsa
);
301 THREAD_OFF(oi
->thread_intra_prefix_lsa
);
302 THREAD_OFF(oi
->thread_as_extern_lsa
);
305 static struct in6_addr
*
306 ospf6_interface_get_linklocal_address(struct interface
*ifp
)
310 struct in6_addr
*l
= (struct in6_addr
*)NULL
;
312 /* for each connected address */
313 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, n
, c
)) {
314 /* if family not AF_INET6, ignore */
315 if (c
->address
->family
!= AF_INET6
)
318 /* linklocal scope check */
319 if (IN6_IS_ADDR_LINKLOCAL(&c
->address
->u
.prefix6
))
320 l
= &c
->address
->u
.prefix6
;
325 void ospf6_interface_if_add(struct interface
*ifp
)
327 struct ospf6_interface
*oi
;
328 unsigned int iobuflen
;
330 oi
= (struct ospf6_interface
*)ifp
->info
;
334 /* Try to adjust I/O buffer size with IfMtu */
336 oi
->ifmtu
= ifp
->mtu6
;
337 iobuflen
= ospf6_iobuf_size(ifp
->mtu6
);
338 if (oi
->ifmtu
> iobuflen
) {
339 if (IS_OSPF6_DEBUG_INTERFACE
)
341 "Interface %s: IfMtu is adjusted to I/O buffer size: %d.",
342 ifp
->name
, iobuflen
);
343 oi
->ifmtu
= iobuflen
;
346 /* interface start */
347 ospf6_interface_state_update(oi
->interface
);
350 void ospf6_interface_state_update(struct interface
*ifp
)
352 struct ospf6_interface
*oi
;
353 unsigned int iobuflen
;
355 oi
= (struct ospf6_interface
*)ifp
->info
;
358 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
))
361 /* Adjust the mtu values if the kernel told us something new */
362 if (ifp
->mtu6
!= oi
->ifmtu
) {
363 /* If nothing configured, accept it and check for buffer size */
365 oi
->ifmtu
= ifp
->mtu6
;
366 iobuflen
= ospf6_iobuf_size(ifp
->mtu6
);
367 if (oi
->ifmtu
> iobuflen
) {
368 if (IS_OSPF6_DEBUG_INTERFACE
)
370 "Interface %s: IfMtu is adjusted to I/O buffer size: %d.",
371 ifp
->name
, iobuflen
);
372 oi
->ifmtu
= iobuflen
;
374 } else if (oi
->c_ifmtu
> ifp
->mtu6
) {
375 oi
->ifmtu
= ifp
->mtu6
;
377 "Configured mtu %u on %s overridden by kernel %u",
378 oi
->c_ifmtu
, ifp
->name
, ifp
->mtu6
);
380 oi
->ifmtu
= oi
->c_ifmtu
;
383 if (if_is_operative(ifp
)
384 && (ospf6_interface_get_linklocal_address(oi
->interface
)
385 || if_is_loopback(oi
->interface
)))
386 thread_execute(master
, interface_up
, oi
, 0);
388 thread_execute(master
, interface_down
, oi
, 0);
393 void ospf6_interface_connected_route_update(struct interface
*ifp
)
395 struct ospf6_interface
*oi
;
396 struct ospf6_route
*route
;
398 struct listnode
*node
, *nnode
;
399 struct in6_addr nh_addr
;
401 oi
= (struct ospf6_interface
*)ifp
->info
;
405 /* reset linklocal pointer */
406 oi
->linklocal_addr
= ospf6_interface_get_linklocal_address(ifp
);
408 /* if area is null, do not make connected-route list */
409 if (oi
->area
== NULL
)
412 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
))
415 /* update "route to advertise" interface route table */
416 ospf6_route_remove_all(oi
->route_connected
);
418 for (ALL_LIST_ELEMENTS(oi
->interface
->connected
, node
, nnode
, c
)) {
419 if (c
->address
->family
!= AF_INET6
)
422 CONTINUE_IF_ADDRESS_LINKLOCAL(IS_OSPF6_DEBUG_INTERFACE
,
424 CONTINUE_IF_ADDRESS_UNSPECIFIED(IS_OSPF6_DEBUG_INTERFACE
,
426 CONTINUE_IF_ADDRESS_LOOPBACK(IS_OSPF6_DEBUG_INTERFACE
,
428 CONTINUE_IF_ADDRESS_V4COMPAT(IS_OSPF6_DEBUG_INTERFACE
,
430 CONTINUE_IF_ADDRESS_V4MAPPED(IS_OSPF6_DEBUG_INTERFACE
,
434 if (oi
->plist_name
) {
435 struct prefix_list
*plist
;
436 enum prefix_list_type ret
;
437 char buf
[PREFIX2STR_BUFFER
];
439 prefix2str(c
->address
, buf
, sizeof(buf
));
440 plist
= prefix_list_lookup(AFI_IP6
, oi
->plist_name
);
441 ret
= prefix_list_apply(plist
, (void *)c
->address
);
442 if (ret
== PREFIX_DENY
) {
443 if (IS_OSPF6_DEBUG_INTERFACE
)
445 "%s on %s filtered by prefix-list %s ",
446 buf
, oi
->interface
->name
,
452 route
= ospf6_route_create();
453 memcpy(&route
->prefix
, c
->address
, sizeof(struct prefix
));
454 apply_mask(&route
->prefix
);
455 route
->type
= OSPF6_DEST_TYPE_NETWORK
;
456 route
->path
.area_id
= oi
->area
->area_id
;
457 route
->path
.type
= OSPF6_PATH_TYPE_INTRA
;
458 route
->path
.cost
= oi
->cost
;
459 inet_pton(AF_INET6
, "::1", &nh_addr
);
460 ospf6_route_add_nexthop(route
, oi
->interface
->ifindex
,
462 ospf6_route_add(route
, oi
->route_connected
);
465 /* create new Link-LSA */
466 OSPF6_LINK_LSA_SCHEDULE(oi
);
467 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi
);
468 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi
->area
);
471 static void ospf6_interface_state_change(uint8_t next_state
,
472 struct ospf6_interface
*oi
)
476 prev_state
= oi
->state
;
477 oi
->state
= next_state
;
479 if (prev_state
== next_state
)
483 if (IS_OSPF6_DEBUG_INTERFACE
) {
484 zlog_debug("Interface state change %s: %s -> %s",
486 ospf6_interface_state_str
[prev_state
],
487 ospf6_interface_state_str
[next_state
]);
491 if ((prev_state
== OSPF6_INTERFACE_DR
492 || prev_state
== OSPF6_INTERFACE_BDR
)
493 && (next_state
!= OSPF6_INTERFACE_DR
494 && next_state
!= OSPF6_INTERFACE_BDR
))
495 ospf6_sso(oi
->interface
->ifindex
, &alldrouters6
,
498 if ((prev_state
!= OSPF6_INTERFACE_DR
499 && prev_state
!= OSPF6_INTERFACE_BDR
)
500 && (next_state
== OSPF6_INTERFACE_DR
501 || next_state
== OSPF6_INTERFACE_BDR
))
502 ospf6_sso(oi
->interface
->ifindex
, &alldrouters6
,
505 OSPF6_ROUTER_LSA_SCHEDULE(oi
->area
);
506 if (next_state
== OSPF6_INTERFACE_DOWN
) {
507 OSPF6_NETWORK_LSA_EXECUTE(oi
);
508 OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(oi
);
509 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi
->area
);
510 OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(oi
);
511 } else if (prev_state
== OSPF6_INTERFACE_DR
512 || next_state
== OSPF6_INTERFACE_DR
) {
513 OSPF6_NETWORK_LSA_SCHEDULE(oi
);
514 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi
);
515 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi
->area
);
518 hook_call(ospf6_interface_change
, oi
, next_state
, prev_state
);
522 /* DR Election, RFC2328 section 9.4 */
524 #define IS_ELIGIBLE(n) \
525 ((n)->state >= OSPF6_NEIGHBOR_TWOWAY && (n)->priority != 0)
527 static struct ospf6_neighbor
*better_bdrouter(struct ospf6_neighbor
*a
,
528 struct ospf6_neighbor
*b
)
530 if ((a
== NULL
|| !IS_ELIGIBLE(a
) || a
->drouter
== a
->router_id
)
531 && (b
== NULL
|| !IS_ELIGIBLE(b
) || b
->drouter
== b
->router_id
))
533 else if (a
== NULL
|| !IS_ELIGIBLE(a
) || a
->drouter
== a
->router_id
)
535 else if (b
== NULL
|| !IS_ELIGIBLE(b
) || b
->drouter
== b
->router_id
)
538 if (a
->bdrouter
== a
->router_id
&& b
->bdrouter
!= b
->router_id
)
540 if (a
->bdrouter
!= a
->router_id
&& b
->bdrouter
== b
->router_id
)
543 if (a
->priority
> b
->priority
)
545 if (a
->priority
< b
->priority
)
548 if (ntohl(a
->router_id
) > ntohl(b
->router_id
))
550 if (ntohl(a
->router_id
) < ntohl(b
->router_id
))
553 zlog_warn("Router-ID duplicate ?");
557 static struct ospf6_neighbor
*better_drouter(struct ospf6_neighbor
*a
,
558 struct ospf6_neighbor
*b
)
560 if ((a
== NULL
|| !IS_ELIGIBLE(a
) || a
->drouter
!= a
->router_id
)
561 && (b
== NULL
|| !IS_ELIGIBLE(b
) || b
->drouter
!= b
->router_id
))
563 else if (a
== NULL
|| !IS_ELIGIBLE(a
) || a
->drouter
!= a
->router_id
)
565 else if (b
== NULL
|| !IS_ELIGIBLE(b
) || b
->drouter
!= b
->router_id
)
568 if (a
->drouter
== a
->router_id
&& b
->drouter
!= b
->router_id
)
570 if (a
->drouter
!= a
->router_id
&& b
->drouter
== b
->router_id
)
573 if (a
->priority
> b
->priority
)
575 if (a
->priority
< b
->priority
)
578 if (ntohl(a
->router_id
) > ntohl(b
->router_id
))
580 if (ntohl(a
->router_id
) < ntohl(b
->router_id
))
583 zlog_warn("Router-ID duplicate ?");
587 static uint8_t dr_election(struct ospf6_interface
*oi
)
589 struct listnode
*node
, *nnode
;
590 struct ospf6_neighbor
*on
, *drouter
, *bdrouter
, myself
;
591 struct ospf6_neighbor
*best_drouter
, *best_bdrouter
;
592 uint8_t next_state
= 0;
594 drouter
= bdrouter
= NULL
;
595 best_drouter
= best_bdrouter
= NULL
;
597 /* pseudo neighbor myself, including noting current DR/BDR (1) */
598 memset(&myself
, 0, sizeof(myself
));
599 inet_ntop(AF_INET
, &oi
->area
->ospf6
->router_id
, myself
.name
,
600 sizeof(myself
.name
));
601 myself
.state
= OSPF6_NEIGHBOR_TWOWAY
;
602 myself
.drouter
= oi
->drouter
;
603 myself
.bdrouter
= oi
->bdrouter
;
604 myself
.priority
= oi
->priority
;
605 myself
.router_id
= oi
->area
->ospf6
->router_id
;
607 /* Electing BDR (2) */
608 for (ALL_LIST_ELEMENTS(oi
->neighbor_list
, node
, nnode
, on
))
609 bdrouter
= better_bdrouter(bdrouter
, on
);
611 best_bdrouter
= bdrouter
;
612 bdrouter
= better_bdrouter(best_bdrouter
, &myself
);
614 /* Electing DR (3) */
615 for (ALL_LIST_ELEMENTS(oi
->neighbor_list
, node
, nnode
, on
))
616 drouter
= better_drouter(drouter
, on
);
618 best_drouter
= drouter
;
619 drouter
= better_drouter(best_drouter
, &myself
);
623 /* the router itself is newly/no longer DR/BDR (4) */
624 if ((drouter
== &myself
&& myself
.drouter
!= myself
.router_id
)
625 || (drouter
!= &myself
&& myself
.drouter
== myself
.router_id
)
626 || (bdrouter
== &myself
&& myself
.bdrouter
!= myself
.router_id
)
627 || (bdrouter
!= &myself
&& myself
.bdrouter
== myself
.router_id
)) {
628 myself
.drouter
= (drouter
? drouter
->router_id
: htonl(0));
629 myself
.bdrouter
= (bdrouter
? bdrouter
->router_id
: htonl(0));
631 /* compatible to Electing BDR (2) */
632 bdrouter
= better_bdrouter(best_bdrouter
, &myself
);
634 /* compatible to Electing DR (3) */
635 drouter
= better_drouter(best_drouter
, &myself
);
640 /* Set interface state accordingly (5) */
641 if (drouter
&& drouter
== &myself
)
642 next_state
= OSPF6_INTERFACE_DR
;
643 else if (bdrouter
&& bdrouter
== &myself
)
644 next_state
= OSPF6_INTERFACE_BDR
;
646 next_state
= OSPF6_INTERFACE_DROTHER
;
648 /* If NBMA, schedule Start for each neighbor having priority of 0 (6) */
651 /* If DR or BDR change, invoke AdjOK? for each neighbor (7) */
652 /* RFC 2328 section 12.4. Originating LSAs (3) will be handled
653 accordingly after AdjOK */
654 if (oi
->drouter
!= (drouter
? drouter
->router_id
: htonl(0))
655 || oi
->bdrouter
!= (bdrouter
? bdrouter
->router_id
: htonl(0))) {
656 if (IS_OSPF6_DEBUG_INTERFACE
)
657 zlog_debug("DR Election on %s: DR: %s BDR: %s",
659 (drouter
? drouter
->name
: "0.0.0.0"),
660 (bdrouter
? bdrouter
->name
: "0.0.0.0"));
662 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, node
, on
)) {
663 if (on
->state
< OSPF6_NEIGHBOR_TWOWAY
)
665 /* Schedule AdjOK. */
666 thread_add_event(master
, adj_ok
, on
, 0, NULL
);
670 oi
->drouter
= (drouter
? drouter
->router_id
: htonl(0));
671 oi
->bdrouter
= (bdrouter
? bdrouter
->router_id
: htonl(0));
676 /* Interface State Machine */
677 int interface_up(struct thread
*thread
)
679 struct ospf6_interface
*oi
;
681 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
682 assert(oi
&& oi
->interface
);
685 oi
->type
= ospf6_default_iftype(oi
->interface
);
688 * Remove old pointer. If this thread wasn't a timer this
689 * operation won't make a difference, because it is already NULL.
691 oi
->thread_sso
= NULL
;
693 if (IS_OSPF6_DEBUG_INTERFACE
)
694 zlog_debug("Interface Event %s: [InterfaceUp]",
695 oi
->interface
->name
);
697 /* check physical interface is up */
698 if (!if_is_operative(oi
->interface
)) {
699 if (IS_OSPF6_DEBUG_INTERFACE
)
701 "Interface %s is down, can't execute [InterfaceUp]",
702 oi
->interface
->name
);
706 /* check interface has a link-local address */
707 if (!(ospf6_interface_get_linklocal_address(oi
->interface
)
708 || if_is_loopback(oi
->interface
))) {
709 if (IS_OSPF6_DEBUG_INTERFACE
)
711 "Interface %s has no link local address, can't execute [InterfaceUp]",
712 oi
->interface
->name
);
717 ospf6_interface_recalculate_cost(oi
);
719 /* if already enabled, do nothing */
720 if (oi
->state
> OSPF6_INTERFACE_DOWN
) {
721 if (IS_OSPF6_DEBUG_INTERFACE
)
722 zlog_debug("Interface %s already enabled",
723 oi
->interface
->name
);
727 /* If no area assigned, return */
728 if (oi
->area
== NULL
) {
730 "%s: Not scheduleing Hello for %s as there is no area assigned yet",
731 __func__
, oi
->interface
->name
);
737 * XXX: Schedule IPv6 group join for later, otherwise we might
738 * lose the multicast group registration caused by IPv6 group
741 if (oi
->sso_try_cnt
== 0) {
743 zlog_info("Scheduling %s for sso", oi
->interface
->name
);
744 thread_add_timer(master
, interface_up
, oi
,
745 OSPF6_INTERFACE_SSO_RETRY_INT
,
749 #endif /* __FreeBSD__ */
751 /* Join AllSPFRouters */
752 if (ospf6_sso(oi
->interface
->ifindex
, &allspfrouters6
, IPV6_JOIN_GROUP
)
754 if (oi
->sso_try_cnt
++ < OSPF6_INTERFACE_SSO_RETRY_MAX
) {
756 "Scheduling %s for sso retry, trial count: %d",
757 oi
->interface
->name
, oi
->sso_try_cnt
);
758 thread_add_timer(master
, interface_up
, oi
,
759 OSPF6_INTERFACE_SSO_RETRY_INT
,
764 oi
->sso_try_cnt
= 0; /* Reset on success */
766 /* Update interface route */
767 ospf6_interface_connected_route_update(oi
->interface
);
770 if (!CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_PASSIVE
)
771 && !if_is_loopback(oi
->interface
)) {
772 oi
->thread_send_hello
= NULL
;
773 thread_add_event(master
, ospf6_hello_send
, oi
, 0,
774 &oi
->thread_send_hello
);
777 /* decide next interface state */
778 if (oi
->type
== OSPF_IFTYPE_POINTOPOINT
) {
779 ospf6_interface_state_change(OSPF6_INTERFACE_POINTTOPOINT
, oi
);
780 } else if (oi
->priority
== 0)
781 ospf6_interface_state_change(OSPF6_INTERFACE_DROTHER
, oi
);
783 ospf6_interface_state_change(OSPF6_INTERFACE_WAITING
, oi
);
784 thread_add_timer(master
, wait_timer
, oi
, oi
->dead_interval
,
791 int wait_timer(struct thread
*thread
)
793 struct ospf6_interface
*oi
;
795 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
796 assert(oi
&& oi
->interface
);
798 if (IS_OSPF6_DEBUG_INTERFACE
)
799 zlog_debug("Interface Event %s: [WaitTimer]",
800 oi
->interface
->name
);
802 if (oi
->state
== OSPF6_INTERFACE_WAITING
)
803 ospf6_interface_state_change(dr_election(oi
), oi
);
808 int backup_seen(struct thread
*thread
)
810 struct ospf6_interface
*oi
;
812 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
813 assert(oi
&& oi
->interface
);
815 if (IS_OSPF6_DEBUG_INTERFACE
)
816 zlog_debug("Interface Event %s: [BackupSeen]",
817 oi
->interface
->name
);
819 if (oi
->state
== OSPF6_INTERFACE_WAITING
)
820 ospf6_interface_state_change(dr_election(oi
), oi
);
825 int neighbor_change(struct thread
*thread
)
827 struct ospf6_interface
*oi
;
829 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
830 assert(oi
&& oi
->interface
);
832 if (IS_OSPF6_DEBUG_INTERFACE
)
833 zlog_debug("Interface Event %s: [NeighborChange]",
834 oi
->interface
->name
);
836 if (oi
->state
== OSPF6_INTERFACE_DROTHER
837 || oi
->state
== OSPF6_INTERFACE_BDR
838 || oi
->state
== OSPF6_INTERFACE_DR
)
839 ospf6_interface_state_change(dr_election(oi
), oi
);
844 int interface_down(struct thread
*thread
)
846 struct ospf6_interface
*oi
;
847 struct listnode
*node
, *nnode
;
848 struct ospf6_neighbor
*on
;
850 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
851 assert(oi
&& oi
->interface
);
853 if (IS_OSPF6_DEBUG_INTERFACE
)
854 zlog_debug("Interface Event %s: [InterfaceDown]",
855 oi
->interface
->name
);
858 THREAD_OFF(oi
->thread_send_hello
);
860 /* Stop trying to set socket options. */
861 THREAD_OFF(oi
->thread_sso
);
863 /* Leave AllSPFRouters */
864 if (oi
->state
> OSPF6_INTERFACE_DOWN
)
865 ospf6_sso(oi
->interface
->ifindex
, &allspfrouters6
,
868 ospf6_interface_state_change(OSPF6_INTERFACE_DOWN
, oi
);
870 for (ALL_LIST_ELEMENTS(oi
->neighbor_list
, node
, nnode
, on
))
871 ospf6_neighbor_delete(on
);
873 list_delete_all_node(oi
->neighbor_list
);
875 /* When interface state is reset, also reset information about
876 * DR election, as it is no longer valid. */
877 oi
->drouter
= oi
->prev_drouter
= htonl(0);
878 oi
->bdrouter
= oi
->prev_bdrouter
= htonl(0);
883 static const char *ospf6_iftype_str(uint8_t iftype
)
886 case OSPF_IFTYPE_LOOPBACK
:
888 case OSPF_IFTYPE_BROADCAST
:
890 case OSPF_IFTYPE_POINTOPOINT
:
891 return "POINTOPOINT";
896 /* show specified interface structure */
897 static int ospf6_interface_show(struct vty
*vty
, struct interface
*ifp
)
899 struct ospf6_interface
*oi
;
903 char strbuf
[PREFIX2STR_BUFFER
], drouter
[32], bdrouter
[32];
904 uint8_t default_iftype
;
905 struct timeval res
, now
;
907 struct ospf6_lsa
*lsa
;
909 default_iftype
= ospf6_default_iftype(ifp
);
911 vty_out(vty
, "%s is %s, type %s\n", ifp
->name
,
912 (if_is_operative(ifp
) ? "up" : "down"),
913 ospf6_iftype_str(default_iftype
));
914 vty_out(vty
, " Interface ID: %d\n", ifp
->ifindex
);
916 if (ifp
->info
== NULL
) {
917 vty_out(vty
, " OSPF not enabled on this interface\n");
920 oi
= (struct ospf6_interface
*)ifp
->info
;
922 if (if_is_operative(ifp
) && oi
->type
!= default_iftype
)
923 vty_out(vty
, " Operating as type %s\n",
924 ospf6_iftype_str(oi
->type
));
926 vty_out(vty
, " Internet Address:\n");
928 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, i
, c
)) {
930 prefix2str(p
, strbuf
, sizeof(strbuf
));
933 vty_out(vty
, " inet : %s\n", strbuf
);
936 vty_out(vty
, " inet6: %s\n", strbuf
);
939 vty_out(vty
, " ??? : %s\n", strbuf
);
946 " Instance ID %d, Interface MTU %d (autodetect: %d)\n",
947 oi
->instance_id
, oi
->ifmtu
, ifp
->mtu6
);
948 vty_out(vty
, " MTU mismatch detection: %s\n",
949 oi
->mtu_ignore
? "disabled" : "enabled");
950 inet_ntop(AF_INET
, &oi
->area
->area_id
, strbuf
, sizeof(strbuf
));
951 vty_out(vty
, " Area ID %s, Cost %u\n", strbuf
, oi
->cost
);
953 vty_out(vty
, " Not Attached to Area\n");
955 vty_out(vty
, " State %s, Transmit Delay %d sec, Priority %d\n",
956 ospf6_interface_state_str
[oi
->state
], oi
->transdelay
,
958 vty_out(vty
, " Timer intervals configured:\n");
959 vty_out(vty
, " Hello %d, Dead %d, Retransmit %d\n",
960 oi
->hello_interval
, oi
->dead_interval
, oi
->rxmt_interval
);
962 inet_ntop(AF_INET
, &oi
->drouter
, drouter
, sizeof(drouter
));
963 inet_ntop(AF_INET
, &oi
->bdrouter
, bdrouter
, sizeof(bdrouter
));
964 vty_out(vty
, " DR: %s BDR: %s\n", drouter
, bdrouter
);
966 vty_out(vty
, " Number of I/F scoped LSAs is %u\n", oi
->lsdb
->count
);
971 if (oi
->thread_send_lsupdate
)
972 timersub(&oi
->thread_send_lsupdate
->u
.sands
, &now
, &res
);
973 timerstring(&res
, duration
, sizeof(duration
));
975 " %d Pending LSAs for LSUpdate in Time %s [thread %s]\n",
976 oi
->lsupdate_list
->count
, duration
,
977 (oi
->thread_send_lsupdate
? "on" : "off"));
978 for (ALL_LSDB(oi
->lsupdate_list
, lsa
))
979 vty_out(vty
, " %s\n", lsa
->name
);
982 if (oi
->thread_send_lsack
)
983 timersub(&oi
->thread_send_lsack
->u
.sands
, &now
, &res
);
984 timerstring(&res
, duration
, sizeof(duration
));
985 vty_out(vty
, " %d Pending LSAs for LSAck in Time %s [thread %s]\n",
986 oi
->lsack_list
->count
, duration
,
987 (oi
->thread_send_lsack
? "on" : "off"));
988 for (ALL_LSDB(oi
->lsack_list
, lsa
))
989 vty_out(vty
, " %s\n", lsa
->name
);
990 ospf6_bfd_show_info(vty
, oi
->bfd_info
, 1);
995 DEFUN (show_ipv6_ospf6_interface
,
996 show_ipv6_ospf6_interface_ifname_cmd
,
997 "show ipv6 ospf6 interface [IFNAME]",
1004 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
1006 struct interface
*ifp
;
1009 ifp
= if_lookup_by_name(argv
[idx_ifname
]->arg
, VRF_DEFAULT
);
1011 vty_out(vty
, "No such Interface: %s\n",
1012 argv
[idx_ifname
]->arg
);
1015 ospf6_interface_show(vty
, ifp
);
1017 FOR_ALL_INTERFACES (vrf
, ifp
)
1018 ospf6_interface_show(vty
, ifp
);
1024 static int ospf6_interface_show_traffic(struct vty
*vty
, uint32_t vrf_id
,
1025 struct interface
*intf_ifp
,
1028 struct interface
*ifp
;
1029 struct vrf
*vrf
= NULL
;
1030 struct ospf6_interface
*oi
= NULL
;
1032 vrf
= vrf_lookup_by_id(vrf_id
);
1034 if (!display_once
) {
1036 vty_out(vty
, "%-12s%-17s%-17s%-17s%-17s%-17s\n", "Interface",
1037 " HELLO", " DB-Desc", " LS-Req", " LS-Update",
1039 vty_out(vty
, "%-10s%-18s%-18s%-17s%-17s%-17s\n", "",
1040 " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx",
1043 "--------------------------------------------------------------------------------------------\n");
1046 if (intf_ifp
== NULL
) {
1047 FOR_ALL_INTERFACES (vrf
, ifp
) {
1049 oi
= (struct ospf6_interface
*)ifp
->info
;
1054 "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u\n",
1055 oi
->interface
->name
, oi
->hello_in
,
1056 oi
->hello_out
, oi
->db_desc_in
, oi
->db_desc_out
,
1057 oi
->ls_req_in
, oi
->ls_req_out
, oi
->ls_upd_in
,
1058 oi
->ls_upd_out
, oi
->ls_ack_in
, oi
->ls_ack_out
);
1061 oi
= intf_ifp
->info
;
1066 "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u\n",
1067 oi
->interface
->name
, oi
->hello_in
, oi
->hello_out
,
1068 oi
->db_desc_in
, oi
->db_desc_out
, oi
->ls_req_in
,
1069 oi
->ls_req_out
, oi
->ls_upd_in
, oi
->ls_upd_out
,
1070 oi
->ls_ack_in
, oi
->ls_ack_out
);
1076 /* show interface */
1077 DEFUN (show_ipv6_ospf6_interface_traffic
,
1078 show_ipv6_ospf6_interface_traffic_cmd
,
1079 "show ipv6 ospf6 interface traffic [IFNAME]",
1084 "Protocol Packet counters\n"
1088 int display_once
= 0;
1089 char *intf_name
= NULL
;
1090 struct interface
*ifp
= NULL
;
1092 if (argv_find(argv
, argc
, "IFNAME", &idx_ifname
)) {
1093 intf_name
= argv
[idx_ifname
]->arg
;
1094 ifp
= if_lookup_by_name(intf_name
, VRF_DEFAULT
);
1096 vty_out(vty
, "No such Interface: %s\n", intf_name
);
1099 if (ifp
->info
== NULL
) {
1101 " OSPF not enabled on this interface %s\n",
1107 ospf6_interface_show_traffic(vty
, VRF_DEFAULT
, ifp
, display_once
);
1114 DEFUN (show_ipv6_ospf6_interface_ifname_prefix
,
1115 show_ipv6_ospf6_interface_ifname_prefix_cmd
,
1116 "show ipv6 ospf6 interface IFNAME prefix\
1119 |<X:X::X:X|X:X::X:X/M> [<match|detail>]\
1126 "Display connected prefixes to advertise\n"
1127 "Display details of the prefixes\n"
1128 OSPF6_ROUTE_ADDRESS_STR
1129 OSPF6_ROUTE_PREFIX_STR
1130 OSPF6_ROUTE_MATCH_STR
1131 "Display details of the prefixes\n")
1135 struct interface
*ifp
;
1136 struct ospf6_interface
*oi
;
1138 ifp
= if_lookup_by_name(argv
[idx_ifname
]->arg
, VRF_DEFAULT
);
1140 vty_out(vty
, "No such Interface: %s\n", argv
[idx_ifname
]->arg
);
1146 vty_out(vty
, "OSPFv3 is not enabled on %s\n",
1147 argv
[idx_ifname
]->arg
);
1151 ospf6_route_table_show(vty
, idx_prefix
, argc
, argv
,
1152 oi
->route_connected
);
1157 DEFUN (show_ipv6_ospf6_interface_prefix
,
1158 show_ipv6_ospf6_interface_prefix_cmd
,
1159 "show ipv6 ospf6 interface prefix\
1162 |<X:X::X:X|X:X::X:X/M> [<match|detail>]\
1168 "Display connected prefixes to advertise\n"
1169 "Display details of the prefixes\n"
1170 OSPF6_ROUTE_ADDRESS_STR
1171 OSPF6_ROUTE_PREFIX_STR
1172 OSPF6_ROUTE_MATCH_STR
1173 "Display details of the prefixes\n")
1175 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
1177 struct ospf6_interface
*oi
;
1178 struct interface
*ifp
;
1180 FOR_ALL_INTERFACES (vrf
, ifp
) {
1181 oi
= (struct ospf6_interface
*)ifp
->info
;
1185 ospf6_route_table_show(vty
, idx_prefix
, argc
, argv
,
1186 oi
->route_connected
);
1192 /* interface variable set command */
1193 DEFUN (ipv6_ospf6_ifmtu
,
1194 ipv6_ospf6_ifmtu_cmd
,
1195 "ipv6 ospf6 ifmtu (1-65535)",
1199 "OSPFv3 Interface MTU\n"
1202 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1204 struct ospf6_interface
*oi
;
1205 unsigned int ifmtu
, iobuflen
;
1206 struct listnode
*node
, *nnode
;
1207 struct ospf6_neighbor
*on
;
1211 oi
= (struct ospf6_interface
*)ifp
->info
;
1213 oi
= ospf6_interface_create(ifp
);
1216 ifmtu
= strtol(argv
[idx_number
]->arg
, NULL
, 10);
1218 if (oi
->c_ifmtu
== ifmtu
)
1221 if (ifp
->mtu6
!= 0 && ifp
->mtu6
< ifmtu
) {
1223 "%s's ospf6 ifmtu cannot go beyond physical mtu (%d)\n",
1224 ifp
->name
, ifp
->mtu6
);
1225 return CMD_WARNING_CONFIG_FAILED
;
1228 if (oi
->ifmtu
< ifmtu
) {
1229 iobuflen
= ospf6_iobuf_size(ifmtu
);
1230 if (iobuflen
< ifmtu
) {
1232 "%s's ifmtu is adjusted to I/O buffer size (%d).\n",
1233 ifp
->name
, iobuflen
);
1234 oi
->ifmtu
= oi
->c_ifmtu
= iobuflen
;
1236 oi
->ifmtu
= oi
->c_ifmtu
= ifmtu
;
1238 oi
->ifmtu
= oi
->c_ifmtu
= ifmtu
;
1240 /* re-establish adjacencies */
1241 for (ALL_LIST_ELEMENTS(oi
->neighbor_list
, node
, nnode
, on
)) {
1242 THREAD_OFF(on
->inactivity_timer
);
1243 thread_add_event(master
, inactivity_timer
, on
, 0, NULL
);
1249 DEFUN (no_ipv6_ospf6_ifmtu
,
1250 no_ipv6_ospf6_ifmtu_cmd
,
1251 "no ipv6 ospf6 ifmtu [(1-65535)]",
1256 "OSPFv3 Interface MTU\n"
1259 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1260 struct ospf6_interface
*oi
;
1261 unsigned int iobuflen
;
1262 struct listnode
*node
, *nnode
;
1263 struct ospf6_neighbor
*on
;
1267 oi
= (struct ospf6_interface
*)ifp
->info
;
1269 oi
= ospf6_interface_create(ifp
);
1272 if (oi
->ifmtu
< ifp
->mtu
) {
1273 iobuflen
= ospf6_iobuf_size(ifp
->mtu
);
1274 if (iobuflen
< ifp
->mtu
) {
1276 "%s's ifmtu is adjusted to I/O buffer size (%d).\n",
1277 ifp
->name
, iobuflen
);
1278 oi
->ifmtu
= iobuflen
;
1280 oi
->ifmtu
= ifp
->mtu
;
1282 oi
->ifmtu
= ifp
->mtu
;
1286 /* re-establish adjacencies */
1287 for (ALL_LIST_ELEMENTS(oi
->neighbor_list
, node
, nnode
, on
)) {
1288 THREAD_OFF(on
->inactivity_timer
);
1289 thread_add_event(master
, inactivity_timer
, on
, 0, NULL
);
1295 DEFUN (ipv6_ospf6_cost
,
1296 ipv6_ospf6_cost_cmd
,
1297 "ipv6 ospf6 cost (1-65535)",
1301 "Outgoing metric of this interface\n")
1303 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1305 struct ospf6_interface
*oi
;
1306 unsigned long int lcost
;
1310 oi
= (struct ospf6_interface
*)ifp
->info
;
1312 oi
= ospf6_interface_create(ifp
);
1315 lcost
= strtol(argv
[idx_number
]->arg
, NULL
, 10);
1317 if (lcost
> UINT32_MAX
) {
1318 vty_out(vty
, "Cost %ld is out of range\n", lcost
);
1319 return CMD_WARNING_CONFIG_FAILED
;
1322 if (oi
->cost
== lcost
)
1326 SET_FLAG(oi
->flag
, OSPF6_INTERFACE_NOAUTOCOST
);
1328 ospf6_interface_force_recalculate_cost(oi
);
1333 DEFUN (no_ipv6_ospf6_cost
,
1334 no_ipv6_ospf6_cost_cmd
,
1335 "no ipv6 ospf6 cost [(1-65535)]",
1339 "Calculate interface cost from bandwidth\n"
1340 "Outgoing metric of this interface\n")
1342 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1343 struct ospf6_interface
*oi
;
1346 oi
= (struct ospf6_interface
*)ifp
->info
;
1348 oi
= ospf6_interface_create(ifp
);
1351 UNSET_FLAG(oi
->flag
, OSPF6_INTERFACE_NOAUTOCOST
);
1353 ospf6_interface_recalculate_cost(oi
);
1358 DEFUN (auto_cost_reference_bandwidth
,
1359 auto_cost_reference_bandwidth_cmd
,
1360 "auto-cost reference-bandwidth (1-4294967)",
1361 "Calculate OSPF interface cost according to bandwidth\n"
1362 "Use reference bandwidth method to assign OSPF cost\n"
1363 "The reference bandwidth in terms of Mbits per second\n")
1365 VTY_DECLVAR_CONTEXT(ospf6
, o
);
1367 struct ospf6_area
*oa
;
1368 struct ospf6_interface
*oi
;
1369 struct listnode
*i
, *j
;
1372 refbw
= strtol(argv
[idx_number
]->arg
, NULL
, 10);
1373 if (refbw
< 1 || refbw
> 4294967) {
1374 vty_out(vty
, "reference-bandwidth value is invalid\n");
1375 return CMD_WARNING_CONFIG_FAILED
;
1378 /* If reference bandwidth is changed. */
1379 if ((refbw
) == o
->ref_bandwidth
)
1382 o
->ref_bandwidth
= refbw
;
1383 for (ALL_LIST_ELEMENTS_RO(o
->area_list
, i
, oa
))
1384 for (ALL_LIST_ELEMENTS_RO(oa
->if_list
, j
, oi
))
1385 ospf6_interface_recalculate_cost(oi
);
1390 DEFUN (no_auto_cost_reference_bandwidth
,
1391 no_auto_cost_reference_bandwidth_cmd
,
1392 "no auto-cost reference-bandwidth [(1-4294967)]",
1394 "Calculate OSPF interface cost according to bandwidth\n"
1395 "Use reference bandwidth method to assign OSPF cost\n"
1396 "The reference bandwidth in terms of Mbits per second\n")
1398 VTY_DECLVAR_CONTEXT(ospf6
, o
);
1399 struct ospf6_area
*oa
;
1400 struct ospf6_interface
*oi
;
1401 struct listnode
*i
, *j
;
1403 if (o
->ref_bandwidth
== OSPF6_REFERENCE_BANDWIDTH
)
1406 o
->ref_bandwidth
= OSPF6_REFERENCE_BANDWIDTH
;
1407 for (ALL_LIST_ELEMENTS_RO(o
->area_list
, i
, oa
))
1408 for (ALL_LIST_ELEMENTS_RO(oa
->if_list
, j
, oi
))
1409 ospf6_interface_recalculate_cost(oi
);
1415 DEFUN (ipv6_ospf6_hellointerval
,
1416 ipv6_ospf6_hellointerval_cmd
,
1417 "ipv6 ospf6 hello-interval (1-65535)",
1420 "Time between HELLO packets\n"
1423 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1425 struct ospf6_interface
*oi
;
1428 oi
= (struct ospf6_interface
*)ifp
->info
;
1430 oi
= ospf6_interface_create(ifp
);
1433 oi
->hello_interval
= strmatch(argv
[0]->text
, "no")
1434 ? OSPF_HELLO_INTERVAL_DEFAULT
1435 : strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1439 ALIAS (ipv6_ospf6_hellointerval
,
1440 no_ipv6_ospf6_hellointerval_cmd
,
1441 "no ipv6 ospf6 hello-interval [(1-65535)]",
1445 "Time between HELLO packets\n"
1448 /* interface variable set command */
1449 DEFUN (ipv6_ospf6_deadinterval
,
1450 ipv6_ospf6_deadinterval_cmd
,
1451 "ipv6 ospf6 dead-interval (1-65535)",
1454 "Interval time after which a neighbor is declared down\n"
1457 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1459 struct ospf6_interface
*oi
;
1462 oi
= (struct ospf6_interface
*)ifp
->info
;
1464 oi
= ospf6_interface_create(ifp
);
1467 oi
->dead_interval
= strmatch(argv
[0]->arg
, "no")
1468 ? OSPF_ROUTER_DEAD_INTERVAL_DEFAULT
1469 : strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1473 ALIAS (ipv6_ospf6_deadinterval
,
1474 no_ipv6_ospf6_deadinterval_cmd
,
1475 "no ipv6 ospf6 dead-interval [(1-65535)]",
1479 "Interval time after which a neighbor is declared down\n"
1482 /* interface variable set command */
1483 DEFUN (ipv6_ospf6_transmitdelay
,
1484 ipv6_ospf6_transmitdelay_cmd
,
1485 "ipv6 ospf6 transmit-delay (1-3600)",
1488 "Link state transmit delay\n"
1491 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1493 struct ospf6_interface
*oi
;
1496 oi
= (struct ospf6_interface
*)ifp
->info
;
1498 oi
= ospf6_interface_create(ifp
);
1501 oi
->transdelay
= strmatch(argv
[0]->text
, "no")
1502 ? OSPF6_INTERFACE_TRANSDELAY
1503 : strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1507 ALIAS (ipv6_ospf6_transmitdelay
,
1508 no_ipv6_ospf6_transmitdelay_cmd
,
1509 "no ipv6 ospf6 transmit-delay [(1-3600)]",
1513 "Link state transmit delay\n"
1516 /* interface variable set command */
1517 DEFUN (ipv6_ospf6_retransmitinterval
,
1518 ipv6_ospf6_retransmitinterval_cmd
,
1519 "ipv6 ospf6 retransmit-interval (1-65535)",
1522 "Time between retransmitting lost link state advertisements\n"
1525 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1527 struct ospf6_interface
*oi
;
1530 oi
= (struct ospf6_interface
*)ifp
->info
;
1532 oi
= ospf6_interface_create(ifp
);
1535 oi
->rxmt_interval
= strmatch(argv
[0]->text
, "no")
1536 ? OSPF_RETRANSMIT_INTERVAL_DEFAULT
1537 : strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1541 ALIAS (ipv6_ospf6_retransmitinterval
,
1542 no_ipv6_ospf6_retransmitinterval_cmd
,
1543 "no ipv6 ospf6 retransmit-interval [(1-65535)]",
1547 "Time between retransmitting lost link state advertisements\n"
1550 /* interface variable set command */
1551 DEFUN (ipv6_ospf6_priority
,
1552 ipv6_ospf6_priority_cmd
,
1553 "ipv6 ospf6 priority (0-255)",
1559 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1561 struct ospf6_interface
*oi
;
1564 oi
= (struct ospf6_interface
*)ifp
->info
;
1566 oi
= ospf6_interface_create(ifp
);
1569 oi
->priority
= strmatch(argv
[0]->text
, "no")
1570 ? OSPF6_INTERFACE_PRIORITY
1571 : strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1573 if (oi
->area
&& (oi
->state
== OSPF6_INTERFACE_DROTHER
1574 || oi
->state
== OSPF6_INTERFACE_BDR
1575 || oi
->state
== OSPF6_INTERFACE_DR
))
1576 ospf6_interface_state_change(dr_election(oi
), oi
);
1581 ALIAS (ipv6_ospf6_priority
,
1582 no_ipv6_ospf6_priority_cmd
,
1583 "no ipv6 ospf6 priority [(0-255)]",
1590 DEFUN (ipv6_ospf6_instance
,
1591 ipv6_ospf6_instance_cmd
,
1592 "ipv6 ospf6 instance-id (0-255)",
1595 "Instance ID for this interface\n"
1596 "Instance ID value\n")
1598 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1600 struct ospf6_interface
*oi
;
1603 oi
= (struct ospf6_interface
*)ifp
->info
;
1605 oi
= ospf6_interface_create(ifp
);
1608 oi
->instance_id
= strmatch(argv
[0]->text
, "no")
1609 ? OSPF6_INTERFACE_INSTANCE_ID
1610 : strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1614 ALIAS (ipv6_ospf6_instance
,
1615 no_ipv6_ospf6_instance_cmd
,
1616 "no ipv6 ospf6 instance-id [(0-255)]",
1620 "Instance ID for this interface\n"
1621 "Instance ID value\n")
1623 DEFUN (ipv6_ospf6_passive
,
1624 ipv6_ospf6_passive_cmd
,
1625 "ipv6 ospf6 passive",
1628 "Passive interface; no adjacency will be formed on this interface\n"
1631 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1632 struct ospf6_interface
*oi
;
1633 struct listnode
*node
, *nnode
;
1634 struct ospf6_neighbor
*on
;
1638 oi
= (struct ospf6_interface
*)ifp
->info
;
1640 oi
= ospf6_interface_create(ifp
);
1643 SET_FLAG(oi
->flag
, OSPF6_INTERFACE_PASSIVE
);
1644 THREAD_OFF(oi
->thread_send_hello
);
1645 THREAD_OFF(oi
->thread_sso
);
1647 for (ALL_LIST_ELEMENTS(oi
->neighbor_list
, node
, nnode
, on
)) {
1648 THREAD_OFF(on
->inactivity_timer
);
1649 thread_add_event(master
, inactivity_timer
, on
, 0, NULL
);
1655 DEFUN (no_ipv6_ospf6_passive
,
1656 no_ipv6_ospf6_passive_cmd
,
1657 "no ipv6 ospf6 passive",
1661 "passive interface: No Adjacency will be formed on this I/F\n"
1664 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1665 struct ospf6_interface
*oi
;
1668 oi
= (struct ospf6_interface
*)ifp
->info
;
1670 oi
= ospf6_interface_create(ifp
);
1673 UNSET_FLAG(oi
->flag
, OSPF6_INTERFACE_PASSIVE
);
1674 THREAD_OFF(oi
->thread_send_hello
);
1675 THREAD_OFF(oi
->thread_sso
);
1676 thread_add_event(master
, ospf6_hello_send
, oi
, 0,
1677 &oi
->thread_send_hello
);
1682 DEFUN (ipv6_ospf6_mtu_ignore
,
1683 ipv6_ospf6_mtu_ignore_cmd
,
1684 "ipv6 ospf6 mtu-ignore",
1687 "Disable MTU mismatch detection on this interface\n"
1690 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1691 struct ospf6_interface
*oi
;
1694 oi
= (struct ospf6_interface
*)ifp
->info
;
1696 oi
= ospf6_interface_create(ifp
);
1704 DEFUN (no_ipv6_ospf6_mtu_ignore
,
1705 no_ipv6_ospf6_mtu_ignore_cmd
,
1706 "no ipv6 ospf6 mtu-ignore",
1710 "Disable MTU mismatch detection on this interface\n"
1713 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1714 struct ospf6_interface
*oi
;
1717 oi
= (struct ospf6_interface
*)ifp
->info
;
1719 oi
= ospf6_interface_create(ifp
);
1727 DEFUN (ipv6_ospf6_advertise_prefix_list
,
1728 ipv6_ospf6_advertise_prefix_list_cmd
,
1729 "ipv6 ospf6 advertise prefix-list WORD",
1732 "Advertising options\n"
1733 "Filter prefix using prefix-list\n"
1734 "Prefix list name\n"
1737 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1739 struct ospf6_interface
*oi
;
1742 oi
= (struct ospf6_interface
*)ifp
->info
;
1744 oi
= ospf6_interface_create(ifp
);
1748 XFREE(MTYPE_CFG_PLIST_NAME
, oi
->plist_name
);
1749 oi
->plist_name
= XSTRDUP(MTYPE_CFG_PLIST_NAME
, argv
[idx_word
]->arg
);
1751 ospf6_interface_connected_route_update(oi
->interface
);
1754 OSPF6_LINK_LSA_SCHEDULE(oi
);
1755 if (oi
->state
== OSPF6_INTERFACE_DR
) {
1756 OSPF6_NETWORK_LSA_SCHEDULE(oi
);
1757 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi
);
1759 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi
->area
);
1765 DEFUN (no_ipv6_ospf6_advertise_prefix_list
,
1766 no_ipv6_ospf6_advertise_prefix_list_cmd
,
1767 "no ipv6 ospf6 advertise prefix-list [WORD]",
1771 "Advertising options\n"
1772 "Filter prefix using prefix-list\n"
1773 "Prefix list name\n")
1775 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1776 struct ospf6_interface
*oi
;
1779 oi
= (struct ospf6_interface
*)ifp
->info
;
1781 oi
= ospf6_interface_create(ifp
);
1785 XFREE(MTYPE_CFG_PLIST_NAME
, oi
->plist_name
);
1787 ospf6_interface_connected_route_update(oi
->interface
);
1790 OSPF6_LINK_LSA_SCHEDULE(oi
);
1791 if (oi
->state
== OSPF6_INTERFACE_DR
) {
1792 OSPF6_NETWORK_LSA_SCHEDULE(oi
);
1793 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi
);
1795 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi
->area
);
1801 DEFUN (ipv6_ospf6_network
,
1802 ipv6_ospf6_network_cmd
,
1803 "ipv6 ospf6 network <broadcast|point-to-point>",
1807 "Specify OSPF6 broadcast network\n"
1808 "Specify OSPF6 point-to-point network\n"
1811 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1812 int idx_network
= 3;
1813 struct ospf6_interface
*oi
;
1816 oi
= (struct ospf6_interface
*)ifp
->info
;
1818 oi
= ospf6_interface_create(ifp
);
1822 oi
->type_cfg
= true;
1824 if (strncmp(argv
[idx_network
]->arg
, "b", 1) == 0) {
1825 if (oi
->type
== OSPF_IFTYPE_BROADCAST
)
1828 oi
->type
= OSPF_IFTYPE_BROADCAST
;
1829 } else if (strncmp(argv
[idx_network
]->arg
, "point-to-p", 10) == 0) {
1830 if (oi
->type
== OSPF_IFTYPE_POINTOPOINT
) {
1833 oi
->type
= OSPF_IFTYPE_POINTOPOINT
;
1836 /* Reset the interface */
1837 thread_execute(master
, interface_down
, oi
, 0);
1838 thread_execute(master
, interface_up
, oi
, 0);
1843 DEFUN (no_ipv6_ospf6_network
,
1844 no_ipv6_ospf6_network_cmd
,
1845 "no ipv6 ospf6 network [<broadcast|point-to-point>]",
1849 "Set default network type\n"
1850 "Specify OSPF6 broadcast network\n"
1851 "Specify OSPF6 point-to-point network\n")
1853 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1854 struct ospf6_interface
*oi
;
1859 oi
= (struct ospf6_interface
*)ifp
->info
;
1864 oi
->type_cfg
= false;
1866 type
= ospf6_default_iftype(ifp
);
1867 if (oi
->type
== type
) {
1872 /* Reset the interface */
1873 thread_execute(master
, interface_down
, oi
, 0);
1874 thread_execute(master
, interface_up
, oi
, 0);
1879 static int config_write_ospf6_interface(struct vty
*vty
)
1881 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
1882 struct ospf6_interface
*oi
;
1883 struct interface
*ifp
;
1885 FOR_ALL_INTERFACES (vrf
, ifp
) {
1886 oi
= (struct ospf6_interface
*)ifp
->info
;
1890 vty_frame(vty
, "interface %s\n", oi
->interface
->name
);
1893 vty_out(vty
, " description %s\n", ifp
->desc
);
1895 vty_out(vty
, " ipv6 ospf6 ifmtu %d\n", oi
->c_ifmtu
);
1897 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_NOAUTOCOST
))
1898 vty_out(vty
, " ipv6 ospf6 cost %d\n", oi
->cost
);
1900 if (oi
->hello_interval
!= OSPF6_INTERFACE_HELLO_INTERVAL
)
1901 vty_out(vty
, " ipv6 ospf6 hello-interval %d\n",
1902 oi
->hello_interval
);
1904 if (oi
->dead_interval
!= OSPF6_INTERFACE_DEAD_INTERVAL
)
1905 vty_out(vty
, " ipv6 ospf6 dead-interval %d\n",
1908 if (oi
->rxmt_interval
!= OSPF6_INTERFACE_RXMT_INTERVAL
)
1909 vty_out(vty
, " ipv6 ospf6 retransmit-interval %d\n",
1912 if (oi
->priority
!= OSPF6_INTERFACE_PRIORITY
)
1913 vty_out(vty
, " ipv6 ospf6 priority %d\n", oi
->priority
);
1915 if (oi
->transdelay
!= OSPF6_INTERFACE_TRANSDELAY
)
1916 vty_out(vty
, " ipv6 ospf6 transmit-delay %d\n",
1919 if (oi
->instance_id
!= OSPF6_INTERFACE_INSTANCE_ID
)
1920 vty_out(vty
, " ipv6 ospf6 instance-id %d\n",
1924 vty_out(vty
, " ipv6 ospf6 advertise prefix-list %s\n",
1927 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_PASSIVE
))
1928 vty_out(vty
, " ipv6 ospf6 passive\n");
1931 vty_out(vty
, " ipv6 ospf6 mtu-ignore\n");
1933 if (oi
->type_cfg
&& oi
->type
== OSPF_IFTYPE_POINTOPOINT
)
1934 vty_out(vty
, " ipv6 ospf6 network point-to-point\n");
1935 else if (oi
->type_cfg
&& oi
->type
== OSPF_IFTYPE_BROADCAST
)
1936 vty_out(vty
, " ipv6 ospf6 network broadcast\n");
1938 ospf6_bfd_write_config(vty
, oi
);
1940 vty_endframe(vty
, "!\n");
1945 static struct cmd_node interface_node
= {
1946 INTERFACE_NODE
, "%s(config-if)# ", 1 /* VTYSH */
1949 void ospf6_interface_init(void)
1951 /* Install interface node. */
1952 install_node(&interface_node
, config_write_ospf6_interface
);
1955 install_element(VIEW_NODE
, &show_ipv6_ospf6_interface_prefix_cmd
);
1956 install_element(VIEW_NODE
, &show_ipv6_ospf6_interface_ifname_cmd
);
1957 install_element(VIEW_NODE
,
1958 &show_ipv6_ospf6_interface_ifname_prefix_cmd
);
1959 install_element(VIEW_NODE
, &show_ipv6_ospf6_interface_traffic_cmd
);
1961 install_element(INTERFACE_NODE
, &ipv6_ospf6_cost_cmd
);
1962 install_element(INTERFACE_NODE
, &no_ipv6_ospf6_cost_cmd
);
1963 install_element(INTERFACE_NODE
, &ipv6_ospf6_ifmtu_cmd
);
1964 install_element(INTERFACE_NODE
, &no_ipv6_ospf6_ifmtu_cmd
);
1966 install_element(INTERFACE_NODE
, &ipv6_ospf6_deadinterval_cmd
);
1967 install_element(INTERFACE_NODE
, &ipv6_ospf6_hellointerval_cmd
);
1968 install_element(INTERFACE_NODE
, &ipv6_ospf6_priority_cmd
);
1969 install_element(INTERFACE_NODE
, &ipv6_ospf6_retransmitinterval_cmd
);
1970 install_element(INTERFACE_NODE
, &ipv6_ospf6_transmitdelay_cmd
);
1971 install_element(INTERFACE_NODE
, &ipv6_ospf6_instance_cmd
);
1972 install_element(INTERFACE_NODE
, &no_ipv6_ospf6_deadinterval_cmd
);
1973 install_element(INTERFACE_NODE
, &no_ipv6_ospf6_hellointerval_cmd
);
1974 install_element(INTERFACE_NODE
, &no_ipv6_ospf6_priority_cmd
);
1975 install_element(INTERFACE_NODE
, &no_ipv6_ospf6_retransmitinterval_cmd
);
1976 install_element(INTERFACE_NODE
, &no_ipv6_ospf6_transmitdelay_cmd
);
1977 install_element(INTERFACE_NODE
, &no_ipv6_ospf6_instance_cmd
);
1979 install_element(INTERFACE_NODE
, &ipv6_ospf6_passive_cmd
);
1980 install_element(INTERFACE_NODE
, &no_ipv6_ospf6_passive_cmd
);
1982 install_element(INTERFACE_NODE
, &ipv6_ospf6_mtu_ignore_cmd
);
1983 install_element(INTERFACE_NODE
, &no_ipv6_ospf6_mtu_ignore_cmd
);
1985 install_element(INTERFACE_NODE
, &ipv6_ospf6_advertise_prefix_list_cmd
);
1986 install_element(INTERFACE_NODE
,
1987 &no_ipv6_ospf6_advertise_prefix_list_cmd
);
1989 install_element(INTERFACE_NODE
, &ipv6_ospf6_network_cmd
);
1990 install_element(INTERFACE_NODE
, &no_ipv6_ospf6_network_cmd
);
1992 /* reference bandwidth commands */
1993 install_element(OSPF6_NODE
, &auto_cost_reference_bandwidth_cmd
);
1994 install_element(OSPF6_NODE
, &no_auto_cost_reference_bandwidth_cmd
);
1997 /* Clear the specified interface structure */
1998 static void ospf6_interface_clear(struct vty
*vty
, struct interface
*ifp
)
2000 struct ospf6_interface
*oi
;
2002 if (!if_is_operative(ifp
))
2005 if (ifp
->info
== NULL
)
2008 oi
= (struct ospf6_interface
*)ifp
->info
;
2010 if (IS_OSPF6_DEBUG_INTERFACE
)
2011 zlog_debug("Interface %s: clear by reset", ifp
->name
);
2013 /* Reset the interface */
2014 thread_execute(master
, interface_down
, oi
, 0);
2015 thread_execute(master
, interface_up
, oi
, 0);
2018 /* Clear interface */
2019 DEFUN (clear_ipv6_ospf6_interface
,
2020 clear_ipv6_ospf6_interface_cmd
,
2021 "clear ipv6 ospf6 interface [IFNAME]",
2029 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
2031 struct interface
*ifp
;
2033 if (argc
== 4) /* Clear all the ospfv3 interfaces. */
2035 FOR_ALL_INTERFACES (vrf
, ifp
)
2036 ospf6_interface_clear(vty
, ifp
);
2037 } else /* Interface name is specified. */
2039 if ((ifp
= if_lookup_by_name(argv
[idx_ifname
]->arg
,
2042 vty_out(vty
, "No such Interface: %s\n",
2043 argv
[idx_ifname
]->arg
);
2046 ospf6_interface_clear(vty
, ifp
);
2052 void install_element_ospf6_clear_interface(void)
2054 install_element(ENABLE_NODE
, &clear_ipv6_ospf6_interface_cmd
);
2057 DEFUN (debug_ospf6_interface
,
2058 debug_ospf6_interface_cmd
,
2059 "debug ospf6 interface",
2062 "Debug OSPFv3 Interface\n"
2065 OSPF6_DEBUG_INTERFACE_ON();
2069 DEFUN (no_debug_ospf6_interface
,
2070 no_debug_ospf6_interface_cmd
,
2071 "no debug ospf6 interface",
2075 "Debug OSPFv3 Interface\n"
2078 OSPF6_DEBUG_INTERFACE_OFF();
2082 int config_write_ospf6_debug_interface(struct vty
*vty
)
2084 if (IS_OSPF6_DEBUG_INTERFACE
)
2085 vty_out(vty
, "debug ospf6 interface\n");
2089 void install_element_ospf6_debug_interface(void)
2091 install_element(ENABLE_NODE
, &debug_ospf6_interface_cmd
);
2092 install_element(ENABLE_NODE
, &no_debug_ospf6_interface_cmd
);
2093 install_element(CONFIG_NODE
, &debug_ospf6_interface_cmd
);
2094 install_element(CONFIG_NODE
, &no_debug_ospf6_interface_cmd
);