加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 黄冈站长网 (http://www.0713zz.com/)- 数据应用、建站、人体识别、智能机器人、语音技术!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

Linux内核分析 - 网络[八]:IP协议

发布时间:2016-10-16 06:06:01 所属栏目:Linux 来源:站长网
导读:副标题#e# 内核版本:2.6.34 这篇是关于IP层协议接收报文时的处理,重点说明了路由表的查找,以及IP分片重组。 ip_rcv 进入IP层报文接收函数 丢弃掉不是发往本机的报文,skb-pkt_type在网卡接收报文处理以太网头时会根据dst mac设置, 协议栈的书会讲不是发

如果是主机可以接收报文,则执行ip_local_deliver。ip_local_deliver在向上传递前,会对分片的IP报文进行组包 ,因为IP层协议会对过大的数据包分片,在接收时,就要进行重组,而重组的操作就是在这里进行的。IP报头的16位偏移字段 frag_off是由3位的标志(CE,DF,MF)和13的偏移量组成。如果收到了分片的IP报文,如果是最后一片,则MF=0且offset!=0;如果 不是最后一片,则MF=1。

在这种情况下会执行ip_defrag来处理分片的IP报文,如果不是最后一片,则将该报文添加到 ip4_frags中保留下来,并return 0,此次数据包接收完成;如果是最后一片,则取出之前收到的分片重组成新的skb,此时 ip_defrag返回值为0,skb被重置为完整的数据包,然后继续处理,之后调用ip_local_deliver_finish处理重组后的数据包。

if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {     
 if (ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER))     
  return 0;     
}

下面来看下ip_defrag()函数,主体就是下面的代码段。它首先用ip_find()查找IP分片,并返回(如果没有则创建), 然后用ip_frag_queue()将新分片加入,关于IP分片的处理,在后面的IP分片中有详细描述。

if ((qp = ip_find(net, 

ip_hdr(skb), user)) != NULL) {     
 int ret;     
         
 spin_lock(&qp->q.lock);     
         
 ret = ip_frag_queue(qp, skb);     
         
 spin_unlock(&qp->q.lock);     
 ipq_put(qp);     
 return ret;     
}

然后会调用ip_local_deliver_finish()完成IP协议层的传递,两者调用间依然有netfilter,这是查找完路由表继续 向上传递的中间点。

NF_HOOK(PF_INET, NF_INET_LOCAL_IN, skb, skb->dev, NULL, ip_local_deliver_finish);

(编辑:PHP编程网 - 黄冈站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读