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

📄 fib_semantics.c

📁 一个基于linux的TCP/IP协议栈的实现
💻 C
📖 第 1 页 / 共 2 页
字号:
		memcpy(&fi->fib_prefsrc, rta->rta_prefsrc, 4);	if (rta->rta_mp) {#ifdef CONFIG_IP_ROUTE_MULTIPATH		if ((err = myfib_get_nhs(fi, rta->rta_mp, r)) != 0)			goto failure;		if (rta->rta_oif && fi->fib_nh->nh_oif != *rta->rta_oif)			goto err_inval;		if (rta->rta_gw && memcmp(&fi->fib_nh->nh_gw, rta->rta_gw, 4))			goto err_inval;#ifdef CONFIG_NET_CLS_ROUTE		if (rta->rta_flow && memcmp(&fi->fib_nh->nh_tclassid, rta->rta_flow, 4))			goto err_inval;#endif#else		goto err_inval;#endif	}else{		struct fib_nh *nh = fi->fib_nh;		if (rta->rta_oif)			nh->nh_oif = *rta->rta_oif;		if (rta->rta_gw)			memcpy(&nh->nh_gw, rta->rta_gw, 4);#ifdef CONFIG_NET_CLS_ROUTE		if (rta->rta_flow)			memcpy(&nh->nh_tclassid, rta->rta_flow, 4);#endif		nh->nh_flags = r->rtm_flags;#ifdef CONFIG_IP_ROUTE_MULTIPATH		nh->nh_weight = 1;#endif	}#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED	fi->fib_mp_alg = mp_alg;#endif	if( myfib_props[r->rtm_type].error ){		if( rta->rta_gw || rta->rta_oif || rta->rta_mp )			goto err_inval;		goto link_it;	}	if( r->rtm_scope > RT_SCOPE_HOST )		goto err_inval;	if( r->rtm_scope == RT_SCOPE_HOST ){		struct fib_nh *nh = fi->fib_nh;		if (nhs != 1 || nh->nh_gw)			goto err_inval;		nh->nh_scope = RT_SCOPE_NOWHERE;		nh->nh_dev = dev_get_by_index( fi->fib_nh->nh_oif );		err = -ENODEV;		if (nh->nh_dev == NULL)			goto failure;	}else{		change_nexthops(fi) {			if ((err = myfib_check_nh(r, fi, nh)) != 0)				goto failure;		} endfor_nexthops(fi)	}	if( fi->fib_prefsrc ){		if (r->rtm_type != RTN_LOCAL || rta->rta_dst == NULL ||		    memcmp(&fi->fib_prefsrc, rta->rta_dst, 4))			if( myinet_addr_type(fi->fib_prefsrc) != RTN_LOCAL )				goto err_inval;	}link_it:	if( (ofi = myfib_find_info(fi)) != NULL ){		PR_DEBUG( "find an old one: %u.%u.%u.%u\n, new: %u.%u.%u.%u\n", 						NIPQUAD(fi->fib_prefsrc), NIPQUAD(ofi->fib_prefsrc) );		fi->fib_dead = 1;		myfree_fib_info(fi);		ofi->fib_treeref++;		return ofi;	}	fi->fib_treeref++;	atomic_inc( &fi->fib_clntref );	write_lock( &myfib_info_lock );	hlist_add_head( &fi->fib_hash, &myfib_info_hash[myfib_info_hashfn(fi)] );	if( fi->fib_prefsrc ){		struct hlist_head *head;		head = &myfib_info_laddrhash[myfib_laddr_hashfn(fi->fib_prefsrc)];		hlist_add_head(&fi->fib_lhash, head);	}	change_nexthops(fi) {		struct hlist_head *head;		unsigned int hash;		if (!nh->nh_dev)			continue;		hash = myfib_devindex_hashfn(nh->nh_dev->ifindex);		head = &myfib_info_devhash[hash];		hlist_add_head(&nh->nh_hash, head);	} endfor_nexthops(fi)	write_unlock( &myfib_info_lock );	return fi;err_inval:	err = -EINVAL;failure:        *errp = err;        if( fi ){			fi->fib_dead = 1;			myfree_fib_info(fi);		}	return NULL;}void myfib_release_info(struct fib_info *fi){	write_lock( &myfib_info_lock );	PR_DEBUG( "myfib_release_info\n");	if( fi && --fi->fib_treeref == 0 ){		hlist_del(&fi->fib_hash);		if( fi->fib_prefsrc )			hlist_del(&fi->fib_lhash);		change_nexthops( fi ){			if( !nh->nh_dev )				continue;			hlist_del(&nh->nh_hash);		}endfor_nexthops( fi )		fi->fib_dead = 1;		myfib_info_put(fi);	}	write_unlock( &myfib_info_lock );}int myfib_semantic_match(struct list_head *head, const struct flowi *flp,		       struct fib_result *res, __u32 zone, __u32 mask, int prefixlen){	struct fib_alias *fa;	int nh_sel = 0;	list_for_each_entry_rcu(fa, head, fa_list) {		int err;		if( fa->fa_tos && fa->fa_tos != flp->fl4_tos )			continue;		if( fa->fa_scope < flp->fl4_scope )			continue;		fa->fa_state |= FA_S_ACCESSED;		err = myfib_props[fa->fa_type].error;		if (err == 0) {			struct fib_info *fi = fa->fa_info;			if (fi->fib_flags & RTNH_F_DEAD)				continue;			switch( fa->fa_type ){			case RTN_UNICAST:			case RTN_LOCAL:			case RTN_BROADCAST:			case RTN_ANYCAST:			case RTN_MULTICAST:				for_nexthops(fi) {					if( nh->nh_flags & RTNH_F_DEAD )						continue;					if( !flp->oif || flp->oif == nh->nh_oif )						break;				}#ifdef CONFIG_IP_ROUTE_MULTIPATH				if( nhsel < fi->fib_nhs ){					nh_sel = nhsel;					goto out_fill_res;				}#else				if( nhsel < 1 ){					goto out_fill_res;				}#endif				endfor_nexthops(fi);				continue;			default:				PR_DEBUG( "impossible 102\n" );				return -EINVAL;			};		}		return err;	}	return 1;out_fill_res:	res->prefixlen = prefixlen;	res->nh_sel = nh_sel;	res->type = fa->fa_type;	res->scope = fa->fa_scope;	res->fi = fa->fa_info;#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED	res->netmask = mask;	res->network = zone & ( 0xFFFFFFFF >> (32 - prefixlen) );#endif	atomic_inc(&res->fi->fib_clntref);	return 0;}#ifdef CONFIG_IP_ROUTE_MULTIPATHint myfib_sync_up(struct net_device *dev){	struct fib_info *prev_fi;	unsigned int hash;	struct hlist_head *head;	struct hlist_node *node;	struct fib_nh *nh;	int ret;	if( !(dev->flags & IFF_UP) )		return 0;	prev_fi = NULL;	hash = myfib_devindex_hashfn( dev->ifindex );	head = &myfib_info_devhash[hash];	ret = 0;	hlist_for_each_entry( nh, node, head, nh_hash ){		struct fib_info *fi = nh->nh_parent;		int alive;		BUG_ON( !fi->fib_nhs );		if (nh->nh_dev != dev || fi == prev_fi)			continue;		prev_fi = fi;		alive = 0;		change_nexthops(fi) {			if( !(nh->nh_flags & RTNH_F_DEAD) ){				alive++;				continue;			}			if( nh->nh_dev == NULL || !(nh->nh_dev->flags & IFF_UP) )				continue;			if( nh->nh_dev != dev || !__in_dev_get_rtnl(dev) )				continue;			alive++;			spin_lock_bh( &myfib_multipath_lock );			nh->nh_power = 0;			nh->nh_flags &= ~RTNH_F_DEAD;			spin_unlock_bh( &myfib_multipath_lock );		} endfor_nexthops(fi)		if (alive > 0) {			fi->fib_flags &= ~RTNH_F_DEAD;			ret++;		}	}	return ret;}void myfib_select_multipath(const struct flowi *flp, struct fib_result *res){	struct fib_info *fi = res->fi;	int w;	spin_lock_bh( &myfib_multipath_lock );	if( fi->fib_power <= 0 ){		int power = 0;		change_nexthops(fi) {			if( !(nh->nh_flags & RTNH_F_DEAD) ){				power += nh->nh_weight;				nh->nh_power = nh->nh_weight;			}		} endfor_nexthops(fi);		fi->fib_power = power;		if (power <= 0) {			spin_unlock_bh( &myfib_multipath_lock );			res->nh_sel = 0;			return;		}	}	w = jiffies % fi->fib_power;	change_nexthops(fi) {		if( !(nh->nh_flags & RTNH_F_DEAD) && nh->nh_power ){			if( (w -= nh->nh_power) <= 0 ){				nh->nh_power--;				fi->fib_power--;				res->nh_sel = nhsel;				spin_unlock_bh( &myfib_multipath_lock );				return;			}		}	} endfor_nexthops(fi);	res->nh_sel = 0;	spin_unlock_bh( &myfib_multipath_lock );}#endifint myfib_nh_match(struct rtmsg *r, struct nlmsghdr *nlh, struct kern_rta *rta,				struct fib_info *fi){#ifdef CONFIG_IP_ROUTE_MULTIPATH	struct rtnexthop *nhp;	int nhlen;#endif	if( rta->rta_priority && *rta->rta_priority != fi->fib_priority)		return 1;	if( rta->rta_oif || rta->rta_gw ){		if( (!rta->rta_oif || *rta->rta_oif == fi->fib_nh->nh_oif) &&						(!rta->rta_gw  || memcmp(rta->rta_gw, &fi->fib_nh->nh_gw, 4) == 0))			return 0;		return 1;	}#ifdef CONFIG_IP_ROUTE_MULTIPATH	if( rta->rta_mp == NULL )		return 0;	nhp = RTA_DATA(rta->rta_mp);	nhlen = RTA_PAYLOAD(rta->rta_mp);		for_nexthops( fi ){		int attrlen = nhlen - sizeof(struct rtnexthop);		u32 gw;		if( attrlen < 0 || (nhlen -= nhp->rtnh_len) < 0 )			return -EINVAL;		if( nhp->rtnh_ifindex && nhp->rtnh_ifindex != nh->nh_oif )			return 1;		if( attrlen ){			gw = myfib_get_attr32( RTNH_DATA(nhp), attrlen, RTA_GATEWAY );			if( gw && gw != nh->nh_gw )				return 1;#ifdef CONFIG_NET_CLS_ROUTE			gw = myfib_get_attr32( RTNH_DATA(nhp), attrlen, RTA_FLOW );			if( gw && gw != nh->nh_tclassid )				return 1;#endif		}		nhp = RTNH_NEXT(nhp);	}endfor_nexthops(fi);#endif	return 0;}int myfib_sync_down( u32 local, struct net_device *dev, int force ){	int ret = 0;	int scope = RT_SCOPE_NOWHERE;		if( force )		scope = -1;	if( local && myfib_info_laddrhash ){		unsigned int hash = myfib_laddr_hashfn( local );		struct hlist_head *head = &myfib_info_laddrhash[hash];		struct hlist_node *node;		struct fib_info *fi;		hlist_for_each_entry(fi, node, head, fib_lhash) {			if( fi->fib_prefsrc == local ){				fi->fib_flags |= RTNH_F_DEAD;				ret++;			}		}	}	if( dev ){		struct fib_info *prev_fi = NULL;		unsigned int hash = myfib_devindex_hashfn( dev->ifindex );		struct hlist_head *head = &myfib_info_devhash[hash];		struct hlist_node *node;		struct fib_nh *nh;		hlist_for_each_entry( nh, node, head, nh_hash ){			struct fib_info *fi = nh->nh_parent;			int dead;			BUG_ON( !fi->fib_nhs );			if( nh->nh_dev != dev || fi == prev_fi )				continue;			prev_fi = fi;			dead = 0;			change_nexthops(fi) {				if( nh->nh_flags & RTNH_F_DEAD )					dead++;				else if( nh->nh_dev == dev && nh->nh_scope != scope ){					nh->nh_flags |= RTNH_F_DEAD;#ifdef CONFIG_IP_ROUTE_MULTIPATH					spin_lock_bh(&myfib_multipath_lock);					fi->fib_power -= nh->nh_power;					nh->nh_power = 0;					spin_unlock_bh( &myfib_multipath_lock );#endif					dead++;				}#ifdef CONFIG_IP_ROUTE_MULTIPATH				if( force > 1 && nh->nh_dev == dev ){					dead = fi->fib_nhs;					break;				}#endif			} endfor_nexthops(fi)			if (dead == fi->fib_nhs) {				fi->fib_flags |= RTNH_F_DEAD;				ret++;			}		}	}	return ret;}#if 0void dump_fib_info(void){	struct hlist_head *head;	struct hlist_node *node;	struct hlist_node *tmp;	struct fib_info *f;	int i;	for( i = 0; i < myfib_hash_size; i ++ ){		f = NULL;		head = &myfib_info_hash[i];		hlist_for_each_entry_safe( f, node, tmp, head, fib_hash ){			int j;			printk( KERN_NOTICE "%d\n", i );			printk( KERN_NOTICE "\ttreeref: %d\n", f->fib_treeref );			printk( KERN_NOTICE "\tclntref: %d\n", atomic_read(&f->fib_clntref) );			printk( KERN_NOTICE "\tflags:   %x\n", f->fib_flags );			printk( KERN_NOTICE "\tprotocol: %d\n", f->fib_protocol );			printk( KERN_NOTICE "\tprefsrc: %u.%u.%u.%u\n", NIPQUAD(f->fib_prefsrc) );			printk( KERN_NOTICE "\tpriority: %u\n", f->fib_priority );			printk( KERN_NOTICE "\tmtu: %u\n", f->fib_mtu );			printk( KERN_NOTICE "\twindow: %u\n", f->fib_window );			printk( KERN_NOTICE "\trtt: %u\n", f->fib_rtt );			printk( KERN_NOTICE "\tadvmss: %u\n", f->fib_advmss );			printk( KERN_NOTICE "\tnhs: %d\n", f->fib_nhs );			for( j=0; j < f->fib_nhs; j ++ ){				printk( KERN_NOTICE "\t%d\n", j );				printk( KERN_NOTICE "\t\tdev name: %s\n", f->fib_nh[j].nh_dev->name );				printk( KERN_NOTICE "\t\tflags: %x\n", f->fib_nh[j].nh_flags );				printk( KERN_NOTICE "\t\tscope: %x\n", f->fib_nh[j].nh_scope );				printk( KERN_NOTICE "\t\tgw: %u.%u.%u.%u\n", NIPQUAD(f->fib_nh[j].nh_gw) );			}		}	}}#elsevoid dump_fib_info(void){}#endifint myfib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,				u8 tb_id, u8 type, u8 scope, void *dst, int dst_len, u8 tos,				struct fib_info *fi, unsigned int flags){	return 0;}void __exit myfib_info_exit(void){	struct hlist_head *head;	struct hlist_node *node;	struct hlist_node *tmp;	struct fib_info *f;	int i;	for( i = 0; i < myfib_hash_size; i ++ ){		f = NULL;		head = &myfib_info_hash[i];		hlist_for_each_entry_safe( f, node, tmp, head, fib_hash ){			hlist_del( node );			PR_DEBUG( "presrc: %u.%u.%u.%u\n", NIPQUAD(f->fib_prefsrc) );			f->fib_dead = 1;			myfree_fib_info( f );		}	}	myfib_hash_free( myfib_info_hash, myfib_hash_size * sizeof(struct hlist_head *) );	myfib_hash_free( myfib_info_laddrhash, myfib_hash_size * sizeof(struct hlist_head *) );	}

⌨️ 快捷键说明

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