接收网络包的过程——从硬件网卡解析到IP层
当一些网络包到来触发了中断,内核处理完这些网络包之后,我们可以先进入主动轮询 poll 网卡的方式,主动去接收到来的网络包。如果一直有,就一直处理,等处理告一段落,就返回干其他的事情。当再有下一批网络包到来的时候,再中断,再轮询 poll。这样就会大大减少中断的数量,提升网络处理的效率,这种处理方式我们称为 NAPI。
在网卡驱动程序初始化的时候,我们会调用 ixgb_init_module,注册一个驱动 ixgb_driver,并且调用它的 probe 函数 ixgb_probe。
在 ixgb_probe 中,我们会创建一个 struct net_device 表示这个网络设备,并且 netif_napi_add 函数为这个网络设备注册一个轮询 poll 函数 ixgb_clean,将来一旦出现网络包的时候,就是要通过它来轮询了。
当一个网卡被激活的时候,我们会调用函数 ixgb_open->ixgb_up,在这里面注册一个硬件的中断处理函数。
如果一个网络包到来,触发了硬件中断,就会调用 ixgb_intr,这里面会调用 __napi_schedule。
__napi_schedule 是处于中断处理的关键部分,在他被调用的时候,中断是暂时关闭的,但是处理网络包是个复杂的过程,需要到延迟处理部分,所以 ____napi_schedule 将当前设备放到 struct softnet_data 结构的 poll_list 里面,说明在延迟处理部分可以接着处理这个 poll_list 里面的网络设备。
然后 ____napi_schedule 触发一个软中断 NET_RX_SOFTIRQ,通过软中断触发中断处理的延迟处理部分,也是常用的手段。
在 net_rx_action 中,会得到 struct softnet_data 结构,这个结构在发送的时候我们也遇到过。当时它的 output_queue 用于网络包的发送,这里的 poll_list 用于网络包的接收。
在 net_rx_action 中,接下来是一个循环,在 poll_list 里面取出网络包到达的设备,然后调用 napi_poll 来轮询这些设备,napi_poll 会调用最初设备初始化的时候,注册的 poll 函数,对于 ixgb_driver,对应的函数是 ixgb_clean。
在网络设备的驱动层,有一个用于接收网络包的 rx_ring。它是一个环,从网卡硬件接收的包会放在这个环里面。这个环里面的 buffer_info[]是一个数组,存放的是网络包的内容。i 和 j 是这个数组的下标,在 ixgb_clean_rx_irq 里面的 while 循环中,依次处理环里面的数据。在这里面,我们看到了 i 和 j 加一之后,如果超过了数组的大小,就跳回下标 0,就说明这是一个环。
ixgb_check_copybreak 函数将 buffer_info 里面的内容,拷贝到 struct sk_buff *skb,从而可以作为一个网络包进行后续的处理,然后调用 netif_receive_skb。
从 netif_receive_skb 函数开始,我们就进入了内核的网络协议栈。
接下来的调用链为:netif_receive_skb->netif_receive_skb_internal->__netif_receive_skb->__netif_receive_skb_core。
在 __netif_receive_skb_core 中,我们先是处理了二层的一些逻辑。例如,对于 VLAN 的处理,接下来要想办法交给第三层。
在网络包 struct sk_buff 里面,二层的头里面有一个 protocol,表示里面一层,也即三层是什么协议。deliver_ptype_list_skb 在一个协议列表中逐个匹配。如果能够匹配到,就返回。
网络协议栈的 IP 层,从 ip_rcv 函数开始,我们的处理逻辑就从二层到了三层,IP 层。
在 ip_rcv 中,得到 IP 头,然后又遇到了我们见过多次的 NF_HOOK,这次因为是接收网络包,第一个 hook 点是 NF_INET_PRE_ROUTING,也就是 iptables 的 PREROUTING 链。如果里面有规则,则执行规则,然后调用 ip_rcv_finish。
ip_rcv_finish 得到网络包对应的路由表,然后调用 dst_input,在 dst_input 中,调用的是 struct rtable 的成员的 dst 的 input 函数。在 rt_dst_alloc 中,我们可以看到,input 函数指向的是 ip_local_deliver。
在 ip_local_deliver 函数中,如果 IP 层进行了分段,则进行重新的组合。接下来就是我们熟悉的 NF_HOOK。hook 点在 NF_INET_LOCAL_IN,对应 iptables 里面的 INPUT 链。在经过 iptables 规则处理完毕后,我们调用 ip_local_deliver_finish。
在 IP 头中,有一个字段 protocol 用于指定里面一层的协议,在这里应该是 TCP 协议。于是,从 inet_protos 数组中,找出 TCP 协议对应的处理函数。这个数组的定义如下,里面的内容是 struct net_protocol。
在系统初始化的时候,网络协议栈的初始化调用的是 inet_init,它会调用 inet_add_protocol,将 TCP 协议对应的处理函数 tcp_protocol、UDP 协议对应的处理函数 udp_protocol,放到 inet_protos 数组中。
在上面的网络包的接收过程中,会取出 TCP 协议对应的处理函数 tcp_protocol,然后调用 handler 函数,也即 tcp_v4_rcv 函数。
接收网络包的上半部分,分以下几个层次。
- 硬件网卡接收到网络包之后,通过 DMA 技术,将网络包放入 Ring Buffer。
- 硬件网卡通过中断通知 CPU 新的网络包的到来。
- 网卡驱动程序会注册中断处理函数 ixgb_intr。
- 中断处理函数处理完需要暂时屏蔽中断的核心流程之后,通过软中断 NET_RX_SOFTIRQ 触发接下来的处理过程。
- NET_RX_SOFTIRQ 软中断处理函数 net_rx_action,net_rx_action 会调用 napi_poll,进而调用 ixgb_clean_rx_irq,从 Ring Buffer 中读取数据到内核 struct sk_buff。
- 调用 netif_receive_skb 进入内核网络协议栈,进行一些关于 VLAN 的二层逻辑处理后,调用 ip_rcv 进入三层 IP 层。
- 在 IP 层,会处理 iptables 规则,然后调用 ip_local_deliver,交给更上层 TCP 层。
- 在 TCP 层调用 tcp_v4_rcv。

