[WOL_ARP] = "arp",
[WOL_MAGIC] = "magic",
[WOL_MAGICSECURE] = "secureon",
- [WOL_OFF] = "off"
+ [WOL_OFF] = "off",
};
DEFINE_STRING_TABLE_LOOKUP(wol, WakeOnLan);
DEFINE_CONFIG_PARSE_ENUM(config_parse_wol, wol, WakeOnLan, "Failed to parse WakeOnLan setting");
-static const char* const port_table[_NET_DEV_PORT_MAX] = {
+static const char* const port_table[] = {
[NET_DEV_PORT_TP] = "tp",
[NET_DEV_PORT_AUI] = "aui",
[NET_DEV_PORT_MII] = "mii",
[NET_DEV_PORT_FIBRE] = "fibre",
- [NET_DEV_PORT_BNC] = "bnc"
+ [NET_DEV_PORT_BNC] = "bnc",
};
DEFINE_STRING_TABLE_LOOKUP(port, NetDevPort);
[NET_DEV_FEAT_TSO6] = "tx-tcp6-segmentation",
};
-static const char* const advertise_table[_NET_DEV_ADVERTISE_MAX] = {
- [NET_DEV_ADVERTISE_10BASET_HALF] = "10baset-half",
- [NET_DEV_ADVERTISE_10BASET_FULL] = "10baset-full",
- [NET_DEV_ADVERTISE_100BASET_HALF] = "100baset-half",
- [NET_DEV_ADVERTISE_100BASET_FULL] = "100baset-full",
- [NET_DEV_ADVERTISE_1000BASET_HALF] = "1000baset-half",
- [NET_DEV_ADVERTISE_1000BASET_FULL] = "1000baset-full",
- [NET_DEV_ADVERTISE_10000BASET_FULL] = "10000baset-full",
- [NET_DEV_ADVERTISE_2500BASEX_FULL] = "2500basex-full",
- [NET_DEV_ADVERTISE_1000BASEKX_FULL] = "1000basekx-full",
- [NET_DEV_ADVERTISE_10000BASEKX4_FULL] = "10000basekx4-full",
- [NET_DEV_ADVERTISE_10000BASEKR_FULL] = "10000basekr-full",
- [NET_DEV_ADVERTISE_10000BASER_FEC] = "10000baser-fec",
- [NET_DEV_ADVERTISE_20000BASEMLD2_Full] = "20000basemld2-full",
- [NET_DEV_ADVERTISE_20000BASEKR2_Full] = "20000basekr2-full",
+static const char* const ethtool_link_mode_bit_table[] = {
+ [ETHTOOL_LINK_MODE_10baseT_Half_BIT] = "10baset-half",
+ [ETHTOOL_LINK_MODE_10baseT_Full_BIT] = "10baset-full",
+ [ETHTOOL_LINK_MODE_100baseT_Half_BIT] = "100baset-half",
+ [ETHTOOL_LINK_MODE_100baseT_Full_BIT] = "100baset-full",
+ [ETHTOOL_LINK_MODE_1000baseT_Half_BIT] = "1000baset-half",
+ [ETHTOOL_LINK_MODE_1000baseT_Full_BIT] = "1000baset-full",
+ [ETHTOOL_LINK_MODE_Autoneg_BIT] = "autonegotiation",
+ [ETHTOOL_LINK_MODE_TP_BIT] = "tp",
+ [ETHTOOL_LINK_MODE_AUI_BIT] = "aui",
+ [ETHTOOL_LINK_MODE_MII_BIT] = "mii",
+ [ETHTOOL_LINK_MODE_FIBRE_BIT] = "fibre",
+ [ETHTOOL_LINK_MODE_BNC_BIT] = "bnc",
+ [ETHTOOL_LINK_MODE_10000baseT_Full_BIT] = "10000baset-full",
+ [ETHTOOL_LINK_MODE_Pause_BIT] = "pause",
+ [ETHTOOL_LINK_MODE_Asym_Pause_BIT] = "asym-pause",
+ [ETHTOOL_LINK_MODE_2500baseX_Full_BIT] = "2500basex-full",
+ [ETHTOOL_LINK_MODE_Backplane_BIT] = "backplane",
+ [ETHTOOL_LINK_MODE_1000baseKX_Full_BIT] = "1000basekx-full",
+ [ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT] = "10000basekx4-full",
+ [ETHTOOL_LINK_MODE_10000baseKR_Full_BIT] = "10000basekr-full",
+ [ETHTOOL_LINK_MODE_10000baseR_FEC_BIT] = "10000baser-fec",
+ [ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT] = "20000basemld2-full",
+ [ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT] = "20000basekr2-full",
+ [ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT] = "40000basekr4-full",
+ [ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT] = "40000basecr4-full",
+ [ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT] = "40000basesr4-full",
+ [ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT] = "40000baselr4-full",
+ [ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT] = "56000basekr4-full",
+ [ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT] = "56000basecr4-full",
+ [ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT] = "56000basesr4-full",
+ [ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT] = "56000baselr4-full",
+ [ETHTOOL_LINK_MODE_25000baseCR_Full_BIT] = "25000basecr-full",
+ [ETHTOOL_LINK_MODE_25000baseKR_Full_BIT] = "25000basekr-full",
+ [ETHTOOL_LINK_MODE_25000baseSR_Full_BIT] = "25000basesr-full",
+ [ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT] = "50000basecr2-full",
+ [ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT] = "50000basekr2-full",
+ [ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT] = "100000basekr4-full",
+ [ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT] = "100000basesr4-full",
+ [ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT] = "100000basecr4-full",
+ [ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT] = "100000baselr4-er4-full",
+ [ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT] = "50000basesr2-full",
+ [ETHTOOL_LINK_MODE_1000baseX_Full_BIT] = "1000basex-full",
+ [ETHTOOL_LINK_MODE_10000baseCR_Full_BIT] = "10000basecr-full",
+ [ETHTOOL_LINK_MODE_10000baseSR_Full_BIT] = "10000basesr-full",
+ [ETHTOOL_LINK_MODE_10000baseLR_Full_BIT] = "10000baselr-full",
+ [ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT] = "10000baselrm-full",
+ [ETHTOOL_LINK_MODE_10000baseER_Full_BIT] = "10000baseer-full",
+ [ETHTOOL_LINK_MODE_2500baseT_Full_BIT] = "2500baset-full",
+ [ETHTOOL_LINK_MODE_5000baseT_Full_BIT] = "5000baset-full",
+ [ETHTOOL_LINK_MODE_FEC_NONE_BIT] = "fec-none",
+ [ETHTOOL_LINK_MODE_FEC_RS_BIT] = "fec-rs",
+ [ETHTOOL_LINK_MODE_FEC_BASER_BIT] = "fec-baser",
};
+/* Make sure the array is large enough to fit all bits */
+assert_cc((ELEMENTSOF(ethtool_link_mode_bit_table)-1) / 32 < ELEMENTSOF(((struct link_config){}).advertise));
-DEFINE_STRING_TABLE_LOOKUP(advertise, NetDevAdvertise);
+DEFINE_STRING_TABLE_LOOKUP(ethtool_link_mode_bit, enum ethtool_link_mode_bit_indices);
int ethtool_connect(int *ret) {
int fd;
return i;
}
- return -1;
+ return -ENODATA;
}
int ethtool_set_features(int *fd, const char *ifname, int *features) {
/* If autonegotiation is disabled, the speed and duplex represent the fixed link
* mode and are writable if the driver supports multiple link modes. If it is
- * enabled then they are read-only. If the link is up they represent the negotiated
+ * enabled then they are read-only. If the link is up they represent the negotiated
* link mode; if the link is down, the speed is 0, %SPEED_UNKNOWN or the highest
* enabled speed and @duplex is %DUPLEX_UNKNOWN or the best enabled duplex mode.
*/
struct ifreq ifr = {};
int r;
- if (link->autonegotiation != 0) {
+ if (link->autonegotiation != AUTONEG_DISABLE && eqzero(link->advertise)) {
log_info("link_config: autonegotiation is unset or enabled, the speed and duplex are not writable.");
return 0;
}
if (link->port != _NET_DEV_PORT_INVALID)
u->base.port = link->port;
- u->base.autoneg = link->autonegotiation;
+ if (link->autonegotiation >= 0)
+ u->base.autoneg = link->autonegotiation;
- if (link->advertise) {
- uint32_t advertise[ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32] = {};
-
- advertise[0] = link->advertise;
- memcpy(&u->link_modes.advertising, advertise, ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NBYTES);
+ if (!eqzero(link->advertise)) {
+ u->base.autoneg = AUTONEG_ENABLE;
+ memcpy(&u->link_modes.advertising, link->advertise, sizeof(link->advertise));
+ memzero((uint8_t*) &u->link_modes.advertising + sizeof(link->advertise),
+ ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NBYTES - sizeof(link->advertise));
}
if (u->base.cmd == ETHTOOL_GLINKSETTINGS)
void *data,
void *userdata) {
link_config *config = data;
- NetDevAdvertise mode, a = 0;
const char *p;
int r;
if (isempty(rvalue)) {
/* Empty string resets the value. */
- config->advertise = 0;
+ zero(config->advertise);
return 0;
}
for (p = rvalue;;) {
_cleanup_free_ char *w = NULL;
+ enum ethtool_link_mode_bit_indices mode;
r = extract_first_word(&p, &w, NULL, 0);
if (r == -ENOMEM)
if (r == 0)
break;
- mode = advertise_from_string(w);
- if (mode == _NET_DEV_ADVERTISE_INVALID) {
+ mode = ethtool_link_mode_bit_from_string(w);
+ /* We reuse the kernel provided enum which does not contain negative value. So, the cast
+ * below is mandatory. Otherwise, the check below always passes and access an invalid address. */
+ if ((int) mode < 0) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse advertise mode, ignoring: %s", w);
continue;
}
- a |= mode;
- }
- config->advertise |= a;
+ config->advertise[mode / 32] |= 1UL << (mode % 32);
+ }
return 0;
}