DOCA 文档 v2.10.0

本页内容

DOCA SNAP-4 服务指南

本指南提供关于在 NVIDIA® BlueField®-3 DPU 上使用 DOCA SNAP-4 服务的说明。

NVIDIA® BlueField® SNAP 和 virtio-blk SNAP(存储定义网络加速处理)技术支持本地存储的硬件加速虚拟化。NVMe/virtio-blk SNAP 将网络存储呈现为本地块存储设备(例如,SSD),模拟 PCIe 总线上的本地驱动器。主机操作系统或虚拟机监控程序使用其标准存储驱动程序,不知道通信不是与物理驱动器进行的,而是与 NVMe/virtio-blk SNAP 框架进行的。在通过基于 Fabric 的网络将请求和/或数据重定向到远程或本地存储目标之前,任何逻辑都可以应用于 I/O 请求或通过 NVMe/virtio-blk SNAP 框架的数据。

NVMe/virtio-blk SNAP 基于 NVIDIA® BlueField® DPU 系列技术,并将独特的软件定义硬件加速存储虚拟化与 DPU 的高级网络和可编程功能相结合。NVMe/virtio-blk SNAP 与 BlueField DPU 一起,为解决存储和网络效率及性能的应用开辟了广阔前景。

snap-arch-version-1-modificationdate-1731488139820-api-v2.png

从主机到达仿真 PCIe 设备的流量被重定向到在 mlnx_snap 服务上打开的匹配存储控制器。

控制器实现设备规范,并可能相应地公开后端设备(在本用例中,SPDK 用作公开后端设备的存储堆栈)。当收到命令时,控制器会执行它。

管理命令通常立即响应,而 I/O 命令则被重定向到后端设备进行处理。

请求处理管道是完全异步的,并且工作负载分布在所有 Arm 核心(分配给 SPDK 应用程序)上,以实现最佳性能。

以下是 SNAP 的关键概念

  • 在 Fabric/传输/协议方面具有完全的灵活性(例如 NVMe-oF/iSCSI/其他、RDMA/TCP、ETH/IB)

  • NVMe 和 virtio-blk 仿真支持

  • 可编程性

  • 轻松的数据操作

  • 允许从远程存储到主机的零拷贝 DMA

  • 使用 Arm 核心进行数据路径

注意

用于 NVIDIA® BlueField®-2 DPU 的 BlueField SNAP 是许可软件。用户必须为每个 BlueField-2 DPU 购买许可证才能使用它们。

NVIDIA® BlueField®-3 DPU 运行 BlueField SNAP 没有许可证要求。

SNAP 作为容器

在这种方法中,可以从 NVIDIA NGC 下载容器,并可以轻松地将其部署在 DPU 上。

yaml 文件包含与最新 spdk.nvda 版本对齐的 SNAP 二进制文件。在这种情况下,SNAP 源代码不可用,并且无法修改 SNAP 以支持不同的 SPDK 版本(SNAP 作为 SDK 软件包应用于此)。

注意

SNAP 4.x 未预安装在 BFB 上,但可以根据需要手动下载。

有关如何安装 SNAP 容器的说明,请参阅“SNAP 容器部署”。

SNAP 作为软件包

SNAP 开发包(自定义)旨在为希望根据自己的环境自定义 SNAP 服务的用户提供,通常用于使用专有的 bdev 而不是 spdk.nvda 版本。这允许用户完全访问服务代码和 lib 标头,从而能够编译他们的更改。

SNAP 仿真库

这包括协议库以及与固件/硬件 (PRM) 的交互,以及

  • 普通共享对象 (*.so)

  • 静态存档 (*.a)

  • pkgconfig 定义 (*.pc)

  • 包含文件 (*.h)

SNAP 服务源

这包括以下管理器

  • 仿真设备管理器

    • 仿真管理器 – 管理设备仿真、功能发现和功能事件

    • 热插拔管理器 – 管理设备仿真热插拔和热拔出

    • 配置管理器 – 处理通用配置和 RCP(非协议特定的)

  • 服务基础设施管理器

    • 内存管理器 – 处理 SNAP 内存池,当主机和远程目标之间不使用零拷贝时,该内存池用于复制到 Arm 内存中

    • 线程管理器 – 处理 SPDK 线程

  • 协议特定的控制路径管理器

    • NVMe 管理器 – 处理 NVMe 子系统、NVMe 控制器和命名空间功能

    • VBLK 管理器 – 处理 virtio-blk 控制器功能

  • IO 管理器

    • 实现常规和优化流程的 IO 路径(RDMA ZC 和 TCP XLIO ZC)

    • 处理 bdev 创建和功能

SNAP 服务依赖项

SNAP 服务依赖于以下库

  • SPDK – 依赖于 bdev 和 SPDK 资源,例如 SPDK 线程、SPDK 内存和 SPDK RPC 服务

  • XLIO(用于 NVMeTCP 加速)

SNAP 服务流程

snap-service-managers-version-1-modificationdate-1731488139460-api-v2.png

IO 流程

RDMA 零拷贝读/写 IO 流程示例

rdma-zero-copy-read-write-io-flow-version-1-modificationdate-1731488139127-api-v2.png

RDMA 非零拷贝读取 IO 流程示例

rdma-non-zero-copy-read-io-flow-version-1-modificationdate-1731488138813-api-v2.png

数据路径提供程序

SNAP 方便用户配置提供程序,以协助从主机卸载数据路径应用程序。这些包括设备仿真、IO 密集型操作和 DMA 操作。

  • DPA 提供程序 – DPA(数据路径加速器)是嵌入在 BlueField 中的多核和多执行单元 RISC-V 处理器的集群

  • DPU 提供程序 – 使用 BlueField CPU 处理来自主机的数据路径应用程序。此模式可改善 IO 延迟并减少崩溃恢复期间的 SNAP 停机时间。

注意

对于 NVMe 和 virtio-blk,DPA 是 SNAP 中的默认提供程序。

注意

virtio-blk 仅支持 DPU 模式。要设置 DPU 模式,请使用环境变量 VIRTIO_EMU_PROVIDER=dpu 修改 YAML 上的变量。有关更多信息,请参阅“SNAP 环境变量”页面。

本节介绍如何将 SNAP 部署为容器。

注意

SNAP 未预装在 BFB 中。

在 DPU 上安装完整 DOCA 镜像

要安装 NVIDIA® BlueField®-3 BFB

复制
已复制!
            

[host] sudo bfb-install --rshim <rshimN> --bfb <image_path.bfb>

有关更多信息,请参阅 Linux 版 DOCA 安装指南 中的“在 DPU 上安装完整 DOCA 镜像”部分。

固件安装

复制
已复制!
            

[dpu] sudo /opt/mellanox/mlnx-fw-updater/mlnx_fw_updater.pl --force-fw-update

有关更多信息,请参阅 Linux 版 DOCA 安装指南 中的“升级固件”部分。

固件配置

注意

固件配置可能会公开新的仿真 PCI 功能,这些功能稍后可供主机操作系统使用。因此,用户必须确保所有公开的 PCI 功能(静态/热插拔 PF、VF)都由支持的 SNAP SW 配置支持,否则这些功能将保持故障状态,并且主机行为将是未定义的。

  1. 在实施所需配置之前,清除固件配置

    复制
    已复制!
                

    [dpu] mst start [dpu] mlxconfig -d /dev/mst/mt41692_pciconf0 reset

  2. 查看固件配置

    复制
    已复制!
                

    [dpu] mlxconfig -d /dev/mst/mt41692_pciconf0 query

    输出示例

    复制
    已复制!
                

    mlxconfig -d /dev/mst/mt41692_pciconf0 -e query | grep NVME Configurations: Default Current Next Boot * NVME_EMULATION_ENABLE False(0) True(1) True(1) * NVME_EMULATION_NUM_VF 0 125 125 * NVME_EMULATION_NUM_PF 1 2 2 NVME_EMULATION_VENDOR_ID 5555 5555 5555 NVME_EMULATION_DEVICE_ID 24577 24577 24577 NVME_EMULATION_CLASS_CODE 67586 67586 67586 NVME_EMULATION_REVISION_ID 0 0 0 NVME_EMULATION_SUBSYSTEM_VENDOR_ID 0 0 0

    其中输出提供 5 列

    • 非默认配置标记 (*)

    • 固件配置名称

    • 默认固件值

    • 当前固件值

    • 重启后的固件值 – 显示等待系统重启的配置更新

  3. 要启用存储仿真选项,必须将第一个 DPU 设置为在内部 CPU 模型中工作

    复制
    已复制!
                

    [dpu] mlxconfig -d /dev/mst/mt41692_pciconf0 s INTERNAL_CPU_MODEL=1

  4. 要启用具有 virtio-blk 仿真 PF 的固件配置

    复制
    已复制!
                

    [dpu] mlxconfig -d /dev/mst/mt41692_pciconf0 s VIRTIO_BLK_EMULATION_ENABLE=1 VIRTIO_BLK_EMULATION_NUM_PF=1

  5. 要启用具有 NVMe 仿真 PF 的固件配置

    复制
    已复制!
                

    [dpu] mlxconfig -d /dev/mst/mt41692_pciconf0 s NVME_EMULATION_ENABLE=1 NVME_EMULATION_NUM_PF=1

注意

有关 SNAP 固件配置选项的完整列表,请参阅附录“DPU 固件配置”。

注意

需要断电重启才能应用固件配置更改。

RDMA/RoCE 固件配置

BlueField OS 的默认接口(名为 ECPF,通常为 mlx5_0mlx5_1)阻止 RoCE 通信。如果需要 RoCE 流量,则必须添加额外的网络功能,即可扩展功能 (SF),这些功能支持 RoCE 传输。

要启用 RDMA/RoCE

复制
已复制!
            

[dpu] mlxconfig -d /dev/mst/mt41692_pciconf0 s PER_PF_NUM_SF=1 [dpu] mlxconfig -d /dev/mst/mt41692_pciconf0 s PF_SF_BAR_SIZE=8 PF_TOTAL_SF=2 [dpu] mlxconfig -d /dev/mst/mt41692_pciconf0.1 s PF_SF_BAR_SIZE=8 PF_TOTAL_SF=2

注意

通过 TCP 或 InfiniBand 上的 RDMA 工作时,不需要这样做。


SR-IOV 固件配置

SNAP 在 NVMe 上最多支持 512 个 VF,在 virtio-blk 上最多支持 2000 个 VF。VF 可以分布在最多 4 个 virtio-blk PF 或 2 个 NVMe PF 之间。

信息

以下示例仅供参考。有关参数范围的完整详细信息,请参阅附录“DPU 固件配置”。

  • 常见示例

    复制
    已复制!
                

    [dpu] mlxconfig -d /dev/mst/mt41692_pciconf0 s SRIOV_EN=1 PER_PF_NUM_SF=1 LINK_TYPE_P1=2 LINK_TYPE_P2=2 PF_TOTAL_SF=1 PF_SF_BAR_SIZE=8 TX_SCHEDULER_BURST=15

    注意

    当使用 64KB 页大小的操作系统时,应配置 PF_SF_BAR_SIZE=10(而不是 8)。

  • Virtio-blk 250 个 VF 示例(每个 VF 2 个队列)

    复制
    已复制!
                

    [dpu] mlxconfig -d /dev/mst/mt41692_pciconf0 s VIRTIO_BLK_EMULATION_ENABLE=1 VIRTIO_BLK_EMULATION_NUM_VF=125 VIRTIO_BLK_EMULATION_NUM_PF=2 VIRTIO_BLK_EMULATION_NUM_MSIX=2 VIRTIO_BLK_EMULATION_NUM_VF_MSIX=2

  • Virtio-blk 1000 个 VF 示例(每个 VF 2 个队列)

    复制
    已复制!
                

    [dpu] mlxconfig -d /dev/mst/mt41692_pciconf0 s VIRTIO_BLK_EMULATION_ENABLE=1 VIRTIO_BLK_EMULATION_NUM_VF=250 VIRTIO_BLK_EMULATION_NUM_PF=4 VIRTIO_BLK_EMULATION_NUM_MSIX=2 VIRTIO_NET_EMULATION_ENABLE=0 NUM_OF_VFS=0 PCI_SWITCH_EMULATION_ENABLE=0 VIRTIO_BLK_EMULATION_NUM_VF_MSIX=2

  • NVMe 250 个 VF 示例(每个 VF 2 个 IO 队列)

    复制
    已复制!
                

    [dpu] mlxconfig -d /dev/mst/mt41692_pciconf0 s NVME_EMULATION_ENABLE=1 NVME_EMULATION_NUM_VF=125 NVME_EMULATION_NUM_PF=2 NVME_EMULATION_NUM_MSIX=2 NVME_EMULATION_NUM_VF_MSIX=2

热插拔固件配置

一旦启用 PCIe 交换机仿真,BlueField 最多可以支持 31 个热插拔 NVMe/Virtio-blk 功能。“PCI_SWITCH_EMULATION_NUM_PORT-1”个热插拔 PCIe 功能。这些插槽在所有 DPU 用户和应用程序之间共享,并且可以容纳 NVMe、virtio-blk、virtio-fs 或其他类型(例如,virtio-net)的热插拔设备。

要启用 PCIe 交换机仿真并确定要使用的热插拔端口数

复制
已复制!
            

[dpu] mlxconfig -d /dev/mst/mt41692_pciconf0 s PCI_SWITCH_EMULATION_ENABLE=1 PCI_SWITCH_EMULATION_NUM_PORT=32

PCI_SWITCH_EMULATION_NUM_PORT 等于 1 + 热插拔 PCIe 功能的数量。

有关热插拔设备的更多信息,请参阅“热插拔 PCIe 功能管理”部分。

注意

不能保证热插拔在 AMD 机器上工作。

注意

启用PCI_SWITCH_EMULATION_ENABLE可能会影响 Intel 和 AMD 机器上的 SR-IOV 功能。

注意

目前,热插拔 PF 不支持 SR-IOV。


UEFI 固件配置

要使用存储仿真作为启动设备,建议使用 DPU 嵌入的 UEFI 扩展 ROM 驱动程序供 UEFI 使用,而不是原始供应商的 BIOS 驱动程序。

要启用 UEFI 驱动程序

复制
已复制!
            

[dpu] mlxconfig -d /dev/mst/mt41692_pciconf0 s EXP_ROM_VIRTIO_BLK_UEFI_x86_ENABLE=1 EXP_ROM_NVME_UEFI_x86_ENABLE=1

DPU 配置

DPA 核心掩码

数据路径加速器 (DPA) 是一个包含 16 个核心的集群,每个核心有 16 个执行单元 (EU)。

注意

只有 EU 0-170 可用于 SNAP。

SNAP 支持为 NVMe 或 virtio-blk 控制器预留 DPA EU。默认情况下,所有可用的 EU 0-170 在系统上的 NVMe、virtio-blk 和其他 DPA 应用程序(例如,virtio-net)之间共享。

要分配特定的 EU 集,请设置以下环境变量

  • 对于 NVMe

    复制
    已复制!
                

    dpa_nvme_core_mask=0x<EU_mask>

  • 对于 virtio-blk

    复制
    已复制!
                

    dpa_helper_core_mask=0x<EU_mask>

核心掩码必须包含有效的十六进制数字(从右向左解析)。例如,dpa_virtq_split_core_mask=0xff00 设置 8 个 EU(即 EU 8-16)。

注意

每个 DPA EU 的硬件限制为 128 个队列(线程)。


SNAP 容器部署

SNAP 容器在 DOCA SNAP NVIDIA NGC 目录页面上可用。

在 BlueField DPU 之上部署 SNAP 容器需要以下步骤

  1. 容器部署的设置准备和 SNAP 资源下载。有关详细信息,请参阅“准备步骤”部分。

  2. 如果需要高级配置,请根据“调整 YAML 配置”部分调整 doca_snap.yaml

  3. 部署容器。镜像会自动从 NGC 中拉取。有关详细信息,请参阅“生成 SNAP 容器”部分。

以下是 SNAP 容器设置的示例。

snap-container-setup-example-version-1-modificationdate-1731488138570-api-v2.png

准备步骤

步骤 1:分配 Hugepages

通用

根据 DPU OS 的 Hugepagesize 值,为 SNAP 容器分配 4GiB hugepages

  1. 查询 Hugepagesize

    复制
    已复制!
                

    [dpu] grep Hugepagesize /proc/meminfo

    在 Ubuntu 中,该值应为 2048KB。在 CentOS 8.x 中,该值应为 524288KB。

  2. 将以下行附加到 /etc/sysctl.conf 文件的末尾

    • 对于 Ubuntu 或 CentOS 7.x 设置(即,Hugepagesize = 2048 kB)

      复制
      已复制!
                  

      vm.nr_hugepages = 2048

    • 对于 CentOS 8.x 设置(即,Hugepagesize = 524288 kB)

      复制
      已复制!
                  

      vm.nr_hugepages = 8

  3. 运行以下命令

    复制
    已复制!
                

    [dpu] sysctl --system