此文章为11月Day25学习笔记,内容来源于极客时间《趣谈Linux操作系统》,推荐该课程。
相关文章:
接收网络包的过程——从硬件网卡解析到IP层
当一些网络包到来触发了中断,内核处理完这些网络包之后,我们可以先进入主动轮询 poll 网卡的方式,主动去接收到来的网络包。如果一直有,就一直处理,等处理告一段落,就返回干其他的事情。当再有下一批网络包…...
正则化与正则剪枝
写在前面:本博客仅作记录学习之用,部分图片来自网络,如需引用请注明出处,同时如有侵犯您的权益,请联系删除! 文章目录 引言正则化为什么会过拟合拉格朗日与正则化梯度衰减与正则化 应用解决过拟合网络剪枝 …...
Element-Plus 图标自动导入
🚀 作者主页: 有来技术 🔥 开源项目: youlai-mall 🍃 vue3-element-admin 🍃 youlai-boot 🌺 仓库主页: Gitee 💫 Github 💫 GitCode 💖 欢迎点赞…...
关于DCDC电源中的PWM与PFM
在开关电源DCDC中,我们经常会听到PWM模式与PFM模式。 关于,这两种模式,小编在之前的文章中,做过简单的描述。今天就来针对性的就这两种模式展开讲讲。 PWM:脉冲宽度调制,即频率不变,不断调整脉…...
S25FL系列FLASH读写的FPGA实现
文章目录 实现思路具体实现子模块实现top模块 测试Something 实现思路 建议读者先对 S25FL-S 系列 FLASH 进行了解,我之前的博文中有详细介绍。 笔者的芯片具体型号为 S25FL256SAGNFI00,存储容量 256Mb,增强高性能 EHPLC,4KB 与 6…...
一次【自定义编辑器功能脚本】【调用时内存爆仓】事故排查
一 、事故描述 我有一个需求:在工程文件中找得到所有的图片(Texture 2D),然后把WebGL发布打包时的图片压缩规则进行修改。 项目中有图片2千多张,其中2k分辨率的图片上百张,当我右键进行批量处理的时候&…...
【STM32单片机】简易计算器设计
文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用STM32F103C8T6单片机控制器,使用动态数码管模块、矩阵按键、蜂鸣器模块等。 主要功能: 系统运行后,数码管默认显示0,输入对应的操作数进行四则运…...
【详解二叉树】
🌠作者:TheMythWS. 🎇座右铭:不走心的努力都是在敷衍自己,让自己所做的选择,熠熠发光。 目录 树形结构 概念 树的示意图 树的基本术语 树的表示 树的应用 二叉树(重点) 二叉树的定义 二叉树的五…...
【Amazon】在Amazon EKS集群中安装部署最小化KubeSphere容器平台
文章目录 一、准备工作二、部署 KubeSphere三、访问 KubeSphere 控制台四、安装Amazon EBS CSI 驱动程序4.1 集群IAM角色建立并赋予权限4.2 安装 Helm Kubernetes 包管理器4.3 安装Amazon EBS CSI 驱动程序 五、常见问题六、参考链接 一、准备工作 Kubernetes 版本必须为&…...
ubuntu20.04下安装标注工具CVAT
1 安装docker sudo apt-get update sudo apt-get --no-install-recommends install -y apt-transport-https ca-certificates \curl \gnupg-agent \software-properties-commoncurl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - sudo add-apt-r…...
pytest-pytest-html测试报告这样做,学完能涨薪3k
在 pytest 中提供了生成html格式测试报告的插件 pytest-html 安装 安装命令如下: pip install pytest-html使用 我们已经知道执行用例的两种方式,pytest.main()执行和命令行执行,而要使用pytest-html生成报告,只需要在执行时加…...
本地运行“李开复”的零一万物 34B 大模型
这篇文章,我们来聊聊如何本地运行最近争议颇多的,李开复带队的国产大模型:零一万物 34B。 写在前面 零一万物的模型争议有很多,不论是在海外的社交媒体平台,还是在国内的知乎和一种科技媒体上,不论是针对…...
Redis-Redis缓存高可用集群
1、Redis集群方案比较 哨兵模式 在redis3.0以前的版本要实现集群一般是借助哨兵sentinel工具来监控master节点的状态,如果master节点异常,则会做主从切换,将某一台slave作为master,哨兵的配置略微复杂,并且性能和高可…...
Django之admin页面样式定制(Simpleui)
好久不见,各位it朋友们! 本篇文章我将向各位介绍Django框架中admin后台页面样式定制的一个插件库,名为Simpleui。 一)简介 SimpleUI是一款简单易用的用户界面(UI)库,旨在帮助开发人员快速构建…...
TypeScript 中的type与interface
TypeScript 中的type与interface 对于 TypeScript,有两种定义类型的方法:type与interface。 人们常常想知道该使用哪一种,而答案并不是一刀切的。这确实取决于具体情况。有时,其中一种比另一种更好,但在许多情况下&a…...
【uniapp】uniapp开发小程序定制uni-collapse(折叠面板)
需求 最近在做小程序,有一个类似折叠面板的ui控件,效果大概是这样 代码 因为项目使用的是uniapp,所以打算去找uniapp的扩展组件,果然给我找到了这个叫uni-collapse的组件(链接:uni-collapse)…...
单片机学习7——定时器/计数器编程
#include<reg52.h>unsigned char a, num; sbit LED1 P1^0;void main() {num0;EA1;ET01;//IT00;//设置TMOD的工作模式TMOD0x01;//给定时器装初值,50000,50ms中断20次,就得到1sTH0(65536-50000)/256;TL0(65536-50000)%256;TR01; // 定时器/计数器启…...
OpenWrt Lan口上网设置
LAN口上网设置 连接上openwrt,我用的 倍控N5105,eth0,看到Openwrt的IP是10.0.0.1 在 网络 -> 网口配置 -> 设置好 WAN 口和 LAN 口 初次使用经常重置 openwrt 所以我设置的是 静态IP模式 - 网络 -> 防火墙 -> 常规设置 ->…...
监控同一局域网内其它主机上网访问信息
1.先取得网关IP 2.安装IPTABLES路由表 sudo apt-get install iptables 3.启用IP转发 sudo sysctl -p 查看配置是否生效 4.配置路由 iptables -t nat -A POSTROUTING -j MASQUERADE 配置成功后,使用sudo iptables-save查看...
DC cut 滤直流滤波器实现
在音频处理中,会无意中产生直流偏置,这个偏置如果通过功放去推喇叭,会对喇叭造成不可逆转的损坏,所以在实际应用中,会通过硬件(添加直流检测模块,如果有 使用继电器切断输出) 、软件(软件直流滤波算法)&…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...
【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
JavaScript 数据类型详解
JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型(Primitive) 和 对象类型(Object) 两大类,共 8 种(ES11): 一、原始类型(7种) 1. undefined 定…...
数据库正常,但后端收不到数据原因及解决
从代码和日志来看,后端SQL查询确实返回了数据,但最终user对象却为null。这表明查询结果没有正确映射到User对象上。 在前后端分离,并且ai辅助开发的时候,很容易出现前后端变量名不一致情况,还不报错,只是单…...
数据结构:泰勒展开式:霍纳法则(Horner‘s Rule)
目录 🔍 若用递归计算每一项,会发生什么? Horners Rule(霍纳法则) 第一步:我们从最原始的泰勒公式出发 第二步:从形式上重新观察展开式 🌟 第三步:引出霍纳法则&…...
