Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2762471
  • 博文数量: 79
  • 博客积分: 30130
  • 博客等级: 大将
  • 技术积分: 2608
  • 用 户 组: 普通用户
  • 注册时间: 2007-10-22 14:58
个人简介

博所搬至http://xiaogr.com

文章存档

2015年(2)

2009年(3)

2008年(56)

2007年(18)

分类: LINUX

2007-10-25 18:12:14

------------------------------------------

本文系本站原创,欢迎转载!

转载请注明出处:http://ericxiao.cublog.cn/

------------------------------------------

天气越来越暖和,人也变得越来越浮躁。以往望眼欲穿的越狱第三季,现在下载下来后也被扔在了一边。情节变得越来越无味。似还珠格格三部曲般。越嚼越无味了。老毛说过,懒惰让人退步,我们不能退步,所以,继续踩着上一篇的脚印进步吧。

         上一篇概述了数据在网卡驱动上的处理,接着数据包的流程继续往下走。网卡驱动的最后一个函数是netif_receive_skb.就从它说起。

为了简单起见,去掉了里面预编译代码

int netif_receive_skb(struct sk_buff *skb)         net/core/dev.c

{

         struct packet_type *ptype, *pt_prev;

         int ret = NET_RX_DROP;

         unsigned short type;

         //打上接收的时间戳

         if (!skb->stamp.tv_sec)

                   net_timestamp(&skb->stamp);

         //如果存在dev->master。则更新相应指针

         skb_bond(skb);

         //更新CPU的接收统计数据

         __get_cpu_var(netdev_rx_stat).total++;

         skb->h.raw = skb->nh.raw = skb->data;

         skb->mac_len = skb->nh.raw - skb->mac.raw;

         pt_prev = NULL;

         rcu_read_lock();

         //处理所有协议的模块

         list_for_each_entry_rcu(ptype, &ptype_all, list) {

                   if (!ptype->dev || ptype->dev == skb->dev) {

                            if (pt_prev)

                                     ret = deliver_skb(skb, pt_prev);

                            pt_prev = ptype;

                   }

         }

         //分片处理

         handle_diverter(skb);

         //网桥处理

         if (handle_bridge(&skb, &pt_prev, &ret))

                   goto out;

         type = skb->protocol;

         //为协议调用相应模块处理。

         list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type)&15], list) {

                   if (ptype->type == type &&

                       (!ptype->dev || ptype->dev == skb->dev)) {

                            if (pt_prev)

                                     ret = deliver_skb(skb, pt_prev);

                            pt_prev = ptype;

                   }

         }

         if (pt_prev) {

                   ret = pt_prev->func(skb, skb->dev, pt_prev);

         } else {

                   kfree_skb(skb);

                   /* Jamal, now you will not able to escape explaining

                    * me how you were going to use this. :-)

                    */

                   ret = NET_RX_DROP;

         }

 

out:

         rcu_read_unlock();

         return ret;

}

此函数主要完成了分片重组,网桥处理,根据不同协议调用不同的传输层处理模块。本节的重点是概述linux的网桥实现与处理。传输层协议分层将在后续章节陆续给出。进入网桥处理代码:

#if defined(CONFIG_BRIDGE) || defined (CONFIG_BRIDGE_MODULE)                 net/core/dev.c

int (*br_handle_frame_hook)(struct net_bridge_port *p, struct sk_buff **pskb);

 

static __inline__ int handle_bridge(struct sk_buff **pskb,

                                         struct packet_type **pt_prev, int *ret)

{

         struct net_bridge_port *port;

         //回环接口?非以太网接口?

         if ((*pskb)->pkt_type == PACKET_LOOPBACK ||

             (port = rcu_dereference((*pskb)->dev->br_port)) == NULL)

                   return 0;

 

         if (*pt_prev) {

                   *ret = deliver_skb(*pskb, *pt_prev);

                   *pt_prev = NULL;

         }

         // br_handle_frame_hook是一个全局的函数指针

         return br_handle_frame_hook(port, pskb);

}

#else

#define handle_bridge(skb, pt_prev, ret) (0)

#endif

从此可以看出。如果编译的时候选择了网桥模式,则会进入网桥的处理模块了,否则,只是一个空函数,直接返回。br_handle_frame_hook代表的函数是什么呢?网桥的数据处理框架又是什么样的呢?呵呵。这就是今天所要分析的问题了。

 

阅读(3684) | 评论(0) | 转发(3) |
给主人留下些什么吧!~~