注意

如果在此部署中使用了实时升级,则有必要为升级后的容器分配两倍于上面列出的资源量。

警告

如果其他应用程序在设置中同时运行并消耗 hugepages,请确保为这些应用程序分配超出本节描述数量的额外 hugepages。

当以高连接规模(即,500 个或更多磁盘)部署 SNAP 时,hugepages 的默认分配 (4GiB) 变得不足。可以通过 SNAP 和 SPDK 层中的错误消息来识别这种 hugepages 短缺。这些错误消息通常指示在创建或修改 QP 或其他对象时发生故障。

步骤 2:创建 nvda_snap 文件夹

容器使用 /etc/nvda_snap 文件夹在部署后进行自动配置。

下载 YAML 配置

SNAP 容器的 .yaml 文件配置为 doca_snap.yaml.yaml 文件的下载命令可以在 DOCA SNAP NGC 页面上找到。

注意

下载 SNAP 资源需要互联网连接。要在没有互联网连接的 DPU 上部署容器,请参阅附录“在没有互联网连接的设置上部署容器”。

调整 YAML 配置

可以轻松编辑 .yaml 文件以进行高级配置。

  • SNAP .yaml 文件默认配置为通过使用 hugepages-2Mi 来支持 Ubuntu 设置(即,Hugepagesize = 2048 kB)。

    要支持其他设置,请根据 DPU OS 的相关 Hugepagesize 值编辑 hugepages 部分。例如,要支持 CentOS 8.x,请将 Hugepagesize 配置为 512MB

    复制
    已复制!
                

    limits: hugepages-512Mi: "<number-of-hugepages>Gi"

    注意

    当部署具有大量控制器(500 个或更多)的 SNAP 时,hugepages 的默认分配 (4GB) 可能会变得不足。可以通过错误消息来识别这种 hugepages 短缺,这些错误消息通常指示在创建或修改 QP 或其他对象时发生故障。在这些情况下,需要更多 hugepages。

  • 以下示例编辑 .yaml 文件,为 SNAP 容器请求 16 个 CPU 核心和 4Gi 内存以及 4Gi hugepages

    复制
    已复制!
                

    resources: requests: memory: "2Gi" hugepages-2Mi: "4Gi" cpu: "8" limits: memory: "4Gi" hugepages-2Mi: "4Gi" cpu: "16" env: - name: APP_ARGS value: "-m 0xffff"

    注意

    如果请求了所有 BlueField-3 核心,则用户必须验证没有其他容器在 CPU 资源上发生冲突。

    注意

    当使用大量核心运行 Virtio-fs 服务时,有必要增加 SPDK 中 IO 缓冲区的数量。例如,要使用 16 个核心运行,大型 IO 缓冲池的大小必须设置为至少 4095。这可以通过将 RPC 命令 iobuf_set_options --large-pool-count 4095 添加到 /etc/nvda_snap 下的 spdk_rpc_init.conf 来配置。根据使用的规模和 SPDK 子系统,可能需要调整其他 SPDK 配置参数。有关更多详细信息,请参阅 SPDK 文档。

  • 要在部署时自动配置 SNAP 容器

    1. /etc/nvda_snap/ 下添加 spdk_rpc_init.conf 文件。文件示例

      复制
      已复制!
                  

      bdev_malloc_create 64 512

    2. /etc/nvda_snap/ 下添加 snap_rpc_init.conf 文件。

      Virtio-blk 文件示例

      复制
      已复制!
                  

      virtio_blk_controller_create --pf_id 0 --bdev Malloc0

      NVMe 文件示例

      复制
      已复制!
                  

      nvme_subsystem_create --nqn nqn.2022-10.io.nvda.nvme:0 nvme_namespace_create -b Malloc0 -n 1 --nqn nqn.2022-10.io.nvda.nvme:0 --uuid 16dab065-ddc9-8a7a-108e-9a489254a839 nvme_controller_create --nqn nqn.2022-10.io.nvda.nvme:0 --ctrl NVMeCtrl1 --pf_id 0 --suspended nvme_controller_attach_ns -c NVMeCtrl1 -n 1 nvme_controller_resume -c NVMeCtrl1

    3. 相应地编辑 .yaml 文件(取消注释)

      复制
      已复制!
                  

      env: - name: SPDK_RPC_INIT_CONF value: "/etc/nvda_snap/spdk_rpc_init.conf" - name: SNAP_RPC_INIT_CONF value: "/etc/nvda_snap/snap_rpc_init.conf"

      注意

      用户有责任确保 SNAP 配置与固件配置匹配。也就是说,必须在所有现有(静态/热插拔)仿真 PCIe 功能上打开仿真控制器(通过自动或手动配置)。没有支持控制器的 PCIe 功能被认为是故障的,并且主机行为是异常的。

生成 SNAP 容器

运行 Kubernetes 工具

复制
已复制!
            

[dpu] systemctl restart containerd [dpu] systemctl restart kubelet [dpu] systemctl enable kubelet [dpu] systemctl enable containerd

将更新后的 doca_snap.yaml 文件复制到 /etc/kubelet.d 目录。

Kubelet 自动从 YAML 文件中描述的 NGC 拉取容器镜像,并生成一个执行容器的 pod。

复制
已复制!
            

cp doca_snap.yaml /etc/kubelet.d/

SNAP 服务立即开始初始化,这可能需要几秒钟。要验证 SNAP 是否正在运行

  • 在日志中查找消息“SNAP 服务成功运行”

  • 发送 spdk_rpc.py spdk_get_version 以确认 SNAP 是否正在运行或仍在初始化

调试和日志

查看当前活动的 pod 及其 ID(pod 可能需要长达 20 秒才能启动)

复制
已复制!
            

crictl pods

输出示例

复制
已复制!
            

POD ID CREATED STATE NAME 0379ac2c4f34c About a minute ago Ready snap

查看当前活动的容器及其 ID

复制
已复制!
            

crictl ps

查看现有容器及其 ID

复制
已复制!
            

crictl ps -a

检查给定容器的日志(SNAP 日志)

复制
已复制!
            

crictl logs <container_id>

如果某些内容未按预期工作,请检查 kubelet 日志

复制
已复制!
            

journalctl -u kubelet

容器日志文件由 Kubelet 自动保存在 /var/log/containers 下。

有关更多日志记录信息,请参阅“RPC 日志历史”部分。

停止、启动、重启 SNAP 容器

SNAP 二进制文件在 Docker 容器中部署为 SNAP 服务,该服务作为 supervisorctl 服务进行管理。Supervisorctl 为各种部署选项提供控制和配置层。

  • 如果 SNAP 崩溃或重启,supervisorctl 会检测到该操作并等待退出的进程释放其资源。然后,它在同一容器内部署一个新的 SNAP 进程,该进程启动恢复流程以替换终止的进程。

  • 如果容器崩溃或重启,kubeletclt 会检测到该操作并等待退出的容器释放其资源。然后,它部署一个带有新 SNAP 进程的新容器,该进程启动恢复流程以替换终止的进程。

注意

在容器崩溃或退出后,kubelet 会以指数退避延迟(10 秒、20 秒、40 秒等)重启它们,延迟上限为五分钟。一旦容器在没有问题的情况下运行了 10 分钟,kubelet 就会重置该容器的重启退避计时器。在不重启容器的情况下重启 SNAP 服务有助于避免发生退避延迟。

不同的 SNAP 终止选项

容器终止

  • 要终止容器,请从 /etc/kubelet.d/ 中删除 .yaml 文件。要启动容器,请将 .yaml 文件 cp 回到同一路径

    复制
    已复制!
                

    cp doca_snap.yaml /etc/kubelet.d/

  • 要使用 crictl 重启容器(使用 sig-term),请使用 -t(超时)选项

    复制
    已复制!
                

    crictl stop -t 10 <container-id>

SNAP 进程终止

  • 要在不重启容器的情况下重启 SNAP 服务,请终止 DPU 上的 SNAP 服务进程。不同的信号可用于不同的终止选项。例如

    复制
    已复制!
                

    pkill -9 -f snap

注意

SNAP 服务终止可能需要时间,因为它会释放所有已分配的资源。持续时间取决于用例的规模以及任何其他与 SNAP 共享资源的应用程序。

SNAP 源码包部署

系统准备

根据 DPU OS 的 Hugepagesize 值,为 SNAP 容器分配 4GiB hugepages

  1. 查询 Hugepagesize

    复制
    已复制!
                

    [dpu] grep Hugepagesize /proc/meminfo

    在 Ubuntu 中,该值应为 2048KB。在 CentOS 8.x 中,该值应为 524288KB。

  2. 将以下行附加到 /etc/sysctl.conf 文件的末尾

    • 对于 Ubuntu 或 CentOS 7.x 设置(即,Hugepagesize = 2048 kB)

      复制
      已复制!
                  

      vm.nr_hugepages = 2048

    • 对于 CentOS 8.x 设置(即,Hugepagesize = 524288 kB)

      复制
      已复制!
                  

      vm.nr_hugepages = 8

  3. 运行以下命令

    复制
    已复制!
                

    [dpu] sysctl --system

注意

如果在此部署中使用了实时升级,则有必要为升级后的容器分配两倍于上面列出的资源量。

警告

如果其他应用程序在设置中同时运行并消耗 hugepages,请确保为这些应用程序分配超出本节描述数量的额外 hugepages。

当以高连接规模(即,500 个或更多磁盘)部署 SNAP 时,hugepages 的默认分配 (4GiB) 变得不足。可以通过 SNAP 和 SPDK 层中的错误消息来识别这种 hugepages 短缺。这些错误消息通常指示在创建或修改 QP 或其他对象时发生故障。

安装 SNAP 源码包

安装软件包

  • 对于 Ubuntu,运行

    复制
    已复制!
                

    dpkg -i snap-sources_<version>_arm64.*

  • 对于 CentOS,运行

    复制
    已复制!
                

    rpm -i snap-sources_<version>_arm64.*

构建、编译和安装源码

注意

要使用自定义 SPDK 构建 SNAP,请参阅“替换 BFB SPDK”部分。

  1. 移动到源码文件夹。运行

    复制
    已复制!
                

    cd /opt/nvidia/nvda_snap/src/

  2. 构建源码。运行

    复制
    已复制!
                

    meson /tmp/build

  3. 编译源码。运行

    复制
    已复制!
                

    meson compile -C /tmp/build

  4. 安装源码。运行

    复制
    已复制!
                

    meson install -C /tmp/build

配置 SNAP 环境变量

要配置 SNAP 的环境变量,请运行

复制
已复制!
            

source /opt/nvidia/nvda_snap/src/scripts/set_environment_variables.sh


运行 SNAP 服务

复制
已复制!
            

/opt/nvidia/nvda_snap/bin/snap_service


替换 BFB SPDK(可选)

首先安装 SPDK。

注意

对于旧版 SPDK 版本(例如,SPDK 19.04),请参阅附录“安装旧版 SPDK”。

要使用自定义 SPDK 构建 SNAP,而不是按照基本构建步骤,请执行以下操作

  1. 移动到源码文件夹。运行

    复制
    已复制!
                

    cd /opt/nvidia/nvda_snap/src/

  2. 构建启用 spdk-compat 的源码,并提供自定义 SPDK 的路径。运行

    复制
    已复制!
                

    meson setup /tmp/build -Denable-spdk-compat=true -Dsnap_spdk_prefix=</path/to/custom/spdk>

  3. 编译源码。运行

    复制
    已复制!
                

    meson compile -C /tmp/build

  4. 安装源码。运行

    复制
    已复制!
                

    meson install -C /tmp/build

  5. 配置 SNAP 环境变量并运行 SNAP 服务,如“配置 SNAP 环境变量”和“运行 SNAP 服务”部分中所述。

启用调试打印进行构建(可选)

而不是基本构建步骤,请执行以下操作

  1. 移动到源码文件夹。运行

    复制
    已复制!
                

    cd /opt/nvidia/nvda_snap/src/

  2. 使用 buildtype=debug 构建源码。运行

    复制
    已复制!
                

    meson --buildtype=debug /tmp/build

  3. 编译源码。运行

    复制
    已复制!
                

    meson compile -C /tmp/build

  4. 安装源码。运行

    复制
    已复制!
                

    meson install -C /tmp/build

  5. 配置 SNAP 环境变量并运行 SNAP 服务,如“配置 SNAP 环境变量”和“运行 SNAP 服务”部分中所述。

自动化 SNAP 配置(可选)

脚本 run_snap.sh 自动化 SNAP 部署。用户必须修改以下文件以与其设置对齐。如果用户使用了不同的目录,则必须相应地对 run_snap.sh 进行编辑

  1. 在以下位置编辑 SNAP 环境变量

    复制
    已复制!
                

    /opt/nvidia/nvda_snap/bin/set_environment_variables.sh

  2. 编辑 SPDK 初始化 RPC 调用

    复制
    已复制!
                

    /opt/nvidia/nvda_snap/bin/spdk_rpc_init.conf

  3. 编辑 SNAP 初始化 RPC 调用

    复制
    已复制!
                

    /opt/nvidia/nvda_snap/bin/snap_rpc_init.conf

运行脚本

复制
已复制!
            

/opt/nvidia/nvda_snap/bin/run_snap.sh

支持的环境变量

名称

描述

默认值

SNAP_RDMA_ZCOPY_ENABLE

启用/禁用 RDMA 零拷贝传输类型。

有关更多信息,请参阅“零拷贝 (SNAP-direct)”部分。

1(已启用)

NVME_BDEV_RESET_ENABLE

建议从同一远程目标发现的命名空间不要由不同的 PCIe 仿真共享。如果希望这样做,用户应将变量 NVME_BDEV_RESET_ENABLE 设置为 0

警告

通过这样做,用户必须确保 SPDK bdev 始终在合理的时间内完成 IO(无论是成功还是失败)。否则,系统可能会停顿,直到所有 IO 返回。

1(已启用)

VBLK_RECOVERY_SHM

启用/禁用使用共享内存文件的 virtio-blk 恢复。这允许在不使用 --force_in_order 的情况下进行恢复。

1(已启用)

SNAP_EMULATION_MANAGER

配置为具有仿真管理功能的 RDMA 设备的名称。

如果未定义变量(默认),SNAP 将搜索所有可用设备以查找仿真管理器(这可能会减慢初始化过程)。除非另行配置,否则 SNAP 选择第一个 ECPF(即“mlx5_0”)作为仿真管理器。

NULL(未配置)


YAML 配置

要更改 SNAP 环境变量,请将以下内容添加到 doca_snap.yaml 并从“调整 YAML 配置”部分继续。

复制
已复制!
            

env: - name: VARIABLE_NAME value: "VALUE"

例如

复制
已复制!
            

env: - name: SNAP_RDMA_ZCOPY_ENABLE value: "1"


源码包配置

要更改 SNAP 环境变量

  1. scripts/set_environment_variables.sh 下添加/修改配置。

  2. 重新运行

    复制
    已复制!
                

    source scripts/set_environment_variables.sh

  3. 重新运行 SNAP。

远程过程调用 (RPC) 协议用于控制 SNAP 服务。NVMe/virtio-blk SNAP 与其他标准 SPDK 应用程序一样,支持基于 JSON 的 RPC 协议命令,以控制任何资源并轻松地从 CLI 创建、删除、查询或修改命令。

除了扩展的 SNAP 特定命令集外,SNAP 还支持所有标准 SPDK RPC 命令。SPDK 标准命令由 spdk_rpc.py 工具执行,而 SNAP 特定命令集扩展由 snap_rpc.py 工具执行。

完整的 spdk_rpc.py 命令集文档可以在 SPDK 官方文档站点中找到。

完整的 snap_rpc.py 扩展命令在本章后面会详细介绍。

使用基于 JSON 的 RPC 协议

基于 JSON 的 RPC 协议可以通过 SNAP 容器内的 snap_rpc.py 脚本和 crictl 工具使用。

信息

SNAP 容器与 CRI 兼容。

  • 要查询活动的容器 ID

    复制
    已复制!
                

    crictl ps -s running -q --name snap

  • 要使用 crictl 将 RPC 发布到容器

    复制
    已复制!
                

    crictl exec <container-id> snap_rpc.py <RPC-method>

    例如

    复制
    已复制!
                

    crictl exec 0379ac2c4f34c snap_rpc.py emulation_function_list

    此外,可以使用别名

    复制
    已复制!
                

    alias snap_rpc.py="crictl ps -s running -q --name snap | xargs -I{} crictl exec -i {} snap_rpc.py " alias spdk_rpc.py="crictl ps -s running -q --name snap | xargs -I{} crictl exec -i {} spdk_rpc.py "

  • 要打开容器的 bash shell,可用于发布 RPC

    复制
    已复制!
                

    crictl exec -it <container-id> bash

日志管理

snap_log_level_set

SNAP 允许使用 snap_log_level_set 动态更改记录器后端的日志级别。将显示请求级别下的任何日志。

参数

必填?

类型

描述

level

数字

