MLX5 Linux 驱动代码分析

Mellanox ConnectX 系列网卡的 Linux 驱动 (mlx5) 是一个高性能 RDMA 和 Ethernet 驱动,支持 InfiniBand 和 Ethernet 功能。以下是对 mlx5 驱动代码的关键分析:

1. 代码结构

mlx5 驱动代码主要位于 Linux 内核的 drivers/net/ethernet/mellanox/mlx5/core/ 目录下:

复制代码
mlx5_core/
├── cmd.c          # 固件命令接口
├── main.c         # 模块初始化和主要逻辑
├── eq.c           # 事件队列处理
├── port.c         # 端口管理
├── devlink.c      # devlink 接口
├── en/            # Ethernet 功能
├── fpga/          # FPGA 相关功能
├── ib/            # InfiniBand 相关功能
├── lib/           # 共享库函数
├── lag/           # LAG 功能
└── vport.c        # 虚拟端口管理

2. 关键组件分析

2.1 初始化流程 (main.c)

复制代码
static int __init init(void)
{
    mlx5_register_debugfs();  // 注册调试文件系统
    mlx5e_init();             // 初始化以太网功能
    mlx5_ib_init();           // 初始化 IB 功能
    mlx5_fpga_init();         // 初始化 FPGA 功能
}

module_init(init);

2.2 设备探测和初始化

复制代码
static int mlx5_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
    struct mlx5_core_dev *dev;
    
    // 分配设备结构
    dev = mlx5_dev_alloc(pdev);
    
    // 初始化硬件
    mlx5_mdev_init(dev, prof_sel);
    
    // 加载固件
    mlx5_load_one(dev);
    
    // 创建网络设备
    mlx5_eth_add(dev);
}

2.3 数据路径 (en_rx.c, en_tx.c)

数据路径实现分为接收和发送两部分:

接收路径
复制代码
bool mlx5e_post_rx_wqes(struct mlx5e_rq *rq)
{
    // 发布接收缓冲区到硬件队列
    // 使用 WQE (Work Queue Element) 结构
}

void mlx5e_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe)
{
    // 处理接收完成事件
    // 将数据包传递给网络栈
}
发送路径
复制代码
netdev_tx_t mlx5e_xmit(struct sk_buff *skb, struct net_device *dev)
{
    // 将 skb 转换为硬件描述符
    // 发布到发送队列
}

2.4 硬件抽象层 (fw.c, cmd.c)

复制代码
int mlx5_cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out, int out_size)
{
    // 执行固件命令
    // 使用邮箱机制与固件通信
}

3. 性能优化技术

  1. 多队列支持:支持 RSS (Receive Side Scaling) 和 RPS (Receive Packet Steering)

  2. 零拷贝:使用 DMA 直接传输数据,减少内存拷贝

  3. 中断合并:使用自适应中断节流

  4. 内存预分配:预先分配关键数据结构减少运行时开销

  5. 内联函数:关键路径使用内联函数减少函数调用开销

4. 关键数据结构

4.1 核心设备结构

(1) 设备 (Device) - struct mlx5_core_dev

表示一个 Mellanox 硬件设备(如 ConnectX 网卡),是所有资源的根容器。
关键成员

复制代码
struct mlx5_core_dev {
    struct pci_dev *pdev;               // 关联的PCI设备
    struct mlx5_priv *priv;             // 设备私有数据
    struct mlx5_eq_table eq_table;      // 事件队列表
    struct mlx5_cq_table cq_table;      // 完成队列表
    struct mlx5_qp_table qp_table;      // QP表(管理所有QP)
    // ...
};

作用:管理硬件资源(如 PCI 配置、DMA 内存)、全局队列表和设备状态。


(2) 完成队列 (CQ) - struct mlx5_core_cq

用于接收硬件通知(如操作完成、错误事件)。
关键成员

复制代码
struct mlx5_core_cq {
    struct mlx5_core_dev *dev;          // 所属设备
    u32 cqn;                           // CQ的唯一标识号
    struct mlx5_wq_ctrl wq_ctrl;        // 队列控制结构(存储CQE数组)
    void (*comp)(struct mlx5_core_cq *); // 完成事件回调函数
    // ...
};

作用

  • 存储完成队列条目(CQE),每个 CQE 描述一个已完成的操作(如发送/接收完成)。

  • 通过中断或轮询通知软件事件完成。


