您的位置:首页 > 其它

netif_receive_skb 函数解析

2014-04-30 15:02 429 查看
转载地址:http://codefarmer.blog.51cto.com/1002646/733386

int netif_receive_skb(struct sk_buff *skb)

{
   //略去一些代码
    rcu_read_lock();
   
//第一步:先处理 ptype_all 上所有的 packet_type->func()           

    //所有包都会调func,对性能影响严重!内核默认没挂任何钩子函数
    list_for_each_entry_rcu(ptype, &ptype_all,
list) { //遍历ptye_all链表
        if (!ptype->dev || ptype->dev == skb->dev) {    //上面的paket_type.type
为 ETH_P_ALL
            if (pt_prev)                                //对所有包调用paket_type.func()
                ret = deliver_skb(skb, pt_prev, orig_dev); //此函数最终调用paket_type.func()
            pt_prev = ptype;
        }
    }
   
//第二步:若编译内核时选上BRIDGE,下面会执行网桥模块

    //调用函数指针 br_handle_frame_hook(skb), 在动态模块 linux_2_6_24/net/bridge/br.c中

    //br_handle_frame_hook = br_handle_frame;

    //所以实际函数 br_handle_frame。

    //注意:在此网桥模块里初始化 skb->pkt_type 为 PACKET_HOST、PACKET_OTHERHOST
    skb = handle_bridge(skb,
&pt_prev, &ret, orig_dev);
    if (!skb) goto out;

   
//第三步:编译内核时选上MAC_VLAN模块,下面才会执行

    //调用 macvlan_handle_frame_hook(skb), 在动态模块linux_2_6_24/drivers/net/macvlan.c中

    //macvlan_handle_frame_hook = macvlan_handle_frame; 

    //所以实际函数为 macvlan_handle_frame。 

    //注意:此函数里会初始化 skb->pkt_type 为 PACKET_BROADCAST、PACKET_MULTICAST、PACKET_HOST
    skb = handle_macvlan(skb,
&pt_prev, &ret, orig_dev);
    if (!skb)  goto out;

   
//第四步:最后 type = skb->protocol; &ptype_base[ntohs(type)&15]

    //处理ptype_base[ntohs(type)&15]上的所有的
packet_type->func()
    //根据第二层不同协议来进入不同的钩子函数,重要的有:ip_rcv()
arp_rcv()

    type = skb->protocol;
    list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type)&15],
list) {
        if (ptype->type == type &&                      //遍历包type所对应的链表
            (!ptype->dev || ptype->dev == skb->dev)) {  //调用链表上所有pakcet_type.func()
            if (pt_prev)
                ret = deliver_skb(skb, pt_prev, orig_dev); //就这里!arp包会调arp_rcv()
            pt_prev = ptype;                               //       
ip包会调ip_rcv()
        }
    }
    if (pt_prev) {
        ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
    } else {               //下面就是数据包从协议栈返回来了
        kfree_skb(skb);    //注意这句,若skb没进入socket的接收队列,则在这里被释放
        ret = NET_RX_DROP; //若skb进入接收队列,则系统调用取包时skb释放,这里skb引用数减一而已
    }
out:
    rcu_read_unlock();
    return ret;
}

int deliver_skb(struct sk_buff *skb,struct packet_type *pt_prev, struct net_device *orig_dev){
    atomic_inc(&skb->users);
    return pt_prev->func(skb,
skb->dev, pt_prev, orig_dev)
;//调函数ip_rcv() arp_rcv()等
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  netif_receive_skb