日志级别

  • 0 – 严重

  • 1 – 错误

  • 2 – 警告

  • 3 – 信息

  • 4 – 调试

  • 5 – 跟踪

PCIe 功能管理

仿真的 PCIe 功能通过称为仿真管理器的 IB 设备进行管理。仿真管理器是普通的 IB 设备,具有控制 PCIe 通信和面向主机操作系统的设备仿真的特殊权限。

SNAP 查询支持请求的功能集的仿真管理器。

仿真管理器保存其控制的仿真 PCIe 功能的列表。PCIe 功能稍后可以通过 3 种方式访问

  • vuid – 建议使用,因为它保证保持不变(有关详细信息,请参阅附录“PCIe BDF 到 VUID 转换”)

  • vhca_id

  • 功能索引(即,pf_idvf_id

emulation_function_list

emulation_function_list 列出所有现有功能。

以下是 emulation_function_list 命令的示例响应

复制
已复制!
            

[ { "hotplugged": true, "hotplug state": "POWER_ON", "emulation_type": "VBLK", "pf_index": 0, "pci_bdf": "87:00.0", "vhca_id": 5, "vuid": "MT2306XZ009TVBLKS1D0F0", "ctrl_id": "VblkCtrl1", "num_vfs": 0, "vfs": [] } ]

注意

使用 -a--all,以显示所有非活动 VF 功能。

SNAP 支持 2 种类型的 PCIe 功能

  • 静态功能 – 在固件配置阶段配置的 PCIe 功能(物理和虚拟)。有关更多信息,请参阅附录“DPU 固件配置”。

  • 热插拔功能 – 在运行时动态配置的 PCIe 功能。用户可以添加可分离的功能。有关更多信息,请参阅“热插拔 PCIe 功能管理”部分。

热插拔 PCIe 功能管理

热插拔 PCIe 功能在运行时使用 RPC 动态配置。一旦新的 PCIe 功能被热插拔,它将出现在主机的 PCIe 设备列表中,并保持持久存在,直到被显式拔出或系统进行冷重启。重要的是,即使 SNAP 进程终止,这种持久性仍然存在。因此,建议不要在自动初始化脚本(例如,snap_rpc_init.conf)中包含热插拔/热拔出操作。

注意

热插拔 PF 不支持 SR-IOV。

两步 PCIe 热插拔

以下 RPC 命令用于在 DPU 应用程序中动态添加或删除 PCIe PF(即热插拔功能)。

一旦 PCIe 功能被创建(通过 virtio_blk_function_create),它在 DPU 应用程序中是可访问和可管理的,但不会立即对主机 OS/内核可见。这与传统的 API 不同,在传统 API 中,创建和主机暴露是同时发生的。相反,向主机 OS 暴露或隐藏 PCIe 功能由单独的 RPC 命令(virtio_blk_controller_hotplugvirtio_blk_controller_hotunplug)管理。热拔出后,可以安全地从 DPU 中移除该功能(使用 virtio_blk_function_destroy)。

这种方法的一个主要优点是能够在功能上预配置控制器,使其在暴露给主机驱动程序后立即为其服务。事实上,用户必须创建一个控制器才能使用 virtio_blk_controller_hotplug API,这是使功能对主机 OS 可见所必需的。

命令

描述

virtio_blk_function_create

创建一个新的 virtio-blk 模拟功能

virtio_blk_controller_hotplug

向主机 OS 暴露(热插拔)模拟功能

virtio_blk_controller_hotunplug

从主机 OS 中移除(热拔出)模拟功能

virtio_blk_function_destroy

删除现有的 virtio-blk 模拟功能

virtio_blk_function_create

创建一个新的 virtio-blk 模拟功能。

命令参数

参数

必填?

类型

描述

manager

字符串

用于管理热插拔功能的模拟管理器(未使用)


virtio_blk_function_destroy

删除现有的 virtio-blk 模拟功能。

命令参数

参数

必填?

类型

描述

vuid

字符串

要删除的热插拔功能的标识符


virtio_blk_controller_hotplug

向主机 OS 暴露(热插拔)模拟功能。

命令参数

参数

必填?

类型

描述

ctrl

字符串

要暴露给主机 OS 的控制器

wait_for_done

布尔值

阻塞直到主机发现并确认新命令

timeout

整数

放弃等待的时间(毫秒)。仅当使用 wait_for_done 时有效。


virtio_blk_controller_hotunplug

从主机 OS 中移除(热拔出)模拟功能。

命令参数

参数

必填?

类型

描述

ctrl

字符串

要暴露给主机 OS 的控制器

wait_for_done

布尔值

阻塞直到主机识别并移除该功能

注意

非传统 API 尚不支持 NVMe 协议。

注意

当不使用 wait_for_done 方法时,用户有责任验证主机是否识别出新的热插拔功能。这可以通过查询 emulation_function_list RPC 输出中的 pci_hotplug_state 参数来完成。

两步 PCIe 热插拔/热拔出示例

复制
已复制!
            

# Bringup spdk_rpc.py bdev_nvme_attach_controller -b nvme0 -t rdma -a 1.1.1.1 -f ipv4 -s 4420 -n nqn.2022-10.io.nvda.nvme:swx-storage snap_rpc.py virtio_blk_function_create snap_rpc.py virtio_blk_controller_create --vuid MT2114X12200VBLKS1D0F0 --bdev nvme0n1 snap_rpc.py virtio_blk_controller_hotplug -c VblkCtrl1   # Cleanup snap_rpc.py virtio_blk_controller_hotunplug -c VblkCtrl1 snap_rpc.py virtio_blk_controller_destroy -c VblkCtrl1 snap_rpc.py virtio_blk_function_destroy --vuid MT2114X12200VBLKS1D0F0 spdk_rpc.py bdev_nvme_detach_controller nvme0


(已弃用)旧版 API

热插拔传统命令

以下命令将新的 PCIe 功能热插拔到系统中。

在新的 PCIe 功能插入后,它会立即显示在主机的 PCIe 设备列表中,直到它被显式拔出或系统进行冷重启。因此,用户有责任在功能创建后立即打开一个控制器实例来管理新功能。保持热插拔功能而没有匹配的控制器来管理可能会导致主机 OS 驱动程序出现异常行为。

命令

描述

virtio_blk_emulation_device_attach

附加 virtio-blk 模拟功能

nvme_emulation_device_attach

附加 NVMe 模拟功能

virtio_blk_emulation_device_attach

附加 virtio-blk 模拟功能。

命令参数

参数

必填?

类型

描述

id

数字

设备 ID

vid

数字

供应商 ID

ssid

数字

子系统设备 ID

ssvid

数字

子系统供应商 ID

revid

数字

修订 ID

class_code

数字

类代码

num_msix

数字

MSI-X 表大小

total_vf

数字

允许的最大 VF 数量

bdev

字符串

用作后端的块设备

num_queues

数字

IO 队列的数量(默认 1,范围 1-62)。

注意

实际队列数受硬件支持的队列数限制。

提示

建议 MSIX 的数量大于 IO 队列的数量(1 个用于配置中断)。

queue_depth

数字

队列深度(默认 256,范围 1-256)

注意

只有在驱动程序未加载时才能修改队列深度。

transitional_device

布尔值

过渡设备支持。有关更多详细信息,请参阅“Virtio-blk 过渡设备支持”部分。

dbg_bdev_type

布尔值

不适用 – 不支持


nvme_emulation_device_attach

附加 NVMe 模拟功能。

命令参数

参数

必填?

类型

描述

id

数字

设备 ID

vid

数字

供应商 ID

ssid

数字

子系统设备 ID

ssvid

数字

子系统供应商 ID

revid

数字

修订 ID

class_code

数字

类代码

num_msix

数字

MSI-X 表大小

total_vf

数字

允许的最大 VF 数量

num_queues

数字

IO 队列的数量(默认 31,范围 1-31)。

注意

实际队列数受硬件支持的队列数限制。

提示

建议 MSIX 的数量大于 IO 队列的数量(1 个用于配置中断)。

version

字符串

规范版本(目前仅支持 1.4

热拔出传统命令

以下命令分两步从系统中热拔出 PCIe 功能

命令

描述

1

emulation_device_detach_prepare

准备要分离的模拟功能

2

emulation_device_detach

分离模拟功能

emulation_device_detach_prepare

这是分离模拟设备的第一步。它准备系统分离热插拔的模拟功能。如果成功,主机的热插拔设备状态会发生变化,您可以安全地继续执行 emulation_device_detach 命令

连接到模拟功能的控制器必须在执行此命令时创建并处于活动状态。

命令参数

参数

必填?

类型

描述

vhca_id

数字

PCIe 功能的 vHCA ID

vuid

字符串

PCIe 设备 VUID

ctrl

字符串

控制器 ID

注意

必须至少提供一个标识符来描述要分离的 PCIe 功能。


emulation_device_detach

这是完成热插拔模拟功能分离的第二步。如果 分离准备 超时,您可以使用 --force 命令执行意外拔出。

注意

驱动程序必须卸载,否则可能会发生错误。

命令参数

参数

必填?

类型

描述

vhca_id

数字

PCIe 功能的 vHCA ID

vuid

字符串

PCIe 设备 VUID

force

布尔值

在准备失败的情况下分离

注意

必须至少提供一个标识符来描述要分离的 PCIe 功能。

Virtio-blk 热插拔/热拔出示例

复制
已复制!
            

// Bringup spdk_rpc.py bdev_nvme_attach_controller -b nvme0 -t rdma -a 1.1.1.1 -f ipv4 -s 4420 -n nqn.2022-10.io.nvda.nvme:swx-storage snap_rpc.py virtio_blk_emulation_device_attach snap_rpc.py virtio_blk_controller_create --vuid MT2114X12200VBLKS1D0F0 --bdev nvme0n1   // Cleanup snap_rpc.py emulation_device_detach_prepare --vuid MT2114X12200VBLKS1D0F0 snap_rpc.py virtio_blk_controller_destroy -c VblkCtrl1 snap_rpc.py emulation_device_detach --vuid MT2114X12200VBLKS1D0F0 spdk_rpc.py bdev_nvme_detach_controller nvme0

(已弃用)SPDK Bdev 管理

以下 RPC 已弃用,不再支持

  • spdk_bdev_create

  • spdk_bdev_destroy

  • bdev_list

这些 RPC 是可选的。如果不执行,SNAP 将自动生成 SNAP 块设备 (bdev)。

Virtio-blk 模拟管理

Virtio-blk 模拟是一种存储协议,属于 virtio 设备系列。这些设备在虚拟环境中找到,但从设计上来看,对于虚拟机内的用户来说,它们看起来像物理设备。

每个暴露给主机的 virtio-blk 设备(例如,virtio-blk PCIe 条目),无论是 PF 还是 VF,都必须由 virtio-blk 控制器支持。

注意

Virtio-blk 限制

  • 在主机上探测 virtio-blk 驱动程序时,如果没有已经正常工作的 virtio-blk 控制器,可能会导致主机挂起,直到成功打开这样的控制器(不存在超时机制)。

  • 在创建 virtio-blk 控制器时,后端设备必须已经存在。

Virtio-blk 仿真管理命令

命令

描述

virtio_blk_controller_create

创建新的基于 SNAP 的 virtio-blk 控制器

virtio_blk_controller_destroy

销毁 virtio-blk SNAP 控制器

virtio_blk_controller_suspend

暂停 virtio-blk SNAP 控制器

virtio_blk_controller_resume

恢复 virtio-blk SNAP 控制器

virtio_blk_controller_bdev_attach

将 bdev 附加到 virtio-blk SNAP 控制器

virtio_blk_controller_bdev_detach

从 virtio-blk SNAP 控制器分离 bdev

virtio_blk_controller_list

Virtio-blk SNAP 控制器列表

virtio_blk_controller_modify

Virtio-blk 控制器参数修改

virtio_blk_controller_dbg_io_stats_get

获取 virtio-blk SNAP 控制器 IO 统计信息

virtio_blk_controller_dbg_debug_stats_get

获取 virtio-blk SNAP 控制器调试统计信息

virtio_blk_controller_state_save

保存已暂停的 virtio-blk SNAP 控制器的状态

virtio_blk_controller_state_restore

恢复已暂停的 virtio-blk SNAP 控制器的状态

virtio_blk_controller_vfs_msix_reclaim

将 virtio-blk SNAP 控制器 VF 的 MSIX 回收至空闲 MSIX 池。仅对 PF 有效。

virtio_blk_controller_create

在主机上的特定 PCIe 功能上创建新的基于 SNAP 的 virtio-blk 控制器。要指定在其上打开控制器的 PCIe 功能,必须按照“PCIe 功能管理”部分所述提供。

  1. vuid(推荐,因为它保证保持不变)。

  2. vhca_id。

  3. 功能索引 – pf_idvf_id

可以通过运行 emulation_function_list 查询 pci_index 的映射。

命令参数

参数

必填?

类型

描述

vuid

字符串

PCIe 设备 VUID

vhca_id

数字

PCIe 功能的 vHCA ID

pf_id

数字

要在其上启动模拟的 PCIe PF 索引

vf_id

数字

要在其上启动模拟的 PCIe VF 索引(如果控制器要在 VF 上打开)

pci_bdf

字符串

PCIe 设备 BDF

ctrl

字符串

控制器 ID

num_queues

数字

IO 队列的数量(默认 1,范围 1-64)。

提示

建议 MSIX 的数量大于 IO 队列的数量(1 个用于配置中断)。

基于有效的 num_msix 值(可以从 virtio_blk_controller_list RPC 查询),稍后可以使用 virtio_blk_controller_modify RPC 对齐)。

queue_size

数字

队列深度(默认 256,范围 1-256)

size_max

数字

最大 SGE 数据传输大小(默认 4096,范围 1–MAX_UINT16

seg_max

数字

最大 SGE 列表长度(默认 1,范围 1-queue_depth

bdev

字符串

用作后端的 SNAP SPDK 块设备

vblk_id

字符串

控制器的序列号

admin_q

0/1

启用实时迁移和 NVIDIA vDPA

dynamic_msix

0/1

此 PF 上 SR-IOV VF 的动态 MSIX。仅对 PF 有效。

vf_num_msix

数字

控制要与此控制器关联的 MSIX 表的数量。仅对 VF 有效(其父 PF 控制器是使用 --dynamic_msix 选项创建的),并且仅当启用动态 MSIX 管理功能时有效。必须是大于等于 2 的偶数。

注意

当使用 virtio_blk_controller_vfs_msix_reclaim 回收 VF 的 MSIX 或在 virtio_blk_controller_destroy 上使用 --release_msix 释放 VF 的 MSIX 时,此字段是必需的。

force_in_order

0/1

支持 virtio-blk 崩溃恢复。将此参数设置为 1 可能会影响 virtio-blk 性能(默认为 0)。有关更多信息,请参阅“Virtio-blk 崩溃恢复”部分。

indirect_desc

0/1

启用控制器 virt-queues 的间接描述符支持。

注意

当使用 virtio-blk 内核驱动程序时,如果启用了间接描述符,驱动程序始终会使用它。对于大多数 IO 流量模式,对所有 IO 流量模式使用间接描述符可能会损害性能。

read_only

0/1

创建只读 virtio-blk 控制器。

suspended

0/1

在暂停状态下创建控制器。

live_update_listener

0/1

创建具有通过 IPC 侦听实时更新通知功能的控制器。

dbg_bdev_type

0/1

不适用 – 不支持

dbg_local_optimized

0/1

不适用 – 不支持

示例响应

复制
已复制!
            

{ "jsonrpc": "2.0", "id": 1, "result": "VblkCtrl1" }


virtio_blk_controller_destroy

销毁先前创建的 virtio-blk 控制器。可以通过从 virtio_blk_controller_create() 获取的控制器名称唯一标识控制器。

命令参数

参数

必填?

类型

描述

ctrl

字符串

控制器名称

force

布尔值

强制销毁 SR-IOV 的 VF 控制器


virtio_blk_controller_suspend

暂停后,控制器停止接收来自主机驱动程序的新请求,仅完成处理已在进行中的请求。所有暂停的请求(如果有)将在 恢复 后处理。

命令参数

参数

必填?

类型

描述

ctrl

字符串

控制器名称


virtio_blk_controller_resume

在控制器停止接收来自主机驱动程序的新请求(即,已暂停)并且仅完成处理已在进行中的请求后,恢复命令将恢复控制器对 IO 的处理。

命令参数

参数

必填?

类型

描述

ctrl

字符串

控制器名称


virtio_blk_controller_bdev_attach

将指定的 bdev 附加到 virtIO-blk SNAP 控制器。如果附加了新的 bdev,则可以更改序列 ID(使用 vblk_id 参数)。

命令参数

参数

必填?

类型

描述

ctrl

字符串

控制器名称

bdev

字符串

块设备名称

vblk_id

字符串

控制器的序列号


virtio_blk_controller_bdev_detach

您可以替换 virtio-blk 控制器的 bdev。首先,您应该从控制器分离 bdev。当 bdev 分离后,控制器停止接收来自主机驱动程序的新请求(即,已暂停),并且仅完成处理已在进行中的请求。

此时,您可以附加新的 bdev 或销毁控制器。

当附加新的 bdev 时,控制器恢复处理所有未完成的 I/O。

注意

如果驱动程序已加载,则无法更改块大小。

如果驱动程序未加载,则可以将 bdev 替换为不同的块大小。

注意

没有附加 bdev 的控制器被认为是临时状态,在这种状态下,控制器未完全运行,并且可能不会响应驱动程序请求的某些操作。

如果没有立即调用 virtio_blk_controller_bdev_attach 的意图,建议附加 none bdev 代替。例如

复制
已复制!
            

snap_rpc.py virtio_blk_controller_bdev_attach -c VblkCtrl1 --bdev none --dbg_bdev_type null

命令参数

参数

必填?

类型

描述

ctrl

字符串

控制器名称


virtio_blk_controller_list

列出 virtio-blk SNAP 控制器。

命令参数

参数

必填?

类型

描述

ctrl

字符串

控制器名称

示例响应

复制
已复制!
            

{ "ctrl_id": "VblkCtrl2", "vhca_id": 38, "num_queues": 4, "queue_size": 256, "seg_max": 32, "size_max": 65536, "bdev": "Nvme1", "plugged": true, "indirect_desc": true, "num_msix": 2, "min configurable num_msix": 2, "max configurable num_msix": 32 }


virtio_blk_controller_modify

此功能允许用户在控制器已创建后实时修改控制器的某些参数。

修改只能在模拟功能处于空闲状态时完成 - 因此没有驱动程序与其通信。

命令参数

参数

必填?

类型

描述

ctrl

字符串

控制器名称

num_queues

整数

控制器的队列数

num_msix

整数

要用于控制器的 MSIX 数量。

仅与 VF 控制器相关(当启用动态 MSIX 功能时)。

注意

标准 virtio-blk 内核驱动程序当前不支持 PCI FLR。因此,


virtio_blk_controller_dbg_io_stats_get

调试计数器是每个控制器的 I/O 统计信息,可以帮助了解控制器不同队列之间的 I/O 分布以及控制器上接收的总 I/O。

命令参数

参数

必填?

类型

描述

ctrl

字符串

控制器名称

示例响应

复制
已复制!
            

"ctrl_id": "VblkCtrl2", "queues": [ { "queue_id": 0, "core_id": 0, "read_io_count": 19987068, "write_io_count": 6319931, "flush_io_count": 0 }, { "queue_id": 1, "core_id": 1, "read_io_count": 9769556, "write_io_count": 3180098, "flush_io_count": 0 } ], "read_io_count": 29756624, "write_io_count": 9500029, "flush_io_count": 0 }


virtio_blk_controller_dbg_debug_stats_get

调试计数器是每个控制器的调试统计信息,可以帮助了解控制器和队列的健康状况和状态。

命令参数

参数

必填?

类型

描述

ctrl

字符串

控制器名称

示例响应

复制
已复制!
            

{ "ctrl_id": "VblkCtrl1", "queues": [ { "qid": 0, "state": "RUNNING", "hw_available_index": 6, "sw_available_index": 6, "hw_used_index": 6, "sw_used_index": 6, "hw_received_descs": 13, "hw_completed_descs": 13 }, { "qid": 1, "state": "RUNNING", "hw_available_index": 2, "sw_available_index": 2, "hw_used_index": 2, "sw_used_index": 2, "hw_received_descs": 6, "hw_completed_descs": 6 }, { "qid": 2, "state": "RUNNING", "hw_available_index": 0, "sw_available_index": 0, "hw_used_index": 0, "sw_used_index": 0, "hw_received_descs": 4, "hw_completed_descs": 4 }, { "qid": 3, "state": "RUNNING", "hw_available_index": 0, "sw_available_index": 0, "hw_used_index": 0, "sw_used_index": 0, "hw_received_descs": 3, "hw_completed_descs": 3 } ] }


virtio_blk_controller_state_save

保存已暂停的 virtio-blk SNAP 控制器的状态。

命令参数

参数

必填?

类型

描述

ctrl

字符串

控制器名称

file_name

字符串

要将状态保存到的文件名


virtio_blk_controller_state_restore

恢复已暂停的 virtio-blk SNAP 控制器的状态。

命令参数

参数

必填?

类型

描述

ctrl

字符串

控制器名称

file_name

字符串

要将状态保存到的文件名


virtio_blk_controller_vfs_msix_reclaim

将 virtio-blk SNAP 控制器 VF 的 MSIX 回收至空闲 MSIX 池。仅对 PF 有效。

命令参数

参数

必填?

类型

描述

ctrl

字符串

控制器名称

Virtio-blk 配置示例

单控制器的 Virtio-blk 配置

复制
已复制!
            

spdk_rpc.py bdev_nvme_attach_controller -b nvme0 -t rdma -a 1.1.1.1 -f ipv4 -s 4420 -n nqn.2022-10.io.nvda.nvme:swx-storage snap_rpc.py virtio_blk_controller_create --vuid MT2114X12200VBLKS1D0F0 --bdev nvme0n1


单控制器的 Virtio-blk 清理

复制
已复制!
            

snap_rpc.py virtio_blk_controller_destroy -c VblkCtrl1 spdk_rpc.py bdev_nvme_detach_controller nvme0


125 个 VF 的 Virtio-blk 动态配置

  1. 按照“SR-IOV 固件配置”部分所述更新固件配置。

  2. 重启主机。

  3. 运行

    复制
    已复制!
                

    [dpu] spdk_rpc.py bdev_nvme_attach_controller -b nvme0 -t rdma -a 1.1.1.1 -f ipv4 -s 4420 -n nqn.2022-10.io.nvda.nvme:swx-storage [dpu] snap_rpc.py virtio_blk_controller_create --vuid MT2114X12200VBLKS1D0F0   [host] modprobe -v virtio-pci && modprobe -v virtio-blk [host] echo 125 > /sys/bus/pci/devices/0000:86:00.3/sriov_numvfs   [dpu] for i in `seq 0 124`; do snap_rpc.py virtio_blk_controller_create --pf_id 0 --vf_id $i --bdev nvme0n1; done;

    注意

    当启用 SR-IOV 时,建议使用以下方法而不是 virito_blk_controller_destroy RPC 命令来销毁 VF 上的 virtio-blk 控制器

    复制
    已复制!
                

    [host] echo 0 > /sys/bus/pci/devices/0000:86:00.3/sriov_numvfs

    要销毁单个 virtio-blk 控制器,请运行

    复制
    已复制!
                

    [dpu] ./snap_rpc.py -t 1000 virtio_blk_controller_destroy -c VblkCtrl5 –f

Virtio-blk 暂停、恢复示例

复制
已复制!
            

[host] // Run fio [dpu] snap_rpc.py virtio_blk_controller_suspend -c VBLKCtrl1 [host] // IOs will get suspended [dpu] snap_rpc.py virtio_blk_controller_resume -c VBLKCtrl1 [host] // fio will resume sending IOs


Virtio-blk Bdev 附加、分离示例

复制
已复制!
            

[host] // Run fio [dpu] snap_rpc.py virtio_blk_controller_bdev_detach -c VBLKCtrl1 [host] // Bdev will be detached and IOs will get suspended [dpu] snap_rpc.py virtio_blk_controller_bdev_attach -c VBLKCtrl1 --bdev null2 [host] // The null2 bdev will be attached into controller and fio will resume sending IOs


注释

  • Virtio-blk 协议控制器仅支持一个后端设备

  • Virtio-blk 协议不支持添加后端的管理命令。因此,所有后端属性都通过 PCIe BAR 传达给主机 virtio-blk 驱动程序,并且在驱动程序探测期间必须可访问。因此,只有当 PCIe 功能未被任何主机存储驱动程序使用时,才能更改后端。

NVMe 仿真管理

NVMe 子系统

NVMe 子系统如 NVMe 规范中所述,是一个逻辑实体,它封装了 NVMe 后端(或命名空间)和连接(或控制器)的集合。当使用多个 NVMe 控制器,尤其是在使用 NVMe VF 时,NVMe 子系统非常有用。每个 NVMe 子系统在创建后都由其序列号 (SN)、型号 (MN) 和合格名称 (NQN) 定义。

本节列出的 RPC 控制 NVMe 子系统的创建和销毁。

NVMe 命名空间

NVMe 命名空间是本地/远程存储中连续 LBA 范围的代表。每个命名空间都必须链接到一个子系统,并在整个 NVMe 子系统中具有唯一的标识符 (NSID)(例如,即使两个命名空间链接到不同的控制器,它们也不能共享相同的 NSID)。

创建后,NVMe 命名空间可以附加到控制器。

注意

SNAP 目前不支持不同控制器之间的共享命名空间。因此,每个命名空间应附加到单个控制器。

SNAP 应用程序使用 SPDK 块设备框架作为其 NVMe 命名空间的后端。因此,应提前配置它们。有关 SPDK 块设备的更多信息,请参阅 SPDK bdev 文档附录 SPDK 配置

NVMe 控制器

每个暴露给主机的 NVMe 设备(例如,NVMe PCIe 条目),无论是 PF 还是 VF,都必须由 NVMe 控制器支持,该控制器负责与主机驱动程序的所有协议通信。

每个新的 NVMe 控制器也必须链接到 NVMe 子系统。创建后,可以使用其名称(例如,“Nvmectrl1”)或其子系统 NQN 和控制器 ID 来寻址 NVMe 控制器。

将 NVMe 命名空间附加到 NVMe 控制器

在同一子系统下创建 NVMe 控制器和 NVMe 命名空间后,使用以下方法将命名空间附加到控制器。

NVMe 仿真管理命令

命令

描述

nvme_subsystem_create

创建 NVMe 子系统

nvme_subsystem_destroy

销毁 NVMe 子系统

nvme_subsystem_list

NVMe 子系统列表

nvme_namespace_create

创建 NVMe 命名空间

nvme_namespace_destroy

销毁 NVMe 命名空间

nvme_controller_suspend

暂停 NVMe 控制器

nvme_controller_resume

恢复 NVMe 控制器

nvme_controller_snapshot_get

将 NVMe 控制器的快照保存到文件

nvme_namespace_list

NVMe 命名空间列表

nvme_controller_create

创建新的 NVMe 控制器

nvme_controller_destroy

销毁 NVMe 控制器

nvme_controller_list

NVMe 控制器列表

nvme_controller_modify

NVMe 控制器参数修改

nvme_controller_attach_ns

将 NVMe 命名空间附加到控制器

nvme_controller_detach_ns

从控制器分离 NVMe 命名空间

nvme_controller_vfs_msix_reclaim

将 NVMe SNAP 控制器 VF 的 MSIX 回收至空闲 MSIX 池。仅对 PF 有效。

nvme_controller_dbg_io_stats_get

获取 NVMe 控制器 IO 调试统计信息

nvme_subsystem_create

创建一个新的 NVMe 子系统,由一个或多个 NVMe SNAP 控制器控制。NVMe 子系统包括一个或多个控制器、零个或多个命名空间以及一个或多个端口。NVMe 子系统可能包括非易失性存储介质以及 NVMe 子系统中的控制器与非易失性存储介质之间的接口。

命令参数

参数

必填?

类型

描述

nqn

字符串

子系统合格名称

serial_number

字符串

子系统序列号

model_number

字符串

子系统型号

nn

数字

子系统中允许的最大命名空间 ID(默认 0xFFFFFFFE;范围 1-0xFFFFFFFE)

mnan

数字

子系统中允许的最大命名空间数量(默认 1024;范围 1-0xFFFFFFFE)

示例请求

复制
已复制!
            

{ "jsonrpc": "2.0", "id": 1, "method": "nvme_subsystem_create", "params": { "nqn": "nqn.2022-10.io.nvda.nvme:0" } }


nvme_subsystem_destroy

销毁(先前创建的)NVMe SNAP 子系统。

命令参数

参数

必填?

类型

描述

nqn

字符串

子系统合格名称

force

布尔值

强制删除子系统下的所有控制器和命名空间


nvme_subsystem_list

列出 NVMe 子系统。

nvme_namespace_create

创建新的 NVMe 命名空间,这些命名空间代表先前配置的 bdev 中的连续 LBA 范围。每个命名空间都必须链接到一个子系统,并在整个 NVMe 子系统中具有唯一的标识符 (NSID)。

命令参数

参数

必填?

类型

描述

nqn

字符串

子系统合格名称

bdev_name

字符串

用作后端的块设备

nsid

数字

命名空间 ID

uuid

数字

命名空间 UUID

注意

为了安全地分离/附加命名空间,应提供 UUID 以强制 UUID 保持持久性。

dbg_bdev_type

string

要与控制器附加的 Bdev 插件。有关更多信息,请参阅“Bdev”部分。


nvme_namespace_destroy

销毁先前创建的 NVMe 命名空间。

命令参数

参数

必填?

类型

描述

nqn

字符串

子系统合格名称

nsid

数字

命名空间 ID


nvme_namespace_list

列出 NVMe SNAP 命名空间。

命令参数

参数

必填?

类型

描述

nqn

字符串

子系统合格名称


nvme_controller_create

在主机上的特定 PCIe 功能上创建一个新的基于 SNAP 的 NVMe blk 控制器。

要指定在其上打开控制器的 PCIe 功能,必须提供 pci_index

可以通过运行 emulation_function_list 查询 pci_index 的映射。

命令参数

参数

必填?

类型

描述

nqn

字符串

子系统合格名称

vuid

数字

PCIe 功能的 VUID

pf_id

数字

要在其上启动模拟的 PCIe PF 索引

vf_id

数字

要在其上启动模拟的 PCIe VF 索引(如果控制器注定要在 VF 上打开)

pci_bdf

字符串

要在其上启动模拟的 PCIe BDF

vhca_id

数字

PCIe 功能的 vHCA ID

ctrl

数字

控制器 ID

num_queues

数字

IO 队列的数量(默认 1,范围 1-31)。

注意

实际队列数受硬件支持的队列数限制。

提示

建议 MSIX 的数量与 IO 队列的数量相匹配或更大。

mdts

数字

MDTS(默认 7,范围 1-7)

fw_slots

数字

最大固件槽数(默认 4)

write_zeroes

0/1

启用 write_zeroes 可选 NVMe 命令

compare

0/1

设置控制器中 compare 支持位的值

compare_write

0/1

设置控制器中 compare_write 支持位的值

注意

在崩溃恢复期间,所有 compare 和 write 命令都应失败。

deallocate_dsm

0/1

设置控制器中 dsm(数据集管理)支持位的值。当前唯一支持的 dsm 请求是 deallocate

suspended

0/1

在暂停状态下打开控制器(需要额外调用 nvme_controller_resume 后才能变为活动状态)

注意

如果预期进行 NVMe 恢复或者在驱动程序已加载时创建控制器,则这是必需的。因此,建议在所有场景中使用它。

要在附加命名空间后恢复控制器,请使用 nvme_controller_resume

snapshot

字符串

从快照文件路径创建控制器。快照是先前使用 nvme_controller_snapshot_get 拍摄的。

dynamic_msix

0/1

为此控制器启用动态 MSIX 管理(默认 0)。仅适用于 PF。

vf_num_msix

数字

控制要与此控制器关联的 MSIX 表的数量。仅对 VF 有效(其父 PF 控制器是使用 --dynamic_msix 选项创建的),并且仅当启用动态 MSIX 管理功能时有效。

注意

当使用 nvme_controller_vfs_msix_reclaim 回收 VF 的 MSIX 或在 nvme_controller_destroy 上使用 --release_msix 释放 VF 的 MSIX 时,此字段是必需的。

admin_only

0/1

创建仅具有管理队列的 NVMe 控制器(即,没有 IO 队列)

quirks

数字

用于支持不符合 NVMe 规范的错误驱动程序的位掩码。

  • 位 0 – 发送“命名空间属性已更改”异步事件,即使驱动程序在“设置功能”命令期间禁用了它

  • 位 1 – 继续发送“命名空间属性已更改”异步事件,即使“已更改命名空间列表”Get Log Page 尚未从驱动程序到达

  • 位 2 – 保留

  • 位 3 – 强制启用“命名空间管理功能”NVMe OACS,即使控制器不支持它

  • 位 4 - 禁用 Scatter-Gather Lists 支持。

有关更多详细信息,请参阅“OS 问题”部分。

注意

如果未设置,则 SNAP NVMe 控制器仅在其加载驱动程序时附加到它的所有命名空间都支持可选 NVMe 命令时才支持该命令。要绕过此功能,您可以显式设置 NVMe 可选命令支持位,方法是使用其对应的标志。

例如,使用 –-compare 0 创建的控制器将不支持可选的 compare NVMe 命令,无论其附加的命名空间如何。

示例请求

复制
已复制!
            

{ "jsonrpc": "2.0", "id": 1, "method": "nvme_controller_create", "params": { "nqn": "nqn.2022-10.io.nvda.nvme:0", "pf_id": 0, "num_queues": 8, } }


nvme_controller_destroy

销毁先前创建的 NVMe 控制器。可以通过从 nvme_controller_create 获取的控制器名称唯一标识控制器。

命令参数

参数

必填?

类型

描述

ctrl

字符串

控制器名称

release_msix

1/0

将 MSIX 释放回空闲池。仅适用于 VF。


nvme_controller_suspend

暂停后,控制器停止处理来自主机驱动程序的新请求。所有挂起的请求(如果有)将在 恢复 后处理。

命令参数

参数

必填?

类型

描述

ctrl

字符串

控制器名称

timeout_ms

数字

暂停超时

注意

如果 I/O 在 bdev 层(或远程目标)中处于挂起状态,则操作将失败,并在超时后恢复。

如果未提供 timeout_ms,则操作将等待 I/O 完成,SNAP 层不会设置超时。

force

0/1

即使存在正在进行的 I/O,也强制挂起

admin_only

0/1

仅挂起管理队列

live_update_notifier

0/1

通过 IPC 发送实时更新通知


nvme_controller_resume

resume 命令继续(先前已挂起的)控制器处理驱动程序发送的新请求。如果控制器在挂起模式下创建,则 resume 也用于启动与主机驱动程序的初始通信。

命令参数

参数

必填?

类型

描述

ctrl

字符串

控制器名称

live_update

0/1

实时更新恢复


nvme_controller_snapshot_get

拍摄控制器当前状态的快照并将其转储到文件中。此文件可用于基于此快照创建控制器。为了保证快照的一致性,用户应仅在控制器挂起时调用此函数(请参阅 nvme_controller_suspend RPC)。

命令参数

参数

必填?

类型

描述

ctrl

字符串

控制器名称

filename

字符串

文件路径


nvme_controller_vfs_msix_reclaim

将所有 VF 的 MSIX 回收至 PF 的可用 MSIX 池。

此函数只能应用于 PF,并且只能在主机端未设置 SR-IOV 时运行(即,sriov_numvfs = 0)。

命令参数

参数

必填?

类型

描述

ctrl

字符串

控制器名称


nvme_controller_list

提供所有活动的(已创建的)NVMe 控制器的列表及其特性。

命令参数

参数

必填?

类型

描述

nqn

字符串

子系统合格名称

ctrl

字符串

仅搜索特定的控制器


nvme_controller_modify

此功能允许用户在控制器已创建后实时修改控制器的某些参数。

修改只能在模拟功能处于空闲状态时完成 - 因此没有驱动程序与其通信。

命令参数

参数

必填?

类型

描述

ctrl

字符串

控制器名称

num_queues

整数

控制器的队列数

num_msix

整数

要用于控制器的 MSIX 数量。

仅与 VF 控制器相关(当启用动态 MSIX 功能时)。


nvme_controller_attach_ns

将先前创建的 NVMe 命名空间附加到同一子系统下的给定 NVMe 控制器。

响应对象中的结果对于成功返回 true,对于失败返回 false

命令参数

参数

必填?

类型

描述

ctrl

字符串

控制器名称

nsid

数字

命名空间 ID


nvme_controller_detach_ns

从 NVMe 控制器分离先前附加的具有给定 NSID 的命名空间。

响应对象中的结果对于成功返回 true,对于失败返回 false

命令参数

参数

必填?

类型

描述

ctrl

字符串

控制器名称

nsid

数字

命名空间 ID


nvme_controller_dbg_io_stats_get

响应对象中的结果对于成功返回 true,对于失败返回 false

命令参数

参数

必填?

类型

描述

ctrl

字符串

控制器名称

复制
已复制!
            

"ctrl_id": "NVMeCtrl2", "queues": [ { "queue_id": 0, "core_id": 0, "read_io_count": 19987068, "write_io_count": 6319931, "flush_io_count": 0 }, { "queue_id": 1, "core_id": 1, "read_io_count": 9769556, "write_io_count": 3180098, "flush_io_count": 0 } ], "read_io_count": 29756624, "write_io_count": 9500029, "flush_io_count": 0 }

NVMe 配置示例

单控制器 NVMe 配置

在 DPU 上

复制
已复制!
            

spdk_rpc.py bdev_nvme_attach_controller -b nvme0 -t rdma -a 1.1.1.1 -f ipv4 -s 4420 -n nqn.2022-10.io.nvda.nvme:swx-storage snap_rpc.py nvme_subsystem_create --nqn nqn.2022-10.io.nvda.nvme:0 snap_rpc.py nvme_namespace_create -b nvme0n1 -n 1 --nqn nqn.2022-10.io.nvda.nvme:0 --uuid 263826ad-19a3-4feb-bc25-4bc81ee7749e snap_rpc.py nvme_controller_create --nqn nqn.2022-10.io.nvda.nvme:0 --pf_id 0 --suspended snap_rpc.py nvme_controller_attach_ns -c NVMeCtrl1 -n 1 snap_rpc.py nvme_controller_resume -c NVMeCtrl1

注意

必须在挂起状态下创建控制器。之后,可以附加命名空间,然后才应使用 nvme_controller_resume RPC 恢复控制器。

注意

为了安全地分离/附加命名空间,必须提供 UUID 以强制 UUID 保持持久。


单控制器 NVMe 清理

复制
已复制!
            

snap_rpc.py nvme_controller_detach_ns -c NVMeCtrl2 -n 1 snap_rpc.py nvme_controller_destroy -c NVMeCtrl2 snap_rpc.py nvme_namespace_destroy -n 1 --nqn nqn.2022-10.io.nvda.nvme:0 snap_rpc.py nvme_subsystem_destroy --nqn nqn.2022-10.io.nvda.nvme:0 spdk_rpc.py bdev_nvme_detach_controller nvme0


单控制器 NVMe 和热插拔清理

复制
已复制!
            

snap_rpc.py nvme_controller_detach_ns -c NVMeCtrl1 -n 1 snap_rpc.py emulation_device_detach_prepare --vuid MT2114X12200VBLKS1D0F0 snap_rpc.py nvme_controller_destroy -c NVMeCtrl1 snap_rpc.py emulation_device_detach --vuid MT2114X12200VBLKS1D0F0 snap_rpc.py nvme_namespace_destroy -n 1 --nqn nqn.2022-10.io.nvda.nvme:0 snap_rpc.py nvme_subsystem_destroy --nqn nqn.2022-10.io.nvda.nvme:0 spdk_rpc.py bdev_nvme_detach_controller nvme0


125 个 VF SR-IOV 的 NVMe 配置

  1. 按照“SR-IOV 固件配置”部分所述更新固件配置。

  2. 重启主机。

  3. 在父 PF 上创建虚拟控制器

    复制
    已复制!
                

    [dpu] # snap_rpc.py nvme_subsystem_create --nqn nqn.2022-10.io.nvda.nvme:0 [dpu] # snap_rpc.py nvme_controller_create --nqn nqn.2022-10.io.nvda.nvme:0 --ctrl NVMeCtrl1 --pf_id 0 --admin_only

  4. 创建 125 个 Bdev(远程或本地)、125 个 NS 和 125 个控制器

    复制
    已复制!
                

    [dpu] for i in `seq 0 124`; do \ # spdk_rpc.py bdev_null_create null$((i+1)) 64 512; # snap_rpc.py nvme_namespace_create -b null$((i+1)) -n $((i+1)) --nqn nqn.2022-10.io.nvda.nvme:0 --uuid 3d9c3b54-5c31-410a-b4f0-7cf2afd9e$((i+100));   # snap_rpc.py nvme_controller_create --nqn nqn.2022-10.io.nvda.nvme:0 --ctrl NVMeCtrl$((i+2)) --pf_id 0 --vf_id $i --suspended; # snap_rpc.py nvme_controller_attach_ns -c NVMeCtrl$((i+2)) -n $((i+1)); # snap_rpc.py nvme_controller_resume -c NVMeCtrl$(i+2); done

  5. 加载驱动程序并配置 VF

    复制
    已复制!
                

    [host] # modprobe -v nvme [host] # echo 125 > /sys/bus/pci/devices/0000\:25\:00.2/sriov_numvfs

环境变量管理

snap_global_param_list

snap_global_param_list 列出所有现有的环境变量。

以下是 snap_global_param_list 命令的示例响应

复制
已复制!
            

[ "SNAP_ENABLE_POLL_SKIP : set : 0 ", "SNAP_POLL_CYCLE_SIZE : not set : 16 ", "SNAP_RPC_LOG_ENABLE : set : 1 ", "SNAP_MEMPOOL_SIZE_MB : set : 1024", "SNAP_MEMPOOL_4K_BUFFS_PER_CORE : not set : 1024", "SNAP_RDMA_ZCOPY_ENABLE : set : 1 ", "SNAP_TCP_XLIO_ENABLE : not set : 1 ", "SNAP_TCP_XLIO_TX_ZCOPY : not set : 1 ", "MLX5_SHUT_UP_BF : not set : 0 ", "SNAP_SHARED_RX_CQ : not set : 1 ", "SNAP_SHARED_TX_CQ : not set : 1 ", ...

RPC 日志历史

RPC 日志历史记录(默认启用)记录发送到 SNAP 应用程序的所有 RPC 请求(来自 snap_rpc.pyspdk_rpc.py)以及每个 RPC 请求的 RPC 响应,记录在一个专用的日志文件 /var/log/snap-log/rpc-log 中。此文件在容器外部可见(即,DPU 上的日志文件路径也为 /var/log/snap-log/rpc-log)。

可以使用 SNAP_RPC_LOG_ENABLE 环境变量来启用 (1) 或禁用 (0) 此功能。

信息

SPDK 版本 spdk23.01.2-12 及更高版本支持 RPC 日志历史记录。

警告

启用 RPC 日志历史记录后,SNAP 应用程序会持续(以追加模式)将 RPC 请求和响应消息写入 /var/log/snap-log/rpc-log。请注意此文件的大小。如果文件过大,请在启动 SNAP pod 之前删除 DPU 上的该文件。

SR-IOV

SR-IOV 的配置取决于内核版本,需要仔细考虑以确保最佳的设备可见性和系统稳定性。

对于具有多个虚拟设备的部署,必须禁用自动探测 (autoprobe),以通过在 /sys/bus/pci/devices/<BDF>/ 中设置 sriov_drivers_autoprobe=0 来确保可靠的设备发现。未能这样做可能会导致以下问题

  • 设备可见性不完整

  • 虚拟磁盘丢失

  • 设备初始化期间可能发生系统挂起

  • 大量 VF(>100)的不可靠行为

大规模部署所需的配置

  1. 禁用自动探测 (autoprobe)

    复制
    已复制!
                

    echo 0 > /sys/bus/pci/devices/<BDF>/sriov_drivers_autoprobe

  2. 根据需要使用特定的驱动程序绑定工具(例如,sysfs 中的 driverctlbind/unbind)手动绑定 VF。

对于小规模部署(少于 100 个 VF),您可以使用 sriov_totalvfs sysfs 条目来设置 VF 的数量

复制
已复制!
            

echo <number_of_vfs> > /sys/bus/pci/devices/<BDF>/sriov_totalvfs

注意

将此配置应用于更大规模的部署。

注意

完成 SR-IOV 配置后,默认情况下不会在 hypervisor 中公开任何磁盘。只有在使用虚拟化管理器(例如,libvirt、VMware 等)将关联的 PCIe VF 分配给 VM 后,磁盘才会出现在 VM 中。如果您需要直接从 hypervisor 使用设备,请手动将 PCIe VF 绑定到所需的驱动程序。

注意

热插拔 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 配置启用此功能。

要启用零拷贝,请设置环境变量(默认情况下已启用)

复制
已复制!
            

SNAP_RDMA_ZCOPY_ENABLE=1

更多信息请参考 "SNAP 环境变量" 部分。

NVMe/TCP XLIO 零拷贝

NVMe/TCP 零拷贝在 SPDK NVMe initiator 中作为自定义的 NVDA_TCP 传输实现,并且它基于新的 XLIO socket 层实现。

Tx 和 Rx 的实现方式不同

  • NVMe/TCP Tx 零拷贝在 RDMA 和 TCP 之间是相似的,因为数据直接从主机内存发送到网络线路,而无需中间复制到 Arm 内存。

  • NVMe/TCP Rx 零拷贝允许在 Rx 流上实现部分零拷贝,方法是消除从 socket 缓冲区 (XLIO) 到应用程序缓冲区 (SNAP) 的复制。但是数据仍然必须从 Arm DMA 到主机内存。

要启用 NVMe/TCP 零拷贝,请使用 SPDK v22.05.nvda --with-xliov22.05.nvda 或更高版本)。

注意

有关 XLIO 的更多信息,包括限制和错误修复,请参阅 NVIDIA 加速 IO (XLIO) 文档

要启用 SNAP TCP XLIO 零拷贝

  1. SNAP 容器:在 YAML 文件中设置环境变量和资源

    复制
    已复制!
                

    resources: requests: memory: "4Gi" cpu: "8" limits: hugepages-2Mi: "4Gi" memory: "6Gi" cpu: "16"   ## Set according to the local setup env: - name: APP_ARGS value: "--wait-for-rpc" - name: SPDK_XLIO_PATH value: "/usr/lib/libxlio.so"

  2. SNAP 源代码:在相关脚本中设置环境变量和资源

    1. run_snap.sh 中,编辑 APP_ARGS 变量以使用 SPDK 命令行参数 --wait-for-rpc

      run_snap.sh

      复制
      已复制!
                  

      APP_ARGS="--wait-for-rpc"

    2. set_environment_variables.sh 中,取消注释 SPDK_XLIO_PATH 环境变量

      set_environment_variables.sh

      复制
      已复制!
                  

      export SPDK_XLIO_PATH="/usr/lib/libxlio.so"

注意

NVMe/TCP XLIO 需要 4Gi 的 BlueField Arm OS 巨页大小。有关配置巨页的信息,请参阅 "步骤 1:分配巨页" 和 "调整 YAML 配置" 部分。

在大规模部署中,即使会导致高内存消耗,也需要使用全局变量 XLIO_RX_BUFS=4096。使用 XLIO_RX_BUFS=1024 需要较低的内存消耗,但会限制扩展工作负载的能力。

信息

更多信息请参考 "SNAP 环境变量" 部分。

提示

建议将 NVMe/TCP XLIO 配置为将传输 ack 超时选项增加到 12。

复制
已复制!
            

[dpu] spdk_rpc.py bdev_nvme_set_options --transport-ack-timeout 12

其他 bdev_nvme 选项可以根据需求进行调整。

通过在远程 SPDK 目标上使用 TCP 传输类型,公开具有一个命名空间的 NVMe-oF 子系统。

复制
已复制!
            

[dpu] spdk_rpc.py sock_set_default_impl -i xlio [dpu] spdk_rpc.py framework_start_init [dpu] spdk_rpc.py bdev_nvme_set_options --transport-ack-timeout 12 [dpu] spdk_rpc.py bdev_nvme_attach_controller -b nvme0 -t nvda_tcp -a 3.3.3.3 -f ipv4 -s 4420 -n nqn.2023-01.io.nvmet [dpu] snap_rpc.py nvme_subsystem_create --nqn nqn.2023-01.com.nvda:nvme:0 [dpu] snap_rpc.py nvme_namespace_create -b nvme0n1 -n 1 --nqn nqn. 2023-01.com.nvda:nvme:0 --uuid 16dab065-ddc9-8a7a-108e-9a489254a839 [dpu] snap_rpc.py nvme_controller_create --nqn nqn.2023-01.com.nvda:nvme:0 --ctrl NVMeCtrl1 --pf_id 0 --suspended --num_queues 16 [dpu] snap_rpc.py nvme_controller_attach_ns -c NVMeCtrl1 -n 1 [dpu] snap_rpc.py nvme_controller_resume -c NVMeCtrl1 -n 1   [host] modprobe -v nvme [host] fio --filename /dev/nvme0n1 --rw randrw --name=test-randrw --ioengine=libaio --iodepth=64 --bs=4k --direct=1 --numjobs=1 --runtime=63 --time_based --group_reporting --verify=md5

信息

有关 XLIO 的更多信息,请参考 XLIO 文档


加密

SNAP 附带的 SPDK 版本支持硬件加密/解密卸载。要启用 AES/XTS,请按照 "修改 SF 信任级别以启用加密" 部分下的说明进行操作。

零拷贝 (SNAP-direct) 与加密

SNAP 为使用 RDMA 传输的 bdev_nvme 提供对零拷贝和加密的支持。

注意

如果使用另一个 bdev_nvme 传输或 NVMe 以外的基础 bdev,则不支持零拷贝流,并且会执行从主机到 BlueField Arm 的额外 DMA 操作。

信息

请参考 "SPDK 加密示例" 部分,了解如何配置具有 AES_XTS 卸载的零拷贝流。

命令

描述

mlx5_scan_accel_module

接受用于加密操作的设备列表

accel_crypto_key_create

创建加密密钥

bdev_nvme_attach_controller

构建 NVMe 块设备

bdev_crypto_create

创建一个虚拟块设备,该设备加密写入 IO 命令并解密读取 IO 命令


mlx5_scan_accel_module

接受在 --allowed-devs 参数中提供的用于加密操作的设备列表。如果未指定任何设备,则使用第一个支持加密的设备。

为了获得最佳性能,建议使用具有最大 InfiniBand MTU (4096) 的设备。可以使用 ibv_devinfo 命令验证 MTU 大小(查找 max 和 active MTU 字段)。通常,mlx5_2 设备预计具有 4096 的 MTU,应将其用作允许的加密设备。

命令参数

参数

必填?

类型

描述

qp-size

数字

QP 大小

num-requests

数字

共享请求池的大小

allowed-devs

字符串

以逗号分隔的允许设备名称列表(例如,“mlx5_2”)

注意

确保选择用于 RDMA 流量的设备以支持零拷贝。

enable-driver

布尔值

启用 accel_mlx5 平台驱动程序。允许 AES_XTS RDMA 零拷贝。


accel_crypto_key_create

创建加密密钥。一个密钥可以由多个 bdev 共享。

命令参数

参数

必填?

类型

描述

cipher

数字

加密协议 (AES_XTS)

key

数字

密钥

key2

数字

密钥 2

name

字符串

密钥名称


bdev_nvme_attach_controller

创建 NVMe 块设备。

命令参数

参数

必填?

类型

描述

name

字符串

NVMe 控制器的名称,每个 bdev 名称的前缀

trtype

字符串

NVMe-oF 目标 trtype(例如,rdma、pcie)

traddr

字符串

NVMe-oF 目标地址(例如,IP 地址或 BDF)

trsvcid

字符串

NVMe-oF 目标 trsvcid(例如,端口号)

addrfam

字符串

NVMe-oF 目标 adrfam(例如,ipv4、ipv6)

nqn

字符串

NVMe-oF 目标 subnqn


bdev_crypto_create

此 RPC 创建一个虚拟加密块设备,该设备为基础块设备添加加密。

命令参数

参数

必填?

类型

描述

base_bdev_name

字符串

基础 bdev 的名称

name

字符串

加密 bdev 名称

key-name

字符串

使用 accel_crypto_key_create 创建的加密密钥的名称


SPDK 加密示例

以下是在 bdev_nvme 之上创建加密虚拟块设备的配置示例,该配置具有 RDMA 传输和零拷贝支持

复制
已复制!
            

[dpu] # spdk_rpc.py mlx5_scan_accel_module --allowed-devs "mlx5_2" --enable-driver [dpu] # spdk_rpc.py framework_start_init [dpu] # spdk_rpc.py accel_crypto_key_create -c AES_XTS -k 00112233445566778899001122334455 -e 11223344556677889900112233445500 -n test_dek [dpu] # spdk_rpc.py bdev_nvme_attach_controller -b nvme0 -t rdma -a 1.1.1.1 -f ipv4 -s 4420 -n nqn.2016-06.io.spdk:cnode0 [dpu] # spdk_rpc.py bdev_crypto_create nvme0n1 crypto_0 -n test_dek [dpu] # snap_rpc.py spdk_bdev_create crypto_0 [dpu] # snap_rpc.py nvme_subsystem_create --nqn nqn.2023-05.io.nvda.nvme:0 [dpu] # snap_rpc.py nvme_controller_create --nqn nqn.2023-05.io.nvda.nvme:0 --pf_id 0 --ctrl NVMeCtrl0 --suspended [dpu] # snap_rpc.py nvme_namespace_create –nqn nqn.2023-05.io.nvda.nvme:0 --bdev_name crypto_0 –-nsid 1 -–uuid 263826ad-19a3-4feb-bc25-4bc81ee7749e [dpu] # snap_rpc.py nvme_controller_attach_ns –-ctrl NVMeCtrl0 --nsid 1 [dpu] # snap_rpc.py nvme_controller_resume –-ctrl NVMeCtrl0

Virtio-blk 实时迁移

实时迁移是 QEMU 支持的标准流程,它允许系统管理员在实时运行的系统中在虚拟机之间传递设备。有关更多信息,请参阅 QEMU VFIO 设备迁移文档

SNAP virtio-blk 设备支持实时迁移。可以使用具有适当支持的驱动程序激活它(例如,NVIDIA 的专有 vDPA 实时迁移解决方案)。

复制
已复制!
            

snap_rpc.py virtio_blk_controller_create --dbg_admin_q …


SNAP 容器实时升级

实时升级允许更新容器使用的 SNAP 镜像,而不会导致 SNAP 容器停机。

虽然较新的 SNAP 版本可能会引入其他内容,这可能会在升级期间导致行为差异,但该过程旨在确保向后兼容性。同一子版本(例如,4.0.0-x 到 4.0.0-y)内的版本更新应顺利进行。

但是,跨不同主要版本或次要版本的更新可能需要更改系统组件(例如,固件、BFB),这可能会影响向后兼容性,并需要在更新后完全重启。在这些情况下,实时更新是不必要的。

实时升级先决条件

要启用实时升级,请执行以下修改

  1. 为目标容器和源容器分配双倍巨页。

  2. 确保请求的 CPU 核心数量可用。

    默认 YAML 配置将容器设置为请求 8-16 个 CPU 核心的范围。这意味着如果可用核心少于 8 个,则不会部署容器;如果有 16 个空闲核心,则容器将使用所有 16 个核心。

    例如,如果一个容器当前正在使用所有 16 个核心,并且在实时升级期间,部署了一个额外的 SNAP 容器。在这种情况下,每个容器在升级过程中使用 8 个核心。一旦源容器终止,目标容器开始使用所有 16 个核心。

    注意

    对于 8 核 DPU,必须将 .yaml 编辑为 4-8 个 CPU 核心的范围。

  3. 更改描述目标容器的 doca_snap.yaml 文件的名称(例如,doca_snap_new.yaml),以避免覆盖正在运行的容器 .yaml

  4. 在第 16 行中更改新的 .yaml pod 的名称(例如,snap-new)。

  5. 通过将新的 yaml 文件(例如,doca_snap_new.yaml)复制到 kubelet 来部署目标容器。

注意

部署目标容器后,在实时更新过程完成之前,避免通过 RPC 进行任何配置更改。具体来说,不要创建或销毁热插拔功能。

注意

在实时更新期间在目标容器中恢复控制器时,建议使用与源容器中最初用于控制器创建的参数相同的参数。


实时升级流程

实时升级 SNAP 镜像的方法是在不同容器之间移动 SNAP 控制器和 SPDK 块设备,同时最大限度地减少主机 VM 影响的持续时间。

live-upgrade-flow-diagram-version-1-modificationdate-1731488138287-api-v2.png

  • 源容器 – 实时升级前正在运行的容器

  • 目标容器 – 实时升级后正在运行的容器

SNAP 容器实时升级步骤

  1. 按照 "实时升级先决条件" 部分中的步骤,并使用修改后的 yaml 文件部署目标 SNAP 容器。

  2. 查询源容器和目标容器

    复制
    已复制!
                

    crictl ps -r

  3. 检查目标容器的日志中是否出现 SNAP started successfully,然后将实时更新从容器复制到您的环境。

    复制
    已复制!
                

    [dpu] crictl logs -f <dest-container-id> [dpu] crictl exec <dest-container-id> cp /opt/nvidia/nvda_snap/bin/live_update.py /etc/nvda_snap/

  4. 运行 live_update.py 脚本,将所有活动对象从源容器移动到目标容器

    复制
    已复制!
                

    [dpu] cd /etc/nvda_snap [dpu] ./live_update.py -s <source-container-id> -d <dest-container-id>

  5. 删除源容器。

    注意

    要发布 RPC,请使用 crictl 工具

    复制
    已复制!
                

    crictl exec -it <container-id X> snap_rpc.py <RPC-method> crictl exec -it <container-id Y> spdk_rpc.py <RPC-method>

    注意

    为了自动化 SNAP 配置(例如,在失败或重启后),如 "自动化 SNAP 配置(可选)" 部分所述,spdk_rpc_init.confsnap_rpc_init.conf 不得包含任何作为实时升级一部分的配置。然后,一旦完成到新容器的转换,就可以使用所需的配置修改 spdk_rpc_init.confsnap_rpc_init.conf

SNAP 容器实时升级命令

实时更新工具旨在支持快速实时更新。它迭代可用的仿真功能,并为每个功能执行以下操作

  1. 在源容器上

    复制
    已复制!
                

    snap_rpc.py virtio_blk_controller_suspend --ctrl [ctrl_name] --events_only

  2. 在目标容器上

    复制
    已复制!
                

    spdk_rpc.py bdev_nvme_attach_controller ... snap_rpc.py virtio_blk_controller_create ... --suspended --live_update_listener

  3. 在源容器上

    复制
    已复制!
                

    snap_rpc.py virtio_blk_controller_destroy --ctrl [ctrl_name] spdk_rpc.py bdev_nvme_detach_controller [bdev_name]

SR-IOV 动态 MSIX 管理

消息信号中断扩展 (MSIX) 是一种中断机制,允许设备使用多个中断向量,从而提供比传统中断机制(如共享中断)更高效的中断处理。在 Linux 中,内核支持 MSIX,并且 MSIX 通常用于高性能设备,例如网络适配器、存储控制器和图形卡。MSIX 具有诸如降低 CPU 利用率、提高设备性能和更好的可伸缩性等优点,使其成为现代硬件的常用选择。

然而,MSIX 中断的正确配置和管理可能具有挑战性,并且需要仔细调整才能实现最佳性能,尤其是在 SR-IOV 等多功能环境中。

默认情况下,BlueField 在所有虚拟 PCIe 功能 (VF) 之间均匀分配 MSIX 向量。这种方法不是最佳的,因为用户可以选择将 VF 附加到不同的 VM,每个 VM 具有不同数量的资源。动态 MSIX 管理允许用户独立地手动控制每个 VF 提供的 MSIX 向量的数量。

注意

所有仿真类型(特别是 NVMe 和 virtio-blk)的配置和行为都相似。

动态 MSIX 管理由几个配置步骤构建而成

  1. 此时,以及将来任何时候未打开 VF 控制器(sriov_numvfs=0)时,所有 PF 相关的 MSIX 向量都可以从 VF 回收到 PF 的可用 MSIX 池。

  2. 用户必须在 VF 控制器创建期间从可用池中获取一些 MSIX,并将它们提供给特定的 VF。

  3. 销毁 VF 控制器时,用户可以选择将其 MSIX 释放回池中。

配置完成后,MSIX 到 VF 的链接将保持持久性,并且仅在以下情况下可能会更改

  • 用户在控制器销毁期间明确请求将 VF MSIX 返回到池中。

  • PF 明确地将所有 VF MSIX 回收到池中。

  • 发生了 Arm 重启(FE 重置/冷启动)。

为了强调,以下情况不会更改 MSIX 配置

  • 应用程序重启/崩溃。

  • 在没有动态 MSIX 支持的情况下关闭和重新打开 PF/VF。

以下是动态 MSIX 配置步骤的 NVMe 示例(类似的配置也适用于 virtio-blk)

  1. 将所有 VF 的 MSIX 回收至 PF 的可用 MSIX 池

    复制
    已复制!
                

    snap_rpc.py nvme_controller_vfs_msix_reclaim <CtrlName>

  2. 查询控制器列表以获取有关 PF 资源约束的信息

    复制
    已复制!
                

    # snap_rpc.py nvme_controller_list -c <CtrlName> …     'free_msix': 100, …     'free_queues': 200, …     'vf_min_msix': 2, …     'vf_max_msix': 64, …     'vf_min_queues': 0, …     'vf_max_queues': 31, …

    其中

    • free_msix 表示 PF 的可用池中可用的 MSIX 总数,通过参数 vf_num_msix<protocol>_controller_create RPC 的参数)分配给 VF。

    • free_queues 表示 PF 的可用池中可用的队列(或“门铃”)总数,通过参数 num_queues<protocol>_controller_create RPC 的参数)分配给 VF。

    • vf_min_msixvf_max_msix 共同定义了 vf_num_msix 参数值的可用可配置范围,该参数值可以在 <protocol>_controller_create RPC 中为每个 VF 传递。

    • vf_min_queuesvf_max_queues 共同定义了 num_queues 参数值的可用可配置范围,该参数值可以在 <protocol>_controller_create RPC 中为每个 VF 传递。

  3. 在 VF 的创建过程中,考虑到 PF 的限制,在 VF 之间分配 MSIX

    复制
    已复制!
                

    snap_rpc.py nvme_controller_create_ --vf_num_msix <n> --num_queues <m> …

    注意

    强烈建议在 VF 控制器创建时同时提供 vf_num_msixnum_queues 参数。仅提供其中一个值可能会导致 MSIX 和队列配置之间发生冲突,这反过来可能会导致控制器/驱动程序发生故障。

    提示

    在 NVMe 协议中,MSIX 由 NVMe CQ 使用。因此,建议为每个分配的队列从 PF 的全局池 (free_msix) 中分配 1 个 MSIX。

    在 virtio 协议中,MSIX 由 virtqueue 使用,并且 BAR 配置更改通知需要一个额外的 MSIX。因此,建议为每个分配的队列从 PF 的全局池 (free_msix) 中分配 1 个 MSIX,再分配一个作为配置 MSIX。

    总而言之,队列/MSIX 比率配置的最佳实践是

    • 对于 NVMe – num_queues = vf_num_msix

    • 对于 virtio – num_queues = vf_num_msix-1

  4. 在 VF 拆卸时,将 MSIX 释放回可用池

    复制
    已复制!
                

    snap_rpc.py nvme_controller_destroy_ --release_msix …

  5. 在主机驱动程序上设置 SR-IOV

    复制
    已复制!
                

    echo <N> > /sys/bus/pci/devices/<BDF>/sriov_numvfs

    注意

    强烈建议在将 VF 绑定到主机/客户机驱动程序之前,预先在 SNAP 中打开所有 VF 控制器。这样,例如,如果配置错误导致没有为所有 VF 留下足够的 MSIX,则配置仍然是可逆的,因为 MSIX 仍然是可修改的。否则,驱动程序可能会尝试在所有 VF 配置完成之前使用已配置的 VF,但将无法使用所有 VF(由于缺少 MSIX)。后一种情况可能会导致主机死锁,在最坏的情况下,只能通过冷启动恢复。

    注意

    有几种方法可以安全地配置动态 MSIX(无需 VF 绑定)

    1. 禁用内核驱动程序自动将 VF 绑定到内核驱动程序

      复制
      已复制!
                  

      # echo 0 > /sys/bus/pci/devices/sriov_driver_autoprobe

      在完成所有 VF 的 MSIX 配置后,可以将它们绑定到 VM,甚至绑定回 hypervisor

      复制
      已复制!
                  

      echo "0000:01:00.0" > /sys/bus/pci/drivers/nvme/bind

    2. 使用 VFIO 驱动程序(而不是内核驱动程序)进行 SR-IOV 配置。

    例如

    复制
    已复制!
                

    # echo 0000:af:00.2 > /sys/bus/pci/drivers/vfio-pci/bind # Bind PF to VFIO driver # echo 1 > /sys/module/vfio_pci/parameters/enable_sriov # echo <N> > /sys/bus/pci/drivers/vfio-pci/0000:af:00.2/sriov_numvfs # Create VFs device for it

