0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

linux网络栈监控及调优:数据接收

Linux阅码场 来源:窗有老梅 2023-03-25 16:44 次阅读

4. 初始化

b5041890-cae8-11ed-bfe3-dac502259ad0.jpg

图 1 网络设备在 packet 到达并需要处理时,通常会触发一个 IRQ。IRQ 处理函数是在很高的优先级下执行的,一般会阻塞其他 IRQs 的触发(译者注:often blocks additional IRQs from being generated。个人觉得原文这里并不准确,中断上下文中关中往往只是让 CPU 不响应中断,而不是让其他设备直接不发出中断)。故而,设备驱动中的 IRQ 处理函数必须越快越好,并将比较耗时的工作挪到中断上下文之外去执行,这就是为啥会有软中断系统。

linux 内核软中断系统支持在设备驱动的中断上下文之外处理工作。网络设备场景下,软中断系统用作处理 incoming packets。内核在 boot 阶段做软中断系统的初始化。 图 1 对应前文“软中断”一节,展示的是软中断系统及其 per-CPU 内核线程的初始化。 软中断系统的初始化流程如下:

spawn_ksoftirqd(kernel/softirq.c)调用 smpboot_register_percpu_thread(kernel/smpboot.c)创建软中断内核线程(每个 CPU 一个)。如代码所示,run_ksoftirqd 作为 smp_hotplug_thread 的 thread_fn,会在一个 loop 中被执行。

ksoftirqd 线程会在 run_ksoftirqd 中运行其 processing loop。

随后,创建 softnet_data 数据结构(前文“struct softnet_data 数据结构初始化”一节),每个 CPU 一个。此数据结构包含在网络数据处理时所需要的重要信息。另外还有一个 poll_list,下文会说。设备驱动调用 napi_schedule 或其他 NAPI APIs,将 NAPI poll 数据结构添加至 poll_list 上。

net_dev_init 调用 open_softirq 向软中断系统注册 NET_RX_SOFTIRQ 软中断,被注册的软中断处理函数是 net_rx_action(前文“软中断处理函数初始化”一节)。软中断内核线程会调用此函数来处理 packets。

图 1 中的第 5 - 8 步与数据的到达有关,下一节会说。

5. 数据到达

b536fc38-cae8-11ed-bfe3-dac502259ad0.jpg

图 2 数据从网络上来了(前文“数据到达”一节)! 网络数据到达 NIC 时,NIC 会通过 DMA 将 packet 数据写入 RAM。igb 网络驱动会在 RAM 中构建一个 ring buffer,其指向接收到的 packets。值得注意的是,有些 NIC 支持 "multiqueue",这些 NIC 可以使用多个处理器来处理 incoming 网络数据(前文“准备从网络接收数据”一节)。

简化起见,图 2 只画了一个 ring buffer,但取决于 NIC 以及硬件配置,你的系统可能使用的是多个队列。 下面流程的细节参阅前文“数据到达”一节。 我们来过一遍数据接收流程:

数据从网络到达 NIC。

NIC 通过 DMA 将网络数据写入 RAM。

NIC 触发一个 IRQ。

执行设备驱动注册的 IRQ 处理函数(前文“中断处理”一节)。

NIC 清除 IRQ,这样新 packet 到来时可以继续触发 IRQs。

调用 napi_schedule 拉起 NAPI 软中断 poll loop(前文“NAPI 与 napi_schedule”一节)。

napi_schedule 的调用触发了 图 1 中的 5 - 8 步。如后面所见,NAPI 软中断 poll loop 拉起的原理,就是翻转一个 bit 域,并向 poll_list 上添加一个数据结构。napi_schedule 没干什么其他事,这就是驱动将处理工作转交给软中断系统的原理。

继续分析 图 1,对照图中相应的数字:

驱动调用 napi_schedule 将驱动的 NAPI poll 数据结构添加至当前 CPU 的 poll_list 上。

软中断 pending bit 会被置上,如此该 CPU 上的 ksoftirqd 线程知晓有 packets 需要处理。

执行 run_ksoftirqd 函数(在 ksoftirqd 内核线程的 loop 中执行)。

调用 __do_softirq 检查是否有 pending 的 bit 域,以此确认是否有 pending 的软中断,进而调用 pending 软中断的处理函数:net_rx_action,该函数干了所有的 incoming 网络数据处理的脏活。

需要注意的是,软中断内核线程执行的是 net_rx_action,而不是设备驱动的 IRQ 处理函数。

6. 网络数据处理的开始

b556db02-cae8-11ed-bfe3-dac502259ad0.jpg

