From 6cbadc42341b0cb4b0aa32fa96129c56138afcf7 Mon Sep 17 00:00:00 2001 From: "Alexander V. Chernikov" Date: Thu, 13 Aug 2020 18:35:29 +0000 Subject: [PATCH] Move rtzone handling code to net/route_ctl.c After moving the route control plane code from net/route.c, all rtzone users ended up being in net/route_ctl.c. Move uma(9) rtzone setup/teardown code to net/route_ctl.c as well to have everything in a single place. While here, remove custom initializers from the zone. It was added originally to avoid setup/teardown of costy per-cpu couters. With these counters removed, the only remaining job was avoiding rte mutex setup/teardown. Mutex setup is relatively cheap. Additionally, this mutex will soon be removed. With that in mind, there is no sense in keeping custom zone callbacks. Differential Revision: https://reviews.freebsd.org/D26051 --- sys/net/route.c | 96 +-------------------------------------- sys/net/route.h | 9 ---- sys/net/route/route_ctl.c | 76 ++++++++++++++++++++++++++++++- sys/net/route/route_var.h | 4 ++ sys/net/route/shared.h | 3 -- 5 files changed, 81 insertions(+), 107 deletions(-) diff --git a/sys/net/route.c b/sys/net/route.c index 8795dde4372..2f9baa68552 100644 --- a/sys/net/route.c +++ b/sys/net/route.c @@ -122,14 +122,10 @@ VNET_DEFINE(struct rib_head *, rt_tables); #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,43 +203,6 @@ route_init(void) } 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) { @@ -255,9 +214,7 @@ vnet_route_init(const void *unused __unused) 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 @@ vnet_route_uninit(const void *unused __unused) 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); @@ -405,55 +362,6 @@ sys_setfib(struct thread *td, struct setfib_args *uap) 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); -} - /* * Adds a temporal redirect entry to the routing table. * @fibnum: fib number diff --git a/sys/net/route.h b/sys/net/route.h index 1ffabcbc86d..b8a98007a41 100644 --- a/sys/net/route.h +++ b/sys/net/route.h @@ -387,16 +387,7 @@ int rtsock_routemsg_info(int, struct rt_addrinfo *, int); 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); diff --git a/sys/net/route/route_ctl.c b/sys/net/route/route_ctl.c index 7debef06ce8..212f5b51e5b 100644 --- a/sys/net/route/route_ctl.c +++ b/sys/net/route/route_ctl.c @@ -87,6 +87,77 @@ static void rib_notify(struct rib_head *rnh, enum rib_subscription_type type, 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 @@ add_route(struct rib_head *rnh, struct rt_addrinfo *info, 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 @@ add_route(struct rib_head *rnh, struct rt_addrinfo *info, RIB_WUNLOCK(rnh); nhop_free(nh); + RT_LOCK_DESTROY(rt); uma_zfree(V_rtzone, rt); return (EEXIST); } @@ -286,6 +359,7 @@ add_route(struct rib_head *rnh, struct rt_addrinfo *info, */ if (rn == NULL) { nhop_free(nh); + RT_LOCK_DESTROY(rt); uma_zfree(V_rtzone, rt); return (EEXIST); } diff --git a/sys/net/route/route_var.h b/sys/net/route/route_var.h index 3632aaf07c4..a55835ffa9d 100644 --- a/sys/net/route/route_var.h +++ b/sys/net/route/route_var.h @@ -237,4 +237,8 @@ void tmproutes_update(struct rib_head *rnh, struct rtentry *rt); 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 diff --git a/sys/net/route/shared.h b/sys/net/route/shared.h index 4ea20c5e011..3d68f5db0c8 100644 --- a/sys/net/route/shared.h +++ b/sys/net/route/shared.h @@ -72,9 +72,6 @@ void rib_init_subscriptions(struct rib_head *rnh); 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); -- 2.45.0