恢复

NVMe 恢复

NVMe 恢复允许在 SNAP 应用程序关闭后(无论是正常关闭还是崩溃后,例如 kill -9)恢复 NVMe 控制器。

要使用 NVMe 恢复,必须在挂起状态下重新创建控制器,并使用与崩溃前相同的配置(即,相同的 bdev、队列数和具有相同 uuid 的命名空间等)。

注意

只有在附加所有 NS 后才能恢复控制器。

NVMe 恢复使用 BlueField 上 /dev/shm 下的文件来恢复控制器的内部状态。当 BlueField 重置时,共享内存文件将被删除。因此,BF 重置后不支持恢复。

Virtio-blk 崩溃恢复

以下选项可用于启用 virtio-blk 崩溃恢复。

使用 --force_in_order 的 Virtio-blk 崩溃恢复

对于使用 --force_in_order 的 virtio-blk 崩溃恢复,禁用 VBLK_RECOVERY_SHM 环境变量,并使用 --force_in_order 参数创建控制器。

在 virtio-blk SNAP 中,应用程序不能保证在突然崩溃(例如 kill -9)后正确恢复。

要启用 virtio-blk 崩溃恢复,请设置以下内容

复制
已复制!
            

snap_rpc.py virtio_blk_controller_create --force_in_order …