图 3 至此开始数据的处理。net_rx_action 函数(在 ksoftirqd 内核线程中调用)会执行当前 CPU poll_list 上注册的 NAPI poll 数据结构。poll 数据结构的注册一般有两种情况:

设备驱动调用 napi_schedule。

Receive Packet Steering 场景(前文“Receive Packet Steering(RPS)”一节)下使用 Inter-processor Interrupt。

我们将从 poll_list 获取驱动 NAPI 数据结构的流程串起来(下一节会讲 RPS 是怎么通过 IPIs 注册 NAPI 数据结构的)。 图 3 流程在前文有详细拆解过,总结一下就是:

net_rx_action poll 检查 NAPI poll list 中的 NAPI 数据结构。

校验 budget 及消耗的时间,以确保软中断不会霸占 CPU。

调用注册的 poll 函数(前文“NAPI poll 函数及权重”一节)。本文场景下,igb 驱动注册的是 igb_poll 函数。

驱动的 poll 函数收取 RAM ring buffer 中的 packets(前文“NAPI poll”一节)。

packets 进一步给到 napi_gro_receive,其可能会进一步被 Generic Receive Offloading 处理(前文“Generic Receive Offloading(GRO)”一节)。

packets 要么被 GRO 处理,这样整个调用链也就结束了;要么 packets 通过 net_receive_skb 进一步给到上层协议栈。

下面会讲 net_receive_skb 是怎么实现 Receive Packet Steering,也就是在多个 CPUs 之间分发 packet 的。

7. 网络数据的进一步处理

b55fbea2-cae8-11ed-bfe3-dac502259ad0.jpg

图 4 从 netif_receive_skb 开始继续网络数据的处理,数据的具体路径取决于是否使能了 Receive Packet Steering(RPS)。一个“开箱即用”的 linux 内核(译者注:意思就是通用的发行版)默认是不使能 RPS 的,如果你想用 RPS,就必须显式地配置及使能之。

RPS 禁能的情况下(前文“禁能 RPS 场景(默认配置)”一节),对应 图 4 中的如下数字:

1. netif_receive_skb 将数据给到 __netif_receive_core。

