Closes #36278.
</variablelist>
</refsect1>
+ <refsect1>
+ <title>[EnergyEfficientEthernet] Section Options</title>
+ <para>The [EnergyEfficientEthernet] section controls the Energy Efficient Ethernet (EEE) feature of the
+ interface, and accepts the following keys.</para>
+
+ <variablelist class='network-directives'>
+ <varlistentry>
+ <term><varname>Enabled=</varname></term>
+ <listitem>
+ <para>Takes a boolean argument. When true, the Energy Efficient Ethernet (EEE) feature will be
+ enabled on the interface. Defaults to unset, and the enablement of EEE will be unchanged.</para>
+
+ <xi:include href="version-info.xml" xpointer="v258"/>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>TxLowPowerIdle=</varname></term>
+ <listitem>
+ <para>Takes a boolean argument. When true, the transmit Low Power Idle (Tx-LPI) mode of the Energy
+ Efficient Ethernet feature will be enabled on the interface. Defaults to unset, and the enablement
+ of the mode will be unchanged.</para>
+
+ <xi:include href="version-info.xml" xpointer="v258"/>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>TxLowPowerIdleSec=</varname></term>
+ <listitem>
+ <para>Takes a timespan. This configures how long the interface should not enter the Low Power Idle
+ mode after transmission. If it is too short, may decrease performance. If it is too long, may not
+ gain energy saving. Defaults to unset, and the timespan will be unchanged.</para>
+
+ <xi:include href="version-info.xml" xpointer="v258"/>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>LinkMode=</varname></term>
+ <listitem>
+ <para>Takes a list of link modes, e.g. <literal>1000baset-full</literal>. See the table for
+ <varname>Advertise=</varname> setting in [Link] section in the above for possible values. This
+ configures the Energy Efficient Ethernet capable connection modes to be advertised. Defaults to
+ unset, and the advertised modes will be unchanged.</para>
+
+ <xi:include href="version-info.xml" xpointer="v258"/>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
<refsect1>
<title>Specifiers</title>
return RET_NERRNO(ioctl(*ethtool_fd, SIOCETHTOOL, &ifr));
}
+int ethtool_set_eee_settings(
+ int *ethtool_fd,
+ const char *ifname,
+ int enabled,
+ int tx_lpi_enabled,
+ usec_t tx_lpi_timer_usec,
+ uint32_t advertise) {
+
+ int r;
+
+ assert(ethtool_fd);
+ assert(ifname);
+
+ if (enabled < 0 &&
+ tx_lpi_enabled < 0 &&
+ tx_lpi_timer_usec == USEC_INFINITY &&
+ advertise == 0)
+ return 0; /* Nothing requested. */
+
+ r = ethtool_connect(ethtool_fd);
+ if (r < 0)
+ return r;
+
+ struct ethtool_eee ecmd = {
+ .cmd = ETHTOOL_GEEE,
+ };
+ struct ifreq ifr = {
+ .ifr_data = (void*) &ecmd,
+ };
+
+ strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname);
+
+ if (ioctl(*ethtool_fd, SIOCETHTOOL, &ifr) < 0)
+ return -errno;
+
+ if (ecmd.supported == 0)
+ return 0; /* Unsupported. */
+
+ bool need_update = false;
+
+ if (enabled >= 0)
+ UPDATE(ecmd.eee_enabled, (uint32_t) enabled, need_update);
+ if (tx_lpi_enabled >= 0)
+ UPDATE(ecmd.tx_lpi_enabled, (uint32_t) tx_lpi_enabled, need_update);
+ if (tx_lpi_timer_usec != USEC_INFINITY)
+ UPDATE(ecmd.tx_lpi_timer, (uint32_t) MIN(DIV_ROUND_UP(tx_lpi_timer_usec, USEC_PER_MSEC), (usec_t) UINT32_MAX), need_update);
+ if (advertise != 0)
+ UPDATE(ecmd.advertised, advertise & ecmd.supported, need_update);
+
+ if (!need_update)
+ return 0; /* Nothing changed. */
+
+ ecmd.cmd = ETHTOOL_SEEE;
+ return RET_NERRNO(ioctl(*ethtool_fd, SIOCETHTOOL, &ifr));
+}
+
int config_parse_advertise(
const char *unit,
const char *filename,
#include "conf-parser.h"
#include "ether-addr-util.h"
+#include "time-util.h"
#define N_ADVERTISE 4
int ethtool_set_channels(int *ethtool_fd, const char *ifname, const netdev_channels *channels);
int ethtool_set_flow_control(int *fd, const char *ifname, int rx, int tx, int autoneg);
int ethtool_set_nic_coalesce_settings(int *ethtool_fd, const char *ifname, const netdev_coalesce_param *coalesce);
+int ethtool_set_eee_settings(
+ int *ethtool_fd,
+ const char *ifname,
+ int enabled,
+ int tx_lpi_enabled,
+ usec_t tx_lpi_timer_usec,
+ uint32_t advertise);
const char* duplex_to_string(Duplex d) _const_;
Duplex duplex_from_string(const char *d) _pure_;
SR-IOV.Trust, config_parse_sr_iov_boolean, 0, offsetof(LinkConfig, sr_iov_by_section)
SR-IOV.LinkState, config_parse_sr_iov_link_state, 0, offsetof(LinkConfig, sr_iov_by_section)
SR-IOV.MACAddress, config_parse_sr_iov_mac, 0, offsetof(LinkConfig, sr_iov_by_section)
+/* ethtool EEE settings */
+EnergyEfficientEthernet.Enable, config_parse_tristate, 0, offsetof(LinkConfig, eee_enabled)
+EnergyEfficientEthernet.TxLowPowerIdle, config_parse_tristate, 0, offsetof(LinkConfig, eee_tx_lpi_enabled)
+EnergyEfficientEthernet.TxLowPowerIdleSec, config_parse_sec, 0, offsetof(LinkConfig, eee_tx_lpi_timer_usec)
+EnergyEfficientEthernet.LinkMode, config_parse_advertise, 0, offsetof(LinkConfig, eee_advertise)
.coalesce.use_adaptive_tx_coalesce = -1,
.mdi = ETH_TP_MDI_INVALID,
.sr_iov_num_vfs = UINT32_MAX,
+ .eee_enabled = -1,
+ .eee_tx_lpi_enabled = -1,
+ .eee_tx_lpi_timer_usec = USEC_INFINITY,
};
FOREACH_ELEMENT(feature, config->features)
if (r < 0)
log_link_warning_errno(link, r, "Could not set coalesce settings, ignoring: %m");
+ r = ethtool_set_eee_settings(ethtool_fd, name, config->eee_enabled, config->eee_tx_lpi_enabled, config->eee_tx_lpi_timer_usec, config->eee_advertise[0]);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Could not set energy efficient ethernet settings, ignoring: %m");
+
return 0;
}
/* ethtool coalesce settings */
netdev_coalesce_param coalesce;
+ /* ethtool energy efficient ethernet settings */
+ int eee_enabled;
+ int eee_tx_lpi_enabled;
+ usec_t eee_tx_lpi_timer_usec;
+ uint32_t eee_advertise[N_ADVERTISE];
+
/* Rx RPS CPU mask */
CPUSet *rps_cpu_mask;