注意

force_in_order 设置为 1 可能会影响 virtio-blk 性能,因为它将按顺序处理命令。

注意

如果未使用 --force_in_order,由于 Linux 内核 virtio-blk 驱动程序中的支持有限,SNAP 或驱动程序中的任何故障或意外拆卸都可能导致异常行为。


Virtio-blk 无需 --force_in_order 的崩溃恢复

对于无需 --force_in_order 的 virtio-blk 崩溃恢复,启用 VBLK_RECOVERY_SHM 环境变量,并创建一个不带 --force_in_order 参数的控制器。

Virtio-blk 恢复允许在 SNAP 应用程序关闭后(无论是正常关闭还是崩溃后,例如 kill -9)恢复 virtio-blk 控制器。

要使用无需 --force_in_order 标志的 virtio-blk 恢复,必须启用 VBLK_RECOVERY_SHM,并且必须使用与崩溃前相同的配置(即相同的 bdev、队列数等)重新创建控制器。

当启用 VBLK_RECOVERY_SHM 时,virtio-blk 恢复使用 BlueField 上 /dev/shm 中的文件来恢复控制器的内部状态。当 BlueField 重置时,共享内存文件将被删除。因此,BlueField 重置后不支持恢复。

SNAP 配置恢复

SNAP 配置恢复机制目前支持 virtio-blk,并允许使用已保存的配置文件恢复 SNAP 的状态。此功能允许 SNAP 在重启时重新加载其先前的状态,而无需通过 RPC 重新配置。

