in6_rmx.c
来自「eCos操作系统源码」· C语言 代码 · 共 532 行 · 第 1/2 页
C
532 行
struct radix_node *rn = rn_match(v_arg, head); struct rtentry *rt = (struct rtentry *)rn; if (rt && rt->rt_refcnt == 0) { /* this is first reference */ if (rt->rt_flags & RTPRF_OURS) { rt->rt_flags &= ~RTPRF_OURS; rt->rt_rmx.rmx_expire = 0; } } return rn;}SYSCTL_DECL(_net_inet6_ip6);static int rtq_reallyold = 60*60; /* one hour is ``really old'' */SYSCTL_INT(_net_inet6_ip6, IPV6CTL_RTEXPIRE, rtexpire, CTLFLAG_RW, &rtq_reallyold , 0, ""); static int rtq_minreallyold = 10; /* never automatically crank down to less */SYSCTL_INT(_net_inet6_ip6, IPV6CTL_RTMINEXPIRE, rtminexpire, CTLFLAG_RW, &rtq_minreallyold , 0, "");static int rtq_toomany = 128; /* 128 cached routes is ``too many'' */SYSCTL_INT(_net_inet6_ip6, IPV6CTL_RTMAXCACHE, rtmaxcache, CTLFLAG_RW, &rtq_toomany , 0, "");/* * On last reference drop, mark the route as belong to us so that it can be * timed out. */static voidin6_clsroute(struct radix_node *rn, struct radix_node_head *head){ struct rtentry *rt = (struct rtentry *)rn; if (!(rt->rt_flags & RTF_UP)) return; /* prophylactic measures */ if ((rt->rt_flags & (RTF_LLINFO | RTF_HOST)) != RTF_HOST) return; if ((rt->rt_flags & (RTF_WASCLONED | RTPRF_OURS)) != RTF_WASCLONED) return; /* * As requested by David Greenman: * If rtq_reallyold is 0, just delete the route without * waiting for a timeout cycle to kill it. */ if (rtq_reallyold != 0) { rt->rt_flags |= RTPRF_OURS; rt->rt_rmx.rmx_expire = time_second + rtq_reallyold; } else { rtrequest(RTM_DELETE, (struct sockaddr *)rt_key(rt), rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0); }}struct rtqk_arg { struct radix_node_head *rnh; int mode; int updating; int draining; int killed; int found; 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 intin6_rtqkill(struct radix_node *rn, void *rock){ struct rtqk_arg *ap = rock; struct rtentry *rt = (struct rtentry *)rn; int err; if (rt->rt_flags & RTPRF_OURS) { ap->found++; if (ap->draining || rt->rt_rmx.rmx_expire <= time_second) { if (rt->rt_refcnt > 0) panic("rtqkill route really not free"); err = rtrequest(RTM_DELETE, (struct sockaddr *)rt_key(rt), rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0); if (err) { log(LOG_WARNING, "in6_rtqkill: error %d", err); } else { ap->killed++; } } else { if (ap->updating && (rt->rt_rmx.rmx_expire - time_second > rtq_reallyold)) { rt->rt_rmx.rmx_expire = time_second + 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 int rtq_timeout = RTQ_TIMEOUT;static voidin6_rtqtimo(void *rock){ struct radix_node_head *rnh = rock; struct rtqk_arg arg; struct timeval atv; static time_t last_adjusted_timeout = 0; int s; arg.found = arg.killed = 0; arg.rnh = rnh; arg.nextstop = time_second + rtq_timeout; arg.draining = arg.updating = 0; s = splnet(); rnh->rnh_walktree(rnh, in6_rtqkill, &arg); splx(s); /* * 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 > rtq_toomany) && (time_second - last_adjusted_timeout >= rtq_timeout) && rtq_reallyold > rtq_minreallyold) { rtq_reallyold = 2*rtq_reallyold / 3; if (rtq_reallyold < rtq_minreallyold) { rtq_reallyold = rtq_minreallyold; } last_adjusted_timeout = time_second;#ifdef DIAGNOSTIC log(LOG_DEBUG, "in6_rtqtimo: adjusted rtq_reallyold to %d", rtq_reallyold);#endif arg.found = arg.killed = 0; arg.updating = 1; s = splnet(); rnh->rnh_walktree(rnh, in6_rtqkill, &arg); splx(s); } atv.tv_usec = 0; atv.tv_sec = arg.nextstop; timeout(in6_rtqtimo, rock, tvtohz(&atv));}/* * Age old PMTUs. */struct mtuex_arg { struct radix_node_head *rnh; time_t nextstop;};static intin6_mtuexpire(struct radix_node *rn, 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_rmx.rmx_expire && !(rt->rt_flags & RTF_PROBEMTU)) { if (rt->rt_rmx.rmx_expire <= time_second) { rt->rt_flags |= RTF_PROBEMTU; } else { ap->nextstop = lmin(ap->nextstop, rt->rt_rmx.rmx_expire); } } return 0;}#define MTUTIMO_DEFAULT (60*1)static voidin6_mtutimo(void *rock){ struct radix_node_head *rnh = rock; struct mtuex_arg arg; struct timeval atv; int s; arg.rnh = rnh; arg.nextstop = time_second + MTUTIMO_DEFAULT; s = splnet(); rnh->rnh_walktree(rnh, in6_mtuexpire, &arg); splx(s); atv.tv_usec = 0; atv.tv_sec = arg.nextstop; if (atv.tv_sec < time_second) { printf("invalid mtu expiration time on routing table\n"); arg.nextstop = time_second + 30; /* last resort */ } timeout(in6_mtutimo, rock, tvtohz(&atv));}#if 0voidin6_rtqdrain(){ struct radix_node_head *rnh = rt_tables[AF_INET6]; struct rtqk_arg arg; int s; arg.found = arg.killed = 0; arg.rnh = rnh; arg.nextstop = 0; arg.draining = 1; arg.updating = 0; s = splnet(); rnh->rnh_walktree(rnh, in6_rtqkill, &arg); splx(s);}#endif/* * Initialize our routing tree. */intin6_inithead(void **head, int off){ struct radix_node_head *rnh; if (!rn_inithead(head, off)) return 0; if (head != (void **)&rt_tables[AF_INET6]) /* BOGUS! */ return 1; /* only do this for the real routing table */ rnh = *head; rnh->rnh_addaddr = in6_addroute; rnh->rnh_matchaddr = in6_matroute; rnh->rnh_close = in6_clsroute; in6_rtqtimo(rnh); /* kick off timeout first time */ in6_mtutimo(rnh); /* kick off timeout first time */ return 1;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?