📄 myinet_timewait_sock.c
字号:
static inline void myinet_twsk_put(struct inet_timewait_sock *tw){ printk(KERN_INFO "THE TW REFCNT: %d\n", atomic_read(&tw->tw_refcnt) ); if( atomic_dec_and_test(&tw->tw_refcnt) ) { struct module *owner = tw->tw_prot->owner; printk(KERN_DEBUG "%s timewait_sock %p released\n", tw->tw_prot->name, tw); kmem_cache_free(tw->tw_prot->twsk_prot->twsk_slab, tw); module_put(owner); }}static int myinet_twdr_do_twkill_work(struct inet_timewait_death_row *twdr, const int slot){ struct inet_timewait_sock *tw; struct hlist_node *node; unsigned int killed; int ret; killed = 0; ret = 0;rescan: inet_twsk_for_each_inmate(tw, node, &twdr->cells[slot]) { __inet_twsk_del_dead_node(tw); spin_unlock(&twdr->death_lock); __myinet_twsk_kill(tw, twdr->hashinfo); myinet_twsk_put(tw); killed++; spin_lock(&twdr->death_lock); if (killed > INET_TWDR_TWKILL_QUOTA) { ret = 1; break; } goto rescan; } twdr->tw_count -= killed; NET_ADD_STATS_BH(LINUX_MIB_TIMEWAITED, killed); return ret;}void myinet_twdr_hangman(unsigned long data){ struct inet_timewait_death_row *twdr; int unsigned need_timer; twdr = (struct inet_timewait_death_row *)data; spin_lock(&twdr->death_lock); if (twdr->tw_count == 0) goto out; need_timer = 0; if (myinet_twdr_do_twkill_work(twdr, twdr->slot)) { twdr->thread_slots |= (1 << twdr->slot); mb(); schedule_work(&twdr->twkill_work); need_timer = 1; } else { if (twdr->tw_count) need_timer = 1; } twdr->slot = ((twdr->slot + 1) & (INET_TWDR_TWKILL_SLOTS - 1)); if (need_timer) mod_timer(&twdr->tw_timer, jiffies + twdr->period);out: spin_unlock(&twdr->death_lock);}extern void twkill_slots_invalid(void);void myinet_twdr_twkill_work(void *data){ struct inet_timewait_death_row *twdr = data; int i; if ((INET_TWDR_TWKILL_SLOTS - 1) > (sizeof(twdr->thread_slots) * 8)) twkill_slots_invalid(); while (twdr->thread_slots) { spin_lock_bh(&twdr->death_lock); for (i = 0; i < INET_TWDR_TWKILL_SLOTS; i++) { if (!(twdr->thread_slots & (1 << i))) continue; while( myinet_twdr_do_twkill_work(twdr, i) != 0 ){ if (need_resched()) { spin_unlock_bh(&twdr->death_lock); schedule(); spin_lock_bh(&twdr->death_lock); } } twdr->thread_slots &= ~(1 << i); } spin_unlock_bh(&twdr->death_lock); }}void myinet_twdr_twcal_tick(unsigned long data){ struct inet_timewait_death_row *twdr; int n, slot; unsigned long j; unsigned long now = jiffies; int killed = 0; int adv = 0; twdr = (struct inet_timewait_death_row *)data; spin_lock(&twdr->death_lock); if (twdr->twcal_hand < 0) goto out; slot = twdr->twcal_hand; j = twdr->twcal_jiffie; printk(KERN_INFO "tick!!!!!!!!!!!!!!!!!!!!!!!!!\n"); for (n = 0; n < INET_TWDR_RECYCLE_SLOTS; n++) { if (time_before_eq(j, now)) { struct hlist_node *node, *safe; struct inet_timewait_sock *tw; inet_twsk_for_each_inmate_safe(tw, node, safe, &twdr->twcal_row[slot]) { __inet_twsk_del_dead_node(tw); __myinet_twsk_kill( tw, twdr->hashinfo ); printk(KERN_INFO "call in time_wait sock 127!\n"); myinet_twsk_put(tw); killed++; } }else{ if (!adv) { adv = 1; twdr->twcal_jiffie = j; twdr->twcal_hand = slot; } if (!hlist_empty(&twdr->twcal_row[slot])) { mod_timer(&twdr->twcal_timer, j); goto out; } } j += 1 << INET_TWDR_RECYCLE_TICK; slot = (slot + 1) & (INET_TWDR_RECYCLE_SLOTS - 1); } twdr->twcal_hand = -1;out: if ((twdr->tw_count -= killed) == 0) del_timer(&twdr->tw_timer); NET_ADD_STATS_BH(LINUX_MIB_TIMEWAITKILLED, killed); spin_unlock(&twdr->death_lock);}void __myinet_twsk_kill(struct inet_timewait_sock *tw, struct inet_hashinfo *hashinfo){ struct inet_bind_hashbucket *bhead; struct inet_bind_bucket *tb; struct inet_ehash_bucket *ehead = inet_ehash_bucket(hashinfo, tw->tw_hash); write_lock(&ehead->lock); if (hlist_unhashed(&tw->tw_node)) { write_unlock(&ehead->lock); return; } __hlist_del(&tw->tw_node); sk_node_init(&tw->tw_node); write_unlock(&ehead->lock); bhead = &hashinfo->bhash[inet_bhashfn(tw->tw_num, hashinfo->bhash_size)]; spin_lock(&bhead->lock); tb = tw->tw_tb; __hlist_del(&tw->tw_bind_node); tw->tw_tb = NULL; myinet_bind_bucket_destroy(hashinfo->bind_bucket_cachep, tb); spin_unlock(&bhead->lock);#ifdef SOCK_REFCNT_DEBUG if (atomic_read(&tw->tw_refcnt) != 1) { printk(KERN_DEBUG "%s timewait_sock %p refcnt=%d\n", tw->tw_prot->name, tw, atomic_read(&tw->tw_refcnt)); }#endif myinet_twsk_put(tw);}void myinet_twsk_deschedule(struct inet_timewait_sock *tw, struct inet_timewait_death_row *twdr){ spin_lock(&twdr->death_lock); if (inet_twsk_del_dead_node(tw)) { printk(KERN_INFO "call in time_wait sock 193!\n"); myinet_twsk_put(tw); if (--twdr->tw_count == 0) del_timer(&twdr->tw_timer); } spin_unlock(&twdr->death_lock); __myinet_twsk_kill(tw, twdr->hashinfo);}struct inet_timewait_sock *myinet_twsk_alloc(const struct sock *sk, const int state){ struct inet_timewait_sock *tw = kmem_cache_alloc(sk->sk_prot_creator->twsk_prot->twsk_slab, SLAB_ATOMIC); if (tw != NULL) { const struct inet_sock *inet = inet_sk(sk); tw->tw_daddr = inet->daddr; tw->tw_rcv_saddr = inet->rcv_saddr; tw->tw_bound_dev_if = sk->sk_bound_dev_if; tw->tw_num = inet->num; tw->tw_state = TCP_TIME_WAIT; tw->tw_substate = state; tw->tw_sport = inet->sport; tw->tw_dport = inet->dport; tw->tw_family = sk->sk_family; tw->tw_reuse = sk->sk_reuse; tw->tw_hash = sk->sk_hash; tw->tw_ipv6only = 0; tw->tw_prot = sk->sk_prot_creator; atomic_set(&tw->tw_refcnt, 1); inet_twsk_dead_node_init(tw); __module_get(tw->tw_prot->owner); } return tw;}void __myinet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk, struct inet_hashinfo *hashinfo){ const struct inet_sock *inet = inet_sk(sk); const struct inet_connection_sock *icsk = inet_csk(sk); struct inet_ehash_bucket *ehead = inet_ehash_bucket(hashinfo, sk->sk_hash); struct inet_bind_hashbucket *bhead; bhead = &hashinfo->bhash[inet_bhashfn(inet->num, hashinfo->bhash_size)]; spin_lock(&bhead->lock); tw->tw_tb = icsk->icsk_bind_hash; BUG_TRAP(icsk->icsk_bind_hash); inet_twsk_add_bind_node(tw, &tw->tw_tb->owners); spin_unlock(&bhead->lock); write_lock(&ehead->lock); if (__sk_del_node_init(sk)) sock_prot_dec_use(sk->sk_prot); inet_twsk_add_node(tw, &(ehead + hashinfo->ehash_size)->chain); atomic_inc(&tw->tw_refcnt); write_unlock(&ehead->lock);}void myinet_twsk_schedule(struct inet_timewait_sock *tw, struct inet_timewait_death_row *twdr, const int timeo, const int timewait_len){ struct hlist_head *list; int slot; printk(KERN_INFO "timeo: %d\n", timeo); slot = (timeo + (1 << INET_TWDR_RECYCLE_TICK) - 1) >> INET_TWDR_RECYCLE_TICK; printk(KERN_INFO "slot: %d, tick: %d, %d\n", slot, INET_TWDR_RECYCLE_TICK, HZ ); printk(KERN_INFO "slots: %d\n", INET_TWDR_RECYCLE_SLOTS ); spin_lock(&twdr->death_lock); if (inet_twsk_del_dead_node(tw)) twdr->tw_count--; else atomic_inc(&tw->tw_refcnt); if (slot >= INET_TWDR_RECYCLE_SLOTS) { if (timeo >= timewait_len) { slot = INET_TWDR_TWKILL_SLOTS - 1; } else { slot = (timeo + twdr->period - 1) / twdr->period; if (slot >= INET_TWDR_TWKILL_SLOTS) slot = INET_TWDR_TWKILL_SLOTS - 1; } tw->tw_ttd = jiffies + timeo; slot = (twdr->slot + slot) & (INET_TWDR_TWKILL_SLOTS - 1); list = &twdr->cells[slot]; } else { tw->tw_ttd = jiffies + (slot << INET_TWDR_RECYCLE_TICK); if (twdr->twcal_hand < 0) { twdr->twcal_hand = 0; twdr->twcal_jiffie = jiffies; twdr->twcal_timer.expires = twdr->twcal_jiffie + (slot << INET_TWDR_RECYCLE_TICK); printk(KERN_INFO "twdr->twcal_hand<0, expires: %lu\n", twdr->twcal_timer.expires ); add_timer(&twdr->twcal_timer); } else { if (time_after(twdr->twcal_timer.expires,jiffies + (slot << INET_TWDR_RECYCLE_TICK))){ printk(KERN_INFO "else: %lu\n", jiffies + (slot << INET_TWDR_RECYCLE_TICK) ); mod_timer(&twdr->twcal_timer, jiffies + (slot << INET_TWDR_RECYCLE_TICK)); } slot = (twdr->twcal_hand + slot) & (INET_TWDR_RECYCLE_SLOTS - 1); } list = &twdr->twcal_row[slot]; } hlist_add_head(&tw->tw_death_node, list); if (twdr->tw_count++ == 0){ printk(KERN_INFO "last: %lu\n", jiffies + twdr->period ); mod_timer(&twdr->tw_timer, jiffies + twdr->period); } spin_unlock(&twdr->death_lock);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -