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

博通BCM575系列 RDMA 网卡驱动 bnxt_re 分析(一)

简介

整个BCM系列驱动分成以太网部分(bnxt_en.ko)和RDMA部分(bnxt_re.ko), 两个模块之间通过内核的auxiliary_bus进行管理.我们主要分析下bnxt_re驱动.

代码结构

这个驱动的核心是 qplib_fp.c, 这个文件主要包含了驱动的数据路径, 包括Post Send, Post Recv, Poll CQ流程的实现. ib_verbs.c主要是实现了上层的Verbs接口, qplib_rcfw.c 实现了驱动和固件通信的部分, qplib_res.c 实现了核心资源的初始化和分配函数.
在这里插入图片描述
整个驱动四万多行代码, 每个小模块精密合作共同构成了这个性能利器.

Page Buffer List(PBL)

在Infiniband中QP接收用户发送的命令, 硬件处理QP中的命令. 处理完成后硬件将结果写入CQ, 用户Poll CQ去取命令执行结果. 这整个过程需要固件和驱动的协作, QP和CQ应该怎么实现, 才能保证硬件和驱动高效协作以实现RoCE的高带宽和低时延将数据包快速可靠的交付给用户呢 ?

在bnxt_re中, 实现这个目标的方法是Page Buffer List(PBL), 驱动使用PBL作为核心去实现QP, CQ等核心资源, PBL使用类似页表的结构去管理DMA Buffer. PBL用来管理多个物理Page, 类似scatter-gather列表, 通过PBL将多个物理不连续的页组织成一个虚拟连续的空间.Page Table Entry(PTE)用来描述一个物理页面, 一个一级的PBL如下图所示, 通过多个vmalloc出来的PTE结构来描述多个物理页面.

在这里插入图片描述

PTE长度为64位, 格式如下图所示, page表示页号, 共52位. next_to_last为1表示PTE指向的页是PBL的倒数第二个页, last为1表示PTE指向的页是PBL的最后一个页,

在这里插入图片描述

二级PBL使用两次遍历去找到最终的页, 第一次使用Page Directory Entry(PDE)找到存储PTE的页, 在使用PTE找到最终的数据页.

在这里插入图片描述

page字段表示PTE Page地址的高位, 如果PTE页的大小超过了4K(用来描述页的PDE会变少), page低位应该置为0.valid表示PDE是否指向了一个有效的PTE Page.
在这里插入图片描述

有效位

类似内核页表的有效位, PBL的valid的含义和内核页表类似, 表示PTE描述的页面是否有效. 避免在一开始就分配一大片的Page, 提高性能, 并且降低资源浪费.

队列PBL

有些PBL用来描述队列, 当PBL被缓存到硬件cache的时候, current和next指针可以被保存, 用来提高cache利用率(通过预取next指针到硬件cache). 但是如果是环形队列最后一个元素, 这种prefetch机制可能会遇到一些障碍, 为了顺利的进行prefetch操作, 在PTE中加入了next_to_last指向PBL表中倒数第二个Page, last表示PTE指向队列最后一个Page.

实现原理

以一级PBL为例讲解下PBL的实现原理, 从上图中我们可以看到要实现一级PBL我们需要一片内存去存储PTE, 实际驱动中会先计算出占用的内存的大小, 然后计算出需要多少个Page, 再计算需要多少个PBL去管理这些Page. 一个4K页最多存储512个指针(4K / 8). 因此使用PBL的数量, 通过下面的方式计算得出:

npbl = npages >> 9;
if (npages % BIT(9))npbl++;
bnxt_qplib_pbl

一个PBL结构用来描述多个Page, 其中pg_arr用来存储页面的CPU地址, pg_map_arr用来存储页面的DMA地址.

struct bnxt_qplib_pbl {//PBL管理的页面数量u32				pg_count;//每个页的大小u32				pg_size;//存储PBL管理的Page的首地址void				**pg_arr;//Page首地址的DMA表示dma_addr_t			*pg_map_arr;
};
PBL的创建和初始化

PBL结构嵌入到HWQ中使用, 根据页的数量分配DMA内存.

struct bnxt_qplib_hwq {struct bnxt_qplib_pbl		pbl[PBL_LVL_MAX];
};int __alloc_pbl(struct bnxt_qplib_res *res, struct bnxt_qplib_pbl *pbl,struct bnxt_qplib_sg_info *sginfo)
{struct pci_dev *pdev;int i;if (sginfo->nopte)return 0;pdev = res->pdev;//分配PBL表pbl->pg_arr = vmalloc(sginfo->npages * sizeof(void *));if (!pbl->pg_arr)return -ENOMEM;//存储dma地址pbl->pg_map_arr = vmalloc(sginfo->npages * sizeof(dma_addr_t));if (!pbl->pg_map_arr) {vfree(pbl->pg_arr);return -ENOMEM;}//初始化页面数为0, pg_size等于要管理的sg的页面大小pbl->pg_count = 0;pbl->pg_size = sginfo->pgsize;if (!sginfo->sghead) {//从DMA_ZONE分配空间给Pagefor (i = 0; i < sginfo->npages; i++) {pbl->pg_arr[i] = msdrv_dma_alloc_coherent(&pdev->dev,pbl->pg_size,&pbl->pg_map_arr[i],GFP_KERNEL);if (!pbl->pg_arr[i])goto fail;memset(pbl->pg_arr[i], 0, pbl->pg_size);pbl->pg_count++;}}return 0;
fail:__free_pbl(res, pbl, is_umem);return -ENOMEM;
}

PBL_LVL_0表示描述PTE Page的PBL, PBL_LVL_1表示描述数据Page的PBL, 整个过程就是把数据Page的DMA地址 | flag, 然后写入到PTE中的过程. 对于队列类型的HWQ, 还需要将PTE Page的最后两项写入魔数PTU_PTE_NEXT_TO_LAST和PTU_PTE_LAST.

/* Fill PBL with PTE pointers */
dst_virt_ptr =(dma_addr_t **)hwq->pbl[PBL_LVL_0].pg_arr;
src_phys_ptr = hwq->pbl[PBL_LVL_1].pg_map_arr;
for (i = 0; i < hwq->pbl[PBL_LVL_1].pg_count; i++)//只有将地址写入到DMA内存中, PTE才算生效dst_virt_ptr[PTR_PG(i)][PTR_IDX(i)] =src_phys_ptr[i] | flag;
if (hwq_attr->type == HWQ_TYPE_QUEUE) {/* Find the last pg of the size */i = hwq->pbl[PBL_LVL_1].pg_count;dst_virt_ptr[PTR_PG(i - 1)][PTR_IDX(i - 1)] |=PTU_PTE_LAST;if (i > 1)dst_virt_ptr[PTR_PG(i - 2)][PTR_IDX(i - 2)] |=PTU_PTE_NEXT_TO_LAST;
}

PBL实现了结合了scatter-gather list和页表的优点, 实现了一个拓展性好, 且虚拟连续的内存空间.

Hardware Queue(HWQ)

HWQ是驱动中抽象出来的生产者-消费者队列, 实体是由PBL. 队列中每个元素的大小是16字节(stride=(sizeof sq_sge)), 在代码中一个元素被称为一个slot. 一个Page最多能容纳, 4K/16=256个slot. 下图是HWQ被封装后的示意图, 通过指针cons和prod的挪动实现了一个生产者-消费者队列.

在这里插入图片描述

原理

HWQ的底层是通过PBL实现, 在访问时需要将slot id翻译成对应的PBL的页号和页内偏移, 如下所示, pg_num就是页号, pg_idx就是在页面内的slot偏移.

void *bnxt_qplib_get_qe(struct bnxt_qplib_hwq *hwq,u32 indx, u64 *pg)
{u32 pg_num, pg_idx;pg_num = (indx / hwq->qe_ppg);pg_idx = (indx % hwq->qe_ppg);if (pg)*pg = (u64)&hwq->pbl_ptr[pg_num];return (void *)(hwq->pbl_ptr[pg_num] + hwq->element_size * pg_idx);
}

通过这样的读写方式, 我们可以将PBL抽象成下面的形式, 我们可以看到多个物理不连续的页面, 被划分成了连续的slot. 这些slot的数量就是HWQ的深度.

在这里插入图片描述

以下就是HWQ的实现, 其中pbl_ptr和pbl_dma_ptr存储了物理页面的首地址, depth是队列深度, element_size是每个slot的大小, qe_ppg表示每个页面能容纳多少个slot.

