diff --git a/man/systemd.link.xml b/man/systemd.link.xml index 9ddcaf7c09d..42ad2c27eae 100644 --- a/man/systemd.link.xml +++ b/man/systemd.link.xml @@ -1361,6 +1361,58 @@ + + [EnergyEfficientEthernet] Section Options + The [EnergyEfficientEthernet] section controls the Energy Efficient Ethernet (EEE) feature of the + interface, and accepts the following keys. + + + + Enabled= + + 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. + + + + + + + TxLowPowerIdle= + + 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. + + + + + + + TxLowPowerIdleSec= + + 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. + + + + + + + LinkMode= + + Takes a list of link modes, e.g. 1000baset-full. See the table for + Advertise= 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. + + + + + + + Specifiers diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c index aeed917a6a5..b29d2641ef2 100644 --- a/src/shared/ethtool-util.c +++ b/src/shared/ethtool-util.c @@ -1123,6 +1123,62 @@ int ethtool_set_nic_coalesce_settings(int *ethtool_fd, const char *ifname, const 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, diff --git a/src/shared/ethtool-util.h b/src/shared/ethtool-util.h index d431b4452ce..9aa36da227a 100644 --- a/src/shared/ethtool-util.h +++ b/src/shared/ethtool-util.h @@ -7,6 +7,7 @@ #include "conf-parser.h" #include "ether-addr-util.h" +#include "time-util.h" #define N_ADVERTISE 4 @@ -180,6 +181,13 @@ int ethtool_set_glinksettings( 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_; diff --git a/src/udev/net/link-config-gperf.gperf b/src/udev/net/link-config-gperf.gperf index 61e7d624101..4f4a016a425 100644 --- a/src/udev/net/link-config-gperf.gperf +++ b/src/udev/net/link-config-gperf.gperf @@ -39,9 +39,11 @@ Match.Credential, config_parse_net_condition, Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(LinkConfig, conditions) Match.Firmware, config_parse_net_condition, CONDITION_FIRMWARE, offsetof(LinkConfig, conditions) Link.Description, config_parse_string, 0, offsetof(LinkConfig, description) +/* udev property */ Link.Property, config_parse_udev_property, 0, offsetof(LinkConfig, properties) Link.ImportProperty, config_parse_udev_property_name, 0, offsetof(LinkConfig, import_properties) Link.UnsetProperty, config_parse_udev_property_name, 0, offsetof(LinkConfig, unset_properties) +/* rtnl setlink */ Link.MACAddressPolicy, config_parse_mac_address_policy, 0, offsetof(LinkConfig, mac_address_policy) Link.MACAddress, config_parse_hw_addr, 0, offsetof(LinkConfig, hw_addr) Link.NamePolicy, config_parse_name_policy, 0, offsetof(LinkConfig, name_policy) @@ -53,12 +55,19 @@ Link.TransmitQueues, config_parse_rx_tx_queues, Link.ReceiveQueues, config_parse_rx_tx_queues, 0, offsetof(LinkConfig, rxqueues) Link.TransmitQueueLength, config_parse_txqueuelen, 0, offsetof(LinkConfig, txqueuelen) Link.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(LinkConfig, mtu) +Link.GenericSegmentOffloadMaxBytes, config_parse_iec_size, 0, offsetof(LinkConfig, gso_max_size) +Link.GenericSegmentOffloadMaxSegments, config_parse_uint32, 0, offsetof(LinkConfig, gso_max_segments) +/* ethtool link settings */ Link.BitsPerSecond, config_parse_si_uint64, 0, offsetof(LinkConfig, speed) Link.Duplex, config_parse_duplex, 0, offsetof(LinkConfig, duplex) Link.AutoNegotiation, config_parse_tristate, 0, offsetof(LinkConfig, autonegotiation) +Link.Advertise, config_parse_advertise, 0, offsetof(LinkConfig, advertise) +Link.Port, config_parse_port, 0, offsetof(LinkConfig, port) +Link.MDI, config_parse_mdi, 0, offsetof(LinkConfig, mdi) +/* ethtool WoL settings */ Link.WakeOnLan, config_parse_wol, 0, offsetof(LinkConfig, wol) Link.WakeOnLanPassword, config_parse_wol_password, 0, 0 -Link.Port, config_parse_port, 0, offsetof(LinkConfig, port) +/* ethtool features */ Link.ReceiveChecksumOffload, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_RXCSUM]) Link.TransmitChecksumOffload, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_TXCSUM]) Link.GenericSegmentationOffload, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_GSO]) @@ -76,20 +85,21 @@ Link.TransmitVLANSTAGHardwareAcceleration, config_parse_tristate, Link.NTupleFilter, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_NTUPLE]) Link.ReceiveFCS, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_RXFCS]) Link.ReceiveAll, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_RXALL]) +/* ethtool channels */ Link.RxChannels, config_parse_ring_buffer_or_channel, 0, offsetof(LinkConfig, channels.rx) Link.TxChannels, config_parse_ring_buffer_or_channel, 0, offsetof(LinkConfig, channels.tx) Link.OtherChannels, config_parse_ring_buffer_or_channel, 0, offsetof(LinkConfig, channels.other) Link.CombinedChannels, config_parse_ring_buffer_or_channel, 0, offsetof(LinkConfig, channels.combined) -Link.Advertise, config_parse_advertise, 0, offsetof(LinkConfig, advertise) +/* ethtool ring parameters */ Link.RxBufferSize, config_parse_ring_buffer_or_channel, 0, offsetof(LinkConfig, ring.rx) Link.RxMiniBufferSize, config_parse_ring_buffer_or_channel, 0, offsetof(LinkConfig, ring.rx_mini) Link.RxJumboBufferSize, config_parse_ring_buffer_or_channel, 0, offsetof(LinkConfig, ring.rx_jumbo) Link.TxBufferSize, config_parse_ring_buffer_or_channel, 0, offsetof(LinkConfig, ring.tx) +/* ethtool pause parameters */ Link.RxFlowControl, config_parse_tristate, 0, offsetof(LinkConfig, rx_flow_control) Link.TxFlowControl, config_parse_tristate, 0, offsetof(LinkConfig, tx_flow_control) Link.AutoNegotiationFlowControl, config_parse_tristate, 0, offsetof(LinkConfig, autoneg_flow_control) -Link.GenericSegmentOffloadMaxBytes, config_parse_iec_size, 0, offsetof(LinkConfig, gso_max_size) -Link.GenericSegmentOffloadMaxSegments, config_parse_uint32, 0, offsetof(LinkConfig, gso_max_segments) +/* ethtool coalesce settings */ Link.RxCoalesceSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.rx_coalesce_usecs) Link.RxMaxCoalescedFrames, config_parse_coalesce_u32, 0, offsetof(LinkConfig, coalesce.rx_max_coalesced_frames) Link.RxCoalesceIrqSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.rx_coalesce_usecs_irq) @@ -112,8 +122,9 @@ Link.RxMaxCoalescedHighFrames, config_parse_coalesce_u32, Link.TxCoalesceHighSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.tx_coalesce_usecs_high) Link.TxMaxCoalescedHighFrames, config_parse_coalesce_u32, 0, offsetof(LinkConfig, coalesce.tx_max_coalesced_frames_high) Link.CoalescePacketRateSampleIntervalSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.rate_sample_interval) +/* Rx RPS CPU mask */ Link.ReceivePacketSteeringCPUMask, config_parse_rps_cpu_mask, 0, offsetof(LinkConfig, rps_cpu_mask) -Link.MDI, config_parse_mdi, 0, offsetof(LinkConfig, mdi) +/* SR-IOV settings */ Link.SR-IOVVirtualFunctions, config_parse_sr_iov_num_vfs, 0, offsetof(LinkConfig, sr_iov_num_vfs) SR-IOV.VirtualFunction, config_parse_sr_iov_uint32, 0, offsetof(LinkConfig, sr_iov_by_section) SR-IOV.VLANId, config_parse_sr_iov_uint32, 0, offsetof(LinkConfig, sr_iov_by_section) @@ -124,3 +135,8 @@ SR-IOV.QueryReceiveSideScaling, config_parse_sr_iov_boolean, 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) diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c index 5a4b7261bbd..3400286566f 100644 --- a/src/udev/net/link-config.c +++ b/src/udev/net/link-config.c @@ -263,6 +263,9 @@ int link_load_one(LinkConfigContext *ctx, const char *filename) { .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) @@ -548,6 +551,10 @@ static int link_apply_ethtool_settings(Link *link, int *ethtool_fd) { 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; } diff --git a/src/udev/net/link-config.h b/src/udev/net/link-config.h index fd796bbaa53..dcbc61359c5 100644 --- a/src/udev/net/link-config.h +++ b/src/udev/net/link-config.h @@ -56,9 +56,13 @@ struct LinkConfig { LIST_HEAD(Condition, conditions); char *description; + + /* udev property */ char **properties; char **import_properties; char **unset_properties; + + /* rtnl setlink */ struct hw_addr_data hw_addr; MACAddressPolicy mac_address_policy; NamePolicy *name_policy; @@ -72,24 +76,47 @@ struct LinkConfig { uint32_t mtu; uint32_t gso_max_segments; size_t gso_max_size; + + /* ethtool link settings */ uint64_t speed; Duplex duplex; int autonegotiation; uint32_t advertise[N_ADVERTISE]; + NetDevPort port; + uint8_t mdi; + + /* ethtool WoL */ uint32_t wol; char *wol_password_file; uint8_t *wol_password; - NetDevPort port; + + /* ethtool features */ int features[_NET_DEV_FEAT_MAX]; + + /* ethtool channels */ netdev_channels channels; + + /* ethtool ring parameters */ netdev_ring_param ring; + + /* ethtool pause parameters */ int rx_flow_control; int tx_flow_control; int autoneg_flow_control; + + /* ethtool coalesce settings */ netdev_coalesce_param coalesce; - uint8_t mdi; + + /* 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; + /* SR-IOV */ uint32_t sr_iov_num_vfs; OrderedHashmap *sr_iov_by_section;