You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用Ethtool ioctl API获取网卡链路速度时ethtool_link_settings未填充

解决ETHTOOL_GLINKSETTINGS返回全0的问题

我来帮你排查这个坑——你用Ethtool的ioctl API获取链路速度时,ethtool_link_settings全返回0,但命令行工具正常,而且驱动也支持新API,这种情况大概率是你对新API的初始化细节没处理到位。我整理了几个关键问题点和修正后的代码:

常见原因分析

新的ETHTOOL_GLINKSETTINGS API比旧版ETHTOOL_GSET要求更严格,几个容易踩的坑:

  • 没初始化ethtool_link_settings的cmd字段,内核根本不知道你要调用哪个命令
  • 没设置link_mode_masks_nwords,内核会认为你不需要任何链路数据,直接返回空值
  • Socket创建类型不对,或者网卡名填错
  • 没检查ioctl的返回值,可能调用已经失败了你还在读空数据

修正后的完整代码

#include <iostream>
#include <cstring>
#include <linux/ethtool.h>
#include <linux/sockios.h>
#include <netinet/in.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <cerrno>

int main() {
    const char* ifname = "enp0s3"; // 替换成你的实际网卡名,用ip link查看
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd == -1) {
        std::cerr << "创建Socket失败: " << strerror(errno) << std::endl;
        return 1;
    }

    struct ifreq ifr{};
    strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
    ifr.ifr_name[IFNAMSIZ - 1] = '\0'; // 确保字符串结束符

    struct ethtool_link_settings settings{};
    // 关键1:必须设置cmd字段,告诉内核我们要调用ETHTOOL_GLINKSETTINGS
    settings.cmd = ETHTOOL_GLINKSETTINGS;
    // 关键2:设置掩码长度,让内核知道我们能接收多少链路模式数据
    settings.link_mode_masks_nwords = ETHTOOL_LINK_MODE_MASK_NWORDS;

    ifr.ifr_data = reinterpret_cast<char*>(&settings);

    // 调用ioctl并检查返回值
    if (ioctl(sockfd, SIOCETHTOOL, &ifr) == -1) {
        std::cerr << "ioctl调用失败: " << strerror(errno) << std::endl;
        close(sockfd);
        return 1;
    }

    // 输出结果
    std::cout << "链路速度: " << settings.speed << " Mbps" << std::endl;
    std::cout << "双工模式: " << (settings.duplex == ETHTOOL_DUPLEX_FULL ? "全双工" : "半双工") << std::endl;
    std::cout << "链路状态: " << (settings.link_ok ? "已连接" : "断开") << std::endl;

    close(sockfd);
    return 0;
}

关键修复点详解

  • 初始化cmd字段:这是内核识别ethtool命令的唯一标识,必须设置为ETHTOOL_GLINKSETTINGS,否则内核无法解析你的请求,直接返回空结构。
  • 设置link_mode_masks_nwords:这个字段告诉内核你的用户态结构能容纳多少个32位的链路掩码字。如果设为0,内核会跳过填充所有链路相关字段,包括speed。直接用内核定义的ETHTOOL_LINK_MODE_MASK_NWORDS就能兼容当前所有链路模式。
  • Socket类型正确:必须用AF_INET或AF_UNIX的SOCK_DGRAM/SOCK_STREAM,不能用SOCK_RAW,否则ioctl会失败。
  • 错误处理:一定要检查ioctl的返回值,调用失败时用strerror(errno)查看具体错误(比如权限不足、网卡名错误),不要直接读空数据。

额外排查步骤

  1. 确认网卡名:用ip link命令查看你的实际网卡名称,别把enp0s3写成eth0了。
  2. 权限检查:普通用户运行可能需要CAP_NET_ADMIN权限,或者直接用sudo运行程序试试。
  3. 验证驱动支持:用ethtool -i <网卡名>查看驱动版本,内核4.15以上基本都支持ETHTOOL_GLINKSETTINGS。
  4. 对比旧版API:如果还是有问题,可以先试试旧版ETHTOOL_GSET(struct ethtool_cmd),看看能不能获取数据,排除硬件或驱动的问题。

内容的提问来源于stack exchange,提问作者cmannett85

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:15:35