struct bnxt_qplib_hwq {struct pci_dev			*pdev;spinlock_t			lock;struct bnxt_qplib_pbl		pbl[PBL_LVL_MAX];enum bnxt_qplib_pbl_lvl		level;		/* 0, 1, or 2 */void				**pbl_ptr;	/* ptr for easy accessto the PBL entries */dma_addr_t			*pbl_dma_ptr;	/* ptr for easy accessto the dma_addr */u32				max_elements;u32				depth;	/* original requested depth */u16				element_size;	/* Size of each entry */u16				qe_ppg;		/* queue entry per page */u32				prod;		/* raw */u32				cons;		/* raw */
};

参考

https://lore.kernel.org/all/1581786665-23705-4-git-send-email-devesh.sharma@broadcom.com/

相关文章:

博通BCM575系列 RDMA 网卡驱动 bnxt_re 分析(一)

简介 整个BCM系列驱动分成以太网部分(bnxt_en.ko)和RDMA部分(bnxt_re.ko), 两个模块之间通过内核的auxiliary_bus进行管理.我们主要分析下bnxt_re驱动. 代码结构 这个驱动的核心是 qplib_fp.c, 这个文件主要包含了驱动的数据路径, 包括Post Send, Post Recv, Poll CQ流程的实…...

ExcelPatternTool 开箱即用的Excel工具包现已发布!

文章目录 ExcelPatternTool功能特点&#xff1a;快速开始使用说明常规类型高级类型Importable注解Exportable注解IImportOption导入选项IExportOption导出选项单元格样式StyleMapping样式映射使用数据库作为数据源 示例Sample1&#xff1a;不同类型字段导出Sample2&#xff1a;…...

Navicat for MySQL 视图创建使用方法

创建视图步骤&#xff1a; 点击新建&#xff1b;选择视图&#xff1b;点击视图创建工具&#xff1b;可以在左侧拖拽表到工作区&#xff1b;选择表字段进行连线...

计算机视觉的相机选型

#你一般什么时候会用到GPT?# 目前市面上的工业相机大多是基于CCD&#xff08;ChargeCoupled Device&#xff09;或CMOS&#xff08;Complementary Metal Oxide Semiconductor&#xff09;芯片的相机。一般CCD制造工艺更加复杂&#xff0c;也会更贵一点&#xff01; 1、CCD工…...

实体店做商城小程序如何

互联网电商深入各个行业&#xff0c;传统线下店商家无论产品销售还是服务业&#xff0c;仅靠以往的经营模式&#xff0c;很难拓展到客户&#xff0c;老客流失严重&#xff0c;同时渠道单一&#xff0c;无法实现外地客户购物及线上客户赋能等。 入驻第三方平台有优势但也有不足…...

sql-50练习题0-5

sql练习题0-5题 前言数据库表结构介绍学生表课程表成绩表教师表 0-1 查询"01"课程比"02"课程成绩高的学生的信息及课程分数0-2查询"01"课程比"02"课程成绩小的学生的信息及课程分数0-3查询平均成绩大于等于60分的同学的学生编号和学生…...

Flutter框架实现登录注册功能,不连接数据库

要在Flutter框架中实现登录和注册功能&#xff0c;而不连接数据库&#xff0c;可以使用本地存储来存储用户信息。以下是一个简单的示例&#xff0c;演示如何使用本地存储来实现登录和注册功能。 首先&#xff0c;我们需要添加 shared_preferences 插件到 pubspec.yaml 文件中&…...

持续集成部署-k8s-部署利器-Helm

这里写目录标题 1. Helm 是什么?2. 快速安装 Helm2.1 前置条件2.2 Helm 版本与 K8s 版本对应关系2.3 离线安装 Helm3. Helm 常用命令1. Helm 是什么? Helm 是一个用于 Kubernetes 应用程序部署和管理的开源工具。它可以帮助简化 Kubernetes 应用程序的打包、发布、配置和升级…...

替换所有的问号

这篇也是凑数的 哈哈.... 稍后会整合到算法通关第三关白银挑战 . 描述 : 给你一个仅包含小写英文字母和 ? 字符的字符串 s&#xff0c;请你将所有的 ? 转换为若干小写字母&#xff0c;使最终的字符串不包含任何 连续重复 的字符。 注意 : 不能 修改非 ? 字符 . 题目 : …...

NCCL后端

