網絡子係統53_ip協議分片重組_內存閾值
//調用路徑:ip_defrag->ip_evictor // 分片重組時,可使用內存上下限: // 1.sysctl_ipfrag_high_thresh 可用內存上限 // 2.sysctl_ipfrag_low_thresh 內存超過上限後,需要釋放內存到此限 1.1 static void ip_evictor(void) { struct ipq *qp; struct list_head *tmp; int work; //計算需要釋放的內存 work = atomic_read(&ip_frag_mem) - sysctl_ipfrag_low_thresh; if (work <= 0) return; while (work > 0) { read_lock(&ipfrag_lock); if (list_empty(&ipq_lru_list)) {//最近最久沒有沒有被使用的鏈表,鏈表頭的ipq最久沒有被使用 read_unlock(&ipfrag_lock); return; } //在獲取鎖的情況下,釋放ipq tmp = ipq_lru_list.next; qp = list_entry(tmp, struct ipq, lru_list); atomic_inc(&qp->refcnt);//增加ipq的引用計數,防止其突然消失 read_unlock(&ipfrag_lock); spin_lock(&qp->lock); if (!(qp->last_in&COMPLETE))//ipq沒有接收完全 ipq_kill(qp);// spin_unlock(&qp->lock); ipq_put(qp, &work); IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); } } //調用路徑:ip_evictor->ipq_kill 1.2 static void ipq_kill(struct ipq *ipq) { if (del_timer(&ipq->timer))//刪除ipq的定時器 atomic_dec(&ipq->refcnt);//遞減定時器持有的引用計數 if (!(ipq->last_in & COMPLETE)) {//ipq沒有接收完全 ipq_unlink(ipq);//將ipq從ipq hash表bucket的鏈表上摘下來 atomic_dec(&ipq->refcnt);//遞減ipq hash表bucket對其持有的引用計數 ipq->last_in |= COMPLETE;//標記ipq接收完全,防止其被更新 } } 1.3 static __inline__ void ipq_put(struct ipq *ipq, int *work) { if (atomic_dec_and_test(&ipq->refcnt))//遞減在ip_evictor中對ipq的引用 ip_frag_destroy(ipq, work);//釋放關聯到此ipq的skb } 1.4 static void ip_frag_destroy(struct ipq *qp, int *work) { struct sk_buff *fp; //此ipq接收到的所有分片 fp = qp->fragments; while (fp) { struct sk_buff *xp = fp->next; frag_kfree_skb(fp, work);//釋放skb,從work中減去此skb的大小 fp = xp; } frag_free_queue(qp, work);//釋放ipq結構 }
最後更新:2017-04-03 14:53:41