在设备驱动收包之后,会通过netif_receive_skb将收取的包,按照注册的协议回调,传递到上层进行处理;

 /* 将skb传递到上层 */
static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc)
{
struct packet_type *ptype, *pt_prev;
rx_handler_func_t *rx_handler;
struct net_device *orig_dev;
bool deliver_exact = false;
int ret = NET_RX_DROP;
__be16 type; /* 记录收包时间,netdev_tstamp_prequeue为0,表示可能有包延迟 */
net_timestamp_check(!netdev_tstamp_prequeue, skb); trace_netif_receive_skb(skb); /* 记录收包设备 */
orig_dev = skb->dev; /* 重置各层头部 */
skb_reset_network_header(skb);
if (!skb_transport_header_was_set(skb))
skb_reset_transport_header(skb);
skb_reset_mac_len(skb); /*
留下一个节点,最后一次向上层传递时,
不需要在inc引用,回调中会free
这样相当于少调用了一次free
*/
pt_prev = NULL; another_round: /* 接收设备索引号 */
skb->skb_iif = skb->dev->ifindex; /* 处理包数统计 */
__this_cpu_inc(softnet_data.processed); /* vlan包,则去掉vlan头 */
if (skb->protocol == cpu_to_be16(ETH_P_8021Q) ||
skb->protocol == cpu_to_be16(ETH_P_8021AD)) { /*
这里改了三层协议,protocol指向ip等
another_round不会再走这里
*/
skb = skb_vlan_untag(skb);
if (unlikely(!skb))
goto out;
} /* 不对数据包进行分类 */
if (skb_skip_tc_classify(skb))
goto skip_classify; /* prmemalloc */
if (pfmemalloc)
goto skip_taps; /* 下面两个是未(指定)设备的所有协议传递的上层传递 */ /* 如抓包程序未指定设备 */
/* 进行未指定设备的全局链表对应协议的skb上层传递 */
list_for_each_entry_rcu(ptype, &ptype_all, list) {
if (pt_prev)
ret = deliver_skb(skb, pt_prev, orig_dev);
pt_prev = ptype;
} /* 如抓包程序指定了设备 */
/* 进行指定设备的协议链表的skb上层传递 */
list_for_each_entry_rcu(ptype, &skb->dev->ptype_all, list) {
if (pt_prev)
ret = deliver_skb(skb, pt_prev, orig_dev);
pt_prev = ptype;
} skip_taps:
#ifdef CONFIG_NET_INGRESS
if (static_key_false(&ingress_needed)) {
skb = sch_handle_ingress(skb, &pt_prev, &ret, orig_dev);
if (!skb)
goto out; if (nf_ingress(skb, &pt_prev, &ret, orig_dev) < )
goto out;
}
#endif
skb_reset_tc(skb);
skip_classify: /* 不支持使用pfmemalloc */
if (pfmemalloc && !skb_pfmemalloc_protocol(skb))
goto drop; /* 如果是vlan包 */
if (skb_vlan_tag_present(skb)) {
/* 处理prev */
if (pt_prev) {
ret = deliver_skb(skb, pt_prev, orig_dev);
pt_prev = NULL;
} /* 根据实际的vlan设备调整信息,再走一遍 */
if (vlan_do_receive(&skb))
goto another_round;
else if (unlikely(!skb))
goto out;
} /* 如果有注册handler,那么调用,比如网桥模块 */
rx_handler = rcu_dereference(skb->dev->rx_handler);
if (rx_handler) {
if (pt_prev) {
ret = deliver_skb(skb, pt_prev, orig_dev);
pt_prev = NULL;
}
switch (rx_handler(&skb)) {
/* 已处理,无需进一步处理 */
case RX_HANDLER_CONSUMED:
ret = NET_RX_SUCCESS;
goto out;
/* 修改了skb->dev,在处理一次 */
case RX_HANDLER_ANOTHER:
goto another_round;
/* 精确传递到ptype->dev == skb->dev */
case RX_HANDLER_EXACT:
deliver_exact = true;
/* 正常传递即可 */
case RX_HANDLER_PASS:
break;
default:
BUG();
}
} /* 还有vlan标记,说明找不到vlanid对应的设备 */
if (unlikely(skb_vlan_tag_present(skb))) {
/* 存在vlanid,则判定是到其他设备的包 */
if (skb_vlan_tag_get_id(skb))
skb->pkt_type = PACKET_OTHERHOST;
/* Note: we might in the future use prio bits
* and set skb->priority like in vlan_do_receive()
* For the time being, just ignore Priority Code Point
*/
skb->vlan_tci = ;
} /* 设置三层协议,下面提交都是按照三层协议提交的 */
type = skb->protocol; /* deliver only exact match when indicated */
/* 未设置精确发送,则向未指定设备的指定协议全局发送一份 */
if (likely(!deliver_exact)) {
deliver_ptype_list_skb(skb, &pt_prev, orig_dev, type,
&ptype_base[ntohs(type) &
PTYPE_HASH_MASK]);
} /* 指定设备的,向原设备上层传递 */
deliver_ptype_list_skb(skb, &pt_prev, orig_dev, type,
&orig_dev->ptype_specific); /* 当前设备与原设备不同,向当前设备传递 */
if (unlikely(skb->dev != orig_dev)) {
deliver_ptype_list_skb(skb, &pt_prev, orig_dev, type,
&skb->dev->ptype_specific);
} if (pt_prev) {
if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC)))
goto drop;
else
/*
使用pt_prev这里就不需要deliver_skb来inc应用数了
func执行内部会free,减少了一次skb_free
*/
/* 传递到上层*/
ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
} else {
drop:
if (!deliver_exact)
atomic_long_inc(&skb->dev->rx_dropped);
else
atomic_long_inc(&skb->dev->rx_nohandler);
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:
return ret;
}

