diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index a2ddba65e972..27851ad80a88 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -405,6 +405,7 @@ void ospf6_interface_connected_route_update(struct interface *ifp) struct connected *c; struct listnode *node, *nnode; struct in6_addr nh_addr; + int count = 0, max_addr_count; oi = (struct ospf6_interface *)ifp->info; if (oi == NULL) @@ -423,10 +424,22 @@ void ospf6_interface_connected_route_update(struct interface *ifp) /* update "route to advertise" interface route table */ ospf6_route_remove_all(oi->route_connected); + if (oi->ifmtu >= OSPF6_JUMBO_MTU) + max_addr_count = OSPF6_MAX_IF_ADDRS_JUMBO; + else + max_addr_count = OSPF6_MAX_IF_ADDRS; + for (ALL_LIST_ELEMENTS(oi->interface->connected, node, nnode, c)) { if (c->address->family != AF_INET6) continue; + /* number of interface addresses supported is based on MTU + * size of OSPFv3 packet + */ + count++; + if (count >= max_addr_count) + break; + CONTINUE_IF_ADDRESS_LINKLOCAL(IS_OSPF6_DEBUG_INTERFACE, c->address); CONTINUE_IF_ADDRESS_UNSPECIFIED(IS_OSPF6_DEBUG_INTERFACE, diff --git a/ospf6d/ospf6_interface.h b/ospf6d/ospf6_interface.h index a45a841406da..48b2cbff7402 100644 --- a/ospf6d/ospf6_interface.h +++ b/ospf6d/ospf6_interface.h @@ -188,6 +188,7 @@ extern void ospf6_interface_disable(struct ospf6_interface *); extern void ospf6_interface_if_add(struct interface *); extern void ospf6_interface_state_update(struct interface *); extern void ospf6_interface_connected_route_update(struct interface *); +extern void ospf6_interface_connected_route_add(struct connected *); /* interface event */ extern int interface_up(struct thread *); diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c index adff76ec4114..b1cc7f63d682 100644 --- a/ospf6d/ospf6_intra.c +++ b/ospf6d/ospf6_intra.c @@ -757,6 +757,7 @@ int ospf6_link_lsa_originate(struct thread *thread) struct ospf6_link_lsa *link_lsa; struct ospf6_route *route; struct ospf6_prefix *op; + int count, max_addr_count; oi = (struct ospf6_interface *)THREAD_ARG(thread); oi->thread_link_lsa = NULL; @@ -800,14 +801,20 @@ int ospf6_link_lsa_originate(struct thread *thread) memcpy(link_lsa->options, oi->area->options, 3); memcpy(&link_lsa->linklocal_addr, oi->linklocal_addr, sizeof(struct in6_addr)); - link_lsa->prefix_num = htonl(oi->route_connected->count); op = (struct ospf6_prefix *)((caddr_t)link_lsa + sizeof(struct ospf6_link_lsa)); - /* connected prefix to advertise */ - for (route = ospf6_route_head(oi->route_connected); route; - route = ospf6_route_next(route)) { + /* connected prefix to advertise, number of interface addresses + * supported is based on MTU size of OSPFv3 packets + */ + if (oi->ifmtu >= OSPF6_JUMBO_MTU) + max_addr_count = OSPF6_MAX_IF_ADDRS_JUMBO; + else + max_addr_count = OSPF6_MAX_IF_ADDRS; + for (route = ospf6_route_head(oi->route_connected), count = 0; + route && count < max_addr_count; + route = ospf6_route_next(route), count++) { op->prefix_length = route->prefix.prefixlen; op->prefix_options = route->path.prefix_options; op->prefix_metric = htons(0); @@ -816,6 +823,8 @@ int ospf6_link_lsa_originate(struct thread *thread) op = OSPF6_PREFIX_NEXT(op); } + link_lsa->prefix_num = htonl(count); + /* Fill LSA Header */ lsa_header->age = 0; lsa_header->type = htons(OSPF6_LSTYPE_LINK); @@ -995,6 +1004,7 @@ int ospf6_intra_prefix_lsa_originate_stub(struct thread *thread) unsigned short prefix_num = 0; struct ospf6_route_table *route_advertise; int ls_id = 0; + int count, max_addr_count; oa = (struct ospf6_area *)THREAD_ARG(thread); oa->thread_intra_prefix_lsa = NULL; @@ -1040,6 +1050,8 @@ int ospf6_intra_prefix_lsa_originate_stub(struct thread *thread) intra_prefix_lsa->ref_adv_router = oa->ospf6->router_id; route_advertise = ospf6_route_table_create(0, 0); + route_advertise->hook_add = NULL; + route_advertise->hook_remove = NULL; for (ALL_LIST_ELEMENTS_RO(oa->if_list, i, oi)) { if (oi->state == OSPF6_INTERFACE_DOWN) { @@ -1068,8 +1080,14 @@ int ospf6_intra_prefix_lsa_originate_stub(struct thread *thread) zlog_debug(" Interface %s:", oi->interface->name); /* connected prefix to advertise */ - for (route = ospf6_route_head(oi->route_connected); route; - route = ospf6_route_best_next(route)) { + if (oi->ifmtu >= OSPF6_JUMBO_MTU) + max_addr_count = OSPF6_MAX_IF_ADDRS_JUMBO; + else + max_addr_count = OSPF6_MAX_IF_ADDRS; + + for (route = ospf6_route_head(oi->route_connected), count = 0; + route && count < max_addr_count; + route = ospf6_route_best_next(route), count++) { if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX)) zlog_debug(" include %pFX", &route->prefix); ospf6_route_add(ospf6_route_copy(route), @@ -1284,6 +1302,8 @@ int ospf6_intra_prefix_lsa_originate_transit(struct thread *thread) /* connected prefix to advertise */ route_advertise = ospf6_route_table_create(0, 0); + route_advertise->hook_add = NULL; + route_advertise->hook_remove = NULL; type = ntohs(OSPF6_LSTYPE_LINK); for (ALL_LSDB_TYPED(oi->lsdb, type, lsa)) { diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 8c6d4b126d09..0a6639d887b1 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -740,11 +740,13 @@ DEFUN (ospf6_interface_area, struct ospf6_area *oa; struct ospf6_interface *oi; struct interface *ifp; + int ipv6_count = 0; VTY_DECLVAR_CONTEXT(ospf6, ospf6); /* find/create ospf6 interface */ ifp = if_get_by_name(argv[idx_ifname]->arg, VRF_DEFAULT); + oi = (struct ospf6_interface *)ifp->info; if (oi == NULL) oi = ospf6_interface_create(ifp); @@ -754,6 +756,23 @@ DEFUN (ospf6_interface_area, return CMD_SUCCESS; } + /* if more than OSPF6_MAX_IF_ADDRS are configured on this interface + * then don't allow ospfv3 to be configured + */ + ipv6_count = connected_count_by_family(ifp, AF_INET6); + if (oi->ifmtu == OSPF6_DEFAULT_MTU && ipv6_count > OSPF6_MAX_IF_ADDRS) { + vty_out(vty, + "can not configure OSPFv3 on if %s, must have less than %d interface addresses but has %d addresses\n", + ifp->name, OSPF6_MAX_IF_ADDRS, ipv6_count); + return CMD_WARNING_CONFIG_FAILED; + } else if (oi->ifmtu >= OSPF6_JUMBO_MTU + && ipv6_count > OSPF6_MAX_IF_ADDRS_JUMBO) { + vty_out(vty, + "can not configure OSPFv3 on if %s, must have less than %d interface addresses but has %d addresses\n", + ifp->name, OSPF6_MAX_IF_ADDRS_JUMBO, ipv6_count); + return CMD_WARNING_CONFIG_FAILED; + } + /* parse Area-ID */ OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, oa, ospf6); diff --git a/ospf6d/ospf6_top.h b/ospf6d/ospf6_top.h index 08b884f23a99..dbd0da85b3f4 100644 --- a/ospf6d/ospf6_top.h +++ b/ospf6d/ospf6_top.h @@ -153,6 +153,10 @@ DECLARE_QOBJ_TYPE(ospf6); #define OSPF6_DISABLED 0x01 #define OSPF6_STUB_ROUTER 0x02 #define OSPF6_FLAG_ASBR 0x04 +#define OSPF6_MAX_IF_ADDRS 100 +#define OSPF6_MAX_IF_ADDRS_JUMBO 200 +#define OSPF6_DEFAULT_MTU 1500 +#define OSPF6_JUMBO_MTU 9000 /* global pointer for OSPF top data structure */ extern struct ospf6 *ospf6; diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c index 76e717287040..170d545c49cd 100644 --- a/ospf6d/ospf6_zebra.c +++ b/ospf6d/ospf6_zebra.c @@ -130,17 +130,38 @@ void ospf6_zebra_no_redistribute(int type, vrf_id_t vrf_id) static int ospf6_zebra_if_address_update_add(ZAPI_CALLBACK_ARGS) { struct connected *c; + struct ospf6_interface *oi; + int ipv6_count = 0; c = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, zclient->ibuf, vrf_id); if (c == NULL) return 0; + oi = (struct ospf6_interface *)c->ifp->info; + if (oi == NULL) + oi = ospf6_interface_create(c->ifp); + assert(oi); + if (IS_OSPF6_DEBUG_ZEBRA(RECV)) zlog_debug("Zebra Interface address add: %s %5s %pFX", c->ifp->name, prefix_family_str(c->address), c->address); + ipv6_count = connected_count_by_family(c->ifp, AF_INET6); + if (oi->ifmtu == OSPF6_DEFAULT_MTU && ipv6_count > OSPF6_MAX_IF_ADDRS) { + zlog_warn( + "Zebra Interface : %s has too many interface addresses %d only support %d, increase MTU", + c->ifp->name, ipv6_count, OSPF6_MAX_IF_ADDRS); + return 0; + } else if (oi->ifmtu >= OSPF6_JUMBO_MTU + && ipv6_count > OSPF6_MAX_IF_ADDRS_JUMBO) { + zlog_warn( + "Zebra Interface : %s has too many interface addresses %d only support %d", + c->ifp->name, ipv6_count, OSPF6_MAX_IF_ADDRS_JUMBO); + return 0; + } + if (c->address->family == AF_INET6) { ospf6_interface_state_update(c->ifp); ospf6_interface_connected_route_update(c->ifp); @@ -303,7 +324,7 @@ static void ospf6_zebra_route_update(int type, struct ospf6_route *request, struct prefix *dest; if (IS_OSPF6_DEBUG_ZEBRA(SEND)) - zlog_debug("Send %s route: %pFX", + zlog_debug("Zebra Send %s route: %pFX", (type == REM ? "remove" : "add"), &request->prefix); if (zclient->sock < 0) {