2. 获取设备属性

任务目标

编写一个命令行程序,通过输入设备名称(如 mlx5_0),查询并输出该 InfiniBand 设备的节点 GUID、设备版本、固件版本、硬件版本等属性。程序需处理设备不存在或打开失败的错误场景。

核心实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <infiniband/verbs.h>

static void print_device_attr(const char *dev_name) {
    struct ibv_device **dev_list;
    struct ibv_device *dev = NULL;
    struct ibv_context *ctx = NULL;
    struct ibv_device_attr attr;
    int i;

    dev_list = ibv_get_device_list(NULL);
    if (!dev_list) {
        fprintf(stderr, "无法获取设备列表\n");
        exit(1);
    }

    for (i = 0; dev_list[i]; ++i) {
        if (strcmp(ibv_get_device_name(dev_list[i]), dev_name) == 0) {
            dev = dev_list[i];
            break;
        }
    }

    if (!dev) {
        fprintf(stderr, "设备 %s 不存在\n", dev_name);
        ibv_free_device_list(dev_list);
        exit(1);
    }

    ctx = ibv_open_device(dev);
    if (!ctx) {
        fprintf(stderr, "打开设备 %s 失败\n", dev_name);
        ibv_free_device_list(dev_list);
        exit(1);
    }

    memset(&attr, 0, sizeof(attr));
    if (ibv_query_device(ctx, &attr) != 0) {
        fprintf(stderr, "查询设备属性失败\n");
        ibv_close_device(ctx);
        ibv_free_device_list(dev_list);
        exit(1);
    }

    printf("设备名称: %s\n", dev_name);
    printf("节点 GUID: 0x%016llx\n", (unsigned long long)attr.node_guid);
    printf("设备版本: %d\n", attr.device_version);
    printf("固件版本: %s\n", attr.fw_ver);
    printf("硬件版本: %s\n", attr.hw_ver);
    printf("最大 QP 数: %d\n", attr.max_qp);
    printf("最大 CQ 数: %d\n", attr.max_cq);

    ibv_close_device(ctx);
    ibv_free_device_list(dev_list);
}

int main(int argc, char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "用法: %s <设备名>\n", argv[0]);
        fprintf(stderr, "示例: %s mlx5_0\n", argv[0]);
        return 1;
    }

    print_device_attr(argv[1]);
    return 0;
}

编译与运行

# 编译(需安装 libibverbs-dev)
gcc -o query_dev query_dev.c -libverbs

# 查询设备属性
./query_dev mlx5_0

验证方法

程序执行后,观察输出是否包含以下字段:

  • 节点 GUID:非零的 64 位十六进制数
  • 固件版本:形如 xx.xx.xxxx 的字符串
  • 硬件版本:非空字符串
  • 设备版本:整数值

可通过 ibv_devinfo -v 命令交叉验证输出结果的一致性。若输入不存在的设备名(如 ./query_dev fake_dev),程序应输出错误信息并以非零状态退出。

预期输出示例

设备名称: mlx5_0
节点 GUID: 0x248a070300a1b2c3
设备版本: 0
固件版本: 16.32.1010
硬件版本: 0x0000000000000000
最大 QP 数: 131072
最大 CQ 数: 16777216

常见问题

  • 编译报错找不到头文件:安装 libibverbs-dev 包(Ubuntu/Debian)或 rdma-core-devel(RHEL/CentOS)。
  • 运行提示设备不存在:先执行 ibv_devinfo -l 查看系统实际可用的设备名称。
  • 权限不足:部分系统需要 root 权限或加入 rdma 用户组才能访问 InfiniBand 设备。