Всем привет, версия ядра 4.19, хочу получить поддерживаемые ‘link modes’ с помощью API ethtool, моя сетевая карточка подерживает много режимов:
Supported link modes: 1000baseKX/Full
10000baseKR/Full
40000baseKR4/Full
40000baseCR4/Full
40000baseSR4/Full
40000baseLR4/Full
25000baseCR/Full
25000baseKR/Full
25000baseSR/Full
50000baseCR2/Full
50000baseKR2/Full
и я хочу получать эти режимы из своей программы не используя терминал. вот пример кода:
#define ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32 (SCHAR_MAX)
#define ETHTOOL_DECLARE_LINK_MODE_MASK(name) \
uint32_t name[ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32]
int netlink_get_link_speed (const char *dev_name, int *speed)
{
int sock;
struct ifreq ifr = {{{0}}};
//struct ethtool_cmd edata = {0};
int rc;
//int err;
struct {
struct ethtool_link_settings req;
__u32 link_mode_data[3 * ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32];
} ecmd;
/*
struct ethtool_link_usettings {
struct {
uint8_t transceiver;
} deprecated;
struct ethtool_link_settings base;
struct {
ETHTOOL_DECLARE_LINK_MODE_MASK(supported);
ETHTOOL_DECLARE_LINK_MODE_MASK(advertising);
ETHTOOL_DECLARE_LINK_MODE_MASK(lp_advertising);
} link_modes;
};
struct ethtool_link_usettings *link_usettings;
unsigned int u32_offs;*/
if (0 == strcmp(dev_name, "lo"))
{
*speed = 0;
return ERR_OK;
}
sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
if (sock < 0) {
err("Unable to open socket (for location)");
return ERR_OK;
}
memset(&ecmd, 0, sizeof(ecmd));
ecmd.req.cmd = ETHTOOL_GLINKSETTINGS;
strcpy(ifr.ifr_name, dev_name);
ifr.ifr_data = (void *)&ecmd;
rc = ioctl(sock, SIOCETHTOOL, &ifr);
if (rc < 0)
{
err("Cannot read speed '%s' interface", dev_name);
close(sock);
return ERR_SYS_API;
}
/* see above: we expect a strictly negative value from kernel.
*/
if (ecmd.req.link_mode_masks_nwords >= 0
|| ecmd.req.cmd != ETHTOOL_GLINKSETTINGS)
{
err("Incorrect kernel answer");
close(sock);
*speed = 0;
return ERR_SYS_API;
}
/* got the real ecmd.req.link_mode_masks_nwords,
* now send the real request
*/
ecmd.req.cmd = ETHTOOL_GLINKSETTINGS;
ecmd.req.link_mode_masks_nwords = -ecmd.req.link_mode_masks_nwords;
rc = ioctl( sock, SIOCETHTOOL, &ifr);
if (rc < 0)
{
err("Cannot read speed '%s' interface", dev_name);
close(sock);
return ERR_SYS_API;
}
if (ecmd.req.link_mode_masks_nwords <= 0
|| ecmd.req.cmd != ETHTOOL_GLINKSETTINGS)
{
err("Incorrect kernel answer");
close(sock);
*speed = 0;
return ERR_SYS_API;
}
close(sock);
return 0;
}
я выяснил что информация(выставленные биты) вроде как содержатся в переменной link_mode_masks структуры ethtool_link_settings, но как применить не знаю, инфы в интернете не нашел. есть макрос в ethtool.h SUPPORTED_56000baseKR4_Full который путем сравнения битов можно узнать поддерживается этот режим или нет, но он уже устарел, и его просят не использовать, вот выдержка из ethtool.h:
/* Last allowed bit for __ETHTOOL_LINK_MODE_LEGACY_MASK is bit
* 31. Please do NOT define any SUPPORTED_* or ADVERTISED_*
* macro for bits > 31. The only way to use indices > 31 is to
* use the new ETHTOOL_GLINKSETTINGS/ETHTOOL_SLINKSETTINGS API.
*/
так как 50000baseKR2/Full равна 35 в списке enum, то макрос написанный выше уже не подойдет. каким образом тогда можно получить поддерживается данный режим или нет?