Index: sys/net/route.h =================================================================== --- sys/net/route.h +++ sys/net/route.h @@ -387,16 +387,7 @@ struct sockaddr *rtsock_fix_netmask(const struct sockaddr *dst, const struct sockaddr *smask, struct sockaddr_storage *dmask); -/* - * Note the following locking behavior: - * - * rtfree() and RTFREE_LOCKED() require a locked rtentry - * - * RTFREE() uses an unlocked entry. - */ -void rtfree(struct rtentry *); -void rtfree_func(struct rtentry *); void rt_updatemtu(struct ifnet *); void rt_flushifroutes_af(struct ifnet *, int); Index: sys/net/route.c =================================================================== --- sys/net/route.c +++ sys/net/route.c @@ -122,14 +122,10 @@ #define V_rt_tables VNET(rt_tables) -VNET_DEFINE(uma_zone_t, rtzone); /* Routing table UMA zone. */ -#define V_rtzone VNET(rtzone) - EVENTHANDLER_LIST_DEFINE(rt_addrmsg); static int rt_ifdelroute(const struct rtentry *rt, const struct nhop_object *, void *arg); -static void destroy_rtentry_epoch(epoch_context_t ctx); static int rt_exportinfo(struct rtentry *rt, struct rt_addrinfo *info, int flags); @@ -207,44 +203,7 @@ } SYSINIT(route_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, route_init, NULL); -static int -rtentry_zinit(void *mem, int size, int how) -{ - struct rtentry *rt = mem; - - RT_LOCK_INIT(rt); - - return (0); -} - static void -rtentry_zfini(void *mem, int size) -{ - struct rtentry *rt = mem; - - RT_LOCK_DESTROY(rt); -} - -static int -rtentry_ctor(void *mem, int size, void *arg, int how) -{ - struct rtentry *rt = mem; - - bzero(rt, offsetof(struct rtentry, rt_endzero)); - rt->rt_chain = NULL; - - return (0); -} - -static void -rtentry_dtor(void *mem, int size, void *arg) -{ - struct rtentry *rt = mem; - - RT_UNLOCK_COND(rt); -} - -static void vnet_route_init(const void *unused __unused) { struct domain *dom; @@ -255,9 +214,7 @@ V_rt_tables = malloc(rt_numfibs * (AF_MAX+1) * sizeof(struct rib_head *), M_RTABLE, M_WAITOK|M_ZERO); - V_rtzone = uma_zcreate("rtentry", sizeof(struct rtentry), - rtentry_ctor, rtentry_dtor, - rtentry_zinit, rtentry_zfini, UMA_ALIGN_PTR, 0); + vnet_rtzone_init(); for (dom = domains; dom; dom = dom->dom_next) { if (dom->dom_rtattach == NULL) continue; @@ -314,7 +271,7 @@ epoch_drain_callbacks(net_epoch_preempt); free(V_rt_tables, M_RTABLE); - uma_zdestroy(V_rtzone); + vnet_rtzone_destroy(); } VNET_SYSUNINIT(vnet_route_uninit, SI_SUB_PROTO_DOMAIN, SI_ORDER_FIRST, vnet_route_uninit, 0); @@ -403,55 +360,6 @@ return EINVAL; td->td_proc->p_fibnum = uap->fibnum; return (0); -} - -/* - * Remove a reference count from an rtentry. - * If the count gets low enough, take it out of the routing table - */ -void -rtfree(struct rtentry *rt) -{ - - KASSERT(rt != NULL,("%s: NULL rt", __func__)); - - RT_LOCK_ASSERT(rt); - - RT_UNLOCK(rt); - epoch_call(net_epoch_preempt, destroy_rtentry_epoch, - &rt->rt_epoch_ctx); -} - -static void -destroy_rtentry(struct rtentry *rt) -{ - - /* - * At this moment rnh, nh_control may be already freed. - * nhop interface may have been migrated to a different vnet. - * Use vnet stored in the nexthop to delete the entry. - */ - CURVNET_SET(nhop_get_vnet(rt->rt_nhop)); - - /* Unreference nexthop */ - nhop_free(rt->rt_nhop); - - uma_zfree(V_rtzone, rt); - - CURVNET_RESTORE(); -} - -/* - * Epoch callback indicating rtentry is safe to destroy - */ -static void -destroy_rtentry_epoch(epoch_context_t ctx) -{ - struct rtentry *rt; - - rt = __containerof(ctx, struct rtentry, rt_epoch_ctx); - - destroy_rtentry(rt); } /* Index: sys/net/route/route_ctl.c =================================================================== --- sys/net/route/route_ctl.c +++ sys/net/route/route_ctl.c @@ -87,6 +87,77 @@ static void destroy_subscription_epoch(epoch_context_t ctx); +/* Routing table UMA zone */ +VNET_DEFINE_STATIC(uma_zone_t, rtzone); +#define V_rtzone VNET(rtzone) + +void +vnet_rtzone_init() +{ + + V_rtzone = uma_zcreate("rtentry", sizeof(struct rtentry), + NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); +} + +#ifdef VIMAGE +void +vnet_rtzone_destroy() +{ + + uma_zdestroy(V_rtzone); +} +#endif + +static void +destroy_rtentry(struct rtentry *rt) +{ + + /* + * At this moment rnh, nh_control may be already freed. + * nhop interface may have been migrated to a different vnet. + * Use vnet stored in the nexthop to delete the entry. + */ + CURVNET_SET(nhop_get_vnet(rt->rt_nhop)); + + /* Unreference nexthop */ + nhop_free(rt->rt_nhop); + + uma_zfree(V_rtzone, rt); + + CURVNET_RESTORE(); +} + +/* + * Epoch callback indicating rtentry is safe to destroy + */ +static void +destroy_rtentry_epoch(epoch_context_t ctx) +{ + struct rtentry *rt; + + rt = __containerof(ctx, struct rtentry, rt_epoch_ctx); + + destroy_rtentry(rt); +} + +/* + * Schedule rtentry deletion + */ +static void +rtfree(struct rtentry *rt) +{ + + KASSERT(rt != NULL, ("%s: NULL rt", __func__)); + + RT_LOCK_ASSERT(rt); + + RT_UNLOCK(rt); + epoch_call(net_epoch_preempt, destroy_rtentry_epoch, + &rt->rt_epoch_ctx); +} + + + static struct rib_head * get_rnh(uint32_t fibnum, const struct rt_addrinfo *info) { @@ -173,12 +244,13 @@ return (error); } - rt = uma_zalloc(V_rtzone, M_NOWAIT); + rt = uma_zalloc(V_rtzone, M_NOWAIT | M_ZERO); if (rt == NULL) { ifa_free(info->rti_ifa); nhop_free(nh); return (ENOBUFS); } + RT_LOCK_INIT(rt); rt->rt_flags = RTF_UP | flags; rt->rt_nhop = nh; @@ -219,6 +291,7 @@ RIB_WUNLOCK(rnh); nhop_free(nh); + RT_LOCK_DESTROY(rt); uma_zfree(V_rtzone, rt); return (EEXIST); } @@ -286,6 +359,7 @@ */ if (rn == NULL) { nhop_free(nh); + RT_LOCK_DESTROY(rt); uma_zfree(V_rtzone, rt); return (EEXIST); } Index: sys/net/route/route_var.h =================================================================== --- sys/net/route/route_var.h +++ sys/net/route/route_var.h @@ -237,4 +237,8 @@ void tmproutes_init(struct rib_head *rh); void tmproutes_destroy(struct rib_head *rh); +/* route_ctl.c */ +void vnet_rtzone_init(void); +void vnet_rtzone_destroy(void); + #endif Index: sys/net/route/shared.h =================================================================== --- sys/net/route/shared.h +++ sys/net/route/shared.h @@ -72,9 +72,6 @@ void rib_destroy_subscriptions(struct rib_head *rnh); /* route */ -VNET_DECLARE(uma_zone_t, rtzone); /* Routing table UMA zone. */ -#define V_rtzone VNET(rtzone) - struct rtentry *rt_unlinkrte(struct rib_head *rnh, struct rt_addrinfo *info, int *perror);