"NCCL" 代表 "NVIDIA Collective Communications Library"&#xff0c;"NVIDIA 集体通信库"&#xff0c;它是一种由 NVIDIA 开发的用于高性能计算的通信库。NCCL 专门设计用于加速 GPU 群集之间的通信&#xff0c;以便在并行计算和深度学习等领域…...

【API篇】十、生成Flink水位线

文章目录 1、水位线的生成原则2、有序流内置水位线3、乱序流内置水位线4、自定义周期性水位线生成器5、自定义断点式水位线生成器6、从数据源中发送水位线 1、水位线的生成原则 水位线出现&#xff0c;即代表这个时间之前的数据已经全部到齐&#xff0c;之后不会再出现之前的数…...

【Javascript】弹出框

目录 警告框 确认框 提示框 警告框 alert(你好); 确认框 var isConfirm confirm(请确认) console.log( isConfirm); 提示框...

NSS [鹤城杯 2021]EasyP

NSS [鹤城杯 2021]EasyP 直接给了源码 <?php include utils.php;if (isset($_POST[guess])) {$guess (string) $_POST[guess];if ($guess $secret) {$message Congratulations! The flag is: . $flag;} else {$message Wrong. Try Again;} }if (preg_match(/utils\.p…...

mysql用户及权限管理(InsCode AI 创作助手)

MySQL是一个广泛使用的开源关系型数据库管理系统&#xff0c;用于存储和管理大量数据。对于那些需要使用MySQL的管理员和开发人员来说&#xff0c;用户权限管理是确保数据库安全性的至关重要的一环。在本篇技术博客中&#xff0c;我们将深入探讨MySQL的用户权限管理&#xff0c…...

命令模式——让程序舒畅执行

● 命令模式介绍 命令模式&#xff08;Command Pattern&#xff09;&#xff0c;是行为型设计模式之一。命令模式相对于其他的设计模式来说并没有那么多条条框框&#xff0c;其实并不是一个很“规矩”的模式&#xff0c;不过&#xff0c;就是基于一点&#xff0c;命令模式相对于…...

GZ035 5G组网与运维赛题第3套

2023年全国职业院校技能大赛 GZ035 5G组网与运维赛项&#xff08;高职组&#xff09; 赛题第3套 一、竞赛须知 1.竞赛内容分布 竞赛模块1--5G公共网络规划部署与开通&#xff08;35分&#xff09; 子任务1&#xff1a;5G公共网络部署与调试&#xff08;15分&#xff09; 子…...

071:mapboxGL上传含shp的zip文件,在map上解析显示图形

第071个 点击查看专栏目录 本示例是介绍演示如何在vue+mapbox中上传含有shp文件的zip,在地图上显示图形。这里先通过上传解压解析,转换生成geojson文件,然后在地图上渲染图形。 直接复制下面的 vue+mapbox源代码,操作2分钟即可运行实现效果 文章目录 示例效果所用的zip文…...

python下拉框选择测试

把下拉选择的值得打印出来&#xff1a; import tkinter as tk def on_select(event): # 当选择下拉框中的一项时&#xff0c;此函数将被调用 selected event.widget.cget("text") # 获取选中的文本 print(f"You selected: {selected}") # 打印选中…...

即时编译器JIT

类编译加载执行过程 如下图所示&#xff0c;一个Java代码从编译到运行大抵会经历以下几个过程。具体每个过程笔者会在下文站展开讨论。 类编译 首先是类编译阶段&#xff0c;这个阶段会将Java文件变为class文件&#xff0c;这个class文件包含一个常量池和方法表集合&#xf…...

npm更新包时This operation requires a one-time password.

[访问我的npm包](mhfwork/yt-ui - npm) 更新npm包时出现 This operation requires a one-time password.是因为需要认证 解决办法 1. 点击红线处的链接 2. 进入npm官网获取指定秘钥 3. 再次填入 one-time password 即可...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

ES6从入门到精通:前言

ES6简介 ES6&#xff08;ECMAScript 2015&#xff09;是JavaScript语言的重大更新&#xff0c;引入了许多新特性&#xff0c;包括语法糖、新数据类型、模块化支持等&#xff0c;显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var&#xf…...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽&#xff0c;大家好&#xff0c;我是左手python&#xff01; Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库&#xff0c;用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

JVM 内存结构 详解

内存结构 运行时数据区&#xff1a; Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器&#xff1a; ​ 线程私有&#xff0c;程序控制流的指示器&#xff0c;分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 ​ 每个线程都有一个程序计数…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...