netif_receive_skb 函数解析
来源:互联网 发布:sql查看表中所有列名 编辑:程序博客网 时间:2024/05/16 11:46
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()等
}
{
//略去一些代码
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 函数解析
- netif_receive_skb 函数解析
- netif_receive_skb 函数注解
- netif_receive_skb 函数注解
- netif_receive_skb 函数注解
- netif_receive_skb
- netif_receive_skb()
- 【Linux4.1.12源码分析】协议栈报文接收之netif_receive_skb函数分析
- netif_receive_skb为什么使用pt_prev
- Linux内核分析 - 网络[三]:从netif_receive_skb()说起
- Linux内核分析 - 网络[三]:从netif_receive_skb()说起
- Linux内核分析 - 网络[三]:从netif_receive_skb()说起
- Linux内核分析 - 网络[三]:从netif_receive_skb()说起
- Linux内核分析 - 网络[三]:从netif_receive_skb()说起
- 函数调用约定解析
- 函数解析字符串(ZT)
- setsockopt函数解析(转)
- ARX函数解析
- WPF多语言化的实现
- ubuntu安装rpm格式的方法
- Master Note For Oracle Recovery Manager (RMAN) [ID 1116484.1]
- 关于CheckBoxList取值
- 所有程序员都应该至少读上两遍的十篇论文
- netif_receive_skb 函数解析
- CentOS 6.3(x86_32)下安装Oracle 10g R2
- 六大原则之合成聚合原则
- Linux Oracle服务启动&停止脚本与开机自启动
- 单向关联:多对一
- CentOS 6.3下源码安装LAMP(Linux+Apache+Mysql+Php)环境
- PHPCMS 2008 V9的 发邮件函数
- Entity Framework若干个扩展
- TFS,FastDFS性能对比与分析