Linux 网卡收包流程如下

Linux 网卡收包流程如下

  • 网卡收到数据包
  • 将数据包从网卡硬件缓存移动到服务器内存中(DMA方式,不经过CPU)
  • 通过硬中断通知CPU处理
  • CPU通过软中断通知内核处理
  • 经过TCP/IP协议栈处理
  • 应用程序通过read()从socket buffer读取数据

网卡丢包
我们先看下ifconfig的输出:

# ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.5.224.27  netmask 255.255.255.0  broadcast 10.5.224.255
        inet6 fe80::5054:ff:fea4:44ae  prefixlen 64  scopeid 0x20<link>
        ether 52:54:00:a4:44:ae  txqueuelen 1000  (Ethernet)
        RX packets 9525661556  bytes 10963926751740 (9.9 TiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 8801210220  bytes 12331600148587 (11.2 TiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0Copy

登录系统底层,检查管理网网卡收发是否存在持续增长的errors包,使用命令:

# watch -n 1 "ifconfig eth0"
# watch -n 1 ip -s link show eth0
说明:watch可以将命令的输出结果输出到标准输出设备,多用于周期性执行命令/定时执行命令,-n或-interval来指定间隔的时间,缺省每2秒运行一下程序;eth1为网卡名称。

  • 正常的
  • 异常的

RX(receive) 代表接收报文, TX(transmit) 表示发送报文。

  • RX errors: 表示总的收包的错误数量,这包括 too-long-frames 错误,Ring Buffer 溢出错误,crc 校验错误,帧同步错误,fifo overruns 以及 missed pkg 等等。
  • RX dropped: 表示数据包已经进入了 Ring Buffer,但是由于内存不够等系统原因,导致在拷贝到内存的过程中被丢弃。
  • RX overruns: 表示 fifo 的 overruns,由于 Ring Buffer(aka Driver Queue) 传输的 IO 大于 kernel 能够处理的 IO 导致的,而 Ring Buffer 则是指在发起 IRQ 请求之前的那块 buffer。很明显,overruns 的增大意味着数据包没到 Ring Buffer 就被网卡物理层给丢弃了,CPU 无法及时的处理中断是造成 Ring Buffer 满的原因之一,可能原因是因为 interruprs 分布的不均匀,没有做 affinity 而造成的丢包。
  • RX frame: 表示 misaligned 的 frames。

dropped 与 overruns 的区别:

  • dropped,表示这个数据包已经进入到网卡的接收缓存 fifo 队列,并且开始被系统中断处理准备进行数据包拷贝(从网卡缓存 fifo 队列拷贝到系统内存),但由于此时的系统原因(比如内存不够等)导致这个数据包被丢掉,即这个数据包被 Linux 系统丢掉。
  • overruns,表示这个数据包还没有被进入到网卡的接收缓存 fifo 队列就被丢掉,因此此时网卡的 fifo 是满的。为什么 fifo 会是满的?因为系统繁忙,来不及响应网卡中断,导致网卡里的数据包没有及时的拷贝到系统内存, fifo 是满的就导致后面的数据包进不来,即这个数据包被网卡硬件丢掉。所以,如果遇到 overruns 非0,需要检测cpu负载与cpu中断情况。

环形队列Ring Buffer溢出
当网卡的缓存区(ring buffer)设置的太小。网络数据包到达(生产)的速率快于内核处理(消费)的速率时, Ring Buffer 很快会被填满,新来的数据包将被丢弃。
通过 ethtool 或 /proc/net/dev 可以查看因Ring Buffer满而丢弃的包统计

[root@xxx ~]# ethtool -S ens2 | grep fifo
     rx_fifo_errors: 0
     tx_fifo_errors: 0
[root@xxx ~]# cat /proc/net/dev | grep ens2
  ens2:  659229    8107    0    0    0     0          0         0   249827    2833    0    0    0     0       0          0

可以通过ethtool 设置ring buffer 的缓冲区大小

# 修改网卡eth0接收与发送硬件缓存区大小
$ ethtool -G eth0 rx 4096 tx 4096
Pre-set maximums:
RX:     4096  
RX Mini:    0
RX Jumbo:   0
TX:     4096  
Current hardware settings:
RX:     4096  
RX Mini:    0
RX Jumbo:   0
TX:     4096

中断过程中的问题

  • 什么是中断
    中断有两种:一种硬中断;一种软中断。硬中断是由硬件产生的,比如,像磁盘,网卡,键盘;软中断是由当前正在运行的进程所产生的。

硬中断,是一种由硬件产生的电信号直接发送到中断控制器上,然后由中断控制器向 CPU 发送信号,CPU 检测到该信号后,会中断当前的工作转而去处理中断。然后,处理器会通知内核已经产生中断,这样内核就会对这个中断进行适当的处理。

当网卡收到数据包时会产生中断请求(硬中断)通知到 CPU,CPU 会中断当前正在运行的任务,然后通知内核有新数据包,内核调用中断处理程序(软中断)进行响应,把数据包从网卡缓存及时拷贝到内存,否则会因为缓存溢出被丢弃。剩下的处理和操作数据包的工作就会交给软中断。

  • 什么是多队列网卡
    当网卡不断的接收数据包,就会产生很多中断,一个中断请求只能被一个CPU处理, 而现在的机器都是用多个CPU,同时只有一个 CPU 去处理 Ring Buffer 数据会很低效,这个时候就产生了叫做 Receive Side Scaling(RSS) 或者叫做 multiqueue 的机制来处理这个问题, 这就是为啥需要多队列的原因。

RSS(Receive Side Scaling)是网卡的硬件特性,实现了多队列。通过多队列网卡驱动加载,获取网卡型号,得到网卡的硬件 queue 的数量,并结合 CPU 核的数量,最终通过 Sum=Min(网卡 queue,CPU core)得出所要激活的网卡 queue 数量。

NIC 收到 Frame 的时候能通过 Hash Function 来决定 Frame 该放在哪个 Ring Buffer 上,触发的 IRQ 也可以通过操作系统或者手动配置 IRQ affinity 将 IRQ 分配到多个 CPU 上。这样 IRQ 能被不同的 CPU 处理,从而做到 Ring Buffer 上的数据也能被不同的 CPU 处理,从而提高数据的并行处理能力。

RSS 除了会影响到 NIC 将 IRQ 发到哪个 CPU 之外,不会影响别的逻辑。

  • 什么是RPS
    Receive Packet Steering(RPS) 是在 NIC 不支持 RSS 时候在软件中实现 RSS 类似功能的机制。其好处就是对 NIC 没有要求,任何 NIC 都能支持 RPS,但缺点是 NIC 收到数据后 DMA 将数据存入的还是一个 Ring Buffer,NIC 触发 IRQ 还是发到一个 CPU,还是由这一个 CPU 调用 driver 的 poll 来将 Ring Buffer 的数据取出来。RPS 是在单个 CPU 将数据从 Ring Buffer 取出来之后才开始起作用,它会为每个 Packet 计算 Hash 之后将 Packet 发到对应 CPU 的 backlog 中,并通过 Inter-processor Interrupt(IPI) 告知目标 CPU 来处理 backlog。后续 Packet 的处理流程就由这个目标 CPU 来完成。从而实现将负载分到多个 CPU 的目的。通常如果开启了RPS会加重所有 CPU 的负担.
  • IRQ 中断请求 亲和绑定
    /proc/interrupts 文件中可以看到各个 CPU 上的中断情况。

/proc/irq/[irq_num]/smp_affinity_list 可以查看指定中断当前绑定的 CPU。

可以通过配置 IRQ affinity 指定 IRQ 由哪个 CPU 来处理中断, 先通过 /proc/interrupts 找到 IRQ 号之后,将希望绑定的 CPU 号写入 /proc/irq/IRQ_NUMBER/smp_affinity,写入的是 16 进制的 bit mask。比如看到队列 rx_0 对应的中断号是 41 那就执行:

echo 6 > /proc/irq/41/smp_affinity
6 表示的是 CPU2 和 CPU1

0 号 CPU 的掩码是 0x1 (0001),1 号 CPU 掩码是 0x2 (0010),2 号 CPU 掩码是 0x4 (0100),3 号 CPU 掩码是 0x8 (1000) 依此类推。

  • softirq 数统计
    通过 /proc/softirqs 能看到每个 CPU 上 softirq 数量统计:

cat /proc/softirqs
                    CPU0       CPU1      
          HI:          1          0
       TIMER: 1650579324 3521734270
      NET_TX:   10282064   10655064
      NET_RX: 3618725935       2446
       BLOCK:          0          0
BLOCK_IOPOLL:          0          0
     TASKLET:      47013      41496
       SCHED: 1706483540 1003457088
     HRTIMER:    1698047   11604871
         RCU: 4218377992 3049934909

NET_RX 表示网卡收到包时候触发的 softirq,一般看这个统计是为了看看 softirq 在每个 CPU 上分布是否均匀,不均匀的话可能就需要做一些调整。比如上面看到 CPU0 和 CPU1 两个差距很大,原因是这个机器的 NIC 不支持 RSS,没有多个 Ring Buffer。开启 RPS 后就均匀多了。

  • 如何开启RPS
    RPS 默认是关闭的,当机器有多个 CPU 并且通过 softirqs 的统计 /proc/softirqs 发现 NET_RX 在 CPU 上分布不均匀或者发现网卡不支持 mutiqueue 时,就可以考虑开启 RPS。

开启 RPS 需要调整 /sys/class/net/DEVICE_NAME/queues/QUEUE/rps_cpus 的值。比如执行:

echo f > /sys/class/net/eth0/queues/rx-0/rps_cpus
表示的含义是处理网卡 eth0 的 rx-0 队列的 CPU 数设置为 f 。即设置有 15 个 CPU 来处理 rx-0 这个队列的数据,如果你的 CPU 数没有这么多就会默认使用所有 CPU 。

  • netdev_max_backlog调优
    netdev_max_backlog 是内核从 NIC 收到包后,交由协议栈(如 IP、TCP )处理之前的缓冲队列, 通过softnet_stat可以确定是否发生了netdev backlog队列溢出

[root@xxx ~]# cat /proc/net/softnet_stat
000000bf 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000028 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
000000c7 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000031 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
000021d8 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000929 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

C#复制全屏

每一行代表每个 CPU 核的状态统计,从 CPU0 依次往下。
每一列代表一个 CPU 核的各项统计:第一列代表中断处理程序收到的包总数;第二列即代表由于 netdev_max_backlog 队列溢出而被丢弃的包总数。
第3列表示软中断一次取走netdev_budget个数据包,或取数据包时间超过2ms的次数。
第4~8列固定为0,没有意义。
第9列表示发送数据包时,对应的队列被锁住的次数。

netdev_max_backlog 的默认值是 1000,我们可以修改内核参数来调优:

sysctl -w net.core.netdev_max_backlog=2000

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/483684.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

<数据集>路面坑洼识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;665张 标注数量(xml文件个数)&#xff1a;665 标注数量(txt文件个数)&#xff1a;665 标注类别数&#xff1a;1 标注类别名称&#xff1a;[pothole] 序号类别名称图片数框数1pothole6651740 使用标注工具&#x…

Oracle篇—通过官网下载最新的数据库软件或者历史数据库软件

&#x1f4ab;《博主介绍》&#xff1a;✨又是一天没白过&#xff0c;我是奈斯&#xff0c;DBA一名✨ &#x1f4ab;《擅长领域》&#xff1a;✌️擅长Oracle、MySQL、SQLserver、阿里云AnalyticDB for MySQL(分布式数据仓库)、Linux&#xff0c;也在扩展大数据方向的知识面✌️…

dns实验3:主从同步-完全区域传输

服务器192.168.234.111&#xff08;主服务器&#xff09;&#xff0c;打开配置文件&#xff1a; 打开配置文件&#xff1a; 关闭防火墙&#xff0c;改宽松模式&#xff1a; 重启服务&#xff1a; 服务器192.168.234.112&#xff08;从服务器&#xff09;&#xff0c;打开配置文…

OpenCV圆形标定板检测算法findCirclesGrid原理详解

OpenCV的findCirclesGrid函数检测圆形标定板的流程如下:   findCirclesGrid函数源码: //_image,输入图像 //patternSize,pattern的宽高 //_centers,blobs中心点的位置 //flags,pattern是否对称 //blobDetector,这里使用的是SimpleBlobDetector bool cv::findCirclesGrid(…

Java - JSR223规范解读_在JVM上实现多语言支持

文章目录 1. 概述2. 核心目标3. 支持的脚本语言4. 主要接口5. 脚本引擎的使用执行JavaScript脚本执行groovy脚本1. Groovy简介2. Groovy脚本示例3. 如何在Java中集成 Groovy4. 集成注意事项 6. 与Java集成7. 常见应用场景8. 优缺点9. 总结 1. 概述 JSR223&#xff08;Java Spe…

自然语言处理:基于BERT预训练模型的中文命名实体识别(使用PyTorch)

命名实体识别&#xff08;NER&#xff09; 命名实体识别&#xff08;Named Entity Recognition, NER&#xff09;是自然语言处理&#xff08;NLP&#xff09;中的一个关键任务&#xff0c;其目标是从文本中识别出具有特定意义的实体&#xff0c;并将其分类到预定义的类别中。这…

【C++】数组

1.概述 所谓数组&#xff0c;就是一个集合&#xff0c;该集合里面存放了相同类型的数据元素。 数组特点&#xff1a; &#xff08;1&#xff09;数组中的每个数据元素都是相同的数据类型。 &#xff08;2&#xff09;数组是有连续的内存空间组成的。 2、一维数组 2.1维数组定…

微软表示不会使用你的 Word、Excel 数据进行 AI 训练

​微软否认使用 Microsoft 365 应用程序&#xff08;包括 Word、Excel 和 PowerPoint&#xff09;收集数据来训练公司人工智能 (AI) 模型的说法。 此前&#xff0c;Tumblr 的一篇博文声称&#xff0c;雷德蒙德使用“互联体验”功能抓取客户的 Word 和 Excel 数据&#xff0c;用…

leetcode--螺旋矩阵

LCR 146.螺旋遍历二维数组 给定一个二维数组 array&#xff0c;请返回「螺旋遍历」该数组的结果。 螺旋遍历&#xff1a;从左上角开始&#xff0c;按照 向右、向下、向左、向上 的顺序 依次 提取元素&#xff0c;然后再进入内部一层重复相同的步骤&#xff0c;直到提取完所有元…

C++ 分治

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 1.分治法 2.二分搜索 函数传参——数组 3.棋盘覆盖 4.合并排序 5.快速排序 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 1.分治法 基…

Spark常问面试题---项目总结

一、数据清洗&#xff0c;你都清洗什么&#xff1f;或者说 ETL 你是怎么做的&#xff1f; 我在这个项目主要清洗的式日志数据&#xff0c;日志数据传过来的json格式 去除掉无用的字段&#xff0c;过滤掉json格式不正确的脏数据 过滤清洗掉日志中缺少关键字段的数据&#xff…

基于智能语音交互的智能呼叫中心工作机制

在智能化和信息化不断进步的现代&#xff0c;智能呼叫中心为客户提供高质量、高效率的服务体验&#xff0c;提升众多品牌用户的满意度和忠诚度。作为实现智能呼叫中心的关键技术之一的智能语音交互技术&#xff0c;它通过集成自然语言处理&#xff08;NLP&#xff09;、语音识别…

Android Studio 右侧工具栏 Gradle 不显示 Task 列表

问题&#xff1a; android studio 4.2.1版本更新以后AS右侧工具栏Gradle Task列表不显示&#xff0c;这里需要手动去设置 解决办法&#xff1a; android studio 2024.2.1 Patch 2版本以前的版本设置&#xff1a;依次打开 File -> Settings -> Experimental 选项&#x…

SpringBoot集成Kafka和avro和Schema注册表

Schema注册表 为了提升kafka的性能&#xff0c;减少网络传输和存储的数据大小&#xff0c;可以把数据的schema部分单独存储到外部的schema注册表中&#xff0c;整体架构如下图所示&#xff1a; 1&#xff09;把所有数据需要用到的 schema 保存在注册表里&#xff0c;然后在记…

http(请求方法,状态码,Cookie与)

目录 1.http中常见的Header(KV结构) 2.http请求方法 2.1 请求方法 2.2 telnet 2.3 网页根目录 2.3.1 概念 2.3.2 构建一个首页 2.4 GET与POST方法 2.4.1 提交参数 2.4.2 GET与POST提交参数对比 2.4.3 GET和POST对比 3.状态码 3.1 状态码分类 3.2 3XXX状态码 3.2 …

十,[极客大挑战 2019]Secret File1

点击进入靶场 查看源代码 有个显眼的紫色文件夹&#xff0c;点击 点击secret看看 既然这样&#xff0c;那就回去查看源代码吧 好像没什么用 抓个包 得到一个文件名 404 如果包含"../"、"tp"、"input"或"data"&#xff0c;则输出"…

pytest自定义命令行参数

实际使用场景&#xff1a;pytest运行用例的时候&#xff0c;启动mitmdump进程试试抓包&#xff0c;pytest命令行启动的时候&#xff0c;传入mitmdump需要的参数&#xff08;1&#xff09;抓包生成的文件地址 &#xff08;2&#xff09;mitm的proxy设置 # 在pytest的固定文件中…

Unity AssetBundles(AB包)

目录 前言 AB包是什么 AB包有什么作用 1.相对Resources下的资源AB包更好管理资源 2.减小包体大小 3.热更新 官方提供的打包工具:Asset Bundle Browser AB包资源加载 AB包资源管理模块代码 前言 在现代游戏开发中&#xff0c;资源管理是一项至关重要的任务。随着游戏内容…

(一)Linux下安装NVIDIA驱动(操作记录)

目录 一、查看CUDA版本 1.输入nvidia-smi&#xff0c;查看驱动支持的最大CUDA版本&#xff0c;这里是11.6 2.输入nvcc --version&#xff0c;查看当前安装的CUDA版本&#xff0c;这里是11.3 二、卸载旧的NVIDIA驱动 1.卸载原有驱动 2.禁用nouveau&#xff08;必须&#x…

用Python做数据分析环境搭建及工具使用(Jupyter)

目录 一、Anaconda下载、安装 二、Jupyter 打开 三、Jupyter 常用快捷键 3.1 创建控制台 3.2 命令行模式下的快捷键 3.3 运行模式下快捷键 3.4 代码模式和笔记模式 3.5 编写Python代码 一、Anaconda下载、安装 【最新最全】Anaconda安装python环境_anaconda配置python…