在设备驱动收包之后,会通过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. 第94天:CSS3 盒模型详解

    CSS3盒模型详解 盒模型设定为border-box时 width = border + padding + content 盒模型设定为content-box时 width = content所谓定 ...

  2. web端调百度地图页面

    在点击进入地图的入口(下面数据是vue渲染的数据) <a class="navigation" v-if="merchant.longitude && ...

  3. HDU2460-Network

    题目 给一个\(n\)个点\(m\)条边的无向连通图,\(Q\)次往图中加边,每次加边后问图中的桥有多少个.(加边后边留着). \(n\le 10^5,m\le 2\times 10^5,Q\le 1 ...

  4. bzoj3663/4660CrazyRabbit && bzoj4206最大团

    题意 给出平面上N个点的坐标,和一个半径为R的圆心在原点的圆.对于两个点,它们之间有连边,当且仅当它们的连线与圆不相交.求此图的最大团. 点数<=2000,坐标的绝对值和半径<=5000. ...

  5. 【uoj#175】新年的网警 结论题+Hash

    题目描述 给出一张 $n$ 个点 $m$ 条边的无向连通图,每条边的边权为1.对于每个点 $i$ ,问是否存在另一个点 $j$ ,使得对于任意一个不为 $i$ 或 $j$ 的点 $k$ ,$i$ 到 ...

  6. [十二]SpringBoot 之 servlet

    Web开发使用 Controller 基本上可以完成大部分需求,但是我们还可能会用到 Servlet.Filter.Listener.Interceptor 等等. 当使用spring-Boot时,嵌 ...

  7. css基于文件格式使用不同的样式

    a[href^="http://"]{ padding-right: 20px; background: url(external.gif) no-repeat center ri ...

  8. 解数独(Python)

    0.目录 1.介绍 2.一些通用函数 3.全局变量(宏变量) 4.数独预处理(约束传播) 5.解数独(深度优先搜索+最小代价优先) 6.主函数 7.总代码 1.介绍 数独是一个非常有趣味性的智力游戏, ...

  9. Unity3D手游开发日记(4) - 适合移动平台的热浪扭曲

    热浪扭曲效果的实现,分两部分,一是抓图,二是扭曲扰动.其中难点在于抓图的处理,网上的解决方案有两种,在移动平台都有很多问题,只好自己实现了一种新的方案,效果还不错. 网上方案1. 用GrabPass抓 ...

  10. 51nod1967 路径定向(欧拉回路+结论题)

    看到入度等于出度想到欧拉回路. 我们把边都变成无向边,有一个结论是偶数度的点都可以变成出入度相等的点,而奇数点的不行,感性理解分类讨论一下就知道是对的. 还有一个更好理解的结论是变成无向边后奇数点的个 ...