注意

此恢复过程不能用于 SNAP 的初始配置。

注意

热插拔仿真功能在 SNAP 运行之间(而不是跨 BlueField 重置)持续存在,并且仅需要在初始配置期间设置。在这些功能上创建的控制器将被保存和恢复。

配置恢复步骤

  1. 设置环境变量

    1. 为环境变量 SNAP_RPC_INIT_CONF_JSON 定义一个目录路径。

      • 该目录应该是临时的,并在 BlueField 重置后清除(例如,/dev/shm),因为配置在重置后将失效。

      • 如果在重启 SNAP 后需要新配置,请删除此目录中现有的 snap_config.json 文件。

    2. SPDK_RPC_INIT_CONF_JSON 设置文件路径。对于首次运行,这应指向现有的配置文件

      复制
      已复制!
                  

      export SPDK_RPC_INIT_CONF_JSON=<spdk_config.json>

  2. 创建并保存所需的配置

    1. 使用 SPDK/SNAP RPC 来配置所需的状态。

    2. 保存配置

      复制
      已复制!
                  

      spdk_rpc.py save_config > <spdk_config.json>

      这确保仅在所有更改都已成功应用后才保存配置。

  3. 使用已保存的配置重启 SNAP

    • 重启 SNAP 后,它将自动从 SNAP_RPC_INIT_CONF_JSON 文件加载配置。

    • 在初始配置之后,无需重新运行 SNAP RPC 或在初始化文件中设置 RPC。

