4. DPU存储卸载配置

任务目标

在DPU(以NVIDIA BlueField-2为例)上启用NVMe-oF(NVMe over Fabrics)存储协议卸载,使主机CPU不再参与远程存储的数据通路处理,从而降低CPU占用并加速远程存储访问。完成本案例后,主机将能够通过DPU上的卸载路径访问远端NVMe存储设备。

环境依赖

  • 硬件:NVIDIA BlueField-2 DPU(或兼容的BlueField系列),x86主机通过PCIe连接DPU
  • 软件:DOCA 2.x(含doca-nvmeof工具)、MLNX_OFED驱动、Linux内核≥5.15(支持nvme-tcp卸载)
  • 远端存储:支持NVMe-oF TCP的存储阵列或Linux服务器(运行nvmet)

实现原理

DPU存储卸载的核心是将NVMe-oF的TCP处理从主机卸载到DPU的ARM核与硬件加速引擎。主机侧仅暴露标准NVMe块设备,数据路径为:主机→PCIe→DPU硬件加速→网络→远端存储,主机CPU不参与TCP/IP协议栈与NVMe命令封装。

关键完整代码

以下脚本在DPU的ARM系统上执行,完成NVMe-oF卸载配置。该脚本创建本地子系统、添加远端存储作为命名空间,并通过DPU硬件加速导出为NVMe设备。

#!/bin/bash
# dpu_nvmeof_unload_config.sh
# 在DPU ARM系统上运行,需root权限

set -e

# 配置参数
REMOTE_IP="192.168.100.10"        # 远端NVMe-oF目标IP
REMOTE_NQN="nqn.2024-01.com.test:storage1"  # 远端目标NQN
LOCAL_NQN="nqn.2024-01.com.test:dpu-unload" # 本地子系统NQN
LOCAL_IP="192.168.100.20"         # DPU用于存储流量的IP

# 1. 加载NVMe-oF相关模块
modprobe nvme-tcp
modprobe nvmet
modprobe nvmet-tcp

# 2. 创建本地NVMe子系统
mkdir -p /sys/kernel/config/nvmet/subsystems/${LOCAL_NQN}
echo 1 > /sys/kernel/config/nvmet/subsystems/${LOCAL_NQN}/attr_allow_any_host

# 3. 创建命名空间并关联远端存储
# 先连接远端NVMe-oF目标,获取本地设备名
nvme connect -t tcp -n ${REMOTE_NQN} -a ${REMOTE_IP} -s 4420
sleep 2
REMOTE_DEV=$(nvme list | grep "${REMOTE_NQN}" | awk '{print $1}' | head -1)

if [ -z "${REMOTE_DEV}" ]; then
    echo "ERROR: 无法连接远端存储 ${REMOTE_NQN}"
    exit 1
fi

# 4. 将远端设备作为命名空间添加到本地子系统
mkdir -p /sys/kernel/config/nvmet/subsystems/${LOCAL_NQN}/namespaces/1
echo -n "${REMOTE_DEV}" > /sys/kernel/config/nvmet/subsystems/${LOCAL_NQN}/namespaces/1/device_path
echo 1 > /sys/kernel/config/nvmet/subsystems/${LOCAL_NQN}/namespaces/1/enable

# 5. 配置TCP端口并启用卸载
mkdir -p /sys/kernel/config/nvmet/ports/1
echo "${LOCAL_IP}" > /sys/kernel/config/nvmet/ports/1/addr_traddr
echo "tcp" > /sys/kernel/config/nvmet/ports/1/addr_trtype
echo "4420" > /sys/kernel/config/nvmet/ports/1/addr_trsvcid
echo "ipv4" > /sys/kernel/config/nvmet/ports/1/addr_adrfam

# 关联子系统到端口
ln -s /sys/kernel/config/nvmet/subsystems/${LOCAL_NQN} \
      /sys/kernel/config/nvmet/ports/1/subsystems/${LOCAL_NQN}

# 6. 启用硬件加速卸载(关键步骤)
echo "mlx5_tcp" > /sys/kernel/config/nvmet/ports/1/offload_engine

# 7. 验证配置
echo "=== 本地子系统配置 ==="
cat /sys/kernel/config/nvmet/subsystems/${LOCAL_NQN}/namespaces/1/device_path
echo ""
echo "=== 端口卸载引擎 ==="
cat /sys/kernel/config/nvmet/ports/1/offload_engine
echo ""
echo "=== 主机侧发现的NVMe设备 ==="
nvme list

运行与验证

执行步骤:

  1. 将脚本复制到DPU的ARM系统(如/opt/scripts/),执行 chmod +x dpu_nvmeof_unload_config.sh
  2. 以root运行:./dpu_nvmeof_unload_config.sh
  3. 在主机侧(x86)执行 nvme discover -t tcp -a <DPU_IP> -s 4420,应能看到本地子系统NQN
  4. 主机侧连接:nvme connect -t tcp -n ${LOCAL_NQN} -a <DPU_IP> -s 4420

通过条件:

  • 脚本无错误输出,最后nvme list显示远端设备已连接
  • 主机侧lsblk出现新的NVMe块设备(如/dev/nvme0n1)
  • 在主机上执行 dd if=/dev/zero of=/dev/nvme0n1 bs=1M count=100 oflag=direct 无I/O错误
  • 执行 cat /sys/kernel/config/nvmet/ports/1/offload_engine 输出为 mlx5_tcp,确认卸载已启用

常见问题

  • 远端连接失败:确认远端存储的NVMe-oF目标已配置且网络可达(ping ${REMOTE_IP})
  • 卸载引擎设置失败:确认DPU固件版本支持NVMe-oF硬件卸载,执行 mlxup -q 检查固件
  • 主机无法发现设备:检查DPU上防火墙(iptables -L)是否放行4420端口