DOCA SNAP-3 用户指南
SNAP
NVIDIA® BlueField® SNAP 和 virtio-blk SNAP(存储定义网络加速处理)技术实现了本地存储的硬件加速虚拟化。NVMe/virtio-blk SNAP 将网络存储呈现为本地块存储设备,例如 SSD,模拟 PCIe 总线上的本地驱动器。主机操作系统/虚拟机监控程序使用其标准存储驱动程序,而不知道通信不是与物理驱动器进行的,而是与 NVMe/virtio-blk SNAP 框架进行的。在通过基于光纤通道的网络将请求和/或数据重定向到远程或本地存储目标之前,任何逻辑都可以应用于 I/O 请求或通过 NVMe/virtio-blk SNAP 框架应用于数据。
NVMe/virtio-blk SNAP 基于 NVIDIA® BlueField-2 DPU 系列技术,并将独特的硬件加速存储虚拟化与 DPU 的高级网络和可编程性功能相结合。NVMe/virtio-blk SNAP 与 BlueField DPU 一起,为解决存储和网络效率及性能的各种应用创造了世界。

来自主机仿真 PCIe 设备的流量被重定向到其在 mlnx_snap
服务上打开的匹配存储控制器。控制器在其侧至少持有一个打开的后端设备(通常是 SPDK 块设备)。当收到命令时,控制器会执行它。管理命令会立即响应,而 I/O 命令会重定向到后端设备进行处理。请求处理管道是完全异步的,工作负载分布在所有 Arm 核心(分配给 SPDK 应用程序)上,以实现最佳性能。
以下是 SNAP 的关键概念
在光纤通道/传输/协议(例如 NVMe-oF/iSCSI/其他,RDMA/TCP,ETH/IB)方面的完全灵活性
NVMe 和 virtio-blk 仿真支持
轻松的数据操作
使用 Arm 核心进行数据路径
BlueField SNAP/virtio-blk SNAP 是许可软件。用户必须为每个 BlueField 设备购买许可证才能使用它们。
Libsnap
Libsnap 是一个通用库,旨在帮助希望通过 BlueField DPU 与仿真硬件交互并充分利用硬件功能的应用程序完成常见任务。因此,libsnap 为上层应用程序公开了一个简单的 API,用于创建、修改、查询和销毁不同的仿真对象,例如 PCIe BAR 管理、仿真队列等。
此外,该库还提供了一组辅助函数,用于在主机和 DPU 内存之间执行高效的 DMA 事务。
SNAP 应用程序广泛使用 libsnap 库进行资源管理以及存储控制器所需的高效 DMA 操作。
SNAP 安装过程
DPU 镜像安装
BlueField 操作系统镜像 (BFB) 包含 mlnx_snap 运行所需的所有软件包:MLNX_OFED、RDMA-CORE 库以及支持的 SPDK 版本、libsnap 和 mlnx-snap 标头、库和二进制文件。
要查看支持哪些操作系统,请参阅 BlueField 软件文档,位于“发行说明”→“支持的平台和互操作性”→“支持的 Linux 发行版”下。
主机上必须安装 RShim 才能连接到 NVIDIA® BlueField® DPU。要安装 RShim,请按照 BlueField 软件文档 → “BlueField DPU SW 手册” → “DPU 操作” → “DPU 启动和驱动程序安装” → “在 DPU 上安装 Linux” → “步骤 1:设置 RShim 接口”中描述的说明进行操作。
使用来自 x86 主机的 RShim 接口安装所需的镜像
BFB=/<path>/latest-bluefield-image.bfb
cat $BFB > /dev/rshim0/boot
可选地,可以连接到 DPU 的远程控制台并观看安装过程的进度。例如,使用 screen
工具
screen /dev/rshim0/console
安装后配置
固件配置
请参阅固件配置以确认固件配置是否符合 SNAP 应用程序的要求(SR-IOV 支持、MSI-X 资源等)。
网络配置
在启用 mlnx_snap
或对其进行配置之前,用户必须首先验证上行链路端口配置是否正确,以及与远程目标的网络连接是否正常工作。
默认情况下,打开两个 SF 接口——每个 PF 上一个,如 /etc/mellanox/mlnx-sf.conf
中配置的那样——它们分别与 RDMA 设备 mlx5_2
和 mlx5_3
匹配。如前所述,只有这些接口可能支持远程存储的 RoCE/RDMA 传输。
如果使用 InfiniBand 链路,则必须提供活动的 InfiniBand 端口以允许 InfiniBand 支持。一旦活动的 IB 端口可用,用户必须在 JSON 配置文件中配置端口 RDMA 设备(请参阅 rdma_device
,位于“配置文件示例”下),以便 mlnx_snap
在该端口上工作)。
如果使用 bonding,则它对 MLNX SNAP 配置是透明的,并且在 NVMe/virtio-blk SNAP 级别不需要特定的配置。
开箱即用配置
NVMe/virito-blk SNAP 默认情况下处于禁用状态。启用后(请参阅“固件配置”部分),NVMe/virtio-blk SNAP 的开箱即用配置包括单个 NVMe 控制器,该控制器由非卸载模式下基于 RAM 的 64MB SPDK 块设备(例如 RAM 驱动器)支持。开箱即用配置不包括 virtio-blk 设备。
开箱即用 NVMe 控制器的示例配置文件位于 /etc/mlnx_snap/mlnx_snap.json
中。有关其值的更多信息,请参阅“非卸载模式”部分。
默认初始化命令集在 /etc/mlnx_snap/spdk_rpc_init.conf
和 /etc/mlnx_snap/snap_rpc_init.conf
中描述,如下所示
spdk_rpc_init.conf
bdev_malloc_create 64 512
snap_rpc_init.conf
subsystem_nvme_create Mellanox_NVMe_SNAP "Mellanox NVMe SNAP Controller" controller_nvme_create mlx5_0 --subsys_id 0 --pf_id 0 controller_nvme_namespace_attach -c NvmeEmu0pf0 spdk Malloc0 1
BlueField 开箱即用配置与 BlueField-2 略有不同。为了获得干净的开箱即用体验,/etc/mlnx_snap/snap_rpc_init.conf
是指向相关硬件导向配置的符号链接。
要使任何其他命令集持久化,用户可以根据自己的需要更新和修改 /etc/mlnx_snap/spdk_rpc_init.conf
和 /etc/mlnx_snap/snap_rpc_init.conf
。有关更多信息,请参阅“SNAP 命令”部分。
SNAP 服务控制 (systemd)
要启用、启动、停止或检查 SNAP 服务的状态,请运行
systemctl {start | stop | status} mlnx_snap
日志记录
mlnx_snap 应用程序输出由 SystemD 捕获并存储在内部数据库中。用户可以使用以下 SystemD 命令从服务控制台获取输出
systemctl status mlnx_snap
journalctl -u mlnx_snap
SystemD 将日志以二进制格式保存在 /var/run/log/journal/
目录下,该目录存储在 tmpfs 上(即,它不是持久性的)。
SystemD 将日志消息重定向到 rsyslog
服务。rsyslog
的配置默认为 CentOS/RHEL,因此用户可以在 /var/log/messages
目录中找到所有这些消息。
如果需要,可以将 rsyslog
守护程序配置为将消息发送到远程(集中式)syslog 服务器。
RPC 命令接口
远程过程调用 (RPC) 协议是一个非常简单的协议,定义了少量数据类型和命令。NVMe/virtio-blk SNAP 与其他标准 SPDK 应用程序一样,支持基于 JSON 的 RPC 协议命令,以便从 CLI 轻松控制任何资源创建/删除/查询/修改命令。
mlnx_snap 应用程序支持执行所有标准 SPDK RPC 命令,以及扩展的 SNAP 特定命令集。SPDK 标准命令由标准 spdk_rpc.py
工具执行,而 SNAP 特定命令集扩展由等效的 snap_rpc.py
工具执行。
完整的 spdk_rpc.py
命令集文档可以在 SPDK 官方文档站点中找到。
完整的 snap_rpc.py
扩展命令将在本章稍后详细介绍。
PCIe 功能管理命令
仿真管理器发现
仿真的 PCIe 功能通过称为“仿真管理器”的 IB 设备进行管理。仿真管理器是普通的 IB 设备(例如 mlx5_0、mlx5_1 等),具有特殊权限,还可以控制 PCIe 通信以及面向主机操作系统的设备仿真。可以共存多个仿真管理器,每个管理器都有自己的一组功能。
可以使用以下命令查询仿真管理器及其功能的列表
snap_rpc.py emulation_managers_list
附录 SPDK 配置 包含更多信息。
仿真设备配置(热插拔)
如上所述,每个仿真管理器都保存着它控制的仿真 PCI 功能列表。PCI 功能稍后可以通过其功能索引(在仿真管理器的列表中)或主机操作系统枚举的 PCIe BDF 编号(例如 88:00.2)来访问。在固件配置阶段配置的一些 PCIe 功能被认为是“静态的”(即,始终存在的)。
此外,用户可以在运行时动态地向该列表(以及主机 PCIe 设备列表)添加可分离的功能。这些功能称为“热插拔” PCIe 功能。
插入新的 PCIe 功能后,它将显示在主机 PCIe 设备列表中,直到被显式拔出或系统经历冷重启。即使在 SNAP 进程终止后,热插拔的 PCIe 功能仍将保持持久性。
某些操作系统在插入新功能后会自动开始与其通信。即使在发出信号要拔出功能后,某些操作系统也会继续与该功能通信(一段时间)。因此,用户必须始终在任何现有配置的 PCIe 功能上保持打开的控制器(匹配类型)(有关更多详细信息,请参阅 NVMe 控制器管理 和 Virtio-blk 控制器管理)。
以下命令将新的 PCIe 功能热插拔到系统中
snap_rpc.py emulation_device_attach emu_manager {nvme,virtio_blk} [--id ID] [--vid VID] [--ssid SSID] [--ssvid SSVID] [--revid REVID] [--class_code CLASS_CODE] [--bdev_type {spdk,none}] [--bdev BDEV] [--num_queues NUM_QUEUES] [--queue_depth QUEUE_DEPTH][--total_vf TOTAL_VF] [--num_msix NUM_MSIX]
以下命令从系统中热拔出新的 PCIe 功能
snap_rpc.py emulation_device_detach <emu_manager> {nvme,virtio_blk} [-d PCI_BDF / -i PCI_INDEX / --vuid VUID]
必需参数
emu_manager
– 仿真管理器{nvme,virtio_blk}
– 设备类型
可选参数
--pci_bdf
– PCIe BDF 标识符--pci_index
– PCIe 索引标识符--vuid
– PCIe VUID 标识符--force
– 强制移除设备(不推荐)注意必须至少提供一个标识符来描述要分离的 PCIe 功能。
一旦 PCIe 功能从主机系统拔出(当调用 emulation_device_detach
时),其控制器也将被隐式删除。
以下命令列出所有现有功能(静态或热插拔)
snap_rpc.py emulation_functions_list
NVMe 仿真管理命令
NVMe 子系统
如 NVMe 规范中所述,NVMe 子系统是一个逻辑实体,它封装了多组 NVMe 后端(或命名空间)和连接(或控制器)。当使用多个 NVMe 控制器时,尤其是在使用 NVMe 虚拟功能时,NVMe 子系统非常有用。
每个 NVMe 子系统都由其序列号 (SN)、型号 (MN) 和限定名 (NQN) 定义。创建后,每个子系统还会获得唯一的索引号。
以下示例创建一个新的 NVMe 子系统,其中包含默认生成的 NQN
snap_rpc.py subsystem_nvme_create <serial_number> <model_number>
必需参数
serial_number
– 子系统序列号model_number
– 子系统型号
可选参数
--nqn
– 子系统限定名(如果未提供,则自动生成)--nn
– 子系统中允许的最大命名空间 ID(默认 0xFFFFFFFE;范围 1-0xFFFFFFFE)--mnan
– 子系统中允许的最大命名空间数(默认 1024;范围 1-0xFFFFFFFE)
以下命令删除 NVMe 子系统
snap_rpc.py subsystem_nvme_delete <NQN>
其中 <NQN>
是子系统的 NQN。
以下命令列出所有 NVMe 子系统
snap_rpc.py subsystem_nvme_list
NVMe 控制器
每个暴露给主机的 NVMe 设备(例如 NVMe PCIe 条目),无论是 PF 还是 VF,都必须由 NVMe 控制器支持,该控制器负责与主机驱动程序的所有协议通信。每个新的 NVMe 控制器也必须链接到 NVMe 子系统。创建后,可以使用其名称(例如“NvmeEmu0pf0”)或其子系统 NQN 和控制器 ID 来寻址 NVMe 控制器。
以下命令打开一个新的 NVMe 控制器
snap_rpc.py controller_nvme_create mlx5_0 [--pf_id ID / --pci_bdf / --vuid VUID] [--subsys_id ID / --nqn NQN]
必需参数
emu_manager
– 仿真管理器
可选参数
--vf_id VF_ID
– 要在其上启动仿真的 PCIe VF 索引(如果控制器注定要在 VF 上打开)。--pf_id
也必须设置,命令才能生效。--conf
– JSON 配置文件路径,用于提供扩展的配置参数集。有关配置文件的不同参数的完整信息,请参阅附录“JSON 文件格式”。--nr_io_queues
– I/O 队列最大数量(默认 32,范围 0-32)--mdts
– 最大数据传输大小(默认 4,范围 1-6)--max_namespaces
– 此控制器的最大命名空间数(默认 1024,范围 1-0xFFFFFFFE)--quirks
– 位掩码,用于启用特定的 NVMe 驱动程序怪癖,以与不符合 NVMe 规范的驱动程序一起工作。有关更多信息,请参阅附录“JSON 文件格式”。--mem {static,pool}
– 使用来自全局池或专用缓冲区的内存。有关更多信息,请参阅“内存池”。
以下命令删除现有的 NVMe 控制器
snap_rpc.py controller_nvme_delete [--name NAME / --subnqn SUBNQN --cntlid ID / --vuid VUID]
可选参数
-c NAME
,--name NAME
– 控制器名称。如果未设置--nqn
和--cntlid
,则必须设置。-n SUBNQN
,--subnqn SUBNQN
– NVMe 子系统 (NQN)。如果未设置--name
,则必须设置。-i CNTLID
,--cntlid CNTLID
– NVMe 子系统中的控制器标识符。如果未设置--name
,则必须设置。
以下命令列出所有 NVMe 控制器
snap_rpc.py controller_list --type nvme
可选参数
-t {nvme,virtio_blk,virtio_net}
,--type {nvme,virtio_blk,virtio_net}
– 控制器类型
NVMe 后端(命名空间)
NVMe 命名空间是本地/远程存储设备中连续 LBA 范围的表示(先前在“后端配置”部分中配置)。每个命名空间都必须链接到控制器,并且在整个 NVMe 子系统中具有唯一的标识符 (NSID)(例如,即使链接到不同的控制器,2 个命名空间也不能共享相同的 NSID)。
SNAP 应用程序使用 SPDK 块设备框架作为其 NVMe 命名空间的后端。因此,应提前配置它们。有关 SPDK 块设备的更多信息,请参阅 SPDK BDEV 文档 和附录“SPDK 配置”。
以下命令将新的命名空间附加到现有的 NVMe 控制器
snap_rpc.py controller_nvme_namespace_attach [--ctrl CTRL / --subnqn SUBNQN --cntlid ID] <bdev_type> <bdev> <nsid>
必需参数
bdev_type
– 块设备类型bdev
– 用作后端的块设备nsid
– 命名空间 ID
可选参数
-c CTRL
,--ctrl CTRL
– 控制器名称。如果未设置--nqn
和--cntlid
,则必须设置。-n SUBNQN
,--subnqn SUBNQN
– NVMe 子系统 (NQN)。如果未设置--ctrl
,则必须设置。-i CNTLID
,--cntlid CNTLID
– NVMe 子系统中的控制器标识符。如果未设置--ctrl
,则必须设置。-q QN
,--qn QN
– 提供此命名空间的远程目标的 QN-p PROTOCOL
,--protocol PROTOCOL
– 使用的协议-g NGUID
,--nguid NGUID
– 命名空间全局唯一标识符-e EUI64
,--eui64 EUI64
– 命名空间 EUI-64 标识符-u UUID
,--uuid UUID
– 命名空间 UUID
在完全卸载模式下,后端会自动从远程存储获取,无需手动配置。
以下命令从控制器分离命名空间
snap_rpc.py controller_nvme_namespace_detach [--ctrl CTRL / --subnqn SUBNQN --cntlid ID] <nsid>
必需参数
nsid
– 命名空间 ID
可选参数
-c CTRL
,--ctrl CTRL
– 控制器名称。如果未设置--nqn
和--cntlid
,则必须设置。-n SUBNQN
,--subnqn SUBNQN
– NVMe 子系统 (NQN)。如果未设置--ctrl
,则必须设置。-i CNTLID
,--cntlid CNTLID
– NVMe 子系统中的控制器标识符。如果未设置--ctrl
,则必须设置。
以下命令列出控制器的命名空间
snap_rpc.py controller_nvme_namespace_list [--ctrl CTRL / --subnqn SUBNQN --cntlid ID]
可选参数
-c CTRL
,--ctrl CTRL
– 控制器名称。如果未设置--nqn
和--cntlid
,则必须设置。-n SUBNQN
,--subnqn SUBNQN
– NVMe 子系统 (NQN)。如果未设置--ctrl
,则必须设置。-i CNTLID
,--cntlid CNTLID
– NVMe 子系统中的控制器标识符。如果未设置--ctrl
,则必须设置。
Virtio-blk 仿真管理命令
Virtio-blk 控制器
每个暴露给主机的 virtio-blk 设备(例如 virtio-blk PCI 条目),无论是 PF 还是 VF,都必须由 virtio-blk 控制器支持。与 NVMe 相比,Virtio-blk 被认为是有限的存储协议。
由于协议限制
尝试在没有已正常运行的 virtio-blk 控制器的情况下使用 virtio-blk 设备(例如,在主机上探测 virtio-blk 驱动程序)可能会导致主机服务器挂起,直到成功打开此类控制器(不存在超时机制)
在创建 virtio-blk 控制器时,后端设备必须已经存在
以下命令创建一个新的 virtio-blk 控制器
snap_rpc.py controller_virtio_blk_create <emu_manager> [-d PCI_BDF / --pf_id PF_ID / --vuid VUID]
必需参数
emu_manager
– 仿真管理器
可选参数
--vf_id
– 要在其上启动仿真的 PCIe VF 索引,如果控制器注定要在 VF 上打开--num_queues
– 队列数量(默认 64,范围 2-256)--queue_depth
– 队列深度(默认 128,范围 1-256)--size_max
–- 最大 SGE 数据传输大小(默认 4096,范围 1 – MAX_UINT16)。有关更多信息,请参阅 virtio 规范。--seg_max
– 最大 SGE 列表长度(默认 1,范围 1-queue_depth)。有关更多信息,请参阅 virtio 规范。--bdev_type
– 块设备类型 (spdk/none)。请注意,使用none
后端打开控制器意味着使用大小为 0 的后端打开它。--bdev
– 用作后端的 SPDK 块设备--serial
– 控制器的序列号--force_in_order
- 强制 I/O 按顺序完成。请注意,需要此值以确保未来的 virtio-blk 控制器在应用程序崩溃后始终成功恢复。--suspend
– 创建处于 SUSPENDED 状态的控制器(必须稍后显式恢复)--mem {static,pool}
– 使用来自全局池或专用缓冲区的内存。有关更多信息,请参阅“高级功能”。
以下命令删除 virtio-blk 控制器
snap_rpc.py controller_virtio_blk_delete [-c NAME / --vuid VUID]
必需参数
name
– 控制器名称
可选参数
--f
,--force
– 强制删除控制器
以下命令列出所有 virtio-blk 控制器
snap_rpc.py controller_list --type virtio_blk
可选参数
-t {nvme,virtio_blk,virtio_net}
,--type {nvme,virtio_blk,virtio_net}
– 控制器类型
Virtio-blk 控制器也可以暂停和恢复。暂停后,控制器会停止接收来自主机驱动程序的新请求,并且仅完成处理已在进行中的请求(而不会向驱动程序提示任何 IO 错误)。
以下命令暂停/恢复 virtio-blk 控制器
snap_rpc.py controller_virtio_blk_suspend <name>
snap_rpc.py controller_virtio_blk_resume <name>
必需参数
name
– 控制器名称
Virtio-blk 后端管理
与 NVMe 类似,virtio-blk 也使用 SPDK 块设备框架作为其后端设备,但由于 virtio-blk 是一种有限的存储协议,与 NVMe 相比,后者的后端管理能力也受到限制
Virtio-blk 协议仅支持一个后端设备
Virtio-blk 协议不支持添加后端的管理命令,因此所有后端属性都通过 PCIe BAR 传达给主机 virtio-blk 驱动程序,并且必须在驱动程序探测期间可访问。因此,只有当 PCIe 功能未被任何主机存储驱动程序使用时,才能更改后端。
由于这些原因,当主机驱动程序处于活动状态时,所有后端管理操作都必须仅在控制器处于暂停状态时发生。
以下命令将新的后端附加到控制器
snap_rpc.py controller_virtio_blk_bdev_attach <ctrl_name> {spdk} <bdev_name>
必需参数
name
– 控制器名称{spdk}
– 块设备类型bdev
– 用作后端的块设备
可选参数
--size_max
– 最大 SGE 数据传输大小(无硬性限制)。有关更多信息,请参阅 Virtio 规范。--seg_max
– 最大 SGE 列表长度(无硬性限制)。有关更多信息,请参阅 Virtio 规范。
以下命令从控制器分离后端
snap_rpc.py controller_virtio_blk_bdev_detach <ctrl_name>
必需参数
ctrl_name
– 控制器名称
使用 SPDK 块设备 API 销毁 SPDK 块设备被视为 controller_virtio_blk_bdev_detach
,并且受相同的限制。
以下命令列出控制器的后端详细信息
snap_rpc.py controller_virtio_blk_bdev_list <name>
必需参数
name
– 控制器名称
调试和统计
BlueField 和 virito-blk SNAP 提供了一组命令,可帮助客户检索有关已打开的仿真设备的性能和调试统计信息。统计信息在 SNAP 控制器级别提供(无论是 NVMe 还是 Virtio-blk)。
IO 统计
以下命令可用于衡量控制器执行了多少成功/失败的 IO 操作。
这些命令对 BlueField SNAP 性能的影响极小,因此可以在控制器执行高带宽 IO 操作时用于采样统计信息。
snap_rpc.py controller_nvme_get_iostat [-c CTRL_NAME]
snap_rpc.py controller_virtio_blk_get_iostat [-c CTRL_NAME]
这些命令对 BlueField SNAP 性能的影响极小,因此可以在控制器执行高带宽 IO 操作时用于采样统计信息。
必需参数
CTRL_NAME
– 控制器名称
NVMe/Virtio IO 统计
read_ios
– 处理的读取命令数completed_read_ios
– 成功完成的读取命令数err_read_ios
– 完成时出错的读取命令数write_ios
– 处理的写入命令数completed_write_ios
– 成功完成的写入命令数err_write_ios
– 完成时出错的写入命令数flush_ios
– 处理的刷新命令数completed_flush_ios
– 成功完成的刷新命令数err_flush_ios
– 完成时出错的刷新命令数
Virtio IO 特定统计
fatal_ios
– 丢弃且从未完成的命令数outstanding_in_ios
– 给定时刻的未完成 IO 数outstanding_in_bdev_ios
– 给定时刻的未完成 IO 数,等待后端处理outstanding_to_host_ios
– 给定时刻的未完成 IO 数,等待 DMA 处理
调试统计
以下命令可用于检查具有更详细状态和信息的控制器和队列。
频繁查询时,这些命令可能会影响性能,因此应仅出于调试目的调用它们。
snap_rpc.py controller_nvme_get_debugstat [-c NAME]
snap_rpc.py controller_virtio_blk_get_debugstat [-c NAME]
初始化脚本
默认初始化脚本 /etc/mlnx_snap/spdk_rpc_init.conf
和 /etc/mlnx_snap/snap_rpc_init.conf
允许用户控制启动配置。
用户可以修改这些用于 开箱即用配置 的脚本来控制 SNAP 初始化
性能优化
为了获得最佳性能而调整 MLNX SNAP 可能需要来自系统的其他资源(CPU、内存),并且可能会影响 SNAP 控制器的可扩展性。
增加使用的 Arm 核心数量
默认情况下,MLNX SNAP 使用 4 个 Arm 核心,核心掩码为 0xF0。为了获得最佳性能,可以在 /etc/default/mlnx_snap
(参数 CPU_MASK
)中配置核心掩码(即,CPU_MASK=0xFF
)。
由于 SNAP 是一个基于 SPDK 的应用程序,它会持续轮询 CPU,因此会占用其运行 CPU 的 100%。
禁用内存池
启用内存池 (mem-pool) 后,可以减少内存占用,但会降低整体性能。
要配置控制器不使用内存池,请在 /etc/default/mlnx_snap
中设置 MEM_POOL_SIZE=0
。
有关更多信息,请参阅 “内存池” 部分。
最大化单次 IO 传输数据有效负载
增加数据路径暂存缓冲区大小可以提高较大块大小(>4K)的性能。
对于 NVMe,可以通过增加 JSON 文件或 RPC 参数中的 MDTS 值来控制这一点。有关 MDTS 的更多信息,请参阅 NVMe 规范。默认值为 4(64K 缓冲区),最大值为 6(256K 缓冲区)。
对于 virtio-blk,可以使用
seg_max
和size_max
RPC 参数来控制这一点。有关这些参数的更多信息,请参阅 VirtIO-blk 规范。没有硬性最大限制。
增加仿真管理器 MTU
仿真管理器网络接口的默认 MTU 为 1500。在仿真管理器上将 MTU 增加到 4K 以上(例如,MTU=4200)还可以使 SNAP 应用程序在单个主机 → DPU 内存事务中传输更大量的数据,这可能会提高性能。
优化队列和 MSIX 向量的数量(仅限 virtio-blk)
SNAP 模拟队列均匀分布在所有配置的 PF(静态和动态)和每个 PF 定义的 VF 中(无论是否正在使用功能)。这意味着 SNAP 配置的功能总数(PF 或 VF)越多,分配给每个功能的队列和 MSIX 资源就越少,这将相应地影响其性能。因此,建议在固件配置中配置该特定系统所需的最小 PF 和每个 PF 的 VF 数量。
另一个考虑因素是 MSIX 向量大小与所需队列数量之间的匹配。标准的 virtio-blk 内核驱动程序使用 MSIX 向量来获取控制路径和数据路径上的事件。如果可能,它会为每个 virtqueue(例如,每个 CPU 核心)分配独占 MSIX,并为配置更改保留额外的 MSIX。如果不可能,它将对所有 virtqueue 使用单个 MSIX。因此,为了确保 virtio-blk 设备获得最佳性能,必须应用条件 VIRTIO_BLK_EMULATION_NUM_MSIX
> virtio_blk_controller.num_queues
。
BlueField-2 卡上的 MSIX 总数有限,因此在使用多个设备运行时,可能需要考虑 MSIX 预留。有关更多信息,请参阅此 FAQ。
NVMe-RDMA 完全卸载模式
NVMe-RDMA 完全卸载模式允许通过将数据路径直接卸载到固件/硬件来降低 Arm 核心的 CPU 成本。如果用户需要控制数据平面或后端,则此模式不允许这样做。
在完全卸载模式下,控制平面在 SW 级别处理,而数据平面在 FW 级别处理,无需 SW 交互。因此,用户无法控制后端设备。因此,它们会被自动检测到,并且不需要命名空间管理命令。
NVMe-RDMA 架构

