From owner-svn-src-projects@FreeBSD.ORG Sat Nov 8 16:38:17 2014 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 4B307DA7; Sat, 8 Nov 2014 16:38:17 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 3650A156; Sat, 8 Nov 2014 16:38:17 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id sA8GcHMC006039; Sat, 8 Nov 2014 16:38:17 GMT (envelope-from melifaro@FreeBSD.org) Received: (from melifaro@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id sA8GcFsq006029; Sat, 8 Nov 2014 16:38:15 GMT (envelope-from melifaro@FreeBSD.org) Message-Id: <201411081638.sA8GcFsq006029@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: melifaro set sender to melifaro@FreeBSD.org using -f From: "Alexander V. Chernikov" Date: Sat, 8 Nov 2014 16:38:15 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r274295 - in projects/routing/sys: net netinet netinet6 X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 08 Nov 2014 16:38:17 -0000 Author: melifaro Date: Sat Nov 8 16:38:15 2014 New Revision: 274295 URL: https://svnweb.freebsd.org/changeset/base/274295 Log: Convert most of "for (fibnum = 0; fibnum < rt_numfibs; fibnum++)" users to use new rt_foreach_fib() instead of hand-rolling cycles. Modified: projects/routing/sys/net/if.c projects/routing/sys/net/route.c projects/routing/sys/net/route.h projects/routing/sys/netinet/in_rmx.c projects/routing/sys/netinet6/in6_rmx.c projects/routing/sys/netinet6/nd6_rtr.c Modified: projects/routing/sys/net/if.c ============================================================================== --- projects/routing/sys/net/if.c Sat Nov 8 16:37:59 2014 (r274294) +++ projects/routing/sys/net/if.c Sat Nov 8 16:38:15 2014 (r274295) @@ -171,7 +171,6 @@ static int if_setflag(struct ifnet *, in static int if_transmit(struct ifnet *ifp, struct mbuf *m); static void if_unroute(struct ifnet *, int flag, int fam); static void link_rtrequest(int, struct rtentry *, struct rt_addrinfo *); -static int if_rtdel(struct radix_node *, void *); static int ifhwioctl(u_long, struct ifnet *, caddr_t, struct thread *); static int if_delmulti_locked(struct ifnet *, struct ifmultiaddr *, int); static void do_link_state_change(void *, int); @@ -896,8 +895,7 @@ static void if_detach_internal(struct ifnet *ifp, int vmove) { struct ifaddr *ifa; - struct radix_node_head *rnh; - int i, j; + int i; struct domain *dp; struct ifnet *iter; int found = 0; @@ -981,23 +979,7 @@ if_detach_internal(struct ifnet *ifp, in } } - /* - * Delete all remaining routes using this interface - * Unfortuneatly the only way to do this is to slog through - * the entire routing table looking for routes which point - * to this interface...oh well... - */ - for (i = 1; i <= AF_MAX; i++) { - for (j = 0; j < rt_numfibs; j++) { - rnh = rt_tables_get_rnh(j, i); - if (rnh == NULL) - continue; - RADIX_NODE_HEAD_LOCK(rnh); - (void) rnh->rnh_walktree(rnh, if_rtdel, ifp); - RADIX_NODE_HEAD_UNLOCK(rnh); - } - } - + rt_flushifroutes(ifp); if_delgroups(ifp); /* @@ -1422,49 +1404,6 @@ if_getgroupmembers(struct ifgroupreq *da } /* - * Delete Routes for a Network Interface - * - * Called for each routing entry via the rnh->rnh_walktree() call above - * to delete all route entries referencing a detaching network interface. - * - * Arguments: - * rn pointer to node in the routing table - * arg argument passed to rnh->rnh_walktree() - detaching interface - * - * Returns: - * 0 successful - * errno failed - reason indicated - * - */ -static int -if_rtdel(struct radix_node *rn, void *arg) -{ - struct rtentry *rt = (struct rtentry *)rn; - struct ifnet *ifp = arg; - int err; - - if (rt->rt_ifp == ifp) { - - /* - * Protect (sorta) against walktree recursion problems - * with cloned routes - */ - if ((rt->rt_flags & RTF_UP) == 0) - return (0); - - err = rtrequest_fib(RTM_DELETE, rt_key(rt), rt->rt_gateway, - rt_mask(rt), - rt->rt_flags|RTF_RNH_LOCKED|RTF_PINNED, - (struct rtentry **) NULL, rt->rt_fibnum); - if (err) { - log(LOG_WARNING, "if_rtdel: error %d\n", err); - } - } - - return (0); -} - -/* * Return counter values from counter(9)s stored in ifnet. */ uint64_t Modified: projects/routing/sys/net/route.c ============================================================================== --- projects/routing/sys/net/route.c Sat Nov 8 16:37:59 2014 (r274294) +++ projects/routing/sys/net/route.c Sat Nov 8 16:38:15 2014 (r274295) @@ -141,6 +141,7 @@ static VNET_DEFINE(uma_zone_t, rtzone); static int rtrequest1_fib_change(struct radix_node_head *, struct rt_addrinfo *, struct rtentry **, u_int); static void rt_setmetrics(const struct rt_addrinfo *, struct rtentry *); +static int rt_ifdelroute(struct rtentry *rt, void *arg); /* * handler for net.my_fibnum @@ -810,6 +811,96 @@ rtrequest_fib(int req, return rtrequest1_fib(req, &info, ret_nrt, fibnum); } + +void +rt_foreach_fib(int af, rt_setwarg_t *setwa_f, rt_walktree_f_t *wa_f, void *arg) +{ + struct radix_node_head *rnh; + uint32_t fibnum; + int i; + + for (fibnum = 0; fibnum < rt_numfibs; fibnum++) { + /* Do we want some specific family? */ + if (af != AF_UNSPEC) { + rnh = rt_tables_get_rnh(fibnum, af); + if (rnh == NULL) + continue; + if (setwa_f != NULL) + setwa_f(rnh, fibnum, i, arg); + + RADIX_NODE_HEAD_LOCK(rnh); + rnh->rnh_walktree(rnh, (walktree_f_t *)wa_f, arg); + RADIX_NODE_HEAD_UNLOCK(rnh); + continue; + } + + for (i = 1; i <= AF_MAX; i++) { + rnh = rt_tables_get_rnh(fibnum, i); + if (rnh == NULL) + continue; + if (setwa_f != NULL) + setwa_f(rnh, fibnum, i, arg); + + RADIX_NODE_HEAD_LOCK(rnh); + rnh->rnh_walktree(rnh, (walktree_f_t *)wa_f, arg); + RADIX_NODE_HEAD_UNLOCK(rnh); + } + } +} + +/* + * Delete Routes for a Network Interface + * + * Called for each routing entry via the rnh->rnh_walktree() call above + * to delete all route entries referencing a detaching network interface. + * + * Arguments: + * rt pointer to rtentry + * arg argument passed to rnh->rnh_walktree() - detaching interface + * + * Returns: + * 0 successful + * errno failed - reason indicated + */ +static int +rt_ifdelroute(struct rtentry *rt, void *arg) +{ + struct ifnet *ifp = arg; + int err; + + if (rt->rt_ifp != ifp) + return (0); + + /* + * Protect (sorta) against walktree recursion problems + * with cloned routes + */ + if ((rt->rt_flags & RTF_UP) == 0) + return (0); + + err = rtrequest_fib(RTM_DELETE, rt_key(rt), rt->rt_gateway, + rt_mask(rt), + rt->rt_flags | RTF_RNH_LOCKED | RTF_PINNED, + (struct rtentry **) NULL, rt->rt_fibnum); + if (err != 0) + log(LOG_WARNING, "rt_ifdelroute: error %d\n", err); + + return (0); +} + +/* + * Delete all remaining routes using this interface + * Unfortuneatly the only way to do this is to slog through + * the entire routing table looking for routes which point + * to this interface...oh well... + */ +void +rt_flushifroutes(struct ifnet *ifp) +{ + + rt_foreach_fib(AF_UNSPEC, NULL, rt_ifdelroute, ifp); +} + /* * These (questionable) definitions of apparent local variables apply * to the next two functions. XXXXXX!!! Modified: projects/routing/sys/net/route.h ============================================================================== --- projects/routing/sys/net/route.h Sat Nov 8 16:37:59 2014 (r274294) +++ projects/routing/sys/net/route.h Sat Nov 8 16:38:15 2014 (r274295) @@ -328,6 +328,11 @@ int rt_expunge(struct radix_node_head * void rtfree(struct rtentry *); int rt_check(struct rtentry **, struct rtentry **, struct sockaddr *); +typedef int rt_walktree_f_t(struct rtentry *, void *); +typedef void rt_setwarg_t(struct radix_node_head *, uint32_t, int, void *); +void rt_foreach_fib(int af, rt_setwarg_t *, rt_walktree_f_t *, void *); +void rt_flushifroutes(struct ifnet *ifp); + /* XXX MRT COMPAT VERSIONS THAT SET UNIVERSE to 0 */ /* Thes are used by old code not yet converted to use multiple FIBS */ int rt_getifa(struct rt_addrinfo *); Modified: projects/routing/sys/netinet/in_rmx.c ============================================================================== --- projects/routing/sys/netinet/in_rmx.c Sat Nov 8 16:37:59 2014 (r274294) +++ projects/routing/sys/netinet/in_rmx.c Sat Nov 8 16:38:15 2014 (r274295) @@ -56,6 +56,11 @@ extern int in_inithead(void **head, int extern int in_detachhead(void **head, int off); #endif +static void in_setifarnh(struct radix_node_head *rnh, uint32_t fibnum, + int af, void *_arg); +static void in_rtqtimo_setrnh(struct radix_node_head *rnh, uint32_t fibnum, + int af, void *_arg); + #define RTPRF_OURS RTF_PROTO3 /* set on routes we manage */ /* @@ -172,10 +177,9 @@ struct rtqk_arg { * the timeout is not expired yet. */ static int -in_rtqkill(struct radix_node *rn, void *rock) +in_rtqkill(struct rtentry *rt, void *rock) { struct rtqk_arg *ap = rock; - struct rtentry *rt = (struct rtentry *)rn; int err; RADIX_NODE_HEAD_WLOCK_ASSERT(ap->rnh); @@ -209,62 +213,52 @@ static VNET_DEFINE(struct callout, rtq_t #define V_rtq_timeout VNET(rtq_timeout) #define V_rtq_timer VNET(rtq_timer) -static void in_rtqtimo_one(void *rock); +static void +in_rtqtimo_setrnh(struct radix_node_head *rnh, uint32_t fibnum, int af, + void *_arg) +{ + struct rtqk_arg *arg; + int draining; + + arg = (struct rtqk_arg *)_arg; + + draining = arg->draining; + memset(arg, 0, sizeof(*arg)); + arg->rnh = rnh; + arg->draining = arg->draining; +} static void in_rtqtimo(void *rock) { CURVNET_SET((struct vnet *) rock); - int fibnum; - void *newrock; + struct rtqk_arg arg; struct timeval atv; - for (fibnum = 0; fibnum < rt_numfibs; fibnum++) { - newrock = rt_tables_get_rnh(fibnum, AF_INET); - if (newrock != NULL) - in_rtqtimo_one(newrock); - } + memset(&arg, 0, sizeof(arg)); + rt_foreach_fib(AF_INET, in_rtqtimo_setrnh, in_rtqkill, &arg); + atv.tv_usec = 0; atv.tv_sec = V_rtq_timeout; callout_reset(&V_rtq_timer, tvtohz(&atv), in_rtqtimo, rock); CURVNET_RESTORE(); } -static void -in_rtqtimo_one(void *rock) -{ - struct radix_node_head *rnh = rock; - struct rtqk_arg arg; - - arg.found = arg.killed = 0; - arg.rnh = rnh; - arg.draining = 0; - RADIX_NODE_HEAD_LOCK(rnh); - rnh->rnh_walktree(rnh, in_rtqkill, &arg); - RADIX_NODE_HEAD_UNLOCK(rnh); -} - void in_rtqdrain(void) { VNET_ITERATOR_DECL(vnet_iter); - struct radix_node_head *rnh; struct rtqk_arg arg; - int fibnum; + + memset(&arg, 0, sizeof(arg)); + arg.draining = 1; VNET_LIST_RLOCK_NOSLEEP(); VNET_FOREACH(vnet_iter) { CURVNET_SET(vnet_iter); - for ( fibnum = 0; fibnum < rt_numfibs; fibnum++) { - rnh = rt_tables_get_rnh(fibnum, AF_INET); - arg.found = arg.killed = 0; - arg.rnh = rnh; - arg.draining = 1; - RADIX_NODE_HEAD_LOCK(rnh); - rnh->rnh_walktree(rnh, in_rtqkill, &arg); - RADIX_NODE_HEAD_UNLOCK(rnh); - } + rt_foreach_fib(AF_INET, in_rtqtimo_setrnh, in_rtqkill, &arg); + CURVNET_RESTORE(); } VNET_LIST_RUNLOCK_NOSLEEP(); @@ -341,10 +335,9 @@ struct in_ifadown_arg { }; static int -in_ifadownkill(struct radix_node *rn, void *xap) +in_ifadownkill(struct rtentry *rt, void *xap) { struct in_ifadown_arg *ap = xap; - struct rtentry *rt = (struct rtentry *)rn; RT_LOCK(rt); if (rt->rt_ifa == ap->ifa && @@ -377,26 +370,30 @@ in_ifadownkill(struct radix_node *rn, vo return 0; } +static void +in_setifarnh(struct radix_node_head *rnh, uint32_t fibnum, int af, + void *_arg) +{ + struct in_ifadown_arg *arg; + + arg = (struct in_ifadown_arg *)_arg; + + arg->rnh = rnh; +} + void in_ifadown(struct ifaddr *ifa, int delete) { struct in_ifadown_arg arg; - struct radix_node_head *rnh; - int fibnum; KASSERT(ifa->ifa_addr->sa_family == AF_INET, ("%s: wrong family", __func__)); - for ( fibnum = 0; fibnum < rt_numfibs; fibnum++) { - rnh = rt_tables_get_rnh(fibnum, AF_INET); - arg.rnh = rnh; - arg.ifa = ifa; - arg.del = delete; - RADIX_NODE_HEAD_LOCK(rnh); - rnh->rnh_walktree(rnh, in_ifadownkill, &arg); - RADIX_NODE_HEAD_UNLOCK(rnh); - ifa->ifa_flags &= ~IFA_ROUTE; /* XXXlocking? */ - } + arg.ifa = ifa; + arg.del = delete; + + rt_foreach_fib(AF_INET, in_setifarnh, in_ifadownkill, &arg); + ifa->ifa_flags &= ~IFA_ROUTE; /* XXXlocking? */ } /* Modified: projects/routing/sys/netinet6/in6_rmx.c ============================================================================== --- projects/routing/sys/netinet6/in6_rmx.c Sat Nov 8 16:37:59 2014 (r274294) +++ projects/routing/sys/netinet6/in6_rmx.c Sat Nov 8 16:38:15 2014 (r274295) @@ -188,13 +188,8 @@ static VNET_DEFINE(struct callout, rtq_m #define V_rtq_mtutimer VNET(rtq_mtutimer) static int -in6_mtuexpire(struct radix_node *rn, void *rock) +in6_mtuexpire(struct rtentry *rt, void *rock) { - struct rtentry *rt = (struct rtentry *)rn; - - /* sanity */ - if (!rt) - panic("rt == NULL in in6_mtuexpire"); if (rt->rt_expire && !(rt->rt_flags & RTF_PROBEMTU)) { if (rt->rt_expire <= time_uptime) { @@ -202,35 +197,29 @@ in6_mtuexpire(struct radix_node *rn, voi } } - return 0; + return (0); } #define MTUTIMO_DEFAULT (60*1) static void -in6_mtutimo_one(struct radix_node_head *rnh) +in6_mtutimo_setwa(struct radix_node_head *rnh, uint32_t fibum, int af, void *_arg) { - struct mtuex_arg arg; + struct mtuex_arg *arg; + + arg = (struct mtuex_arg *)_arg; - arg.rnh = rnh; - RADIX_NODE_HEAD_LOCK(rnh); - rnh->rnh_walktree(rnh, in6_mtuexpire, &arg); - RADIX_NODE_HEAD_UNLOCK(rnh); + arg->rnh = rnh; } static void in6_mtutimo(void *rock) { CURVNET_SET_QUIET((struct vnet *) rock); - struct radix_node_head *rnh; struct timeval atv; - u_int fibnum; + struct mtuex_arg arg; - for (fibnum = 0; fibnum < rt_numfibs; fibnum++) { - rnh = rt_tables_get_rnh(fibnum, AF_INET6); - if (rnh != NULL) - in6_mtutimo_one(rnh); - } + rt_foreach_fib(AF_INET6, in6_mtutimo_setwa, in6_mtuexpire, &arg); atv.tv_sec = MTUTIMO_DEFAULT; atv.tv_usec = 0; Modified: projects/routing/sys/netinet6/nd6_rtr.c ============================================================================== --- projects/routing/sys/netinet6/nd6_rtr.c Sat Nov 8 16:37:59 2014 (r274294) +++ projects/routing/sys/netinet6/nd6_rtr.c Sat Nov 8 16:38:15 2014 (r274295) @@ -89,7 +89,7 @@ static void in6_init_address_ltimes(stru static int nd6_prefix_onlink(struct nd_prefix *); static int nd6_prefix_offlink(struct nd_prefix *); -static int rt6_deleteroute(struct radix_node *, void *); +static int rt6_deleteroute(struct rtentry *, void *); VNET_DECLARE(int, nd6_recalc_reachtm_interval); #define V_nd6_recalc_reachtm_interval VNET(nd6_recalc_reachtm_interval) @@ -2060,30 +2060,19 @@ in6_init_address_ltimes(struct nd_prefix void rt6_flush(struct in6_addr *gateway, struct ifnet *ifp) { - struct radix_node_head *rnh; - u_int fibnum; /* We'll care only link-local addresses */ if (!IN6_IS_ADDR_LINKLOCAL(gateway)) return; /* XXX Do we really need to walk any but the default FIB? */ - for (fibnum = 0; fibnum < rt_numfibs; fibnum++) { - rnh = rt_tables_get_rnh(fibnum, AF_INET6); - if (rnh == NULL) - continue; - - RADIX_NODE_HEAD_LOCK(rnh); - rnh->rnh_walktree(rnh, rt6_deleteroute, (void *)gateway); - RADIX_NODE_HEAD_UNLOCK(rnh); - } + rt_foreach_fib(AF_INET6, NULL, rt6_deleteroute, (void *)gateway); } static int -rt6_deleteroute(struct radix_node *rn, void *arg) +rt6_deleteroute(struct rtentry *rt, void *arg) { #define SIN6(s) ((struct sockaddr_in6 *)s) - struct rtentry *rt = (struct rtentry *)rn; struct in6_addr *gate = (struct in6_addr *)arg; if (rt->rt_gateway == NULL || rt->rt_gateway->sa_family != AF_INET6)