此方法通过避免重新配置的需要,显著提高了恢复时间。

警告

确保在对控制器或功能配置进行任何更改期间,驱动程序保持卸载状态。如果配置更改未成功完成,则不这样做可能会导致恢复过程失败。

注意

如果在重启 SNAP 后配置发生显著更改,请删除现有的配置文件 (snap_config.json) 并设置一个新的配置文件,以避免无效的配置。


提高 SNAP 恢复时间

下表概述了旨在加速 SNAP 初始化和终止后恢复过程的功能。

功能

描述

如何操作?

SPDK JSON-RPC 配置文件

可以为 SNAP 中 SPDK 配置指定初始配置。配置文件是一个 JSON 文件,其中包含所需配置的所有 SPDK JSON-RPC 方法调用。从发布 RPC 到 JSON 文件可以缩短启动时间。

信息

有关更多信息,请查看 SPDK JSON-RPC 文档。

要基于当前配置生成 JSON-RPC 文件,请运行

复制
已复制!
            

spdk_rpc.py save_config > config.json

config.json 文件随后可以使用 YAML 中的环境变量 SPDK_RPC_INIT_CONF_JSON 传递给新的 SNAP 部署。

注意

如果 SPDK 在处理 JSON 配置文件时遇到错误,则初始化阶段将失败,导致 SNAP 以错误代码退出。

禁用 SPDK accel 功能

当使用 NVMe TCP 功能时,SPDK accel 功能是必需的。如果未使用 NVMe TCP,则应手动禁用 accel 以减少 SPDK 启动时间,否则可能需要几秒钟。要禁用所有 accel 功能,请编辑标志 disable_signaturedisable_cryptoenable_module

按如下所示编辑配置文件

复制
已复制!
            