6. __netif_receive_core 将数据给到系统中可能存在的 taps(前文“packet tap 投递”一节)(比如 PCAP,https://www.tcpdump.org/manpages/pcap.3pcap.html)。

7. __netif_receive_core 将数据给到协议层注册的 handlers(前文“协议层投递”一节)。大多数情况下,此 handler 是 IPv4 协议栈所注册的 ip_rcv 函数。

RPS 使能的情况下(前文“使能 RPS 场景”一节):

netif_receive_skb 将数据给到 enqueue_to_backlog。

packets 会被送到 per-CPU 的输入队列上以待后续处理。

将远端 CPU 的 NAPI 数据结构添加至该远端 CPU 的 poll_list 上,并向该 CPU 发一个 IPI,进而唤醒远端 CPU 上的软中断内核线程(如果其并未在运行的话)。

当远端 CPU 上的 ksoftirqd 内核线程运行起来后,其处理模式与上一节中的相同,不同之处是,注册进来的 poll 函数是 process_backlog,该函数会从当前(译者注:本 CPU) CPU 的输入队列收取 packets。

packets 进一步给到 __net_receive_skb_core。

__net_receive_skb_core 将数据给到系统中可能存在的 taps(前文“packet tap 投递”一节)(比如 PCAP)。

__net_receive_skb_core 将数据给到协议层注册的 handlers(前文“协议层投递”一节)。大多数情况下,此 handler 是 IPv4 协议栈所注册的 ip_rcv 函数。

8. 协议栈及用户 sockets

数据接下来要走的路径是:协议栈、netfilter、Berkeley Packet Filters,最终到达用户 socket。 虽然代码路径挺长的,但是逻辑是直白清晰的。 网络数据路径更详细地拆解见前文“协议层注册”一节。下面是 high level 的简要总结:

IPv4 协议层通过 ip_rcv 收取 packets。

会做 netfilter 以及路由优化。

目标是本机的数据,会进一步给到更 high level 的协议层,比如 UDP。

UDP 协议层通过 udp_rcv 收取 packets,并通过 udp_queue_rcv_skb 及 sock_queue_rcv 将数据入队到用户 socket 的接收 buffer 中。在入队到接收 buffer 之前,会做 Berkeley Packet Filters。

值得注意的是,netfilter 在这个过程中会被调用多次,具体位置参考前文的详细拆解(前文“协议层注册”一节)。

9. 总结

linux 网络栈极其复杂,涉及到的系统很多。如果要监控这个复杂的系统就必须得搞清楚这些系统之间是怎么交互的,以及对某一系统配置的调整,会如何影响到其他系统。本文作为前文的补充,试图把这些问题梳理的更清晰易懂一些。





审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • cpu
    cpu
    +关注

    关注

    68

    文章

    10449

    浏览量

    206576
  • Linux系统
    +关注

    关注

    4

    文章

    567

    浏览量

    26923
  • IRQ
    IRQ
    +关注

    关注

    0

    文章

    16

    浏览量

    10602
  • 中断系统
    +关注

    关注

    1

    文章

    96

    浏览量

    60889

原文标题:图解之 linux 网络栈监控及调优:数据接收

文章出处:【微信号:LinuxDev,微信公众号:Linux阅码场】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    试验站远程监控系统网络接口的设计

    模块,发射与接收数据。无线传输的另一端经过TTL连接单片机,单片机再通过8位数据总线连接RTL8019AS,网络控制器用RJ45接口与以太网连接。通过无线传输和以太网,仪器仪表或控制设
    发表于 09-26 13:43

    linux网络监控系统

    linux网络监控系统
    发表于 10-07 10:27

    利用NDK网络传输大量数据遇到溢出问题

    的,而我是静态创建的,怎么出现这么大的, 2、假如我用网络调试助手向dsp发送数据,只是每次定义一个长度为2051的unsigned char类型数组来接收
    发表于 06-21 03:47

    利用ZigBee协议与GPRS模块串口通信,ZigBee怎么能有效接收处理串口返回的GPRS模块数据

    利用ZigBee协议,与GPRS模块串口通信,ZigBee怎么能有效接收处理串口返回的GPRS模块数据呢,,由于是利用AT指令,GPRS模块返回的数据均以回车换行(即“\r\n")结
    发表于 05-17 05:37

    HBase性能概述

    HBase性能
    发表于 07-03 11:35

    flume读取文件延迟说明

    flume读取文件延迟
    发表于 07-17 16:38

    功耗时经常用到的几个方法

    前言不清楚当前产品的整机功耗,就不清楚怎么获取产品的整机及各个模块的功耗数据,需要测量正确的功耗测量方法,快速的了解整机的功耗分布,为功耗
    发表于 12-21 06:31

    【视频】开发工具第8期:基于DevEco的系统高效五大法宝(一)

    本课程首先介绍了如何基于DevEco Device Tool内置工具进行系统高效,以及内置工具介绍。主要包含有镜像分析工具,估算分
    发表于 12-23 15:01

    【视频】开发工具第9期:基于DevEco的系统高效五大法宝(二)

    本课程首先介绍了如何基于DevEco Device Tool内置工具进行系统高效,以及内置工具介绍。主要包含有镜像分析工具,估算分
    发表于 12-23 15:08

    关于linux系统ulimit的相关资料分享

    1、linux ulimit介绍在 Linux 系统中,在每个进程中都有一组资源限制,进程默认打开的最大文件数个数为 1024 个,可以通过如下配置查看:在应用程序开发过程中,比如
    发表于 06-27 17:56

    基于全HDD aarch64服务器的Ceph性能实践总结

    提升吞吐率。- Linux内核中有很多网络相关的参数,我们可以根据不同的应用场景,不同的块大小来调整这些网络参数,以达到最优的性能。- 中断也是网络
    发表于 07-05 14:26

    KeenTune的算法之心——KeenOpt 算法框架 | 龙蜥技术

    文/KeenTune SIGKeenTune(轻豚)是一款 AI 算法与专家知识库双轮驱动的操作系统全式智能优化产品,为主流的操作系统提供轻量化、跨平台的一键式性能,让应用在智能定制的运行环境
    发表于 10-28 10:36

    HarmonyOS NEXT工具Smart Perf Host高效使用指南

    数据一键抓取,系统调度分析,CPU使用情况展示,调用展示,Native Memory跟踪和分析,文件系统跟踪,Trace抓取和分析和高阶使用方式(用户可以通过自定义SQL细粒度查询性能
    发表于 11-09 08:35

    基于嵌入式Linux视频的网络监控系统设计

    基于嵌入式Linux视频的网络监控系统设计 摘要:介绍了一种采用Browser/Server结构、在视频服务器上内置一个嵌入式Web服务器、基于嵌入式Linux视频的
    发表于 10-13 14:39 666次阅读
    基于嵌入式<b class='flag-5'>Linux</b>视频的<b class='flag-5'>网络</b><b class='flag-5'>监控</b>系统设计

    Linux网络接收过程的监控与调优

    上一篇文章中《图解Linux网络接收过程》,我们梳理了在Linux系统下一个数据包被接收的整个
    的头像 发表于 11-10 14:50 1467次阅读