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 + -
显示快捷键?