分享好友 最新动态首页 最新动态分类 切换频道
内核是如何接收网络包的
2024-12-26 09:27

1、数据帧从外部网络到达网卡
2、网卡把数据帧从自己的缓存DMA(拷贝到)和内核共有的RingBuffer上
3、网卡发出硬中断通知CPU
4、CPU响应硬中断,简单处理后发出软中断
5、k’softirqd线程处理软中断,调用网卡驱动注册的poll函数开始收包
6、帧被从RingBuffer上摘下来被保存为一个skb
7、协议层开始处理网络帧,处理玩后的数据data被放到socket的接收队列中
8、内核唤醒用户进程

Linux的软中断都是在专门的内核线程(ksoftirqd)中进行的。
该线程的数量等于设备的核数。

系统初始化的时候在kernel/smpboot.c中调用smpboot_register_percpu_thread,该函数进一步会执行到spawn_ksoftirqd(位于kernel/softirq.c)来创建出softirqd线程。

相关代码如下

 

当ksoftirqd被创建出来以后,就会进入线程循环函数ksoftirqd_should_run和run_ksoftirqd了。接下来判断有没有软中断需要处理。软中断不只有网络软中断,还有其他类型。Linux内核在interrupt.h定义了所有类型的软中断类型:

 
 

在网络子系统的初始化过程中,会为每个CPU初始化softnet_data,也会为RX_SOFTIRQ和TX_SOFTIRQ注册处理函数,流程如下:
1、调用subsys_initcall(net_dev_init)(net/core/dev.c
2、为每个CPU初始化softnet_data //include.linux/netdevice.h
3、将NET_RX_SOFTIRQ的处理函数注册为net_rx_action,将NET_TX_SOFTIRQ的处理函数注册为net_tx_action
4、将软中断与处理函数的对应关系记录到soft_irq_vec数组

网络子系统初始化会执行net_dev_init函数,在这个函数里,会为每个CPU都申请一个softnet_data数据结构,这个数据结构里的poll_list用于等待驱动程序将其poll函数注册进来;另外open_softirq为每一种软中断都注册一个处理函数,继续跟踪open_softirq后发现这个注册的方式是记录在softirq_vec变量里的,后面ksoftirqd线程收到软中断的时候,也会使用这个变量查找每一种软中断对应的处理函数。

 
 
 

内核实现了网络层的IP协议,也实现了传输层的TCP协议和UDP协议,这些协议对应的实现函数分别是ip_rcv()、tcp_v4_rcv()和udp_rcv。fs_initcall调用inet_init后开始网络协议栈注册,通过inet_init将这些函数注册到inet_protos和ptype_base数据结构中。
相关代码如下

 
 
 
 
 

inet_add_protocol函数将TCP和UDP对应的处理函数都注册到inet_protos数组中。ip_pack_type结构体中的Type是协议名,func是ip_rcv函数,它们在dev_add_pack中会注册到ptype_base哈希表中。软中断根据ptype_base找到ip_rcv函数地址进而将IP包正确地送到ip_rcv中执行。在ip_rcv中将会通过inet_protos找到TCP或者UDP的处理函数,再把包转发给udp_rcv或tcp_rcv。

每一个驱动程序会使用module_init向内核注册一个初始化函数,当驱动程序被加载时,内核就会调用这个函数;比如igb网卡驱动程序位于drivers/net/ethernet/intel/igb/igb_main.c中。

 

驱动的pci_register_driver调用完成后,Linux内核就知道了该驱动的相关信息。当网卡设备被识别之后,内核会调用其驱动的probe方法让设备处于ready状态。对于igb网卡,其igb_probe位于drivers/net/ethernet/inetl/igb_main.c下。该函数主要执行操作如下:
1、启动注册到内核
2、调用网卡驱动Probe
3、获取网卡MAC
4、DMA初始化
5、注册ethtool实现函数
6、注册net_device_ops、netdev等变量
7、NAPI初始化,注册poll函数

 

第7步在igb_probe初始化过程中,还调用到了igb_alloc_q_vector。它注册了一个NAPI机制必需的poll函数。
igb_probe->igb_sw_init->igb_init_interrupt_scheme->igb_alloc_q_vectors->igb_alloc_q_vector->
netif_napi_add

 

1.5.1 启动网卡

当上面都初始化完成之后,就可以启动网卡。
1、启动网卡
2、调用net_device_ops中注册的open函数,如igb_open
3、分配Rx、Tx队列内存
4、注册中断处理函数
5、打开硬中断,等待包进来

 

_igb_open函数调用了igb_setup_all_tx_resources和igb_setup_all_rx_resources。在调用igb_setup_all_rx_resources这一步操作中,分配了RingBuffer,并建立了内存和Rx队列的映射关系。

 

在上面的源码中,通过循环创建了若干个接收队列。下面看每一个队列是怎么创建出来的。

 

从上述源码可以看到,实际上Ringbuffer的内部不是仅有一个环形队列数组,而是有两个。
igb_rx_buffer数组:这个数组是内核使用,通过vzalloc申请
e1000_adv_rx_desc数组:这个数组是网卡硬件使用的,通过dma_alloc_coherent分配。

 

对于多队列网卡,为每一个队列都注册了中断,其对应中断处理函数为igb_msix_ring。在msix方式下,每个RX队列都有队列的MSI-X中断,从网卡硬件中断的层面就可以设置让收到的包被不同的CPU处理。(可以通过irqalance,或者修改/proc/irq/IRQ_NUMBER/smp_affinity,从而修改和CPU的绑定行为)。

当数据帧从网线到达网卡时,第一站是网卡的接收队列,网卡在自己的RingBuffer寻找可用的内存位置,找到DMA引擎会把数据DMA到网卡之前关联的内存里,到这个时候CPU都是无感的;当DMA操作完成之后,网卡向CPU发起一个硬中断,通知CPU有数据到达。过程如下
1、数据帧从外部网络到达网卡
2、网卡把帧DMA到内存
3、发出IRQ硬中断
4、调用驱动注册的硬中断处理函数
5、启动NAPI,发出软中断
网卡的硬中断处理函数是igb_msix_ring。

 

可以看到,这里只是把驱动napi_struct传过来的poll_list添加到CPU变量softnet_data中的poll_list。紧接着__raise_softirq_irqoff触发了一个软中断NET_RX_SOFTIRQ,这个触发过程只是进行了一个或运算。

1.5.1 ksoftirqd内核线程处理软中断

 

从这里可以看到,此函数和硬中断调用了同一个函数local_softirq_pending。
注意:硬中断中的设置软中断标记和ksoftirq中判断是否有软中断到达,都是基于smp_processor_id()。这意味着只要硬中断在哪个CPU上被响应,那么软中断也是在这个CPU上处理的。如果发现Linux软中断的某个CPU消耗都集中在一个核上,正确做法应该是调整硬中断的CPU亲和性。

使用方式的不同之处在于,在硬中断处理中是为了写入标记,这里是读取。如果读取到了NET_RX_SOFTIRQ,则进入内核线程处理函数run_ksoftirqd进行处理:

 

在__do_softirq中,判断根据当前CPU的软中断类型,调用个其注册的action方法。

 
 

在硬中断中将设备添加到poll_list,会不会重复添加呢?
答案是不会的,在软中断处理函数net_rx_action这里,先调用local_irq_disable把所有的硬中断关闭了,把CPU的netsoft_data的poll_list直接拷贝出来之后再开的中断,不会给硬中断重复添加poll_list的机会。

函数开头的time_limit和budget是用来控制net_rx_action函数主动退出的,目的是保证网络包的接收不霸占CPU不放。这个函数核心逻辑就是获取softnet_data的poll_list进行遍历,然后执行到网卡驱动注册的poll函数。对于igb网卡来说就是igb_poll函数。

 

在读取操作中,igb_poll的重点工作是对igb_clean_rx_igb的调用。

 

igb_fetch_rx_buffer和igb_is_non_eop的作用就是把数据帧从RingBuffer取下来;Skb被从RingBuffer取下来后,会通过igb_alloc_rx_buffer申请新的skb再重新挂上去。接下来进入napi_gro_receive函数。

 

dev_gro_receive这个函数代表的是网卡GRO特性,可以简单理解成把相关小包组成一个大包,目的是减少传送给网络栈的包数,有助于降低对CPU的使用量。接下来看napi_skb_finish,这个函数主要是调用了netif_receive_skb_internal,netif_receive_skb_internal又调用了__netif_receive_skb,在__netif_receive_skb中,数据包将被送到协议栈。

 

1.6 网络协议栈处理

 

在__netif_receive_skb_core中可以看到tcpdump命令的抓包点和netfilter的输入的第一个挂接点,tcpdump将抓包函数以协议形式挂到ptype_all上,设备层遍历所有协议,就能抓到数据包了,tcpdump会执行packet_create。

 

register_prot_hook会把tcpdump用到的协议挂到ptype_all上。

接着__netif_receive_skb_core函数取出protocol,它会从数据包中取出协议信息,然后遍历注册在这个协议上的回调函数列表。ptype_base是一个哈希表。ip_rcv函数地址就存在这个哈希表中。

 

pt_prev->func调用了协议层注册的处理函数,对于IP包就会进入ip_rcv(如果是arp包就会进入arp_rcv)。

1.7 IP层处理

 

这是第二个iptables_netfilter的挂载点(NF_INET_PRE_ROUTING)。

 

当执行完注册的钩子后就会执行到最后一个参数指向的函数ip_rcv_finish。

 

所以回到ip_rcv_finish中的return dst_input(skb)调用的input方法就是路由子系统赋的ip_local_deliver。

 
 

inet_protos中保存着tcp_v4_rcv和udp_rcv的函数地址。这里会根据包的协议类型选择分发,在这里skb包派送到更上层的协议中。

准备工作

  • 创建ksoftirqd线程,为它设置好自己的线程函数
  • 协议栈注册
  • 网卡驱动初始化,每个驱动都有一个初始化函数,内核让驱动也初始化,在初始化过程中,把自己的DMA准备好,把NAPI的poll函数地址告诉内核
  • 启动网卡,分配RX、TX队列,注册中断对应的处理函数
最新文章
潮玩宇宙运动会游戏源码搭建二开运动会(用户PK平台/用户PK用户)潮玩大逃杀游戏源码H
演示找客服要。带有“卡拉米运动会”字样的都是抄袭,这是我们随便命名的一个名字,却被一些同行拿来当成自己演示忽悠客户,一定要看准演示站,好好体验一下是否跟图一致,图片好抄,演示不给看,请各位老板谨慎考察对待哦。鹿鸣成品演示站
来领100元、30元、10元中银消费券啦!(仅限河南省)
大家好,我是向南2013!下面为大家介绍一下推出的手机银行消费券活动!2023年11月18日10:00-12月31日23:59每天上午10:00开始活动内容:参与流程:特别提醒:1、三种面额消费券,每人每月仅可领取其中一张。2、使用商户:河南省内线下支持中
股票行情快报:精测电子(300567)12月12日主力资金净买入383.69万元
证券之星消息,截至2024年12月12日收盘,精测电子(300567)报收于69.06元,下跌0.04%,换手率2.49%,成交量5.05万手,成交额3.47亿元。12月12日的资金流向数据方面,主力资金净流入383.69万元,占总成交额1.11%,游资资金净流出1994.82万元
看过《猪里同学X相马同学》的人还看过
感谢您对我方的信任,我们将按照法律法规要求,采取严格的安全保护措施,保护您的个人隐私信息。在此,我们郑重的提醒您:1.在您使用我方提供的服务时,建议您详细阅读本用户隐私政策,详细了解我方收集,存储,使用,披露和保护您的个人信
再见,樱桃子!爸爸讨厌她,爷爷偷看她洗澡,一生苦难却要赠与全世界温暖…
本文来自:微悉尼(wesydney)“你的梦想是什么?”“希望能活得很有趣,很满足地迎接消亡。”——三浦美纪(1965~2018)照片上的这个女孩笑容腼腆,而眼神里充满了乐观。她的打扮不算光芒四射,就算站在颁奖台上也吸引不了灯光师的注意。
提升百度推广创意效果的关键策略
优化百度推广创意,提升广告效果的关键在于:深入分析目标受众,精准定位关键词;创意内容应简洁有力,突出产品优势;合理运用A/B,持续优化广告文案和图片;结合时事热点,提高广告的吸引力和相关性;合理分配预算,关注广告投放效果,及
天猫推广怎么收费?天猫有哪些推广方式?
现在已经不是酒香不怕巷子深的时代了,尤其做电商,可以说是酒香也怕巷子深。要想要更多的消费者,一定要推广,淘宝推广方法就牵扯费用的问题。那么,天猫推广怎么收费?天猫有哪些推广方式? 要看你的推广方法了,不同的方式费用是不一样的
不玩遥遥领先也不选国外品牌,手机怎么买?OPPO一加手机2023新品盘点
临近双11了,准备换新的人也越来越多,很多朋友机关单位工作,苹果三星手机各种限制不能用,华为手机又觉得遥遥领先超出预算,听说我略懂手机,就问我国产手机还能选什么,既要性价比高,品牌和品质也要可靠。思来想去,还是推荐了oppo和一
跨境电商选品之道:精准定位,制胜全球市场
在跨境电商的浩瀚商海中,选品无疑是决定远航方向的罗盘,其重要性不言而喻。 一.市场调研是选品的灯塔。借助跨境电商平台提供的大数据分析工具,能洞察各类产品在不同地区的销售热度与趋势走向。例如,观察到欧美
面部识别追踪创纪录鲸类迁徙
近日,一项发表于英国《皇家学会开放科学》的研究中,海洋生态学家使用面部识别软件成功追踪到一头跨越了1.3万公里、从哥伦比亚迁徙到坦桑尼亚的座头鲸,打破了此前1万公里的纪录。加拿大渔业及海洋部鲸类研究项目的海洋哺乳动物生物学家Ch
相关文章
推荐文章
发表评论
0评