📄 myinet_hashtables.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 + -