当前位置: 首页 > article >正文

Realtek 8126驱动分析第四篇——multi queue相关

Realtek 8126是 5G 网卡,因为和 8125 较为接近,第四篇从这里开始也无不可。本篇主要是讲 multi queue 相关,其他的一些内容在之前就已经提过,不加赘述。

1 初始化

1.1 rtl8126_init_one

从第一篇我们可以知道每个 PCI 驱动都注册了一个 probe() 方法,为设备寻找驱动就是调用其 probe() 方法,即 rtl8126_init_one。这里我们重点讲 multi queue 相关的内容。

1.1.1 rtl8126_init_board

/* dev zeroed in alloc_etherdev */
dev = alloc_etherdev_mq(sizeof (*tp), R8126_MAX_QUEUES);

分配并设置以太网设备,这里的 R8126_MAX_QUEUES 指 TX 和 RX 都有这么多个 queue。

1.1.2 rtl8126_try_msi

该函数里主要是先确定了支援的 irq vector number,最关键的是 rtl8126_enable_msix 函数。这样内核就根据硬件能力分配了实际的 vector 即中断号。

static int rtl8126_enable_msix(struct rtl8126_private *tp)
{int i, nvecs = 0;struct msix_entry msix_ent[R8126_MAX_MSIX_VEC];/** 这里的entry表示设备支持的MSI-X表项索引(即设备硬件层面的中断条目编号)。* 例如,设备支持16个MSI-X中断,entry可以是0-15* 而vector表示系统范围内唯一的中断向量号(Interrupt Vector Number)。* 该向量号是CPU中断描述符表(IDT)的索引,用于在硬件触发中断时,CPU查找对应的中断处理函数*/for (i = 0; i < R8126_MAX_MSIX_VEC; i++) {msix_ent[i].entry = i;msix_ent[i].vector = 0;}/* 调用pci_enable_msix_range(),内核根据硬件能力和系统资源分配实际的vector,* 并回填到msix_entry.vector*/nvecs = pci_enable_msix_range(tp->pci_dev, msix_ent,tp->min_irq_nvecs, tp->max_irq_nvecs);if (nvecs < 0)goto out;for (i = 0; i < nvecs; i++) {struct r8126_irq *irq = &tp->irq_tbl[i];irq->vector = msix_ent[i].vector;}out:return nvecs;
}

1.1.3 rtl8126_init_software_variable

这个函数主要是初始化一些变量,诸如 HwSuppNumTxQueues 和 HwSuppNumRxQueues。

这里要注意以下代码,这里调用内核限制设置了 rss queue 的数量上限。

/* 此例程应设置多队列设备默认使用的 RSS 队列数量的上限。*/
u8 rss_queue_num = netif_get_num_default_rss_queues();
tp->num_rx_rings = (tp->HwSuppNumRxQueues > rss_queue_num)?rss_queue_num : tp->HwSuppNumRxQueues;

然后根据之前设置的变量的值,在 rtl8126_setup_mqs_reg 函数中,设置不同的 ring 对应的硬件寄存器的值,这里比较重要的就是如果支援 multi queue,那么每个 queue 对应的 descriptor start address 都要设置。另外对于 RX 还要额外设置 ISR 和 IMR。

在函数 rtl8126_set_ring_size 中,设置每个 ring 的 ring size 即 descriptor number。

最关键的就是函数rtl8126_init_rss。

void rtl8126_init_rss(struct rtl8126_private *tp)
{int i;/* 0~HwSuppIndirTblEntries对queue numbers取余,得到hash indirection table*/for (i = 0; i < rtl8126_rss_indir_tbl_entries(tp); i++)tp->rss_indir_tbl[i] = ethtool_rxfh_indir_default(i, tp->num_rx_rings);/* 该函数依赖内核的强随机数生成器,生成 RSS 哈希密钥*/netdev_rss_key_fill(tp->rss_key, RTL8126_RSS_KEY_SIZE);
}

1.1.4 rtl8126_init_napi

这个函数主要是为每一个 irq vector 注册napi的poll方法。在中断线程被触发后,内核会执行中断处理函数 ISR,进而进入软中断收包环节。而进入软中断,就会调用到这里注册的 poll 函数。

1.1.5 rtl8126_set_real_num_queue

