深入分析linux网络技术内幕之网络层

        上次研究到netif_receive_skb(),这是网络层的入口。这个函数根据skb的protocol字段,调用不同的函数。
  //linux-3.0.8/net/core/dev.c
	type = skb->protocol;
	list_for_each_entry_rcu(ptype,
			&ptype_base[ntohs(type) & PTYPE_HASH_MASK], list) {
		if (ptype->type == type &&
		    (ptype->dev == null_or_dev || ptype->dev == skb->dev ||
		     ptype->dev == orig_dev)) {
			if (pt_prev)
				ret = deliver_skb(skb, pt_prev, orig_dev);
			pt_prev = ptype;
		}
	}

        deliver_skb()是一个内联函数,它的作用就是调用不同协议的处理函数。这是很好理解的,在数据报文在两层之间传递时,报文需要提供一些字段,让下一层根据这些字段做出不同的处理。对于一个网络系统,L3(网络层)有很多不同的协议,比如IP,IPX,appletalk等,当然也可能有L2的LCC协议。这些协议在内核协议栈中都是有明确定义的,对应于skb的protocol字段。如果是IPv4,就会调用非常重要的ip_rcv()函数了。ip_rcv()函数在最后时候,会通过NetFilter调用ip_rcv_finish()。                                                   

        ip_rcv_finish()函数中会间接调用ip_route_input_slow(),这个函数中会设置skb的_skb_refdst->input函数指针。这个指针可能被设置为ip_local_deliver()或者是ip_forward()。这次先看看ip_local_deliver(),即接收本地的数据报文。

   int ip_local_deliver(struct sk_buff *skb)
	 {
		/*
		 *	Reassemble IP fragments.
		 */
	
		if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
			if (ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER))
				return 0;
		}
	
		return NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_IN, skb, skb->dev, NULL,
			       ip_local_deliver_finish);
 	 }
  这个函数就是做了网络从L3到L4的最后工作。首先,这个函数会根据ip帧的头部信息尝试重组ip帧。如果没有重组成功,就返回0。这次返回就标志着新数据帧的处理基本完成了。当然,如果重组成功的话,还需要通过NetFilter调用ip_local_deliver_finish()。如果NetFilter觉得该数据包可以接收,就会调用ip_local_deliver_finish()。看到这个函数,我们就知道ip帧就要和网络层说byebye了,是的它进入了L4传输层。

         这部分显得的有点简单,其实真正的重头戏在ip_forward()中,路由子系统还没开始看,所以先绕过了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值