(3) 队列对 (QP) - struct mlx5_core_qp

包含一对队列(发送队列 SQ 和接收队列 RQ),是数据传输的核心。
关键成员

复制代码
struct mlx5_core_qp {
    struct mlx5_core_dev *dev;          // 所属设备
    u32 qpn;                            // QP的唯一标识号
    struct mlx5_wq_sq sq;               // 发送队列
    struct mlx5_wq_rq rq;               // 接收队列
    struct mlx5_core_cq *send_cq;       // 关联的发送CQ
    struct mlx5_core_cq *recv_cq;       // 关联的接收CQ
    // ...
};

作用

  • SQ:存放发送请求(WQE),硬件从 SQ 读取描述符并执行发送操作。

  • RQ:存放接收缓冲区(WQE),硬件将接收到的数据写入 RQ 描述的缓冲区。


(4) 三者的关系

复制代码
Device (mlx5_core_dev)
├── CQ Table (多个CQ)
│   ├── CQ1 → 处理QP1的完成事件
│   └── CQ2 → 处理QP2的完成事件
└── QP Table (多个QP)
    ├── QP1
    │   ├── SQ → 关联CQ1(发送完成通知)
    │   └── RQ → 关联CQ2(接收完成通知)
    └── QP2
        ├── SQ → 关联CQ1
        └── RQ → 关联CQ3
交互流程
  1. 数据传输

    • 应用向 QP 的 SQ 提交发送请求(WQE)。

    • 硬件执行发送后,在关联的 CQ 中生成 CQE。

    • 驱动通过轮询/中断处理 CQE,通知应用完成状态。

  2. 事件通知

    • 当数据到达时,硬件将数据写入 QP 的 RQ 缓冲区,并在关联的 CQ 中生成 CQE。

    • 驱动处理 CQE 并将数据传递给上层协议栈(如 TCP/IP 或 RDMA 应用)。

5. 调试和分析

  1. sysfs 接口/sys/class/net/<dev>/device/

  2. ethtool 统计ethtool -S <interface>

  3. devlinkdevlink dev info pci/0000:01:00.0

  4. tracepointstrace-cmd record -e mlx5:*

6. 典型工作流程示例

6.1 数据包接收流程

  1. 硬件 DMA 数据到预分配缓冲区

  2. 生成完成队列事件 (CQE)

  3. 中断处理程序调度 NAPI

  4. NAPI 轮询处理 CQE

  5. 构建 sk_buff 并传递给网络栈

6.2 数据包发送流程

  1. 网络栈调用驱动 xmit 函数

  2. 驱动将 skb 转换为 WQE

  3. 发布 WQE 到发送队列

  4. 硬件处理完成后生成发送完成事件

  5. 驱动释放 skb 资源

7. 扩展功能

  1. RDMA 支持:通过 mlx5_ib 模块提供

  2. SR-IOV:支持虚拟功能

  3. TC offload:流量控制卸载

  4. TLS offload:加密卸载

mlx5 驱动是一个复杂的高性能网络驱动,充分利用了现代网卡的硬件加速功能,同时提供了丰富的管理和调试接口。

相关推荐
yangshuo12819 分钟前
风车OVF镜像:解放AI开发限制的Ubuntu精简系统
linux·人工智能·ubuntu
文牧之16 分钟前
AutoVACUUM (PostgreSQL) 与 DBMS_STATS.GATHER_DATABASE_STATS_JOB_PROC (Oracle) 对比
运维·数据库·postgresql·oracle
flypig哗啦啦18 分钟前
ubuntu服务器版启动卡在start job is running for wait for...to be Configured
linux·运维·ubuntu
霖0031 分钟前
PCIe数据采集系统
数据结构·经验分享·单片机·嵌入式硬件·fpga开发·信号处理
_Itachi__34 分钟前
LeetCode 热题 100 114. 二叉树展开为链表
linux·leetcode·链表
不之道37 分钟前
通过 wsl 安装 docker
运维·docker·容器
あ-1 小时前
CentOS7 OpenSSL升级1.1.1w
linux
tianyuanwo1 小时前
深入解读tcpdump:原理、数据结构与操作手册
linux·运维·服务器·tcpdump
xjdksxkmd1 小时前
5.11作业
运维·服务器·网络
FakeOccupational2 小时前
fpga系列 HDL : Microchip FPGA开发软件 Libero Soc 安装 & license申请
fpga开发