通过合理设置实际队列数,可最大化利用多核CPU和硬件加速特性(如RSS),同时避免因配置不当导致的性能瓶颈或稳定性问题。

1.2 rtl8126_open

ndo_open 在 8126 驱动中就是 rtl8126_open,当网络设备转换为启动状态时,将调用此函数。

1.2.1 alloc desc

这两个函数初始化DMA描述符环形缓冲区,用于网卡收发包。

1.2.2 rtl8126_init_ring

int
rtl8126_init_ring(struct net_device *dev)
{struct rtl8126_private *tp = netdev_priv(dev);int i;/* 初始化ring的一些变量 */rtl8126_init_ring_indexes(tp);/* 初始化trx desc ring,并为tx ring设置 end of ring */rtl8126_tx_desc_init(tp);rtl8126_rx_desc_init(tp);for (i = 0; i < tp->num_tx_rings; i++) {struct rtl8126_tx_ring *ring = &tp->tx_ring[i];memset(ring->tx_skb, 0x0, sizeof(ring->tx_skb));}for (i = 0; i < tp->num_rx_rings; i++) {struct rtl8126_rx_ring *ring = &tp->rx_ring[i];
#ifdef ENABLE_PAGE_REUSEring->rx_offset = R8126_RX_ALIGN;
#elsememset(ring->Rx_skbuff, 0x0, sizeof(ring->Rx_skbuff));
#endif //ENABLE_PAGE_REUSEif (rtl8126_rx_fill(tp, ring, dev, 0, ring->num_rx_desc, 0) != ring->num_rx_desc)goto err_out;rtl8126_mark_as_last_descriptor(tp, rtl8126_get_rxdesc(tp, ring->RxDescArray, ring->num_rx_desc - 1));}return 0;err_out:rtl8126_rx_clear(tp);return -ENOMEM;
}

1.2.3 rtl8126_alloc_irq

该函数主要是为每个 irq 设置 中断处理函数 iSR rtl8126_interrupt_msix,并利用 request_irq 注册中断。

1.2.4 rtl8126_hw_config

void rtl8126_config_rss(struct rtl8126_private *tp)
{if (!tp->EnableRss) {rtl8126_disable_rss(tp);return;}_rtl8126_config_rss(tp);
}

着重就是讲这个函数。

void _rtl8126_config_rss(struct rtl8126_private *tp)
{/* 设置寄存器 RSS_CTRL_8125 的值 */_rtl8126_set_rss_hash_opt(tp);/* 把之前得到的 redirection table 写进寄存器里 */rtl8126_store_reta(tp);/* 将之前内核生成的 rss key 写进寄存器里 */rtl8126_store_rss_key(tp);
}

rtl8126_set_rx_q_num 和 rtl8126_set_tx_q_num 要向寄存器里写入 TRX queue 的数目。

到此为止,关于 multi queue 的所有初始化就已经完成了。

2 收发包

2.1 收包

如果有数据包过来,并且触发了硬件中断,那么就会调用 rtl8126_interrupt_msix 函数,首先判断是否是 link change,这显然不是,然后就会 disable hw interrupt,随后要转入软中断。

进而就会调用对应的 poll 函数,这里我们不去区分 mapping 方式,最终 RX 都会调用到函数 rtl8126_rx_interrupt。这里其他的我们不用去管,只要看一个函数 rtl8126_rx_hash。

以 rtl8126_rx_hash_v3 为例,关于 hash 的信息保存在 descriptor 中,提取出 hash 值后,赋给 skb->hash,至此工作完成。

2.2 发包

发包的部分更为简单,发包函数 rtl8126_start_xmit 会通过 skb_get_queue_mapping 来选择用哪个 queue,得出 queue_mapping 用作 queue number 即可。这里的 skb->queue_mapping 是上层计算出的结果。

到此为止,主要的 multi queue 相关的就已经完成了,但是在 linux driver 中,还有通过 ethtool 来修改 rss 相关的 code 需要介绍。

3 ethtool

.get_rxnfc => rtl8126_get_rxnfc 该函数用于返回 rx ring number 以及 返回 rss hash option。

.set_rxnfc >= rtl8126_set_rxnfc 该函数用于设置 rss hash option,这里要注意,UDP RSS 是需要通过这个函数来开启的,default 不支持。

.get_rxfh_indir_size >= rtl8126_rss_indir_size 该函数用于返回 indirection table 的 size。

.get_rxfh_key_size >= rtl8126_get_rxfh_key_size 该函数返回 rss_key 的 size。

.get_rxfh >= rtl8126_get_rxfh 该函数用于获得 indirection table 和 rss_key。

.set_rxfh >= rtl8126_set_rxfh 该函数用于将 ethtool 给的 indirection table 和 rss_key 写入寄存器,采用它们。

如果觉得这篇文章有用的话,可以点赞、评论或者收藏,万分感谢,goodbye~

相关文章:

Realtek 8126驱动分析第四篇——multi queue相关

Realtek 8126是 5G 网卡&#xff0c;因为和 8125 较为接近&#xff0c;第四篇从这里开始也无不可。本篇主要是讲 multi queue 相关&#xff0c;其他的一些内容在之前就已经提过&#xff0c;不加赘述。 1 初始化 1.1 rtl8126_init_one 从第一篇我们可以知道每个 PCI 驱动都注…...

基于Java和PostGIS的AOI面数据球面面积计算实践

目录 前言 一、计算方法简介 二、球面面积计算 1、AOI数据转Polygon 2、Geotools面积计算 3、GeographicLib面积计算 4、PostGIS面积计算 三、结果分析 1、不同算法结果对比 2、与互联网AOI对比 3、与天地图测面对比 四、总结 前言 在现代地理信息系统&#xff08;G…...

Spring Boot之Web服务器的启动流程分析

如何判断创建哪种web容器&#xff1a;servlet&#xff1f;reactive&#xff1f; 我们在启动Spring Boot程序的时候&#xff0c;会使用SpringApplication.run方法来启动&#xff0c;在启动流程中首先要判断的就是需要启动什么类型的服务器&#xff0c;是servlet&#xff1f;或者…...

C# SQLite高级功能示例

目录 1 主要功能 2 程序结构和流程 3 详细实现说明 3.1 基础设置 3.2 事务演示 3.3 索引演示 3.4 视图演示 3.5 触发器演示 3.6 全文搜索演示 3.7 窗口函数演示 3.8 外键约束演示 4 高级功能示例 5 单个方法详细介绍 5.1 SetupExampleData()方法 5.2 UseTransact…...

【周输入】510周阅读推荐-1

本号一年了&#xff0c;有一定的成长&#xff0c;也有很多读者和点赞。自觉更新仍然远远不够&#xff0c;需要继续努力。 但是还是要坚持2点&#xff1a; 在当前这个时代&#xff0c;信息大爆炸&#xff0c;层次不齐&#xff0c;不追加多&#xff0c; 信息输入可以很多&#x…...

基于动态规划的强化学习方法

目录 # 动态规划 # 基于动态规划的强化学习方法 # 求解过程&#xff1a; ## 策略评估 ## 策略提升 # 价值迭代算法 # 参考 # 动态规划 动态规划的基本思想是将待求解问题分解成若干个子问题&#xff0c;先求解子问题&#xff0c;然后从这些子问题的解得到目标问题的解。…...

启动 spyder ModuleNotFoundError: No module named ‘PyQt5.QtWebKitWidgets‘

一、根本原因 Spyder 版本兼容性&#xff1a;Spyder 4.x 依赖 QtWebKitWidgets&#xff0c;但该模块在 PyQt5 5.15 中已被移除。 PyQt5 版本冲突&#xff1a;如果你安装了较新的 PyQt5&#xff08;如 5.15&#xff09;&#xff0c;则会缺少 QtWebKitWidgets。 二、解决方案 方法…...

ChemBlender:科研绘图创新解决方案

一、研究背景与冲突 &#xff08;一&#xff09;研究背景 在科学研究领域&#xff0c;可视化表达对于成果的呈现与交流至关重要。科研绘图作为科学可视化的关键手段&#xff0c;涵盖了从微观分子结构到宏观实验现象等广泛的内容。随着科研的深入发展&#xff0c;研究对象的复杂…...

Uniapp Android/IOS 获取手机通讯录

介绍 最近忙着开发支付宝小程序和app&#xff0c;下面给大家介绍一下 app 获取通讯录的全部过程吧&#xff0c;也是这也是我app开发中的一项需求吧。 效果图如下 勾选配置文件 使用uniapp开发的童鞋都知道有一个配置文件 manifest.json 简单的说一下&#xff0c;就是安卓/ios/…...

设计一个分布式系统:要求全局消息顺序,如何使用Kafka实现?

一、高吞吐低延迟 Kafka 集群设计要点 1. 分区策略优化 // 计算合理分区数公式&#xff08;动态调整&#xff09; int numPartitions max(Tp, Tc) / min(Tp, Tc) // Tp生产者吞吐量 Tc消费者吞吐量建议初始按业务键&#xff08;如订单ID&#xff09;哈希分区单分区吞吐建议…...

2025年RIS SCI2区,改进白鲸优化算法+复杂非线性方程组求解,深度解析+性能实测

目录 1.摘要2.白鲸优化算法BWO原理3.改进策略4.结果展示5.参考文献6.代码获取7.读者交流 1.摘要 本文提出了一种改进白鲸优化算法&#xff08;ABWOA&#xff09;用来解决非线性方程组&#xff08;SNLEs&#xff09;求解问题。ABWOA引入了平衡因子和非线性自适应参数&#xff0…...

Java后端开发day48--反射动态代理

&#xff08;以下内容全部来自上述课程&#xff09; 反射 反射允许对成员变量&#xff0c;成员方法和构造方法的信息进行编程访问。 就是获取里面的成员变量、构造方法和成员方法&#xff0c;idea中打代码跳出来的提示就是反射。 1. 获取class对象的三种方式 Class.for…...

十四、继承与组合(Inheritance Composition)

十四、继承与组合&#xff08;Inheritance & Composition&#xff09; 引言 C最引人注目的特性之一是代码复用。组合&#xff1a;在新类中创建已有类的对象。继承&#xff1a;将新类作为已有类的一个类型来创建。 14.1 组合的语法 Useful.h //C14:Useful.h #ifndef US…...

ValueError: Caught ValueError in DataLoader worker process 0.

参考链接&#xff1a; https://stackoverflow.com/questions/1841565/valueerror-invalid-literal-for-int-with-base-10 它提示我有个地方值错误空字符 果然因为格式处理没有传进去东西&#xff0c;找下原因&#xff0c;让它正常处理 原来是相对路径的.影响了程序运行 将v…...

【数据结构】——链表OJ(下)

前面我们已经刷了几道单链表的题目&#xff0c;下面我们继续看几道题目。 一、相交链表 这道题题目的要求是很好理解的&#xff0c;就是现在我们有两个链表&#xff0c;然后我们就相办法进行判断&#xff0c;这两个链表是否是相交的&#xff0c;那么链表的相交其实就是有没有共…...

Adobe Acrobat pro在一份PDF中插入空白页

在Adobe Acrobat pro中先打开我们的PDF文件&#xff1b; 用鼠标点击需要插入空白页处的上一页&#xff1b; 然后如下图操作&#xff1a; 默认会在光标处的下一页插入一张空白页&#xff0c;你也可以修改插入页的页码或者向前一页插入...

java-----异常

对于Error&#xff1a;表示系统级错误或者资源耗尽的状况&#xff0c;像OutOfMemoryError、StackOverflowError等。这类错误是程序无法处理的&#xff0c;通常也不应该尝试去处理。 对于Exception&#xff1a;表示程序可以处理的异常。它又能细分为&#xff1a; 受检查异常&a…...

[工具]B站缓存工具箱 (By 郭逍遥)

&#x1f4cc; 项目简介 B站缓存工具箱是一个多功能的B站缓存工具&#xff0c;包含视频下载、缓存重载、文件合并及系统设置四大核心功能。基于yutto开发&#xff0c;采用图形化界面操作&#xff0c;极大简化B站资源获取与管理流程。 工具可以直接将原本缓存的视频读取&#…...

《内网渗透测试:绕过最新防火墙策略》

内网渗透测试是检验企业网络安全防御体系有效性的核心手段&#xff0c;而现代防火墙策略的持续演进&#xff08;如零信任架构、AI流量分析、深度包检测&#xff09;对攻击者提出了更高挑战。本文系统解析2024年新型防火墙的防护机制&#xff0c;聚焦协议隐蔽隧道、上下文感知绕…...

python_竞态条件

好的&#xff0c;我们通过一个具体的例子来说明在多线程环境中&#xff0c;可变对象和不可变对象的行为差异&#xff0c;以及不可变对象如何避免竞态条件&#xff08;race condition&#xff09;。 1. 竞态条件&#xff08;Race Condition&#xff09; 竞态条件是指在多线程环…...

聊聊JetCache的CachePenetrationProtect

序 本文主要研究一下JetCache的CachePenetrationProtect CachePenetrationProtect com/alicp/jetcache/anno/CachePenetrationProtect.java Documented Retention(RetentionPolicy.RUNTIME) Target({ElementType.METHOD, ElementType.FIELD}) public interface CachePenetr…...

【实战】基于 ABP vNext 构建高可用 S7 协议采集平台(西门子 PLC 通信全流程)

&#x1f680;&#x1f527;【实战】基于 ABP vNext 构建高可用 S7 协议采集平台&#xff08;西门子 PLC 通信全流程&#xff09;&#x1f4ca; &#x1f4d1; 目录 &#x1f680;&#x1f527;【实战】基于 ABP vNext 构建高可用 S7 协议采集平台&#xff08;西门子 PLC 通信全…...

数据结构:树(Tree)

目录 为什么需要树&#xff1f; &#x1f331; 基本的树结构定义 什么是树&#xff1f; 树的术语 &#x1f33f; 常见基本树的变体 &#x1f333; 二叉搜索树&#xff08;BST&#xff09; &#x1f332; 自平衡二叉搜索树 1. AVL树&#xff08;Adelson-Velsky and La…...

自动化测试与功能测试详解

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 什么是自动化测试? 自动化测试是指利用软件测试工具自动实现全部或部分测试&#xff0c;它是软件测试的一个重要组成 部分&#xff0c;能完成许多手工测试无…...

java中的Optional

在 Java 8 中&#xff0c;Optional 是一个用于处理可能为 null 的值的容器类&#xff0c;旨在减少空指针异常&#xff08;NullPointerException&#xff09;并提升代码的可读性。以下是 Optional 的核心用法和最佳实践&#xff1a; 1. 创建 Optional 对象 1.1 常规创建方式 Op…...

Qt事件循环机制

受事件循环机制影响&#xff0c;按钮的样式表改变了可能不会立即刷新。 需要使用 update() 或 repaint() 或者调用 QApplication::processEvents() 强制处理所有待处理的事件&#xff0c;从而确保界面更新。 在 Qt 中&#xff0c;事件循环&#xff08;Event Loop&#xff09;是…...

深入理解 OAuth 2.0:技术核心与实战场景

在互联网应用日益复杂的今天&#xff0c;如何安全、高效地实现第三方应用授权访问资源&#xff0c;成为开发者面临的重要问题。OAuth 2.0 凭借其灵活、安全的授权机制&#xff0c;成为解决这一问题的主流方案。本文将深入剖析 OAuth 2.0 的技术重点&#xff0c;并结合具体使用场…...

Rust 环境变量管理秘籍:从菜鸟到老鸟都爱的 dotenv 教程

前言 写代码的你,是否遭遇过这些灵魂拷问: “我现在在哪个环境?开发?测试?还是直接在生产线上裸奔?”“少写一个 .env,测试脚本在数据库里上演清空大法,客户当场破防。”“每次手动设置 RUST_ENV,命令敲到一半就开始怀疑人生,还怕输错一个字符引发灭世级事故。”别慌…...

CSS经典布局之圣杯布局和双飞翼布局

目标&#xff1a; 中间自适应&#xff0c;两边定宽&#xff0c;并且三栏布局在一行展示。 圣杯布局 实现方法&#xff1a; 通过float搭建布局margin使三列布局到一行上relative相对定位调整位置&#xff1b; 给外部容器添加padding&#xff0c;通过相对定位调整左右两列的…...

OpenCV 的 CUDA 模块中用于将多个单通道的 GpuMat 图像合并成一个多通道的图像 函数cv::cuda::merge

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 OpenCV 的 CUDA 模块中&#xff0c;cv::cuda::merge 函数用于将多个单通道的 GpuMat 图像合并成一个多通道的图像。该函数是 cv::merge 的 GP…...