diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-10-07 15:10:20 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2017-01-10 09:53:31 +0100 |
commit | c40e45b75eb76d79a05c7fa85c1fa9b5c728a12f (patch) | |
tree | ad4f2519067709f00ab98b3c591186c26dc3a21f /freebsd/sys/netinet/in_rmx.c | |
parent | userspace-header-gen.py: Simplify program ports (diff) | |
download | rtems-libbsd-c40e45b75eb76d79a05c7fa85c1fa9b5c728a12f.tar.bz2 |
Update to FreeBSD head 2016-08-23
Git mirror commit 9fe7c416e6abb28b1398fd3e5687099846800cfd.
Diffstat (limited to 'freebsd/sys/netinet/in_rmx.c')
-rw-r--r-- | freebsd/sys/netinet/in_rmx.c | 377 |
1 files changed, 36 insertions, 341 deletions
diff --git a/freebsd/sys/netinet/in_rmx.c b/freebsd/sys/netinet/in_rmx.c index 939193f6..2062d1d1 100644 --- a/freebsd/sys/netinet/in_rmx.c +++ b/freebsd/sys/netinet/in_rmx.c @@ -38,11 +38,11 @@ __FBSDID("$FreeBSD$"); #include <sys/sysctl.h> #include <sys/socket.h> #include <sys/mbuf.h> -#include <sys/syslog.h> -#include <sys/callout.h> #include <net/if.h> +#include <net/if_var.h> #include <net/route.h> +#include <net/route_var.h> #include <net/vnet.h> #include <netinet/in.h> @@ -56,19 +56,16 @@ extern int in_inithead(void **head, int off); extern int in_detachhead(void **head, int off); #endif -#define RTPRF_OURS RTF_PROTO3 /* set on routes we manage */ - /* * Do what we need to do when inserting a route. */ static struct radix_node * -in_addroute(void *v_arg, void *n_arg, struct radix_node_head *head, +in_addroute(void *v_arg, void *n_arg, struct radix_head *head, struct radix_node *treenodes) { struct rtentry *rt = (struct rtentry *)treenodes; struct sockaddr_in *sin = (struct sockaddr_in *)rt_key(rt); - RADIX_NODE_HEAD_WLOCK_ASSERT(head); /* * A little bit of help for both IP output and input: * For host routes, we make sure that RTF_BROADCAST @@ -95,247 +92,20 @@ in_addroute(void *v_arg, void *n_arg, struct radix_node_head *head, if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) rt->rt_flags |= RTF_MULTICAST; - if (!rt->rt_rmx.rmx_mtu && rt->rt_ifp) - rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; - - return (rn_addroute(v_arg, n_arg, head, treenodes)); -} - -/* - * This code is the inverse of in_clsroute: on first reference, if we - * were managing the route, stop doing so and set the expiration timer - * back off again. - */ -static struct radix_node * -in_matroute(void *v_arg, struct radix_node_head *head) -{ - struct radix_node *rn = rn_match(v_arg, head); - struct rtentry *rt = (struct rtentry *)rn; - - if (rt) { - RT_LOCK(rt); - if (rt->rt_flags & RTPRF_OURS) { - rt->rt_flags &= ~RTPRF_OURS; - rt->rt_rmx.rmx_expire = 0; - } - RT_UNLOCK(rt); - } - return rn; -} - -static VNET_DEFINE(int, rtq_reallyold) = 60*60; /* one hour is "really old" */ -#define V_rtq_reallyold VNET(rtq_reallyold) -SYSCTL_VNET_INT(_net_inet_ip, IPCTL_RTEXPIRE, rtexpire, CTLFLAG_RW, - &VNET_NAME(rtq_reallyold), 0, - "Default expiration time on dynamically learned routes"); - -/* never automatically crank down to less */ -static VNET_DEFINE(int, rtq_minreallyold) = 10; -#define V_rtq_minreallyold VNET(rtq_minreallyold) -SYSCTL_VNET_INT(_net_inet_ip, IPCTL_RTMINEXPIRE, rtminexpire, CTLFLAG_RW, - &VNET_NAME(rtq_minreallyold), 0, - "Minimum time to attempt to hold onto dynamically learned routes"); - -/* 128 cached routes is "too many" */ -static VNET_DEFINE(int, rtq_toomany) = 128; -#define V_rtq_toomany VNET(rtq_toomany) -SYSCTL_VNET_INT(_net_inet_ip, IPCTL_RTMAXCACHE, rtmaxcache, CTLFLAG_RW, - &VNET_NAME(rtq_toomany), 0, - "Upper limit on dynamically learned routes"); - -/* - * On last reference drop, mark the route as belong to us so that it can be - * timed out. - */ -static void -in_clsroute(struct radix_node *rn, struct radix_node_head *head) -{ - struct rtentry *rt = (struct rtentry *)rn; - - RT_LOCK_ASSERT(rt); - - if (!(rt->rt_flags & RTF_UP)) - return; /* prophylactic measures */ - - if (rt->rt_flags & RTPRF_OURS) - return; - - if (!(rt->rt_flags & RTF_DYNAMIC)) - return; - - /* - * If rtq_reallyold is 0, just delete the route without - * waiting for a timeout cycle to kill it. - */ - if (V_rtq_reallyold != 0) { - rt->rt_flags |= RTPRF_OURS; - rt->rt_rmx.rmx_expire = time_uptime + V_rtq_reallyold; - } else { - rtexpunge(rt); - } -} - -struct rtqk_arg { - struct radix_node_head *rnh; - int draining; - int killed; - int found; - int updating; - time_t nextstop; -}; - -/* - * Get rid of old routes. When draining, this deletes everything, even when - * the timeout is not expired yet. When updating, this makes sure that - * nothing has a timeout longer than the current value of rtq_reallyold. - */ -static int -in_rtqkill(struct radix_node *rn, void *rock) -{ - struct rtqk_arg *ap = rock; - struct rtentry *rt = (struct rtentry *)rn; - int err; - - RADIX_NODE_HEAD_WLOCK_ASSERT(ap->rnh); - - if (rt->rt_flags & RTPRF_OURS) { - ap->found++; - - if (ap->draining || rt->rt_rmx.rmx_expire <= time_uptime) { - if (rt->rt_refcnt > 0) - panic("rtqkill route really not free"); - - err = in_rtrequest(RTM_DELETE, - (struct sockaddr *)rt_key(rt), - rt->rt_gateway, rt_mask(rt), - rt->rt_flags | RTF_RNH_LOCKED, 0, - rt->rt_fibnum); - if (err) { - log(LOG_WARNING, "in_rtqkill: error %d\n", err); - } else { - ap->killed++; - } - } else { - if (ap->updating && - (rt->rt_rmx.rmx_expire - time_uptime > - V_rtq_reallyold)) { - rt->rt_rmx.rmx_expire = - time_uptime + V_rtq_reallyold; - } - ap->nextstop = lmin(ap->nextstop, - rt->rt_rmx.rmx_expire); - } - } - - return 0; -} - -#define RTQ_TIMEOUT 60*10 /* run no less than once every ten minutes */ -static VNET_DEFINE(int, rtq_timeout) = RTQ_TIMEOUT; -static VNET_DEFINE(struct callout, rtq_timer); - -#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(void *rock) -{ - CURVNET_SET((struct vnet *) rock); - int fibnum; - void *newrock; - 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); - } - atv.tv_usec = 0; - atv.tv_sec = V_rtq_timeout; - callout_reset(&V_rtq_timer, tvtohz(&atv), in_rtqtimo, rock); - CURVNET_RESTORE(); -} + if (rt->rt_ifp != NULL) { -static void -in_rtqtimo_one(void *rock) -{ - struct radix_node_head *rnh = rock; - struct rtqk_arg arg; - static time_t last_adjusted_timeout = 0; - - arg.found = arg.killed = 0; - arg.rnh = rnh; - arg.nextstop = time_uptime + V_rtq_timeout; - arg.draining = arg.updating = 0; - RADIX_NODE_HEAD_LOCK(rnh); - rnh->rnh_walktree(rnh, in_rtqkill, &arg); - RADIX_NODE_HEAD_UNLOCK(rnh); - - /* - * Attempt to be somewhat dynamic about this: - * If there are ``too many'' routes sitting around taking up space, - * then crank down the timeout, and see if we can't make some more - * go away. However, we make sure that we will never adjust more - * than once in rtq_timeout seconds, to keep from cranking down too - * hard. - */ - if ((arg.found - arg.killed > V_rtq_toomany) && - (time_uptime - last_adjusted_timeout >= V_rtq_timeout) && - V_rtq_reallyold > V_rtq_minreallyold) { - V_rtq_reallyold = 2 * V_rtq_reallyold / 3; - if (V_rtq_reallyold < V_rtq_minreallyold) { - V_rtq_reallyold = V_rtq_minreallyold; - } - - last_adjusted_timeout = time_uptime; -#ifdef DIAGNOSTIC - log(LOG_DEBUG, "in_rtqtimo: adjusted rtq_reallyold to %d\n", - V_rtq_reallyold); -#endif - arg.found = arg.killed = 0; - arg.updating = 1; - 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; - - 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.nextstop = 0; - arg.draining = 1; - arg.updating = 0; - RADIX_NODE_HEAD_LOCK(rnh); - rnh->rnh_walktree(rnh, in_rtqkill, &arg); - RADIX_NODE_HEAD_UNLOCK(rnh); - } - CURVNET_RESTORE(); + /* + * Check route MTU: + * inherit interface MTU if not set or + * check if MTU is too large. + */ + if (rt->rt_mtu == 0) { + rt->rt_mtu = rt->rt_ifp->if_mtu; + } else if (rt->rt_mtu > rt->rt_ifp->if_mtu) + rt->rt_mtu = rt->rt_ifp->if_mtu; } - VNET_LIST_RUNLOCK_NOSLEEP(); -} -void -in_setmatchfunc(struct radix_node_head *rnh, int val) -{ - - rnh->rnh_matchaddr = (val != 0) ? rn_match : in_matroute; + return (rn_addroute(v_arg, n_arg, head, treenodes)); } static int _in_rt_was_here; @@ -345,29 +115,16 @@ static int _in_rt_was_here; int in_inithead(void **head, int off) { - struct radix_node_head *rnh; + struct rib_head *rh; - /* XXX MRT - * This can be called from vfs_export.c too in which case 'off' - * will be 0. We know the correct value so just use that and - * return directly if it was 0. - * This is a hack that replaces an even worse hack on a bad hack - * on a bad design. After RELENG_7 this should be fixed but that - * will change the ABI, so for now do it this way. - */ - if (!rn_inithead(head, 32)) - return 0; + rh = rt_table_init(32); + if (rh == NULL) + return (0); - if (off == 0) /* XXX MRT see above */ - return 1; /* only do the rest for a real routing table */ + rh->rnh_addaddr = in_addroute; + *head = (void *)rh; - rnh = *head; - rnh->rnh_addaddr = in_addroute; - in_setmatchfunc(rnh, V_drop_redirect); - rnh->rnh_close = in_clsroute; if (_in_rt_was_here == 0 ) { - callout_init(&V_rtq_timer, CALLOUT_MPSAFE); - callout_reset(&V_rtq_timer, 1, in_rtqtimo, curvnet); _in_rt_was_here = 1; } return 1; @@ -378,7 +135,7 @@ int in_detachhead(void **head, int off) { - callout_drain(&V_rtq_timer); + rt_table_destroy((struct rib_head *)(*head)); return (1); } #endif @@ -398,62 +155,32 @@ struct in_ifadown_arg { }; static int -in_ifadownkill(struct radix_node *rn, void *xap) +in_ifadownkill(const 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 && - (ap->del || !(rt->rt_flags & RTF_STATIC))) { - /* - * Aquire a reference so that it can later be freed - * as the refcount would be 0 here in case of at least - * ap->del. - */ - RT_ADDREF(rt); - /* - * Disconnect it from the tree and permit protocols - * to cleanup. - */ - rtexpunge(rt); - /* - * At this point it is an rttrash node, and in case - * the above is the only reference we must free it. - * If we do not noone will have a pointer and the - * rtentry will be leaked forever. - * In case someone else holds a reference, we are - * fine as we only decrement the refcount. In that - * case if the other entity calls RT_REMREF, we - * will still be leaking but at least we tried. - */ - RTFREE_LOCKED(rt); + if (rt->rt_ifa != ap->ifa) return (0); - } - RT_UNLOCK(rt); - return 0; + + if ((rt->rt_flags & RTF_STATIC) != 0 && ap->del == 0) + return (0); + + return (1); } -int +void in_ifadown(struct ifaddr *ifa, int delete) { struct in_ifadown_arg arg; - struct radix_node_head *rnh; - int fibnum; - if (ifa->ifa_addr->sa_family != AF_INET) - return 1; + 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.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? */ - } - return 0; + arg.ifa = ifa; + arg.del = delete; + + rt_foreach_fib_walk_del(AF_INET, in_ifadownkill, &arg); + ifa->ifa_flags &= ~IFA_ROUTE; /* XXXlocking? */ } /* @@ -467,25 +194,6 @@ in_rtalloc_ign(struct route *ro, u_long ignflags, u_int fibnum) rtalloc_ign_fib(ro, ignflags, fibnum); } -int -in_rtrequest( int req, - struct sockaddr *dst, - struct sockaddr *gateway, - struct sockaddr *netmask, - int flags, - struct rtentry **ret_nrt, - u_int fibnum) -{ - return (rtrequest_fib(req, dst, gateway, netmask, - flags, ret_nrt, fibnum)); -} - -struct rtentry * -in_rtalloc1(struct sockaddr *dst, int report, u_long ignflags, u_int fibnum) -{ - return (rtalloc1_fib(dst, report, ignflags, fibnum)); -} - void in_rtredirect(struct sockaddr *dst, struct sockaddr *gateway, @@ -497,16 +205,3 @@ in_rtredirect(struct sockaddr *dst, rtredirect_fib(dst, gateway, netmask, flags, src, fibnum); } -void -in_rtalloc(struct route *ro, u_int fibnum) -{ - rtalloc_ign_fib(ro, 0UL, fibnum); -} - -#if 0 -int in_rt_getifa(struct rt_addrinfo *, u_int fibnum); -int in_rtioctl(u_long, caddr_t, u_int); -int in_rtrequest1(int, struct rt_addrinfo *, struct rtentry **, u_int); -#endif - - |