在此模式下,必须使用 JSON 配置文件提供远程目标参数(JSON 文件示例可以在 /etc/mlnx_snap/mlnx_snap_offload.json.example
中找到),NVMe 控制器可以自行检测并连接到相关的后端。
由于 SNAP 应用程序不参与数据路径,并且需要的资源较少,因此建议将 CPU_MASK 减少到单个核心(即,CPU_MASK=0x80
)。有关 CPU_MASK
配置,请参阅“增加使用的 Arm 核心数量”。
完成配置后,用户必须创建 NVMe 子系统和(卸载的)控制器。请注意,不需要 snap_rpc.py controller_nvme_namespace_attach
,并且提供 --rdma_device mlx5_2
以标记用于连接的相关 RDMA 接口。
以下示例创建了一个 NVMe 完全卸载控制器
# snap_rpc.py subsystem_nvme_create "Mellanox_NVMe_SNAP" "Mellanox NVMe SNAP Controller"
# snap_rpc.py controller_nvme_create mlx5_0 --subsys_id 0 --pci_bdf 88:00.2 --nr_io_queues 32 --mdts 4 -c /etc/mlnx_snap/mlnx_snap.json --rdma_device mlx5_2
这是匹配的 JSON 文件示例
{
"ctrl": {
"offload": true,
},
"backends": [
{
"type": "nvmf_rdma",
"name": "testsubsystem",
"paths": [
{
"addr": "1.1.1.1",
"port": 4420,
"ka_timeout_ms": 15000,
"hostnqn": "r-nvmx03"
}
]
}
]
}
完全卸载模式要求提供的 RDMA 设备(在 --rdma_device
参数中给出)支持 RoCE 传输(通常为 SF 接口)。不支持 virtio-blk 的完全卸载模式。
发现的命名空间 ID 可能会被重新映射以获得另一个 ID,以便在暴露给主机时符合固件限制。
SR-IOV
SR-IOV 配置取决于内核版本
如果新内核中
/sys/bus/pci/devices/<BDF>/
中存在sriov_drivers_autoprobe sysfs
条目,则可以实现最佳配置否则,如果
/sys/bus/pci/devices/<BDF>/
中存在sriov_totalvfs sysfs
条目,则可以满足最低要求
SR-IOV 配置需要在主机和 DPU 端都完成,在以下示例中分别标记为 [HOST] 和 [ARM]。此示例假设静态 virtio-blk PF 86:00.3 上有 1 个 VF(NVMe 流程类似),并且存在 Malloc0
SPDK BDEV。
最优配置
[ARM] snap_rpc.py controller_virtio_blk_create mlx5_0 -d 86:00.3 --bdev_type none
[HOST] modprobe -v virtio-pci && modprobe -v virtio-blk
[HOST] echo 0 > /sys/bus/pci/devices/0000:86:00.3/sriov_drivers_autoprobe
[HOST] echo 1 > /sys/bus/pci/devices/0000:86:00.3/sriov_numvfs [ARM] snap_rpc.py controller_virtio_blk_create mlx5_0 --pf_id 0 --vf_id 0 --bdev_type spdk --bdev Malloc0
\* Continue by binding the VF PCIe function to the desired VM. *\
配置完成后,预计在虚拟机监控程序中不会暴露任何磁盘。只有在使用虚拟化管理器将 PCIe VF 分配给 VM 后,磁盘才会出现在 VM 中。如果用户想从虚拟机监控程序中使用该设备,他们只需手动绑定 PCIe VF 即可。
最低要求
[ARM] snap_rpc.py controller_virtio_blk_create mlx5_0 -d 86:00.3 --bdev_type none
[HOST] modprobe -v virtio-pci && modprobe -v virtio-blk
[HOST] echo 1 > /sys/bus/pci/devices/0000:86:00.3/sriov_numvfs
\* the host now hangs until configuration is performed on the DPU side *\ [ARM] snap_rpc.py controller_virtio_blk_create mlx5_0 --pf_id 0 --vf_id 0 --bdev_type spdk --bdev Malloc0
\* Host is now released *\
\* Continue by binding the VF PCIe function to the desired VM. *\
热插拔 PF 不支持 SR-IOV。
建议在创建超过 127 个 VF 时,将 pci=assign-busses
添加到启动命令行。
如果没有此选项,主机可能会出现以下错误,并且 virtio 驱动程序将不会探测这些设备。
pci 0000:84:00.0: [1af4:1041] type 7f class 0xffffff
pci 0000:84:00.0: unknown header type 7f, ignoring device
零拷贝 (SNAP-direct)
SPDK 21.07 及更高版本支持零拷贝。
SNAP-direct 功能允许 SNAP 应用程序直接将数据从主机内存传输到远程存储,而无需在 DPU 内部使用任何暂存缓冲区。
仅当针对 SPDK NVMe-oF RDMA 块设备工作时,SNAP 才会根据 SPDK BDEV 配置启用此功能。
要配置控制器使用零拷贝,请在 /etc/default/mlnx_snap
中设置以下内容
对于 virtio-blk
VIRTIO_BLK_SNAP_ZCOPY=1
对于 NVMe
NVME_SNAP_ZCOPY=1
NVMe/TCP 零拷贝
NVMe/TCP 零拷贝在 SPDK NVMe initiator 中实现为自定义 NVDA_TCP 传输,它基于新的 XLIO 套接字层实现。
Tx 和 Rx 的实现方式不同
NVMe/TCP Tx 零拷贝在 RDMA 和 TCP 之间是相似的,因为数据直接从主机内存发送到网络,而无需中间复制到 Arm 内存
NVMe/TCP Rx 零拷贝允许通过消除从套接字缓冲区 (XLIO) 到应用程序缓冲区 (SNAP) 的复制来实现 Rx 流的部分零拷贝。但数据仍然必须从 Arm DMA 到主机内存。
要启用 NVMe/TCP 零拷贝,请使用 SPDK v22.05.nvda --with-xlio
。
有关 XLIO 的更多信息,包括限制和错误修复,请参阅 NVIDIA 加速 IO (XLIO) 文档。
要配置控制器使用 NVMe/TCP 零拷贝,请在 /etc/default/mlnx_snap
中设置以下内容
EXTRA_ARGS="-u –mem-size 1200 –wait-for-rpc"
NVME_SNAP_TCP_RX_ZCOPY=1
SPDK_XLIO_PATH=/usr/lib/libxlio.so
MIN_HUGEMEM=4G
要使用 NVDA_TCP 传输进行连接
如果未使用
/etc/mlnx_snap/spdk_rpc_init.conf
,请在给定顺序的文件开头添加以下内容sock_set_default_impl -i xlio framework_start_init
当
mlnx_snap
服务启动时,运行以下命令[ARM] spdk_rpc.py bdev_nvme_attach_controller -b <NAME> -t NVDA_TCP -f ipv4 -a <IP> -s <PORT> -n <SUBNQN>
如果未使用
/etc/mlnx_snap/spdk_rpc_init.conf
,一旦服务启动,请按给定顺序运行以下命令[ARM] spdk_rpc.py sock_set_default_impl -i xlio [ARM] spdk_rpc.py framework_start_init [ARM] spdk_rpc.py bdev_nvme_attach_controller -b <NAME> -t NVDA_TCP -f ipv4 -a <IP> -s <PORT> -n <SUBNQN>
NVDA_TCP 传输与基于 NVMe/TCP 规范的其他实现完全互操作。
NVDA_TCP 限制
不支持 SPDK 多路径
不支持 NVMe/TCP 数据摘要
不支持 SR-IOV
鲁棒性和恢复
由于 SNAP 是在 DPU 操作系统上运行的标准用户应用程序,因此它容易受到系统干扰,例如正常关闭 SNAP 应用程序(即,停止 mlnx_snap 服务)、粗暴地终止 SNAP 进程(即,运行 kill -9
),甚至对 DPU 执行完整的操作系统重启。如果当这些干扰中的任何一个发生时,主机驱动程序已在使用暴露的设备,则可能会导致主机驱动程序/应用程序故障。
为了避免这种情况,SNAP 应用程序支持“鲁棒性和恢复”选项。因此,如果 SNAP 应用程序因任何原因中断,则 SNAP 应用程序的下一个实例将能够从上一个实例停止的地方继续。
此功能可以在以下条件下启用
仅使用 virtio-blk 设备(此功能目前不支持 NVMe 协议)
默认情况下,SNAP 应用程序被编程为可以应对任何类型的“正常”终止,包括控制器删除、服务重启,甚至(正常)Arm 重启。如果需要扩展的保护以防止粗暴终止,例如向 SNAP 进程发送 SIGKILL 或执行粗暴的 Arm 关闭,则必须将
--force_in_order
标志添加到snap_rpc.py controller_virtio_blk_create
命令。注意如果使用远程目标,
force_in_order
标志可能会影响性能,因为它可能导致高频率的乱序完成,或者不同的队列以不同的速率提供服务。用户有责任使用与中断的 virtio-blk 控制器完全相同的特性(相同的远程存储设备、相同的 BAR 参数等)打开恢复的 virtio-blk 控制器。
内存池
默认情况下,SNAP 应用程序预先分配所有必需的内存缓冲区。
当使用以下情况时,可能需要大量分配的内存
大量控制器(如 SR-IOV)
每个控制器的大量队列
高队列深度
大型 mdfs(对于 NVMe)或
seg_max
和size_max
(对于 virtio-blk)
为了减少应用程序的内存占用,用户可以选择使用内存池(共享内存缓冲区池)来代替。但是,使用内存池可能会降低整体性能。
要配置控制器使用内存池而不是私有内存池
在
/etc/default/mlnx_snap
中,将参数MEM_POOL_SIZE
设置为非零值。此参数接受 K/M/G 表示法(例如,MEM_POOL_SIZE=100M
)。如果未指定 K/M/G 表示法,则该值默认为字节。用户必须根据自己的需求选择合适的值——值太小可能会导致更长的饥饿时间,而值太大则会消耗更多内存。作为经验法则,典型用法可以选择将其设置为最小值(num_devices*4MB,512MB)。
在创建控制器时,添加选项
--mempool
。例如snap_rpc.py controller_nvme_create mlx5_0 —subsys_id 0 —pf_id 0 --mem pool
注意每个控制器的内存池配置与其他所有控制器都是独立的。用户可以将某些控制器设置为使用内存池,而将其他控制器设置为不使用。
Virtio-blk 过渡设备 (0.95)
SNAP 支持 virtio-blk 过渡设备。Virtio 过渡设备是指支持符合现代规范的驱动程序和旧版驱动程序(符合旧版 0.95 规范)的设备。
要将 virtio-blk PCIe 功能配置为过渡设备,必须应用特殊的固件配置参数
VIRTIO_BLK_EMULATION_PF_PCI_LAYOUT
(0:现代 / 1:过渡)– 配置 PF 的过渡设备支持注意目前不支持此参数。
VIRTIO_BLK_EMULATION_VF_PCI_LAYOUT
(0:现代 / 1:过渡)– 配置底层 VF 的过渡设备支持注意目前不支持此参数。
VIRTIO_EMULATION_HOTPLUG_TRANS
(True/False)– 配置热插拔 virtio-blk 设备的过渡设备支持
要使用 virtio-blk 过渡设备,必须在主机上设置 Linux 启动参数
如果内核版本低于 5.1,请在主机操作系统上设置以下 Linux 启动参数
intel_iommu=off
如果
virtio_pci
是从主机操作系统内置的,请设置以下 Linux 启动参数virtio_pci.force_legacy=
1
如果
virtio_pci
是内核模块而不是从主机操作系统内置的,请使用 force legacy 加载模块modprobe -rv virtio_pci modprobe -v virtio_pci force_legacy=
1
对于热插拔功能,必须在 SNAP 热插拔操作期间应用其他配置
# snap_rpc.py emulation_device_attach mlx5_0 virtio_blk -- transitional_device --bdev_type spdk --bdev BDEV
Virtio-blk 实时迁移
实时迁移是 QEMU 支持的标准流程,允许系统管理员在实时运行的系统中在虚拟机之间传递设备。有关更多信息,请参阅 QEMUVFIO 设备迁移文档。
SNAP virtio-blk 设备支持实时迁移。可以使用具有适当支持的驱动程序(例如,NVIDIA 的专有基于 VDPA 的实时迁移解决方案)激活它。有关更多信息,请参阅 TBD。
如果物理功能 (PF) 已被删除,例如,使用 vDPA 调配 virtio-blk PF 并使用以下命令
python ./app/vfe-vdpa/vhostmgmt mgmtpf -a 0000:af:00.3
建议在使用以下命令尝试重新添加控制器之前,确认并恢复 SNAP 中控制器的存在
python dpdk-vhost-vfe/app/vfe-vdpa/vhostmgmt vf -v /tmp/sock-blk-0 -a 0000:59:04.5
以下过程旨在用于 SNAP 应用程序中进行的小型软件错误修复或修改的实时部署。将此过程用于其他目的(例如,在较旧的 BFB 映像之上升级 SNAP 服务到新版本)可能会导致 SNAP 出现故障。
要实时升级 SNAP,必须并行打开 2 个 SNAP 进程。
所有系统资源(例如,巨页、内存)必须足以在升级过程中临时支持 2 个并行运行的 SNAP 应用程序实例。
在 SNAP 进程之间传递 virtio-blk 控制器的管理
在 Arm 上同时打开 2 个 SNAP 进程。
注意这需要更改 SPDK RPC 服务器路径。
信息为了减少停机时间,强烈建议在不同的 CPU 掩码上运行每个进程。
对于 SNAP 进程 1,运行
./mlnx_snap_emu -m 0xf0 -r /var/tmp/spdk.sock1
对于 SNAP 进程 2,运行
./mlnx_snap_emu -m 0x0f -r /var/tmp/spdk.sock2
使用两个进程连接到同一个 bdev(即,使用 Malloc 设备)。
对于 SNAP 进程 1,运行
spdk_rpc.py -s /var/tmp/spdk.sock1 bdev_malloc_create -b Malloc1 1024 512
对于 SNAP 进程 2,运行
spdk_rpc.py -s /var/tmp/spdk.sock2 bdev_malloc_create -b Malloc1 1024 512
在 SNAP 进程 1 上打开 virtio-blk 控制器
snap_rpc.py -s /var/tmp/spdk.sock1 controller_virtio_blk_create mlx5_0 --pf_id 0 --bdev_type spdk --bdev Malloc1 --num_queues 16
在主机端加载 virtio-blk 驱动程序并开始使用它。
从 SNAP 进程 1 中删除 virtio-blk 控制器实例,并立即在 SNAP 进程 2 上打开 virtio-blk 控制器
snap_rpc.py -s /var/tmp/spdk.sock1 controller_virtio_blk_delete VblkEmu0pf0 --force && snap_rpc.py -s /var/tmp/spdk.sock2 controller_virtio_blk_create mlx5_0 --pf_id 0 --bdev_type spdk --bdev Malloc1 --num_queues 16
完整“实时升级”过程
假设系统上已经运行了一个完全配置的 SNAP 服务
创建 SNAP 二进制文件的本地副本(例如,在
/tmp
文件夹下)cp /usr/bin/mlnx_snap_emu /tmp/
对于所有活动的 virtio-blk 控制器,请按照“在 SNAP 进程之间传递 virtio-blk 控制器的管理”部分中描述的管理传递过程进行操作。
停止原始 SNAP 服务。
systemctl stop mlnx_snap
升级 SNAP 服务。
如果是从二进制文件安装的,请使用 Linux 官方安装框架 (
apt
/yum
)如果是从源代码安装的,请按照最初完成的相同安装过程进行操作
重复管理传递过程,这次是将控制权从本地副本移回官方(更新的)SNAP 服务版本。
对于主机操作系统上的 Linux 环境,可能需要额外的内核启动参数来支持 SNAP 相关功能
要使用 SR-IOV,必须添加
intel_iommu=on iommu=ptmust
要使用 PCIe 热插拔,必须添加
pci=realloc
使用 SR-IOV 时,必须添加
pci=assign-busses
要查看启动参数值,请使用命令 cat /proc/cmdline
。
SPDK 后端 (BDEV) 管理命令
spdk_rpc.py bdev_nvme_attach_controller -b <name> -t rdma -a <ip> -f ipv4 -s <port> -n <nqn>
spdk_rpc.py bdev_nvme_detach_controller <name>
spdk_rpc.py bdev_null_create <name> <size_mb> <blk_size>
spdk_rpc.py bdev_null_delete <name>
spdk_rpc.py bdev_aio_create <filepath> <name> <blk_size>
spdk_rpc.py bdev_aio_delete <name>
有关更多信息,请参阅 SPDK BDEV 文档。
在配置 mlnx_snap 之前,用户必须确保满足所有 FW 配置要求。默认情况下,mlnx_snap 是禁用的,需要通过运行通用的 mlnx-snap 配置以及额外的协议特定配置来启用,具体取决于应用程序的预期用途(例如,热插拔、SR-IOV、UEFI 启动等)。
完成所有配置后,需要重启主机才能使这些更改生效。
为了验证是否满足所有配置要求,用户可以通过运行以下命令查询当前/下一个配置
mlxconfig -d /dev/mst/mt41686_pciconf0 -e query
基本配置
(可选)重置所有先前的配置。
[dpu] mst start [dpu] mlxconfig -d /dev/mst/mt41686_pciconf0 reset
注意这将使您的产品恢复到其默认配置。仅当您无法使 SNAP 工作时才执行此操作。
设置常规基本参数。
在 BlueField-2 上
[dpu] mlxconfig -d /dev/mst/mt41686_pciconf0 s INTERNAL_CPU_MODEL=1
在 BlueField 上
[dpu] sudo mlxconfig -d /dev/mst/mt41682_pciconf0 s INTERNAL_CPU_MODEL=1 PF_BAR2_ENABLE=1 PF_BAR2_SIZE=1
当使用 RDMA/RoCE 传输时,必须配置其他参数
[dpu] mlxconfig -d /dev/mst/mt41686_pciconf0 s PER_PF_NUM_SF=
1
[dpu] mlxconfig -d /dev/mst/mt41686_pciconf0 s PF_SF_BAR_SIZE=8
PF_TOTAL_SF=2
[dpu] mlxconfig -d /dev/mst/mt41686_pciconf0.1
s PF_SF_BAR_SIZE=8
PF_TOTAL_SF=2
系统配置参数
参数 | 描述 | 可能的值 | 注释 |
| 启用 SR-IOV | 0/1 | |
| 每个模拟 PF 的 VF 数量 | [0-127] | |
| 分配给模拟 PF 的 MSIX 数量 | [0-63] | |
| 分配给模拟 VF 的 MSIX 数量 | [0-63] | |
| 为模拟 PF 启用 PCIe 交换机 | 0/1 | |
| 模拟 PF 的最大数量 | [0-32] | 单个端口为所有静态 PF 保留 |
SRIOV_EN 仅对静态 PF 有效
NVMe 配置
参数 | 描述 | 可能的值 | 注释 |
| 启用 NVMe 设备仿真 | 0/1 | |
| 静态模拟 NVMe PF 的数量 | [0-2] | |
| 分配给模拟 NVMe PF/VF 的 MSIX 数量 | [0-63] | |
| 每个模拟 NVMe PF 的 VF 数量 | [0-127] | 如果非 0,则覆盖 |
| 启用 NVMe UEFI exprom 驱动程序 | 0/1 | 用于 UEFI 启动过程 |
Virtio-blk 配置
由于 virtio-blk 协议的限制,在使用静态 virtio-blk PF 时使用错误的配置可能会导致主机服务器操作系统启动失败。
在继续之前,请确保您已配置
即使主机关闭,也可以访问 Arm 的工作通道。设置此类通道不在本文档的范围内。有关更多详细信息,请参阅“NVIDIA BlueField BSP 文档”。
将以下行添加到
/etc/mlnx_snap/snap_rpc_init.conf
controller_virtio_blk_create mlx5_0 --pf_id 0 --bdev_type none
有关更多信息,请参阅“Virtio-blk 控制器管理”部分。
参数 | 描述 | 可能的值 | 注释 |
| 启用 virtio-blk 设备仿真 | 0/1 | |
| 静态模拟 virtio-blk PF 的数量 | [0-2] | 请参阅上面的警告 |
| 分配给模拟 virtio-blk PF/VF 的 MSIX 数量 | [0-63] | |
| 每个模拟 virtio-blk PF 的 VF 数量 | [0-127] | 如果非 0,则覆盖 |
| 启用 virtio-blk UEFI exprom 驱动程序 | 0/1 | 用于 UEFI 启动过程 |
本节仅与以下情况相关
使用传统模式,用户倾向于不使用推荐的 SNAP 命令,而是使用 JSON 文件格式
NVMe-RDMA 完全卸载模式,其中配置只能使用 JSON 文件格式
配置参数分为两类:控制器和后端。
配置文件示例
传统模式配置
对于非完全卸载模式,建议使用 SNAP RPC 命令(在 SNAP 命令中描述)而不是本节中描述的 JSON 文件格式的传统模式。
{
"ctrl": {
"func_num": 0,
"rdma_device": "mlx5_2",
"sqes": 0x6,
"cqes": 0x4,
"cq_period": 3,
"cq_max_count": 6,
"nr_io_queues": 32,
"mn": "Mellanox BlueField NVMe SNAP Controller",
"sn": "MNC12",
"mdts": 4,
"oncs": 0,
"offload": false,
"max_namespaces": 1024,
"quirks": 0x0,
"version": "1.3.0"
},
"backends": [
{
"type": "spdk_bdev",
"paths": [
{
}
]
}
]
}
NVMe-RDMA 完全卸载模式配置
对于 NVMe-RDMA 完全卸载模式,用户只能使用 JSON 文件格式(而不是 SNAP RPC 命令)。
{
"ctrl": {
"func_num": 0,
"rdma_device": "mlx5_2",
"sqes": 0x6,
"cqes": 0x4,
"cq_period": 3,
"cq_max_count": 6,
"nr_io_queues": 32,
"mn": "Mellanox BlueField NVMe SNAP Controller",
"sn": "MNC12",
"mdts": 4,
"oncs": 0,
"offload": true,
"max_namespaces": 1024,
"quirks": 0x0
"version": "1.3.0"
},
"backends": [
{
"type": "nvmf_rdma",
"name": "testsubsystem",
"paths": [
{
"addr": "1.1.1.1",
"port": 4420,
"ka_timeout_ms": 15000,
"hostnqn": "r-nvmx03"
}
]
}
]
}
配置参数
控制器参数
SNAP JSON 配置文件中的参数。默认文件位于 /etc/mlnx_snap/mlnx_snap.json
中。
参数 | 描述 | 合法值 | 默认值 |
| 描述用于传递 RPC 命令的 RPC 服务器套接字。 仅当从主机使用特定于供应商的 RPC 命令时才相关。 | 任何 |
|
| 启用完全卸载模式 |
|
|
| 最大 I/O 队列数。 注意
实际队列数受 FW 支持的队列数限制。 | ≥ 0 |
|
| 型号 | 字符串(最多 40 个字符) |
|
| 序列号 | 字符串(最多 20 个字符) |
|
| 命名空间数量 (NN) 指示 NVM 子系统的有效 NSID 的最大值。如果 | 0-0xFFFFFFFE |
|
| NVM 子系统支持的最大允许命名空间数量 (MNAN) | 1-0xFFFFFFFE |
|
| 最大数据传输大小。此值以最小内存页面大小 (CAP.MPSMIN) 为单位,并报告为 2 的幂 (2n)。 值 0h 表示没有最大数据传输大小。 | 1-6 |
|
| 用于启用特定 NVMe 驱动程序怪癖以与不符合 NVMe 规范的驱动程序一起工作的位掩码。
|
|
|
| 限制可用命名空间的数量 | 任何 |
|
后端参数
这些参数用于定义后端服务器。
即使可以配置后端列表,但目前仅支持单个后端。
参数 | 描述 | 合法值 | 默认值 |
| 后端类型
|
|
|
| 取决于后端类型
| 任何 | 空 |
| 表示打开的后端的所需大小(以 MB 为单位) 注意
仅与 | 任何 | 未使用 |
| 表示打开的后端的所需块大小(以对数刻度表示) 注意
仅与 | 9, 12 | 未使用 |
路径部分
仅当后端类型设置为 nvmf_rdma
时,此部分才相关。对于每个后端,可以使用以下参数指定路径列表
参数 | 描述 | 合法值 | 默认值 |
| 目标 IPv4 地址 |
|
|
| 目标端口号 | 1024-65534 |
|
| 保持活动超时时间,以毫秒为单位 | >0 |
|
| 主机 NQN | 最多 223 个字符的字符串 |
|
如何启用 SNAP?
请参阅“SNAP 安装”部分。
如何配置 SNAP 以支持 VirtIO-blk?
请参阅“Virtio-blk 配置”部分。
如何配置 SNAP 以使用两个端口(用于相同或多个目标)在非卸载模式下工作?
假设
远程目标配置了 nqn "Test" 和 1 个命名空间,并通过 2 个 RDMA 接口 1.1.1.1/24 和 2.2.2.1/24 暴露它
RDMA 接口为 1.1.1.2/24 和 2.2.2.2/24
非卸载模式配置
创建 SPDK BDEV。运行
spdk_rpc.py bdev_nvme_attach_controller -b Nvme0 -t rdma -a 1.1.1.1 -f ipv4 -s 4420 -n Test spdk_rpc.py bdev_nvme_attach_controller -b Nvme1 -t rdma -a 2.2.2.1 -f ipv4 -s 4420 -n Test
创建 NVMe 控制器。运行
snap_rpc.py controller_nvme_create mlx5_0 --subsys_id 0 -c /etc/mlnx_snap/mlnx_snap.json --rdma_device mlx5_2
通过每个端口将命名空间附加两次。运行
snap_rpc.py controller_nvme_namespace_attach -c NvmeEmu0pf0 spdk Nvme0n1 1 snap_rpc.py controller_nvme_namespace_attach -c NvmeEmu0pf0 spdk Nvme1n1 2
在此阶段,您应该在主机 “nvme list” 上看到 /dev/nvme0n1
和 /dev/nvme0n2
,它们都通过 2 个不同的端口映射到同一个远程磁盘。
完全卸载模式配置
完全卸载模式目前允许用户并行连接到多个远程目标(但不能通过不同的路径连接到同一个远程目标)。
创建 2 个单独的 JSON 完全卸载配置文件(请参阅“NVMe-RDMA 完全卸载模式配置”部分)。每个文件都描述了通过不同 RDMA 接口到远程目标的连接。
配置 2 个单独的 NVMe 设备条目以暴露给主机,可以是热插拔 PCIe 功能或“静态”功能(请参阅“固件配置”部分)。
创建 2 个 NVMe 控制器,每个 RDMA 接口一个。运行
snap_rpc.py subsystem_nvme_create Mellanox_NVMe_SNAP "Mellanox NVMe SNAP Controller" snap_rpc.py controller_nvme_create mlx5_0 --subsys_id 0 --pf_id 0 -c /etc/mlnx_snap/mlnx_snap_p0.json --rdma_device mlx5_2 snap_rpc.py subsystem_nvme_create Mellanox_NVMe_SNAP "Mellanox NVMe SNAP Controller" snap_rpc.py controller_nvme_create mlx5_0 --subsys_id 1 --pf_id 1 -c /etc/mlnx_snap/mlnx_snap_p1.json --rdma_device mlx5_3
注意NVMe 控制器也可以共享同一个 NVMe 子系统。在这种情况下,用户必须确保所有远程目标中的所有命名空间都具有不同的 NSID。
在此阶段,您应该在主机 nvme list
上看到 /dev/nvme0n1
和 /dev/nvme1n1
。
如何配置卸载模式?支持哪些协议?
请参阅“NVMe-RDMA 完全卸载模式配置”部分。
有关完全卸载的更多信息,请参阅“NVMe-RDMA 完全卸载模式”部分。
如何为 SNAP 配置固件?
请参阅“固件配置”部分。
我可以在 Arm 上使用自定义 SPDK 吗?
MLNX SNAP 是针对 NVIDIA 内部 SPDK 分支进行原生编译的。在以下条件下,可以使用不同的 SPDK 版本:
必须针对新的 SPDK 源代码重新编译 mlnx-snap 源代码
新的 SPDK 版本更改不会破坏任何外部 SPDK API
集成过程
使用共享库构建 SPDK(和 DPDK)。
[spdk.git] ./configure --prefix=/opt/mellanox/spdk-custom --disable-tests --disable-unit-tests --without-crypto --without-fio --with-vhost --without-pmdk --without-rbd --with-rdma --with-shared --with-iscsi-initiator --without-vtune --without-isal [spdk.git] make && sudo make install [spdk.git] cp -r dpdk/build/lib/* /opt/mellanox/spdk-custom/lib/ [spdk.git] cp -r dpdk/build/include/* /opt/mellanox/spdk-custom/include/
注意也可以在该目录中安装 DPDK,但复制就足够了。
注意只有标志
with-shared
是强制性的针对新的 SPDK 构建 SNAP。
[mlnx-snap.src] ./configure --with-snap --with-spdk=/opt/mellanox/spdk-custom --without-gtest --prefix=/usr [mlnx-snap.src] make -j8 && sudo make install
将其他自定义库附加到 mlnx-snap 应用程序。设置
LD_PRELOAD="/opt/mellanox/spdk/lib/libspdk_custom_library.so"
。注意libspdk_custom_library.so
所需的其他 SPDK/DPDK 库也可能需要附加到LD_PRELOAD
。注意LD_PRELOAD
设置可以添加到/etc/default/mlnx_snap
以便与 mlnx_snap 系统服务持久工作。运行应用程序。
我可以在运行时更换后端存储吗?
NVMe 协议内置支持在运行时附加/分离后端(命名空间)。
要在 NVMe 运行时更改后端存储,请运行
snap_rpc.py controller_nvme_namespace_detach -c NvmeEmu0pf0 1
snap_rpc.py controller_nvme_namespace_attach -c NvmeEmu0pf0 spdk nvme0n1 1
Virtio-blk 协议规范中没有类似的支持。因此,在运行 IO 时分离会导致在分离和附加请求之间收到的任何 IO 上发生错误。
要在 virtio-blk 运行时更改后端存储,请运行
snap_rpc.py controller_virtio_blk_bdev_detach VblkEmu0pf0
snap_rpc.py controller_virtio_blk_bdev_attach VblkEmu0pf0 spdk nvme0n1
更新到最新的 mlnx-snap 后,我遇到了性能低下的问题。如何解决?
在添加使用大量控制器的选项后,必须考虑资源因素。有必要特别注意 MSIX 资源,该资源在整个 BlueField-2 卡上限制为约 1K。因此,现在默认情况下使用有限的资源打开新的 PCI 功能(特别是,MSIX 设置为 2)。
用户可以选择为特定功能分配更多资源,如下详述
增加允许分配给某个功能的 MSIX 数量(可能需要重新启动电源才能使更改生效)
[dpu] mlxconfig -d /dev/mst/mt41686_pciconf0 s VIRTIO_BLK_EMULATION_NUM_MSIX=63
热插拔 virtio-blk PF,增加 MSIX 值。
[dpu] snap_rpc.py emulation_device_attach mlx5_0 virtio_blk --num_msix=63
打开控制器,增加队列数量(每个 MSIX 1 个队列,并为配置中断保留另一个空闲 MSIX)
[dpu] snap_rpc.py controller_virtio_blk_create mlx5_0 --pf_id 0 --bdev_type spdk --bdev Null0 --num_queues=62
有关更多信息,请参阅“性能优化”部分。