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

相关推荐
倔强的石头10628 分钟前
【Linux指南】文件系统基础操作与路径管理
linux·运维·服务器
ThreeYear_s31 分钟前
基于fpga的疲劳驾驶检测
fpga开发
中科三方1 小时前
如何通过DNS解析实现负载均衡?有哪些优势?
运维·负载均衡
安科瑞刘鸿鹏1 小时前
双碳时代,能源调度的难题正从“发电侧”转向“企业侧”
大数据·运维·物联网·安全·能源
小呆瓜历险记2 小时前
ubuntu 22.04搭建SOC开发环境
linux·运维·ubuntu
码农101号2 小时前
Linux中shell流程控制语句
linux·运维·服务器
ajassi20002 小时前
开源 java android app 开发(十二)封库.aar
android·java·linux·开源
聪明小萝卜2 小时前
无法与IP建立连接,未能下载VSCode服务器
运维·服务器
JuiceFS2 小时前
深度解析 JuiceFS 权限管理:Linux 多种安全机制全兼容
运维·后端
暗夜潜行2 小时前
ubuntu + nginx 1.26 + php7.4 + mysql8.0 调优
linux·运维·ubuntu