diff options
Diffstat (limited to 'ospf6d/ospf6_interface.c')
| -rw-r--r-- | ospf6d/ospf6_interface.c | 696 |
1 files changed, 516 insertions, 180 deletions
diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index 621cc36a0c..a169b9c60e 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -36,6 +36,7 @@ #include "ospf6_message.h" #include "ospf6_route.h" #include "ospf6_area.h" +#include "ospf6_abr.h" #include "ospf6_interface.h" #include "ospf6_neighbor.h" #include "ospf6_intra.h" @@ -45,11 +46,12 @@ #include "ospf6_zebra.h" #include "lib/json.h" -DEFINE_MTYPE_STATIC(OSPF6D, CFG_PLIST_NAME, "configured prefix list names") -DEFINE_QOBJ_TYPE(ospf6_interface) +DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_IF, "OSPF6 interface"); +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)) + (oi, state, old_state)); unsigned char conf_debug_ospf6_interface = 0; @@ -108,7 +110,7 @@ static uint8_t ospf6_default_iftype(struct interface *ifp) { if (if_is_pointopoint(ifp)) return OSPF_IFTYPE_POINTOPOINT; - else if (if_is_loopback(ifp)) + else if (if_is_loopback_or_vrf(ifp)) return OSPF_IFTYPE_LOOPBACK; else return OSPF_IFTYPE_BROADCAST; @@ -183,6 +185,8 @@ struct ospf6_interface *ospf6_interface_create(struct interface *ifp) oi = XCALLOC(MTYPE_OSPF6_IF, sizeof(struct ospf6_interface)); + oi->obuf = ospf6_fifo_new(); + oi->area = (struct ospf6_area *)NULL; oi->neighbor_list = list_new(); oi->neighbor_list->cmp = ospf6_neighbor_cmp; @@ -241,6 +245,8 @@ void ospf6_interface_delete(struct ospf6_interface *oi) QOBJ_UNREG(oi); + ospf6_fifo_free(oi->obuf); + for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) ospf6_neighbor_delete(on); @@ -271,11 +277,12 @@ void ospf6_interface_delete(struct ospf6_interface *oi) if (oi->plist_name) XFREE(MTYPE_CFG_PLIST_NAME, oi->plist_name); - ospf6_bfd_info_free(&(oi->bfd_info)); - /* disable from area list if possible */ ospf6_area_interface_delete(oi); + /* Free BFD allocated data. */ + XFREE(MTYPE_TMP, oi->bfd_config.profile); + XFREE(MTYPE_OSPF6_IF, oi); } @@ -328,31 +335,6 @@ ospf6_interface_get_linklocal_address(struct interface *ifp) 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; - - /* Try to adjust I/O buffer size with IfMtu */ - 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; - } - - /* interface start */ - ospf6_interface_state_update(oi->interface); -} - void ospf6_interface_state_update(struct interface *ifp) { struct ospf6_interface *oi; @@ -388,7 +370,7 @@ void ospf6_interface_state_update(struct interface *ifp) if (if_is_operative(ifp) && (ospf6_interface_get_linklocal_address(oi->interface) - || if_is_loopback(oi->interface))) + || if_is_loopback_or_vrf(oi->interface))) thread_execute(master, interface_up, oi, 0); else thread_execute(master, interface_down, oi, 0); @@ -453,7 +435,7 @@ void ospf6_interface_connected_route_update(struct interface *ifp) } } - route = ospf6_route_create(); + route = ospf6_route_create(oi->area->ospf6); memcpy(&route->prefix, c->address, sizeof(struct prefix)); apply_mask(&route->prefix); route->type = OSPF6_DEST_TYPE_NETWORK; @@ -472,8 +454,8 @@ void ospf6_interface_connected_route_update(struct interface *ifp) OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area); } -static void ospf6_interface_state_change(uint8_t next_state, - struct ospf6_interface *oi) +static int ospf6_interface_state_change(uint8_t next_state, + struct ospf6_interface *oi) { uint8_t prev_state; struct ospf6 *ospf6; @@ -482,7 +464,10 @@ static void ospf6_interface_state_change(uint8_t next_state, oi->state = next_state; if (prev_state == next_state) - return; + return -1; + + if (!oi->area) + return -1; /* log */ if (IS_OSPF6_DEBUG_INTERFACE) { @@ -492,7 +477,8 @@ static void ospf6_interface_state_change(uint8_t next_state, ospf6_interface_state_str[next_state]); } oi->state_change++; - ospf6 = ospf6_lookup_by_vrf_id(oi->interface->vrf_id); + + ospf6 = oi->area->ospf6; if ((prev_state == OSPF6_INTERFACE_DR || prev_state == OSPF6_INTERFACE_BDR) @@ -523,6 +509,8 @@ static void ospf6_interface_state_change(uint8_t next_state, } hook_call(ospf6_interface_change, oi, next_state, prev_state); + + return 0; } @@ -679,6 +667,43 @@ static uint8_t dr_election(struct ospf6_interface *oi) return next_state; } +#ifdef __FreeBSD__ + +#include <ifaddrs.h> + +static bool ifmaddr_check(ifindex_t ifindex, struct in6_addr *addr) +{ + struct ifmaddrs *ifmap, *ifma; + struct sockaddr_dl *sdl; + struct sockaddr_in6 *sin6; + bool found = false; + + if (getifmaddrs(&ifmap) != 0) + return false; + + for (ifma = ifmap; ifma; ifma = ifma->ifma_next) { + if (ifma->ifma_name == NULL || ifma->ifma_addr == NULL) + continue; + if (ifma->ifma_name->sa_family != AF_LINK) + continue; + if (ifma->ifma_addr->sa_family != AF_INET6) + continue; + sdl = (struct sockaddr_dl *)ifma->ifma_name; + sin6 = (struct sockaddr_in6 *)ifma->ifma_addr; + if (sdl->sdl_index == ifindex + && memcmp(&sin6->sin6_addr, addr, IPV6_MAX_BYTELEN) == 0) { + found = true; + break; + } + } + + if (ifmap) + freeifmaddrs(ifmap); + + return found; +} + +#endif /* __FreeBSD__ */ /* Interface State Machine */ int interface_up(struct thread *thread) @@ -692,11 +717,7 @@ int interface_up(struct thread *thread) if (!oi->type_cfg) oi->type = ospf6_default_iftype(oi->interface); - /* - * Remove old pointer. If this thread wasn't a timer this - * operation won't make a difference, because it is already NULL. - */ - oi->thread_sso = NULL; + thread_cancel(&oi->thread_sso); if (IS_OSPF6_DEBUG_INTERFACE) zlog_debug("Interface Event %s: [InterfaceUp]", @@ -704,20 +725,17 @@ int interface_up(struct thread *thread) /* check physical interface is up */ if (!if_is_operative(oi->interface)) { - if (IS_OSPF6_DEBUG_INTERFACE) - zlog_debug( - "Interface %s is down, can't execute [InterfaceUp]", - oi->interface->name); + zlog_warn("Interface %s is down, can't execute [InterfaceUp]", + oi->interface->name); return 0; } /* check interface has a link-local address */ 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); + || if_is_loopback_or_vrf(oi->interface))) { + zlog_warn( + "Interface %s has no link local address, can't execute [InterfaceUp]", + oi->interface->name); return 0; } @@ -734,31 +752,33 @@ int interface_up(struct thread *thread) /* If no area assigned, return */ if (oi->area == NULL) { - zlog_debug( - "%s: Not scheduleing Hello for %s as there is no area assigned yet", + zlog_warn( + "%s: Not scheduling Hello for %s as there is no area assigned yet", __func__, oi->interface->name); return 0; } #ifdef __FreeBSD__ /* - * XXX: Schedule IPv6 group join for later, otherwise we might - * lose the multicast group registration caused by IPv6 group - * leave race. + * There's a delay in FreeBSD between issuing a command to leave a + * multicast group and an actual leave. If we execute "no router ospf6" + * and "router ospf6" fast enough, we can end up in a situation when OS + * performs the leave later than it performs the join and the interface + * remains without a multicast group. We have to do the join only after + * the interface actually left the group. */ - if (oi->sso_try_cnt == 0) { - oi->sso_try_cnt++; - zlog_info("Scheduling %s for sso", oi->interface->name); + if (ifmaddr_check(oi->interface->ifindex, &allspfrouters6)) { + zlog_info( + "Interface %s is still in all routers group, rescheduling for SSO", + oi->interface->name); thread_add_timer(master, interface_up, oi, OSPF6_INTERFACE_SSO_RETRY_INT, &oi->thread_sso); return 0; } #endif /* __FreeBSD__ */ - if (oi->area->ospf6) - ospf6 = oi->area->ospf6; - else - ospf6 = ospf6_lookup_by_vrf_id(oi->interface->vrf_id); + + ospf6 = oi->area->ospf6; /* Join AllSPFRouters */ if (ospf6_sso(oi->interface->ifindex, &allspfrouters6, IPV6_JOIN_GROUP, @@ -781,14 +801,16 @@ int interface_up(struct thread *thread) /* Schedule Hello */ if (!CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE) - && !if_is_loopback(oi->interface)) { + && !if_is_loopback_or_vrf(oi->interface)) { oi->thread_send_hello = NULL; thread_add_event(master, ospf6_hello_send, oi, 0, &oi->thread_send_hello); } /* decide next interface state */ - if (oi->type == OSPF_IFTYPE_POINTOPOINT) { + if (oi->type == OSPF_IFTYPE_LOOPBACK) { + ospf6_interface_state_change(OSPF6_INTERFACE_LOOPBACK, oi); + } else 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); @@ -873,13 +895,6 @@ int interface_down(struct thread *thread) /* Stop trying to set socket options. */ THREAD_OFF(oi->thread_sso); - ospf6 = ospf6_lookup_by_vrf_id(oi->interface->vrf_id); - /* Leave AllSPFRouters */ - if (oi->state > OSPF6_INTERFACE_DOWN) - ospf6_sso(oi->interface->ifindex, &allspfrouters6, - IPV6_LEAVE_GROUP, ospf6->fd); - - ospf6_interface_state_change(OSPF6_INTERFACE_DOWN, oi); for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) ospf6_neighbor_delete(on); @@ -890,6 +905,27 @@ int interface_down(struct thread *thread) * DR election, as it is no longer valid. */ oi->drouter = oi->prev_drouter = htonl(0); oi->bdrouter = oi->prev_bdrouter = htonl(0); + + if (oi->area == NULL) + return 0; + + ospf6 = oi->area->ospf6; + /* Leave AllSPFRouters */ + if (oi->state > OSPF6_INTERFACE_DOWN) + ospf6_sso(oi->interface->ifindex, &allspfrouters6, + IPV6_LEAVE_GROUP, ospf6->fd); + + /* deal with write fifo */ + ospf6_fifo_flush(oi->obuf); + if (oi->on_write_q) { + listnode_delete(ospf6->oi_write_q, oi); + if (list_isempty(ospf6->oi_write_q)) + thread_cancel(&ospf6->t_write); + oi->on_write_q = 0; + } + + ospf6_interface_state_change(OSPF6_INTERFACE_DOWN, oi); + return 0; } @@ -1147,23 +1183,59 @@ static int ospf6_interface_show(struct vty *vty, struct interface *ifp, for (ALL_LSDB(oi->lsack_list, lsa, lsanext)) vty_out(vty, " %s\n", lsa->name); } - ospf6_bfd_show_info(vty, oi->bfd_info, 1, json_obj, use_json); + + /* BFD specific. */ + if (oi->bfd_config.enabled) { + if (use_json) { + struct json_object *json_bfd = json_object_new_object(); + + json_object_int_add( + json_bfd, "detectMultiplier", + oi->bfd_config.detection_multiplier); + json_object_int_add(json_bfd, "rxMinInterval", + oi->bfd_config.min_rx); + json_object_int_add(json_bfd, "txMinInterval", + oi->bfd_config.min_tx); + json_object_object_add(json_obj, "peerBfdInfo", + json_bfd); + } else { + vty_out(vty, + " BFD: Detect Multiplier: %d, Min Rx interval: %d, Min Tx interval: %d\n", + oi->bfd_config.detection_multiplier, + oi->bfd_config.min_rx, oi->bfd_config.min_tx); + } + } + return 0; } -/* show interface */ -DEFUN(show_ipv6_ospf6_interface, - show_ipv6_ospf6_interface_ifname_cmd, - "show ipv6 ospf6 interface [IFNAME] [json]", - SHOW_STR - IP6_STR - OSPF6_STR - INTERFACE_STR - IFNAME_STR - JSON_STR) +/* Find the global address to be used as a forwarding address in NSSA LSA.*/ +struct in6_addr *ospf6_interface_get_global_address(struct interface *ifp) { - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); - int idx_ifname = 4; + struct listnode *n; + struct connected *c; + struct in6_addr *l = (struct in6_addr *)NULL; + + /* for each connected address */ + for (ALL_LIST_ELEMENTS_RO(ifp->connected, n, c)) { + /* if family not AF_INET6, ignore */ + if (c->address->family != AF_INET6) + continue; + + if (!IN6_IS_ADDR_LINKLOCAL(&c->address->u.prefix6)) + l = &c->address->u.prefix6; + } + return l; +} + + +static int show_ospf6_interface_common(struct vty *vty, vrf_id_t vrf_id, + int argc, struct cmd_token **argv, + int idx_ifname, int intf_idx, + int json_idx) +{ + + struct vrf *vrf = vrf_lookup_by_id(vrf_id); struct interface *ifp; json_object *json; json_object *json_int; @@ -1171,9 +1243,8 @@ DEFUN(show_ipv6_ospf6_interface, if (uj) { json = json_object_new_object(); - if (argc == 6) { - ifp = if_lookup_by_name(argv[idx_ifname]->arg, - VRF_DEFAULT); + if (argc == json_idx) { + ifp = if_lookup_by_name(argv[idx_ifname]->arg, vrf_id); json_int = json_object_new_object(); if (ifp == NULL) { json_object_string_add(json, "noSuchInterface", @@ -1200,9 +1271,8 @@ DEFUN(show_ipv6_ospf6_interface, json, JSON_C_TO_STRING_PRETTY)); json_object_free(json); } else { - if (argc == 5) { - ifp = if_lookup_by_name(argv[idx_ifname]->arg, - VRF_DEFAULT); + if (argc == intf_idx) { + ifp = if_lookup_by_name(argv[idx_ifname]->arg, vrf_id); if (ifp == NULL) { vty_out(vty, "No such Interface: %s\n", argv[idx_ifname]->arg); @@ -1214,6 +1284,42 @@ DEFUN(show_ipv6_ospf6_interface, ospf6_interface_show(vty, ifp, NULL, uj); } } + return CMD_SUCCESS; +} + +/* show interface */ +DEFUN(show_ipv6_ospf6_interface, show_ipv6_ospf6_interface_ifname_cmd, + "show ipv6 ospf6 [vrf <NAME|all>] interface [IFNAME] [json]", + SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR + "All VRFs\n" INTERFACE_STR IFNAME_STR JSON_STR) +{ + int idx_ifname = 4; + int intf_idx = 5; + int json_idx = 6; + struct listnode *node; + struct ospf6 *ospf6; + const char *vrf_name = NULL; + bool all_vrf = false; + int idx_vrf = 0; + + OSPF6_CMD_CHECK_RUNNING(); + OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + if (idx_vrf > 0) { + idx_ifname += 2; + intf_idx += 2; + json_idx += 2; + } + + for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) { + if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) { + show_ospf6_interface_common(vty, ospf6->vrf_id, argc, + argv, idx_ifname, intf_idx, + json_idx); + + if (!all_vrf) + break; + } + } return CMD_SUCCESS; } @@ -1221,7 +1327,7 @@ DEFUN(show_ipv6_ospf6_interface, static int ospf6_interface_show_traffic(struct vty *vty, struct interface *intf_ifp, int display_once, json_object *json, - bool use_json) + bool use_json, vrf_id_t vrf_id) { struct interface *ifp; struct vrf *vrf = NULL; @@ -1231,7 +1337,7 @@ static int ospf6_interface_show_traffic(struct vty *vty, if (intf_ifp) vrf = vrf_lookup_by_id(intf_ifp->vrf_id); else - vrf = vrf_lookup_by_id(VRF_DEFAULT); + vrf = vrf_lookup_by_id(vrf_id); if (!display_once && !use_json) { vty_out(vty, "\n"); @@ -1332,17 +1438,9 @@ static int ospf6_interface_show_traffic(struct vty *vty, return CMD_SUCCESS; } -/* show interface */ -DEFUN(show_ipv6_ospf6_interface_traffic, - show_ipv6_ospf6_interface_traffic_cmd, - "show ipv6 ospf6 interface traffic [IFNAME] [json]", - SHOW_STR - IP6_STR - OSPF6_STR - INTERFACE_STR - "Protocol Packet counters\n" - IFNAME_STR - JSON_STR) +static int ospf6_interface_show_traffic_common(struct vty *vty, int argc, + struct cmd_token **argv, + vrf_id_t vrf_id) { int idx_ifname = 0; int display_once = 0; @@ -1356,7 +1454,7 @@ DEFUN(show_ipv6_ospf6_interface_traffic, if (argv_find(argv, argc, "IFNAME", &idx_ifname)) { intf_name = argv[idx_ifname]->arg; - ifp = if_lookup_by_name(intf_name, VRF_DEFAULT); + ifp = if_lookup_by_name(intf_name, vrf_id); if (uj) { if (ifp == NULL) { json_object_string_add(json, "status", @@ -1396,7 +1494,7 @@ DEFUN(show_ipv6_ospf6_interface_traffic, } } - ospf6_interface_show_traffic(vty, ifp, display_once, json, uj); + ospf6_interface_show_traffic(vty, ifp, display_once, json, uj, vrf_id); if (uj) { vty_out(vty, "%s\n", @@ -1405,94 +1503,275 @@ DEFUN(show_ipv6_ospf6_interface_traffic, json_object_free(json); } + return CMD_SUCCESS; +} + +/* show interface */ +DEFUN(show_ipv6_ospf6_interface_traffic, show_ipv6_ospf6_interface_traffic_cmd, + "show ipv6 ospf6 [vrf <NAME|all>] interface traffic [IFNAME] [json]", + SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR + "All VRFs\n" INTERFACE_STR + "Protocol Packet counters\n" IFNAME_STR JSON_STR) +{ + struct ospf6 *ospf6; + struct listnode *node; + const char *vrf_name = NULL; + bool all_vrf = false; + int idx_vrf = 0; + + OSPF6_CMD_CHECK_RUNNING(); + OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + + for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) { + if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) { + ospf6_interface_show_traffic_common(vty, argc, argv, + ospf6->vrf_id); + + if (!all_vrf) + break; + } + } return CMD_SUCCESS; } -DEFUN (show_ipv6_ospf6_interface_ifname_prefix, - show_ipv6_ospf6_interface_ifname_prefix_cmd, - "show ipv6 ospf6 interface IFNAME prefix\ +DEFUN(show_ipv6_ospf6_interface_ifname_prefix, + show_ipv6_ospf6_interface_ifname_prefix_cmd, + "show ipv6 ospf6 [vrf <NAME|all>] interface IFNAME prefix\ [<\ detail\ |<X:X::X:X|X:X::X:X/M> [<match|detail>]\ >] [json]", - 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" - JSON_STR) + SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR + "All VRFs\n" 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" JSON_STR) { int idx_ifname = 4; int idx_prefix = 6; - struct interface *ifp; struct ospf6_interface *oi; bool uj = use_json(argc, argv); - 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; + struct ospf6 *ospf6; + struct listnode *node; + struct interface *ifp; + const char *vrf_name = NULL; + bool all_vrf = false; + int idx_vrf = 0; + + OSPF6_CMD_CHECK_RUNNING(); + OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + if (idx_vrf > 0) { + idx_ifname += 2; + idx_prefix += 2; } - oi = ifp->info; - if (oi == NULL) { - vty_out(vty, "OSPFv3 is not enabled on %s\n", - argv[idx_ifname]->arg); - return CMD_WARNING; - } + for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) { + if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) { + ifp = if_lookup_by_name(argv[idx_ifname]->arg, + ospf6->vrf_id); + if (ifp == NULL) { + vty_out(vty, "No such Interface: %s\n", + argv[idx_ifname]->arg); + return CMD_WARNING; + } + + oi = ifp->info; + if (oi == NULL + || CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) { + vty_out(vty, + "Interface %s not attached to area\n", + argv[idx_ifname]->arg); + return CMD_WARNING; + } - ospf6_route_table_show(vty, idx_prefix, argc, argv, oi->route_connected, - uj); + ospf6_route_table_show(vty, idx_prefix, argc, argv, + oi->route_connected, uj); + + if (!all_vrf) + break; + } + } return CMD_SUCCESS; } -DEFUN (show_ipv6_ospf6_interface_prefix, - show_ipv6_ospf6_interface_prefix_cmd, - "show ipv6 ospf6 interface prefix\ +DEFUN(show_ipv6_ospf6_interface_prefix, show_ipv6_ospf6_interface_prefix_cmd, + "show ipv6 ospf6 [vrf <NAME|all>] interface prefix\ [<\ detail\ |<X:X::X:X|X:X::X:X/M> [<match|detail>]\ >] [json]", - 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" - JSON_STR) + SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR + "All VRFs\n" 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" JSON_STR) { - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); + struct vrf *vrf = NULL; int idx_prefix = 5; struct ospf6_interface *oi; struct interface *ifp; bool uj = use_json(argc, argv); + struct listnode *node; + struct ospf6 *ospf6; + const char *vrf_name = NULL; + bool all_vrf = false; + int idx_vrf = 0; + + OSPF6_CMD_CHECK_RUNNING(); + OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + if (idx_vrf > 0) + idx_prefix += 2; + + for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) { + if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) { + vrf = vrf_lookup_by_id(ospf6->vrf_id); + FOR_ALL_INTERFACES (vrf, ifp) { + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL + || CHECK_FLAG(oi->flag, + OSPF6_INTERFACE_DISABLE)) + continue; + + ospf6_route_table_show(vty, idx_prefix, argc, + argv, + oi->route_connected, uj); + } + if (!all_vrf) + break; + } + } - FOR_ALL_INTERFACES (vrf, ifp) { - oi = (struct ospf6_interface *)ifp->info; - if (oi == NULL) - continue; + return CMD_SUCCESS; +} + +void ospf6_interface_start(struct ospf6_interface *oi) +{ + struct ospf6 *ospf6; + struct ospf6_area *oa; + + if (oi->area_id_format == OSPF6_AREA_FMT_UNSET) + return; + + if (oi->area) + return; + + ospf6 = ospf6_lookup_by_vrf_id(oi->interface->vrf_id); + if (!ospf6) + return; + + oa = ospf6_area_lookup(oi->area_id, ospf6); + if (oa == NULL) + oa = ospf6_area_create(oi->area_id, ospf6, oi->area_id_format); + + /* attach interface to area */ + listnode_add(oa->if_list, oi); + oi->area = oa; + + SET_FLAG(oa->flag, OSPF6_AREA_ENABLE); + + /* start up */ + ospf6_interface_enable(oi); + + /* If the router is ABR, originate summary routes */ + if (ospf6_check_and_set_router_abr(ospf6)) + ospf6_abr_enable_area(oa); +} + +void ospf6_interface_stop(struct ospf6_interface *oi) +{ + struct ospf6_area *oa; + + oa = oi->area; + if (!oa) + return; + + ospf6_interface_disable(oi); + + listnode_delete(oa->if_list, oi); + oi->area = NULL; + + if (oa->if_list->count == 0) { + UNSET_FLAG(oa->flag, OSPF6_AREA_ENABLE); + ospf6_abr_disable_area(oa); + } +} + +/* interface variable set command */ +DEFUN (ipv6_ospf6_area, + ipv6_ospf6_area_cmd, + "ipv6 ospf6 area <A.B.C.D|(0-4294967295)>", + IP6_STR + OSPF6_STR + "Specify the OSPF6 area ID\n" + "OSPF6 area ID in IPv4 address notation\n" + "OSPF6 area ID in decimal notation\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + struct ospf6_interface *oi; + int idx_ipv4 = 3; + uint32_t area_id; + int format; + + assert(ifp); - ospf6_route_table_show(vty, idx_prefix, argc, argv, - oi->route_connected, uj); + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) + oi = ospf6_interface_create(ifp); + assert(oi); + + if (oi->area) { + vty_out(vty, "%s already attached to Area %s\n", + oi->interface->name, oi->area->name); + return CMD_SUCCESS; + } + + if (str2area_id(argv[idx_ipv4]->arg, &area_id, &format)) { + vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4]->arg); + return CMD_WARNING_CONFIG_FAILED; } + oi->area_id = area_id; + oi->area_id_format = format; + + ospf6_interface_start(oi); + + return CMD_SUCCESS; +} + +DEFUN (no_ipv6_ospf6_area, + no_ipv6_ospf6_area_cmd, + "no ipv6 ospf6 area [<A.B.C.D|(0-4294967295)>]", + NO_STR + IP6_STR + OSPF6_STR + "Specify the OSPF6 area ID\n" + "OSPF6 area ID in IPv4 address notation\n" + "OSPF6 area ID in decimal notation\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); + + ospf6_interface_stop(oi); + + oi->area_id = 0; + oi->area_id_format = OSPF6_AREA_FMT_UNSET; + return CMD_SUCCESS; } -/* interface variable set command */ DEFUN (ipv6_ospf6_ifmtu, ipv6_ospf6_ifmtu_cmd, "ipv6 ospf6 ifmtu (1-65535)", @@ -1622,12 +1901,11 @@ DEFUN (ipv6_ospf6_cost, return CMD_WARNING_CONFIG_FAILED; } + SET_FLAG(oi->flag, OSPF6_INTERFACE_NOAUTOCOST); 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; @@ -1715,6 +1993,38 @@ DEFUN (no_auto_cost_reference_bandwidth, } +DEFUN (ospf6_write_multiplier, + ospf6_write_multiplier_cmd, + "write-multiplier (1-100)", + "Write multiplier\n" + "Maximum number of interface serviced per write\n") +{ + VTY_DECLVAR_CONTEXT(ospf6, o); + uint32_t write_oi_count; + + write_oi_count = strtol(argv[1]->arg, NULL, 10); + if (write_oi_count < 1 || write_oi_count > 100) { + vty_out(vty, "write-multiplier value is invalid\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + o->write_oi_count = write_oi_count; + return CMD_SUCCESS; +} + +DEFUN (no_ospf6_write_multiplier, + no_ospf6_write_multiplier_cmd, + "no write-multiplier (1-100)", + NO_STR + "Write multiplier\n" + "Maximum number of interface serviced per write\n") +{ + VTY_DECLVAR_CONTEXT(ospf6, o); + + o->write_oi_count = OSPF6_WRITE_INTERFACE_COUNT_DEFAULT; + return CMD_SUCCESS; +} + DEFUN (ipv6_ospf6_hellointerval, ipv6_ospf6_hellointerval_cmd, "ipv6 ospf6 hello-interval (1-65535)", @@ -1873,10 +2183,13 @@ DEFUN (ipv6_ospf6_priority, ? 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); + if (oi->area + && (oi->state == OSPF6_INTERFACE_DROTHER + || oi->state == OSPF6_INTERFACE_BDR + || oi->state == OSPF6_INTERFACE_DR)) { + if (ospf6_interface_state_change(dr_election(oi), oi) == -1) + OSPF6_LINK_LSA_SCHEDULE(oi); + } return CMD_SUCCESS; } @@ -1978,7 +2291,7 @@ DEFUN (no_ipv6_ospf6_passive, THREAD_OFF(oi->thread_sso); /* don't send hellos over loopback interface */ - if (!if_is_loopback(oi->interface)) + if (!if_is_loopback_or_vrf(oi->interface)) thread_add_event(master, ospf6_hello_send, oi, 0, &oi->thread_send_hello); @@ -2182,21 +2495,30 @@ DEFUN (no_ipv6_ospf6_network, return CMD_SUCCESS; } -static int config_write_ospf6_interface(struct vty *vty) +static int config_write_ospf6_interface(struct vty *vty, struct vrf *vrf) { - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); struct ospf6_interface *oi; struct interface *ifp; + char buf[INET_ADDRSTRLEN]; 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 (vrf->vrf_id == VRF_DEFAULT) + vty_frame(vty, "interface %s\n", oi->interface->name); + else + vty_frame(vty, "interface %s vrf %s\n", + oi->interface->name, vrf->name); if (ifp->desc) vty_out(vty, " description %s\n", ifp->desc); + if (oi->area_id_format != OSPF6_AREA_FMT_UNSET) { + area_id2str(buf, sizeof(buf), oi->area_id, + oi->area_id_format); + vty_out(vty, " ipv6 ospf6 area %s\n", buf); + } if (oi->c_ifmtu) vty_out(vty, " ipv6 ospf6 ifmtu %d\n", oi->c_ifmtu); @@ -2248,21 +2570,28 @@ static int config_write_ospf6_interface(struct vty *vty) 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, -}; +/* Configuration write function for ospfd. */ +static int config_write_interface(struct vty *vty) +{ + int write = 0; + struct vrf *vrf = NULL; + + /* Display all VRF aware OSPF interface configuration */ + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + write += config_write_ospf6_interface(vty, vrf); + } + + return write; +} 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); + + if (ifp->info) + ospf6_interface_start(ifp->info); return 0; } @@ -2303,14 +2632,16 @@ static int ospf6_ifp_destroy(struct interface *ifp) zlog_debug("Zebra Interface delete: %s index %d mtu %d", ifp->name, ifp->ifindex, ifp->mtu6); + if (ifp->info) + ospf6_interface_stop(ifp->info); + return 0; } void ospf6_interface_init(void) { /* Install interface node. */ - install_node(&interface_node); - if_cmd_init(); + if_cmd_init(config_write_interface); if_zapi_callbacks(ospf6_ifp_create, ospf6_ifp_up, ospf6_ifp_down, ospf6_ifp_destroy); @@ -2320,6 +2651,8 @@ void ospf6_interface_init(void) &show_ipv6_ospf6_interface_ifname_prefix_cmd); install_element(VIEW_NODE, &show_ipv6_ospf6_interface_traffic_cmd); + install_element(INTERFACE_NODE, &ipv6_ospf6_area_cmd); + install_element(INTERFACE_NODE, &no_ipv6_ospf6_area_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); @@ -2354,10 +2687,13 @@ void ospf6_interface_init(void) /* reference bandwidth commands */ install_element(OSPF6_NODE, &auto_cost_reference_bandwidth_cmd); install_element(OSPF6_NODE, &no_auto_cost_reference_bandwidth_cmd); + /* write-multiplier commands */ + install_element(OSPF6_NODE, &ospf6_write_multiplier_cmd); + install_element(OSPF6_NODE, &no_ospf6_write_multiplier_cmd); } /* Clear the specified interface structure */ -static void ospf6_interface_clear(struct vty *vty, struct interface *ifp) +void ospf6_interface_clear(struct interface *ifp) { struct ospf6_interface *oi; @@ -2395,7 +2731,7 @@ DEFUN (clear_ipv6_ospf6_interface, if (argc == 4) /* Clear all the ospfv3 interfaces. */ { FOR_ALL_INTERFACES (vrf, ifp) - ospf6_interface_clear(vty, ifp); + ospf6_interface_clear(ifp); } else /* Interface name is specified. */ { if ((ifp = if_lookup_by_name(argv[idx_ifname]->arg, @@ -2405,7 +2741,7 @@ DEFUN (clear_ipv6_ospf6_interface, argv[idx_ifname]->arg); return CMD_WARNING; } - ospf6_interface_clear(vty, ifp); + ospf6_interface_clear(ifp); } return CMD_SUCCESS; |
