⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 route.c

📁 《嵌入式系统设计与实例开发实验教材二源码》Linux内核移植与编译实验
💻 C
📖 第 1 页 / 共 5 页
字号:
	struct nlmsghdr  *nlh;	unsigned char	 *b = skb->tail;	struct rta_cacheinfo ci;#ifdef CONFIG_IP_MROUTE	struct rtattr *eptr;#endif	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*r));	r = NLMSG_DATA(nlh);	nlh->nlmsg_flags = (nowait && pid) ? NLM_F_MULTI : 0;	r->rtm_family	 = AF_INET;	r->rtm_dst_len	= 32;	r->rtm_src_len	= 0;	r->rtm_tos	= rt->key.tos;	r->rtm_table	= RT_TABLE_MAIN;	r->rtm_type	= rt->rt_type;	r->rtm_scope	= RT_SCOPE_UNIVERSE;	r->rtm_protocol = RTPROT_UNSPEC;	r->rtm_flags	= (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED;	if (rt->rt_flags & RTCF_NOTIFY)		r->rtm_flags |= RTM_F_NOTIFY;	RTA_PUT(skb, RTA_DST, 4, &rt->rt_dst);	if (rt->key.src) {		r->rtm_src_len = 32;		RTA_PUT(skb, RTA_SRC, 4, &rt->key.src);	}	if (rt->u.dst.dev)		RTA_PUT(skb, RTA_OIF, sizeof(int), &rt->u.dst.dev->ifindex);#ifdef CONFIG_NET_CLS_ROUTE	if (rt->u.dst.tclassid)		RTA_PUT(skb, RTA_FLOW, 4, &rt->u.dst.tclassid);#endif	if (rt->key.iif)		RTA_PUT(skb, RTA_PREFSRC, 4, &rt->rt_spec_dst);	else if (rt->rt_src != rt->key.src)		RTA_PUT(skb, RTA_PREFSRC, 4, &rt->rt_src);	if (rt->rt_dst != rt->rt_gateway)		RTA_PUT(skb, RTA_GATEWAY, 4, &rt->rt_gateway);	if (rtnetlink_put_metrics(skb, &rt->u.dst.mxlock) < 0)		goto rtattr_failure;	ci.rta_lastuse	= jiffies - rt->u.dst.lastuse;	ci.rta_used	= rt->u.dst.__use;	ci.rta_clntref	= atomic_read(&rt->u.dst.__refcnt);	if (rt->u.dst.expires)		ci.rta_expires = rt->u.dst.expires - jiffies;	else		ci.rta_expires = 0;	ci.rta_error	= rt->u.dst.error;	ci.rta_id	= ci.rta_ts = ci.rta_tsage = 0;	if (rt->peer) {		ci.rta_id = rt->peer->ip_id_count;		if (rt->peer->tcp_ts_stamp) {			ci.rta_ts = rt->peer->tcp_ts;			ci.rta_tsage = xtime.tv_sec - rt->peer->tcp_ts_stamp;		}	}#ifdef CONFIG_IP_MROUTE	eptr = (struct rtattr*)skb->tail;#endif	RTA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci);	if (rt->key.iif) {#ifdef CONFIG_IP_MROUTE		u32 dst = rt->rt_dst;		if (MULTICAST(dst) && !LOCAL_MCAST(dst) &&		    ipv4_devconf.mc_forwarding) {			int err = ipmr_get_route(skb, r, nowait);			if (err <= 0) {				if (!nowait) {					if (err == 0)						return 0;					goto nlmsg_failure;				} else {					if (err == -EMSGSIZE)						goto nlmsg_failure;					((struct rta_cacheinfo*)RTA_DATA(eptr))->rta_error = err;				}			}		} else#endif			RTA_PUT(skb, RTA_IIF, sizeof(int), &rt->key.iif);	}	nlh->nlmsg_len = skb->tail - b;	return skb->len;nlmsg_failure:rtattr_failure:	skb_trim(skb, b - skb->data);	return -1;}int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg){	struct rtattr **rta = arg;	struct rtmsg *rtm = NLMSG_DATA(nlh);	struct rtable *rt = NULL;	u32 dst = 0;	u32 src = 0;	int iif = 0;	int err = -ENOBUFS;	struct sk_buff *skb;	skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);	if (!skb)		goto out;	/* Reserve room for dummy headers, this skb can pass	   through good chunk of routing engine.	 */	skb->mac.raw = skb->data;	skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr));	if (rta[RTA_SRC - 1])		memcpy(&src, RTA_DATA(rta[RTA_SRC - 1]), 4);	if (rta[RTA_DST - 1])		memcpy(&dst, RTA_DATA(rta[RTA_DST - 1]), 4);	if (rta[RTA_IIF - 1])		memcpy(&iif, RTA_DATA(rta[RTA_IIF - 1]), sizeof(int));	if (iif) {		struct net_device *dev = __dev_get_by_index(iif);		err = -ENODEV;		if (!dev)			goto out;		skb->protocol	= __constant_htons(ETH_P_IP);		skb->dev	= dev;		local_bh_disable();		err = ip_route_input(skb, dst, src, rtm->rtm_tos, dev);		local_bh_enable();		rt = (struct rtable*)skb->dst;		if (!err && rt->u.dst.error)			err = -rt->u.dst.error;	} else {		int oif = 0;		if (rta[RTA_OIF - 1])			memcpy(&oif, RTA_DATA(rta[RTA_OIF - 1]), sizeof(int));		err = ip_route_output(&rt, dst, src, rtm->rtm_tos, oif);	}	if (err) {		kfree_skb(skb);		goto out;	}	skb->dst = &rt->u.dst;	if (rtm->rtm_flags & RTM_F_NOTIFY)		rt->rt_flags |= RTCF_NOTIFY;	NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;	err = rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq,				RTM_NEWROUTE, 0);	if (!err)		goto out;	if (err < 0) {		err = -EMSGSIZE;		goto out;	}	err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);	if (err > 0)		err = 0;out:	return err;}int ip_rt_dump(struct sk_buff *skb,  struct netlink_callback *cb){	struct rtable *rt;	int h, s_h;	int idx, s_idx;	s_h = cb->args[0];	s_idx = idx = cb->args[1];	for (h = 0; h <= rt_hash_mask; h++) {		if (h < s_h) continue;		if (h > s_h)			s_idx = 0;		read_lock_bh(&rt_hash_table[h].lock);		for (rt = rt_hash_table[h].chain, idx = 0; rt;		     rt = rt->u.rt_next, idx++) {			if (idx < s_idx)				continue;			skb->dst = dst_clone(&rt->u.dst);			if (rt_fill_info(skb, NETLINK_CB(cb->skb).pid,					 cb->nlh->nlmsg_seq,					 RTM_NEWROUTE, 1) <= 0) {				dst_release(xchg(&skb->dst, NULL));				read_unlock_bh(&rt_hash_table[h].lock);				goto done;			}			dst_release(xchg(&skb->dst, NULL));		}		read_unlock_bh(&rt_hash_table[h].lock);	}done:	cb->args[0] = h;	cb->args[1] = idx;	return skb->len;}void ip_rt_multicast_event(struct in_device *in_dev){	rt_cache_flush(0);}#ifdef CONFIG_SYSCTLstatic int flush_delay;static int ipv4_sysctl_rtcache_flush(ctl_table *ctl, int write,					struct file *filp, void *buffer,					size_t *lenp){	if (write) {		proc_dointvec(ctl, write, filp, buffer, lenp);		rt_cache_flush(flush_delay);		return 0;	} 	return -EINVAL;}static int ipv4_sysctl_rtcache_flush_strategy(ctl_table *table, int *name,						int nlen, void *oldval,						size_t *oldlenp, void *newval,						size_t newlen, void **context){	int delay;	if (newlen != sizeof(int))		return -EINVAL;	if (get_user(delay, (int *)newval))		return -EFAULT; 	rt_cache_flush(delay); 	return 0;}ctl_table ipv4_route_table[] = {        {		ctl_name:	NET_IPV4_ROUTE_FLUSH,		procname:	"flush",		data:		&flush_delay,		maxlen:		sizeof(int),		mode:		0644,		proc_handler:	&ipv4_sysctl_rtcache_flush,		strategy:	&ipv4_sysctl_rtcache_flush_strategy,	},	{		ctl_name:	NET_IPV4_ROUTE_MIN_DELAY,		procname:	"min_delay",		data:		&ip_rt_min_delay,		maxlen:		sizeof(int),		mode:		0644,		proc_handler:	&proc_dointvec_jiffies,		strategy:	&sysctl_jiffies,	},	{		ctl_name:	NET_IPV4_ROUTE_MAX_DELAY,		procname:	"max_delay",		data:		&ip_rt_max_delay,		maxlen:		sizeof(int),		mode:		0644,		proc_handler:	&proc_dointvec_jiffies,		strategy:	&sysctl_jiffies,	},	{		ctl_name:	NET_IPV4_ROUTE_GC_THRESH,		procname:	"gc_thresh",		data:		&ipv4_dst_ops.gc_thresh,		maxlen:		sizeof(int),		mode:		0644,		proc_handler:	&proc_dointvec,	},	{		ctl_name:	NET_IPV4_ROUTE_MAX_SIZE,		procname:	"max_size",		data:		&ip_rt_max_size,		maxlen:		sizeof(int),		mode:		0644,		proc_handler:	&proc_dointvec,	},	{		ctl_name:	NET_IPV4_ROUTE_GC_MIN_INTERVAL,		procname:	"gc_min_interval",		data:		&ip_rt_gc_min_interval,		maxlen:		sizeof(int),		mode:		0644,		proc_handler:	&proc_dointvec_jiffies,		strategy:	&sysctl_jiffies,	},	{		ctl_name:	NET_IPV4_ROUTE_GC_TIMEOUT,		procname:	"gc_timeout",		data:		&ip_rt_gc_timeout,		maxlen:		sizeof(int),		mode:		0644,		proc_handler:	&proc_dointvec_jiffies,		strategy:	&sysctl_jiffies,	},	{		ctl_name:	NET_IPV4_ROUTE_GC_INTERVAL,		procname:	"gc_interval",		data:		&ip_rt_gc_interval,		maxlen:		sizeof(int),		mode:		0644,		proc_handler:	&proc_dointvec_jiffies,		strategy:	&sysctl_jiffies,	},	{		ctl_name:	NET_IPV4_ROUTE_REDIRECT_LOAD,		procname:	"redirect_load",		data:		&ip_rt_redirect_load,		maxlen:		sizeof(int),		mode:		0644,		proc_handler:	&proc_dointvec,	},	{		ctl_name:	NET_IPV4_ROUTE_REDIRECT_NUMBER,		procname:	"redirect_number",		data:		&ip_rt_redirect_number,		maxlen:		sizeof(int),		mode:		0644,		proc_handler:	&proc_dointvec,	},	{		ctl_name:	NET_IPV4_ROUTE_REDIRECT_SILENCE,		procname:	"redirect_silence",		data:		&ip_rt_redirect_silence,		maxlen:		sizeof(int),		mode:		0644,		proc_handler:	&proc_dointvec,	},	{		ctl_name:	NET_IPV4_ROUTE_ERROR_COST,		procname:	"error_cost",		data:		&ip_rt_error_cost,		maxlen:		sizeof(int),		mode:		0644,		proc_handler:	&proc_dointvec,	},	{		ctl_name:	NET_IPV4_ROUTE_ERROR_BURST,		procname:	"error_burst",		data:		&ip_rt_error_burst,		maxlen:		sizeof(int),		mode:		0644,		proc_handler:	&proc_dointvec,	},	{		ctl_name:	NET_IPV4_ROUTE_GC_ELASTICITY,		procname:	"gc_elasticity",		data:		&ip_rt_gc_elasticity,		maxlen:		sizeof(int),		mode:		0644,		proc_handler:	&proc_dointvec,	},	{		ctl_name:	NET_IPV4_ROUTE_MTU_EXPIRES,		procname:	"mtu_expires",		data:		&ip_rt_mtu_expires,		maxlen:		sizeof(int),		mode:		0644,		proc_handler:	&proc_dointvec_jiffies,		strategy:	&sysctl_jiffies,	},	{		ctl_name:	NET_IPV4_ROUTE_MIN_PMTU,		procname:	"min_pmtu",		data:		&ip_rt_min_pmtu,		maxlen:		sizeof(int),		mode:		0644,		proc_handler:	&proc_dointvec,	},	{		ctl_name:	NET_IPV4_ROUTE_MIN_ADVMSS,		procname:	"min_adv_mss",		data:		&ip_rt_min_advmss,		maxlen:		sizeof(int),		mode:		0644,		proc_handler:	&proc_dointvec,	},	 { 0 }};#endif#ifdef CONFIG_NET_CLS_ROUTEstruct ip_rt_acct *ip_rt_acct;static int ip_rt_acct_read(char *buffer, char **start, off_t offset,			   int length, int *eof, void *data){	*start = buffer;	if ((offset & 3) || (length & 3))		return -EIO;	if (offset + length >= sizeof(struct ip_rt_acct) * 256) {		length = sizeof(struct ip_rt_acct) * 256 - offset;		*eof = 1;	}	if (length > 0) {		u32 *dst = (u32*)buffer;		u32 *src = (u32*)(((u8*)ip_rt_acct) + offset);		memcpy(dst, src, length);#ifdef CONFIG_SMP		if (smp_num_cpus > 1 || cpu_logical_map(0) != 0) {			int i;			int cnt = length / 4;			for (i = 0; i < smp_num_cpus; i++) {				int cpu = cpu_logical_map(i);				int k;				if (cpu == 0)					continue;				src = (u32*)(((u8*)ip_rt_acct) + offset +					cpu * 256 * sizeof(struct ip_rt_acct));				for (k = 0; k < cnt; k++)					dst[k] += src[k];			}		}#endif		return length;	}	return 0;}#endifvoid __init ip_rt_init(void){	int i, order, goal;#ifdef CONFIG_NET_CLS_ROUTE	for (order = 0;	     (PAGE_SIZE << order) < 256 * sizeof(ip_rt_acct) * NR_CPUS; order++)		/* NOTHING */;	ip_rt_acct = (struct ip_rt_acct *)__get_free_pages(GFP_KERNEL, order);	if (!ip_rt_acct)		panic("IP: failed to allocate ip_rt_acct\n");	memset(ip_rt_acct, 0, PAGE_SIZE << order);#endif	ipv4_dst_ops.kmem_cachep = kmem_cache_create("ip_dst_cache",						     sizeof(struct rtable),						     0, SLAB_HWCACHE_ALIGN,						     NULL, NULL);	if (!ipv4_dst_ops.kmem_cachep)		panic("IP: failed to allocate ip_dst_cache\n");	goal = num_physpages >> (26 - PAGE_SHIFT);	for (order = 0; (1UL << order) < goal; order++)		/* NOTHING */;	do {		rt_hash_mask = (1UL << order) * PAGE_SIZE /			sizeof(struct rt_hash_bucket);		while (rt_hash_mask & (rt_hash_mask - 1))			rt_hash_mask--;		rt_hash_table = (struct rt_hash_bucket *)			__get_free_pages(GFP_ATOMIC, order);	} while (rt_hash_table == NULL && --order > 0);	if (!rt_hash_table)		panic("Failed to allocate IP route cache hash table\n");	printk("IP: routing cache hash table of %u buckets, %ldKbytes\n",	       rt_hash_mask,	       (long) (rt_hash_mask * sizeof(struct rt_hash_bucket)) / 1024);	for (rt_hash_log = 0; (1 << rt_hash_log) != rt_hash_mask; rt_hash_log++)		/* NOTHING */;	rt_hash_mask--;	for (i = 0; i <= rt_hash_mask; i++) {		rt_hash_table[i].lock = RW_LOCK_UNLOCKED;		rt_hash_table[i].chain = NULL;	}	ipv4_dst_ops.gc_thresh = (rt_hash_mask + 1);	ip_rt_max_size = (rt_hash_mask + 1) * 16;	devinet_init();	ip_fib_init();	rt_flush_timer.function = rt_run_flush;	rt_periodic_timer.function = rt_check_expire;	/* All the timers, started at system startup tend	   to synchronize. Perturb it a bit.	 */	rt_periodic_timer.expires = jiffies + net_random() % ip_rt_gc_interval +					ip_rt_gc_interval;	add_timer(&rt_periodic_timer);	proc_net_create ("rt_cache", 0, rt_cache_get_info);	proc_net_create ("rt_cache_stat", 0, rt_cache_stat_get_info);#ifdef CONFIG_NET_CLS_ROUTE	create_proc_read_entry("net/rt_acct", 0, 0, ip_rt_acct_read, NULL);#endif}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -