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

📄 fib_trie.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
			cb->args[4] = i;			return -1;		}		i++;	}	cb->args[4] = i;	return skb->len;}static int fn_trie_dump_plen(struct trie *t, int plen, struct fib_table *tb, struct sk_buff *skb,			     struct netlink_callback *cb){	int h, s_h;	struct list_head *fa_head;	struct leaf *l = NULL;	s_h = cb->args[3];	for (h = 0; (l = nextleaf(t, l)) != NULL; h++) {		if (h < s_h)			continue;		if (h > s_h)			memset(&cb->args[4], 0,			       sizeof(cb->args) - 4*sizeof(cb->args[0]));		fa_head = get_fa_head(l, plen);		if (!fa_head)			continue;		if (list_empty(fa_head))			continue;		if (fn_trie_dump_fa(l->key, plen, fa_head, tb, skb, cb)<0) {			cb->args[3] = h;			return -1;		}	}	cb->args[3] = h;	return skb->len;}static int fn_trie_dump(struct fib_table *tb, struct sk_buff *skb, struct netlink_callback *cb){	int m, s_m;	struct trie *t = (struct trie *) tb->tb_data;	s_m = cb->args[2];	rcu_read_lock();	for (m = 0; m <= 32; m++) {		if (m < s_m)			continue;		if (m > s_m)			memset(&cb->args[3], 0,				sizeof(cb->args) - 3*sizeof(cb->args[0]));		if (fn_trie_dump_plen(t, 32-m, tb, skb, cb)<0) {			cb->args[2] = m;			goto out;		}	}	rcu_read_unlock();	cb->args[2] = m;	return skb->len;out:	rcu_read_unlock();	return -1;}/* Fix more generic FIB names for init later */#ifdef CONFIG_IP_MULTIPLE_TABLESstruct fib_table * fib_hash_init(u32 id)#elsestruct fib_table * __init fib_hash_init(u32 id)#endif{	struct fib_table *tb;	struct trie *t;	if (fn_alias_kmem == NULL)		fn_alias_kmem = kmem_cache_create("ip_fib_alias",						  sizeof(struct fib_alias),						  0, SLAB_HWCACHE_ALIGN,						  NULL);	tb = kmalloc(sizeof(struct fib_table) + sizeof(struct trie),		     GFP_KERNEL);	if (tb == NULL)		return NULL;	tb->tb_id = id;	tb->tb_lookup = fn_trie_lookup;	tb->tb_insert = fn_trie_insert;	tb->tb_delete = fn_trie_delete;	tb->tb_flush = fn_trie_flush;	tb->tb_select_default = fn_trie_select_default;	tb->tb_dump = fn_trie_dump;	memset(tb->tb_data, 0, sizeof(struct trie));	t = (struct trie *) tb->tb_data;	trie_init(t);	if (id == RT_TABLE_LOCAL)		trie_local = t;	else if (id == RT_TABLE_MAIN)		trie_main = t;	if (id == RT_TABLE_LOCAL)		printk(KERN_INFO "IPv4 FIB: Using LC-trie version %s\n", VERSION);	return tb;}#ifdef CONFIG_PROC_FS/* Depth first Trie walk iterator */struct fib_trie_iter {	struct tnode *tnode;	struct trie *trie;	unsigned index;	unsigned depth;};static struct node *fib_trie_get_next(struct fib_trie_iter *iter){	struct tnode *tn = iter->tnode;	unsigned cindex = iter->index;	struct tnode *p;	/* A single entry routing table */	if (!tn)		return NULL;	pr_debug("get_next iter={node=%p index=%d depth=%d}\n",		 iter->tnode, iter->index, iter->depth);rescan:	while (cindex < (1<<tn->bits)) {		struct node *n = tnode_get_child(tn, cindex);		if (n) {			if (IS_LEAF(n)) {				iter->tnode = tn;				iter->index = cindex + 1;			} else {				/* push down one level */				iter->tnode = (struct tnode *) n;				iter->index = 0;				++iter->depth;			}			return n;		}		++cindex;	}	/* Current node exhausted, pop back up */	p = node_parent((struct node *)tn);	if (p) {		cindex = tkey_extract_bits(tn->key, p->pos, p->bits)+1;		tn = p;		--iter->depth;		goto rescan;	}	/* got root? */	return NULL;}static struct node *fib_trie_get_first(struct fib_trie_iter *iter,				       struct trie *t){	struct node *n ;	if (!t)		return NULL;	n = rcu_dereference(t->trie);	if (!iter)		return NULL;	if (n) {		if (IS_TNODE(n)) {			iter->tnode = (struct tnode *) n;			iter->trie = t;			iter->index = 0;			iter->depth = 1;		} else {			iter->tnode = NULL;			iter->trie  = t;			iter->index = 0;			iter->depth = 0;		}		return n;	}	return NULL;}static void trie_collect_stats(struct trie *t, struct trie_stat *s){	struct node *n;	struct fib_trie_iter iter;	memset(s, 0, sizeof(*s));	rcu_read_lock();	for (n = fib_trie_get_first(&iter, t); n;	     n = fib_trie_get_next(&iter)) {		if (IS_LEAF(n)) {			s->leaves++;			s->totdepth += iter.depth;			if (iter.depth > s->maxdepth)				s->maxdepth = iter.depth;		} else {			const struct tnode *tn = (const struct tnode *) n;			int i;			s->tnodes++;			if (tn->bits < MAX_STAT_DEPTH)				s->nodesizes[tn->bits]++;			for (i = 0; i < (1<<tn->bits); i++)				if (!tn->child[i])					s->nullpointers++;		}	}	rcu_read_unlock();}/* *	This outputs /proc/net/fib_triestats */static void trie_show_stats(struct seq_file *seq, struct trie_stat *stat){	unsigned i, max, pointers, bytes, avdepth;	if (stat->leaves)		avdepth = stat->totdepth*100 / stat->leaves;	else		avdepth = 0;	seq_printf(seq, "\tAver depth:     %d.%02d\n", avdepth / 100, avdepth % 100 );	seq_printf(seq, "\tMax depth:      %u\n", stat->maxdepth);	seq_printf(seq, "\tLeaves:         %u\n", stat->leaves);	bytes = sizeof(struct leaf) * stat->leaves;	seq_printf(seq, "\tInternal nodes: %d\n\t", stat->tnodes);	bytes += sizeof(struct tnode) * stat->tnodes;	max = MAX_STAT_DEPTH;	while (max > 0 && stat->nodesizes[max-1] == 0)		max--;	pointers = 0;	for (i = 1; i <= max; i++)		if (stat->nodesizes[i] != 0) {			seq_printf(seq, "  %d: %d",  i, stat->nodesizes[i]);			pointers += (1<<i) * stat->nodesizes[i];		}	seq_putc(seq, '\n');	seq_printf(seq, "\tPointers: %d\n", pointers);	bytes += sizeof(struct node *) * pointers;	seq_printf(seq, "Null ptrs: %d\n", stat->nullpointers);	seq_printf(seq, "Total size: %d  kB\n", (bytes + 1023) / 1024);#ifdef CONFIG_IP_FIB_TRIE_STATS	seq_printf(seq, "Counters:\n---------\n");	seq_printf(seq,"gets = %d\n", t->stats.gets);	seq_printf(seq,"backtracks = %d\n", t->stats.backtrack);	seq_printf(seq,"semantic match passed = %d\n", t->stats.semantic_match_passed);	seq_printf(seq,"semantic match miss = %d\n", t->stats.semantic_match_miss);	seq_printf(seq,"null node hit= %d\n", t->stats.null_node_hit);	seq_printf(seq,"skipped node resize = %d\n", t->stats.resize_node_skipped);#ifdef CLEAR_STATS	memset(&(t->stats), 0, sizeof(t->stats));#endif#endif /*  CONFIG_IP_FIB_TRIE_STATS */}static int fib_triestat_seq_show(struct seq_file *seq, void *v){	struct trie_stat *stat;	stat = kmalloc(sizeof(*stat), GFP_KERNEL);	if (!stat)		return -ENOMEM;	seq_printf(seq, "Basic info: size of leaf: %Zd bytes, size of tnode: %Zd bytes.\n",		   sizeof(struct leaf), sizeof(struct tnode));	if (trie_local) {		seq_printf(seq, "Local:\n");		trie_collect_stats(trie_local, stat);		trie_show_stats(seq, stat);	}	if (trie_main) {		seq_printf(seq, "Main:\n");		trie_collect_stats(trie_main, stat);		trie_show_stats(seq, stat);	}	kfree(stat);	return 0;}static int fib_triestat_seq_open(struct inode *inode, struct file *file){	return single_open(file, fib_triestat_seq_show, NULL);}static const struct file_operations fib_triestat_fops = {	.owner	= THIS_MODULE,	.open	= fib_triestat_seq_open,	.read	= seq_read,	.llseek	= seq_lseek,	.release = single_release,};static struct node *fib_trie_get_idx(struct fib_trie_iter *iter,				      loff_t pos){	loff_t idx = 0;	struct node *n;	for (n = fib_trie_get_first(iter, trie_local);	     n; ++idx, n = fib_trie_get_next(iter)) {		if (pos == idx)			return n;	}	for (n = fib_trie_get_first(iter, trie_main);	     n; ++idx, n = fib_trie_get_next(iter)) {		if (pos == idx)			return n;	}	return NULL;}static void *fib_trie_seq_start(struct seq_file *seq, loff_t *pos){	rcu_read_lock();	if (*pos == 0)		return SEQ_START_TOKEN;	return fib_trie_get_idx(seq->private, *pos - 1);}static void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos){	struct fib_trie_iter *iter = seq->private;	void *l = v;	++*pos;	if (v == SEQ_START_TOKEN)		return fib_trie_get_idx(iter, 0);	v = fib_trie_get_next(iter);	BUG_ON(v == l);	if (v)		return v;	/* continue scan in next trie */	if (iter->trie == trie_local)		return fib_trie_get_first(iter, trie_main);	return NULL;}static void fib_trie_seq_stop(struct seq_file *seq, void *v){	rcu_read_unlock();}static void seq_indent(struct seq_file *seq, int n){	while (n-- > 0) seq_puts(seq, "   ");}static inline const char *rtn_scope(enum rt_scope_t s){	static char buf[32];	switch (s) {	case RT_SCOPE_UNIVERSE: return "universe";	case RT_SCOPE_SITE:	return "site";	case RT_SCOPE_LINK:	return "link";	case RT_SCOPE_HOST:	return "host";	case RT_SCOPE_NOWHERE:	return "nowhere";	default:		snprintf(buf, sizeof(buf), "scope=%d", s);		return buf;	}}static const char *rtn_type_names[__RTN_MAX] = {	[RTN_UNSPEC] = "UNSPEC",	[RTN_UNICAST] = "UNICAST",	[RTN_LOCAL] = "LOCAL",	[RTN_BROADCAST] = "BROADCAST",	[RTN_ANYCAST] = "ANYCAST",	[RTN_MULTICAST] = "MULTICAST",	[RTN_BLACKHOLE] = "BLACKHOLE",	[RTN_UNREACHABLE] = "UNREACHABLE",	[RTN_PROHIBIT] = "PROHIBIT",	[RTN_THROW] = "THROW",	[RTN_NAT] = "NAT",	[RTN_XRESOLVE] = "XRESOLVE",};static inline const char *rtn_type(unsigned t){	static char buf[32];	if (t < __RTN_MAX && rtn_type_names[t])		return rtn_type_names[t];	snprintf(buf, sizeof(buf), "type %d", t);	return buf;}/* Pretty print the trie */static int fib_trie_seq_show(struct seq_file *seq, void *v){	const struct fib_trie_iter *iter = seq->private;	struct node *n = v;	if (v == SEQ_START_TOKEN)		return 0;	if (!node_parent(n)) {		if (iter->trie == trie_local)			seq_puts(seq, "<local>:\n");		else			seq_puts(seq, "<main>:\n");	}	if (IS_TNODE(n)) {		struct tnode *tn = (struct tnode *) n;		__be32 prf = htonl(mask_pfx(tn->key, tn->pos));		seq_indent(seq, iter->depth-1);		seq_printf(seq, "  +-- %d.%d.%d.%d/%d %d %d %d\n",			   NIPQUAD(prf), tn->pos, tn->bits, tn->full_children,			   tn->empty_children);	} else {		struct leaf *l = (struct leaf *) n;		int i;		__be32 val = htonl(l->key);		seq_indent(seq, iter->depth);		seq_printf(seq, "  |-- %d.%d.%d.%d\n", NIPQUAD(val));		for (i = 32; i >= 0; i--) {			struct leaf_info *li = find_leaf_info(l, i);			if (li) {				struct fib_alias *fa;				list_for_each_entry_rcu(fa, &li->falh, fa_list) {					seq_indent(seq, iter->depth+1);					seq_printf(seq, "  /%d %s %s", i,						   rtn_scope(fa->fa_scope),						   rtn_type(fa->fa_type));					if (fa->fa_tos)						seq_printf(seq, "tos =%d\n",							   fa->fa_tos);					seq_putc(seq, '\n');				}			}		}	}	return 0;}static const struct seq_operations fib_trie_seq_ops = {	.start  = fib_trie_seq_start,	.next   = fib_trie_seq_next,	.stop   = fib_trie_seq_stop,	.show   = fib_trie_seq_show,};static int fib_trie_seq_open(struct inode *inode, struct file *file){	return seq_open_private(file, &fib_trie_seq_ops,			sizeof(struct fib_trie_iter));}static const struct file_operations fib_trie_fops = {	.owner  = THIS_MODULE,	.open   = fib_trie_seq_open,	.read   = seq_read,	.llseek = seq_lseek,	.release = seq_release_private,};static unsigned fib_flag_trans(int type, __be32 mask, const struct fib_info *fi){	static unsigned type2flags[RTN_MAX + 1] = {		[7] = RTF_REJECT, [8] = RTF_REJECT,	};	unsigned flags = type2flags[type];	if (fi && fi->fib_nh->nh_gw)		flags |= RTF_GATEWAY;	if (mask == htonl(0xFFFFFFFF))		flags |= RTF_HOST;	flags |= RTF_UP;	return flags;}/* *	This outputs /proc/net/route. *	The format of the file is not supposed to be changed * 	and needs to be same as fib_hash output to avoid breaking *	legacy utilities */static int fib_route_seq_show(struct seq_file *seq, void *v){	const struct fib_trie_iter *iter = seq->private;	struct leaf *l = v;	int i;	char bf[128];	if (v == SEQ_START_TOKEN) {		seq_printf(seq, "%-127s\n", "Iface\tDestination\tGateway "			   "\tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU"			   "\tWindow\tIRTT");		return 0;	}	if (iter->trie == trie_local)		return 0;	if (IS_TNODE(l))		return 0;	for (i=32; i>=0; i--) {		struct leaf_info *li = find_leaf_info(l, i);		struct fib_alias *fa;		__be32 mask, prefix;		if (!li)			continue;		mask = inet_make_mask(li->plen);		prefix = htonl(l->key);		list_for_each_entry_rcu(fa, &li->falh, fa_list) {			const struct fib_info *fi = fa->fa_info;			unsigned flags = fib_flag_trans(fa->fa_type, mask, fi);			if (fa->fa_type == RTN_BROADCAST			    || fa->fa_type == RTN_MULTICAST)				continue;			if (fi)				snprintf(bf, sizeof(bf),					 "%s\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",					 fi->fib_dev ? fi->fib_dev->name : "*",					 prefix,					 fi->fib_nh->nh_gw, flags, 0, 0,					 fi->fib_priority,					 mask,					 (fi->fib_advmss ? fi->fib_advmss + 40 : 0),					 fi->fib_window,					 fi->fib_rtt >> 3);			else				snprintf(bf, sizeof(bf),					 "*\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",					 prefix, 0, flags, 0, 0, 0,					 mask, 0, 0, 0);			seq_printf(seq, "%-127s\n", bf);		}	}	return 0;}static const struct seq_operations fib_route_seq_ops = {	.start  = fib_trie_seq_start,	.next   = fib_trie_seq_next,	.stop   = fib_trie_seq_stop,	.show   = fib_route_seq_show,};static int fib_route_seq_open(struct inode *inode, struct file *file){	return seq_open_private(file, &fib_route_seq_ops,			sizeof(struct fib_trie_iter));}static const struct file_operations fib_route_fops = {	.owner  = THIS_MODULE,	.open   = fib_route_seq_open,	.read   = seq_read,	.llseek = seq_lseek,	.release = seq_release_private,};int __init fib_proc_init(void){	if (!proc_net_fops_create(&init_net, "fib_trie", S_IRUGO, &fib_trie_fops))		goto out1;	if (!proc_net_fops_create(&init_net, "fib_triestat", S_IRUGO, &fib_triestat_fops))		goto out2;	if (!proc_net_fops_create(&init_net, "route", S_IRUGO, &fib_route_fops))		goto out3;	return 0;out3:	proc_net_remove(&init_net, "fib_triestat");out2:	proc_net_remove(&init_net, "fib_trie");out1:	return -ENOMEM;}void __init fib_proc_exit(void){	proc_net_remove(&init_net, "fib_trie");	proc_net_remove(&init_net, "fib_triestat");	proc_net_remove(&init_net, "route");}#endif /* CONFIG_PROC_FS */

⌨️ 快捷键说明

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