diff options
author | melifaro <melifaro@FreeBSD.org> | 2015-08-08 18:14:59 +0000 |
---|---|---|
committer | melifaro <melifaro@FreeBSD.org> | 2015-08-08 18:14:59 +0000 |
commit | 33c52eed1855d2984aa791416cb5bb850d2097fa (patch) | |
tree | c3479630a644ca1ee6c62d252dedc4067486c3b8 | |
parent | 20bb5966e2075bde042b8b62c236e29d6e8934da (diff) | |
download | FreeBSD-src-33c52eed1855d2984aa791416cb5bb850d2097fa.zip FreeBSD-src-33c52eed1855d2984aa791416cb5bb850d2097fa.tar.gz |
MFP r274295:
* Move interface route cleanup to route.c:rt_flushifroutes()
* Convert most of "for (fibnum = 0; fibnum < rt_numfibs; fibnum++)" users
to use new rt_foreach_fib() instead of hand-rolling cycles.
-rw-r--r-- | sys/net/if.c | 65 | ||||
-rw-r--r-- | sys/net/route.c | 91 | ||||
-rw-r--r-- | sys/net/route.h | 5 | ||||
-rw-r--r-- | sys/netinet/in_rmx.c | 36 | ||||
-rw-r--r-- | sys/netinet6/in6_rmx.c | 30 | ||||
-rw-r--r-- | sys/netinet6/nd6_rtr.c | 17 |
6 files changed, 132 insertions, 112 deletions
diff --git a/sys/net/if.c b/sys/net/if.c index 6ebfdbf..9997692 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -166,7 +166,6 @@ static int if_setflag(struct ifnet *, int, int, int *, int); 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); @@ -885,8 +884,7 @@ static void if_detach_internal(struct ifnet *ifp, int vmove, struct if_clone **ifcp) { struct ifaddr *ifa; - struct radix_node_head *rnh; - int i, j; + int i; struct domain *dp; struct ifnet *iter; int found = 0; @@ -974,23 +972,7 @@ if_detach_internal(struct ifnet *ifp, int vmove, struct if_clone **ifcp) } } - /* - * 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); /* @@ -1411,49 +1393,6 @@ if_getgroupmembers(struct ifgroupreq *data) } /* - * 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 diff --git a/sys/net/route.c b/sys/net/route.c index a887422..90dd843 100644 --- a/sys/net/route.c +++ b/sys/net/route.c @@ -139,6 +139,7 @@ static VNET_DEFINE(uma_zone_t, rtzone); /* Routing table UMA zone. */ 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); struct if_mtuinfo { @@ -811,6 +812,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!!! diff --git a/sys/net/route.h b/sys/net/route.h index ef00877..dc72d05 100644 --- a/sys/net/route.h +++ b/sys/net/route.h @@ -380,6 +380,11 @@ void rtfree(struct rtentry *); int rt_check(struct rtentry **, struct rtentry **, struct sockaddr *); void rt_updatemtu(struct ifnet *); +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 *); diff --git a/sys/netinet/in_rmx.c b/sys/netinet/in_rmx.c index a53a7ac..39b8832 100644 --- a/sys/netinet/in_rmx.c +++ b/sys/netinet/in_rmx.c @@ -53,6 +53,11 @@ extern int in_inithead(void **head, int off); 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); + /* * Do what we need to do when inserting a route. */ @@ -153,10 +158,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 && @@ -189,26 +193,30 @@ in_ifadownkill(struct radix_node *rn, void *xap) 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? */ } /* diff --git a/sys/netinet6/in6_rmx.c b/sys/netinet6/in6_rmx.c index 9aef3db..dfaac91 100644 --- a/sys/netinet6/in6_rmx.c +++ b/sys/netinet6/in6_rmx.c @@ -189,15 +189,10 @@ static VNET_DEFINE(struct callout, rtq_mtutimer); #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; struct mtuex_arg *ap = rock; - /* sanity */ - if (!rt) - panic("rt == NULL in in6_mtuexpire"); - if (rt->rt_expire && !(rt->rt_flags & RTF_PROBEMTU)) { if (rt->rt_expire <= time_uptime) { rt->rt_flags |= RTF_PROBEMTU; @@ -206,36 +201,29 @@ in6_mtuexpire(struct radix_node *rn, void *rock) } } - 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; - arg.nextstop = time_uptime + MTUTIMO_DEFAULT; - 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; diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c index 0576aa2..e983995 100644 --- a/sys/netinet6/nd6_rtr.c +++ b/sys/netinet6/nd6_rtr.c @@ -88,7 +88,7 @@ static void in6_init_address_ltimes(struct nd_prefix *, 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) @@ -2067,30 +2067,19 @@ in6_init_address_ltimes(struct nd_prefix *new, struct in6_addrlifetime *lt6) 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) |