首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ethtool返回未填充的ethtool_link_settings。

ethtool返回未填充的ethtool_link_settings。
EN

Stack Overflow用户
提问于 2018-03-30 11:23:54
回答 1查看 778关注 0票数 1

我试图使用Ethtool从我的NIC中检索链接速度数据,但我只是在ethtool_link_settings实例中获得零。使用ethtool命令行工具返回期望值,我的NIC驱动程序支持更新的NIC API。

代码语言:javascript
复制
#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>

int main()
{
    auto ifn = if_nameindex();
    auto fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);

    for (auto i = ifn; i->if_name; ++i) {
        // Skip the loopback
        if (i->if_index == 1) {
            continue;
        }

        std::cout << "Testing: " << i->if_name << std::endl;

        auto ifr = ifreq{};
        std::strncpy(ifr.ifr_name, i->if_name, IF_NAMESIZE);

        auto msg = ethtool_link_settings{};
        msg.cmd = ETHTOOL_GLINKSETTINGS;
        ifr.ifr_data = reinterpret_cast<char*>(&msg);

        if (ioctl(fd, SIOCETHTOOL, &ifr) == -1) {
            std::cerr << "ioctl fail: " << strerror(errno) << std::endl;
        }

        std::cout << "\tSpeed: " << msg.speed
                  << "\n\tDuplex: " << static_cast<int>(msg.duplex)
                  << "\n\tPort: " << static_cast<int>(msg.port)
                  << std::endl;
    }

    close(fd);
    if_freenameindex(ifn);
    return EXIT_SUCCESS;
}

在以下方面的成果:

代码语言:javascript
复制
Testing: enp0s3
    Speed: 0
    Duplex: 0
    Port: 0
Testing: enp0s8
    Speed: 0
    Duplex: 0
    Port: 0
Testing: enp0s9
    Speed: 0
    Duplex: 0
    Port: 0
Testing: enp0s10
    Speed: 0
    Duplex: 0
    Port: 0

我肯定我在做傻事,但我看不见。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-12-18 12:26:11

隐藏在link_mode_masks_nwords字段struct ethtool_link_settings in /usr/include/linux/ethtool.h中的评论中有一些令人钦佩的神秘评论,ETHTOOL_GLINKSETTINGS做了一点握手,所以您需要不止一次地对它进行调用。

我通过使用民族工具命令的代码来执行ETHTOOL_GLINKSETTINGS命令来调整您的代码:

代码语言:javascript
复制
#include <iostream>
#include <cstring>

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

int main()
{
    auto ifn = if_nameindex();
    auto fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);

    for (auto i = ifn; i->if_name; ++i) {
        struct {
                struct ethtool_link_settings req;
                __u32 link_mode_data[3 * 127];
            } ecmd;

        // Skip the loopback
        if (i->if_index == 1) {
            continue;
        }

        std::cout << "Testing: " << i->if_name << std::endl;

        auto ifr = ifreq{};
        std::strncpy(ifr.ifr_name, i->if_name, IF_NAMESIZE);

        ecmd.req.cmd = ETHTOOL_GLINKSETTINGS;
        ifr.ifr_data = reinterpret_cast<char*>(&ecmd);

        if (ioctl(fd, SIOCETHTOOL, &ifr) == -1) {
            std::cerr << "ioctl fail: " << strerror(errno) << std::endl;
            return 1;
        }

        if (ecmd.req.link_mode_masks_nwords >= 0 || ecmd.req.cmd != ETHTOOL_GLINKSETTINGS)
            return 1;

        ecmd.req.link_mode_masks_nwords = -ecmd.req.link_mode_masks_nwords;

        if (ioctl(fd, SIOCETHTOOL, &ifr) == -1) {
            std::cerr << "ioctl fail: " << strerror(errno) << std::endl;
            return 1;
        }

        std::cout << "\tSpeed: " << ecmd.req.speed
                  << "\n\tDuplex: " << static_cast<int>(ecmd.req.duplex)
                  << "\n\tPort: " << static_cast<int>(ecmd.req.port)
                  << std::endl;
    }

    close(fd);
    if_freenameindex(ifn);
    return EXIT_SUCCESS;
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49573499

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档