netif_receive_skb->__netif_receive_skb_core的更多相关文章

  1. ebtables hook

    1 概述 netfliter框架不仅仅在ipv4中有应用,bridge,ipv4,ipv6,decnet 这四种协议中都有应用,其中ipv4中又分开了arp和ip的两种 其实netfliter是个大的 ...

  2. Monitoring and Tuning the Linux Networking Stack: Receiving Data

    http://blog.packagecloud.io/eng/2016/06/22/monitoring-tuning-linux-networking-stack-receiving-data/ ...

  3. http://blog.csdn.net/zgl07/article/details/43491399

    转载申明:本文转载自http://www.brendangregg.com/perf.html   请大家看了之后如果要转载一定要注上这个地址!!! ========================= ...

  4. LInux下桥接模式详解三

    上篇文章介绍了Linux内核桥接模式涉及到的几个结构,本节就重点放在数据包的处理上! 本节所有代码参考LInux 3.10.1内核! 前面已经提到一个数据包从网卡流到Linux内核中的L2层,最终被交 ...

  5. 《Monitoring and Tuning the Linux Networking Stack: Receiving Data》翻译

    Overview 从宏观的角度来看,一个packet从网卡到socket接收缓冲区的路径如下所示: 驱动加载并初始化 packet到达网卡 packet通过DMA被拷贝到内核中的一个ring buff ...

  6. Linux内核网络数据包处理流程

    Linux内核网络数据包处理流程 from kernel-4.9: 0. Linux内核网络数据包处理流程 - 网络硬件 网卡工作在物理层和数据链路层,主要由PHY/MAC芯片.Tx/Rx FIFO. ...

  7. Linux内核网络报文简单流程

    转:http://blog.csdn.net/adamska0104/article/details/45397177 Linux内核网络报文简单流程2014-08-12 10:05:09 分类: L ...

  8. Linux 网络栈 转载

    此文章  来自      http://arthurchiao.art/blog/tuning-stack-rx-zh/ [译] Linux 网络栈监控和调优:接收数据(2016) Published ...

  9. Linux网络驱动--snull

    snull是<Linux Device Drivers>中的一个网络驱动的例子.这里引用这个例子学习Linux网络驱动. 因为snull的源码,网上已经更新到适合最新内核,而我自己用的还是 ...

随机推荐

  1. jquery中的append功能相当于剪切的作用 将原来的元素剪切走

    jquery中的append功能相当于剪切的作用 将原来的元素剪切走

  2. 下载文件 通过a 标签 请求某个servlet进行下载的

    下载文件 通过a 标签 请求某个servlet进行下载的

  3. Object 接受集合里面的任意数据类型 所有的类型默认继承object

  4. BZOJ3622 已经没有什么好害怕的了(动态规划+容斥原理)

    显然可以转化为一个阶梯状01矩阵每行每列取一个使权值和为k的方案数.直接做不可做,考虑设f[i][j]为前i行权值和至少为j,即在其中固定了j行选1的方案数.设第i行从1~a[i]列都是1且a[i]+ ...

  5. 【bzoj3295】[Cqoi2011]动态逆序对 树套树 线段树套替罪羊树

    这个东西,关于某个数的逆序对数为在他之前比他大的在他之后比他小的数的数目的和,所以删除之前先把这个减去就好了 人傻自带超大常数,中间由于内存池开小了所以运行错误. #include<cstdio ...

  6. C++11Mutex(互斥锁)详解

    多个线程访问同一资源时,为了保证数据的一致性,最简单的方式就是使用 mutex(互斥锁). (1).直接操作 mutex,即直接调用 mutex 的 lock / unlock 函数.此例顺带使用了 ...

  7. Android开发性能优化总结(一)

    安卓开发应用首先要讲究良好的用户体验,如果一款软件卡顿现象严重,不流畅,经常崩溃,那么将给用户带来极不良好的体验,从而损失用户. 在实际开发和学习中,我总结了一下关于安卓性能的优化,供大家参考交流. ...

  8. 【BZOJ4011】【HNOI2015】落忆枫音(动态规划)

    [BZOJ4011][HNOI2015]落忆枫音(动态规划) 题面 BZOJ 洛谷 Description 「恒逸,你相信灵魂的存在吗?」 郭恒逸和姚枫茜漫步在枫音乡的街道上.望着漫天飞舞的红枫,枫茜 ...

  9. BZOJ 4864: [BeiJing 2017 Wc]神秘物质 解题报告

    4864: [BeiJing 2017 Wc]神秘物质 Description 21ZZ 年,冬. 小诚退休以后, 不知为何重新燃起了对物理学的兴趣. 他从研究所借了些实验仪器,整天研究各种微观粒子. ...

  10. <深入理解计算机系统>第七章读书笔记

    第七章读书笔记 链接 链接:将各种代码和数据部分收集起来并组合成为一个单一文件的过程.(这个文件可被加载或拷贝到存储器并执行) 链接可以执行于编译,加载或运行时. 静态链接: 两个主要任务: 1 符号 ...