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()等
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()等
相关文章推荐
- Struts2应用的开发步骤
- IOS之缩放图片
- hibernate配置文档
- 网络安全专题
- win7下安装vc++6.0以及解决vc++6.0与office的兼容性问题的方法
- 【jQuery学习笔记----AJAX之javascript角度】
- 使用ViewPager实现广告滑动效果
- 下面的类是文件下载类,支持文件的多线程断点续传,使用该类的即可安全、高效的下载任何类型的二进制文件:
- JS正则表达式全局标记g的解释
- 浮点数在计算机中的表示
- cocos2d: Cast name Layer doesn't include modular name which it belongs to,please add the modular name
- 韩磊欠款245万 法院喊他领传票
- 面
- android activity生命周期的七个状态转换
- 使用tintColor改变图片的颜色
- Service的作用
- poj 3041 最小点覆盖=最大匹配
- Xcode 自动加Comment插件:VVDocumenter-Xcode
- AS3常用动画效果公式集合
- 三数取中的划分方式