4. NVMe-oF协议基础与DPU卸载切入点
NVMe-oF(NVMe over Fabrics)把本地 PCIe 上的 NVMe 命令语义搬到网络上,让主机像访问本地盘一样访问远端 SSD。理解它的关键不在于“把 NVMe 包一层网络”,而在于三件事:用哪条传输承载(TCP 还是 RoCEv2)、命令如何走完一次往返(命令流程)、队列如何映射到网络连接(队列机制)。DPU 的卸载价值,恰恰藏在这三件事的边界上。
一、两种承载:NVMe/TCP 与 NVMe/RoCEv2 的协议栈差异
NVMe-oF 定义了统一的 Fabrics 命令层(Capsule、Command、Response、Data),但底层传输可以不同。NVMe/TCP 把 Capsule 直接放进 TCP 字节流,依赖 TCP 的重传、拥塞控制和有序交付;NVMe/RoCEv2 则把 Capsule 封装进 RDMA 的 Send/Write/Read 语义,由 RoCEv2(UDP + IB BTH)承载,靠 PFC/ECN 做无损保障。
两者的栈结构差异决定了卸载切入点不同:
- NVMe/TCP:NVMe → Fabrics Capsule → TCP → IP → Ethernet。主机侧需要处理 TCP 分段、重组、ACK、窗口与重传,CPU 开销集中在协议栈与内存拷贝。
- NVMe/RoCEv2:NVMe → Fabrics Capsule → RDMA Send/Write/Read → RoCEv2(UDP+BTH) → Ethernet。主机侧需要处理 QP 状态、WQE 构造、CQ 轮询与内存注册(MR),开销集中在 verbs 路径与 doorbell。
一个常见的教学示例参数:MTU 1500、单次 I/O 4 KiB 随机读、队列深度 128。NVMe/TCP 下每个 I/O 至少涉及一次命令 Capsule 与一次数据回传,TCP 侧还要承担 ACK 与可能的合并;NVMe/RoCEv2 下数据可通过 RDMA Read 直接落到主机预注册缓冲区,减少一次拷贝。这里的数值仅为示例,用于说明路径差异,并非实测结果。
二、命令流程:一次 I/O 的完整往返
无论哪种承载,NVMe-oF 的命令流程都遵循“主机提交命令 → 目标执行 → 数据/状态回传”的骨架。以读 I/O 为例:
- 主机在提交队列(SQ)写入 NVMe Read 命令,更新 SQ Tail Doorbell。
- Fabrics 层把命令封装为 Capsule,经 TCP 或 RDMA Send 发往目标。
- 目标解析命令,从命名空间读取数据,按约定方式回传:TCP 下走独立数据流,RoCEv2 下可用 RDMA Write 或 Read Response。
- 目标写完成队列(CQ)条目,主机轮询 CQ 得到完成状态与 Phase Tag。
写 I/O 的差异在于数据方向:主机需先把数据送到目标缓冲区(TCP 内联或 RDMA Write),再发命令 Capsule,目标落盘后回完成。这个“数据先行还是命令先行”的顺序,是判断卸载点的重要线索。
三、队列机制:SQ/CQ 如何映射到网络连接
NVMe 的队列模型是“多提交队列 + 多完成队列”,每个队列对(Queue Pair,此处指 NVMe 的 SQ/CQ 组合)独立工作。NVMe-oF 把这个模型映射到网络连接上:
- NVMe/TCP:一个 TCP 连接可承载多个 NVMe 队列,通过 PDU 头中的 Queue ID 区分;也可以一个队列一个连接,换取更简单的流控与更低的队头阻塞。
- NVMe/RoCEv2:每个 NVMe 队列通常绑定一个 RDMA QP,SQ 对应 Send Queue,CQ 对应 Completion Queue,命令与数据通过 WQE 描述。
队列深度(Queue Depth)与连接数的组合,直接决定并发能力。例如 4 个队列、每队列深度 128,理论可挂起 512 个未完成命令;若只用一个 TCP 连接承载全部队列,则 TCP 窗口与重传会成为瓶颈。这也是 DPU 卸载需要关注“队列到连接/QP 的映射策略”的原因。
四、DPU 可卸载的关键环节
把上面的流程拆开看,DPU 的卸载点可以落在四个位置:
- 传输层卸载:NVMe/TCP 的 TCP 分段、重组、ACK、重传、校验和计算;NVMe/RoCEv2 的 RoCEv2 封装、BTH 处理、PFC/ECN 响应。这些是纯协议处理,适合硬件或可编程流水线。
- Fabrics 层卸载:Capsule 的封装与解封装、PDU 头解析、命令与数据的关联。DPU 可在网卡侧完成 Capsule 组装,减少主机内存往返。
- 队列与连接管理:SQ/CQ 与 TCP 连接/QP 的映射、Doorbell 聚合、CQ 事件合并。DPU 可代主机维护队列状态,降低 doorbell 频率与中断次数。
- 数据搬运与内存注册:RDMA MR 管理、数据直接落盘或落内存、零拷贝路径。DPU 可承担数据缓冲区管理与地址翻译,避免主机侧重复拷贝。
五、一个可参考的观察方法
在实验环境中,可以用 nvme-cli 连接远端目标,观察队列与连接状态:
nvme discover -t tcp -a 192.168.10.20 -s 4420
nvme connect -t tcp -n nqn.2024-01.com.example:subsys1 \
-a 192.168.10.20 -s 4420
nvme list-subsys
执行后重点看 list-subsys 输出的传输类型、队列数量与状态。若把同样的目标换成 RoCEv2,传输类型变为 rdma,此时可用 ibv_devinfo 查看 QP 与端口状态。对比两种承载下 iostat -x 的 %system 与 await,可以直观看到协议栈开销的差异。这些命令与观察项属于通用方法,具体数值需以实际环境为准。
理解 NVMe-oF 的协议栈、命令流程与队列机制,是为了准确找到 DPU 的介入位置:传输层与 Fabrics 层是“协议搬运”,队列与内存管理是“状态与数据搬运”。把这两类工作从主机 CPU 上移走,才是 DPU 存储加速的真正起点。