首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

网络处理的软中断机制分析(2)

网络处理的软中断机制分析(2)

接下来看一下sk_buff是如何被递交到上层协议进行处理的,只是通过调用netif_receive_skb(在net/core/dev.c中定义)函数实现的:
int netif_receive_skb(struct sk_buff *skb)
{
       struct packet_type *ptype, *pt_prev;
       int ret = NET_RX_DROP;
       unsigned short type = skb->protocol;

       /*
       给每个网络数据包打上时间戳。
       */
       if (skb->stamp.tv_sec == 0)
              do_gettimeofday(&skb->stamp);

       skb_bond(skb);

       pt_prev = NULL;
       /*
       上层的每个协议在其初始化的过程中会调用dev_add_pack函数将自己的packet_type结构加入到ptye_all列表当中,其中 packet_type结构中定义了该协议的处理方法,对于ip协议来说,func方法就注册为ip_rcv。另外,一般协议packet_type结构 的dev字段设为NULL,所以下面的ptype->dev就为NULL。
       另外,如果我们需要增加自己的协议,则需要创建一个packet_type结构,用我们自己的协议处理函数填充该结构的func方法,并且调用dev_add_pack函数将我们自己的协议加入ptype_all数组当中。
       */
       for (ptype = ptype_all; ptype; ptype = ptype->next) {
              /*
              这里每一种协议在定义其packet_type结构时都设置接收这种
              数据包协议类型的设备指针,如果设置为NULL,则可以从
任何设备接收数据包。
这里针对协议类型为ETH_P_ALL的情况进行处理,对于IP
协议来说,类型定义为ETH_P_IP,因此不在这里处理。
              */
              if (!ptype->dev || ptype->dev == skb->dev) {
                     if (pt_prev) {
                            if (!pt_prev->data) {
                                   ret = deliver_to_old_ones(pt_prev, skb, 0);
                            } else {
                                   atomic_inc(&skb->users);
                                   ret = pt_prev->func(skb, skb->dev, pt_prev);
                            }
                     }
                     pt_prev = ptype;
              }
       }
       /*
这里针对各种协议进行处理,IP包的类型为ETH_P_IP,因此在这里处理。
*/
       for (ptype=ptype_base[ntohs(type)&15];ptype;ptype=ptype->next) {
              if (ptype->type == type &&
                  (!ptype->dev || ptype->dev == skb->dev)) {
                     if (pt_prev) {
                            if (!pt_prev->data) {
                                   ret = deliver_to_old_ones(pt_prev, skb, 0);
                            } else {
                                   atomic_inc(&skb->users);
                                   ret = pt_prev->func(skb, skb->dev, pt_prev);
                            }
                     }
                     pt_prev = ptype;
              }
       }

       if (pt_prev) {
              if (!pt_prev->data) {
                     ret = deliver_to_old_ones(pt_prev, skb, 1);
              } else {
                     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;
       }

       return ret;
}
       在软中断处理函数当中,我们根据数据包的类型,调用相应的底层数据处理函数,对于IP包来说,就是调用ip_rcv函数并且进一步向上层协议递交和处理。至此,内核的软中断的主要过程已经结束了。
继承事业,薪火相传
返回列表