内核态数据通路架构:内核网络协议栈、RDMA子系统(ib_core)与数据包处理流程

核心原理:两条数据通路的本质分野

RDMA 与传统内核网络协议栈的根本差异,在于数据是否经过内核的通用网络协议栈(TCP/IP 处理链)。传统网卡收包后,数据依次经过驱动、协议栈(IP、TCP/UDP)、Socket 层,最终由用户态进程通过系统调用读取;而 RDMA 网卡(HCA)通过硬件卸载了传输层甚至网络层的部分工作,数据在用户态与网卡之间直接搬运,内核仅负责控制面(创建 QP、注册 MR、配置地址等)。

理解这一分野,需要先厘清内核中两个关键模块的职责边界:

  • 内核网络协议栈(net stack):负责传统以太网数据包的收发、路由、分片重组、TCP 状态机等,其数据路径以 sk_buff 为核心载体,处理链长、上下文切换多。
  • RDMA 子系统(ib_core):位于内核驱动与上层协议(如 InfiniBand、RoCE、iWARP)之间,提供统一的设备管理、QP(Queue Pair)生命周期管理、MR(Memory Region)注册、事件分发等机制。它不参与数据搬运,但为数据搬运提供“轨道”和“信号灯”。
关键认知:RDMA 的“内核态数据通路”并非指数据经过内核转发,而是指内核为数据通路提供控制面基础设施。真正的高性能数据面由 HCA 硬件与用户态驱动(如 libibverbs)直接协作完成。
用户态 (User Space) 用户应用 (NFS/RDMA, 数据库, AI训练) libibverbs 用户态驱动库 Socket API (send/recv) 用户态直接IO (RDMA数据面, 不经过内核) 内核态 (Kernel Space) RDMA子系统 (ib_core) QP管理 / MR注册 / 事件分发 设备抽象 / 多厂商支持 内核网络协议栈 TCP/IP / UDP / sk_buff 路由 / Netfilter / Socket 网卡驱动层 传统NIC驱动 (e1000/ixgbe) RDMA HCA驱动 (mlx5_ib/irdma) 硬件层 (Hardware) 传统以太网卡 (NIC) RDMA网卡 (HCA/RNIC) 传统数据路径 控制面 (verbs API) RDMA数据面 (硬件直通) 驱动注册/回调 NAPI/中断

方法流程:ib_core 在内核中的注册与设备管理链路

RDMA 设备驱动(如 mlx5_ib)加载时,并非直接暴露给用户态,而是先向 ib_core 注册。其核心流程如下:

  1. 驱动探测与注册:PCI 驱动探测到 HCA 硬件后,调用 ib_register_device(),将 struct ib_device 注册进 ib_core 的设备列表。
  2. 设备能力上报:驱动填充 struct ib_device_attr(如最大 QP 数、MR 大小、原子操作能力、端口速率等),ib_core 据此向用户态导出设备能力。
  3. 字符设备创建:ib_core 为每个设备创建 /dev/infiniband/rdma_cm 及 /dev/infiniband/uverbs0 等字符设备,用户态通过 open() 获取文件描述符。
  4. QP/MR 资源管理:用户态调用 ibv_create_qp() 时,libibverbs 通过 ioctl 或 write 系统调用进入内核,ib_core 分配 struct ib_qp 并调用驱动提供的 create_qp 回调,最终在硬件中创建队列对。
数据包处理流程(以 RoCE v2 为例):
发送路径:
  用户态写 WQE (Work Queue Element) → 硬件 DMA 读取数据
  → HCA 封装 RoCE v2 头 (ETH+IP+UDP+BTH)
  → 从网口发出

接收路径:
  网口收到 RoCE v2 包 → HCA 解析 BTH 找到 QP
  → 硬件 DMA 将 payload 写入用户预先注册的 MR
  → 在 CQ 中产生 CQE → 用户态 poll CQ 获取完成通知

值得注意的是,RoCE v2 的报文会物理上经过网卡,但内核协议栈完全看不到这些数据包——因为 HCA 在硬件层面完成了 L2/L3/L4 的处理,仅当发生异常(如 QP 错误、流控问题)时,驱动才会将事件上报给 ib_core,进而通知用户态。

案例场景:多网卡共存时的数据通路隔离

在一台同时配置了传统以太网卡(如 eno1)和 RoCE 网卡(如 ens2f0)的服务器上,数据通路的隔离性体现得尤为明显:

操作 传统网络 (TCP) RDMA (RoCE)
IP 配置 内核网络栈管理 ip addr add ib_core 关联 IP,但数据不经过内核 IP 栈
数据发送 应用 → Socket → TCP → IP → 驱动 → NIC 应用 → WQE → HCA 硬件直接封装发送
数据接收 NIC → 驱动 → 协议栈 → Socket → 应用 HCA → DMA → 用户内存 → CQE 通知
CPU 参与 每个包均产生中断/软中断,CPU 拷贝多次 仅创建 QP/MR 时 CPU 参与,数据面零拷贝
错误处理 内核协议栈重传、ICMP 差错 HCA 硬件重传,QP 进入 ERROR 状态后上报 ib_core

实际部署中,若使用 ip route 将 RoCE 网卡的 IP 指向网关,传统 TCP 流量可能误入 RoCE 网卡,导致性能骤降——因为 RoCE 网卡虽然支持以太网帧,但其驱动默认将 ETH_P_IB 之外的包丢弃或慢路径处理。此时需要显式配置 rdma_cm 或使用 tc 分流,确保两类流量各走各的物理端口。

误区与复盘:内核态数据通路的常见误解

误区一:认为 RDMA 完全不需要内核。
实际上,控制面(设备打开、QP 建立、内存注册、中断处理)必须经过内核 ib_core。只有数据面(post_send / poll_cq)可以做到用户态直通硬件。若完全绕过内核,则无法利用内核的内存管理、安全隔离和资源调度能力。
误区二:混淆“内核协议栈卸载”与“内核旁路”。
RoCE 的 data path 是内核旁路,但 RoCE 的 ARP 解析、GID 索引管理仍依赖内核网络栈(例如 ip route 和 rdma link 的协同)。iWARP 则更特殊——其 DDP 层映射到 TCP,因此数据面虽然绕过内核 Socket,但 TCP 状态机仍由内核维护(或由硬件 TCP 卸载引擎处理)。

复盘建议:排查 RDMA 性能问题时,不要只盯着用户态代码。先用 rdma link show 确认链路状态,用 ibstat 查看 HCA 端口速率,再用 perf 观察是否有大量 ib_core 相关软中断——若软中断占比过高,说明驱动或 ib_core 配置存在瓶颈(如中断合并参数 moderation 设置不当)。

内核态调优切入点:
  • 检查 /sys/class/infiniband/mlx5_0/ports/1/rate 确认链路速率未降级。
  • 通过 echo 0 > /sys/class/infiniband/mlx5_0/ports/1/rate 无法调速,需用 mlxconfig 或 ethtool 调整。
  • 观察 cat /proc/interrupts 中 HCA 中断是否均衡分布在多个 CPU 上,必要时设置 irqbalance 或手动绑定。