閱讀261 返回首頁    go 阿裏雲 go 技術社區[雲棲]


網絡子係統52_ip協議報文重組

//分片子模塊初始化函數
//	1.ipq hash 函數的隨機因子
//	2.定時器,到期更新隨機因子
//	3.ipq_hash 靜態全局變量,靜態分配64個buckets
//調用路徑:inet_init->ipfrag_init
1.1 void ipfrag_init(void)
{
	//分片暫存的hash表
	ipfrag_hash_rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^
				 (jiffies ^ (jiffies >> 6)));
	//定期修改ip分片的哈希函數,將hash表中的所有分片根據信息的哈希函數搬到新的位置
	init_timer(&ipfrag_secret_timer);
	ipfrag_secret_timer.function = ipfrag_secret_rebuild;
	ipfrag_secret_timer.expires = jiffies + sysctl_ipfrag_secret_interval;
	add_timer(&ipfrag_secret_timer);
}

//調用路徑:ip_local_deliver->ip_defrag
//	1.檢查檢查ipq hash是否超過內存閾值
//		1.1 如果超過閾值則清除超時的分片
//	2.從ipq hash表中找到與入口分片相關的ipq結構
//	3.將分片插入到ipq的分片列表中
//	4.如果分片接收完全,重組

1.2 struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user)
{
	struct iphdr *iph = skb->nh.iph;
	struct ipq *qp;
	struct net_device *dev;
	
	IP_INC_STATS_BH(IPSTATS_MIB_REASMREQDS);

	//重組ip片段使用的內存已經超過閥值
	if (atomic_read(&ip_frag_mem) > sysctl_ipfrag_high_thresh)
		ip_evictor();//通過LRU鏈表,刪除不完整封包的ipq結構

	dev = skb->dev;

	if ((qp = ip_find(iph, user)) != NULL) {//找出和正在被處理的片段相關的封包
		struct sk_buff *ret = NULL;

		spin_lock(&qp->lock);

		ip_frag_queue(qp, skb);//將skb加入到ipq中

		if (qp->last_in == (FIRST_IN|LAST_IN) &&//第一個和最後一個分片都已經收到
		    qp->meat == qp->len)//meat為已經收到的skb的數據長度,len為通過iph->tot,iph->offset猜測的最大長度
			ret = ip_frag_reasm(qp, dev);//重組

		spin_unlock(&qp->lock);
		ipq_put(qp, NULL);
		return ret;
	}

	IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
	kfree_skb(skb);
	return NULL;
}

最後更新:2017-04-03 14:53:41

  上一篇:go 網絡子係統53_ip協議分片重組_內存閾值
  下一篇:go windows和linux中檢查端口是否被占用