您的位置:首页 > 理论基础 > 计算机网络

网络子系统52_ip协议报文重组

2013-10-12 20:13 253 查看
//分片子模块初始化函数
//	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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Linux ip 网络 kernel 重组