diff --git a/man/systemd.link.xml b/man/systemd.link.xml
index 5f5930adf50..df352b0a427 100644
--- a/man/systemd.link.xml
+++ b/man/systemd.link.xml
@@ -1376,6 +1376,27 @@
+
+ RxMaxCoalescedCQEFrames=
+
+ Configures the maximum number of received frames that can be
+ coalesced into a single Completion Queue Entry (CQE) or descriptor writeback. An unsigned integer
+ in the range 0…4294967295. When unset, the kernel's default will be used.
+
+
+
+
+
+ RxCoalesceCQENSec=
+
+ Takes a timespan. If no unit is specified, the value is parsed as nanoseconds. The value
+ must not exceed 4294967295 ns (about 4.29 seconds). This configures the maximum time a
+ coalesced CQE or writeback can be delayed after the first packet arrives. If unset, the
+ kernel's default will be used.
+
+
+
+
MDI=
diff --git a/src/include/uapi/linux/ethtool_netlink_generated.h b/src/include/uapi/linux/ethtool_netlink_generated.h
new file mode 100644
index 00000000000..572c5f93e43
--- /dev/null
+++ b/src/include/uapi/linux/ethtool_netlink_generated.h
@@ -0,0 +1,964 @@
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* Do not edit directly, auto-generated from: */
+/* Documentation/netlink/specs/ethtool.yaml */
+/* YNL-GEN uapi header */
+/* To regenerate run: tools/net/ynl/ynl-regen.sh */
+
+#ifndef _LINUX_ETHTOOL_NETLINK_GENERATED_H
+#define _LINUX_ETHTOOL_NETLINK_GENERATED_H
+
+#define ETHTOOL_GENL_NAME "ethtool"
+#define ETHTOOL_GENL_VERSION 1
+
+enum {
+ ETHTOOL_UDP_TUNNEL_TYPE_VXLAN,
+ ETHTOOL_UDP_TUNNEL_TYPE_GENEVE,
+ ETHTOOL_UDP_TUNNEL_TYPE_VXLAN_GPE,
+
+ /* private: */
+ __ETHTOOL_UDP_TUNNEL_TYPE_CNT,
+ ETHTOOL_UDP_TUNNEL_TYPE_MAX = (__ETHTOOL_UDP_TUNNEL_TYPE_CNT - 1)
+};
+
+/**
+ * enum ethtool_header_flags - common ethtool header flags
+ * @ETHTOOL_FLAG_COMPACT_BITSETS: use compact bitsets in reply
+ * @ETHTOOL_FLAG_OMIT_REPLY: provide optional reply for SET or ACT requests
+ * @ETHTOOL_FLAG_STATS: request statistics, if supported by the driver
+ */
+enum ethtool_header_flags {
+ ETHTOOL_FLAG_COMPACT_BITSETS = 1,
+ ETHTOOL_FLAG_OMIT_REPLY = 2,
+ ETHTOOL_FLAG_STATS = 4,
+};
+
+enum ethtool_tcp_data_split {
+ ETHTOOL_TCP_DATA_SPLIT_UNKNOWN,
+ ETHTOOL_TCP_DATA_SPLIT_DISABLED,
+ ETHTOOL_TCP_DATA_SPLIT_ENABLED,
+};
+
+/**
+ * enum hwtstamp_source - Source of the hardware timestamp
+ * @HWTSTAMP_SOURCE_NETDEV: Hardware timestamp comes from a MAC or a device
+ * which has MAC and PHY integrated
+ * @HWTSTAMP_SOURCE_PHYLIB: Hardware timestamp comes from one PHY device of the
+ * network topology
+ */
+enum hwtstamp_source {
+ HWTSTAMP_SOURCE_NETDEV = 1,
+ HWTSTAMP_SOURCE_PHYLIB,
+};
+
+/**
+ * enum ethtool_pse_event - PSE event list for the PSE controller
+ * @ETHTOOL_PSE_EVENT_OVER_CURRENT: PSE output current is too high
+ * @ETHTOOL_PSE_EVENT_OVER_TEMP: PSE in over temperature state
+ * @ETHTOOL_C33_PSE_EVENT_DETECTION: detection process occur on the PSE. IEEE
+ * 802.3-2022 33.2.5 and 145.2.6 PSE detection of PDs. IEEE 802.3-202
+ * 30.9.1.1.5 aPSEPowerDetectionStatus
+ * @ETHTOOL_C33_PSE_EVENT_CLASSIFICATION: classification process occur on the
+ * PSE. IEEE 802.3-2022 33.2.6 and 145.2.8 classification of PDs mutual
+ * identification. IEEE 802.3-2022 30.9.1.1.8 aPSEPowerClassification.
+ * @ETHTOOL_C33_PSE_EVENT_DISCONNECTION: PD has been disconnected on the PSE.
+ * IEEE 802.3-2022 33.3.8 and 145.3.9 PD Maintain Power Signature. IEEE
+ * 802.3-2022 33.5.1.2.9 MPS Absent. IEEE 802.3-2022 30.9.1.1.20
+ * aPSEMPSAbsentCounter.
+ * @ETHTOOL_PSE_EVENT_OVER_BUDGET: PSE turned off due to over budget situation
+ * @ETHTOOL_PSE_EVENT_SW_PW_CONTROL_ERROR: PSE faced an error managing the
+ * power control from software
+ */
+enum ethtool_pse_event {
+ ETHTOOL_PSE_EVENT_OVER_CURRENT = 1,
+ ETHTOOL_PSE_EVENT_OVER_TEMP = 2,
+ ETHTOOL_C33_PSE_EVENT_DETECTION = 4,
+ ETHTOOL_C33_PSE_EVENT_CLASSIFICATION = 8,
+ ETHTOOL_C33_PSE_EVENT_DISCONNECTION = 16,
+ ETHTOOL_PSE_EVENT_OVER_BUDGET = 32,
+ ETHTOOL_PSE_EVENT_SW_PW_CONTROL_ERROR = 64,
+};
+
+enum {
+ ETHTOOL_A_HEADER_UNSPEC,
+ ETHTOOL_A_HEADER_DEV_INDEX,
+ ETHTOOL_A_HEADER_DEV_NAME,
+ ETHTOOL_A_HEADER_FLAGS,
+ ETHTOOL_A_HEADER_PHY_INDEX,
+
+ __ETHTOOL_A_HEADER_CNT,
+ ETHTOOL_A_HEADER_MAX = (__ETHTOOL_A_HEADER_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_BITSET_BIT_UNSPEC,
+ ETHTOOL_A_BITSET_BIT_INDEX,
+ ETHTOOL_A_BITSET_BIT_NAME,
+ ETHTOOL_A_BITSET_BIT_VALUE,
+
+ __ETHTOOL_A_BITSET_BIT_CNT,
+ ETHTOOL_A_BITSET_BIT_MAX = (__ETHTOOL_A_BITSET_BIT_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_BITSET_BITS_UNSPEC,
+ ETHTOOL_A_BITSET_BITS_BIT,
+
+ __ETHTOOL_A_BITSET_BITS_CNT,
+ ETHTOOL_A_BITSET_BITS_MAX = (__ETHTOOL_A_BITSET_BITS_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_BITSET_UNSPEC,
+ ETHTOOL_A_BITSET_NOMASK,
+ ETHTOOL_A_BITSET_SIZE,
+ ETHTOOL_A_BITSET_BITS,
+ ETHTOOL_A_BITSET_VALUE,
+ ETHTOOL_A_BITSET_MASK,
+
+ __ETHTOOL_A_BITSET_CNT,
+ ETHTOOL_A_BITSET_MAX = (__ETHTOOL_A_BITSET_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_STRING_UNSPEC,
+ ETHTOOL_A_STRING_INDEX,
+ ETHTOOL_A_STRING_VALUE,
+
+ __ETHTOOL_A_STRING_CNT,
+ ETHTOOL_A_STRING_MAX = (__ETHTOOL_A_STRING_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_STRINGS_UNSPEC,
+ ETHTOOL_A_STRINGS_STRING,
+
+ __ETHTOOL_A_STRINGS_CNT,
+ ETHTOOL_A_STRINGS_MAX = (__ETHTOOL_A_STRINGS_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_STRINGSET_UNSPEC,
+ ETHTOOL_A_STRINGSET_ID,
+ ETHTOOL_A_STRINGSET_COUNT,
+ ETHTOOL_A_STRINGSET_STRINGS,
+
+ __ETHTOOL_A_STRINGSET_CNT,
+ ETHTOOL_A_STRINGSET_MAX = (__ETHTOOL_A_STRINGSET_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_STRINGSETS_UNSPEC,
+ ETHTOOL_A_STRINGSETS_STRINGSET,
+
+ __ETHTOOL_A_STRINGSETS_CNT,
+ ETHTOOL_A_STRINGSETS_MAX = (__ETHTOOL_A_STRINGSETS_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_STRSET_UNSPEC,
+ ETHTOOL_A_STRSET_HEADER,
+ ETHTOOL_A_STRSET_STRINGSETS,
+ ETHTOOL_A_STRSET_COUNTS_ONLY,
+
+ __ETHTOOL_A_STRSET_CNT,
+ ETHTOOL_A_STRSET_MAX = (__ETHTOOL_A_STRSET_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_PRIVFLAGS_UNSPEC,
+ ETHTOOL_A_PRIVFLAGS_HEADER,
+ ETHTOOL_A_PRIVFLAGS_FLAGS,
+
+ __ETHTOOL_A_PRIVFLAGS_CNT,
+ ETHTOOL_A_PRIVFLAGS_MAX = (__ETHTOOL_A_PRIVFLAGS_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_RINGS_UNSPEC,
+ ETHTOOL_A_RINGS_HEADER,
+ ETHTOOL_A_RINGS_RX_MAX,
+ ETHTOOL_A_RINGS_RX_MINI_MAX,
+ ETHTOOL_A_RINGS_RX_JUMBO_MAX,
+ ETHTOOL_A_RINGS_TX_MAX,
+ ETHTOOL_A_RINGS_RX,
+ ETHTOOL_A_RINGS_RX_MINI,
+ ETHTOOL_A_RINGS_RX_JUMBO,
+ ETHTOOL_A_RINGS_TX,
+ ETHTOOL_A_RINGS_RX_BUF_LEN,
+ ETHTOOL_A_RINGS_TCP_DATA_SPLIT,
+ ETHTOOL_A_RINGS_CQE_SIZE,
+ ETHTOOL_A_RINGS_TX_PUSH,
+ ETHTOOL_A_RINGS_RX_PUSH,
+ ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN,
+ ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN_MAX,
+ ETHTOOL_A_RINGS_HDS_THRESH,
+ ETHTOOL_A_RINGS_HDS_THRESH_MAX,
+
+ __ETHTOOL_A_RINGS_CNT,
+ ETHTOOL_A_RINGS_MAX = (__ETHTOOL_A_RINGS_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_MM_STAT_UNSPEC,
+ ETHTOOL_A_MM_STAT_PAD,
+ ETHTOOL_A_MM_STAT_REASSEMBLY_ERRORS,
+ ETHTOOL_A_MM_STAT_SMD_ERRORS,
+ ETHTOOL_A_MM_STAT_REASSEMBLY_OK,
+ ETHTOOL_A_MM_STAT_RX_FRAG_COUNT,
+ ETHTOOL_A_MM_STAT_TX_FRAG_COUNT,
+ ETHTOOL_A_MM_STAT_HOLD_COUNT,
+
+ __ETHTOOL_A_MM_STAT_CNT,
+ ETHTOOL_A_MM_STAT_MAX = (__ETHTOOL_A_MM_STAT_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_MM_UNSPEC,
+ ETHTOOL_A_MM_HEADER,
+ ETHTOOL_A_MM_PMAC_ENABLED,
+ ETHTOOL_A_MM_TX_ENABLED,
+ ETHTOOL_A_MM_TX_ACTIVE,
+ ETHTOOL_A_MM_TX_MIN_FRAG_SIZE,
+ ETHTOOL_A_MM_RX_MIN_FRAG_SIZE,
+ ETHTOOL_A_MM_VERIFY_ENABLED,
+ ETHTOOL_A_MM_VERIFY_STATUS,
+ ETHTOOL_A_MM_VERIFY_TIME,
+ ETHTOOL_A_MM_MAX_VERIFY_TIME,
+ ETHTOOL_A_MM_STATS,
+
+ __ETHTOOL_A_MM_CNT,
+ ETHTOOL_A_MM_MAX = (__ETHTOOL_A_MM_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_LINKINFO_UNSPEC,
+ ETHTOOL_A_LINKINFO_HEADER,
+ ETHTOOL_A_LINKINFO_PORT,
+ ETHTOOL_A_LINKINFO_PHYADDR,
+ ETHTOOL_A_LINKINFO_TP_MDIX,
+ ETHTOOL_A_LINKINFO_TP_MDIX_CTRL,
+ ETHTOOL_A_LINKINFO_TRANSCEIVER,
+
+ __ETHTOOL_A_LINKINFO_CNT,
+ ETHTOOL_A_LINKINFO_MAX = (__ETHTOOL_A_LINKINFO_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_LINKMODES_UNSPEC,
+ ETHTOOL_A_LINKMODES_HEADER,
+ ETHTOOL_A_LINKMODES_AUTONEG,
+ ETHTOOL_A_LINKMODES_OURS,
+ ETHTOOL_A_LINKMODES_PEER,
+ ETHTOOL_A_LINKMODES_SPEED,
+ ETHTOOL_A_LINKMODES_DUPLEX,
+ ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG,
+ ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE,
+ ETHTOOL_A_LINKMODES_LANES,
+ ETHTOOL_A_LINKMODES_RATE_MATCHING,
+
+ __ETHTOOL_A_LINKMODES_CNT,
+ ETHTOOL_A_LINKMODES_MAX = (__ETHTOOL_A_LINKMODES_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_LINKSTATE_UNSPEC,
+ ETHTOOL_A_LINKSTATE_HEADER,
+ ETHTOOL_A_LINKSTATE_LINK,
+ ETHTOOL_A_LINKSTATE_SQI,
+ ETHTOOL_A_LINKSTATE_SQI_MAX,
+ ETHTOOL_A_LINKSTATE_EXT_STATE,
+ ETHTOOL_A_LINKSTATE_EXT_SUBSTATE,
+ ETHTOOL_A_LINKSTATE_EXT_DOWN_CNT,
+
+ __ETHTOOL_A_LINKSTATE_CNT,
+ ETHTOOL_A_LINKSTATE_MAX = (__ETHTOOL_A_LINKSTATE_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_DEBUG_UNSPEC,
+ ETHTOOL_A_DEBUG_HEADER,
+ ETHTOOL_A_DEBUG_MSGMASK,
+
+ __ETHTOOL_A_DEBUG_CNT,
+ ETHTOOL_A_DEBUG_MAX = (__ETHTOOL_A_DEBUG_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_WOL_UNSPEC,
+ ETHTOOL_A_WOL_HEADER,
+ ETHTOOL_A_WOL_MODES,
+ ETHTOOL_A_WOL_SOPASS,
+
+ __ETHTOOL_A_WOL_CNT,
+ ETHTOOL_A_WOL_MAX = (__ETHTOOL_A_WOL_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_FEATURES_UNSPEC,
+ ETHTOOL_A_FEATURES_HEADER,
+ ETHTOOL_A_FEATURES_HW,
+ ETHTOOL_A_FEATURES_WANTED,
+ ETHTOOL_A_FEATURES_ACTIVE,
+ ETHTOOL_A_FEATURES_NOCHANGE,
+
+ __ETHTOOL_A_FEATURES_CNT,
+ ETHTOOL_A_FEATURES_MAX = (__ETHTOOL_A_FEATURES_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_CHANNELS_UNSPEC,
+ ETHTOOL_A_CHANNELS_HEADER,
+ ETHTOOL_A_CHANNELS_RX_MAX,
+ ETHTOOL_A_CHANNELS_TX_MAX,
+ ETHTOOL_A_CHANNELS_OTHER_MAX,
+ ETHTOOL_A_CHANNELS_COMBINED_MAX,
+ ETHTOOL_A_CHANNELS_RX_COUNT,
+ ETHTOOL_A_CHANNELS_TX_COUNT,
+ ETHTOOL_A_CHANNELS_OTHER_COUNT,
+ ETHTOOL_A_CHANNELS_COMBINED_COUNT,
+
+ __ETHTOOL_A_CHANNELS_CNT,
+ ETHTOOL_A_CHANNELS_MAX = (__ETHTOOL_A_CHANNELS_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_IRQ_MODERATION_UNSPEC,
+ ETHTOOL_A_IRQ_MODERATION_USEC,
+ ETHTOOL_A_IRQ_MODERATION_PKTS,
+ ETHTOOL_A_IRQ_MODERATION_COMPS,
+
+ __ETHTOOL_A_IRQ_MODERATION_CNT,
+ ETHTOOL_A_IRQ_MODERATION_MAX = (__ETHTOOL_A_IRQ_MODERATION_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_PROFILE_UNSPEC,
+ ETHTOOL_A_PROFILE_IRQ_MODERATION,
+
+ __ETHTOOL_A_PROFILE_CNT,
+ ETHTOOL_A_PROFILE_MAX = (__ETHTOOL_A_PROFILE_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_COALESCE_UNSPEC,
+ ETHTOOL_A_COALESCE_HEADER,
+ ETHTOOL_A_COALESCE_RX_USECS,
+ ETHTOOL_A_COALESCE_RX_MAX_FRAMES,
+ ETHTOOL_A_COALESCE_RX_USECS_IRQ,
+ ETHTOOL_A_COALESCE_RX_MAX_FRAMES_IRQ,
+ ETHTOOL_A_COALESCE_TX_USECS,
+ ETHTOOL_A_COALESCE_TX_MAX_FRAMES,
+ ETHTOOL_A_COALESCE_TX_USECS_IRQ,
+ ETHTOOL_A_COALESCE_TX_MAX_FRAMES_IRQ,
+ ETHTOOL_A_COALESCE_STATS_BLOCK_USECS,
+ ETHTOOL_A_COALESCE_USE_ADAPTIVE_RX,
+ ETHTOOL_A_COALESCE_USE_ADAPTIVE_TX,
+ ETHTOOL_A_COALESCE_PKT_RATE_LOW,
+ ETHTOOL_A_COALESCE_RX_USECS_LOW,
+ ETHTOOL_A_COALESCE_RX_MAX_FRAMES_LOW,
+ ETHTOOL_A_COALESCE_TX_USECS_LOW,
+ ETHTOOL_A_COALESCE_TX_MAX_FRAMES_LOW,
+ ETHTOOL_A_COALESCE_PKT_RATE_HIGH,
+ ETHTOOL_A_COALESCE_RX_USECS_HIGH,
+ ETHTOOL_A_COALESCE_RX_MAX_FRAMES_HIGH,
+ ETHTOOL_A_COALESCE_TX_USECS_HIGH,
+ ETHTOOL_A_COALESCE_TX_MAX_FRAMES_HIGH,
+ ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL,
+ ETHTOOL_A_COALESCE_USE_CQE_MODE_TX,
+ ETHTOOL_A_COALESCE_USE_CQE_MODE_RX,
+ ETHTOOL_A_COALESCE_TX_AGGR_MAX_BYTES,
+ ETHTOOL_A_COALESCE_TX_AGGR_MAX_FRAMES,
+ ETHTOOL_A_COALESCE_TX_AGGR_TIME_USECS,
+ ETHTOOL_A_COALESCE_RX_PROFILE,
+ ETHTOOL_A_COALESCE_TX_PROFILE,
+ ETHTOOL_A_COALESCE_RX_CQE_FRAMES,
+ ETHTOOL_A_COALESCE_RX_CQE_NSECS,
+
+ __ETHTOOL_A_COALESCE_CNT,
+ ETHTOOL_A_COALESCE_MAX = (__ETHTOOL_A_COALESCE_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_PAUSE_STAT_UNSPEC,
+ ETHTOOL_A_PAUSE_STAT_PAD,
+ ETHTOOL_A_PAUSE_STAT_TX_FRAMES,
+ ETHTOOL_A_PAUSE_STAT_RX_FRAMES,
+ ETHTOOL_A_PAUSE_STAT_TX_PAUSE_STORM_EVENTS,
+
+ __ETHTOOL_A_PAUSE_STAT_CNT,
+ ETHTOOL_A_PAUSE_STAT_MAX = (__ETHTOOL_A_PAUSE_STAT_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_PAUSE_UNSPEC,
+ ETHTOOL_A_PAUSE_HEADER,
+ ETHTOOL_A_PAUSE_AUTONEG,
+ ETHTOOL_A_PAUSE_RX,
+ ETHTOOL_A_PAUSE_TX,
+ ETHTOOL_A_PAUSE_STATS,
+ ETHTOOL_A_PAUSE_STATS_SRC,
+
+ __ETHTOOL_A_PAUSE_CNT,
+ ETHTOOL_A_PAUSE_MAX = (__ETHTOOL_A_PAUSE_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_EEE_UNSPEC,
+ ETHTOOL_A_EEE_HEADER,
+ ETHTOOL_A_EEE_MODES_OURS,
+ ETHTOOL_A_EEE_MODES_PEER,
+ ETHTOOL_A_EEE_ACTIVE,
+ ETHTOOL_A_EEE_ENABLED,
+ ETHTOOL_A_EEE_TX_LPI_ENABLED,
+ ETHTOOL_A_EEE_TX_LPI_TIMER,
+
+ __ETHTOOL_A_EEE_CNT,
+ ETHTOOL_A_EEE_MAX = (__ETHTOOL_A_EEE_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_TS_STAT_UNSPEC,
+ ETHTOOL_A_TS_STAT_TX_PKTS,
+ ETHTOOL_A_TS_STAT_TX_LOST,
+ ETHTOOL_A_TS_STAT_TX_ERR,
+ ETHTOOL_A_TS_STAT_TX_ONESTEP_PKTS_UNCONFIRMED,
+
+ __ETHTOOL_A_TS_STAT_CNT,
+ ETHTOOL_A_TS_STAT_MAX = (__ETHTOOL_A_TS_STAT_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_TS_HWTSTAMP_PROVIDER_UNSPEC,
+ ETHTOOL_A_TS_HWTSTAMP_PROVIDER_INDEX,
+ ETHTOOL_A_TS_HWTSTAMP_PROVIDER_QUALIFIER,
+
+ __ETHTOOL_A_TS_HWTSTAMP_PROVIDER_CNT,
+ ETHTOOL_A_TS_HWTSTAMP_PROVIDER_MAX = (__ETHTOOL_A_TS_HWTSTAMP_PROVIDER_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_TSINFO_UNSPEC,
+ ETHTOOL_A_TSINFO_HEADER,
+ ETHTOOL_A_TSINFO_TIMESTAMPING,
+ ETHTOOL_A_TSINFO_TX_TYPES,
+ ETHTOOL_A_TSINFO_RX_FILTERS,
+ ETHTOOL_A_TSINFO_PHC_INDEX,
+ ETHTOOL_A_TSINFO_STATS,
+ ETHTOOL_A_TSINFO_HWTSTAMP_PROVIDER,
+ ETHTOOL_A_TSINFO_HWTSTAMP_SOURCE,
+ ETHTOOL_A_TSINFO_HWTSTAMP_PHYINDEX,
+
+ __ETHTOOL_A_TSINFO_CNT,
+ ETHTOOL_A_TSINFO_MAX = (__ETHTOOL_A_TSINFO_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_CABLE_RESULT_UNSPEC,
+ ETHTOOL_A_CABLE_RESULT_PAIR,
+ ETHTOOL_A_CABLE_RESULT_CODE,
+ ETHTOOL_A_CABLE_RESULT_SRC,
+
+ __ETHTOOL_A_CABLE_RESULT_CNT,
+ ETHTOOL_A_CABLE_RESULT_MAX = (__ETHTOOL_A_CABLE_RESULT_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_CABLE_FAULT_LENGTH_UNSPEC,
+ ETHTOOL_A_CABLE_FAULT_LENGTH_PAIR,
+ ETHTOOL_A_CABLE_FAULT_LENGTH_CM,
+ ETHTOOL_A_CABLE_FAULT_LENGTH_SRC,
+
+ __ETHTOOL_A_CABLE_FAULT_LENGTH_CNT,
+ ETHTOOL_A_CABLE_FAULT_LENGTH_MAX = (__ETHTOOL_A_CABLE_FAULT_LENGTH_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_CABLE_NEST_UNSPEC,
+ ETHTOOL_A_CABLE_NEST_RESULT,
+ ETHTOOL_A_CABLE_NEST_FAULT_LENGTH,
+
+ __ETHTOOL_A_CABLE_NEST_CNT,
+ ETHTOOL_A_CABLE_NEST_MAX = (__ETHTOOL_A_CABLE_NEST_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_CABLE_TEST_UNSPEC,
+ ETHTOOL_A_CABLE_TEST_HEADER,
+
+ __ETHTOOL_A_CABLE_TEST_CNT,
+ ETHTOOL_A_CABLE_TEST_MAX = (__ETHTOOL_A_CABLE_TEST_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_CABLE_TEST_NTF_UNSPEC,
+ ETHTOOL_A_CABLE_TEST_NTF_HEADER,
+ ETHTOOL_A_CABLE_TEST_NTF_STATUS,
+ ETHTOOL_A_CABLE_TEST_NTF_NEST,
+
+ __ETHTOOL_A_CABLE_TEST_NTF_CNT,
+ ETHTOOL_A_CABLE_TEST_NTF_MAX = (__ETHTOOL_A_CABLE_TEST_NTF_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_CABLE_TEST_TDR_CFG_UNSPEC,
+ ETHTOOL_A_CABLE_TEST_TDR_CFG_FIRST,
+ ETHTOOL_A_CABLE_TEST_TDR_CFG_LAST,
+ ETHTOOL_A_CABLE_TEST_TDR_CFG_STEP,
+ ETHTOOL_A_CABLE_TEST_TDR_CFG_PAIR,
+
+ __ETHTOOL_A_CABLE_TEST_TDR_CFG_CNT,
+ ETHTOOL_A_CABLE_TEST_TDR_CFG_MAX = (__ETHTOOL_A_CABLE_TEST_TDR_CFG_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_CABLE_TEST_TDR_NTF_UNSPEC,
+ ETHTOOL_A_CABLE_TEST_TDR_NTF_HEADER,
+ ETHTOOL_A_CABLE_TEST_TDR_NTF_STATUS,
+ ETHTOOL_A_CABLE_TEST_TDR_NTF_NEST,
+
+ __ETHTOOL_A_CABLE_TEST_TDR_NTF_CNT,
+ ETHTOOL_A_CABLE_TEST_TDR_NTF_MAX = (__ETHTOOL_A_CABLE_TEST_TDR_NTF_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_CABLE_TEST_TDR_UNSPEC,
+ ETHTOOL_A_CABLE_TEST_TDR_HEADER,
+ ETHTOOL_A_CABLE_TEST_TDR_CFG,
+
+ __ETHTOOL_A_CABLE_TEST_TDR_CNT,
+ ETHTOOL_A_CABLE_TEST_TDR_MAX = (__ETHTOOL_A_CABLE_TEST_TDR_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_TUNNEL_UDP_ENTRY_UNSPEC,
+ ETHTOOL_A_TUNNEL_UDP_ENTRY_PORT,
+ ETHTOOL_A_TUNNEL_UDP_ENTRY_TYPE,
+
+ __ETHTOOL_A_TUNNEL_UDP_ENTRY_CNT,
+ ETHTOOL_A_TUNNEL_UDP_ENTRY_MAX = (__ETHTOOL_A_TUNNEL_UDP_ENTRY_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_TUNNEL_UDP_TABLE_UNSPEC,
+ ETHTOOL_A_TUNNEL_UDP_TABLE_SIZE,
+ ETHTOOL_A_TUNNEL_UDP_TABLE_TYPES,
+ ETHTOOL_A_TUNNEL_UDP_TABLE_ENTRY,
+
+ __ETHTOOL_A_TUNNEL_UDP_TABLE_CNT,
+ ETHTOOL_A_TUNNEL_UDP_TABLE_MAX = (__ETHTOOL_A_TUNNEL_UDP_TABLE_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_TUNNEL_UDP_UNSPEC,
+ ETHTOOL_A_TUNNEL_UDP_TABLE,
+
+ __ETHTOOL_A_TUNNEL_UDP_CNT,
+ ETHTOOL_A_TUNNEL_UDP_MAX = (__ETHTOOL_A_TUNNEL_UDP_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_TUNNEL_INFO_UNSPEC,
+ ETHTOOL_A_TUNNEL_INFO_HEADER,
+ ETHTOOL_A_TUNNEL_INFO_UDP_PORTS,
+
+ __ETHTOOL_A_TUNNEL_INFO_CNT,
+ ETHTOOL_A_TUNNEL_INFO_MAX = (__ETHTOOL_A_TUNNEL_INFO_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_FEC_HIST_PAD = 1,
+ ETHTOOL_A_FEC_HIST_BIN_LOW,
+ ETHTOOL_A_FEC_HIST_BIN_HIGH,
+ ETHTOOL_A_FEC_HIST_BIN_VAL,
+ ETHTOOL_A_FEC_HIST_BIN_VAL_PER_LANE,
+
+ __ETHTOOL_A_FEC_HIST_CNT,
+ ETHTOOL_A_FEC_HIST_MAX = (__ETHTOOL_A_FEC_HIST_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_FEC_STAT_UNSPEC,
+ ETHTOOL_A_FEC_STAT_PAD,
+ ETHTOOL_A_FEC_STAT_CORRECTED,
+ ETHTOOL_A_FEC_STAT_UNCORR,
+ ETHTOOL_A_FEC_STAT_CORR_BITS,
+ ETHTOOL_A_FEC_STAT_HIST,
+
+ __ETHTOOL_A_FEC_STAT_CNT,
+ ETHTOOL_A_FEC_STAT_MAX = (__ETHTOOL_A_FEC_STAT_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_FEC_UNSPEC,
+ ETHTOOL_A_FEC_HEADER,
+ ETHTOOL_A_FEC_MODES,
+ ETHTOOL_A_FEC_AUTO,
+ ETHTOOL_A_FEC_ACTIVE,
+ ETHTOOL_A_FEC_STATS,
+
+ __ETHTOOL_A_FEC_CNT,
+ ETHTOOL_A_FEC_MAX = (__ETHTOOL_A_FEC_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_MODULE_EEPROM_UNSPEC,
+ ETHTOOL_A_MODULE_EEPROM_HEADER,
+ ETHTOOL_A_MODULE_EEPROM_OFFSET,
+ ETHTOOL_A_MODULE_EEPROM_LENGTH,
+ ETHTOOL_A_MODULE_EEPROM_PAGE,
+ ETHTOOL_A_MODULE_EEPROM_BANK,
+ ETHTOOL_A_MODULE_EEPROM_I2C_ADDRESS,
+ ETHTOOL_A_MODULE_EEPROM_DATA,
+
+ __ETHTOOL_A_MODULE_EEPROM_CNT,
+ ETHTOOL_A_MODULE_EEPROM_MAX = (__ETHTOOL_A_MODULE_EEPROM_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_STATS_GRP_UNSPEC,
+ ETHTOOL_A_STATS_GRP_PAD,
+ ETHTOOL_A_STATS_GRP_ID,
+ ETHTOOL_A_STATS_GRP_SS_ID,
+ ETHTOOL_A_STATS_GRP_STAT,
+ ETHTOOL_A_STATS_GRP_HIST_RX,
+ ETHTOOL_A_STATS_GRP_HIST_TX,
+ ETHTOOL_A_STATS_GRP_HIST_BKT_LOW,
+ ETHTOOL_A_STATS_GRP_HIST_BKT_HI,
+ ETHTOOL_A_STATS_GRP_HIST_VAL,
+
+ __ETHTOOL_A_STATS_GRP_CNT,
+ ETHTOOL_A_STATS_GRP_MAX = (__ETHTOOL_A_STATS_GRP_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_STATS_UNSPEC,
+ ETHTOOL_A_STATS_PAD,
+ ETHTOOL_A_STATS_HEADER,
+ ETHTOOL_A_STATS_GROUPS,
+ ETHTOOL_A_STATS_GRP,
+ ETHTOOL_A_STATS_SRC,
+
+ __ETHTOOL_A_STATS_CNT,
+ ETHTOOL_A_STATS_MAX = (__ETHTOOL_A_STATS_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_PHC_VCLOCKS_UNSPEC,
+ ETHTOOL_A_PHC_VCLOCKS_HEADER,
+ ETHTOOL_A_PHC_VCLOCKS_NUM,
+ ETHTOOL_A_PHC_VCLOCKS_INDEX,
+
+ __ETHTOOL_A_PHC_VCLOCKS_CNT,
+ ETHTOOL_A_PHC_VCLOCKS_MAX = (__ETHTOOL_A_PHC_VCLOCKS_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_MODULE_UNSPEC,
+ ETHTOOL_A_MODULE_HEADER,
+ ETHTOOL_A_MODULE_POWER_MODE_POLICY,
+ ETHTOOL_A_MODULE_POWER_MODE,
+
+ __ETHTOOL_A_MODULE_CNT,
+ ETHTOOL_A_MODULE_MAX = (__ETHTOOL_A_MODULE_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_C33_PSE_PW_LIMIT_UNSPEC,
+ ETHTOOL_A_C33_PSE_PW_LIMIT_MIN,
+ ETHTOOL_A_C33_PSE_PW_LIMIT_MAX,
+
+ __ETHTOOL_A_C33_PSE_PW_LIMIT_CNT,
+ __ETHTOOL_A_C33_PSE_PW_LIMIT_MAX = (__ETHTOOL_A_C33_PSE_PW_LIMIT_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_PSE_UNSPEC,
+ ETHTOOL_A_PSE_HEADER,
+ ETHTOOL_A_PODL_PSE_ADMIN_STATE,
+ ETHTOOL_A_PODL_PSE_ADMIN_CONTROL,
+ ETHTOOL_A_PODL_PSE_PW_D_STATUS,
+ ETHTOOL_A_C33_PSE_ADMIN_STATE,
+ ETHTOOL_A_C33_PSE_ADMIN_CONTROL,
+ ETHTOOL_A_C33_PSE_PW_D_STATUS,
+ ETHTOOL_A_C33_PSE_PW_CLASS,
+ ETHTOOL_A_C33_PSE_ACTUAL_PW,
+ ETHTOOL_A_C33_PSE_EXT_STATE,
+ ETHTOOL_A_C33_PSE_EXT_SUBSTATE,
+ ETHTOOL_A_C33_PSE_AVAIL_PW_LIMIT,
+ ETHTOOL_A_C33_PSE_PW_LIMIT_RANGES,
+ ETHTOOL_A_PSE_PW_D_ID,
+ ETHTOOL_A_PSE_PRIO_MAX,
+ ETHTOOL_A_PSE_PRIO,
+
+ __ETHTOOL_A_PSE_CNT,
+ ETHTOOL_A_PSE_MAX = (__ETHTOOL_A_PSE_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_FLOW_ETHER = 1,
+ ETHTOOL_A_FLOW_IP4,
+ ETHTOOL_A_FLOW_IP6,
+ ETHTOOL_A_FLOW_TCP4,
+ ETHTOOL_A_FLOW_TCP6,
+ ETHTOOL_A_FLOW_UDP4,
+ ETHTOOL_A_FLOW_UDP6,
+ ETHTOOL_A_FLOW_SCTP4,
+ ETHTOOL_A_FLOW_SCTP6,
+ ETHTOOL_A_FLOW_AH4,
+ ETHTOOL_A_FLOW_AH6,
+ ETHTOOL_A_FLOW_ESP4,
+ ETHTOOL_A_FLOW_ESP6,
+ ETHTOOL_A_FLOW_AH_ESP4,
+ ETHTOOL_A_FLOW_AH_ESP6,
+ ETHTOOL_A_FLOW_GTPU4,
+ ETHTOOL_A_FLOW_GTPU6,
+ ETHTOOL_A_FLOW_GTPC4,
+ ETHTOOL_A_FLOW_GTPC6,
+ ETHTOOL_A_FLOW_GTPC_TEID4,
+ ETHTOOL_A_FLOW_GTPC_TEID6,
+ ETHTOOL_A_FLOW_GTPU_EH4,
+ ETHTOOL_A_FLOW_GTPU_EH6,
+ ETHTOOL_A_FLOW_GTPU_UL4,
+ ETHTOOL_A_FLOW_GTPU_UL6,
+ ETHTOOL_A_FLOW_GTPU_DL4,
+ ETHTOOL_A_FLOW_GTPU_DL6,
+
+ __ETHTOOL_A_FLOW_CNT,
+ ETHTOOL_A_FLOW_MAX = (__ETHTOOL_A_FLOW_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_RSS_UNSPEC,
+ ETHTOOL_A_RSS_HEADER,
+ ETHTOOL_A_RSS_CONTEXT,
+ ETHTOOL_A_RSS_HFUNC,
+ ETHTOOL_A_RSS_INDIR,
+ ETHTOOL_A_RSS_HKEY,
+ ETHTOOL_A_RSS_INPUT_XFRM,
+ ETHTOOL_A_RSS_START_CONTEXT,
+ ETHTOOL_A_RSS_FLOW_HASH,
+
+ __ETHTOOL_A_RSS_CNT,
+ ETHTOOL_A_RSS_MAX = (__ETHTOOL_A_RSS_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_PLCA_UNSPEC,
+ ETHTOOL_A_PLCA_HEADER,
+ ETHTOOL_A_PLCA_VERSION,
+ ETHTOOL_A_PLCA_ENABLED,
+ ETHTOOL_A_PLCA_STATUS,
+ ETHTOOL_A_PLCA_NODE_CNT,
+ ETHTOOL_A_PLCA_NODE_ID,
+ ETHTOOL_A_PLCA_TO_TMR,
+ ETHTOOL_A_PLCA_BURST_CNT,
+ ETHTOOL_A_PLCA_BURST_TMR,
+
+ __ETHTOOL_A_PLCA_CNT,
+ ETHTOOL_A_PLCA_MAX = (__ETHTOOL_A_PLCA_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_MODULE_FW_FLASH_UNSPEC,
+ ETHTOOL_A_MODULE_FW_FLASH_HEADER,
+ ETHTOOL_A_MODULE_FW_FLASH_FILE_NAME,
+ ETHTOOL_A_MODULE_FW_FLASH_PASSWORD,
+ ETHTOOL_A_MODULE_FW_FLASH_STATUS,
+ ETHTOOL_A_MODULE_FW_FLASH_STATUS_MSG,
+ ETHTOOL_A_MODULE_FW_FLASH_DONE,
+ ETHTOOL_A_MODULE_FW_FLASH_TOTAL,
+
+ __ETHTOOL_A_MODULE_FW_FLASH_CNT,
+ ETHTOOL_A_MODULE_FW_FLASH_MAX = (__ETHTOOL_A_MODULE_FW_FLASH_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_PHY_UNSPEC,
+ ETHTOOL_A_PHY_HEADER,
+ ETHTOOL_A_PHY_INDEX,
+ ETHTOOL_A_PHY_DRVNAME,
+ ETHTOOL_A_PHY_NAME,
+ ETHTOOL_A_PHY_UPSTREAM_TYPE,
+ ETHTOOL_A_PHY_UPSTREAM_INDEX,
+ ETHTOOL_A_PHY_UPSTREAM_SFP_NAME,
+ ETHTOOL_A_PHY_DOWNSTREAM_SFP_NAME,
+
+ __ETHTOOL_A_PHY_CNT,
+ ETHTOOL_A_PHY_MAX = (__ETHTOOL_A_PHY_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_TSCONFIG_UNSPEC,
+ ETHTOOL_A_TSCONFIG_HEADER,
+ ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER,
+ ETHTOOL_A_TSCONFIG_TX_TYPES,
+ ETHTOOL_A_TSCONFIG_RX_FILTERS,
+ ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS,
+
+ __ETHTOOL_A_TSCONFIG_CNT,
+ ETHTOOL_A_TSCONFIG_MAX = (__ETHTOOL_A_TSCONFIG_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_PSE_NTF_HEADER = 1,
+ ETHTOOL_A_PSE_NTF_EVENTS,
+
+ __ETHTOOL_A_PSE_NTF_CNT,
+ ETHTOOL_A_PSE_NTF_MAX = (__ETHTOOL_A_PSE_NTF_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_MSE_CAPABILITIES_MAX_AVERAGE_MSE = 1,
+ ETHTOOL_A_MSE_CAPABILITIES_MAX_PEAK_MSE,
+ ETHTOOL_A_MSE_CAPABILITIES_REFRESH_RATE_PS,
+ ETHTOOL_A_MSE_CAPABILITIES_NUM_SYMBOLS,
+
+ __ETHTOOL_A_MSE_CAPABILITIES_CNT,
+ ETHTOOL_A_MSE_CAPABILITIES_MAX = (__ETHTOOL_A_MSE_CAPABILITIES_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_MSE_SNAPSHOT_AVERAGE_MSE = 1,
+ ETHTOOL_A_MSE_SNAPSHOT_PEAK_MSE,
+ ETHTOOL_A_MSE_SNAPSHOT_WORST_PEAK_MSE,
+
+ __ETHTOOL_A_MSE_SNAPSHOT_CNT,
+ ETHTOOL_A_MSE_SNAPSHOT_MAX = (__ETHTOOL_A_MSE_SNAPSHOT_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_MSE_HEADER = 1,
+ ETHTOOL_A_MSE_CAPABILITIES,
+ ETHTOOL_A_MSE_CHANNEL_A,
+ ETHTOOL_A_MSE_CHANNEL_B,
+ ETHTOOL_A_MSE_CHANNEL_C,
+ ETHTOOL_A_MSE_CHANNEL_D,
+ ETHTOOL_A_MSE_WORST_CHANNEL,
+ ETHTOOL_A_MSE_LINK,
+
+ __ETHTOOL_A_MSE_CNT,
+ ETHTOOL_A_MSE_MAX = (__ETHTOOL_A_MSE_CNT - 1)
+};
+
+enum {
+ ETHTOOL_MSG_USER_NONE = 0,
+ ETHTOOL_MSG_STRSET_GET = 1,
+ ETHTOOL_MSG_LINKINFO_GET,
+ ETHTOOL_MSG_LINKINFO_SET,
+ ETHTOOL_MSG_LINKMODES_GET,
+ ETHTOOL_MSG_LINKMODES_SET,
+ ETHTOOL_MSG_LINKSTATE_GET,
+ ETHTOOL_MSG_DEBUG_GET,
+ ETHTOOL_MSG_DEBUG_SET,
+ ETHTOOL_MSG_WOL_GET,
+ ETHTOOL_MSG_WOL_SET,
+ ETHTOOL_MSG_FEATURES_GET,
+ ETHTOOL_MSG_FEATURES_SET,
+ ETHTOOL_MSG_PRIVFLAGS_GET,
+ ETHTOOL_MSG_PRIVFLAGS_SET,
+ ETHTOOL_MSG_RINGS_GET,
+ ETHTOOL_MSG_RINGS_SET,
+ ETHTOOL_MSG_CHANNELS_GET,
+ ETHTOOL_MSG_CHANNELS_SET,
+ ETHTOOL_MSG_COALESCE_GET,
+ ETHTOOL_MSG_COALESCE_SET,
+ ETHTOOL_MSG_PAUSE_GET,
+ ETHTOOL_MSG_PAUSE_SET,
+ ETHTOOL_MSG_EEE_GET,
+ ETHTOOL_MSG_EEE_SET,
+ ETHTOOL_MSG_TSINFO_GET,
+ ETHTOOL_MSG_CABLE_TEST_ACT,
+ ETHTOOL_MSG_CABLE_TEST_TDR_ACT,
+ ETHTOOL_MSG_TUNNEL_INFO_GET,
+ ETHTOOL_MSG_FEC_GET,
+ ETHTOOL_MSG_FEC_SET,
+ ETHTOOL_MSG_MODULE_EEPROM_GET,
+ ETHTOOL_MSG_STATS_GET,
+ ETHTOOL_MSG_PHC_VCLOCKS_GET,
+ ETHTOOL_MSG_MODULE_GET,
+ ETHTOOL_MSG_MODULE_SET,
+ ETHTOOL_MSG_PSE_GET,
+ ETHTOOL_MSG_PSE_SET,
+ ETHTOOL_MSG_RSS_GET,
+ ETHTOOL_MSG_PLCA_GET_CFG,
+ ETHTOOL_MSG_PLCA_SET_CFG,
+ ETHTOOL_MSG_PLCA_GET_STATUS,
+ ETHTOOL_MSG_MM_GET,
+ ETHTOOL_MSG_MM_SET,
+ ETHTOOL_MSG_MODULE_FW_FLASH_ACT,
+ ETHTOOL_MSG_PHY_GET,
+ ETHTOOL_MSG_TSCONFIG_GET,
+ ETHTOOL_MSG_TSCONFIG_SET,
+ ETHTOOL_MSG_RSS_SET,
+ ETHTOOL_MSG_RSS_CREATE_ACT,
+ ETHTOOL_MSG_RSS_DELETE_ACT,
+ ETHTOOL_MSG_MSE_GET,
+
+ __ETHTOOL_MSG_USER_CNT,
+ ETHTOOL_MSG_USER_MAX = (__ETHTOOL_MSG_USER_CNT - 1)
+};
+
+enum {
+ ETHTOOL_MSG_KERNEL_NONE = 0,
+ ETHTOOL_MSG_STRSET_GET_REPLY = 1,
+ ETHTOOL_MSG_LINKINFO_GET_REPLY,
+ ETHTOOL_MSG_LINKINFO_NTF,
+ ETHTOOL_MSG_LINKMODES_GET_REPLY,
+ ETHTOOL_MSG_LINKMODES_NTF,
+ ETHTOOL_MSG_LINKSTATE_GET_REPLY,
+ ETHTOOL_MSG_DEBUG_GET_REPLY,
+ ETHTOOL_MSG_DEBUG_NTF,
+ ETHTOOL_MSG_WOL_GET_REPLY,
+ ETHTOOL_MSG_WOL_NTF,
+ ETHTOOL_MSG_FEATURES_GET_REPLY,
+ ETHTOOL_MSG_FEATURES_SET_REPLY,
+ ETHTOOL_MSG_FEATURES_NTF,
+ ETHTOOL_MSG_PRIVFLAGS_GET_REPLY,
+ ETHTOOL_MSG_PRIVFLAGS_NTF,
+ ETHTOOL_MSG_RINGS_GET_REPLY,
+ ETHTOOL_MSG_RINGS_NTF,
+ ETHTOOL_MSG_CHANNELS_GET_REPLY,
+ ETHTOOL_MSG_CHANNELS_NTF,
+ ETHTOOL_MSG_COALESCE_GET_REPLY,
+ ETHTOOL_MSG_COALESCE_NTF,
+ ETHTOOL_MSG_PAUSE_GET_REPLY,
+ ETHTOOL_MSG_PAUSE_NTF,
+ ETHTOOL_MSG_EEE_GET_REPLY,
+ ETHTOOL_MSG_EEE_NTF,
+ ETHTOOL_MSG_TSINFO_GET_REPLY,
+ ETHTOOL_MSG_CABLE_TEST_NTF,
+ ETHTOOL_MSG_CABLE_TEST_TDR_NTF,
+ ETHTOOL_MSG_TUNNEL_INFO_GET_REPLY,
+ ETHTOOL_MSG_FEC_GET_REPLY,
+ ETHTOOL_MSG_FEC_NTF,
+ ETHTOOL_MSG_MODULE_EEPROM_GET_REPLY,
+ ETHTOOL_MSG_STATS_GET_REPLY,
+ ETHTOOL_MSG_PHC_VCLOCKS_GET_REPLY,
+ ETHTOOL_MSG_MODULE_GET_REPLY,
+ ETHTOOL_MSG_MODULE_NTF,
+ ETHTOOL_MSG_PSE_GET_REPLY,
+ ETHTOOL_MSG_RSS_GET_REPLY,
+ ETHTOOL_MSG_PLCA_GET_CFG_REPLY,
+ ETHTOOL_MSG_PLCA_GET_STATUS_REPLY,
+ ETHTOOL_MSG_PLCA_NTF,
+ ETHTOOL_MSG_MM_GET_REPLY,
+ ETHTOOL_MSG_MM_NTF,
+ ETHTOOL_MSG_MODULE_FW_FLASH_NTF,
+ ETHTOOL_MSG_PHY_GET_REPLY,
+ ETHTOOL_MSG_PHY_NTF,
+ ETHTOOL_MSG_TSCONFIG_GET_REPLY,
+ ETHTOOL_MSG_TSCONFIG_SET_REPLY,
+ ETHTOOL_MSG_PSE_NTF,
+ ETHTOOL_MSG_RSS_NTF,
+ ETHTOOL_MSG_RSS_CREATE_ACT_REPLY,
+ ETHTOOL_MSG_RSS_CREATE_NTF,
+ ETHTOOL_MSG_RSS_DELETE_NTF,
+ ETHTOOL_MSG_MSE_GET_REPLY,
+
+ __ETHTOOL_MSG_KERNEL_CNT,
+ ETHTOOL_MSG_KERNEL_MAX = (__ETHTOOL_MSG_KERNEL_CNT - 1)
+};
+
+#define ETHTOOL_MCGRP_MONITOR_NAME "monitor"
+
+#endif /* _LINUX_ETHTOOL_NETLINK_GENERATED_H */
diff --git a/src/libsystemd/sd-netlink/netlink-genl.c b/src/libsystemd/sd-netlink/netlink-genl.c
index d4d33ae52da..2becbdf801e 100644
--- a/src/libsystemd/sd-netlink/netlink-genl.c
+++ b/src/libsystemd/sd-netlink/netlink-genl.c
@@ -16,6 +16,7 @@ typedef struct GenericNetlinkFamily {
sd_netlink *genl;
const NLAPolicySet *policy_set;
+ bool policy_set_indexed_by_command;
uint16_t id; /* a.k.a nlmsg_type */
char *name;
@@ -87,6 +88,7 @@ static int genl_family_new_unsupported(
*f = (GenericNetlinkFamily) {
.policy_set = policy_set,
+ .policy_set_indexed_by_command = genl_family_is_indexed_by_command(family_name),
};
f->name = strdup(family_name);
@@ -126,6 +128,7 @@ static int genl_family_new(
*f = (GenericNetlinkFamily) {
.policy_set = policy_set,
+ .policy_set_indexed_by_command = genl_family_is_indexed_by_command(expected_family_name),
};
r = sd_genl_message_get_family_name(nl, message, &family_name);
@@ -227,6 +230,12 @@ static const NLAPolicySet *genl_family_get_policy_set(const GenericNetlinkFamily
return genl_get_policy_set_by_name(family->name);
}
+static size_t genl_family_get_header_size(const GenericNetlinkFamily *family) {
+ assert(family);
+
+ return sizeof(struct genlmsghdr) + family->additional_header_size;
+}
+
static int genl_message_new(
sd_netlink *nl,
const GenericNetlinkFamily *family,
@@ -246,8 +255,14 @@ static int genl_message_new(
if (!policy_set)
return -EOPNOTSUPP;
+ if (family->policy_set_indexed_by_command) {
+ policy_set = policy_set_get_policy_set(policy_set, cmd);
+ if (!policy_set)
+ return -EOPNOTSUPP;
+ }
+
r = message_new_full(nl, family->id, NLM_F_REQUEST | NLM_F_ACK, policy_set,
- sizeof(struct genlmsghdr) + family->additional_header_size, &m);
+ genl_family_get_header_size(family), &m);
if (r < 0)
return r;
@@ -364,6 +379,12 @@ int genl_get_policy_set_and_header_size(
if (r < 0)
return r;
+ /* For families whose policy sets are indexed by command, the kernel to userspace commands are
+ * numbered separately from the userspace to kernel commands and the two overlap. Parsing replies
+ * and notifications of such families is not supported yet. */
+ if (f->policy_set_indexed_by_command)
+ return -EOPNOTSUPP;
+
if (ret_policy_set) {
const NLAPolicySet *p;
@@ -374,7 +395,7 @@ int genl_get_policy_set_and_header_size(
*ret_policy_set = p;
}
if (ret_header_size)
- *ret_header_size = sizeof(struct genlmsghdr) + f->additional_header_size;
+ *ret_header_size = genl_family_get_header_size(f);
return 0;
}
@@ -417,9 +438,9 @@ int sd_genl_message_get_family_name(sd_netlink *nl, sd_netlink_message *m, const
}
int sd_genl_message_get_command(sd_netlink *nl, sd_netlink_message *m, uint8_t *ret) {
+ const GenericNetlinkFamily *family;
struct genlmsghdr *h;
uint16_t nlmsg_type;
- size_t size;
int r;
assert_return(nl, -EINVAL);
@@ -433,11 +454,11 @@ int sd_genl_message_get_command(sd_netlink *nl, sd_netlink_message *m, uint8_t *
if (r < 0)
return r;
- r = genl_get_policy_set_and_header_size(nl, nlmsg_type, NULL, &size);
+ r = genl_family_get_by_id(nl, nlmsg_type, &family);
if (r < 0)
return r;
- if (m->hdr->nlmsg_len < NLMSG_LENGTH(size))
+ if (m->hdr->nlmsg_len < NLMSG_LENGTH(genl_family_get_header_size(family)))
return -EBADMSG;
h = NLMSG_DATA(m->hdr);
diff --git a/src/libsystemd/sd-netlink/netlink-types-genl.c b/src/libsystemd/sd-netlink/netlink-types-genl.c
index e97d9012235..84eed0b1455 100644
--- a/src/libsystemd/sd-netlink/netlink-types-genl.c
+++ b/src/libsystemd/sd-netlink/netlink-types-genl.c
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include
+#include
#include
#include
#include
@@ -14,6 +15,7 @@
#include "missing-network.h"
#include "netlink-genl.h"
#include "netlink-types-internal.h"
+#include "string-util.h"
/***************** genl ctrl type systems *****************/
static const NLAPolicy genl_ctrl_mcast_group_policies[] = {
@@ -109,6 +111,74 @@ static const NLAPolicy genl_batadv_policies[] = {
[BATADV_ATTR_THROUGHPUT_OVERRIDE] = BUILD_POLICY(U32),
};
+/***************** genl ethtool type systems *****************/
+static const NLAPolicy genl_ethtool_header_policies[] = {
+ [ETHTOOL_A_HEADER_DEV_INDEX] = BUILD_POLICY(U32),
+ [ETHTOOL_A_HEADER_DEV_NAME] = BUILD_POLICY_WITH_SIZE(STRING, ALTIFNAMSIZ - 1),
+ [ETHTOOL_A_HEADER_FLAGS] = BUILD_POLICY(U32),
+ [ETHTOOL_A_HEADER_PHY_INDEX] = BUILD_POLICY(U32),
+};
+
+DEFINE_POLICY_SET(genl_ethtool_header);
+
+static const NLAPolicy genl_ethtool_irq_moderation_policies[] = {
+ [ETHTOOL_A_IRQ_MODERATION_USEC] = BUILD_POLICY(U32),
+ [ETHTOOL_A_IRQ_MODERATION_PKTS] = BUILD_POLICY(U32),
+ [ETHTOOL_A_IRQ_MODERATION_COMPS] = BUILD_POLICY(U32),
+};
+
+DEFINE_POLICY_SET(genl_ethtool_irq_moderation);
+
+static const NLAPolicy genl_ethtool_profile_policies[] = {
+ [ETHTOOL_A_PROFILE_IRQ_MODERATION] = BUILD_POLICY_NESTED(genl_ethtool_irq_moderation),
+};
+
+DEFINE_POLICY_SET(genl_ethtool_profile);
+
+static const NLAPolicy genl_ethtool_coalesce_policies[] = {
+ [ETHTOOL_A_COALESCE_HEADER] = BUILD_POLICY_NESTED(genl_ethtool_header),
+ [ETHTOOL_A_COALESCE_RX_USECS] = BUILD_POLICY(U32),
+ [ETHTOOL_A_COALESCE_RX_MAX_FRAMES] = BUILD_POLICY(U32),
+ [ETHTOOL_A_COALESCE_RX_USECS_IRQ] = BUILD_POLICY(U32),
+ [ETHTOOL_A_COALESCE_RX_MAX_FRAMES_IRQ] = BUILD_POLICY(U32),
+ [ETHTOOL_A_COALESCE_TX_USECS] = BUILD_POLICY(U32),
+ [ETHTOOL_A_COALESCE_TX_MAX_FRAMES] = BUILD_POLICY(U32),
+ [ETHTOOL_A_COALESCE_TX_USECS_IRQ] = BUILD_POLICY(U32),
+ [ETHTOOL_A_COALESCE_TX_MAX_FRAMES_IRQ] = BUILD_POLICY(U32),
+ [ETHTOOL_A_COALESCE_STATS_BLOCK_USECS] = BUILD_POLICY(U32),
+ [ETHTOOL_A_COALESCE_USE_ADAPTIVE_RX] = BUILD_POLICY(U8),
+ [ETHTOOL_A_COALESCE_USE_ADAPTIVE_TX] = BUILD_POLICY(U8),
+ [ETHTOOL_A_COALESCE_PKT_RATE_LOW] = BUILD_POLICY(U32),
+ [ETHTOOL_A_COALESCE_RX_USECS_LOW] = BUILD_POLICY(U32),
+ [ETHTOOL_A_COALESCE_RX_MAX_FRAMES_LOW] = BUILD_POLICY(U32),
+ [ETHTOOL_A_COALESCE_TX_USECS_LOW] = BUILD_POLICY(U32),
+ [ETHTOOL_A_COALESCE_TX_MAX_FRAMES_LOW] = BUILD_POLICY(U32),
+ [ETHTOOL_A_COALESCE_PKT_RATE_HIGH] = BUILD_POLICY(U32),
+ [ETHTOOL_A_COALESCE_RX_USECS_HIGH] = BUILD_POLICY(U32),
+ [ETHTOOL_A_COALESCE_RX_MAX_FRAMES_HIGH] = BUILD_POLICY(U32),
+ [ETHTOOL_A_COALESCE_TX_USECS_HIGH] = BUILD_POLICY(U32),
+ [ETHTOOL_A_COALESCE_TX_MAX_FRAMES_HIGH] = BUILD_POLICY(U32),
+ [ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL] = BUILD_POLICY(U32),
+ [ETHTOOL_A_COALESCE_USE_CQE_MODE_TX] = BUILD_POLICY(U8),
+ [ETHTOOL_A_COALESCE_USE_CQE_MODE_RX] = BUILD_POLICY(U8),
+ [ETHTOOL_A_COALESCE_TX_AGGR_MAX_BYTES] = BUILD_POLICY(U32),
+ [ETHTOOL_A_COALESCE_TX_AGGR_MAX_FRAMES] = BUILD_POLICY(U32),
+ [ETHTOOL_A_COALESCE_TX_AGGR_TIME_USECS] = BUILD_POLICY(U32),
+ [ETHTOOL_A_COALESCE_RX_PROFILE] = BUILD_POLICY_NESTED(genl_ethtool_profile),
+ [ETHTOOL_A_COALESCE_TX_PROFILE] = BUILD_POLICY_NESTED(genl_ethtool_profile),
+ [ETHTOOL_A_COALESCE_RX_CQE_FRAMES] = BUILD_POLICY(U32),
+ [ETHTOOL_A_COALESCE_RX_CQE_NSECS] = BUILD_POLICY(U32),
+};
+
+DEFINE_POLICY_SET(genl_ethtool_coalesce);
+
+/* Unlike the other families, the attributes of ethtool depend on the command. Hence, the policy set of
+ * ethtool is indexed by the (userspace to kernel) command, and each entry refers to the policy set of the
+ * attributes for that command. See genl_family_is_indexed_by_command(). */
+static const NLAPolicy genl_ethtool_policies[] = {
+ [ETHTOOL_MSG_COALESCE_SET] = BUILD_POLICY_NESTED(genl_ethtool_coalesce),
+};
+
/***************** genl fou type systems *****************/
static const NLAPolicy genl_fou_policies[] = {
[FOU_ATTR_PORT] = BUILD_POLICY(U16),
@@ -236,6 +306,7 @@ static const NLAPolicy genl_wireguard_policies[] = {
static const NLAPolicySetUnionElement genl_policy_set_union_elements[] = {
BUILD_UNION_ELEMENT_BY_STRING(CTRL_GENL_NAME, genl_ctrl),
BUILD_UNION_ELEMENT_BY_STRING(BATADV_NL_NAME, genl_batadv),
+ BUILD_UNION_ELEMENT_BY_STRING(ETHTOOL_GENL_NAME, genl_ethtool),
BUILD_UNION_ELEMENT_BY_STRING(FOU_GENL_NAME, genl_fou),
BUILD_UNION_ELEMENT_BY_STRING(L2TP_GENL_NAME, genl_l2tp),
BUILD_UNION_ELEMENT_BY_STRING(MACSEC_GENL_NAME, genl_macsec),
@@ -250,3 +321,7 @@ DEFINE_POLICY_SET_UNION(genl, 0);
const NLAPolicySet *genl_get_policy_set_by_name(const char *name) {
return policy_set_union_get_policy_set_by_string(&genl_policy_set_union, name);
}
+
+bool genl_family_is_indexed_by_command(const char *name) {
+ return streq(name, ETHTOOL_GENL_NAME);
+}
diff --git a/src/libsystemd/sd-netlink/netlink-types.h b/src/libsystemd/sd-netlink/netlink-types.h
index 8682a9b8b98..21b70a187dd 100644
--- a/src/libsystemd/sd-netlink/netlink-types.h
+++ b/src/libsystemd/sd-netlink/netlink-types.h
@@ -37,6 +37,7 @@ const NLAPolicy *rtnl_get_policy(uint16_t nlmsg_type);
const NLAPolicy *nfnl_get_policy(uint16_t nlmsg_type);
const NLAPolicy *sdnl_get_policy(uint16_t nlmsg_type, uint16_t nlmsg_flags);
const NLAPolicySet *genl_get_policy_set_by_name(const char *name);
+bool genl_family_is_indexed_by_command(const char *name);
int genl_get_policy_set_and_header_size(
sd_netlink *nl,
uint16_t id,
diff --git a/src/libsystemd/sd-netlink/test-netlink.c b/src/libsystemd/sd-netlink/test-netlink.c
index e0154b7ef77..0bc183a7a29 100644
--- a/src/libsystemd/sd-netlink/test-netlink.c
+++ b/src/libsystemd/sd-netlink/test-netlink.c
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#include
#include
#include
#include
@@ -604,6 +605,56 @@ TEST(genl) {
}
}
+TEST(genl_ethtool) {
+ _cleanup_(sd_netlink_unrefp) sd_netlink *genl = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL;
+ const struct nlmsgerr *ack;
+ const char *name;
+ uint8_t cmd;
+ int r;
+
+ ASSERT_OK(sd_genl_socket_open(&genl));
+
+ r = sd_genl_message_new(genl, ETHTOOL_GENL_NAME, ETHTOOL_MSG_COALESCE_SET, &m);
+ if (r == -EOPNOTSUPP)
+ return (void) log_tests_skipped("ethtool netlink is not supported");
+ ASSERT_OK(r);
+
+ ASSERT_OK(sd_netlink_message_open_container(m, ETHTOOL_A_COALESCE_HEADER));
+ ASSERT_OK(sd_netlink_message_append_u32(m, ETHTOOL_A_HEADER_DEV_INDEX, LOOPBACK_IFINDEX));
+ ASSERT_OK(sd_netlink_message_close_container(m));
+ ASSERT_OK(sd_netlink_message_append_u32(m, ETHTOOL_A_COALESCE_RX_CQE_FRAMES, 8));
+ ASSERT_OK(sd_netlink_message_append_u32(m, ETHTOOL_A_COALESCE_RX_CQE_NSECS, 1000));
+ /* Check that the policy set for the command is used. */
+ ASSERT_ERROR(sd_netlink_message_append_u8(m, ETHTOOL_A_COALESCE_RX_CQE_FRAMES, 1), EINVAL);
+ ASSERT_ERROR(sd_netlink_message_append_u32(m, ETHTOOL_A_COALESCE_MAX + 1, 1), EOPNOTSUPP);
+ ASSERT_OK(sd_genl_message_get_family_name(genl, m, &name));
+ ASSERT_STREQ(name, ETHTOOL_GENL_NAME);
+ ASSERT_OK(sd_genl_message_get_command(genl, m, &cmd));
+ ASSERT_EQ(cmd, (uint8_t) ETHTOOL_MSG_COALESCE_SET);
+ ASSERT_NULL(m = sd_netlink_message_unref(m));
+
+ /* Commands without policy set are refused. */
+ ASSERT_ERROR(sd_genl_message_new(genl, ETHTOOL_GENL_NAME, ETHTOOL_MSG_RINGS_SET, &m), EOPNOTSUPP);
+
+ /* Replies are not supported yet, and must be dropped without breaking the socket. As the header
+ * attribute of ETHTOOL_MSG_LINKSTATE_GET is the same as the one of ETHTOOL_MSG_COALESCE_SET, let's
+ * build the request by rewriting the command, which does not require any privileges. The kernel
+ * sends ETHTOOL_MSG_LINKSTATE_GET_REPLY, which must be dropped, followed by the ACK. */
+ ASSERT_OK(sd_genl_message_new(genl, ETHTOOL_GENL_NAME, ETHTOOL_MSG_COALESCE_SET, &m));
+ ASSERT_OK(sd_netlink_message_open_container(m, ETHTOOL_A_LINKSTATE_HEADER));
+ ASSERT_OK(sd_netlink_message_append_u32(m, ETHTOOL_A_HEADER_DEV_INDEX, LOOPBACK_IFINDEX));
+ ASSERT_OK(sd_netlink_message_close_container(m));
+ ((struct genlmsghdr*) NLMSG_DATA(m->hdr))->cmd = ETHTOOL_MSG_LINKSTATE_GET;
+ ASSERT_OK(sd_netlink_call(genl, m, /* timeout= */ 0, &reply));
+ ASSERT_TRUE(sd_netlink_message_is_error(reply));
+ ASSERT_OK_ZERO(sd_netlink_message_get_errno(reply));
+ /* The ACK echoes the header of the request it acknowledges. */
+ ack = NLMSG_DATA(reply->hdr);
+ ASSERT_EQ(ack->msg.nlmsg_type, m->hdr->nlmsg_type);
+ ASSERT_EQ(ack->msg.nlmsg_seq, m->hdr->nlmsg_seq);
+}
+
static void remove_dummy_interfacep(int *ifindex) {
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c
index 44e9c49e817..bdb2b9668f7 100644
--- a/src/shared/ethtool-util.c
+++ b/src/shared/ethtool-util.c
@@ -1,10 +1,13 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include
+#include
#include
#include
#include
+#include "sd-netlink.h"
+
#include "alloc-util.h"
#include "conf-parser.h"
#include "errno-util.h"
@@ -1000,6 +1003,69 @@ int ethtool_set_nic_coalesce_settings(int *ethtool_fd, const char *ifname, const
return RET_NERRNO(ioctl(*ethtool_fd, SIOCETHTOOL, &ifr));
}
+int ethtool_set_nic_cqe_coalesce_settings(
+ sd_netlink **genl,
+ int ifindex,
+ const netdev_coalesce_param *coalesce) {
+
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
+ int r;
+
+ assert(genl);
+ assert(ifindex > 0);
+ assert(coalesce);
+
+ /* The settings below are not supported by the ioctl interface. The kernel merges the
+ * passed attributes with the current settings, so we do not need to fill in
+ * all the attributes in the set request. */
+
+ if (!coalesce->rx_cqe_frames.set && !coalesce->rx_cqe_nsecs.set)
+ return 0;
+
+ if (!*genl) {
+ r = sd_genl_socket_open(genl);
+ if (r < 0)
+ return r;
+ }
+
+ r = sd_genl_message_new(*genl, ETHTOOL_GENL_NAME, ETHTOOL_MSG_COALESCE_SET, &m);
+ if (r < 0)
+ return r;
+
+ r = sd_netlink_message_open_container(m, ETHTOOL_A_COALESCE_HEADER);
+ if (r < 0)
+ return r;
+
+ r = sd_netlink_message_append_u32(m, ETHTOOL_A_HEADER_DEV_INDEX, ifindex);
+ if (r < 0)
+ return r;
+
+ /* ETHTOOL_MSG_COALESCE_SET does not send a reply, but make sure we only ever get the ACK. */
+ r = sd_netlink_message_append_u32(m, ETHTOOL_A_HEADER_FLAGS, ETHTOOL_FLAG_OMIT_REPLY);
+ if (r < 0)
+ return r;
+
+ r = sd_netlink_message_close_container(m);
+ if (r < 0)
+ return r;
+
+ if (coalesce->rx_cqe_frames.set) {
+ r = sd_netlink_message_append_u32(m, ETHTOOL_A_COALESCE_RX_CQE_FRAMES,
+ coalesce->rx_cqe_frames.value);
+ if (r < 0)
+ return r;
+ }
+
+ if (coalesce->rx_cqe_nsecs.set) {
+ r = sd_netlink_message_append_u32(m, ETHTOOL_A_COALESCE_RX_CQE_NSECS,
+ coalesce->rx_cqe_nsecs.value);
+ if (r < 0)
+ return r;
+ }
+
+ return sd_netlink_call(*genl, m, /* timeout= */ 0, /* ret= */ NULL);
+}
+
int ethtool_set_eee_settings(
int *ethtool_fd,
const char *ifname,
@@ -1313,7 +1379,8 @@ int config_parse_coalesce_sec(
void *data,
void *userdata) {
u32_opt *dst = data;
- usec_t usec;
+ bool nsec = ltype;
+ uint64_t t;
int r;
if (isempty(rvalue)) {
@@ -1322,26 +1389,26 @@ int config_parse_coalesce_sec(
return 0;
}
- r = parse_sec(rvalue, &usec);
+ r = nsec ? parse_nsec(rvalue, &t) : parse_sec(rvalue, &t);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse coalesce setting value, ignoring: %s", rvalue);
return 0;
}
- if (usec > UINT32_MAX) {
+ if (t > UINT32_MAX) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Too large %s= value, ignoring: %s", lvalue, rvalue);
return 0;
}
- if (STR_IN_SET(lvalue, "StatisticsBlockCoalesceSec", "CoalescePacketRateSampleIntervalSec") && usec < 1) {
+ if (STR_IN_SET(lvalue, "StatisticsBlockCoalesceSec", "CoalescePacketRateSampleIntervalSec") && t < 1) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid %s= value, ignoring: %s", lvalue, rvalue);
return 0;
}
- dst->value = (uint32_t) usec;
+ dst->value = (uint32_t) t;
dst->set = true;
return 0;
diff --git a/src/shared/ethtool-util.h b/src/shared/ethtool-util.h
index 0c8cf85c132..7209c2af25f 100644
--- a/src/shared/ethtool-util.h
+++ b/src/shared/ethtool-util.h
@@ -142,6 +142,8 @@ typedef struct netdev_coalesce_param {
u32_opt tx_coalesce_usecs_high;
u32_opt tx_max_coalesced_frames_high;
u32_opt rate_sample_interval;
+ u32_opt rx_cqe_frames;
+ u32_opt rx_cqe_nsecs;
} netdev_coalesce_param;
int ethtool_get_driver(int *ethtool_fd, const char *ifname, char **ret);
@@ -164,6 +166,10 @@ int ethtool_set_link_settings(
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_nic_cqe_coalesce_settings(
+ sd_netlink **genl,
+ int ifindex,
+ const netdev_coalesce_param *coalesce);
int ethtool_set_eee_settings(
int *ethtool_fd,
const char *ifname,
diff --git a/src/udev/net/link-config-gperf.gperf b/src/udev/net/link-config-gperf.gperf
index 535c9e9dbb7..4af27166e18 100644
--- a/src/udev/net/link-config-gperf.gperf
+++ b/src/udev/net/link-config-gperf.gperf
@@ -131,6 +131,8 @@ 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)
+Link.RxCoalesceCQENSec, config_parse_coalesce_sec, /* nsec= */ true, offsetof(LinkConfig, coalesce.rx_cqe_nsecs)
+Link.RxMaxCoalescedCQEFrames, config_parse_coalesce_u32, 0, offsetof(LinkConfig, coalesce.rx_cqe_frames)
/* Rx RPS CPU mask */
Link.ReceivePacketSteeringCPUMask, config_parse_rps_cpu_mask, 0, offsetof(LinkConfig, rps_cpu_mask)
/* IRQ affinity settings */
diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c
index ec50a155acd..9354a44850e 100644
--- a/src/udev/net/link-config.c
+++ b/src/udev/net/link-config.c
@@ -58,6 +58,7 @@ static const Specifier link_specifier_table[] = {
struct LinkConfigContext {
LIST_HEAD(LinkConfig, configs);
int ethtool_fd;
+ sd_netlink *genl;
Hashmap *stats_by_path;
};
@@ -106,6 +107,7 @@ LinkConfigContext *link_config_ctx_free(LinkConfigContext *ctx) {
return NULL;
safe_close(ctx->ethtool_fd);
+ sd_netlink_unref(ctx->genl);
link_configs_free(ctx);
return mfree(ctx);
}
@@ -488,13 +490,14 @@ int link_get_config(LinkConfigContext *ctx, Link *link) {
return -ENOENT;
}
-static int link_apply_ethtool_settings(Link *link, int *ethtool_fd) {
+static int link_apply_ethtool_settings(Link *link, int *ethtool_fd, sd_netlink **genl) {
LinkConfig *config = ASSERT_PTR(ASSERT_PTR(link)->config);
const char *name = ASSERT_PTR(link->ifname);
int r;
assert(link->event);
assert(ethtool_fd);
+ assert(genl);
if (link->event->event_mode != EVENT_UDEV_WORKER) {
log_link_debug(link, "Running in test mode, skipping application of ethtool settings.");
@@ -558,6 +561,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_nic_cqe_coalesce_settings(genl, link->ifindex, &config->coalesce);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Could not set CQE 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");
@@ -1769,7 +1776,7 @@ int link_apply_config(LinkConfigContext *ctx, Link *link) {
assert(ctx);
assert(link);
- r = link_apply_ethtool_settings(link, &ctx->ethtool_fd);
+ r = link_apply_ethtool_settings(link, &ctx->ethtool_fd, &ctx->genl);
if (r < 0)
return r;