| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| #include <zebra.h> |
| |
| #include "memory.h" |
| #include "if.h" |
| #include "log.h" |
| #include "command.h" |
| #include "thread.h" |
| #include "prefix.h" |
| #include "plist.h" |
| #include "zclient.h" |
| |
| #include "ospf6_lsa.h" |
| #include "ospf6_lsdb.h" |
| #include "ospf6_network.h" |
| #include "ospf6_message.h" |
| #include "ospf6_route.h" |
| #include "ospf6_top.h" |
| #include "ospf6_area.h" |
| #include "ospf6_interface.h" |
| #include "ospf6_neighbor.h" |
| #include "ospf6_intra.h" |
| #include "ospf6_spf.h" |
| #include "ospf6d.h" |
| #include "ospf6_bfd.h" |
| #include "ospf6_zebra.h" |
| |
| DEFINE_MTYPE_STATIC(OSPF6D, CFG_PLIST_NAME, "configured prefix list names") |
| DEFINE_QOBJ_TYPE(ospf6_interface) |
| DEFINE_HOOK(ospf6_interface_change, |
| (struct ospf6_interface * oi, int state, int old_state), |
| (oi, state, old_state)) |
| |
| unsigned char conf_debug_ospf6_interface = 0; |
| |
| const char *const ospf6_interface_state_str[] = { |
| "None", "Down", "Loopback", "Waiting", "PointToPoint", |
| "DROther", "BDR", "DR", NULL}; |
| |
| struct ospf6_interface *ospf6_interface_lookup_by_ifindex(ifindex_t ifindex, |
| vrf_id_t vrf_id) |
| { |
| struct ospf6_interface *oi; |
| struct interface *ifp; |
| |
| ifp = if_lookup_by_index(ifindex, vrf_id); |
| if (ifp == NULL) |
| return (struct ospf6_interface *)NULL; |
| |
| oi = (struct ospf6_interface *)ifp->info; |
| return oi; |
| } |
| |
| |
| static void ospf6_interface_lsdb_hook(struct ospf6_lsa *lsa, |
| unsigned int reason) |
| { |
| struct ospf6_interface *oi; |
| |
| if (lsa == NULL) |
| return; |
| |
| oi = lsa->lsdb->data; |
| switch (ntohs(lsa->header->type)) { |
| case OSPF6_LSTYPE_LINK: |
| if (oi->state == OSPF6_INTERFACE_DR) |
| OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi); |
| if (oi->area) |
| ospf6_spf_schedule(oi->area->ospf6, reason); |
| break; |
| |
| default: |
| break; |
| } |
| } |
| |
| static void ospf6_interface_lsdb_hook_add(struct ospf6_lsa *lsa) |
| { |
| ospf6_interface_lsdb_hook(lsa, ospf6_lsadd_to_spf_reason(lsa)); |
| } |
| |
| static void ospf6_interface_lsdb_hook_remove(struct ospf6_lsa *lsa) |
| { |
| ospf6_interface_lsdb_hook(lsa, ospf6_lsremove_to_spf_reason(lsa)); |
| } |
| |
| static uint8_t ospf6_default_iftype(struct interface *ifp) |
| { |
| if (if_is_pointopoint(ifp)) |
| return OSPF_IFTYPE_POINTOPOINT; |
| else if (if_is_loopback(ifp)) |
| return OSPF_IFTYPE_LOOPBACK; |
| else |
| return OSPF_IFTYPE_BROADCAST; |
| } |
| |
| static uint32_t ospf6_interface_get_cost(struct ospf6_interface *oi) |
| { |
| |
| uint32_t cost; |
| uint32_t bw, refbw; |
| |
| |
| |
| |
| |
| if (!oi->interface->bandwidth && oi->interface->speed) { |
| bw = oi->interface->speed; |
| } else { |
| bw = oi->interface->bandwidth ? oi->interface->bandwidth |
| : OSPF6_INTERFACE_BANDWIDTH; |
| } |
| |
| refbw = ospf6 ? ospf6->ref_bandwidth : OSPF6_REFERENCE_BANDWIDTH; |
| |
| |
| if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_NOAUTOCOST)) |
| cost = oi->cost; |
| else { |
| cost = (uint32_t)((double)refbw / (double)bw + (double)0.5); |
| if (cost < 1) |
| cost = 1; |
| else if (cost > UINT32_MAX) |
| cost = UINT32_MAX; |
| } |
| |
| return cost; |
| } |
| |
| static void ospf6_interface_force_recalculate_cost(struct ospf6_interface *oi) |
| { |
| |
| ospf6_interface_connected_route_update(oi->interface); |
| |
| |
| if (oi->area) { |
| OSPF6_LINK_LSA_SCHEDULE(oi); |
| OSPF6_ROUTER_LSA_SCHEDULE(oi->area); |
| OSPF6_NETWORK_LSA_SCHEDULE(oi); |
| OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi); |
| OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area); |
| } |
| } |
| |
| static void ospf6_interface_recalculate_cost(struct ospf6_interface *oi) |
| { |
| uint32_t newcost; |
| |
| newcost = ospf6_interface_get_cost(oi); |
| if (newcost == oi->cost) |
| return; |
| oi->cost = newcost; |
| |
| ospf6_interface_force_recalculate_cost(oi); |
| } |
| |
| |
| struct ospf6_interface *ospf6_interface_create(struct interface *ifp) |
| { |
| struct ospf6_interface *oi; |
| unsigned int iobuflen; |
| |
| oi = XCALLOC(MTYPE_OSPF6_IF, sizeof(struct ospf6_interface)); |
| |
| oi->area = (struct ospf6_area *)NULL; |
| oi->neighbor_list = list_new(); |
| oi->neighbor_list->cmp = ospf6_neighbor_cmp; |
| oi->linklocal_addr = (struct in6_addr *)NULL; |
| oi->instance_id = OSPF6_INTERFACE_INSTANCE_ID; |
| oi->transdelay = OSPF6_INTERFACE_TRANSDELAY; |
| oi->priority = OSPF6_INTERFACE_PRIORITY; |
| |
| oi->hello_interval = OSPF_HELLO_INTERVAL_DEFAULT; |
| oi->dead_interval = OSPF_ROUTER_DEAD_INTERVAL_DEFAULT; |
| oi->rxmt_interval = OSPF_RETRANSMIT_INTERVAL_DEFAULT; |
| oi->type = ospf6_default_iftype(ifp); |
| oi->state = OSPF6_INTERFACE_DOWN; |
| oi->flag = 0; |
| oi->mtu_ignore = 0; |
| oi->c_ifmtu = 0; |
| |
| |
| oi->ifmtu = ifp->mtu6; |
| iobuflen = ospf6_iobuf_size(ifp->mtu6); |
| if (oi->ifmtu > iobuflen) { |
| if (IS_OSPF6_DEBUG_INTERFACE) |
| zlog_debug( |
| "Interface %s: IfMtu is adjusted to I/O buffer size: %d.", |
| ifp->name, iobuflen); |
| oi->ifmtu = iobuflen; |
| } |
| |
| QOBJ_REG(oi, ospf6_interface); |
| |
| oi->lsupdate_list = ospf6_lsdb_create(oi); |
| oi->lsack_list = ospf6_lsdb_create(oi); |
| oi->lsdb = ospf6_lsdb_create(oi); |
| oi->lsdb->hook_add = ospf6_interface_lsdb_hook_add; |
| oi->lsdb->hook_remove = ospf6_interface_lsdb_hook_remove; |
| oi->lsdb_self = ospf6_lsdb_create(oi); |
| |
| oi->route_connected = |
| OSPF6_ROUTE_TABLE_CREATE(INTERFACE, CONNECTED_ROUTES); |
| oi->route_connected->scope = oi; |
| |
| |
| oi->interface = ifp; |
| ifp->info = oi; |
| |
| |
| oi->cost = ospf6_interface_get_cost(oi); |
| |
| return oi; |
| } |
| |
| void ospf6_interface_delete(struct ospf6_interface *oi) |
| { |
| struct listnode *node, *nnode; |
| struct ospf6_neighbor *on; |
| |
| QOBJ_UNREG(oi); |
| |
| for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) |
| ospf6_neighbor_delete(on); |
| |
| list_delete(&oi->neighbor_list); |
| |
| THREAD_OFF(oi->thread_send_hello); |
| THREAD_OFF(oi->thread_send_lsupdate); |
| THREAD_OFF(oi->thread_send_lsack); |
| THREAD_OFF(oi->thread_sso); |
| |
| ospf6_lsdb_remove_all(oi->lsdb); |
| ospf6_lsdb_remove_all(oi->lsupdate_list); |
| ospf6_lsdb_remove_all(oi->lsack_list); |
| |
| ospf6_lsdb_delete(oi->lsdb); |
| ospf6_lsdb_delete(oi->lsdb_self); |
| |
| ospf6_lsdb_delete(oi->lsupdate_list); |
| ospf6_lsdb_delete(oi->lsack_list); |
| |
| ospf6_route_table_delete(oi->route_connected); |
| |
| |
| oi->interface->info = NULL; |
| |
| |
| if (oi->plist_name) |
| XFREE(MTYPE_CFG_PLIST_NAME, oi->plist_name); |
| |
| ospf6_bfd_info_free(&(oi->bfd_info)); |
| |
| |
| ospf6_area_interface_delete(oi); |
| |
| XFREE(MTYPE_OSPF6_IF, oi); |
| } |
| |
| void ospf6_interface_enable(struct ospf6_interface *oi) |
| { |
| UNSET_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE); |
| ospf6_interface_state_update(oi->interface); |
| } |
| |
| void ospf6_interface_disable(struct ospf6_interface *oi) |
| { |
| SET_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE); |
| |
| thread_execute(master, interface_down, oi, 0); |
| |
| ospf6_lsdb_remove_all(oi->lsdb); |
| ospf6_lsdb_remove_all(oi->lsdb_self); |
| ospf6_lsdb_remove_all(oi->lsupdate_list); |
| ospf6_lsdb_remove_all(oi->lsack_list); |
| |
| THREAD_OFF(oi->thread_send_hello); |
| THREAD_OFF(oi->thread_send_lsupdate); |
| THREAD_OFF(oi->thread_send_lsack); |
| THREAD_OFF(oi->thread_sso); |
| |
| THREAD_OFF(oi->thread_network_lsa); |
| THREAD_OFF(oi->thread_link_lsa); |
| THREAD_OFF(oi->thread_intra_prefix_lsa); |
| THREAD_OFF(oi->thread_as_extern_lsa); |
| } |
| |
| static struct in6_addr * |
| ospf6_interface_get_linklocal_address(struct interface *ifp) |
| { |
| struct listnode *n; |
| struct connected *c; |
| struct in6_addr *l = (struct in6_addr *)NULL; |
| |
| |
| for (ALL_LIST_ELEMENTS_RO(ifp->connected, n, c)) { |
| |
| if (c->address->family != AF_INET6) |
| continue; |
| |
| |
| if (IN6_IS_ADDR_LINKLOCAL(&c->address->u.prefix6)) |
| l = &c->address->u.prefix6; |
| } |
| return l; |
| } |
| |
| void ospf6_interface_if_add(struct interface *ifp) |
| { |
| struct ospf6_interface *oi; |
| unsigned int iobuflen; |
| |
| oi = (struct ospf6_interface *)ifp->info; |
| if (oi == NULL) |
| return; |
| |
| |
| if (oi->ifmtu == 0) |
| oi->ifmtu = ifp->mtu6; |
| iobuflen = ospf6_iobuf_size(ifp->mtu6); |
| if (oi->ifmtu > iobuflen) { |
| if (IS_OSPF6_DEBUG_INTERFACE) |
| zlog_debug( |
| "Interface %s: IfMtu is adjusted to I/O buffer size: %d.", |
| ifp->name, iobuflen); |
| oi->ifmtu = iobuflen; |
| } |
| |
| |
| ospf6_interface_state_update(oi->interface); |
| } |
| |
| void ospf6_interface_state_update(struct interface *ifp) |
| { |
| struct ospf6_interface *oi; |
| unsigned int iobuflen; |
| |
| oi = (struct ospf6_interface *)ifp->info; |
| if (oi == NULL) |
| return; |
| if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) |
| return; |
| |
| |
| if (ifp->mtu6 != oi->ifmtu) { |
| |
| if (!oi->c_ifmtu) { |
| oi->ifmtu = ifp->mtu6; |
| iobuflen = ospf6_iobuf_size(ifp->mtu6); |
| if (oi->ifmtu > iobuflen) { |
| if (IS_OSPF6_DEBUG_INTERFACE) |
| zlog_debug( |
| "Interface %s: IfMtu is adjusted to I/O buffer size: %d.", |
| ifp->name, iobuflen); |
| oi->ifmtu = iobuflen; |
| } |
| } else if (oi->c_ifmtu > ifp->mtu6) { |
| oi->ifmtu = ifp->mtu6; |
| zlog_warn( |
| "Configured mtu %u on %s overridden by kernel %u", |
| oi->c_ifmtu, ifp->name, ifp->mtu6); |
| } else |
| oi->ifmtu = oi->c_ifmtu; |
| } |
| |
| if (if_is_operative(ifp) |
| && (ospf6_interface_get_linklocal_address(oi->interface) |
| || if_is_loopback(oi->interface))) |
| thread_execute(master, interface_up, oi, 0); |
| else |
| thread_execute(master, interface_down, oi, 0); |
| |
| return; |
| } |
| |
| void ospf6_interface_connected_route_update(struct interface *ifp) |
| { |
| struct ospf6_interface *oi; |
| struct ospf6_route *route; |
| struct connected *c; |
| struct listnode *node, *nnode; |
| struct in6_addr nh_addr; |
| |
| oi = (struct ospf6_interface *)ifp->info; |
| if (oi == NULL) |
| return; |
| |
| |
| oi->linklocal_addr = ospf6_interface_get_linklocal_address(ifp); |
| |
| |
| if (oi->area == NULL) |
| return; |
| |
| if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) |
| return; |
| |
| |
| ospf6_route_remove_all(oi->route_connected); |
| |
| for (ALL_LIST_ELEMENTS(oi->interface->connected, node, nnode, c)) { |
| if (c->address->family != AF_INET6) |
| continue; |
| |
| CONTINUE_IF_ADDRESS_LINKLOCAL(IS_OSPF6_DEBUG_INTERFACE, |
| c->address); |
| CONTINUE_IF_ADDRESS_UNSPECIFIED(IS_OSPF6_DEBUG_INTERFACE, |
| c->address); |
| CONTINUE_IF_ADDRESS_LOOPBACK(IS_OSPF6_DEBUG_INTERFACE, |
| c->address); |
| CONTINUE_IF_ADDRESS_V4COMPAT(IS_OSPF6_DEBUG_INTERFACE, |
| c->address); |
| CONTINUE_IF_ADDRESS_V4MAPPED(IS_OSPF6_DEBUG_INTERFACE, |
| c->address); |
| |
| |
| if (oi->plist_name) { |
| struct prefix_list *plist; |
| enum prefix_list_type ret; |
| char buf[PREFIX2STR_BUFFER]; |
| |
| prefix2str(c->address, buf, sizeof(buf)); |
| plist = prefix_list_lookup(AFI_IP6, oi->plist_name); |
| ret = prefix_list_apply(plist, (void *)c->address); |
| if (ret == PREFIX_DENY) { |
| if (IS_OSPF6_DEBUG_INTERFACE) |
| zlog_debug( |
| "%s on %s filtered by prefix-list %s ", |
| buf, oi->interface->name, |
| oi->plist_name); |
| continue; |
| } |
| } |
| |
| route = ospf6_route_create(); |
| memcpy(&route->prefix, c->address, sizeof(struct prefix)); |
| apply_mask(&route->prefix); |
| route->type = OSPF6_DEST_TYPE_NETWORK; |
| route->path.area_id = oi->area->area_id; |
| route->path.type = OSPF6_PATH_TYPE_INTRA; |
| route->path.cost = oi->cost; |
| inet_pton(AF_INET6, "::1", &nh_addr); |
| ospf6_route_add_nexthop(route, oi->interface->ifindex, |
| &nh_addr); |
| ospf6_route_add(route, oi->route_connected); |
| } |
| |
| |
| OSPF6_LINK_LSA_SCHEDULE(oi); |
| OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi); |
| OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area); |
| } |
| |
| static void ospf6_interface_state_change(uint8_t next_state, |
| struct ospf6_interface *oi) |
| { |
| uint8_t prev_state; |
| |
| prev_state = oi->state; |
| oi->state = next_state; |
| |
| if (prev_state == next_state) |
| return; |
| |
| |
| if (IS_OSPF6_DEBUG_INTERFACE) { |
| zlog_debug("Interface state change %s: %s -> %s", |
| oi->interface->name, |
| ospf6_interface_state_str[prev_state], |
| ospf6_interface_state_str[next_state]); |
| } |
| oi->state_change++; |
| |
| if ((prev_state == OSPF6_INTERFACE_DR |
| || prev_state == OSPF6_INTERFACE_BDR) |
| && (next_state != OSPF6_INTERFACE_DR |
| && next_state != OSPF6_INTERFACE_BDR)) |
| ospf6_sso(oi->interface->ifindex, &alldrouters6, |
| IPV6_LEAVE_GROUP); |
| |
| if ((prev_state != OSPF6_INTERFACE_DR |
| && prev_state != OSPF6_INTERFACE_BDR) |
| && (next_state == OSPF6_INTERFACE_DR |
| || next_state == OSPF6_INTERFACE_BDR)) |
| ospf6_sso(oi->interface->ifindex, &alldrouters6, |
| IPV6_JOIN_GROUP); |
| |
| OSPF6_ROUTER_LSA_SCHEDULE(oi->area); |
| if (next_state == OSPF6_INTERFACE_DOWN) { |
| OSPF6_NETWORK_LSA_EXECUTE(oi); |
| OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(oi); |
| OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area); |
| OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(oi); |
| } else if (prev_state == OSPF6_INTERFACE_DR |
| || next_state == OSPF6_INTERFACE_DR) { |
| OSPF6_NETWORK_LSA_SCHEDULE(oi); |
| OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi); |
| OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area); |
| } |
| |
| hook_call(ospf6_interface_change, oi, next_state, prev_state); |
| } |
| |
| |
| |
| |
| #define IS_ELIGIBLE(n) \ |
| ((n)->state >= OSPF6_NEIGHBOR_TWOWAY && (n)->priority != 0) |
| |
| static struct ospf6_neighbor *better_bdrouter(struct ospf6_neighbor *a, |
| struct ospf6_neighbor *b) |
| { |
| if ((a == NULL || !IS_ELIGIBLE(a) || a->drouter == a->router_id) |
| && (b == NULL || !IS_ELIGIBLE(b) || b->drouter == b->router_id)) |
| return NULL; |
| else if (a == NULL || !IS_ELIGIBLE(a) || a->drouter == a->router_id) |
| return b; |
| else if (b == NULL || !IS_ELIGIBLE(b) || b->drouter == b->router_id) |
| return a; |
| |
| if (a->bdrouter == a->router_id && b->bdrouter != b->router_id) |
| return a; |
| if (a->bdrouter != a->router_id && b->bdrouter == b->router_id) |
| return b; |
| |
| if (a->priority > b->priority) |
| return a; |
| if (a->priority < b->priority) |
| return b; |
| |
| if (ntohl(a->router_id) > ntohl(b->router_id)) |
| return a; |
| if (ntohl(a->router_id) < ntohl(b->router_id)) |
| return b; |
| |
| zlog_warn("Router-ID duplicate ?"); |
| return a; |
| } |
| |
| static struct ospf6_neighbor *better_drouter(struct ospf6_neighbor *a, |
| struct ospf6_neighbor *b) |
| { |
| if ((a == NULL || !IS_ELIGIBLE(a) || a->drouter != a->router_id) |
| && (b == NULL || !IS_ELIGIBLE(b) || b->drouter != b->router_id)) |
| return NULL; |
| else if (a == NULL || !IS_ELIGIBLE(a) || a->drouter != a->router_id) |
| return b; |
| else if (b == NULL || !IS_ELIGIBLE(b) || b->drouter != b->router_id) |
| return a; |
| |
| if (a->drouter == a->router_id && b->drouter != b->router_id) |
| return a; |
| if (a->drouter != a->router_id && b->drouter == b->router_id) |
| return b; |
| |
| if (a->priority > b->priority) |
| return a; |
| if (a->priority < b->priority) |
| return b; |
| |
| if (ntohl(a->router_id) > ntohl(b->router_id)) |
| return a; |
| if (ntohl(a->router_id) < ntohl(b->router_id)) |
| return b; |
| |
| zlog_warn("Router-ID duplicate ?"); |
| return a; |
| } |
| |
| static uint8_t dr_election(struct ospf6_interface *oi) |
| { |
| struct listnode *node, *nnode; |
| struct ospf6_neighbor *on, *drouter, *bdrouter, myself; |
| struct ospf6_neighbor *best_drouter, *best_bdrouter; |
| uint8_t next_state = 0; |
| |
| drouter = bdrouter = NULL; |
| best_drouter = best_bdrouter = NULL; |
| |
| |
| memset(&myself, 0, sizeof(myself)); |
| inet_ntop(AF_INET, &oi->area->ospf6->router_id, myself.name, |
| sizeof(myself.name)); |
| myself.state = OSPF6_NEIGHBOR_TWOWAY; |
| myself.drouter = oi->drouter; |
| myself.bdrouter = oi->bdrouter; |
| myself.priority = oi->priority; |
| myself.router_id = oi->area->ospf6->router_id; |
| |
| |
| for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) |
| bdrouter = better_bdrouter(bdrouter, on); |
| |
| best_bdrouter = bdrouter; |
| bdrouter = better_bdrouter(best_bdrouter, &myself); |
| |
| |
| for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) |
| drouter = better_drouter(drouter, on); |
| |
| best_drouter = drouter; |
| drouter = better_drouter(best_drouter, &myself); |
| if (drouter == NULL) |
| drouter = bdrouter; |
| |
| |
| if ((drouter == &myself && myself.drouter != myself.router_id) |
| || (drouter != &myself && myself.drouter == myself.router_id) |
| || (bdrouter == &myself && myself.bdrouter != myself.router_id) |
| || (bdrouter != &myself && myself.bdrouter == myself.router_id)) { |
| myself.drouter = (drouter ? drouter->router_id : htonl(0)); |
| myself.bdrouter = (bdrouter ? bdrouter->router_id : htonl(0)); |
| |
| |
| bdrouter = better_bdrouter(best_bdrouter, &myself); |
| |
| |
| drouter = better_drouter(best_drouter, &myself); |
| if (drouter == NULL) |
| drouter = bdrouter; |
| } |
| |
| |
| if (drouter && drouter == &myself) |
| next_state = OSPF6_INTERFACE_DR; |
| else if (bdrouter && bdrouter == &myself) |
| next_state = OSPF6_INTERFACE_BDR; |
| else |
| next_state = OSPF6_INTERFACE_DROTHER; |
| |
| |
| |
| |
| |
| |
| |
| if (oi->drouter != (drouter ? drouter->router_id : htonl(0)) |
| || oi->bdrouter != (bdrouter ? bdrouter->router_id : htonl(0))) { |
| if (IS_OSPF6_DEBUG_INTERFACE) |
| zlog_debug("DR Election on %s: DR: %s BDR: %s", |
| oi->interface->name, |
| (drouter ? drouter->name : "0.0.0.0"), |
| (bdrouter ? bdrouter->name : "0.0.0.0")); |
| |
| for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, node, on)) { |
| if (on->state < OSPF6_NEIGHBOR_TWOWAY) |
| continue; |
| |
| thread_add_event(master, adj_ok, on, 0, NULL); |
| } |
| } |
| |
| oi->drouter = (drouter ? drouter->router_id : htonl(0)); |
| oi->bdrouter = (bdrouter ? bdrouter->router_id : htonl(0)); |
| return next_state; |
| } |
| |
| |
| |
| int interface_up(struct thread *thread) |
| { |
| struct ospf6_interface *oi; |
| |
| oi = (struct ospf6_interface *)THREAD_ARG(thread); |
| assert(oi && oi->interface); |
| |
| if (!oi->type_cfg) |
| oi->type = ospf6_default_iftype(oi->interface); |
| |
| |
| |
| |
| |
| oi->thread_sso = NULL; |
| |
| if (IS_OSPF6_DEBUG_INTERFACE) |
| zlog_debug("Interface Event %s: [InterfaceUp]", |
| oi->interface->name); |
| |
| |
| if (!if_is_operative(oi->interface)) { |
| if (IS_OSPF6_DEBUG_INTERFACE) |
| zlog_debug( |
| "Interface %s is down, can't execute [InterfaceUp]", |
| oi->interface->name); |
| return 0; |
| } |
| |
| |
| if (!(ospf6_interface_get_linklocal_address(oi->interface) |
| || if_is_loopback(oi->interface))) { |
| if (IS_OSPF6_DEBUG_INTERFACE) |
| zlog_debug( |
| "Interface %s has no link local address, can't execute [InterfaceUp]", |
| oi->interface->name); |
| return 0; |
| } |
| |
| |
| ospf6_interface_recalculate_cost(oi); |
| |
| |
| if (oi->state > OSPF6_INTERFACE_DOWN) { |
| if (IS_OSPF6_DEBUG_INTERFACE) |
| zlog_debug("Interface %s already enabled", |
| oi->interface->name); |
| return 0; |
| } |
| |
| |
| if (oi->area == NULL) { |
| zlog_debug( |
| "%s: Not scheduleing Hello for %s as there is no area assigned yet", |
| __func__, oi->interface->name); |
| return 0; |
| } |
| |
| #ifdef __FreeBSD__ |
| |
| |
| |
| |
| |
| if (oi->sso_try_cnt == 0) { |
| oi->sso_try_cnt++; |
| zlog_info("Scheduling %s for sso", oi->interface->name); |
| thread_add_timer(master, interface_up, oi, |
| OSPF6_INTERFACE_SSO_RETRY_INT, |
| &oi->thread_sso); |
| return 0; |
| } |
| #endif |
| |
| |
| if (ospf6_sso(oi->interface->ifindex, &allspfrouters6, IPV6_JOIN_GROUP) |
| < 0) { |
| if (oi->sso_try_cnt++ < OSPF6_INTERFACE_SSO_RETRY_MAX) { |
| zlog_info( |
| "Scheduling %s for sso retry, trial count: %d", |
| oi->interface->name, oi->sso_try_cnt); |
| thread_add_timer(master, interface_up, oi, |
| OSPF6_INTERFACE_SSO_RETRY_INT, |
| &oi->thread_sso); |
| } |
| return 0; |
| } |
| oi->sso_try_cnt = 0; |
| |
| |
| ospf6_interface_connected_route_update(oi->interface); |
| |
| |
| if (!CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE) |
| && !if_is_loopback(oi->interface)) { |
| oi->thread_send_hello = NULL; |
| thread_add_event(master, ospf6_hello_send, oi, 0, |
| &oi->thread_send_hello); |
| } |
| |
| |
| if (oi->type == OSPF_IFTYPE_POINTOPOINT) { |
| ospf6_interface_state_change(OSPF6_INTERFACE_POINTTOPOINT, oi); |
| } else if (oi->priority == 0) |
| ospf6_interface_state_change(OSPF6_INTERFACE_DROTHER, oi); |
| else { |
| ospf6_interface_state_change(OSPF6_INTERFACE_WAITING, oi); |
| thread_add_timer(master, wait_timer, oi, oi->dead_interval, |
| NULL); |
| } |
| |
| return 0; |
| } |
| |
| int wait_timer(struct thread *thread) |
| { |
| struct ospf6_interface *oi; |
| |
| oi = (struct ospf6_interface *)THREAD_ARG(thread); |
| assert(oi && oi->interface); |
| |
| if (IS_OSPF6_DEBUG_INTERFACE) |
| zlog_debug("Interface Event %s: [WaitTimer]", |
| oi->interface->name); |
| |
| if (oi->state == OSPF6_INTERFACE_WAITING) |
| ospf6_interface_state_change(dr_election(oi), oi); |
| |
| return 0; |
| } |
| |
| int backup_seen(struct thread *thread) |
| { |
| struct ospf6_interface *oi; |
| |
| oi = (struct ospf6_interface *)THREAD_ARG(thread); |
| assert(oi && oi->interface); |
| |
| if (IS_OSPF6_DEBUG_INTERFACE) |
| zlog_debug("Interface Event %s: [BackupSeen]", |
| oi->interface->name); |
| |
| if (oi->state == OSPF6_INTERFACE_WAITING) |
| ospf6_interface_state_change(dr_election(oi), oi); |
| |
| return 0; |
| } |
| |
| int neighbor_change(struct thread *thread) |
| { |
| struct ospf6_interface *oi; |
| |
| oi = (struct ospf6_interface *)THREAD_ARG(thread); |
| assert(oi && oi->interface); |
| |
| if (IS_OSPF6_DEBUG_INTERFACE) |
| zlog_debug("Interface Event %s: [NeighborChange]", |
| oi->interface->name); |
| |
| if (oi->state == OSPF6_INTERFACE_DROTHER |
| || oi->state == OSPF6_INTERFACE_BDR |
| || oi->state == OSPF6_INTERFACE_DR) |
| ospf6_interface_state_change(dr_election(oi), oi); |
| |
| return 0; |
| } |
| |
| int interface_down(struct thread *thread) |
| { |
| struct ospf6_interface *oi; |
| struct listnode *node, *nnode; |
| struct ospf6_neighbor *on; |
| |
| oi = (struct ospf6_interface *)THREAD_ARG(thread); |
| assert(oi && oi->interface); |
| |
| if (IS_OSPF6_DEBUG_INTERFACE) |
| zlog_debug("Interface Event %s: [InterfaceDown]", |
| oi->interface->name); |
| |
| |
| THREAD_OFF(oi->thread_send_hello); |
| |
| |
| THREAD_OFF(oi->thread_sso); |
| |
| |
| if (oi->state > OSPF6_INTERFACE_DOWN) |
| ospf6_sso(oi->interface->ifindex, &allspfrouters6, |
| IPV6_LEAVE_GROUP); |
| |
| ospf6_interface_state_change(OSPF6_INTERFACE_DOWN, oi); |
| |
| for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) |
| ospf6_neighbor_delete(on); |
| |
| list_delete_all_node(oi->neighbor_list); |
| |
| |
| |
| oi->drouter = oi->prev_drouter = htonl(0); |
| oi->bdrouter = oi->prev_bdrouter = htonl(0); |
| return 0; |
| } |
| |
| |
| static const char *ospf6_iftype_str(uint8_t iftype) |
| { |
| switch (iftype) { |
| case OSPF_IFTYPE_LOOPBACK: |
| return "LOOPBACK"; |
| case OSPF_IFTYPE_BROADCAST: |
| return "BROADCAST"; |
| case OSPF_IFTYPE_POINTOPOINT: |
| return "POINTOPOINT"; |
| } |
| return "UNKNOWN"; |
| } |
| |
| |
| static int ospf6_interface_show(struct vty *vty, struct interface *ifp) |
| { |
| struct ospf6_interface *oi; |
| struct connected *c; |
| struct prefix *p; |
| struct listnode *i; |
| char strbuf[PREFIX2STR_BUFFER], drouter[32], bdrouter[32]; |
| uint8_t default_iftype; |
| struct timeval res, now; |
| char duration[32]; |
| struct ospf6_lsa *lsa; |
| |
| default_iftype = ospf6_default_iftype(ifp); |
| |
| vty_out(vty, "%s is %s, type %s\n", ifp->name, |
| (if_is_operative(ifp) ? "up" : "down"), |
| ospf6_iftype_str(default_iftype)); |
| vty_out(vty, " Interface ID: %d\n", ifp->ifindex); |
| |
| if (ifp->info == NULL) { |
| vty_out(vty, " OSPF not enabled on this interface\n"); |
| return 0; |
| } else |
| oi = (struct ospf6_interface *)ifp->info; |
| |
| if (if_is_operative(ifp) && oi->type != default_iftype) |
| vty_out(vty, " Operating as type %s\n", |
| ospf6_iftype_str(oi->type)); |
| |
| vty_out(vty, " Internet Address:\n"); |
| |
| for (ALL_LIST_ELEMENTS_RO(ifp->connected, i, c)) { |
| p = c->address; |
| prefix2str(p, strbuf, sizeof(strbuf)); |
| switch (p->family) { |
| case AF_INET: |
| vty_out(vty, " inet : %s\n", strbuf); |
| break; |
| case AF_INET6: |
| vty_out(vty, " inet6: %s\n", strbuf); |
| break; |
| default: |
| vty_out(vty, " ??? : %s\n", strbuf); |
| break; |
| } |
| } |
| |
| if (oi->area) { |
| vty_out(vty, |
| " Instance ID %d, Interface MTU %d (autodetect: %d)\n", |
| oi->instance_id, oi->ifmtu, ifp->mtu6); |
| vty_out(vty, " MTU mismatch detection: %s\n", |
| oi->mtu_ignore ? "disabled" : "enabled"); |
| inet_ntop(AF_INET, &oi->area->area_id, strbuf, sizeof(strbuf)); |
| vty_out(vty, " Area ID %s, Cost %u\n", strbuf, oi->cost); |
| } else |
| vty_out(vty, " Not Attached to Area\n"); |
| |
| vty_out(vty, " State %s, Transmit Delay %d sec, Priority %d\n", |
| ospf6_interface_state_str[oi->state], oi->transdelay, |
| oi->priority); |
| vty_out(vty, " Timer intervals configured:\n"); |
| vty_out(vty, " Hello %d, Dead %d, Retransmit %d\n", |
| oi->hello_interval, oi->dead_interval, oi->rxmt_interval); |
| |
| inet_ntop(AF_INET, &oi->drouter, drouter, sizeof(drouter)); |
| inet_ntop(AF_INET, &oi->bdrouter, bdrouter, sizeof(bdrouter)); |
| vty_out(vty, " DR: %s BDR: %s\n", drouter, bdrouter); |
| |
| vty_out(vty, " Number of I/F scoped LSAs is %u\n", oi->lsdb->count); |
| |
| monotime(&now); |
| |
| timerclear(&res); |
| if (oi->thread_send_lsupdate) |
| timersub(&oi->thread_send_lsupdate->u.sands, &now, &res); |
| timerstring(&res, duration, sizeof(duration)); |
| vty_out(vty, |
| " %d Pending LSAs for LSUpdate in Time %s [thread %s]\n", |
| oi->lsupdate_list->count, duration, |
| (oi->thread_send_lsupdate ? "on" : "off")); |
| for (ALL_LSDB(oi->lsupdate_list, lsa)) |
| vty_out(vty, " %s\n", lsa->name); |
| |
| timerclear(&res); |
| if (oi->thread_send_lsack) |
| timersub(&oi->thread_send_lsack->u.sands, &now, &res); |
| timerstring(&res, duration, sizeof(duration)); |
| vty_out(vty, " %d Pending LSAs for LSAck in Time %s [thread %s]\n", |
| oi->lsack_list->count, duration, |
| (oi->thread_send_lsack ? "on" : "off")); |
| for (ALL_LSDB(oi->lsack_list, lsa)) |
| vty_out(vty, " %s\n", lsa->name); |
| ospf6_bfd_show_info(vty, oi->bfd_info, 1); |
| return 0; |
| } |
| |
| |
| DEFUN (show_ipv6_ospf6_interface, |
| show_ipv6_ospf6_interface_ifname_cmd, |
| "show ipv6 ospf6 interface [IFNAME]", |
| SHOW_STR |
| IP6_STR |
| OSPF6_STR |
| INTERFACE_STR |
| IFNAME_STR) |
| { |
| struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); |
| int idx_ifname = 4; |
| struct interface *ifp; |
| |
| if (argc == 5) { |
| ifp = if_lookup_by_name(argv[idx_ifname]->arg, VRF_DEFAULT); |
| if (ifp == NULL) { |
| vty_out(vty, "No such Interface: %s\n", |
| argv[idx_ifname]->arg); |
| return CMD_WARNING; |
| } |
| ospf6_interface_show(vty, ifp); |
| } else { |
| FOR_ALL_INTERFACES (vrf, ifp) |
| ospf6_interface_show(vty, ifp); |
| } |
| |
| return CMD_SUCCESS; |
| } |
| |
| static int ospf6_interface_show_traffic(struct vty *vty, |
| struct interface *intf_ifp, |
| int display_once) |
| { |
| struct interface *ifp; |
| struct vrf *vrf = NULL; |
| struct ospf6_interface *oi = NULL; |
| |
| if (intf_ifp) |
| vrf = vrf_lookup_by_id(intf_ifp->vrf_id); |
| else |
| vrf = vrf_lookup_by_id(VRF_DEFAULT); |
| |
| if (!display_once) { |
| vty_out(vty, "\n"); |
| vty_out(vty, "%-12s%-17s%-17s%-17s%-17s%-17s\n", "Interface", |
| " HELLO", " DB-Desc", " LS-Req", " LS-Update", |
| " LS-Ack"); |
| vty_out(vty, "%-10s%-18s%-18s%-17s%-17s%-17s\n", "", |
| " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx", |
| " Rx/Tx"); |
| vty_out(vty, |
| "--------------------------------------------------------------------------------------------\n"); |
| } |
| |
| if (intf_ifp == NULL) { |
| FOR_ALL_INTERFACES (vrf, ifp) { |
| if (ifp->info) |
| oi = (struct ospf6_interface *)ifp->info; |
| else |
| continue; |
| |
| vty_out(vty, |
| "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u\n", |
| oi->interface->name, oi->hello_in, |
| oi->hello_out, oi->db_desc_in, oi->db_desc_out, |
| oi->ls_req_in, oi->ls_req_out, oi->ls_upd_in, |
| oi->ls_upd_out, oi->ls_ack_in, oi->ls_ack_out); |
| } |
| } else { |
| oi = intf_ifp->info; |
| if (oi == NULL) |
| return CMD_WARNING; |
| |
| vty_out(vty, |
| "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u\n", |
| oi->interface->name, oi->hello_in, oi->hello_out, |
| oi->db_desc_in, oi->db_desc_out, oi->ls_req_in, |
| oi->ls_req_out, oi->ls_upd_in, oi->ls_upd_out, |
| oi->ls_ack_in, oi->ls_ack_out); |
| } |
| |
| return CMD_SUCCESS; |
| } |
| |
| |
| DEFUN (show_ipv6_ospf6_interface_traffic, |
| show_ipv6_ospf6_interface_traffic_cmd, |
| "show ipv6 ospf6 interface traffic [IFNAME]", |
| SHOW_STR |
| IP6_STR |
| OSPF6_STR |
| INTERFACE_STR |
| "Protocol Packet counters\n" |
| IFNAME_STR) |
| { |
| int idx_ifname = 0; |
| int display_once = 0; |
| char *intf_name = NULL; |
| struct interface *ifp = NULL; |
| |
| if (argv_find(argv, argc, "IFNAME", &idx_ifname)) { |
| intf_name = argv[idx_ifname]->arg; |
| ifp = if_lookup_by_name(intf_name, VRF_DEFAULT); |
| if (ifp == NULL) { |
| vty_out(vty, "No such Interface: %s\n", intf_name); |
| return CMD_WARNING; |
| } |
| if (ifp->info == NULL) { |
| vty_out(vty, |
| " OSPF not enabled on this interface %s\n", |
| intf_name); |
| return 0; |
| } |
| } |
| |
| ospf6_interface_show_traffic(vty, ifp, display_once); |
| |
| |
| return CMD_SUCCESS; |
| } |
| |
| |
| DEFUN (show_ipv6_ospf6_interface_ifname_prefix, |
| show_ipv6_ospf6_interface_ifname_prefix_cmd, |
| "show ipv6 ospf6 interface IFNAME prefix\ |
| [<\ |
| detail\ |
| |<X:X::X:X|X:X::X:X/M> [<match|detail>]\ |
| >]", |
| SHOW_STR |
| IP6_STR |
| OSPF6_STR |
| INTERFACE_STR |
| IFNAME_STR |
| "Display connected prefixes to advertise\n" |
| "Display details of the prefixes\n" |
| OSPF6_ROUTE_ADDRESS_STR |
| OSPF6_ROUTE_PREFIX_STR |
| OSPF6_ROUTE_MATCH_STR |
| "Display details of the prefixes\n") |
| { |
| int idx_ifname = 4; |
| int idx_prefix = 6; |
| struct interface *ifp; |
| struct ospf6_interface *oi; |
| |
| ifp = if_lookup_by_name(argv[idx_ifname]->arg, VRF_DEFAULT); |
| if (ifp == NULL) { |
| vty_out(vty, "No such Interface: %s\n", argv[idx_ifname]->arg); |
| return CMD_WARNING; |
| } |
| |
| oi = ifp->info; |
| if (oi == NULL) { |
| vty_out(vty, "OSPFv3 is not enabled on %s\n", |
| argv[idx_ifname]->arg); |
| return CMD_WARNING; |
| } |
| |
| ospf6_route_table_show(vty, idx_prefix, argc, argv, |
| oi->route_connected); |
| |
| return CMD_SUCCESS; |
| } |
| |
| DEFUN (show_ipv6_ospf6_interface_prefix, |
| show_ipv6_ospf6_interface_prefix_cmd, |
| "show ipv6 ospf6 interface prefix\ |
| [<\ |
| detail\ |
| |<X:X::X:X|X:X::X:X/M> [<match|detail>]\ |
| >]", |
| SHOW_STR |
| IP6_STR |
| OSPF6_STR |
| INTERFACE_STR |
| "Display connected prefixes to advertise\n" |
| "Display details of the prefixes\n" |
| OSPF6_ROUTE_ADDRESS_STR |
| OSPF6_ROUTE_PREFIX_STR |
| OSPF6_ROUTE_MATCH_STR |
| "Display details of the prefixes\n") |
| { |
| struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); |
| int idx_prefix = 5; |
| struct ospf6_interface *oi; |
| struct interface *ifp; |
| |
| FOR_ALL_INTERFACES (vrf, ifp) { |
| oi = (struct ospf6_interface *)ifp->info; |
| if (oi == NULL) |
| continue; |
| |
| ospf6_route_table_show(vty, idx_prefix, argc, argv, |
| oi->route_connected); |
| } |
| |
| return CMD_SUCCESS; |
| } |
| |
| |
| DEFUN (ipv6_ospf6_ifmtu, |
| ipv6_ospf6_ifmtu_cmd, |
| "ipv6 ospf6 ifmtu (1-65535)", |
| IP6_STR |
| OSPF6_STR |
| "Interface MTU\n" |
| "OSPFv3 Interface MTU\n" |
| ) |
| { |
| VTY_DECLVAR_CONTEXT(interface, ifp); |
| int idx_number = 3; |
| struct ospf6_interface *oi; |
| unsigned int ifmtu, iobuflen; |
| struct listnode *node, *nnode; |
| struct ospf6_neighbor *on; |
| |
| assert(ifp); |
| |
| oi = (struct ospf6_interface *)ifp->info; |
| if (oi == NULL) |
| oi = ospf6_interface_create(ifp); |
| assert(oi); |
| |
| ifmtu = strtol(argv[idx_number]->arg, NULL, 10); |
| |
| if (oi->c_ifmtu == ifmtu) |
| return CMD_SUCCESS; |
| |
| if (ifp->mtu6 != 0 && ifp->mtu6 < ifmtu) { |
| vty_out(vty, |
| "%s's ospf6 ifmtu cannot go beyond physical mtu (%d)\n", |
| ifp->name, ifp->mtu6); |
| return CMD_WARNING_CONFIG_FAILED; |
| } |
| |
| if (oi->ifmtu < ifmtu) { |
| iobuflen = ospf6_iobuf_size(ifmtu); |
| if (iobuflen < ifmtu) { |
| vty_out(vty, |
| "%s's ifmtu is adjusted to I/O buffer size (%d).\n", |
| ifp->name, iobuflen); |
| oi->ifmtu = oi->c_ifmtu = iobuflen; |
| } else |
| oi->ifmtu = oi->c_ifmtu = ifmtu; |
| } else |
| oi->ifmtu = oi->c_ifmtu = ifmtu; |
| |
| |
| for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) { |
| THREAD_OFF(on->inactivity_timer); |
| thread_add_event(master, inactivity_timer, on, 0, NULL); |
| } |
| |
| return CMD_SUCCESS; |
| } |
| |
| DEFUN (no_ipv6_ospf6_ifmtu, |
| no_ipv6_ospf6_ifmtu_cmd, |
| "no ipv6 ospf6 ifmtu [(1-65535)]", |
| NO_STR |
| IP6_STR |
| OSPF6_STR |
| "Interface MTU\n" |
| "OSPFv3 Interface MTU\n" |
| ) |
| { |
| VTY_DECLVAR_CONTEXT(interface, ifp); |
| struct ospf6_interface *oi; |
| unsigned int iobuflen; |
| struct listnode *node, *nnode; |
| struct ospf6_neighbor *on; |
| |
| assert(ifp); |
| |
| oi = (struct ospf6_interface *)ifp->info; |
| if (oi == NULL) |
| oi = ospf6_interface_create(ifp); |
| assert(oi); |
| |
| if (oi->ifmtu < ifp->mtu) { |
| iobuflen = ospf6_iobuf_size(ifp->mtu); |
| if (iobuflen < ifp->mtu) { |
| vty_out(vty, |
| "%s's ifmtu is adjusted to I/O buffer size (%d).\n", |
| ifp->name, iobuflen); |
| oi->ifmtu = iobuflen; |
| } else |
| oi->ifmtu = ifp->mtu; |
| } else |
| oi->ifmtu = ifp->mtu; |
| |
| oi->c_ifmtu = 0; |
| |
| |
| for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) { |
| THREAD_OFF(on->inactivity_timer); |
| thread_add_event(master, inactivity_timer, on, 0, NULL); |
| } |
| |
| return CMD_SUCCESS; |
| } |
| |
| DEFUN (ipv6_ospf6_cost, |
| ipv6_ospf6_cost_cmd, |
| "ipv6 ospf6 cost (1-65535)", |
| IP6_STR |
| OSPF6_STR |
| "Interface cost\n" |
| "Outgoing metric of this interface\n") |
| { |
| VTY_DECLVAR_CONTEXT(interface, ifp); |
| int idx_number = 3; |
| struct ospf6_interface *oi; |
| unsigned long int lcost; |
| |
| assert(ifp); |
| |
| oi = (struct ospf6_interface *)ifp->info; |
| if (oi == NULL) |
| oi = ospf6_interface_create(ifp); |
| assert(oi); |
| |
| lcost = strtol(argv[idx_number]->arg, NULL, 10); |
| |
| if (lcost > UINT32_MAX) { |
| vty_out(vty, "Cost %ld is out of range\n", lcost); |
| return CMD_WARNING_CONFIG_FAILED; |
| } |
| |
| if (oi->cost == lcost) |
| return CMD_SUCCESS; |
| |
| oi->cost = lcost; |
| SET_FLAG(oi->flag, OSPF6_INTERFACE_NOAUTOCOST); |
| |
| ospf6_interface_force_recalculate_cost(oi); |
| |
| return CMD_SUCCESS; |
| } |
| |
| DEFUN (no_ipv6_ospf6_cost, |
| no_ipv6_ospf6_cost_cmd, |
| "no ipv6 ospf6 cost [(1-65535)]", |
| NO_STR |
| IP6_STR |
| OSPF6_STR |
| "Calculate interface cost from bandwidth\n" |
| "Outgoing metric of this interface\n") |
| { |
| VTY_DECLVAR_CONTEXT(interface, ifp); |
| struct ospf6_interface *oi; |
| assert(ifp); |
| |
| oi = (struct ospf6_interface *)ifp->info; |
| if (oi == NULL) |
| oi = ospf6_interface_create(ifp); |
| assert(oi); |
| |
| UNSET_FLAG(oi->flag, OSPF6_INTERFACE_NOAUTOCOST); |
| |
| ospf6_interface_recalculate_cost(oi); |
| |
| return CMD_SUCCESS; |
| } |
| |
| DEFUN (auto_cost_reference_bandwidth, |
| auto_cost_reference_bandwidth_cmd, |
| "auto-cost reference-bandwidth (1-4294967)", |
| "Calculate OSPF interface cost according to bandwidth\n" |
| "Use reference bandwidth method to assign OSPF cost\n" |
| "The reference bandwidth in terms of Mbits per second\n") |
| { |
| VTY_DECLVAR_CONTEXT(ospf6, o); |
| int idx_number = 2; |
| struct ospf6_area *oa; |
| struct ospf6_interface *oi; |
| struct listnode *i, *j; |
| uint32_t refbw; |
| |
| refbw = strtol(argv[idx_number]->arg, NULL, 10); |
| if (refbw < 1 || refbw > 4294967) { |
| vty_out(vty, "reference-bandwidth value is invalid\n"); |
| return CMD_WARNING_CONFIG_FAILED; |
| } |
| |
| |
| if ((refbw) == o->ref_bandwidth) |
| return CMD_SUCCESS; |
| |
| o->ref_bandwidth = refbw; |
| for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) |
| for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) |
| ospf6_interface_recalculate_cost(oi); |
| |
| return CMD_SUCCESS; |
| } |
| |
| DEFUN (no_auto_cost_reference_bandwidth, |
| no_auto_cost_reference_bandwidth_cmd, |
| "no auto-cost reference-bandwidth [(1-4294967)]", |
| NO_STR |
| "Calculate OSPF interface cost according to bandwidth\n" |
| "Use reference bandwidth method to assign OSPF cost\n" |
| "The reference bandwidth in terms of Mbits per second\n") |
| { |
| VTY_DECLVAR_CONTEXT(ospf6, o); |
| struct ospf6_area *oa; |
| struct ospf6_interface *oi; |
| struct listnode *i, *j; |
| |
| if (o->ref_bandwidth == OSPF6_REFERENCE_BANDWIDTH) |
| return CMD_SUCCESS; |
| |
| o->ref_bandwidth = OSPF6_REFERENCE_BANDWIDTH; |
| for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) |
| for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) |
| ospf6_interface_recalculate_cost(oi); |
| |
| return CMD_SUCCESS; |
| } |
| |
| |
| DEFUN (ipv6_ospf6_hellointerval, |
| ipv6_ospf6_hellointerval_cmd, |
| "ipv6 ospf6 hello-interval (1-65535)", |
| IP6_STR |
| OSPF6_STR |
| "Time between HELLO packets\n" |
| SECONDS_STR) |
| { |
| VTY_DECLVAR_CONTEXT(interface, ifp); |
| int idx_number = 3; |
| struct ospf6_interface *oi; |
| assert(ifp); |
| |
| oi = (struct ospf6_interface *)ifp->info; |
| if (oi == NULL) |
| oi = ospf6_interface_create(ifp); |
| assert(oi); |
| |
| oi->hello_interval = strmatch(argv[0]->text, "no") |
| ? OSPF_HELLO_INTERVAL_DEFAULT |
| : strtoul(argv[idx_number]->arg, NULL, 10); |
| return CMD_SUCCESS; |
| } |
| |
| ALIAS (ipv6_ospf6_hellointerval, |
| no_ipv6_ospf6_hellointerval_cmd, |
| "no ipv6 ospf6 hello-interval [(1-65535)]", |
| NO_STR |
| IP6_STR |
| OSPF6_STR |
| "Time between HELLO packets\n" |
| SECONDS_STR) |
| |
| |
| DEFUN (ipv6_ospf6_deadinterval, |
| ipv6_ospf6_deadinterval_cmd, |
| "ipv6 ospf6 dead-interval (1-65535)", |
| IP6_STR |
| OSPF6_STR |
| "Interval time after which a neighbor is declared down\n" |
| SECONDS_STR) |
| { |
| VTY_DECLVAR_CONTEXT(interface, ifp); |
| int idx_number = 3; |
| struct ospf6_interface *oi; |
| assert(ifp); |
| |
| oi = (struct ospf6_interface *)ifp->info; |
| if (oi == NULL) |
| oi = ospf6_interface_create(ifp); |
| assert(oi); |
| |
| oi->dead_interval = strmatch(argv[0]->arg, "no") |
| ? OSPF_ROUTER_DEAD_INTERVAL_DEFAULT |
| : strtoul(argv[idx_number]->arg, NULL, 10); |
| return CMD_SUCCESS; |
| } |
| |
| ALIAS (ipv6_ospf6_deadinterval, |
| no_ipv6_ospf6_deadinterval_cmd, |
| "no ipv6 ospf6 dead-interval [(1-65535)]", |
| NO_STR |
| IP6_STR |
| OSPF6_STR |
| "Interval time after which a neighbor is declared down\n" |
| SECONDS_STR) |
| |
| |
| DEFUN (ipv6_ospf6_transmitdelay, |
| ipv6_ospf6_transmitdelay_cmd, |
| "ipv6 ospf6 transmit-delay (1-3600)", |
| IP6_STR |
| OSPF6_STR |
| "Link state transmit delay\n" |
| SECONDS_STR) |
| { |
| VTY_DECLVAR_CONTEXT(interface, ifp); |
| int idx_number = 3; |
| struct ospf6_interface *oi; |
| assert(ifp); |
| |
| oi = (struct ospf6_interface *)ifp->info; |
| if (oi == NULL) |
| oi = ospf6_interface_create(ifp); |
| assert(oi); |
| |
| oi->transdelay = strmatch(argv[0]->text, "no") |
| ? OSPF6_INTERFACE_TRANSDELAY |
| : strtoul(argv[idx_number]->arg, NULL, 10); |
| return CMD_SUCCESS; |
| } |
| |
| ALIAS (ipv6_ospf6_transmitdelay, |
| no_ipv6_ospf6_transmitdelay_cmd, |
| "no ipv6 ospf6 transmit-delay [(1-3600)]", |
| NO_STR |
| IP6_STR |
| OSPF6_STR |
| "Link state transmit delay\n" |
| SECONDS_STR) |
| |
| |
| DEFUN (ipv6_ospf6_retransmitinterval, |
| ipv6_ospf6_retransmitinterval_cmd, |
| "ipv6 ospf6 retransmit-interval (1-65535)", |
| IP6_STR |
| OSPF6_STR |
| "Time between retransmitting lost link state advertisements\n" |
| SECONDS_STR) |
| { |
| VTY_DECLVAR_CONTEXT(interface, ifp); |
| int idx_number = 3; |
| struct ospf6_interface *oi; |
| assert(ifp); |
| |
| oi = (struct ospf6_interface *)ifp->info; |
| if (oi == NULL) |
| oi = ospf6_interface_create(ifp); |
| assert(oi); |
| |
| oi->rxmt_interval = strmatch(argv[0]->text, "no") |
| ? OSPF_RETRANSMIT_INTERVAL_DEFAULT |
| : strtoul(argv[idx_number]->arg, NULL, 10); |
| return CMD_SUCCESS; |
| } |
| |
| ALIAS (ipv6_ospf6_retransmitinterval, |
| no_ipv6_ospf6_retransmitinterval_cmd, |
| "no ipv6 ospf6 retransmit-interval [(1-65535)]", |
| NO_STR |
| IP6_STR |
| OSPF6_STR |
| "Time between retransmitting lost link state advertisements\n" |
| SECONDS_STR) |
| |
| |
| DEFUN (ipv6_ospf6_priority, |
| ipv6_ospf6_priority_cmd, |
| "ipv6 ospf6 priority (0-255)", |
| IP6_STR |
| OSPF6_STR |
| "Router priority\n" |
| "Priority value\n") |
| { |
| VTY_DECLVAR_CONTEXT(interface, ifp); |
| int idx_number = 3; |
| struct ospf6_interface *oi; |
| assert(ifp); |
| |
| oi = (struct ospf6_interface *)ifp->info; |
| if (oi == NULL) |
| oi = ospf6_interface_create(ifp); |
| assert(oi); |
| |
| oi->priority = strmatch(argv[0]->text, "no") |
| ? OSPF6_INTERFACE_PRIORITY |
| : strtoul(argv[idx_number]->arg, NULL, 10); |
| |
| if (oi->area && (oi->state == OSPF6_INTERFACE_DROTHER |
| || oi->state == OSPF6_INTERFACE_BDR |
| || oi->state == OSPF6_INTERFACE_DR)) |
| ospf6_interface_state_change(dr_election(oi), oi); |
| |
| return CMD_SUCCESS; |
| } |
| |
| ALIAS (ipv6_ospf6_priority, |
| no_ipv6_ospf6_priority_cmd, |
| "no ipv6 ospf6 priority [(0-255)]", |
| NO_STR |
| IP6_STR |
| OSPF6_STR |
| "Router priority\n" |
| "Priority value\n") |
| |
| DEFUN (ipv6_ospf6_instance, |
| ipv6_ospf6_instance_cmd, |
| "ipv6 ospf6 instance-id (0-255)", |
| IP6_STR |
| OSPF6_STR |
| "Instance ID for this interface\n" |
| "Instance ID value\n") |
| { |
| VTY_DECLVAR_CONTEXT(interface, ifp); |
| int idx_number = 3; |
| struct ospf6_interface *oi; |
| assert(ifp); |
| |
| oi = (struct ospf6_interface *)ifp->info; |
| if (oi == NULL) |
| oi = ospf6_interface_create(ifp); |
| assert(oi); |
| |
| oi->instance_id = strmatch(argv[0]->text, "no") |
| ? OSPF6_INTERFACE_INSTANCE_ID |
| : strtoul(argv[idx_number]->arg, NULL, 10); |
| return CMD_SUCCESS; |
| } |
| |
| ALIAS (ipv6_ospf6_instance, |
| no_ipv6_ospf6_instance_cmd, |
| "no ipv6 ospf6 instance-id [(0-255)]", |
| NO_STR |
| IP6_STR |
| OSPF6_STR |
| "Instance ID for this interface\n" |
| "Instance ID value\n") |
| |
| DEFUN (ipv6_ospf6_passive, |
| ipv6_ospf6_passive_cmd, |
| "ipv6 ospf6 passive", |
| IP6_STR |
| OSPF6_STR |
| "Passive interface; no adjacency will be formed on this interface\n" |
| ) |
| { |
| VTY_DECLVAR_CONTEXT(interface, ifp); |
| struct ospf6_interface *oi; |
| struct listnode *node, *nnode; |
| struct ospf6_neighbor *on; |
| |
| assert(ifp); |
| |
| oi = (struct ospf6_interface *)ifp->info; |
| if (oi == NULL) |
| oi = ospf6_interface_create(ifp); |
| assert(oi); |
| |
| SET_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE); |
| THREAD_OFF(oi->thread_send_hello); |
| THREAD_OFF(oi->thread_sso); |
| |
| for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) { |
| THREAD_OFF(on->inactivity_timer); |
| thread_add_event(master, inactivity_timer, on, 0, NULL); |
| } |
| |
| return CMD_SUCCESS; |
| } |
| |
| DEFUN (no_ipv6_ospf6_passive, |
| no_ipv6_ospf6_passive_cmd, |
| "no ipv6 ospf6 passive", |
| NO_STR |
| IP6_STR |
| OSPF6_STR |
| "passive interface: No Adjacency will be formed on this I/F\n" |
| ) |
| { |
| VTY_DECLVAR_CONTEXT(interface, ifp); |
| struct ospf6_interface *oi; |
| assert(ifp); |
| |
| oi = (struct ospf6_interface *)ifp->info; |
| if (oi == NULL) |
| oi = ospf6_interface_create(ifp); |
| assert(oi); |
| |
| UNSET_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE); |
| THREAD_OFF(oi->thread_send_hello); |
| THREAD_OFF(oi->thread_sso); |
| thread_add_event(master, ospf6_hello_send, oi, 0, |
| &oi->thread_send_hello); |
| |
| return CMD_SUCCESS; |
| } |
| |
| DEFUN (ipv6_ospf6_mtu_ignore, |
| ipv6_ospf6_mtu_ignore_cmd, |
| "ipv6 ospf6 mtu-ignore", |
| IP6_STR |
| OSPF6_STR |
| "Disable MTU mismatch detection on this interface\n" |
| ) |
| { |
| VTY_DECLVAR_CONTEXT(interface, ifp); |
| struct ospf6_interface *oi; |
| assert(ifp); |
| |
| oi = (struct ospf6_interface *)ifp->info; |
| if (oi == NULL) |
| oi = ospf6_interface_create(ifp); |
| assert(oi); |
| |
| oi->mtu_ignore = 1; |
| |
| return CMD_SUCCESS; |
| } |
| |
| DEFUN (no_ipv6_ospf6_mtu_ignore, |
| no_ipv6_ospf6_mtu_ignore_cmd, |
| "no ipv6 ospf6 mtu-ignore", |
| NO_STR |
| IP6_STR |
| OSPF6_STR |
| "Disable MTU mismatch detection on this interface\n" |
| ) |
| { |
| VTY_DECLVAR_CONTEXT(interface, ifp); |
| struct ospf6_interface *oi; |
| assert(ifp); |
| |
| oi = (struct ospf6_interface *)ifp->info; |
| if (oi == NULL) |
| oi = ospf6_interface_create(ifp); |
| assert(oi); |
| |
| oi->mtu_ignore = 0; |
| |
| return CMD_SUCCESS; |
| } |
| |
| DEFUN (ipv6_ospf6_advertise_prefix_list, |
| ipv6_ospf6_advertise_prefix_list_cmd, |
| "ipv6 ospf6 advertise prefix-list WORD", |
| IP6_STR |
| OSPF6_STR |
| "Advertising options\n" |
| "Filter prefix using prefix-list\n" |
| "Prefix list name\n" |
| ) |
| { |
| VTY_DECLVAR_CONTEXT(interface, ifp); |
| int idx_word = 4; |
| struct ospf6_interface *oi; |
| assert(ifp); |
| |
| oi = (struct ospf6_interface *)ifp->info; |
| if (oi == NULL) |
| oi = ospf6_interface_create(ifp); |
| assert(oi); |
| |
| if (oi->plist_name) |
| XFREE(MTYPE_CFG_PLIST_NAME, oi->plist_name); |
| oi->plist_name = XSTRDUP(MTYPE_CFG_PLIST_NAME, argv[idx_word]->arg); |
| |
| ospf6_interface_connected_route_update(oi->interface); |
| |
| if (oi->area) { |
| OSPF6_LINK_LSA_SCHEDULE(oi); |
| if (oi->state == OSPF6_INTERFACE_DR) { |
| OSPF6_NETWORK_LSA_SCHEDULE(oi); |
| OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi); |
| } |
| OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area); |
| } |
| |
| return CMD_SUCCESS; |
| } |
| |
| DEFUN (no_ipv6_ospf6_advertise_prefix_list, |
| no_ipv6_ospf6_advertise_prefix_list_cmd, |
| "no ipv6 ospf6 advertise prefix-list [WORD]", |
| NO_STR |
| IP6_STR |
| OSPF6_STR |
| "Advertising options\n" |
| "Filter prefix using prefix-list\n" |
| "Prefix list name\n") |
| { |
| VTY_DECLVAR_CONTEXT(interface, ifp); |
| struct ospf6_interface *oi; |
| assert(ifp); |
| |
| oi = (struct ospf6_interface *)ifp->info; |
| if (oi == NULL) |
| oi = ospf6_interface_create(ifp); |
| assert(oi); |
| |
| if (oi->plist_name) |
| XFREE(MTYPE_CFG_PLIST_NAME, oi->plist_name); |
| |
| ospf6_interface_connected_route_update(oi->interface); |
| |
| if (oi->area) { |
| OSPF6_LINK_LSA_SCHEDULE(oi); |
| if (oi->state == OSPF6_INTERFACE_DR) { |
| OSPF6_NETWORK_LSA_SCHEDULE(oi); |
| OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi); |
| } |
| OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area); |
| } |
| |
| return CMD_SUCCESS; |
| } |
| |
| DEFUN (ipv6_ospf6_network, |
| ipv6_ospf6_network_cmd, |
| "ipv6 ospf6 network <broadcast|point-to-point>", |
| IP6_STR |
| OSPF6_STR |
| "Network type\n" |
| "Specify OSPF6 broadcast network\n" |
| "Specify OSPF6 point-to-point network\n" |
| ) |
| { |
| VTY_DECLVAR_CONTEXT(interface, ifp); |
| int idx_network = 3; |
| struct ospf6_interface *oi; |
| assert(ifp); |
| |
| oi = (struct ospf6_interface *)ifp->info; |
| if (oi == NULL) { |
| oi = ospf6_interface_create(ifp); |
| } |
| assert(oi); |
| |
| oi->type_cfg = true; |
| |
| if (strncmp(argv[idx_network]->arg, "b", 1) == 0) { |
| if (oi->type == OSPF_IFTYPE_BROADCAST) |
| return CMD_SUCCESS; |
| |
| oi->type = OSPF_IFTYPE_BROADCAST; |
| } else if (strncmp(argv[idx_network]->arg, "point-to-p", 10) == 0) { |
| if (oi->type == OSPF_IFTYPE_POINTOPOINT) { |
| return CMD_SUCCESS; |
| } |
| oi->type = OSPF_IFTYPE_POINTOPOINT; |
| } |
| |
| |
| thread_execute(master, interface_down, oi, 0); |
| thread_execute(master, interface_up, oi, 0); |
| |
| return CMD_SUCCESS; |
| } |
| |
| DEFUN (no_ipv6_ospf6_network, |
| no_ipv6_ospf6_network_cmd, |
| "no ipv6 ospf6 network [<broadcast|point-to-point>]", |
| NO_STR |
| IP6_STR |
| OSPF6_STR |
| "Set default network type\n" |
| "Specify OSPF6 broadcast network\n" |
| "Specify OSPF6 point-to-point network\n") |
| { |
| VTY_DECLVAR_CONTEXT(interface, ifp); |
| struct ospf6_interface *oi; |
| int type; |
| |
| assert(ifp); |
| |
| oi = (struct ospf6_interface *)ifp->info; |
| if (oi == NULL) { |
| return CMD_SUCCESS; |
| } |
| |
| oi->type_cfg = false; |
| |
| type = ospf6_default_iftype(ifp); |
| if (oi->type == type) { |
| return CMD_SUCCESS; |
| } |
| oi->type = type; |
| |
| |
| thread_execute(master, interface_down, oi, 0); |
| thread_execute(master, interface_up, oi, 0); |
| |
| return CMD_SUCCESS; |
| } |
| |
| static int config_write_ospf6_interface(struct vty *vty) |
| { |
| struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); |
| struct ospf6_interface *oi; |
| struct interface *ifp; |
| |
| FOR_ALL_INTERFACES (vrf, ifp) { |
| oi = (struct ospf6_interface *)ifp->info; |
| if (oi == NULL) |
| continue; |
| |
| vty_frame(vty, "interface %s\n", oi->interface->name); |
| |
| if (ifp->desc) |
| vty_out(vty, " description %s\n", ifp->desc); |
| if (oi->c_ifmtu) |
| vty_out(vty, " ipv6 ospf6 ifmtu %d\n", oi->c_ifmtu); |
| |
| if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_NOAUTOCOST)) |
| vty_out(vty, " ipv6 ospf6 cost %d\n", oi->cost); |
| |
| if (oi->hello_interval != OSPF6_INTERFACE_HELLO_INTERVAL) |
| vty_out(vty, " ipv6 ospf6 hello-interval %d\n", |
| oi->hello_interval); |
| |
| if (oi->dead_interval != OSPF6_INTERFACE_DEAD_INTERVAL) |
| vty_out(vty, " ipv6 ospf6 dead-interval %d\n", |
| oi->dead_interval); |
| |
| if (oi->rxmt_interval != OSPF6_INTERFACE_RXMT_INTERVAL) |
| vty_out(vty, " ipv6 ospf6 retransmit-interval %d\n", |
| oi->rxmt_interval); |
| |
| if (oi->priority != OSPF6_INTERFACE_PRIORITY) |
| vty_out(vty, " ipv6 ospf6 priority %d\n", oi->priority); |
| |
| if (oi->transdelay != OSPF6_INTERFACE_TRANSDELAY) |
| vty_out(vty, " ipv6 ospf6 transmit-delay %d\n", |
| oi->transdelay); |
| |
| if (oi->instance_id != OSPF6_INTERFACE_INSTANCE_ID) |
| vty_out(vty, " ipv6 ospf6 instance-id %d\n", |
| oi->instance_id); |
| |
| if (oi->plist_name) |
| vty_out(vty, " ipv6 ospf6 advertise prefix-list %s\n", |
| oi->plist_name); |
| |
| if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE)) |
| vty_out(vty, " ipv6 ospf6 passive\n"); |
| |
| if (oi->mtu_ignore) |
| vty_out(vty, " ipv6 ospf6 mtu-ignore\n"); |
| |
| if (oi->type_cfg && oi->type == OSPF_IFTYPE_POINTOPOINT) |
| vty_out(vty, " ipv6 ospf6 network point-to-point\n"); |
| else if (oi->type_cfg && oi->type == OSPF_IFTYPE_BROADCAST) |
| vty_out(vty, " ipv6 ospf6 network broadcast\n"); |
| |
| ospf6_bfd_write_config(vty, oi); |
| |
| vty_endframe(vty, "!\n"); |
| } |
| return 0; |
| } |
| |
| static int config_write_ospf6_interface(struct vty *vty); |
| static struct cmd_node interface_node = { |
| .name = "interface", |
| .node = INTERFACE_NODE, |
| .parent_node = CONFIG_NODE, |
| .prompt = "%s(config-if)# ", |
| .config_write = config_write_ospf6_interface, |
| }; |
| |
| static int ospf6_ifp_create(struct interface *ifp) |
| { |
| if (IS_OSPF6_DEBUG_ZEBRA(RECV)) |
| zlog_debug("Zebra Interface add: %s index %d mtu %d", ifp->name, |
| ifp->ifindex, ifp->mtu6); |
| ospf6_interface_if_add(ifp); |
| |
| return 0; |
| } |
| |
| static int ospf6_ifp_up(struct interface *ifp) |
| { |
| if (IS_OSPF6_DEBUG_ZEBRA(RECV)) |
| zlog_debug( |
| "Zebra Interface state change: %s index %d flags %llx metric %d mtu %d bandwidth %d", |
| ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, |
| ifp->metric, ifp->mtu6, ifp->bandwidth); |
| |
| ospf6_interface_state_update(ifp); |
| |
| return 0; |
| } |
| |
| static int ospf6_ifp_down(struct interface *ifp) |
| { |
| if (IS_OSPF6_DEBUG_ZEBRA(RECV)) |
| zlog_debug( |
| "Zebra Interface state change: %s index %d flags %llx metric %d mtu %d bandwidth %d", |
| ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, |
| ifp->metric, ifp->mtu6, ifp->bandwidth); |
| |
| ospf6_interface_state_update(ifp); |
| |
| return 0; |
| } |
| |
| static int ospf6_ifp_destroy(struct interface *ifp) |
| { |
| if (if_is_up(ifp)) |
| zlog_warn("Zebra: got delete of %s, but interface is still up", |
| ifp->name); |
| |
| if (IS_OSPF6_DEBUG_ZEBRA(RECV)) |
| zlog_debug("Zebra Interface delete: %s index %d mtu %d", |
| ifp->name, ifp->ifindex, ifp->mtu6); |
| |
| return 0; |
| } |
| |
| void ospf6_interface_init(void) |
| { |
| |
| install_node(&interface_node); |
| if_cmd_init(); |
| if_zapi_callbacks(ospf6_ifp_create, ospf6_ifp_up, |
| ospf6_ifp_down, ospf6_ifp_destroy); |
| |
| install_element(VIEW_NODE, &show_ipv6_ospf6_interface_prefix_cmd); |
| install_element(VIEW_NODE, &show_ipv6_ospf6_interface_ifname_cmd); |
| install_element(VIEW_NODE, |
| &show_ipv6_ospf6_interface_ifname_prefix_cmd); |
| install_element(VIEW_NODE, &show_ipv6_ospf6_interface_traffic_cmd); |
| |
| install_element(INTERFACE_NODE, &ipv6_ospf6_cost_cmd); |
| install_element(INTERFACE_NODE, &no_ipv6_ospf6_cost_cmd); |
| install_element(INTERFACE_NODE, &ipv6_ospf6_ifmtu_cmd); |
| install_element(INTERFACE_NODE, &no_ipv6_ospf6_ifmtu_cmd); |
| |
| install_element(INTERFACE_NODE, &ipv6_ospf6_deadinterval_cmd); |
| install_element(INTERFACE_NODE, &ipv6_ospf6_hellointerval_cmd); |
| install_element(INTERFACE_NODE, &ipv6_ospf6_priority_cmd); |
| install_element(INTERFACE_NODE, &ipv6_ospf6_retransmitinterval_cmd); |
| install_element(INTERFACE_NODE, &ipv6_ospf6_transmitdelay_cmd); |
| install_element(INTERFACE_NODE, &ipv6_ospf6_instance_cmd); |
| install_element(INTERFACE_NODE, &no_ipv6_ospf6_deadinterval_cmd); |
| install_element(INTERFACE_NODE, &no_ipv6_ospf6_hellointerval_cmd); |
| install_element(INTERFACE_NODE, &no_ipv6_ospf6_priority_cmd); |
| install_element(INTERFACE_NODE, &no_ipv6_ospf6_retransmitinterval_cmd); |
| install_element(INTERFACE_NODE, &no_ipv6_ospf6_transmitdelay_cmd); |
| install_element(INTERFACE_NODE, &no_ipv6_ospf6_instance_cmd); |
| |
| install_element(INTERFACE_NODE, &ipv6_ospf6_passive_cmd); |
| install_element(INTERFACE_NODE, &no_ipv6_ospf6_passive_cmd); |
| |
| install_element(INTERFACE_NODE, &ipv6_ospf6_mtu_ignore_cmd); |
| install_element(INTERFACE_NODE, &no_ipv6_ospf6_mtu_ignore_cmd); |
| |
| install_element(INTERFACE_NODE, &ipv6_ospf6_advertise_prefix_list_cmd); |
| install_element(INTERFACE_NODE, |
| &no_ipv6_ospf6_advertise_prefix_list_cmd); |
| |
| install_element(INTERFACE_NODE, &ipv6_ospf6_network_cmd); |
| install_element(INTERFACE_NODE, &no_ipv6_ospf6_network_cmd); |
| |
| |
| install_element(OSPF6_NODE, &auto_cost_reference_bandwidth_cmd); |
| install_element(OSPF6_NODE, &no_auto_cost_reference_bandwidth_cmd); |
| } |
| |
| |
| static void ospf6_interface_clear(struct vty *vty, struct interface *ifp) |
| { |
| struct ospf6_interface *oi; |
| |
| if (!if_is_operative(ifp)) |
| return; |
| |
| if (ifp->info == NULL) |
| return; |
| |
| oi = (struct ospf6_interface *)ifp->info; |
| |
| if (IS_OSPF6_DEBUG_INTERFACE) |
| zlog_debug("Interface %s: clear by reset", ifp->name); |
| |
| |
| thread_execute(master, interface_down, oi, 0); |
| thread_execute(master, interface_up, oi, 0); |
| } |
| |
| |
| DEFUN (clear_ipv6_ospf6_interface, |
| clear_ipv6_ospf6_interface_cmd, |
| "clear ipv6 ospf6 interface [IFNAME]", |
| CLEAR_STR |
| IP6_STR |
| OSPF6_STR |
| INTERFACE_STR |
| IFNAME_STR |
| ) |
| { |
| struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); |
| int idx_ifname = 4; |
| struct interface *ifp; |
| |
| if (argc == 4) |
| { |
| FOR_ALL_INTERFACES (vrf, ifp) |
| ospf6_interface_clear(vty, ifp); |
| } else |
| { |
| if ((ifp = if_lookup_by_name(argv[idx_ifname]->arg, |
| VRF_DEFAULT)) |
| == NULL) { |
| vty_out(vty, "No such Interface: %s\n", |
| argv[idx_ifname]->arg); |
| return CMD_WARNING; |
| } |
| ospf6_interface_clear(vty, ifp); |
| } |
| |
| return CMD_SUCCESS; |
| } |
| |
| void install_element_ospf6_clear_interface(void) |
| { |
| install_element(ENABLE_NODE, &clear_ipv6_ospf6_interface_cmd); |
| } |
| |
| DEFUN (debug_ospf6_interface, |
| debug_ospf6_interface_cmd, |
| "debug ospf6 interface", |
| DEBUG_STR |
| OSPF6_STR |
| "Debug OSPFv3 Interface\n" |
| ) |
| { |
| OSPF6_DEBUG_INTERFACE_ON(); |
| return CMD_SUCCESS; |
| } |
| |
| DEFUN (no_debug_ospf6_interface, |
| no_debug_ospf6_interface_cmd, |
| "no debug ospf6 interface", |
| NO_STR |
| DEBUG_STR |
| OSPF6_STR |
| "Debug OSPFv3 Interface\n" |
| ) |
| { |
| OSPF6_DEBUG_INTERFACE_OFF(); |
| return CMD_SUCCESS; |
| } |
| |
| int config_write_ospf6_debug_interface(struct vty *vty) |
| { |
| if (IS_OSPF6_DEBUG_INTERFACE) |
| vty_out(vty, "debug ospf6 interface\n"); |
| return 0; |
| } |
| |
| void install_element_ospf6_debug_interface(void) |
| { |
| install_element(ENABLE_NODE, &debug_ospf6_interface_cmd); |
| install_element(ENABLE_NODE, &no_debug_ospf6_interface_cmd); |
| install_element(CONFIG_NODE, &debug_ospf6_interface_cmd); |
| install_element(CONFIG_NODE, &no_debug_ospf6_interface_cmd); |
| } |