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

📄 myinet_hashtables.c

📁 一个基于linux的TCP/IP协议栈的实现
💻 C
字号:
#define MYINET_COMBINED_PORTS(__sport, __dport) \	(((__u32)(__dport) << 16) | (__u32)(__sport))#define MYINET_TW_MATCH(__sk, __hash,__cookie, __saddr, __daddr, __ports, __dif)	\		(((__sk)->sk_hash == (__hash))				&&	\		 (inet_twsk(__sk)->tw_daddr	== (__saddr))		&&	\		 (inet_twsk(__sk)->tw_rcv_saddr	== (__daddr))		&&	\		 ((*((__u32 *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) &&	\		 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))#define MYINET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)	\		(((__sk)->sk_hash == (__hash))				&&	\		 (inet_sk(__sk)->daddr		== (__saddr))		&&	\		 (inet_sk(__sk)->rcv_saddr	== (__daddr))		&&	\		 ((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports))	&&	\	 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))extern int mysysctl_local_port_range[2];static inline u32 myinet_sk_port_offset( const struct sock *sk ){	const struct inet_sock *inet = inet_sk(sk);	//return secure_ipv4_port_ephemeral(inet->rcv_saddr, inet->daddr, inet->dport);	return 11;}static int __myinet_check_established(struct inet_timewait_death_row *death_row,				struct sock *sk, __u16 lport, struct inet_timewait_sock **twp){	struct inet_hashinfo *hinfo = death_row->hashinfo;	struct inet_sock *inet = inet_sk(sk);	u32 daddr = inet->rcv_saddr;	u32 saddr = inet->daddr;	int dif = sk->sk_bound_dev_if;	INET_ADDR_COOKIE(acookie, saddr, daddr)	const __u32 ports = MYINET_COMBINED_PORTS(inet->dport, lport);	unsigned int hash = inet_ehashfn(daddr, lport, saddr, inet->dport);	struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash);	struct sock *sk2;	const struct hlist_node *node;	struct inet_timewait_sock *tw;	prefetch(head->chain.first);	write_lock(&head->lock);	sk_for_each(sk2, node, &(head + hinfo->ehash_size)->chain) {		tw = inet_twsk(sk2);		if( MYINET_TW_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif) ){			if (twsk_unique(sk, sk2, twp))				goto unique;			else				goto not_unique;		}	}	tw = NULL;	sk_for_each(sk2, node, &head->chain) {		if( MYINET_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif) )			goto not_unique;	}unique:	inet->num = lport;	inet->sport = htons(lport);	sk->sk_hash = hash;	BUG_TRAP(sk_unhashed(sk));	__sk_add_node(sk, &head->chain);	sock_prot_inc_use(sk->sk_prot);	write_unlock(&head->lock);	if( twp ){		*twp = tw;		MYNET_INC_STATS_BH(LINUX_MIB_TIMEWAITRECYCLED);	}else if( tw ){		inet_twsk_deschedule(tw, death_row);		MYNET_INC_STATS_BH(LINUX_MIB_TIMEWAITRECYCLED);		inet_twsk_put(tw);	}	return 0;not_unique:	write_unlock(&head->lock);	return -EADDRNOTAVAIL;}struct inet_bind_bucket *myinet_bind_bucket_create(kmem_cache_t *cachep,				struct inet_bind_hashbucket *head, const unsigned short snum){	struct inet_bind_bucket *tb = kmem_cache_alloc(cachep, SLAB_ATOMIC);	if (tb != NULL) {		tb->port      = snum;		tb->fastreuse = 0;		INIT_HLIST_HEAD(&tb->owners);		hlist_add_head(&tb->node, &head->chain);	}	return tb;}void myinet_bind_bucket_destroy(kmem_cache_t *cachep, struct inet_bind_bucket *tb){	if (hlist_empty(&tb->owners)) {		__hlist_del(&tb->node);		kmem_cache_free(cachep, tb);	}}void myinet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb,				const unsigned short snum){	inet_sk(sk)->num = snum;	sk_add_bind_node(sk, &tb->owners);	inet_csk(sk)->icsk_bind_hash = tb;}int myinet_hash_connect(struct inet_timewait_death_row *death_row, struct sock *sk){	struct inet_hashinfo *hinfo = death_row->hashinfo;	const unsigned short snum = inet_sk(sk)->num; 	struct inet_bind_hashbucket *head; 	struct inet_bind_bucket *tb;	int ret;	if( !snum ){ 		int low = mysysctl_local_port_range[0]; 		int high = mysysctl_local_port_range[1];		int range = high - low; 		int i;		int port;		static u32 hint;		u32 offset = hint + myinet_sk_port_offset(sk);		struct hlist_node *node; 		struct inet_timewait_sock *tw = NULL;		printk(KERN_INFO "range: %d-%d\n", low, high);		local_bh_disable();		for (i = 1; i <= range; i++) {			port = low + (i + offset) % range; 			head = &hinfo->bhash[ inet_bhashfn(port, hinfo->bhash_size) ];			printk(KERN_INFO "head: %p, port: %d\n", head, port ); 			spin_lock(&head->lock);			inet_bind_bucket_for_each( tb, node, &head->chain ){ 				if( tb->port == port ){ 					BUG_TRAP( !hlist_empty(&tb->owners) ); 					if (tb->fastreuse >= 0) 						goto next_port; 					if ( !__myinet_check_established(death_row, sk, port, &tw) ) 						goto ok; 					goto next_port; 				} 			} 			tb = myinet_bind_bucket_create(hinfo->bind_bucket_cachep, head, port); 			if (!tb) { 				spin_unlock(&head->lock); 				break; 			} 			tb->fastreuse = -1; 			goto ok; 		next_port: 			spin_unlock(&head->lock); 		} 		local_bh_enable();		return -EADDRNOTAVAIL;ok:		hint += i; 		myinet_bind_hash(sk, tb, port);		if( sk_unhashed(sk) ){ 			inet_sk(sk)->sport = htons( port ); 			__inet_hash(hinfo, sk, 0); 		} 		spin_unlock(&head->lock); 		if( tw ){ 			myinet_twsk_deschedule(tw, death_row);; 			inet_twsk_put(tw); 		}		ret = 0;		goto out;	} 	head = &hinfo->bhash[inet_bhashfn(snum, hinfo->bhash_size)]; 	tb  = inet_csk(sk)->icsk_bind_hash;	spin_lock_bh(&head->lock);	if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) {		__inet_hash(hinfo, sk, 0);		spin_unlock_bh(&head->lock);		return 0;	} else {		spin_unlock(&head->lock);		ret = __myinet_check_established(death_row, sk, snum, NULL);out:		local_bh_enable();		return ret;	}}static void __myinet_put_port(struct inet_hashinfo *hashinfo, struct sock *sk){	const int bhash = inet_bhashfn(inet_sk(sk)->num, hashinfo->bhash_size);	struct inet_bind_hashbucket *head = &hashinfo->bhash[bhash];	struct inet_bind_bucket *tb;	spin_lock(&head->lock);	tb = inet_csk(sk)->icsk_bind_hash;	__sk_del_bind_node(sk);	inet_csk(sk)->icsk_bind_hash = NULL;	inet_sk(sk)->num = 0;	myinet_bind_bucket_destroy(hashinfo->bind_bucket_cachep, tb);	spin_unlock(&head->lock);}void myinet_put_port(struct inet_hashinfo *hashinfo, struct sock *sk){	local_bh_disable();	__myinet_put_port(hashinfo, sk);	local_bh_enable();}

⌨️ 快捷键说明

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