{ "method": "mlx5_scan_accel_module", "params": { "qp_size": 64, "cq_size": 1024, "num_requests": 2048, "enable_driver": false, "split_mb_blocks": 0, "siglast": false, "qp_per_domain": false, "disable_signature": true, "disable_crypto": true, "enable_module": false }

提供仿真管理器名称

如果未定义 SNAP_EMULATION_MANAGER 环境变量(默认),SNAP 将搜索所有可用设备以查找仿真管理器,这可能会减慢初始化过程。显式定义设备可减少初始化延迟的可能性。

使用 SNAP_EMULATION_MANAGER 修改 YAML 上的变量。请参阅“SNAP 环境变量”页面以获取更多信息。

virtio-blk 的 DPU 模式

DPU 模式仅在使用 virtio-blk 时受支持。DPU 模式减少了崩溃恢复期间的 SNAP 停机时间。

设置 VIRTIO_EMU_PROVIDER=dpu 以修改 YAML 上的变量。请参阅“SNAP 环境变量”页面以获取更多信息。

virtio-blk 的 SNAP 配置恢复

SNAP 配置恢复使恢复 SNAP 状态成为可能,而无需重新发布 SNAP RPC。通过从发布单个 RPC 转移到使用预先保存的 JSON 配置文件,启动时间得到了显著提高。

SNAP_RPC_INIT_CONF_JSON 设置为应保存配置文件的路径。同时使用 SPDK JSON-RPC 配置文件。

SNAP ML 优化器

SNAP ML 优化器是一个旨在微调 SNAP 轮询器参数的工具,可根据特定环境和工作负载增强 SNAP I/O 处理性能并提高控制器吞吐量。

在工作负载执行期间,优化器迭代地调整配置(操作)并评估其对性能(奖励)的影响。通过预测下一个要测试的最佳配置,它可以有效地缩小到最佳设置,而无需探索每种可能的组合。

一旦确定了最佳配置,就可以将其应用于目标系统,从而提高类似条件下的性能。目前,该工具支持“IOPS”作为奖励指标,其目标是最大化 IOPS。

SNAP ML 优化器准备步骤

机器要求

设备应能够 SSH 连接到 BlueField

  • Python 3.10 或更高版本

  • 至少 6 GB 的可用存储空间

设置 SNAP ML 优化器

要设置 SNAP ML 优化器

  1. snap_ml 文件夹从容器复制到共享的 nvda_snap 文件夹,然后再复制到请求的机器

    复制
    已复制!
                

    crictl exec -it $(crictl ps -s running -q --name snap) cp -r /opt/nvidia/nvda_snap/bin/snap_ml /etc/nvda_snap/

  2. 将目录更改为 snap_ml 文件夹

    复制
    已复制!
                

    cd tools/snap_ml

  3. 为 SNAP ML 优化器创建一个虚拟环境。

    复制
    已复制!
                

    python3 -m venv snap_ml

    这确保所需的依赖项安装在隔离的环境中。

  4. 激活虚拟环境以开始在此隔离环境中工作

    复制
    已复制!
                

    source snap_ml/bin/activate 

  5. 安装 Python 包要求

    复制
    已复制!
                

    pip3 install --no-cache-dir -r requirements.txt

    这可能需要一些时间,具体取决于您的系统性能。

  6. 运行 SNAP ML 优化器。

    复制
    已复制!
                

    python3 snap_ml.py --help

    使用 --help 标志查看可用选项和用法信息

    复制
    已复制!
                

    --version Show the version and exit.  -f, --framework <TEXT> Name of framework (Recommended: ax , supported: ax, pybo). -t, --total-trials <INTEGER> Number of optimization iterations. The recommended range is 25-60.  --filename <TEXT> where to save the results (default: last_opt.json).  --remote <TEXT> connect remotely to the BlueField card, format: <bf_name>:<username>:<password>  --snap-rpc-path <TEXT> Snap RPC prefix (default: container path).  --log-level <TEXT> CRITICAL | ERROR | WARN | WARNING | INFO | DEBUG  --log-dir <TEXT> where to save the logs. 

SNAP ML 优化器相关 RPC

snap_actions_set

snap_actions_set 命令用于动态调整 SNAP 参数(称为“操作”),这些参数控制轮询行为。此命令是 SNAP-AI 工具的核心功能,可实现特定环境和工作负载的自动优化,以及轮询参数的手动调整。

命令参数

参数

必填?

类型

描述

poll_size

数字

SNAP 在单个轮询周期中传递的最大 IO 数量(整数;1-256)

poll_ratio

数字

SNAP 轮询周期发生的速率(浮点数;0<poll_ratio≤1)

max_inflights

数字

每个核心的最大飞行中 IO 数量(整数;1-65535)

max_iog_batch

数字

最大公平性批处理大小(整数;1-4096)

max_new_ios

数字

在单个轮询周期中处理的最大新 IO 数量(整数;1-4096)


snap_reward_get

snap_reward_get 命令检索性能计数器,特别是完成计数器(或“奖励”),优化器使用这些计数器来监视和增强 SNAP 性能。

此命令不需要参数。

为 ML 优化器优化 SNAP 参数

要优化 SNAP 的参数以适应您的环境,请使用以下命令

复制
已复制!
            

python3 snap_ml.py --framework ax --total-trials 40 --filename example.json --remote <bf_hostname>:<username>:<password> --log-dir <log_directory> 

结果和优化后操作

优化过程完成后,该工具会自动应用优化的参数。这些参数也以 example.json 文件格式保存在以下位置

复制
已复制!
            

{      "poll_size": 30,      "poll_ratio": 0.6847347955107689,      "max_inflights": 32768,      "max_iog_batch": 512,      "max_new_ios": 32  } 

此外,该工具还在名为 example_<timestamp>.json 的带时间戳的文件中记录所有迭代,包括所采取的操作和收到的奖励。

手动应用优化的参数

用户可以通过显式调用 snap_actions_set RPC 并使用优化的参数,在 SNAP 服务的新实例上应用优化的参数,如下所示

复制
已复制!
            

snap_rpc.py snap_actions_set –poll_size 30 –poll_ratio 0.6847 --max_inflights 32768 –max_iog_batch 512 –max_new_ios 32 

注意

仅当预期系统行为与使用 SNAP ML 优化器的系统相似时,才建议使用优化的参数。


停用 Python 环境

用户完成 SNAP ML 优化器的使用后,可以通过运行以下命令停用 Python 虚拟环境

复制
已复制!
            

deactivate

插件

插件是模块化组件或附加组件,可增强 SNAP 应用程序的功能。它们与主软件无缝集成,允许添加其他功能,而无需更改核心代码库。插件设计为仅与源代码包一起使用,因为它允许在构建过程中进行自定义,例如根据需要启用或禁用插件。

在容器化环境中,SNAP 应用程序作为具有固定配置的预构建二进制文件交付。由于容器中的二进制文件是预编译的,因此无法添加或删除插件。容器化软件仅支持在其构建期间包含的插件。对于需要插件灵活性的环境(例如添加自定义插件),必须使用源代码包。

要构建带有插件的 SNAP 源代码包,请执行以下操作,而不是遵循 基本构建步骤

  1. 移动到源码文件夹。运行

    复制
    已复制!
                

    cd /opt/nvidia/nvda_snap/src/

  2. 构建要启用插件的源代码。运行

    复制
    已复制!
                

    meson setup /tmp/build -Denable-bdev-null=true -Denable-bdev-malloc=true

  3. 编译源码。运行

    复制
    已复制!
                

    meson compile -C /tmp/build

  4. 安装源码。运行

    复制
    已复制!
                

    meson install -C /tmp/build

  5. 配置 SNAP 环境变量并运行 SNAP 服务,如“配置 SNAP 环境变量”和“运行 SNAP 服务”部分中所述。

Bdev

SNAP 支持各种类型的块设备 (bdev),在与存储后端交互时提供灵活性和可扩展性。这些 bdev 插件提供不同的存储仿真选项,允许自定义,而无需修改核心软件。

SPDK

  • SPDK 是 SNAP 使用的默认插件。如果未显式指定特定插件,SNAP 将默认使用 SPDK 进行块设备操作。

  • 有关更多信息,请参阅 spdk_bdev

Malloc

  • Malloc 插件仅用于性能分析和调试目的;它不适合生产环境使用

  • 它通过在内存中分配缓冲区并将其作为块设备公开来创建内存支持的块设备

  • 由于数据存储在内存中,因此在系统关闭时会丢失

  • 可以使用 enable-bdev-malloc 构建选项启用此插件

Malloc 配置示例

  1. 创建 Malloc bdev 并将其与 NVMe 控制器一起使用

    复制
    已复制!
                

    # snap_rpc.py snap_bdev_malloc_create --bdev test 64 512 # snap_rpc.py nvme_subsystem_create -s nqn.2020-12.mlnx.snap # snap_rpc.py nvme_namespace_create -s nqn.2020-12.mlnx.snap -t malloc -b test -n 1 # snap_rpc.py nvme_controller_create --pf_id=0 -s nqn.2020-12.mlnx.snap --mdts=7 # snap_rpc.py nvme_controller_attach_ns -c NVMeCtrl1 -n 1

  2. 删除 Malloc bdev

    复制
    已复制!
                

    # snap_rpc.py snap_bdev_malloc_destroy test

  3. 调整 Malloc bdev 大小

    复制
    已复制!
                

    # snap_rpc.py snap_bdev_malloc_resize test 32

    这将删除现有的 bdev 并创建一个具有指定大小的新 bdev。现有 bdev 上的数据将丢失。

NULL

  • NULL 插件专为性能分析和调试目的而设计,不适用于生产环境。

  • 它充当虚拟块设备,接受 I/O 请求并仿真块设备,而无需执行实际的 I/O 操作。

  • 它适用于不涉及真实存储设备的测试或基准测试场景。

  • 该插件消耗最少的系统资源。

  • 可以使用 enable-bdev-null 构建选项启用它。

NULL 配置示例

  1. 创建 NULL bdev 并将其与 NVMe 控制器一起使用

    复制
    已复制!
                

    # snap_rpc.py snap_bdev_null_create_dbg test 1 512 # snap_rpc.py nvme_subsystem_create -s nqn.2020-12.mlnx.snap # snap_rpc.py nvme_namespace_create -s nqn.2020-12.mlnx.snap -t malloc -b test -n 1 # snap_rpc.py nvme_controller_create --pf_id=0 -s nqn.2020-12.mlnx.snap --mdts=7 # snap_rpc.py nvme_controller_attach_ns -c NVMeCtrl1 -n 1

  2. 删除 NULL bdev

    复制
    已复制!
                

    # snap_rpc.py snap_bdev_null_destroy_dbg test

在配置 SNAP 之前,用户必须确保满足所有固件配置要求。默认情况下,SNAP 处于禁用状态,必须通过运行常见的 SNAP 配置以及额外的协议特定配置来启用,具体取决于应用程序的预期用途(例如,热插拔、SR-IOV、UEFI 启动等)。

配置完成后,必须对主机进行电源循环,以使更改生效。

注意

要验证是否满足所有配置要求,用户可以运行以下命令查询当前/下一个配置

复制
已复制!
            

mlxconfig -d /dev/mst/mt41692_pciconf0 -e query

系统配置参数

参数

描述

可能的值

INTERNAL_CPU_MODEL

启用 BlueField 以在内部 CPU 模型中工作

注意

对于存储仿真,必须设置为 1

0/1

SRIOV_EN

启用 SR-IOV

0/1

PCI_SWITCH_EMULATION_ENABLE

为仿真的 PF 启用 PCI 交换机

0/1

PCI_SWITCH_EMULATION_NUM_PORT

热插拔仿真 PF 的最大数量,等于 PCI_SWITCH_EMULATION_NUM_PORT–1。例如,如果 PCI_SWITCH_EMULATION_NUM_PORT=32,则热插拔仿真 PF 的最大数量将为 31。

注意

一个交换机端口保留给所有静态 PF。

[0,2-32]

注意

SRIOV_EN 仅对静态 PF 有效。


RDMA/RoCE 配置

BlueField 的 RDMA/RoCE 通信被阻止用于 BlueField 的默认 OS 接口(命名为 ECPF,通常为 mlx5_0 和 mlx5_1)。如果需要 RoCE 流量,则必须添加支持 RDMA/RoCE 流量的附加网络功能(可扩展功能)。

注意

通过 TCP 甚至 RDMA/IB 工作时,不需要以下内容。

要启用 RoCE 接口,请从 DPU 内运行以下命令

复制
已复制!
            

[dpu] mlxconfig -d /dev/mst/mt41692_pciconf0 s PER_PF_NUM_SF=1 [dpu] mlxconfig -d /dev/mst/mt41692_pciconf0 s PF_SF_BAR_SIZE=8 PF_TOTAL_SF=2 [dpu] mlxconfig -d /dev/mst/mt41692_pciconf0.1 s PF_SF_BAR_SIZE=8 PF_TOTAL_SF=2


NVMe 配置

参数

描述

可能的值

NVME_EMULATION_ENABLE

启用 NVMe 设备仿真

0/1

NVME_EMULATION_NUM_PF

静态仿真 NVMe PF 的数量

[0-4]

NVME_EMULATION_NUM_MSIX

分配给仿真 NVMe PF 的 MSIX 数量

注意

固件将此值视为尽力而为的值。分配给函数的有效 MSI-X 数量应作为 nvme_controller_list RPC 命令的一部分进行查询。

[0-63]

NVME_EMULATION_NUM_VF_MSIX

每个仿真 NVMe VF 的 MSIX 数量

注意

固件将此值视为尽力而为的值。分配给函数的有效 MSI-X 数量应作为 nvme_controller_list RPC 命令的一部分进行查询。

注意

此值应与通过 nvme_controller_create num_queues 参数分配给 VF 的 NVMe SNAP 控制器的最大队列数匹配,因为每个队列都需要一个 MSIX 中断。

[0-4095]

NVME_EMULATION_NUM_VF

每个仿真 NVMe PF 的 VF 数量

注意

如果非 0,则覆盖 NUM_OF_VFS;仅当 SRIOV_EN=1 时有效。

[0-256]

EXP_ROM_NVME_UEFI_x86_ENABLE

启用 NVMe UEFI exprom 驱动程序

注意

用于 UEFI 启动过程。

0/1

Virtio-blk 配置

警告

由于 virtio-blk 协议的限制,使用错误的配置与静态 virtio-blk PF 一起工作可能会导致主机服务器操作系统在启动时失败。

在继续之前,请确保您已配置

  • 即使主机关闭,也可以访问 Arm 的工作通道。设置此类通道不在本文档的范围内。请参阅 NVIDIA BlueField DPU BSP 文档以获取更多详细信息。

  • 将以下行添加到 /etc/nvda_snap/snap_rpc_init.conf

    复制
    已复制!
                

    virtio_blk_controller_create –pf_id 0

    有关更多信息,请参阅“Virtio-blk 仿真管理”部分。

参数

描述

可能的值

VIRTIO_BLK_EMULATION_ENABLE

启用 virtio-blk 设备仿真

0/1

VIRTIO_BLK_EMULATION_NUM_PF

静态仿真 virtio-blk PF 的数量

注意

请参阅上面的警告。

[0-4]

VIRTIO_BLK_EMULATION_NUM_MSIX

分配给仿真 virtio-blk PF 的 MSIX 数量

注意

固件将此值视为尽力而为的值。分配给函数的有效 MSI-X 数量应作为 virtio_blk_controller_list RPC 命令的一部分进行查询。

[0-63]

VIRTIO_BLK_EMULATION_NUM_VF_MSIX

每个仿真 virtio-blk VF 的 MSIX 数量

注意

固件将此值视为尽力而为的值。分配给函数的有效 MSI-X 数量应作为 virtio_blk_controller_list RPC 命令的一部分进行查询。

注意

此值应与通过 nvme_controller_create num_queues 参数分配给 VF 的 NVMe SNAP 控制器的最大队列数匹配,因为每个队列都需要一个 MSIX 中断。

[0-4095]

VIRTIO_BLK_EMULATION_NUM_VF

每个仿真 virtio-blk PF 的 VF 数量

注意

如果非 0,则覆盖 NUM_OF_VFS;仅当 SRIOV_EN=1 时有效

[0-2000]

EXP_ROM_VIRTIO_BLK_UEFI_x86_ENABLE

启用 virtio-blk UEFI exprom 驱动程序

注意

用于 UEFI 启动过程。

0/1


要配置持久网络接口,以便它们在重启后不会丢失。在 /etc/sysconfig/network-scripts 下修改以下四个文件,如果不存在则创建它们,然后执行重启

复制
已复制!
            

# cd /etc/sysconfig/network-scripts/ # cat ifcfg-p0 NAME="p0" DEVICE="p0" NM_CONTROLLED="no" DEVTIMEOUT=30 PEERDNS="no" ONBOOT="yes" BOOTPROTO="none" TYPE=Ethernet MTU=9000   # cat ifcfg-p1 NAME="p1" DEVICE="p1" NM_CONTROLLED="no" DEVTIMEOUT=30 PEERDNS="no" ONBOOT="yes" BOOTPROTO="none" TYPE=Ethernet MTU=9000   # cat ifcfg-enp3s0f0s0 NAME="enp3s0f0s0" DEVICE="enp3s0f0s0" NM_CONTROLLED="no" DEVTIMEOUT=30 PEERDNS="no" ONBOOT="yes" BOOTPROTO="static" TYPE=Ethernet IPADDR=1.1.1.1 PREFIX=24 MTU=9000   # cat ifcfg-enp3s0f1s0 NAME="enp3s0f1s0" DEVICE="enp3s0f1s0" NM_CONTROLLED="no" DEVTIMEOUT=30 PEERDNS="no" ONBOOT="yes" BOOTPROTO="static" TYPE=Ethernet IPADDR=1.1.1.2 PREFIX=24 MTU=9000

SNAP 源代码包包含使用自定义 SPDK 构建容器所需的文件。

要构建容器

  1. 下载并安装 SNAP 源代码包

    复制
    已复制!
                

    [dpu] # dpkg -i /path/snap-sources_<version>_arm64.deb

  2. 导航到 src 文件夹并将其用作开发环境

    复制
    已复制!
                

    [dpu] # cd /opt/nvidia/nvda_snap/src

  3. 将以下内容复制到容器文件夹

    • SNAP 源代码包 – 在容器内部安装 SNAP 所必需

    • 自定义 SPDK – 到 container/spdk。例如

      复制
      已复制!
                  

      [dpu] # cp /path/snap-sources_<version>_arm64.deb container/ [dpu] # git clone -b v23.01.1 --single-branch --depth 1 --recursive --shallow-submodules https://github.com/spdk/spdk.git container/spdk

  4. 如果需要,修改 spdk.sh 文件,因为它用于编译 SDPK。

  5. 要构建容器

    • 对于 Ubuntu,运行

      复制
      已复制!
                  

      [dpu] # ./container/build_public.sh --snap-pkg-file=snap-sources_<version>_arm64.deb

    • 对于 CentOS,运行

      复制
      已复制!
                  

      [dpu] # rpm -i snap-sources-<version>.el8.aarch64.rpm [dpu] # cd /opt/nvidia/nvda_snap/src/ [dpu] # cp /path/snap-sources_<version>_arm64.deb container/ [dpu] # git clone -b v23.01.1 --single-branch --depth 1 --recursive --shallow-submodules https://github.com/spdk/spdk.git container/spdk [dpu] # yum install docker-ce docker-ce-cli [dpu] # ./container/build_public.sh --snap-pkg-file=snap-sources_<version>_arm64.deb

  6. 将创建的映像从 Docker 工具传输到 crictl 工具。运行

    复制
    已复制!
                

    [dpu] # docker save doca_snap:<version> doca_snap.tar [dpu] # ctr -n=k8s.io images import doca_snap.tar

    注意

    要将容器映像传输到其他设置,请参阅附录“附录 - 在没有互联网连接的设置上部署容器”。

  7. 要验证映像,请运行

    复制
    已复制!
                

    [DPU] # crictl images IMAGE TAG IMAGE ID SIZE docker.io/library/doca_snap <version> 79c503f0a2bd7 284MB

  8. 编辑 container/doca_snap.yaml 文件中的 image 字段。运行

    复制
    已复制!
                

    image: doca_snap:<version>

  9. 使用 YAML 文件部署容器。运行

    复制
    已复制!
                

    [dpu] # cp doca_snap.yaml /etc/kubelet.d/

    注意

    容器部署 准备步骤 是必需的。

当 DPU 上没有互联网连接时,Kubelet 在检测到 SNAP YAML 时会在本地扫描容器映像。用户可以在部署之前手动加载容器映像。

为了实现这一点,用户必须使用具有互联网连接的 DPU 下载必要的资源,然后将其传输并加载到缺少互联网连接的 DPU 上。

  1. 要下载 .yaml 文件

    复制
    已复制!
                

    [bf] # wget --content-disposition https://api.ngc.nvidia.com/v2/resources/nvidia/doca/doca_container_configs/versions/<path-to-yaml>/doca_snap.yaml

    注意

    通过访问 https://catalog.ngc.nvidia.com/orgs/nvidia/teams/doca/containers/doca_snap,在 NGC 上访问最新的下载命令。SNAP 标签 doca_snap:4.1.0-doca2.0.2 在本节中用作示例。最新标签也可在 NGC 上找到。

  2. 要下载 SNAP 容器映像

    复制
    已复制!
                

    [bf] # crictl pull nvcr.io/nvidia/doca/doca_snap:4.1.0-doca2.0.2

  3. 要验证 SNAP 容器映像是否存在

    复制
    已复制!
                

    [bf] # crictl images   IMAGE TAG IMAGE ID SIZE nvcr.io/nvidia/doca/doca_snap 4.1.0-doca2.0.2 9d941b5994057 267MB k8s.gcr.io/pause 3.2 2a060e2e7101d 251kB

    注意

    SNAP 容器需要 k8s.gcr.io/pause 映像。

  4. 要将映像另存为 .tar 文件

    复制
    已复制!
                

    [bf] # mkdir images [bf] # ctr -n=k8s.io image export images/snap_container_image.tar nvcr.io/nvidia/doca/doca_snap:4.1.0-doca2.0.2 [bf] # ctr -n=k8s.io image export images/pause_image.tar k8s.gcr.io/pause:3.2

  5. 传输 .tar 文件并运行以下命令以将其加载到 Kubelet 中

    复制
    已复制!
                

    [bf] # sudo ctr --namespace k8s.io image import images/snap_container_image.tar [bf] # sudo ctr --namespace k8s.io image import images/pause_image.tar

  6. 现在,该映像已存在于工具中,可以进行部署了。

    复制
    已复制!
                

    [bf] # crictl images IMAGE TAG IMAGE ID SIZE nvcr.io/nvidia/doca/doca_snap 4.1.0-doca2.0.2 9d941b5994057 267MB k8s.gcr.io/pause 3.2 2a060e2e7101d 251kB

要构建用于 SNAP 集成的 SPDK-19.04

  1. Cherry-pick 用于 SPDK 共享库安装的关键修复程序(最初仅在 v19.07 以后的上游应用)。

    复制
    已复制!
                

    [spdk.git] git cherry-pick cb0c0509

  2. 配置 SPDK

    复制
    已复制!
                

    [spdk.git] git submodule update --init [spdk.git] ./configure --prefix=/opt/mellanox/spdk --disable-tests --without-crypto --without-fio --with-vhost --without-pmdk --without-rbd --with-rdma --with-shared --with-iscsi-initiator --without-vtune [spdk.git] sed -i -e 's/CONFIG_RTE_BUILD_SHARED_LIB=n/CONFIG_RTE_BUILD_SHARED_LIB=y/g' dpdk/build/.config

    注意

    标志 --prefix--with-rdma--with-shared 是强制性的。

  3. 制作 SPDK(和 DPDK 库)

    复制
    已复制!
                

    [spdk.git] make && make install [spdk.git] cp dpdk/build/lib/* /opt/mellanox/spdk/lib/ [spdk.git] cp dpdk/build/include/* /opt/mellanox/spdk/include/

PCIe BDF(总线、设备、功能)是分配给连接到计算机的每个 PCIe 设备的唯一标识符。通过使用唯一的 BDF 编号标识每个设备,计算机的操作系统可以高效且有效地管理系统的资源。

PCIe BDF 值由主机操作系统确定,因此可能会在不同的运行之间甚至在单次运行中发生更改。因此,BDF 标识符不是永久配置的最佳选择。

为了克服这个问题,NVIDIA 设备向 PCIe 属性添加了一个扩展,称为 VUID。与 BDF 相比,VUID 在运行之间是持久的,这使其可用作 PCIe 功能标识符。

可以使用 lspci 命令从另一个中提取 PCI BDF 和 VUID

  1. 要从 BDF 中提取 VUID

    复制
    已复制!
                

    [host] lspci -s <BDF> -vvv | grep -i VU | awk '{print $4}'

  2. 要从 VUID 中提取 BDF

    复制
    已复制!
                

    [host] ./get_bdf.py <VUID> [host] cat ./get_bdf.py #!/usr/bin/python3   import subprocess import sys   vuid = sys.argv[1]   # Split the output into individual PCI function entries lspci_output = subprocess.check_output(['lspci']).decode().strip().split('\n')   # Create an empty dictionary to store the results pci_functions = {}   # Loop through each PCI function and extract the BDF and full info for line in lspci_output: bdf = line.split()[0] if vuid in subprocess.check_output(['lspci', '-s', bdf, '-vvv']).decode(): print(bdf) exit(0)   print("Not Found")

本附录解释了 SNAP 如何消耗内存以及如何管理内存分配。

用户必须根据“步骤 1:分配 Hugepages”部分分配 DPA Hugepages 内存。可以按照“调整 YAML 配置”部分中的描述,在 SNAP 容器中使用部分 DPU 内存分配。此配置包括以下最小值和最大值

  • SNAP 容器消耗的最小分配

    复制
    已复制!
                

    resources: requests: memory: "4Gi"

  • SNAP 容器允许消耗的最大分配

    复制
    已复制!
                

    resources: limits:    hugepages-2Mi: "4Gi"

Hugepage 内存由以下项使用

  • SPDK mem-size 全局变量,用于控制 SPDK Hugepages 的消耗(可在 SPDK 中配置,默认为 1GB)

  • SNAP SNAP_MEMPOOL_SIZE_MB – 与非 ZC 模式一起使用,作为 Arm 上的 IO 缓冲区暂存缓冲区。默认情况下,SNAP mempool 从 SPDK mem-size Hugepages 分配中消耗 1G。可以使用 SNAP_MEMPOOL_SIZE_MB 全局变量配置 SNAP mempool(最小值为 64 MB)。

    注意

    如果分配的值太低,使用非 ZC 可能会看到性能下降。

  • SNAP 和 SPDK 内部使用 – 默认应使用 1G。这可能会根据总体规模(即 VF/队列数/QD)而减少。

  • XLIO 缓冲区 – 仅在启用 NVMeTCP XLIO 时分配。

以下是 SNAP 容器允许使用的容器内存限制

复制
已复制!
            

resources: limits: memory: "6Gi"

信息

这包括 Hugepages 限制(在本例中,额外的 2G 非 Hugepages 内存)。

当使用 NVMe 恢复时(在“NVMe 恢复”部分中描述),SNAP 容器还会消耗 DPU SHMEM 内存。此外,还使用了以下资源

复制
已复制!
            

limits: memory:

在主机操作系统上使用 Linux 环境时,可能需要额外的内核启动参数来支持 SNAP 相关功能

  • 要使用 SR-IOV

    • 对于 Intel,必须添加 intel_iommu=on iommu=pt

    • 对于 AMD,必须添加 amd_iommu=on iommu=pt

  • 要使用 PCIe 热插拔,必须添加 pci=realloc

  • 对于非内置的 virtio-blk 驱动程序或 virtio-pci 驱动程序,使用 modprobe.blacklist=virtio_blk,virtio_pci

要查看启动参数值,请运行

复制
已复制!
            

cat /proc/cmdline

建议将以下内容与 virtio-blk 一起使用

复制
已复制!
            

[dpu] cat /proc/cmdline BOOT_IMAGE … pci=realloc modprobe.blacklist=virtio_blk,virtio_pci

要启用 VF(virtio_blk/NVMe)

复制
已复制!
            

echo 125 > /sys/bus/pci/devices/0000\:27\:00.4/sriov_numvfs

英特尔服务器性能优化

复制
已复制!
            

cat /proc/cmdline BOOT_IMAGE=(hd0,msdos1)/vmlinuz-5.15.0_mlnx root=UUID=91528e6a-b7d3-4e78-9d2e-9d5ad60e8273 ro crashkernel=auto resume=UUID=06ff0f35-0282-4812-894e-111ae8d76768 rhgb quiet iommu=pt intel_iommu=on pci=realloc modprobe.blacklist=virtio_blk,virtio_pci


AMD 服务器性能优化

复制
已复制!
            

cat /proc/cmdline cat /proc/cmdline BOOT_IMAGE=(hd0,msdos1)/vmlinuz-5.15.0_mlnx root=UUID=91528e6a-b7d3-4e78-9d2e-9d5ad60e8273 ro crashkernel=auto resume=UUID=06ff0f35-0282-4812-894e-111ae8d76768 rhgb quiet iommu=pt amd_iommu=on pci=realloc modprobe.blacklist=virtio_blk,virtio_pci


© 版权所有 2025 NVIDIA。 上次更新时间:2025 年 2 月 12 日。