diff --git a/0001-patch-to-latest.patch b/0001-patch-to-latest.patch new file mode 100644 index 0000000..4844a85 --- /dev/null +++ b/0001-patch-to-latest.patch @@ -0,0 +1,5873 @@ +diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml +new file mode 100644 +index 000000000000..086b172cfd68 +--- /dev/null ++++ b/.github/workflows/build.yml +@@ -0,0 +1,69 @@ ++name: Build CI ++permissions: read-all ++ ++on: ++ push: ++ branches: ["*"] ++ pull_request: ++ branches: ["master"] ++ ++jobs: ++ build: ++ strategy: ++ matrix: ++ include: ++ - version: 7 ++ os: ubuntu-20.04 ++ - version: 8 ++ os: ubuntu-20.04 ++ - version: 9 ++ os: ubuntu-20.04 ++ - version: 10 ++ os: ubuntu-20.04 ++ - version: 11 ++ os: ubuntu-20.04 ++ - version: 12 ++ os: ubuntu-22.04 ++ - version: 13 ++ os: ubuntu-22.04 ++ - version: 14 ++ os: ubuntu-24.04 ++ fail-fast: false ++ ++ runs-on: ${{ matrix.os }} ++ ++ steps: ++ - uses: actions/checkout@v4 ++ ++ - name: Install dependencies ++ run: > ++ sudo apt-get install -y ++ libconfig-dev libnl-3-dev libnl-genl-3-dev ++ linux-libc-dev rpm libreadline-dev ++ ++ - name: Set up GCC ++ uses: egor-tensin/setup-gcc@v1 ++ with: ++ version: ${{ matrix.version }} ++ platform: x64 ++ ++ - name: Run bootstrap ++ run: ./bootstrap.sh ++ ++ - name: Build RPM ++ run: ./contrib/build-rpm.sh ++ ++ - name: Configure project ++ run: ./configure --enable-warnings --enable-errors ++ ++ - name: Build ++ run: make ++ ++ - name: Run check ++ run: make check ++ ++ - name: Install ++ run: sudo make install ++ ++ - name: Run distcheck ++ run: make distcheck +diff --git a/.gitignore b/.gitignore +index e2230d916826..cbecc1f061b9 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -28,6 +28,7 @@ lldpad.spec + ltmain.sh + m4/ + missing ++test-driver + dcbtool + lldpad + lldptool +diff --git a/.travis.yml b/.travis.yml +index df592adbf481..9f731329a851 100644 +--- a/.travis.yml ++++ b/.travis.yml +@@ -1,5 +1,8 @@ + language: c + dist: xenial ++arch: ++ - amd64 ++ - ppc64le + #before_install: sudo apt-get update + install: sudo apt-get install -y libconfig-dev libnl-3-dev rpm + before_script: ./bootstrap.sh +diff --git a/ChangeLog b/ChangeLog +index b51ea3fba9de..45869f9c8034 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,5 +1,7 @@ +-Changes from 1.1.0 to 1.1.1 +-- Bug fixes ++Changes from 1.1.0 to 1.2.0 ++- Add IEEE8023 support for Additional Ethernet Capabilities TLV (Frame ++ Preemption / MAC Merge layer) ++- Require libnl-genl-3.0 in addition to libnl-3.0 + Changes from 1.0.1 to 1.1 + - VDP: introduce vdptool + - VDP: support retrieving vsi parameter +diff --git a/Makefile.am b/Makefile.am +index 2cd25eecb964..1e27ce122313 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -19,8 +19,8 @@ ACLOCAL_AMFLAGS = -I m4 + parse_cli.o: CFLAGS+=-U_FORTIFY_SOURCE -Wno-error + + ## system requires a shared libconfig +-AM_CFLAGS = $(LIBCONFIG_CFLAGS) $(LIBNL_CFLAGS) +-AM_LDFLAGS = $(LIBCONFIG_LIBS) $(LIBNL_LIBS) -lrt ++AM_CFLAGS = $(LIBCONFIG_CFLAGS) $(LIBNL_CFLAGS) $(LIBNL_GENL_CFLAGS) ++AM_LDFLAGS = $(LIBCONFIG_LIBS) $(LIBNL_LIBS) $(LIBNL_GENL_LIBS) -lrt + + ## header files to be installed, for programs using the client interface to lldpad + lldpad_includedir= ${includedir}/lldpad +@@ -47,9 +47,9 @@ include/lldp_evb22_clif.h include/qbg_vdp_clif.h include/qbg_vdpnl.h \ + include/qbg_vdp22_clif.h include/lldp_8021qaz_clif.h \ + include/lldp_orgspec_clif.h include/lldp_cisco_clif.h \ + include/lldptool.h include/lldp_rtnl.h include/dcbtool.h include/lldp_dcbx_cfg.h \ +-include/qbg_vdp22_cmds.h include/qbg_vdp22_clif.h \ +-include/linux/ethtool.h include/linux/if_bonding.h include/linux/if_bridge.h \ +-include/linux/if.h include/linux/if_link.h include/linux/if_vlan.h ++include/qbg_vdp22_cmds.h include/qbg_vdp22_clif.h include/linux/ethtool.h \ ++include/linux/if_bonding.h include/linux/if_bridge.h include/linux/if.h \ ++include/linux/if_link.h include/linux/if_vlan.h include/linux/ethtool_netlink.h + + lldpad_SOURCES = lldpad.c config.c lldp_dcbx_nl.c ctrl_iface.c \ + event_iface.c eloop.c lldp_dcbx_cmds.c log.c lldpad_shm.c \ +@@ -66,6 +66,7 @@ lldp_evb_cmds.c lldp_evb.c include/lldp_evb.h qbg/vdp_cmds.c \ + include/qbg_vdp_cmds.h \ + include/qbg_ecp.h include/qbg_utils.h qbg/ecp.c qbg_utils.c \ + qbg/vdp.c include/qbg_vdp.h \ ++lldp_ethtool.c include/lldp_ethtool.h \ + lldp_tlv.c include/lldp_tlv.h \ + lldp_basman.c include/lldp_basman.h \ + lldp_med.c include/lldp_med.h \ +@@ -119,7 +120,7 @@ dist_noinst_DATA = lldpad.spec README COPYING ChangeLog lldpad.init + dist_man_MANS = docs/lldpad.8 docs/dcbtool.8 docs/lldptool.8 \ + docs/lldptool-ets.8 docs/lldptool-pfc.8 docs/lldptool-app.8 \ + docs/lldptool-evb.8 docs/lldptool-vdp.8 docs/lldptool-med.8 \ +- docs/lldptool-dcbx.8 \ ++ docs/lldptool-dcbx.8 docs/lldptool-add-eth-caps.8 \ + docs/lldptool-evb22.8 docs/vdptool.8 \ + docs/liblldp_clif-vdp22.3 + if BUILD_DEBUG +diff --git a/clif.c b/clif.c +index cad6f75ef91c..0758a7e107a2 100644 +--- a/clif.c ++++ b/clif.c +@@ -32,6 +32,7 @@ + + #include + #include ++#include + #include + #include + #include +diff --git a/config.c b/config.c +index 7e969b99c485..13ee7aa7ba47 100644 +--- a/config.c ++++ b/config.c +@@ -472,6 +472,32 @@ int get_config_setting(const char *ifname, int agenttype, char *path, + return (rval == CONFIG_FALSE) ? cmd_failed : cmd_success; + } + ++int remove_config_device(const char *ifname, int agenttype) ++{ ++ const char *section = agent_type2section(agenttype); ++ config_setting_t *setting = NULL; ++ int rval = cmd_failed; ++ ++ setting = config_lookup(&lldpad_cfg, section); ++ ++ if (setting != NULL) { ++ rval = config_setting_remove(setting, ifname); ++ if (rval == CONFIG_TRUE) { ++ LLDPAD_DBG("In %s, remove %s from section %s\n", __func__, ifname, section); ++ if (config_write_file(&lldpad_cfg, cfg_file_name)) { ++ rval = cmd_success; ++ } else { ++ LLDPAD_DBG("In %s, update config failed\n", __func__); ++ rval = cmd_failed; ++ } ++ } ++ } else { ++ LLDPAD_DBG("In %s, can't find section %s\n", __func__, section); ++ } ++ ++ return rval; ++} ++ + int remove_config_setting(const char *ifname, int agenttype, char *parent, + char *name) + { +diff --git a/configure.ac b/configure.ac +index fa2f3a05d5d7..e7cb118ade7b 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1,4 +1,4 @@ +-AC_INIT([lldpad], [1.1.1], [lldp-devel@open-lldp.org]) ++AC_INIT([lldpad], [1.2.99], [lldp-devel@open-lldp.org]) + AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) + + m4_pattern_allow([AM_PROG_AR]) +@@ -31,6 +31,8 @@ PKG_CHECK_MODULES([SYSTEMD], [systemd], use_systemd=yes, use_systemd=no) + dnl Configure developer type flags + OPENLLDP_CHECK_WARNINGS + OPENLLDP_CHECK_ERROR ++OPENLLDP_CHECK_UBSAN ++OPENLLDP_CHECK_ASAN + + dnl Set sysvinit values, if system has systemd it will be rewritten + AC_SUBST(SPEC_BUILD_REQUIRES_POST, "chkconfig") +@@ -64,15 +66,19 @@ dnl End systemd stuff + + PKG_CHECK_MODULES([LIBCONFIG], [libconfig >= 1.3.2]) + PKG_CHECK_MODULES([LIBNL], [libnl-3.0 >= 3.2]) ++PKG_CHECK_MODULES([LIBNL_GENL], [libnl-genl-3.0 >= 3.2]) + + AC_SUBST(LIBNL_CFLAGS) + AC_SUBST(LIBNL_LIBS) + ++AC_SUBST(LIBNL_GENL_CFLAGS) ++AC_SUBST(LIBNL_GENL_LIBS) ++ + AC_CHECK_LIB(nl3, rtnl_link_get_by_name) + + AC_CHECK_FUNCS([alarm]) + AC_CHECK_FUNCS([gettimeofday]) +-AC_CHECK_FUNCS([inet_ntoa]) ++AC_CHECK_FUNCS([inet_ntop]) + AC_CHECK_FUNCS([localtime_r]) + AC_CHECK_FUNCS([memmove]) + AC_CHECK_FUNCS([memset]) +@@ -84,6 +90,7 @@ AC_CHECK_FUNCS([strcasecmp]) + AC_CHECK_FUNCS([strchr]) + AC_CHECK_FUNCS([strdup]) + AC_CHECK_FUNCS([strerror]) ++AC_CHECK_FUNCS([strlcpy]) + AC_CHECK_FUNCS([strncasecmp]) + AC_CHECK_FUNCS([strpbrk]) + AC_CHECK_FUNCS([strrchr]) +@@ -116,7 +123,6 @@ AC_CHECK_HEADERS([syslog.h]) + + AC_C_INLINE + AC_FUNC_CHOWN +-AC_FUNC_MALLOC + AC_FUNC_REALLOC + AC_HEADER_STDBOOL + AC_PREREQ +diff --git a/docs/lldptool-add-eth-caps.8 b/docs/lldptool-add-eth-caps.8 +new file mode 100644 +index 000000000000..42e3a9a62ea0 +--- /dev/null ++++ b/docs/lldptool-add-eth-caps.8 +@@ -0,0 +1,91 @@ ++.TH lldptool 8 "January 2023" "open-lldp" "Linux" ++.SH NAME ++addEthCaps \- Show / manipulate Additional Ethernet Capabilities TLV ++.SH SYNOPSIS ++.B lldptool -t -i ethx -V addEthCaps ++.RI [ -c " " CONFIG_ARG " " ... ] ++.sp ++ ++.ti +4 ++.IR CONFIG_ARG " := { " ++.BR enableTx " | " addFragSize " }" ++.sp ++ ++.B lldptool -T -i ethx -V addEthCaps ++.RI CONFIG_ARG=value " " ... ++.sp ++.ti +4 ++.IR CONFIG_ARG " := ++.sp ++.BR enableTx " = " {yes|no} " | " ++.sp ++.BR addFragSize " = " {0|1|2|3} ++.sp ++.SH DESCRIPTION ++The Additional Ethernet Capabilities (addEthCaps) TLV allows neighbour systems ++to automatically discover the Frame Preemption capability and enable their MAC ++Merge layers to make use of it. ++ ++.SH ARGUMENTS ++.TP ++.B enableTx ++Enables the addEthCaps TLV to be transmitted ++.TP ++.B addFragSize ++Sets the additional fragment size to be advertised. This informs the link ++partner what is the minimum size of non-final fragments that it should ++transmit. An addFragSize of 0 corresponds to a minimum fragment size of 60 ++octets, 1 corresponds to 124 octets, 2 to 188 octets, and 3 to 252 octets. ++ ++.SH THEORY OF OPERATION ++ ++If transmission of the Additional Ethernet Capabilities TLV is enabled, the ++application queries the kernel for MAC Merge layer support, and if successful, ++it advertises "Frame Preemption Capability Supported". If the link partner ++advertises the "Frame Preemption Capability Supported" too, the application ++unconditionally enables the pMAC (to allow receiving preemptible and/or ++verification frames from the link partner) and transmission through the MAC ++Merge layer. The latter operation causes the "Frame Preemption Capability ++Enabled" to also be advertised in subsequent TLVs. ++ ++Since the application automatically enables the Frame Preemption capability, ++without any coordination with the link partner, it may be possible for the link ++partner to not enable reception on its pMAC, and thus, all preemptible frames ++transmitted by this device would be dropped as error frames. ++ ++To avoid this, the application also requests the kernel to enable TX ++verification, which starts a handshake of SMD-V and SMD-R frames outside the ++LLDP protocol. If the verification process succeeds (link partner responds to a ++SMD-V frame), the MAC Merge layer also becomes active, and the application will ++advertise "Frame Preemption Capability Active" in subsequent TLVs. ++ ++Which packets are transmitted as preemptible and which are transmitted as ++express (based on their user priority) is outside of the scope of this ++application (and of the LLDP protocol). ++ ++.SH EXAMPLE & USAGE ++.TP ++Enable the transmission of the Additional Ethernet Capabilities TLV for interface \fIeth0\fR: ++.B lldptool -T -i eth0 -V addEthCaps enableTx=yes ++.TP ++Configure the minimum fragment size for interface \fIeth0\fR to receive fragments no smaller than 252 octets: ++.B lldptool -T -i eth0 -V addEthCaps addFragSize=3 ++.TP ++Display the additional fragment size advertised by \fIeth0\fR: ++.B lldptool -t -i eth0 -V addEthCaps -c addFragSize ++.TP ++Display last transmitted Additional Ethernet Capabilities TLV ++.B lldptool -t -i eth0 -V addEthCaps ++ ++.SH NOTES ++The Additional Ethernet Capabilities TLV requires kernel support for the ++ETHTOOL_MSG_MM_GET and ETHTOOL_MSG_MM_SET netlink commands, which first ++appeared in Linux kernel v6.3. ++ ++.SH SEE ALSO ++.BR lldptool (8), ++.BR lldpad (8), ++.BR ethtool (8), ++ ++.SH AUTHOR ++This man page was written by Vladimir Oltean . +diff --git a/include/config.h b/include/config.h +index 61cb5dad7274..92fed7a18a1b 100644 +--- a/include/config.h ++++ b/include/config.h +@@ -79,6 +79,7 @@ int get_cfg(const char *ifname, int agenttype, char *path, union cfg_get value, + int set_cfg(const char *ifname, int agenttype, char *path, union cfg_set value, int type); + int get_config_setting(const char *ifname, int agenttype, char *path, union cfg_get value, int type); + int set_config_setting(const char *ifname, int agenttype, char *path, union cfg_set value, int type); ++int remove_config_device(const char *ifname, int agenttype); + int remove_config_setting(const char *ifname, int agenttype, char *parent, char *name); + int get_config_tlvfield(const char *ifname, int agenttype, u32 tlvid, const char *field, union cfg_get value, int type); + int get_config_tlvfield_int(const char *ifname, int agenttype, u32 tlvid, const char *field, int *value); +diff --git a/include/linux/const.h b/include/linux/const.h +new file mode 100644 +index 000000000000..af2a44c08683 +--- /dev/null ++++ b/include/linux/const.h +@@ -0,0 +1,36 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++/* const.h: Macros for dealing with constants. */ ++ ++#ifndef _UAPI_LINUX_CONST_H ++#define _UAPI_LINUX_CONST_H ++ ++/* Some constant macros are used in both assembler and ++ * C code. Therefore we cannot annotate them always with ++ * 'UL' and other type specifiers unilaterally. We ++ * use the following macros to deal with this. ++ * ++ * Similarly, _AT() will cast an expression with a type in C, but ++ * leave it unchanged in asm. ++ */ ++ ++#ifdef __ASSEMBLY__ ++#define _AC(X,Y) X ++#define _AT(T,X) X ++#else ++#define __AC(X,Y) (X##Y) ++#define _AC(X,Y) __AC(X,Y) ++#define _AT(T,X) ((T)(X)) ++#endif ++ ++#define _UL(x) (_AC(x, UL)) ++#define _ULL(x) (_AC(x, ULL)) ++ ++#define _BITUL(x) (_UL(1) << (x)) ++#define _BITULL(x) (_ULL(1) << (x)) ++ ++#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1) ++#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask)) ++ ++#define __KERNEL_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) ++ ++#endif /* _UAPI_LINUX_CONST_H */ +diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h +index f25bb9addfa3..1d0731b3d289 100644 +--- a/include/linux/ethtool.h ++++ b/include/linux/ethtool.h +@@ -1,3 +1,4 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ + /* + * ethtool.h: Defines for Linux ethtool. + * +@@ -13,75 +14,203 @@ + #ifndef _LINUX_ETHTOOL_H + #define _LINUX_ETHTOOL_H + ++#include + #include ++#include + +-/* This should work for both 32 and 64 bit userland. */ ++#include /* for INT_MAX */ ++ ++/* All structures exposed to userland should be defined such that they ++ * have the same layout for 32-bit and 64-bit userland. ++ */ ++ ++/* Note on reserved space. ++ * Reserved fields must not be accessed directly by user space because ++ * they may be replaced by a different field in the future. They must ++ * be initialized to zero before making the request, e.g. via memset ++ * of the entire structure or implicitly by not being set in a structure ++ * initializer. ++ */ ++ ++/** ++ * struct ethtool_cmd - DEPRECATED, link control and status ++ * This structure is DEPRECATED, please use struct ethtool_link_settings. ++ * @cmd: Command number = %ETHTOOL_GSET or %ETHTOOL_SSET ++ * @supported: Bitmask of %SUPPORTED_* flags for the link modes, ++ * physical connectors and other link features for which the ++ * interface supports autonegotiation or auto-detection. ++ * Read-only. ++ * @advertising: Bitmask of %ADVERTISED_* flags for the link modes, ++ * physical connectors and other link features that are ++ * advertised through autonegotiation or enabled for ++ * auto-detection. ++ * @speed: Low bits of the speed, 1Mb units, 0 to INT_MAX or SPEED_UNKNOWN ++ * @duplex: Duplex mode; one of %DUPLEX_* ++ * @port: Physical connector type; one of %PORT_* ++ * @phy_address: MDIO address of PHY (transceiver); 0 or 255 if not ++ * applicable. For clause 45 PHYs this is the PRTAD. ++ * @transceiver: Historically used to distinguish different possible ++ * PHY types, but not in a consistent way. Deprecated. ++ * @autoneg: Enable/disable autonegotiation and auto-detection; ++ * either %AUTONEG_DISABLE or %AUTONEG_ENABLE ++ * @mdio_support: Bitmask of %ETH_MDIO_SUPPORTS_* flags for the MDIO ++ * protocols supported by the interface; 0 if unknown. ++ * Read-only. ++ * @maxtxpkt: Historically used to report TX IRQ coalescing; now ++ * obsoleted by &struct ethtool_coalesce. Read-only; deprecated. ++ * @maxrxpkt: Historically used to report RX IRQ coalescing; now ++ * obsoleted by &struct ethtool_coalesce. Read-only; deprecated. ++ * @speed_hi: High bits of the speed, 1Mb units, 0 to INT_MAX or SPEED_UNKNOWN ++ * @eth_tp_mdix: Ethernet twisted-pair MDI(-X) status; one of ++ * %ETH_TP_MDI_*. If the status is unknown or not applicable, the ++ * value will be %ETH_TP_MDI_INVALID. Read-only. ++ * @eth_tp_mdix_ctrl: Ethernet twisted pair MDI(-X) control; one of ++ * %ETH_TP_MDI_*. If MDI(-X) control is not implemented, reads ++ * yield %ETH_TP_MDI_INVALID and writes may be ignored or rejected. ++ * When written successfully, the link should be renegotiated if ++ * necessary. ++ * @lp_advertising: Bitmask of %ADVERTISED_* flags for the link modes ++ * and other link features that the link partner advertised ++ * through autonegotiation; 0 if unknown or not applicable. ++ * Read-only. ++ * @reserved: Reserved for future use; see the note on reserved space. ++ * ++ * The link speed in Mbps is split between @speed and @speed_hi. Use ++ * the ethtool_cmd_speed() and ethtool_cmd_speed_set() functions to ++ * access it. ++ * ++ * 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 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. ++ * ++ * Some hardware interfaces may have multiple PHYs and/or physical ++ * connectors fitted or do not allow the driver to detect which are ++ * fitted. For these interfaces @port and/or @phy_address may be ++ * writable, possibly dependent on @autoneg being %AUTONEG_DISABLE. ++ * Otherwise, attempts to write different values may be ignored or ++ * rejected. ++ * ++ * Users should assume that all fields not marked read-only are ++ * writable and subject to validation by the driver. They should use ++ * %ETHTOOL_GSET to get the current values before making specific ++ * changes and then applying them with %ETHTOOL_SSET. ++ * ++ * Deprecated fields should be ignored by both users and drivers. ++ */ + struct ethtool_cmd { + __u32 cmd; +- __u32 supported; /* Features this interface supports */ +- __u32 advertising; /* Features this interface advertises */ +- __u16 speed; /* The forced speed, 10Mb, 100Mb, gigabit */ +- __u8 duplex; /* Duplex, half or full */ +- __u8 port; /* Which connector port */ ++ __u32 supported; ++ __u32 advertising; ++ __u16 speed; ++ __u8 duplex; ++ __u8 port; + __u8 phy_address; +- __u8 transceiver; /* Which transceiver to use */ +- __u8 autoneg; /* Enable or disable autonegotiation */ ++ __u8 transceiver; ++ __u8 autoneg; + __u8 mdio_support; +- __u32 maxtxpkt; /* Tx pkts before generating tx int */ +- __u32 maxrxpkt; /* Rx pkts before generating rx int */ ++ __u32 maxtxpkt; ++ __u32 maxrxpkt; + __u16 speed_hi; + __u8 eth_tp_mdix; +- __u8 reserved2; +- __u32 lp_advertising; /* Features the link partner advertises */ ++ __u8 eth_tp_mdix_ctrl; ++ __u32 lp_advertising; + __u32 reserved[2]; + }; + +-static inline void ethtool_cmd_speed_set(struct ethtool_cmd *ep, +- __u32 speed) ++static __inline__ void ethtool_cmd_speed_set(struct ethtool_cmd *ep, ++ __u32 speed) + { +- +- ep->speed = (__u16)speed; ++ ep->speed = (__u16)(speed & 0xFFFF); + ep->speed_hi = (__u16)(speed >> 16); + } + +-static inline __u32 ethtool_cmd_speed(struct ethtool_cmd *ep) ++static __inline__ __u32 ethtool_cmd_speed(const struct ethtool_cmd *ep) + { + return (ep->speed_hi << 16) | ep->speed; + } + ++/* Device supports clause 22 register access to PHY or peripherals ++ * using the interface defined in . This should not be ++ * set if there are known to be no such peripherals present or if ++ * the driver only emulates clause 22 registers for compatibility. ++ */ ++#define ETH_MDIO_SUPPORTS_C22 1 ++ ++/* Device supports clause 45 register access to PHY or peripherals ++ * using the interface defined in and . ++ * This should not be set if there are known to be no such peripherals ++ * present. ++ */ ++#define ETH_MDIO_SUPPORTS_C45 2 ++ + #define ETHTOOL_FWVERS_LEN 32 + #define ETHTOOL_BUSINFO_LEN 32 +-/* these strings are set to whatever the driver author decides... */ ++#define ETHTOOL_EROMVERS_LEN 32 ++ ++/** ++ * struct ethtool_drvinfo - general driver and device information ++ * @cmd: Command number = %ETHTOOL_GDRVINFO ++ * @driver: Driver short name. This should normally match the name ++ * in its bus driver structure (e.g. pci_driver::name). Must ++ * not be an empty string. ++ * @version: Driver version string; may be an empty string ++ * @fw_version: Firmware version string; driver defined; may be an ++ * empty string ++ * @erom_version: Expansion ROM version string; driver defined; may be ++ * an empty string ++ * @bus_info: Device bus address. This should match the dev_name() ++ * string for the underlying bus device, if there is one. May be ++ * an empty string. ++ * @reserved2: Reserved for future use; see the note on reserved space. ++ * @n_priv_flags: Number of flags valid for %ETHTOOL_GPFLAGS and ++ * %ETHTOOL_SPFLAGS commands; also the number of strings in the ++ * %ETH_SS_PRIV_FLAGS set ++ * @n_stats: Number of u64 statistics returned by the %ETHTOOL_GSTATS ++ * command; also the number of strings in the %ETH_SS_STATS set ++ * @testinfo_len: Number of results returned by the %ETHTOOL_TEST ++ * command; also the number of strings in the %ETH_SS_TEST set ++ * @eedump_len: Size of EEPROM accessible through the %ETHTOOL_GEEPROM ++ * and %ETHTOOL_SEEPROM commands, in bytes ++ * @regdump_len: Size of register dump returned by the %ETHTOOL_GREGS ++ * command, in bytes ++ * ++ * Users can use the %ETHTOOL_GSSET_INFO command to get the number of ++ * strings in any string set (from Linux 2.6.34). ++ */ + struct ethtool_drvinfo { + __u32 cmd; +- char driver[32]; /* driver short name, "tulip", "eepro100" */ +- char version[32]; /* driver version string */ +- char fw_version[ETHTOOL_FWVERS_LEN]; /* firmware version string */ +- char bus_info[ETHTOOL_BUSINFO_LEN]; /* Bus info for this IF. */ +- /* For PCI devices, use pci_name(pci_dev). */ +- char reserved1[32]; ++ char driver[32]; ++ char version[32]; ++ char fw_version[ETHTOOL_FWVERS_LEN]; ++ char bus_info[ETHTOOL_BUSINFO_LEN]; ++ char erom_version[ETHTOOL_EROMVERS_LEN]; + char reserved2[12]; +- /* +- * Some struct members below are filled in +- * using ops->get_sset_count(). Obtaining +- * this info from ethtool_drvinfo is now +- * deprecated; Use ETHTOOL_GSSET_INFO +- * instead. +- */ +- __u32 n_priv_flags; /* number of flags valid in ETHTOOL_GPFLAGS */ +- __u32 n_stats; /* number of u64's from ETHTOOL_GSTATS */ ++ __u32 n_priv_flags; ++ __u32 n_stats; + __u32 testinfo_len; +- __u32 eedump_len; /* Size of data from ETHTOOL_GEEPROM (bytes) */ +- __u32 regdump_len; /* Size of data from ETHTOOL_GREGS (bytes) */ ++ __u32 eedump_len; ++ __u32 regdump_len; + }; + + #define SOPASS_MAX 6 +-/* wake-on-lan settings */ ++ ++/** ++ * struct ethtool_wolinfo - Wake-On-Lan configuration ++ * @cmd: Command number = %ETHTOOL_GWOL or %ETHTOOL_SWOL ++ * @supported: Bitmask of %WAKE_* flags for supported Wake-On-Lan modes. ++ * Read-only. ++ * @wolopts: Bitmask of %WAKE_* flags for enabled Wake-On-Lan modes. ++ * @sopass: SecureOn(tm) password; meaningful only if %WAKE_MAGICSECURE ++ * is set in @wolopts. ++ */ + struct ethtool_wolinfo { + __u32 cmd; + __u32 supported; + __u32 wolopts; +- __u8 sopass[SOPASS_MAX]; /* SecureOn(tm) password */ ++ __u8 sopass[SOPASS_MAX]; + }; + + /* for passing single values */ +@@ -90,212 +219,723 @@ struct ethtool_value { + __u32 data; + }; + +-/* for passing big chunks of data */ ++#define PFC_STORM_PREVENTION_AUTO 0xffff ++#define PFC_STORM_PREVENTION_DISABLE 0 ++ ++enum tunable_id { ++ ETHTOOL_ID_UNSPEC, ++ ETHTOOL_RX_COPYBREAK, ++ ETHTOOL_TX_COPYBREAK, ++ ETHTOOL_PFC_PREVENTION_TOUT, /* timeout in msecs */ ++ ETHTOOL_TX_COPYBREAK_BUF_SIZE, ++ /* ++ * Add your fresh new tunable attribute above and remember to update ++ * tunable_strings[] in net/ethtool/common.c ++ */ ++ __ETHTOOL_TUNABLE_COUNT, ++}; ++ ++enum tunable_type_id { ++ ETHTOOL_TUNABLE_UNSPEC, ++ ETHTOOL_TUNABLE_U8, ++ ETHTOOL_TUNABLE_U16, ++ ETHTOOL_TUNABLE_U32, ++ ETHTOOL_TUNABLE_U64, ++ ETHTOOL_TUNABLE_STRING, ++ ETHTOOL_TUNABLE_S8, ++ ETHTOOL_TUNABLE_S16, ++ ETHTOOL_TUNABLE_S32, ++ ETHTOOL_TUNABLE_S64, ++}; ++ ++struct ethtool_tunable { ++ __u32 cmd; ++ __u32 id; ++ __u32 type_id; ++ __u32 len; ++ void *data[]; ++}; ++ ++#define DOWNSHIFT_DEV_DEFAULT_COUNT 0xff ++#define DOWNSHIFT_DEV_DISABLE 0 ++ ++/* Time in msecs after which link is reported as down ++ * 0 = lowest time supported by the PHY ++ * 0xff = off, link down detection according to standard ++ */ ++#define ETHTOOL_PHY_FAST_LINK_DOWN_ON 0 ++#define ETHTOOL_PHY_FAST_LINK_DOWN_OFF 0xff ++ ++/* Energy Detect Power Down (EDPD) is a feature supported by some PHYs, where ++ * the PHY's RX & TX blocks are put into a low-power mode when there is no ++ * link detected (typically cable is un-plugged). For RX, only a minimal ++ * link-detection is available, and for TX the PHY wakes up to send link pulses ++ * to avoid any lock-ups in case the peer PHY may also be running in EDPD mode. ++ * ++ * Some PHYs may support configuration of the wake-up interval for TX pulses, ++ * and some PHYs may support only disabling TX pulses entirely. For the latter ++ * a special value is required (ETHTOOL_PHY_EDPD_NO_TX) so that this can be ++ * configured from userspace (should the user want it). ++ * ++ * The interval units for TX wake-up are in milliseconds, since this should ++ * cover a reasonable range of intervals: ++ * - from 1 millisecond, which does not sound like much of a power-saver ++ * - to ~65 seconds which is quite a lot to wait for a link to come up when ++ * plugging a cable ++ */ ++#define ETHTOOL_PHY_EDPD_DFLT_TX_MSECS 0xffff ++#define ETHTOOL_PHY_EDPD_NO_TX 0xfffe ++#define ETHTOOL_PHY_EDPD_DISABLE 0 ++ ++enum phy_tunable_id { ++ ETHTOOL_PHY_ID_UNSPEC, ++ ETHTOOL_PHY_DOWNSHIFT, ++ ETHTOOL_PHY_FAST_LINK_DOWN, ++ ETHTOOL_PHY_EDPD, ++ /* ++ * Add your fresh new phy tunable attribute above and remember to update ++ * phy_tunable_strings[] in net/ethtool/common.c ++ */ ++ __ETHTOOL_PHY_TUNABLE_COUNT, ++}; ++ ++/** ++ * struct ethtool_regs - hardware register dump ++ * @cmd: Command number = %ETHTOOL_GREGS ++ * @version: Dump format version. This is driver-specific and may ++ * distinguish different chips/revisions. Drivers must use new ++ * version numbers whenever the dump format changes in an ++ * incompatible way. ++ * @len: On entry, the real length of @data. On return, the number of ++ * bytes used. ++ * @data: Buffer for the register dump ++ * ++ * Users should use %ETHTOOL_GDRVINFO to find the maximum length of ++ * a register dump for the interface. They must allocate the buffer ++ * immediately following this structure. ++ */ + struct ethtool_regs { + __u32 cmd; +- __u32 version; /* driver-specific, indicates different chips/revs */ +- __u32 len; /* bytes */ +- __u8 data[0]; ++ __u32 version; ++ __u32 len; ++ __u8 data[]; + }; + +-/* for passing EEPROM chunks */ ++/** ++ * struct ethtool_eeprom - EEPROM dump ++ * @cmd: Command number = %ETHTOOL_GEEPROM, %ETHTOOL_GMODULEEEPROM or ++ * %ETHTOOL_SEEPROM ++ * @magic: A 'magic cookie' value to guard against accidental changes. ++ * The value passed in to %ETHTOOL_SEEPROM must match the value ++ * returned by %ETHTOOL_GEEPROM for the same device. This is ++ * unused when @cmd is %ETHTOOL_GMODULEEEPROM. ++ * @offset: Offset within the EEPROM to begin reading/writing, in bytes ++ * @len: On entry, number of bytes to read/write. On successful ++ * return, number of bytes actually read/written. In case of ++ * error, this may indicate at what point the error occurred. ++ * @data: Buffer to read/write from ++ * ++ * Users may use %ETHTOOL_GDRVINFO or %ETHTOOL_GMODULEINFO to find ++ * the length of an on-board or module EEPROM, respectively. They ++ * must allocate the buffer immediately following this structure. ++ */ + struct ethtool_eeprom { + __u32 cmd; + __u32 magic; +- __u32 offset; /* in bytes */ +- __u32 len; /* in bytes */ +- __u8 data[0]; ++ __u32 offset; ++ __u32 len; ++ __u8 data[]; + }; + +-/* for configuring coalescing parameters of chip */ +-struct ethtool_coalesce { +- __u32 cmd; /* ETHTOOL_{G,S}COALESCE */ ++/** ++ * struct ethtool_eee - Energy Efficient Ethernet information ++ * @cmd: ETHTOOL_{G,S}EEE ++ * @supported: Mask of %SUPPORTED_* flags for the speed/duplex combinations ++ * for which there is EEE support. ++ * @advertised: Mask of %ADVERTISED_* flags for the speed/duplex combinations ++ * advertised as eee capable. ++ * @lp_advertised: Mask of %ADVERTISED_* flags for the speed/duplex ++ * combinations advertised by the link partner as eee capable. ++ * @eee_active: Result of the eee auto negotiation. ++ * @eee_enabled: EEE configured mode (enabled/disabled). ++ * @tx_lpi_enabled: Whether the interface should assert its tx lpi, given ++ * that eee was negotiated. ++ * @tx_lpi_timer: Time in microseconds the interface delays prior to asserting ++ * its tx lpi (after reaching 'idle' state). Effective only when eee ++ * was negotiated and tx_lpi_enabled was set. ++ * @reserved: Reserved for future use; see the note on reserved space. ++ */ ++struct ethtool_eee { ++ __u32 cmd; ++ __u32 supported; ++ __u32 advertised; ++ __u32 lp_advertised; ++ __u32 eee_active; ++ __u32 eee_enabled; ++ __u32 tx_lpi_enabled; ++ __u32 tx_lpi_timer; ++ __u32 reserved[2]; ++}; + +- /* How many usecs to delay an RX interrupt after +- * a packet arrives. If 0, only rx_max_coalesced_frames +- * is used. +- */ +- __u32 rx_coalesce_usecs; ++/** ++ * struct ethtool_modinfo - plugin module eeprom information ++ * @cmd: %ETHTOOL_GMODULEINFO ++ * @type: Standard the module information conforms to %ETH_MODULE_SFF_xxxx ++ * @eeprom_len: Length of the eeprom ++ * @reserved: Reserved for future use; see the note on reserved space. ++ * ++ * This structure is used to return the information to ++ * properly size memory for a subsequent call to %ETHTOOL_GMODULEEEPROM. ++ * The type code indicates the eeprom data format ++ */ ++struct ethtool_modinfo { ++ __u32 cmd; ++ __u32 type; ++ __u32 eeprom_len; ++ __u32 reserved[8]; ++}; + +- /* How many packets to delay an RX interrupt after +- * a packet arrives. If 0, only rx_coalesce_usecs is +- * used. It is illegal to set both usecs and max frames +- * to zero as this would cause RX interrupts to never be +- * generated. +- */ ++/** ++ * struct ethtool_coalesce - coalescing parameters for IRQs and stats updates ++ * @cmd: ETHTOOL_{G,S}COALESCE ++ * @rx_coalesce_usecs: How many usecs to delay an RX interrupt after ++ * a packet arrives. ++ * @rx_max_coalesced_frames: Maximum number of packets to receive ++ * before an RX interrupt. ++ * @rx_coalesce_usecs_irq: Same as @rx_coalesce_usecs, except that ++ * this value applies while an IRQ is being serviced by the host. ++ * @rx_max_coalesced_frames_irq: Same as @rx_max_coalesced_frames, ++ * except that this value applies while an IRQ is being serviced ++ * by the host. ++ * @tx_coalesce_usecs: How many usecs to delay a TX interrupt after ++ * a packet is sent. ++ * @tx_max_coalesced_frames: Maximum number of packets to be sent ++ * before a TX interrupt. ++ * @tx_coalesce_usecs_irq: Same as @tx_coalesce_usecs, except that ++ * this value applies while an IRQ is being serviced by the host. ++ * @tx_max_coalesced_frames_irq: Same as @tx_max_coalesced_frames, ++ * except that this value applies while an IRQ is being serviced ++ * by the host. ++ * @stats_block_coalesce_usecs: How many usecs to delay in-memory ++ * statistics block updates. Some drivers do not have an ++ * in-memory statistic block, and in such cases this value is ++ * ignored. This value must not be zero. ++ * @use_adaptive_rx_coalesce: Enable adaptive RX coalescing. ++ * @use_adaptive_tx_coalesce: Enable adaptive TX coalescing. ++ * @pkt_rate_low: Threshold for low packet rate (packets per second). ++ * @rx_coalesce_usecs_low: How many usecs to delay an RX interrupt after ++ * a packet arrives, when the packet rate is below @pkt_rate_low. ++ * @rx_max_coalesced_frames_low: Maximum number of packets to be received ++ * before an RX interrupt, when the packet rate is below @pkt_rate_low. ++ * @tx_coalesce_usecs_low: How many usecs to delay a TX interrupt after ++ * a packet is sent, when the packet rate is below @pkt_rate_low. ++ * @tx_max_coalesced_frames_low: Maximum nuumber of packets to be sent before ++ * a TX interrupt, when the packet rate is below @pkt_rate_low. ++ * @pkt_rate_high: Threshold for high packet rate (packets per second). ++ * @rx_coalesce_usecs_high: How many usecs to delay an RX interrupt after ++ * a packet arrives, when the packet rate is above @pkt_rate_high. ++ * @rx_max_coalesced_frames_high: Maximum number of packets to be received ++ * before an RX interrupt, when the packet rate is above @pkt_rate_high. ++ * @tx_coalesce_usecs_high: How many usecs to delay a TX interrupt after ++ * a packet is sent, when the packet rate is above @pkt_rate_high. ++ * @tx_max_coalesced_frames_high: Maximum number of packets to be sent before ++ * a TX interrupt, when the packet rate is above @pkt_rate_high. ++ * @rate_sample_interval: How often to do adaptive coalescing packet rate ++ * sampling, measured in seconds. Must not be zero. ++ * ++ * Each pair of (usecs, max_frames) fields specifies that interrupts ++ * should be coalesced until ++ * (usecs > 0 && time_since_first_completion >= usecs) || ++ * (max_frames > 0 && completed_frames >= max_frames) ++ * ++ * It is illegal to set both usecs and max_frames to zero as this ++ * would cause interrupts to never be generated. To disable ++ * coalescing, set usecs = 0 and max_frames = 1. ++ * ++ * Some implementations ignore the value of max_frames and use the ++ * condition time_since_first_completion >= usecs ++ * ++ * This is deprecated. Drivers for hardware that does not support ++ * counting completions should validate that max_frames == !rx_usecs. ++ * ++ * Adaptive RX/TX coalescing is an algorithm implemented by some ++ * drivers to improve latency under low packet rates and improve ++ * throughput under high packet rates. Some drivers only implement ++ * one of RX or TX adaptive coalescing. Anything not implemented by ++ * the driver causes these values to be silently ignored. ++ * ++ * When the packet rate is below @pkt_rate_high but above ++ * @pkt_rate_low (both measured in packets per second) the ++ * normal {rx,tx}_* coalescing parameters are used. ++ */ ++struct ethtool_coalesce { ++ __u32 cmd; ++ __u32 rx_coalesce_usecs; + __u32 rx_max_coalesced_frames; +- +- /* Same as above two parameters, except that these values +- * apply while an IRQ is being serviced by the host. Not +- * all cards support this feature and the values are ignored +- * in that case. +- */ + __u32 rx_coalesce_usecs_irq; + __u32 rx_max_coalesced_frames_irq; +- +- /* How many usecs to delay a TX interrupt after +- * a packet is sent. If 0, only tx_max_coalesced_frames +- * is used. +- */ + __u32 tx_coalesce_usecs; +- +- /* How many packets to delay a TX interrupt after +- * a packet is sent. If 0, only tx_coalesce_usecs is +- * used. It is illegal to set both usecs and max frames +- * to zero as this would cause TX interrupts to never be +- * generated. +- */ + __u32 tx_max_coalesced_frames; +- +- /* Same as above two parameters, except that these values +- * apply while an IRQ is being serviced by the host. Not +- * all cards support this feature and the values are ignored +- * in that case. +- */ + __u32 tx_coalesce_usecs_irq; + __u32 tx_max_coalesced_frames_irq; +- +- /* How many usecs to delay in-memory statistics +- * block updates. Some drivers do not have an in-memory +- * statistic block, and in such cases this value is ignored. +- * This value must not be zero. +- */ + __u32 stats_block_coalesce_usecs; +- +- /* Adaptive RX/TX coalescing is an algorithm implemented by +- * some drivers to improve latency under low packet rates and +- * improve throughput under high packet rates. Some drivers +- * only implement one of RX or TX adaptive coalescing. Anything +- * not implemented by the driver causes these values to be +- * silently ignored. +- */ + __u32 use_adaptive_rx_coalesce; + __u32 use_adaptive_tx_coalesce; +- +- /* When the packet rate (measured in packets per second) +- * is below pkt_rate_low, the {rx,tx}_*_low parameters are +- * used. +- */ + __u32 pkt_rate_low; + __u32 rx_coalesce_usecs_low; + __u32 rx_max_coalesced_frames_low; + __u32 tx_coalesce_usecs_low; + __u32 tx_max_coalesced_frames_low; +- +- /* When the packet rate is below pkt_rate_high but above +- * pkt_rate_low (both measured in packets per second) the +- * normal {rx,tx}_* coalescing parameters are used. +- */ +- +- /* When the packet rate is (measured in packets per second) +- * is above pkt_rate_high, the {rx,tx}_*_high parameters are +- * used. +- */ + __u32 pkt_rate_high; + __u32 rx_coalesce_usecs_high; + __u32 rx_max_coalesced_frames_high; + __u32 tx_coalesce_usecs_high; + __u32 tx_max_coalesced_frames_high; +- +- /* How often to do adaptive coalescing packet rate sampling, +- * measured in seconds. Must not be zero. +- */ + __u32 rate_sample_interval; + }; + +-/* for configuring RX/TX ring parameters */ ++/** ++ * struct ethtool_ringparam - RX/TX ring parameters ++ * @cmd: Command number = %ETHTOOL_GRINGPARAM or %ETHTOOL_SRINGPARAM ++ * @rx_max_pending: Maximum supported number of pending entries per ++ * RX ring. Read-only. ++ * @rx_mini_max_pending: Maximum supported number of pending entries ++ * per RX mini ring. Read-only. ++ * @rx_jumbo_max_pending: Maximum supported number of pending entries ++ * per RX jumbo ring. Read-only. ++ * @tx_max_pending: Maximum supported number of pending entries per ++ * TX ring. Read-only. ++ * @rx_pending: Current maximum number of pending entries per RX ring ++ * @rx_mini_pending: Current maximum number of pending entries per RX ++ * mini ring ++ * @rx_jumbo_pending: Current maximum number of pending entries per RX ++ * jumbo ring ++ * @tx_pending: Current maximum supported number of pending entries ++ * per TX ring ++ * ++ * If the interface does not have separate RX mini and/or jumbo rings, ++ * @rx_mini_max_pending and/or @rx_jumbo_max_pending will be 0. ++ * ++ * There may also be driver-dependent minimum values for the number ++ * of entries per ring. ++ */ + struct ethtool_ringparam { +- __u32 cmd; /* ETHTOOL_{G,S}RINGPARAM */ +- +- /* Read only attributes. These indicate the maximum number +- * of pending RX/TX ring entries the driver will allow the +- * user to set. +- */ ++ __u32 cmd; + __u32 rx_max_pending; + __u32 rx_mini_max_pending; + __u32 rx_jumbo_max_pending; + __u32 tx_max_pending; +- +- /* Values changeable by the user. The valid values are +- * in the range 1 to the "*_max_pending" counterpart above. +- */ + __u32 rx_pending; + __u32 rx_mini_pending; + __u32 rx_jumbo_pending; + __u32 tx_pending; + }; + +-/* for configuring link flow control parameters */ ++/** ++ * struct ethtool_channels - configuring number of network channel ++ * @cmd: ETHTOOL_{G,S}CHANNELS ++ * @max_rx: Read only. Maximum number of receive channel the driver support. ++ * @max_tx: Read only. Maximum number of transmit channel the driver support. ++ * @max_other: Read only. Maximum number of other channel the driver support. ++ * @max_combined: Read only. Maximum number of combined channel the driver ++ * support. Set of queues RX, TX or other. ++ * @rx_count: Valid values are in the range 1 to the max_rx. ++ * @tx_count: Valid values are in the range 1 to the max_tx. ++ * @other_count: Valid values are in the range 1 to the max_other. ++ * @combined_count: Valid values are in the range 1 to the max_combined. ++ * ++ * This can be used to configure RX, TX and other channels. ++ */ ++ ++struct ethtool_channels { ++ __u32 cmd; ++ __u32 max_rx; ++ __u32 max_tx; ++ __u32 max_other; ++ __u32 max_combined; ++ __u32 rx_count; ++ __u32 tx_count; ++ __u32 other_count; ++ __u32 combined_count; ++}; ++ ++/** ++ * struct ethtool_pauseparam - Ethernet pause (flow control) parameters ++ * @cmd: Command number = %ETHTOOL_GPAUSEPARAM or %ETHTOOL_SPAUSEPARAM ++ * @autoneg: Flag to enable autonegotiation of pause frame use ++ * @rx_pause: Flag to enable reception of pause frames ++ * @tx_pause: Flag to enable transmission of pause frames ++ * ++ * Drivers should reject a non-zero setting of @autoneg when ++ * autoneogotiation is disabled (or not supported) for the link. ++ * ++ * If the link is autonegotiated, drivers should use ++ * mii_advertise_flowctrl() or similar code to set the advertised ++ * pause frame capabilities based on the @rx_pause and @tx_pause flags, ++ * even if @autoneg is zero. They should also allow the advertised ++ * pause frame capabilities to be controlled directly through the ++ * advertising field of &struct ethtool_cmd. ++ * ++ * If @autoneg is non-zero, the MAC is configured to send and/or ++ * receive pause frames according to the result of autonegotiation. ++ * Otherwise, it is configured directly based on the @rx_pause and ++ * @tx_pause flags. ++ */ + struct ethtool_pauseparam { +- __u32 cmd; /* ETHTOOL_{G,S}PAUSEPARAM */ +- +- /* If the link is being auto-negotiated (via ethtool_cmd.autoneg +- * being true) the user may set 'autonet' here non-zero to have the +- * pause parameters be auto-negotiated too. In such a case, the +- * {rx,tx}_pause values below determine what capabilities are +- * advertised. +- * +- * If 'autoneg' is zero or the link is not being auto-negotiated, +- * then {rx,tx}_pause force the driver to use/not-use pause +- * flow control. +- */ ++ __u32 cmd; + __u32 autoneg; + __u32 rx_pause; + __u32 tx_pause; + }; + ++/* Link extended state */ ++enum ethtool_link_ext_state { ++ ETHTOOL_LINK_EXT_STATE_AUTONEG, ++ ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE, ++ ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH, ++ ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY, ++ ETHTOOL_LINK_EXT_STATE_NO_CABLE, ++ ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE, ++ ETHTOOL_LINK_EXT_STATE_EEPROM_ISSUE, ++ ETHTOOL_LINK_EXT_STATE_CALIBRATION_FAILURE, ++ ETHTOOL_LINK_EXT_STATE_POWER_BUDGET_EXCEEDED, ++ ETHTOOL_LINK_EXT_STATE_OVERHEAT, ++ ETHTOOL_LINK_EXT_STATE_MODULE, ++}; ++ ++/* More information in addition to ETHTOOL_LINK_EXT_STATE_AUTONEG. */ ++enum ethtool_link_ext_substate_autoneg { ++ ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_PARTNER_DETECTED = 1, ++ ETHTOOL_LINK_EXT_SUBSTATE_AN_ACK_NOT_RECEIVED, ++ ETHTOOL_LINK_EXT_SUBSTATE_AN_NEXT_PAGE_EXCHANGE_FAILED, ++ ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_PARTNER_DETECTED_FORCE_MODE, ++ ETHTOOL_LINK_EXT_SUBSTATE_AN_FEC_MISMATCH_DURING_OVERRIDE, ++ ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_HCD, ++}; ++ ++/* More information in addition to ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE. ++ */ ++enum ethtool_link_ext_substate_link_training { ++ ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_FRAME_LOCK_NOT_ACQUIRED = 1, ++ ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_INHIBIT_TIMEOUT, ++ ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_PARTNER_DID_NOT_SET_RECEIVER_READY, ++ ETHTOOL_LINK_EXT_SUBSTATE_LT_REMOTE_FAULT, ++}; ++ ++/* More information in addition to ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH. ++ */ ++enum ethtool_link_ext_substate_link_logical_mismatch { ++ ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_BLOCK_LOCK = 1, ++ ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_AM_LOCK, ++ ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_GET_ALIGN_STATUS, ++ ETHTOOL_LINK_EXT_SUBSTATE_LLM_FC_FEC_IS_NOT_LOCKED, ++ ETHTOOL_LINK_EXT_SUBSTATE_LLM_RS_FEC_IS_NOT_LOCKED, ++}; ++ ++/* More information in addition to ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY. ++ */ ++enum ethtool_link_ext_substate_bad_signal_integrity { ++ ETHTOOL_LINK_EXT_SUBSTATE_BSI_LARGE_NUMBER_OF_PHYSICAL_ERRORS = 1, ++ ETHTOOL_LINK_EXT_SUBSTATE_BSI_UNSUPPORTED_RATE, ++ ETHTOOL_LINK_EXT_SUBSTATE_BSI_SERDES_REFERENCE_CLOCK_LOST, ++ ETHTOOL_LINK_EXT_SUBSTATE_BSI_SERDES_ALOS, ++}; ++ ++/* More information in addition to ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE. */ ++enum ethtool_link_ext_substate_cable_issue { ++ ETHTOOL_LINK_EXT_SUBSTATE_CI_UNSUPPORTED_CABLE = 1, ++ ETHTOOL_LINK_EXT_SUBSTATE_CI_CABLE_TEST_FAILURE, ++}; ++ ++/* More information in addition to ETHTOOL_LINK_EXT_STATE_MODULE. */ ++enum ethtool_link_ext_substate_module { ++ ETHTOOL_LINK_EXT_SUBSTATE_MODULE_CMIS_NOT_READY = 1, ++}; ++ + #define ETH_GSTRING_LEN 32 ++ ++/** ++ * enum ethtool_stringset - string set ID ++ * @ETH_SS_TEST: Self-test result names, for use with %ETHTOOL_TEST ++ * @ETH_SS_STATS: Statistic names, for use with %ETHTOOL_GSTATS ++ * @ETH_SS_PRIV_FLAGS: Driver private flag names, for use with ++ * %ETHTOOL_GPFLAGS and %ETHTOOL_SPFLAGS ++ * @ETH_SS_NTUPLE_FILTERS: Previously used with %ETHTOOL_GRXNTUPLE; ++ * now deprecated ++ * @ETH_SS_FEATURES: Device feature names ++ * @ETH_SS_RSS_HASH_FUNCS: RSS hush function names ++ * @ETH_SS_TUNABLES: tunable names ++ * @ETH_SS_PHY_STATS: Statistic names, for use with %ETHTOOL_GPHYSTATS ++ * @ETH_SS_PHY_TUNABLES: PHY tunable names ++ * @ETH_SS_LINK_MODES: link mode names ++ * @ETH_SS_MSG_CLASSES: debug message class names ++ * @ETH_SS_WOL_MODES: wake-on-lan modes ++ * @ETH_SS_SOF_TIMESTAMPING: SOF_TIMESTAMPING_* flags ++ * @ETH_SS_TS_TX_TYPES: timestamping Tx types ++ * @ETH_SS_TS_RX_FILTERS: timestamping Rx filters ++ * @ETH_SS_UDP_TUNNEL_TYPES: UDP tunnel types ++ * @ETH_SS_STATS_STD: standardized stats ++ * @ETH_SS_STATS_ETH_PHY: names of IEEE 802.3 PHY statistics ++ * @ETH_SS_STATS_ETH_MAC: names of IEEE 802.3 MAC statistics ++ * @ETH_SS_STATS_ETH_CTRL: names of IEEE 802.3 MAC Control statistics ++ * @ETH_SS_STATS_RMON: names of RMON statistics ++ * ++ * @ETH_SS_COUNT: number of defined string sets ++ */ + enum ethtool_stringset { + ETH_SS_TEST = 0, + ETH_SS_STATS, + ETH_SS_PRIV_FLAGS, + ETH_SS_NTUPLE_FILTERS, ++ ETH_SS_FEATURES, ++ ETH_SS_RSS_HASH_FUNCS, ++ ETH_SS_TUNABLES, ++ ETH_SS_PHY_STATS, ++ ETH_SS_PHY_TUNABLES, ++ ETH_SS_LINK_MODES, ++ ETH_SS_MSG_CLASSES, ++ ETH_SS_WOL_MODES, ++ ETH_SS_SOF_TIMESTAMPING, ++ ETH_SS_TS_TX_TYPES, ++ ETH_SS_TS_RX_FILTERS, ++ ETH_SS_UDP_TUNNEL_TYPES, ++ ETH_SS_STATS_STD, ++ ETH_SS_STATS_ETH_PHY, ++ ETH_SS_STATS_ETH_MAC, ++ ETH_SS_STATS_ETH_CTRL, ++ ETH_SS_STATS_RMON, ++ ++ /* add new constants above here */ ++ ETH_SS_COUNT ++}; ++ ++/** ++ * enum ethtool_mac_stats_src - source of ethtool MAC statistics ++ * @ETHTOOL_MAC_STATS_SRC_AGGREGATE: ++ * if device supports a MAC merge layer, this retrieves the aggregate ++ * statistics of the eMAC and pMAC. Otherwise, it retrieves just the ++ * statistics of the single (express) MAC. ++ * @ETHTOOL_MAC_STATS_SRC_EMAC: ++ * if device supports a MM layer, this retrieves the eMAC statistics. ++ * Otherwise, it retrieves the statistics of the single (express) MAC. ++ * @ETHTOOL_MAC_STATS_SRC_PMAC: ++ * if device supports a MM layer, this retrieves the pMAC statistics. ++ */ ++enum ethtool_mac_stats_src { ++ ETHTOOL_MAC_STATS_SRC_AGGREGATE, ++ ETHTOOL_MAC_STATS_SRC_EMAC, ++ ETHTOOL_MAC_STATS_SRC_PMAC, ++}; ++ ++/** ++ * enum ethtool_module_power_mode_policy - plug-in module power mode policy ++ * @ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH: Module is always in high power mode. ++ * @ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO: Module is transitioned by the host ++ * to high power mode when the first port using it is put administratively ++ * up and to low power mode when the last port using it is put ++ * administratively down. ++ */ ++enum ethtool_module_power_mode_policy { ++ ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH = 1, ++ ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO, + }; + +-/* for passing string sets for data tagging */ ++/** ++ * enum ethtool_module_power_mode - plug-in module power mode ++ * @ETHTOOL_MODULE_POWER_MODE_LOW: Module is in low power mode. ++ * @ETHTOOL_MODULE_POWER_MODE_HIGH: Module is in high power mode. ++ */ ++enum ethtool_module_power_mode { ++ ETHTOOL_MODULE_POWER_MODE_LOW = 1, ++ ETHTOOL_MODULE_POWER_MODE_HIGH, ++}; ++ ++/** ++ * enum ethtool_podl_pse_admin_state - operational state of the PoDL PSE ++ * functions. IEEE 802.3-2018 30.15.1.1.2 aPoDLPSEAdminState ++ * @ETHTOOL_PODL_PSE_ADMIN_STATE_UNKNOWN: state of PoDL PSE functions are ++ * unknown ++ * @ETHTOOL_PODL_PSE_ADMIN_STATE_DISABLED: PoDL PSE functions are disabled ++ * @ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED: PoDL PSE functions are enabled ++ */ ++enum ethtool_podl_pse_admin_state { ++ ETHTOOL_PODL_PSE_ADMIN_STATE_UNKNOWN = 1, ++ ETHTOOL_PODL_PSE_ADMIN_STATE_DISABLED, ++ ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED, ++}; ++ ++/** ++ * enum ethtool_podl_pse_pw_d_status - power detection status of the PoDL PSE. ++ * IEEE 802.3-2018 30.15.1.1.3 aPoDLPSEPowerDetectionStatus: ++ * @ETHTOOL_PODL_PSE_PW_D_STATUS_UNKNOWN: PoDL PSE ++ * @ETHTOOL_PODL_PSE_PW_D_STATUS_DISABLED: "The enumeration “disabled” is ++ * asserted true when the PoDL PSE state diagram variable mr_pse_enable is ++ * false" ++ * @ETHTOOL_PODL_PSE_PW_D_STATUS_SEARCHING: "The enumeration “searching” is ++ * asserted true when either of the PSE state diagram variables ++ * pi_detecting or pi_classifying is true." ++ * @ETHTOOL_PODL_PSE_PW_D_STATUS_DELIVERING: "The enumeration “deliveringPower” ++ * is asserted true when the PoDL PSE state diagram variable pi_powered is ++ * true." ++ * @ETHTOOL_PODL_PSE_PW_D_STATUS_SLEEP: "The enumeration “sleep” is asserted ++ * true when the PoDL PSE state diagram variable pi_sleeping is true." ++ * @ETHTOOL_PODL_PSE_PW_D_STATUS_IDLE: "The enumeration “idle” is asserted true ++ * when the logical combination of the PoDL PSE state diagram variables ++ * pi_prebiased*!pi_sleeping is true." ++ * @ETHTOOL_PODL_PSE_PW_D_STATUS_ERROR: "The enumeration “error” is asserted ++ * true when the PoDL PSE state diagram variable overload_held is true." ++ */ ++enum ethtool_podl_pse_pw_d_status { ++ ETHTOOL_PODL_PSE_PW_D_STATUS_UNKNOWN = 1, ++ ETHTOOL_PODL_PSE_PW_D_STATUS_DISABLED, ++ ETHTOOL_PODL_PSE_PW_D_STATUS_SEARCHING, ++ ETHTOOL_PODL_PSE_PW_D_STATUS_DELIVERING, ++ ETHTOOL_PODL_PSE_PW_D_STATUS_SLEEP, ++ ETHTOOL_PODL_PSE_PW_D_STATUS_IDLE, ++ ETHTOOL_PODL_PSE_PW_D_STATUS_ERROR, ++}; ++ ++/** ++ * enum ethtool_mm_verify_status - status of MAC Merge Verify function ++ * @ETHTOOL_MM_VERIFY_STATUS_UNKNOWN: ++ * verification status is unknown ++ * @ETHTOOL_MM_VERIFY_STATUS_INITIAL: ++ * the 802.3 Verify State diagram is in the state INIT_VERIFICATION ++ * @ETHTOOL_MM_VERIFY_STATUS_VERIFYING: ++ * the Verify State diagram is in the state VERIFICATION_IDLE, ++ * SEND_VERIFY or WAIT_FOR_RESPONSE ++ * @ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED: ++ * indicates that the Verify State diagram is in the state VERIFIED ++ * @ETHTOOL_MM_VERIFY_STATUS_FAILED: ++ * the Verify State diagram is in the state VERIFY_FAIL ++ * @ETHTOOL_MM_VERIFY_STATUS_DISABLED: ++ * verification of preemption operation is disabled ++ */ ++enum ethtool_mm_verify_status { ++ ETHTOOL_MM_VERIFY_STATUS_UNKNOWN, ++ ETHTOOL_MM_VERIFY_STATUS_INITIAL, ++ ETHTOOL_MM_VERIFY_STATUS_VERIFYING, ++ ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED, ++ ETHTOOL_MM_VERIFY_STATUS_FAILED, ++ ETHTOOL_MM_VERIFY_STATUS_DISABLED, ++}; ++ ++/** ++ * struct ethtool_gstrings - string set for data tagging ++ * @cmd: Command number = %ETHTOOL_GSTRINGS ++ * @string_set: String set ID; one of &enum ethtool_stringset ++ * @len: On return, the number of strings in the string set ++ * @data: Buffer for strings. Each string is null-padded to a size of ++ * %ETH_GSTRING_LEN. ++ * ++ * Users must use %ETHTOOL_GSSET_INFO to find the number of strings in ++ * the string set. They must allocate a buffer of the appropriate ++ * size immediately following this structure. ++ */ + struct ethtool_gstrings { +- __u32 cmd; /* ETHTOOL_GSTRINGS */ +- __u32 string_set; /* string set id e.c. ETH_SS_TEST, etc*/ +- __u32 len; /* number of strings in the string set */ +- __u8 data[0]; ++ __u32 cmd; ++ __u32 string_set; ++ __u32 len; ++ __u8 data[]; + }; + ++/** ++ * struct ethtool_sset_info - string set information ++ * @cmd: Command number = %ETHTOOL_GSSET_INFO ++ * @reserved: Reserved for future use; see the note on reserved space. ++ * @sset_mask: On entry, a bitmask of string sets to query, with bits ++ * numbered according to &enum ethtool_stringset. On return, a ++ * bitmask of those string sets queried that are supported. ++ * @data: Buffer for string set sizes. On return, this contains the ++ * size of each string set that was queried and supported, in ++ * order of ID. ++ * ++ * Example: The user passes in @sset_mask = 0x7 (sets 0, 1, 2) and on ++ * return @sset_mask == 0x6 (sets 1, 2). Then @data[0] contains the ++ * size of set 1 and @data[1] contains the size of set 2. ++ * ++ * Users must allocate a buffer of the appropriate size (4 * number of ++ * sets queried) immediately following this structure. ++ */ + struct ethtool_sset_info { +- __u32 cmd; /* ETHTOOL_GSSET_INFO */ ++ __u32 cmd; + __u32 reserved; +- __u64 sset_mask; /* input: each bit selects an sset to query */ +- /* output: each bit a returned sset */ +- __u32 data[0]; /* ETH_SS_xxx count, in order, based on bits +- in sset_mask. One bit implies one +- __u32, two bits implies two +- __u32's, etc. */ ++ __u64 sset_mask; ++ __u32 data[]; + }; + ++/** ++ * enum ethtool_test_flags - flags definition of ethtool_test ++ * @ETH_TEST_FL_OFFLINE: if set perform online and offline tests, otherwise ++ * only online tests. ++ * @ETH_TEST_FL_FAILED: Driver set this flag if test fails. ++ * @ETH_TEST_FL_EXTERNAL_LB: Application request to perform external loopback ++ * test. ++ * @ETH_TEST_FL_EXTERNAL_LB_DONE: Driver performed the external loopback test ++ */ ++ + enum ethtool_test_flags { +- ETH_TEST_FL_OFFLINE = (1 << 0), /* online / offline */ +- ETH_TEST_FL_FAILED = (1 << 1), /* test passed / failed */ ++ ETH_TEST_FL_OFFLINE = (1 << 0), ++ ETH_TEST_FL_FAILED = (1 << 1), ++ ETH_TEST_FL_EXTERNAL_LB = (1 << 2), ++ ETH_TEST_FL_EXTERNAL_LB_DONE = (1 << 3), + }; + +-/* for requesting NIC test and getting results*/ ++/** ++ * struct ethtool_test - device self-test invocation ++ * @cmd: Command number = %ETHTOOL_TEST ++ * @flags: A bitmask of flags from &enum ethtool_test_flags. Some ++ * flags may be set by the user on entry; others may be set by ++ * the driver on return. ++ * @reserved: Reserved for future use; see the note on reserved space. ++ * @len: On return, the number of test results ++ * @data: Array of test results ++ * ++ * Users must use %ETHTOOL_GSSET_INFO or %ETHTOOL_GDRVINFO to find the ++ * number of test results that will be returned. They must allocate a ++ * buffer of the appropriate size (8 * number of results) immediately ++ * following this structure. ++ */ + struct ethtool_test { +- __u32 cmd; /* ETHTOOL_TEST */ +- __u32 flags; /* ETH_TEST_FL_xxx */ ++ __u32 cmd; ++ __u32 flags; + __u32 reserved; +- __u32 len; /* result length, in number of u64 elements */ +- __u64 data[0]; ++ __u32 len; ++ __u64 data[]; + }; + +-/* for dumping NIC-specific statistics */ ++/** ++ * struct ethtool_stats - device-specific statistics ++ * @cmd: Command number = %ETHTOOL_GSTATS ++ * @n_stats: On return, the number of statistics ++ * @data: Array of statistics ++ * ++ * Users must use %ETHTOOL_GSSET_INFO or %ETHTOOL_GDRVINFO to find the ++ * number of statistics that will be returned. They must allocate a ++ * buffer of the appropriate size (8 * number of statistics) ++ * immediately following this structure. ++ */ + struct ethtool_stats { +- __u32 cmd; /* ETHTOOL_GSTATS */ +- __u32 n_stats; /* number of u64's being returned */ +- __u64 data[0]; ++ __u32 cmd; ++ __u32 n_stats; ++ __u64 data[]; + }; + ++/** ++ * struct ethtool_perm_addr - permanent hardware address ++ * @cmd: Command number = %ETHTOOL_GPERMADDR ++ * @size: On entry, the size of the buffer. On return, the size of the ++ * address. The command fails if the buffer is too small. ++ * @data: Buffer for the address ++ * ++ * Users must allocate the buffer immediately following this structure. ++ * A buffer size of %MAX_ADDR_LEN should be sufficient for any address ++ * type. ++ */ + struct ethtool_perm_addr { +- __u32 cmd; /* ETHTOOL_GPERMADDR */ ++ __u32 cmd; + __u32 size; +- __u8 data[0]; ++ __u8 data[]; + }; + + /* boolean flags controlling per-interface behavior characteristics. +@@ -308,15 +948,28 @@ struct ethtool_perm_addr { + * flag differs from the read-only value. + */ + enum ethtool_flags { ++ ETH_FLAG_TXVLAN = (1 << 7), /* TX VLAN offload enabled */ ++ ETH_FLAG_RXVLAN = (1 << 8), /* RX VLAN offload enabled */ + ETH_FLAG_LRO = (1 << 15), /* LRO is enabled */ + ETH_FLAG_NTUPLE = (1 << 27), /* N-tuple filters enabled */ + ETH_FLAG_RXHASH = (1 << 28), + }; + + /* The following structures are for supporting RX network flow +- * classification configuration. Note, all multibyte fields, e.g., +- * ip4src, ip4dst, psrc, pdst, spi, etc. are expected to be in network +- * byte order. ++ * classification and RX n-tuple configuration. Note, all multibyte ++ * fields, e.g., ip4src, ip4dst, psrc, pdst, spi, etc. are expected to ++ * be in network byte order. ++ */ ++ ++/** ++ * struct ethtool_tcpip4_spec - flow specification for TCP/IPv4 etc. ++ * @ip4src: Source host ++ * @ip4dst: Destination host ++ * @psrc: Source port ++ * @pdst: Destination port ++ * @tos: Type-of-service ++ * ++ * This can be used to specify a TCP/IPv4, UDP/IPv4 or SCTP/IPv4 flow. + */ + struct ethtool_tcpip4_spec { + __be32 ip4src; +@@ -326,6 +979,15 @@ struct ethtool_tcpip4_spec { + __u8 tos; + }; + ++/** ++ * struct ethtool_ah_espip4_spec - flow specification for IPsec/IPv4 ++ * @ip4src: Source host ++ * @ip4dst: Destination host ++ * @spi: Security parameters index ++ * @tos: Type-of-service ++ * ++ * This can be used to specify an IPsec transport or tunnel over IPv4. ++ */ + struct ethtool_ah_espip4_spec { + __be32 ip4src; + __be32 ip4dst; +@@ -333,21 +995,17 @@ struct ethtool_ah_espip4_spec { + __u8 tos; + }; + +-struct ethtool_rawip4_spec { +- __be32 ip4src; +- __be32 ip4dst; +- __u8 hdata[64]; +-}; +- +-struct ethtool_ether_spec { +- __be16 ether_type; +- __u8 frame_size; +- __u8 eframe[16]; +-}; +- + #define ETH_RX_NFC_IP4 1 +-#define ETH_RX_NFC_IP6 2 + ++/** ++ * struct ethtool_usrip4_spec - general flow specification for IPv4 ++ * @ip4src: Source host ++ * @ip4dst: Destination host ++ * @l4_4_bytes: First 4 bytes of transport (layer 4) header ++ * @tos: Type-of-service ++ * @ip_ver: Value must be %ETH_RX_NFC_IP4; mask must be 0 ++ * @proto: Transport protocol number; mask must be 0 ++ */ + struct ethtool_usrip4_spec { + __be32 ip4src; + __be32 ip4dst; +@@ -357,44 +1015,297 @@ struct ethtool_usrip4_spec { + __u8 proto; + }; + ++/** ++ * struct ethtool_tcpip6_spec - flow specification for TCP/IPv6 etc. ++ * @ip6src: Source host ++ * @ip6dst: Destination host ++ * @psrc: Source port ++ * @pdst: Destination port ++ * @tclass: Traffic Class ++ * ++ * This can be used to specify a TCP/IPv6, UDP/IPv6 or SCTP/IPv6 flow. ++ */ ++struct ethtool_tcpip6_spec { ++ __be32 ip6src[4]; ++ __be32 ip6dst[4]; ++ __be16 psrc; ++ __be16 pdst; ++ __u8 tclass; ++}; ++ ++/** ++ * struct ethtool_ah_espip6_spec - flow specification for IPsec/IPv6 ++ * @ip6src: Source host ++ * @ip6dst: Destination host ++ * @spi: Security parameters index ++ * @tclass: Traffic Class ++ * ++ * This can be used to specify an IPsec transport or tunnel over IPv6. ++ */ ++struct ethtool_ah_espip6_spec { ++ __be32 ip6src[4]; ++ __be32 ip6dst[4]; ++ __be32 spi; ++ __u8 tclass; ++}; ++ ++/** ++ * struct ethtool_usrip6_spec - general flow specification for IPv6 ++ * @ip6src: Source host ++ * @ip6dst: Destination host ++ * @l4_4_bytes: First 4 bytes of transport (layer 4) header ++ * @tclass: Traffic Class ++ * @l4_proto: Transport protocol number (nexthdr after any Extension Headers) ++ */ ++struct ethtool_usrip6_spec { ++ __be32 ip6src[4]; ++ __be32 ip6dst[4]; ++ __be32 l4_4_bytes; ++ __u8 tclass; ++ __u8 l4_proto; ++}; ++ ++union ethtool_flow_union { ++ struct ethtool_tcpip4_spec tcp_ip4_spec; ++ struct ethtool_tcpip4_spec udp_ip4_spec; ++ struct ethtool_tcpip4_spec sctp_ip4_spec; ++ struct ethtool_ah_espip4_spec ah_ip4_spec; ++ struct ethtool_ah_espip4_spec esp_ip4_spec; ++ struct ethtool_usrip4_spec usr_ip4_spec; ++ struct ethtool_tcpip6_spec tcp_ip6_spec; ++ struct ethtool_tcpip6_spec udp_ip6_spec; ++ struct ethtool_tcpip6_spec sctp_ip6_spec; ++ struct ethtool_ah_espip6_spec ah_ip6_spec; ++ struct ethtool_ah_espip6_spec esp_ip6_spec; ++ struct ethtool_usrip6_spec usr_ip6_spec; ++ struct ethhdr ether_spec; ++ __u8 hdata[52]; ++}; ++ ++/** ++ * struct ethtool_flow_ext - additional RX flow fields ++ * @h_dest: destination MAC address ++ * @vlan_etype: VLAN EtherType ++ * @vlan_tci: VLAN tag control information ++ * @data: user defined data ++ * @padding: Reserved for future use; see the note on reserved space. ++ * ++ * Note, @vlan_etype, @vlan_tci, and @data are only valid if %FLOW_EXT ++ * is set in &struct ethtool_rx_flow_spec @flow_type. ++ * @h_dest is valid if %FLOW_MAC_EXT is set. ++ */ ++struct ethtool_flow_ext { ++ __u8 padding[2]; ++ unsigned char h_dest[ETH_ALEN]; ++ __be16 vlan_etype; ++ __be16 vlan_tci; ++ __be32 data[2]; ++}; ++ ++/** ++ * struct ethtool_rx_flow_spec - classification rule for RX flows ++ * @flow_type: Type of match to perform, e.g. %TCP_V4_FLOW ++ * @h_u: Flow fields to match (dependent on @flow_type) ++ * @h_ext: Additional fields to match ++ * @m_u: Masks for flow field bits to be matched ++ * @m_ext: Masks for additional field bits to be matched ++ * Note, all additional fields must be ignored unless @flow_type ++ * includes the %FLOW_EXT or %FLOW_MAC_EXT flag ++ * (see &struct ethtool_flow_ext description). ++ * @ring_cookie: RX ring/queue index to deliver to, or %RX_CLS_FLOW_DISC ++ * if packets should be discarded, or %RX_CLS_FLOW_WAKE if the ++ * packets should be used for Wake-on-LAN with %WAKE_FILTER ++ * @location: Location of rule in the table. Locations must be ++ * numbered such that a flow matching multiple rules will be ++ * classified according to the first (lowest numbered) rule. ++ */ + struct ethtool_rx_flow_spec { + __u32 flow_type; +- union { +- struct ethtool_tcpip4_spec tcp_ip4_spec; +- struct ethtool_tcpip4_spec udp_ip4_spec; +- struct ethtool_tcpip4_spec sctp_ip4_spec; +- struct ethtool_ah_espip4_spec ah_ip4_spec; +- struct ethtool_ah_espip4_spec esp_ip4_spec; +- struct ethtool_rawip4_spec raw_ip4_spec; +- struct ethtool_ether_spec ether_spec; +- struct ethtool_usrip4_spec usr_ip4_spec; +- __u8 hdata[64]; +- } h_u, m_u; /* entry, mask */ ++ union ethtool_flow_union h_u; ++ struct ethtool_flow_ext h_ext; ++ union ethtool_flow_union m_u; ++ struct ethtool_flow_ext m_ext; + __u64 ring_cookie; + __u32 location; + }; + ++/* How rings are laid out when accessing virtual functions or ++ * offloaded queues is device specific. To allow users to do flow ++ * steering and specify these queues the ring cookie is partitioned ++ * into a 32bit queue index with an 8 bit virtual function id. ++ * This also leaves the 3bytes for further specifiers. It is possible ++ * future devices may support more than 256 virtual functions if ++ * devices start supporting PCIe w/ARI. However at the moment I ++ * do not know of any devices that support this so I do not reserve ++ * space for this at this time. If a future patch consumes the next ++ * byte it should be aware of this possibility. ++ */ ++#define ETHTOOL_RX_FLOW_SPEC_RING 0x00000000FFFFFFFFLL ++#define ETHTOOL_RX_FLOW_SPEC_RING_VF 0x000000FF00000000LL ++#define ETHTOOL_RX_FLOW_SPEC_RING_VF_OFF 32 ++static __inline__ __u64 ethtool_get_flow_spec_ring(__u64 ring_cookie) ++{ ++ return ETHTOOL_RX_FLOW_SPEC_RING & ring_cookie; ++} ++ ++static __inline__ __u64 ethtool_get_flow_spec_ring_vf(__u64 ring_cookie) ++{ ++ return (ETHTOOL_RX_FLOW_SPEC_RING_VF & ring_cookie) >> ++ ETHTOOL_RX_FLOW_SPEC_RING_VF_OFF; ++} ++ ++/** ++ * struct ethtool_rxnfc - command to get or set RX flow classification rules ++ * @cmd: Specific command number - %ETHTOOL_GRXFH, %ETHTOOL_SRXFH, ++ * %ETHTOOL_GRXRINGS, %ETHTOOL_GRXCLSRLCNT, %ETHTOOL_GRXCLSRULE, ++ * %ETHTOOL_GRXCLSRLALL, %ETHTOOL_SRXCLSRLDEL or %ETHTOOL_SRXCLSRLINS ++ * @flow_type: Type of flow to be affected, e.g. %TCP_V4_FLOW ++ * @data: Command-dependent value ++ * @fs: Flow classification rule ++ * @rss_context: RSS context to be affected ++ * @rule_cnt: Number of rules to be affected ++ * @rule_locs: Array of used rule locations ++ * ++ * For %ETHTOOL_GRXFH and %ETHTOOL_SRXFH, @data is a bitmask indicating ++ * the fields included in the flow hash, e.g. %RXH_IP_SRC. The following ++ * structure fields must not be used, except that if @flow_type includes ++ * the %FLOW_RSS flag, then @rss_context determines which RSS context to ++ * act on. ++ * ++ * For %ETHTOOL_GRXRINGS, @data is set to the number of RX rings/queues ++ * on return. ++ * ++ * For %ETHTOOL_GRXCLSRLCNT, @rule_cnt is set to the number of defined ++ * rules on return. If @data is non-zero on return then it is the ++ * size of the rule table, plus the flag %RX_CLS_LOC_SPECIAL if the ++ * driver supports any special location values. If that flag is not ++ * set in @data then special location values should not be used. ++ * ++ * For %ETHTOOL_GRXCLSRULE, @fs.@location specifies the location of an ++ * existing rule on entry and @fs contains the rule on return; if ++ * @fs.@flow_type includes the %FLOW_RSS flag, then @rss_context is ++ * filled with the RSS context ID associated with the rule. ++ * ++ * For %ETHTOOL_GRXCLSRLALL, @rule_cnt specifies the array size of the ++ * user buffer for @rule_locs on entry. On return, @data is the size ++ * of the rule table, @rule_cnt is the number of defined rules, and ++ * @rule_locs contains the locations of the defined rules. Drivers ++ * must use the second parameter to get_rxnfc() instead of @rule_locs. ++ * ++ * For %ETHTOOL_SRXCLSRLINS, @fs specifies the rule to add or update. ++ * @fs.@location either specifies the location to use or is a special ++ * location value with %RX_CLS_LOC_SPECIAL flag set. On return, ++ * @fs.@location is the actual rule location. If @fs.@flow_type ++ * includes the %FLOW_RSS flag, @rss_context is the RSS context ID to ++ * use for flow spreading traffic which matches this rule. The value ++ * from the rxfh indirection table will be added to @fs.@ring_cookie ++ * to choose which ring to deliver to. ++ * ++ * For %ETHTOOL_SRXCLSRLDEL, @fs.@location specifies the location of an ++ * existing rule on entry. ++ * ++ * A driver supporting the special location values for ++ * %ETHTOOL_SRXCLSRLINS may add the rule at any suitable unused ++ * location, and may remove a rule at a later location (lower ++ * priority) that matches exactly the same set of flows. The special ++ * values are %RX_CLS_LOC_ANY, selecting any location; ++ * %RX_CLS_LOC_FIRST, selecting the first suitable location (maximum ++ * priority); and %RX_CLS_LOC_LAST, selecting the last suitable ++ * location (minimum priority). Additional special values may be ++ * defined in future and drivers must return -%EINVAL for any ++ * unrecognised value. ++ */ + struct ethtool_rxnfc { + __u32 cmd; + __u32 flow_type; +- /* The rx flow hash value or the rule DB size */ + __u64 data; +- /* The following fields are not valid and must not be used for +- * the ETHTOOL_{G,X}RXFH commands. */ + struct ethtool_rx_flow_spec fs; +- __u32 rule_cnt; +- __u32 rule_locs[0]; ++ union { ++ __u32 rule_cnt; ++ __u32 rss_context; ++ }; ++ __u32 rule_locs[]; + }; + ++ ++/** ++ * struct ethtool_rxfh_indir - command to get or set RX flow hash indirection ++ * @cmd: Specific command number - %ETHTOOL_GRXFHINDIR or %ETHTOOL_SRXFHINDIR ++ * @size: On entry, the array size of the user buffer, which may be zero. ++ * On return from %ETHTOOL_GRXFHINDIR, the array size of the hardware ++ * indirection table. ++ * @ring_index: RX ring/queue index for each hash value ++ * ++ * For %ETHTOOL_GRXFHINDIR, a @size of zero means that only the size ++ * should be returned. For %ETHTOOL_SRXFHINDIR, a @size of zero means ++ * the table should be reset to default values. This last feature ++ * is not supported by the original implementations. ++ */ + struct ethtool_rxfh_indir { + __u32 cmd; +- /* On entry, this is the array size of the user buffer. On +- * return from ETHTOOL_GRXFHINDIR, this is the array size of +- * the hardware indirection table. */ + __u32 size; +- __u32 ring_index[0]; /* ring/queue index for each hash value */ ++ __u32 ring_index[]; + }; + ++/** ++ * struct ethtool_rxfh - command to get/set RX flow hash indir or/and hash key. ++ * @cmd: Specific command number - %ETHTOOL_GRSSH or %ETHTOOL_SRSSH ++ * @rss_context: RSS context identifier. Context 0 is the default for normal ++ * traffic; other contexts can be referenced as the destination for RX flow ++ * classification rules. %ETH_RXFH_CONTEXT_ALLOC is used with command ++ * %ETHTOOL_SRSSH to allocate a new RSS context; on return this field will ++ * contain the ID of the newly allocated context. ++ * @indir_size: On entry, the array size of the user buffer for the ++ * indirection table, which may be zero, or (for %ETHTOOL_SRSSH), ++ * %ETH_RXFH_INDIR_NO_CHANGE. On return from %ETHTOOL_GRSSH, ++ * the array size of the hardware indirection table. ++ * @key_size: On entry, the array size of the user buffer for the hash key, ++ * which may be zero. On return from %ETHTOOL_GRSSH, the size of the ++ * hardware hash key. ++ * @hfunc: Defines the current RSS hash function used by HW (or to be set to). ++ * Valid values are one of the %ETH_RSS_HASH_*. ++ * @rsvd8: Reserved for future use; see the note on reserved space. ++ * @rsvd32: Reserved for future use; see the note on reserved space. ++ * @rss_config: RX ring/queue index for each hash value i.e., indirection table ++ * of @indir_size __u32 elements, followed by hash key of @key_size ++ * bytes. ++ * ++ * For %ETHTOOL_GRSSH, a @indir_size and key_size of zero means that only the ++ * size should be returned. For %ETHTOOL_SRSSH, an @indir_size of ++ * %ETH_RXFH_INDIR_NO_CHANGE means that indir table setting is not requested ++ * and a @indir_size of zero means the indir table should be reset to default ++ * values (if @rss_context == 0) or that the RSS context should be deleted. ++ * An hfunc of zero means that hash function setting is not requested. ++ */ ++struct ethtool_rxfh { ++ __u32 cmd; ++ __u32 rss_context; ++ __u32 indir_size; ++ __u32 key_size; ++ __u8 hfunc; ++ __u8 rsvd8[3]; ++ __u32 rsvd32; ++ __u32 rss_config[]; ++}; ++#define ETH_RXFH_CONTEXT_ALLOC 0xffffffff ++#define ETH_RXFH_INDIR_NO_CHANGE 0xffffffff ++ ++/** ++ * struct ethtool_rx_ntuple_flow_spec - specification for RX flow filter ++ * @flow_type: Type of match to perform, e.g. %TCP_V4_FLOW ++ * @h_u: Flow field values to match (dependent on @flow_type) ++ * @m_u: Masks for flow field value bits to be ignored ++ * @vlan_tag: VLAN tag to match ++ * @vlan_tag_mask: Mask for VLAN tag bits to be ignored ++ * @data: Driver-dependent data to match ++ * @data_mask: Mask for driver-dependent data bits to be ignored ++ * @action: RX ring/queue index to deliver to (non-negative) or other action ++ * (negative, e.g. %ETHTOOL_RXNTUPLE_ACTION_DROP) ++ * ++ * For flow types %TCP_V4_FLOW, %UDP_V4_FLOW and %SCTP_V4_FLOW, where ++ * a field value and mask are both zero this is treated as if all mask ++ * bits are set i.e. the field is ignored. ++ */ + struct ethtool_rx_ntuple_flow_spec { + __u32 flow_type; + union { +@@ -403,22 +1314,26 @@ struct ethtool_rx_ntuple_flow_spec { + struct ethtool_tcpip4_spec sctp_ip4_spec; + struct ethtool_ah_espip4_spec ah_ip4_spec; + struct ethtool_ah_espip4_spec esp_ip4_spec; +- struct ethtool_rawip4_spec raw_ip4_spec; +- struct ethtool_ether_spec ether_spec; + struct ethtool_usrip4_spec usr_ip4_spec; +- __u8 hdata[64]; +- } h_u, m_u; /* entry, mask */ ++ struct ethhdr ether_spec; ++ __u8 hdata[72]; ++ } h_u, m_u; + + __u16 vlan_tag; + __u16 vlan_tag_mask; +- __u64 data; /* user-defined flow spec data */ +- __u64 data_mask; /* user-defined flow spec mask */ ++ __u64 data; ++ __u64 data_mask; + +- /* signed to distinguish between queue and actions (DROP) */ + __s32 action; +-#define ETHTOOL_RXNTUPLE_ACTION_DROP -1 ++#define ETHTOOL_RXNTUPLE_ACTION_DROP (-1) /* drop packet */ ++#define ETHTOOL_RXNTUPLE_ACTION_CLEAR (-2) /* clear filter */ + }; + ++/** ++ * struct ethtool_rx_ntuple - command to set or clear RX flow filter ++ * @cmd: Command number - %ETHTOOL_SRXNTUPLE ++ * @fs: Flow filter specification ++ */ + struct ethtool_rx_ntuple { + __u32 cmd; + struct ethtool_rx_ntuple_flow_spec fs; +@@ -436,9 +1351,236 @@ struct ethtool_flash { + char data[ETHTOOL_FLASH_MAX_FILENAME]; + }; + ++/** ++ * struct ethtool_dump - used for retrieving, setting device dump ++ * @cmd: Command number - %ETHTOOL_GET_DUMP_FLAG, %ETHTOOL_GET_DUMP_DATA, or ++ * %ETHTOOL_SET_DUMP ++ * @version: FW version of the dump, filled in by driver ++ * @flag: driver dependent flag for dump setting, filled in by driver during ++ * get and filled in by ethtool for set operation. ++ * flag must be initialized by macro ETH_FW_DUMP_DISABLE value when ++ * firmware dump is disabled. ++ * @len: length of dump data, used as the length of the user buffer on entry to ++ * %ETHTOOL_GET_DUMP_DATA and this is returned as dump length by driver ++ * for %ETHTOOL_GET_DUMP_FLAG command ++ * @data: data collected for get dump data operation ++ */ ++struct ethtool_dump { ++ __u32 cmd; ++ __u32 version; ++ __u32 flag; ++ __u32 len; ++ __u8 data[]; ++}; ++ ++#define ETH_FW_DUMP_DISABLE 0 ++ ++/* for returning and changing feature sets */ ++ ++/** ++ * struct ethtool_get_features_block - block with state of 32 features ++ * @available: mask of changeable features ++ * @requested: mask of features requested to be enabled if possible ++ * @active: mask of currently enabled features ++ * @never_changed: mask of features not changeable for any device ++ */ ++struct ethtool_get_features_block { ++ __u32 available; ++ __u32 requested; ++ __u32 active; ++ __u32 never_changed; ++}; ++ ++/** ++ * struct ethtool_gfeatures - command to get state of device's features ++ * @cmd: command number = %ETHTOOL_GFEATURES ++ * @size: On entry, the number of elements in the features[] array; ++ * on return, the number of elements in features[] needed to hold ++ * all features ++ * @features: state of features ++ */ ++struct ethtool_gfeatures { ++ __u32 cmd; ++ __u32 size; ++ struct ethtool_get_features_block features[]; ++}; ++ ++/** ++ * struct ethtool_set_features_block - block with request for 32 features ++ * @valid: mask of features to be changed ++ * @requested: values of features to be changed ++ */ ++struct ethtool_set_features_block { ++ __u32 valid; ++ __u32 requested; ++}; ++ ++/** ++ * struct ethtool_sfeatures - command to request change in device's features ++ * @cmd: command number = %ETHTOOL_SFEATURES ++ * @size: array size of the features[] array ++ * @features: feature change masks ++ */ ++struct ethtool_sfeatures { ++ __u32 cmd; ++ __u32 size; ++ struct ethtool_set_features_block features[]; ++}; ++ ++/** ++ * struct ethtool_ts_info - holds a device's timestamping and PHC association ++ * @cmd: command number = %ETHTOOL_GET_TS_INFO ++ * @so_timestamping: bit mask of the sum of the supported SO_TIMESTAMPING flags ++ * @phc_index: device index of the associated PHC, or -1 if there is none ++ * @tx_types: bit mask of the supported hwtstamp_tx_types enumeration values ++ * @tx_reserved: Reserved for future use; see the note on reserved space. ++ * @rx_filters: bit mask of the supported hwtstamp_rx_filters enumeration values ++ * @rx_reserved: Reserved for future use; see the note on reserved space. ++ * ++ * The bits in the 'tx_types' and 'rx_filters' fields correspond to ++ * the 'hwtstamp_tx_types' and 'hwtstamp_rx_filters' enumeration values, ++ * respectively. For example, if the device supports HWTSTAMP_TX_ON, ++ * then (1 << HWTSTAMP_TX_ON) in 'tx_types' will be set. ++ * ++ * Drivers should only report the filters they actually support without ++ * upscaling in the SIOCSHWTSTAMP ioctl. If the SIOCSHWSTAMP request for ++ * HWTSTAMP_FILTER_V1_SYNC is supported by HWTSTAMP_FILTER_V1_EVENT, then the ++ * driver should only report HWTSTAMP_FILTER_V1_EVENT in this op. ++ */ ++struct ethtool_ts_info { ++ __u32 cmd; ++ __u32 so_timestamping; ++ __s32 phc_index; ++ __u32 tx_types; ++ __u32 tx_reserved[3]; ++ __u32 rx_filters; ++ __u32 rx_reserved[3]; ++}; ++ ++/* ++ * %ETHTOOL_SFEATURES changes features present in features[].valid to the ++ * values of corresponding bits in features[].requested. Bits in .requested ++ * not set in .valid or not changeable are ignored. ++ * ++ * Returns %EINVAL when .valid contains undefined or never-changeable bits ++ * or size is not equal to required number of features words (32-bit blocks). ++ * Returns >= 0 if request was completed; bits set in the value mean: ++ * %ETHTOOL_F_UNSUPPORTED - there were bits set in .valid that are not ++ * changeable (not present in %ETHTOOL_GFEATURES' features[].available) ++ * those bits were ignored. ++ * %ETHTOOL_F_WISH - some or all changes requested were recorded but the ++ * resulting state of bits masked by .valid is not equal to .requested. ++ * Probably there are other device-specific constraints on some features ++ * in the set. When %ETHTOOL_F_UNSUPPORTED is set, .valid is considered ++ * here as though ignored bits were cleared. ++ * %ETHTOOL_F_COMPAT - some or all changes requested were made by calling ++ * compatibility functions. Requested offload state cannot be properly ++ * managed by kernel. ++ * ++ * Meaning of bits in the masks are obtained by %ETHTOOL_GSSET_INFO (number of ++ * bits in the arrays - always multiple of 32) and %ETHTOOL_GSTRINGS commands ++ * for ETH_SS_FEATURES string set. First entry in the table corresponds to least ++ * significant bit in features[0] fields. Empty strings mark undefined features. ++ */ ++enum ethtool_sfeatures_retval_bits { ++ ETHTOOL_F_UNSUPPORTED__BIT, ++ ETHTOOL_F_WISH__BIT, ++ ETHTOOL_F_COMPAT__BIT, ++}; ++ ++#define ETHTOOL_F_UNSUPPORTED (1 << ETHTOOL_F_UNSUPPORTED__BIT) ++#define ETHTOOL_F_WISH (1 << ETHTOOL_F_WISH__BIT) ++#define ETHTOOL_F_COMPAT (1 << ETHTOOL_F_COMPAT__BIT) ++ ++#define MAX_NUM_QUEUE 4096 ++ ++/** ++ * struct ethtool_per_queue_op - apply sub command to the queues in mask. ++ * @cmd: ETHTOOL_PERQUEUE ++ * @sub_command: the sub command which apply to each queues ++ * @queue_mask: Bitmap of the queues which sub command apply to ++ * @data: A complete command structure following for each of the queues addressed ++ */ ++struct ethtool_per_queue_op { ++ __u32 cmd; ++ __u32 sub_command; ++ __u32 queue_mask[__KERNEL_DIV_ROUND_UP(MAX_NUM_QUEUE, 32)]; ++ char data[]; ++}; ++ ++/** ++ * struct ethtool_fecparam - Ethernet Forward Error Correction parameters ++ * @cmd: Command number = %ETHTOOL_GFECPARAM or %ETHTOOL_SFECPARAM ++ * @active_fec: FEC mode which is active on the port, single bit set, GET only. ++ * @fec: Bitmask of configured FEC modes. ++ * @reserved: Reserved for future extensions, ignore on GET, write 0 for SET. ++ * ++ * Note that @reserved was never validated on input and ethtool user space ++ * left it uninitialized when calling SET. Hence going forward it can only be ++ * used to return a value to userspace with GET. ++ * ++ * FEC modes supported by the device can be read via %ETHTOOL_GLINKSETTINGS. ++ * FEC settings are configured by link autonegotiation whenever it's enabled. ++ * With autoneg on %ETHTOOL_GFECPARAM can be used to read the current mode. ++ * ++ * When autoneg is disabled %ETHTOOL_SFECPARAM controls the FEC settings. ++ * It is recommended that drivers only accept a single bit set in @fec. ++ * When multiple bits are set in @fec drivers may pick mode in an implementation ++ * dependent way. Drivers should reject mixing %ETHTOOL_FEC_AUTO_BIT with other ++ * FEC modes, because it's unclear whether in this case other modes constrain ++ * AUTO or are independent choices. ++ * Drivers must reject SET requests if they support none of the requested modes. ++ * ++ * If device does not support FEC drivers may use %ETHTOOL_FEC_NONE instead ++ * of returning %EOPNOTSUPP from %ETHTOOL_GFECPARAM. ++ * ++ * See enum ethtool_fec_config_bits for definition of valid bits for both ++ * @fec and @active_fec. ++ */ ++struct ethtool_fecparam { ++ __u32 cmd; ++ /* bitmask of FEC modes */ ++ __u32 active_fec; ++ __u32 fec; ++ __u32 reserved; ++}; ++ ++/** ++ * enum ethtool_fec_config_bits - flags definition of ethtool_fec_configuration ++ * @ETHTOOL_FEC_NONE_BIT: FEC mode configuration is not supported. Should not ++ * be used together with other bits. GET only. ++ * @ETHTOOL_FEC_AUTO_BIT: Select default/best FEC mode automatically, usually ++ * based link mode and SFP parameters read from module's ++ * EEPROM. This bit does _not_ mean autonegotiation. ++ * @ETHTOOL_FEC_OFF_BIT: No FEC Mode ++ * @ETHTOOL_FEC_RS_BIT: Reed-Solomon FEC Mode ++ * @ETHTOOL_FEC_BASER_BIT: Base-R/Reed-Solomon FEC Mode ++ * @ETHTOOL_FEC_LLRS_BIT: Low Latency Reed Solomon FEC Mode (25G/50G Ethernet ++ * Consortium) ++ */ ++enum ethtool_fec_config_bits { ++ ETHTOOL_FEC_NONE_BIT, ++ ETHTOOL_FEC_AUTO_BIT, ++ ETHTOOL_FEC_OFF_BIT, ++ ETHTOOL_FEC_RS_BIT, ++ ETHTOOL_FEC_BASER_BIT, ++ ETHTOOL_FEC_LLRS_BIT, ++}; ++ ++#define ETHTOOL_FEC_NONE (1 << ETHTOOL_FEC_NONE_BIT) ++#define ETHTOOL_FEC_AUTO (1 << ETHTOOL_FEC_AUTO_BIT) ++#define ETHTOOL_FEC_OFF (1 << ETHTOOL_FEC_OFF_BIT) ++#define ETHTOOL_FEC_RS (1 << ETHTOOL_FEC_RS_BIT) ++#define ETHTOOL_FEC_BASER (1 << ETHTOOL_FEC_BASER_BIT) ++#define ETHTOOL_FEC_LLRS (1 << ETHTOOL_FEC_LLRS_BIT) ++ + /* CMDs currently supported */ +-#define ETHTOOL_GSET 0x00000001 /* Get settings. */ +-#define ETHTOOL_SSET 0x00000002 /* Set settings. */ ++#define ETHTOOL_GSET 0x00000001 /* DEPRECATED, Get settings. ++ * Please use ETHTOOL_GLINKSETTINGS ++ */ ++#define ETHTOOL_SSET 0x00000002 /* DEPRECATED, Set settings. ++ * Please use ETHTOOL_SLINKSETTINGS ++ */ + #define ETHTOOL_GDRVINFO 0x00000003 /* Get driver info. */ + #define ETHTOOL_GREGS 0x00000004 /* Get NIC registers. */ + #define ETHTOOL_GWOL 0x00000005 /* Get wake-on-lan options. */ +@@ -446,7 +1588,9 @@ struct ethtool_flash { + #define ETHTOOL_GMSGLVL 0x00000007 /* Get driver message level */ + #define ETHTOOL_SMSGLVL 0x00000008 /* Set driver msg level. */ + #define ETHTOOL_NWAY_RST 0x00000009 /* Restart autonegotiation. */ +-#define ETHTOOL_GLINK 0x0000000a /* Get link status (ethtool_value) */ ++/* Get link status for host, i.e. whether the interface *and* the ++ * physical port (if there is one) are up (ethtool_value). */ ++#define ETHTOOL_GLINK 0x0000000a + #define ETHTOOL_GEEPROM 0x0000000b /* Get EEPROM data */ + #define ETHTOOL_SEEPROM 0x0000000c /* Set EEPROM data. */ + #define ETHTOOL_GCOALESCE 0x0000000e /* Get coalesce config */ +@@ -492,77 +1636,318 @@ struct ethtool_flash { + #define ETHTOOL_FLASHDEV 0x00000033 /* Flash firmware to device */ + #define ETHTOOL_RESET 0x00000034 /* Reset hardware */ + #define ETHTOOL_SRXNTUPLE 0x00000035 /* Add an n-tuple filter to device */ +-#define ETHTOOL_GRXNTUPLE 0x00000036 /* Get n-tuple filters from device */ ++#define ETHTOOL_GRXNTUPLE 0x00000036 /* deprecated */ + #define ETHTOOL_GSSET_INFO 0x00000037 /* Get string set info */ + #define ETHTOOL_GRXFHINDIR 0x00000038 /* Get RX flow hash indir'n table */ + #define ETHTOOL_SRXFHINDIR 0x00000039 /* Set RX flow hash indir'n table */ + ++#define ETHTOOL_GFEATURES 0x0000003a /* Get device offload settings */ ++#define ETHTOOL_SFEATURES 0x0000003b /* Change device offload settings */ ++#define ETHTOOL_GCHANNELS 0x0000003c /* Get no of channels */ ++#define ETHTOOL_SCHANNELS 0x0000003d /* Set no of channels */ ++#define ETHTOOL_SET_DUMP 0x0000003e /* Set dump settings */ ++#define ETHTOOL_GET_DUMP_FLAG 0x0000003f /* Get dump settings */ ++#define ETHTOOL_GET_DUMP_DATA 0x00000040 /* Get dump data */ ++#define ETHTOOL_GET_TS_INFO 0x00000041 /* Get time stamping and PHC info */ ++#define ETHTOOL_GMODULEINFO 0x00000042 /* Get plug-in module information */ ++#define ETHTOOL_GMODULEEEPROM 0x00000043 /* Get plug-in module eeprom */ ++#define ETHTOOL_GEEE 0x00000044 /* Get EEE settings */ ++#define ETHTOOL_SEEE 0x00000045 /* Set EEE settings */ ++ ++#define ETHTOOL_GRSSH 0x00000046 /* Get RX flow hash configuration */ ++#define ETHTOOL_SRSSH 0x00000047 /* Set RX flow hash configuration */ ++#define ETHTOOL_GTUNABLE 0x00000048 /* Get tunable configuration */ ++#define ETHTOOL_STUNABLE 0x00000049 /* Set tunable configuration */ ++#define ETHTOOL_GPHYSTATS 0x0000004a /* get PHY-specific statistics */ ++ ++#define ETHTOOL_PERQUEUE 0x0000004b /* Set per queue options */ ++ ++#define ETHTOOL_GLINKSETTINGS 0x0000004c /* Get ethtool_link_settings */ ++#define ETHTOOL_SLINKSETTINGS 0x0000004d /* Set ethtool_link_settings */ ++#define ETHTOOL_PHY_GTUNABLE 0x0000004e /* Get PHY tunable configuration */ ++#define ETHTOOL_PHY_STUNABLE 0x0000004f /* Set PHY tunable configuration */ ++#define ETHTOOL_GFECPARAM 0x00000050 /* Get FEC settings */ ++#define ETHTOOL_SFECPARAM 0x00000051 /* Set FEC settings */ ++ + /* compatibility with older code */ + #define SPARC_ETH_GSET ETHTOOL_GSET + #define SPARC_ETH_SSET ETHTOOL_SSET + +-/* Indicates what features are supported by the interface. */ +-#define SUPPORTED_10baseT_Half (1 << 0) +-#define SUPPORTED_10baseT_Full (1 << 1) +-#define SUPPORTED_100baseT_Half (1 << 2) +-#define SUPPORTED_100baseT_Full (1 << 3) +-#define SUPPORTED_1000baseT_Half (1 << 4) +-#define SUPPORTED_1000baseT_Full (1 << 5) +-#define SUPPORTED_Autoneg (1 << 6) +-#define SUPPORTED_TP (1 << 7) +-#define SUPPORTED_AUI (1 << 8) +-#define SUPPORTED_MII (1 << 9) +-#define SUPPORTED_FIBRE (1 << 10) +-#define SUPPORTED_BNC (1 << 11) +-#define SUPPORTED_10000baseT_Full (1 << 12) +-#define SUPPORTED_Pause (1 << 13) +-#define SUPPORTED_Asym_Pause (1 << 14) +-#define SUPPORTED_2500baseX_Full (1 << 15) +-#define SUPPORTED_Backplane (1 << 16) +-#define SUPPORTED_1000baseKX_Full (1 << 17) +-#define SUPPORTED_10000baseKX4_Full (1 << 18) +-#define SUPPORTED_10000baseKR_Full (1 << 19) +-#define SUPPORTED_10000baseR_FEC (1 << 20) +- +-/* Indicates what features are advertised by the interface. */ +-#define ADVERTISED_10baseT_Half (1 << 0) +-#define ADVERTISED_10baseT_Full (1 << 1) +-#define ADVERTISED_100baseT_Half (1 << 2) +-#define ADVERTISED_100baseT_Full (1 << 3) +-#define ADVERTISED_1000baseT_Half (1 << 4) +-#define ADVERTISED_1000baseT_Full (1 << 5) +-#define ADVERTISED_Autoneg (1 << 6) +-#define ADVERTISED_TP (1 << 7) +-#define ADVERTISED_AUI (1 << 8) +-#define ADVERTISED_MII (1 << 9) +-#define ADVERTISED_FIBRE (1 << 10) +-#define ADVERTISED_BNC (1 << 11) +-#define ADVERTISED_10000baseT_Full (1 << 12) +-#define ADVERTISED_Pause (1 << 13) +-#define ADVERTISED_Asym_Pause (1 << 14) +-#define ADVERTISED_2500baseX_Full (1 << 15) +-#define ADVERTISED_Backplane (1 << 16) +-#define ADVERTISED_1000baseKX_Full (1 << 17) +-#define ADVERTISED_10000baseKX4_Full (1 << 18) +-#define ADVERTISED_10000baseKR_Full (1 << 19) +-#define ADVERTISED_10000baseR_FEC (1 << 20) ++/* Link mode bit indices */ ++enum ethtool_link_mode_bit_indices { ++ ETHTOOL_LINK_MODE_10baseT_Half_BIT = 0, ++ ETHTOOL_LINK_MODE_10baseT_Full_BIT = 1, ++ ETHTOOL_LINK_MODE_100baseT_Half_BIT = 2, ++ ETHTOOL_LINK_MODE_100baseT_Full_BIT = 3, ++ ETHTOOL_LINK_MODE_1000baseT_Half_BIT = 4, ++ ETHTOOL_LINK_MODE_1000baseT_Full_BIT = 5, ++ ETHTOOL_LINK_MODE_Autoneg_BIT = 6, ++ ETHTOOL_LINK_MODE_TP_BIT = 7, ++ ETHTOOL_LINK_MODE_AUI_BIT = 8, ++ ETHTOOL_LINK_MODE_MII_BIT = 9, ++ ETHTOOL_LINK_MODE_FIBRE_BIT = 10, ++ ETHTOOL_LINK_MODE_BNC_BIT = 11, ++ ETHTOOL_LINK_MODE_10000baseT_Full_BIT = 12, ++ ETHTOOL_LINK_MODE_Pause_BIT = 13, ++ ETHTOOL_LINK_MODE_Asym_Pause_BIT = 14, ++ ETHTOOL_LINK_MODE_2500baseX_Full_BIT = 15, ++ ETHTOOL_LINK_MODE_Backplane_BIT = 16, ++ ETHTOOL_LINK_MODE_1000baseKX_Full_BIT = 17, ++ ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT = 18, ++ ETHTOOL_LINK_MODE_10000baseKR_Full_BIT = 19, ++ ETHTOOL_LINK_MODE_10000baseR_FEC_BIT = 20, ++ ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT = 21, ++ ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT = 22, ++ ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT = 23, ++ ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT = 24, ++ ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT = 25, ++ ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT = 26, ++ ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT = 27, ++ ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT = 28, ++ ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT = 29, ++ ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT = 30, ++ ETHTOOL_LINK_MODE_25000baseCR_Full_BIT = 31, ++ ++ /* 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. ++ */ ++ ++ ETHTOOL_LINK_MODE_25000baseKR_Full_BIT = 32, ++ ETHTOOL_LINK_MODE_25000baseSR_Full_BIT = 33, ++ ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT = 34, ++ ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT = 35, ++ ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT = 36, ++ ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT = 37, ++ ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT = 38, ++ ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT = 39, ++ ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT = 40, ++ ETHTOOL_LINK_MODE_1000baseX_Full_BIT = 41, ++ ETHTOOL_LINK_MODE_10000baseCR_Full_BIT = 42, ++ ETHTOOL_LINK_MODE_10000baseSR_Full_BIT = 43, ++ ETHTOOL_LINK_MODE_10000baseLR_Full_BIT = 44, ++ ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT = 45, ++ ETHTOOL_LINK_MODE_10000baseER_Full_BIT = 46, ++ ETHTOOL_LINK_MODE_2500baseT_Full_BIT = 47, ++ ETHTOOL_LINK_MODE_5000baseT_Full_BIT = 48, ++ ++ ETHTOOL_LINK_MODE_FEC_NONE_BIT = 49, ++ ETHTOOL_LINK_MODE_FEC_RS_BIT = 50, ++ ETHTOOL_LINK_MODE_FEC_BASER_BIT = 51, ++ ETHTOOL_LINK_MODE_50000baseKR_Full_BIT = 52, ++ ETHTOOL_LINK_MODE_50000baseSR_Full_BIT = 53, ++ ETHTOOL_LINK_MODE_50000baseCR_Full_BIT = 54, ++ ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT = 55, ++ ETHTOOL_LINK_MODE_50000baseDR_Full_BIT = 56, ++ ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT = 57, ++ ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT = 58, ++ ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT = 59, ++ ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT = 60, ++ ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT = 61, ++ ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT = 62, ++ ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT = 63, ++ ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT = 64, ++ ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT = 65, ++ ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT = 66, ++ ETHTOOL_LINK_MODE_100baseT1_Full_BIT = 67, ++ ETHTOOL_LINK_MODE_1000baseT1_Full_BIT = 68, ++ ETHTOOL_LINK_MODE_400000baseKR8_Full_BIT = 69, ++ ETHTOOL_LINK_MODE_400000baseSR8_Full_BIT = 70, ++ ETHTOOL_LINK_MODE_400000baseLR8_ER8_FR8_Full_BIT = 71, ++ ETHTOOL_LINK_MODE_400000baseDR8_Full_BIT = 72, ++ ETHTOOL_LINK_MODE_400000baseCR8_Full_BIT = 73, ++ ETHTOOL_LINK_MODE_FEC_LLRS_BIT = 74, ++ ETHTOOL_LINK_MODE_100000baseKR_Full_BIT = 75, ++ ETHTOOL_LINK_MODE_100000baseSR_Full_BIT = 76, ++ ETHTOOL_LINK_MODE_100000baseLR_ER_FR_Full_BIT = 77, ++ ETHTOOL_LINK_MODE_100000baseCR_Full_BIT = 78, ++ ETHTOOL_LINK_MODE_100000baseDR_Full_BIT = 79, ++ ETHTOOL_LINK_MODE_200000baseKR2_Full_BIT = 80, ++ ETHTOOL_LINK_MODE_200000baseSR2_Full_BIT = 81, ++ ETHTOOL_LINK_MODE_200000baseLR2_ER2_FR2_Full_BIT = 82, ++ ETHTOOL_LINK_MODE_200000baseDR2_Full_BIT = 83, ++ ETHTOOL_LINK_MODE_200000baseCR2_Full_BIT = 84, ++ ETHTOOL_LINK_MODE_400000baseKR4_Full_BIT = 85, ++ ETHTOOL_LINK_MODE_400000baseSR4_Full_BIT = 86, ++ ETHTOOL_LINK_MODE_400000baseLR4_ER4_FR4_Full_BIT = 87, ++ ETHTOOL_LINK_MODE_400000baseDR4_Full_BIT = 88, ++ ETHTOOL_LINK_MODE_400000baseCR4_Full_BIT = 89, ++ ETHTOOL_LINK_MODE_100baseFX_Half_BIT = 90, ++ ETHTOOL_LINK_MODE_100baseFX_Full_BIT = 91, ++ ETHTOOL_LINK_MODE_10baseT1L_Full_BIT = 92, ++ ETHTOOL_LINK_MODE_800000baseCR8_Full_BIT = 93, ++ ETHTOOL_LINK_MODE_800000baseKR8_Full_BIT = 94, ++ ETHTOOL_LINK_MODE_800000baseDR8_Full_BIT = 95, ++ ETHTOOL_LINK_MODE_800000baseDR8_2_Full_BIT = 96, ++ ETHTOOL_LINK_MODE_800000baseSR8_Full_BIT = 97, ++ ETHTOOL_LINK_MODE_800000baseVR8_Full_BIT = 98, ++ ETHTOOL_LINK_MODE_10baseT1S_Full_BIT = 99, ++ ETHTOOL_LINK_MODE_10baseT1S_Half_BIT = 100, ++ ETHTOOL_LINK_MODE_10baseT1S_P2MP_Half_BIT = 101, ++ ++ /* must be last entry */ ++ __ETHTOOL_LINK_MODE_MASK_NBITS ++}; ++ ++#define __ETHTOOL_LINK_MODE_LEGACY_MASK(base_name) \ ++ (1UL << (ETHTOOL_LINK_MODE_ ## base_name ## _BIT)) ++ ++/* DEPRECATED macros. Please migrate to ++ * ETHTOOL_GLINKSETTINGS/ETHTOOL_SLINKSETTINGS API. Please do NOT ++ * define any new SUPPORTED_* macro for bits > 31. ++ */ ++#define SUPPORTED_10baseT_Half __ETHTOOL_LINK_MODE_LEGACY_MASK(10baseT_Half) ++#define SUPPORTED_10baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10baseT_Full) ++#define SUPPORTED_100baseT_Half __ETHTOOL_LINK_MODE_LEGACY_MASK(100baseT_Half) ++#define SUPPORTED_100baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(100baseT_Full) ++#define SUPPORTED_1000baseT_Half __ETHTOOL_LINK_MODE_LEGACY_MASK(1000baseT_Half) ++#define SUPPORTED_1000baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(1000baseT_Full) ++#define SUPPORTED_Autoneg __ETHTOOL_LINK_MODE_LEGACY_MASK(Autoneg) ++#define SUPPORTED_TP __ETHTOOL_LINK_MODE_LEGACY_MASK(TP) ++#define SUPPORTED_AUI __ETHTOOL_LINK_MODE_LEGACY_MASK(AUI) ++#define SUPPORTED_MII __ETHTOOL_LINK_MODE_LEGACY_MASK(MII) ++#define SUPPORTED_FIBRE __ETHTOOL_LINK_MODE_LEGACY_MASK(FIBRE) ++#define SUPPORTED_BNC __ETHTOOL_LINK_MODE_LEGACY_MASK(BNC) ++#define SUPPORTED_10000baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseT_Full) ++#define SUPPORTED_Pause __ETHTOOL_LINK_MODE_LEGACY_MASK(Pause) ++#define SUPPORTED_Asym_Pause __ETHTOOL_LINK_MODE_LEGACY_MASK(Asym_Pause) ++#define SUPPORTED_2500baseX_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(2500baseX_Full) ++#define SUPPORTED_Backplane __ETHTOOL_LINK_MODE_LEGACY_MASK(Backplane) ++#define SUPPORTED_1000baseKX_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(1000baseKX_Full) ++#define SUPPORTED_10000baseKX4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseKX4_Full) ++#define SUPPORTED_10000baseKR_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseKR_Full) ++#define SUPPORTED_10000baseR_FEC __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseR_FEC) ++#define SUPPORTED_20000baseMLD2_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(20000baseMLD2_Full) ++#define SUPPORTED_20000baseKR2_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(20000baseKR2_Full) ++#define SUPPORTED_40000baseKR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseKR4_Full) ++#define SUPPORTED_40000baseCR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseCR4_Full) ++#define SUPPORTED_40000baseSR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseSR4_Full) ++#define SUPPORTED_40000baseLR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseLR4_Full) ++#define SUPPORTED_56000baseKR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseKR4_Full) ++#define SUPPORTED_56000baseCR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseCR4_Full) ++#define SUPPORTED_56000baseSR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseSR4_Full) ++#define SUPPORTED_56000baseLR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseLR4_Full) ++/* Please do not define any new SUPPORTED_* macro for bits > 31, see ++ * notice above. ++ */ ++ ++/* ++ * DEPRECATED macros. Please migrate to ++ * ETHTOOL_GLINKSETTINGS/ETHTOOL_SLINKSETTINGS API. Please do NOT ++ * define any new ADERTISE_* macro for bits > 31. ++ */ ++#define ADVERTISED_10baseT_Half __ETHTOOL_LINK_MODE_LEGACY_MASK(10baseT_Half) ++#define ADVERTISED_10baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10baseT_Full) ++#define ADVERTISED_100baseT_Half __ETHTOOL_LINK_MODE_LEGACY_MASK(100baseT_Half) ++#define ADVERTISED_100baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(100baseT_Full) ++#define ADVERTISED_1000baseT_Half __ETHTOOL_LINK_MODE_LEGACY_MASK(1000baseT_Half) ++#define ADVERTISED_1000baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(1000baseT_Full) ++#define ADVERTISED_Autoneg __ETHTOOL_LINK_MODE_LEGACY_MASK(Autoneg) ++#define ADVERTISED_TP __ETHTOOL_LINK_MODE_LEGACY_MASK(TP) ++#define ADVERTISED_AUI __ETHTOOL_LINK_MODE_LEGACY_MASK(AUI) ++#define ADVERTISED_MII __ETHTOOL_LINK_MODE_LEGACY_MASK(MII) ++#define ADVERTISED_FIBRE __ETHTOOL_LINK_MODE_LEGACY_MASK(FIBRE) ++#define ADVERTISED_BNC __ETHTOOL_LINK_MODE_LEGACY_MASK(BNC) ++#define ADVERTISED_10000baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseT_Full) ++#define ADVERTISED_Pause __ETHTOOL_LINK_MODE_LEGACY_MASK(Pause) ++#define ADVERTISED_Asym_Pause __ETHTOOL_LINK_MODE_LEGACY_MASK(Asym_Pause) ++#define ADVERTISED_2500baseX_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(2500baseX_Full) ++#define ADVERTISED_Backplane __ETHTOOL_LINK_MODE_LEGACY_MASK(Backplane) ++#define ADVERTISED_1000baseKX_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(1000baseKX_Full) ++#define ADVERTISED_10000baseKX4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseKX4_Full) ++#define ADVERTISED_10000baseKR_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseKR_Full) ++#define ADVERTISED_10000baseR_FEC __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseR_FEC) ++#define ADVERTISED_20000baseMLD2_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(20000baseMLD2_Full) ++#define ADVERTISED_20000baseKR2_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(20000baseKR2_Full) ++#define ADVERTISED_40000baseKR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseKR4_Full) ++#define ADVERTISED_40000baseCR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseCR4_Full) ++#define ADVERTISED_40000baseSR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseSR4_Full) ++#define ADVERTISED_40000baseLR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseLR4_Full) ++#define ADVERTISED_56000baseKR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseKR4_Full) ++#define ADVERTISED_56000baseCR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseCR4_Full) ++#define ADVERTISED_56000baseSR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseSR4_Full) ++#define ADVERTISED_56000baseLR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseLR4_Full) ++/* Please do not define any new ADVERTISED_* macro for bits > 31, see ++ * notice above. ++ */ + + /* The following are all involved in forcing a particular link + * mode for the device for setting things. When getting the + * devices settings, these indicate the current mode and whether +- * it was foced up into this mode or autonegotiated. ++ * it was forced up into this mode or autonegotiated. + */ + +-/* The forced speed, 10Mb, 100Mb, gigabit, 2.5Gb, 10GbE. */ ++/* The forced speed, in units of 1Mb. All values 0 to INT_MAX are legal. ++ * Update drivers/net/phy/phy.c:phy_speed_to_str() and ++ * drivers/net/bonding/bond_3ad.c:__get_link_speed() when adding new values. ++ */ + #define SPEED_10 10 + #define SPEED_100 100 + #define SPEED_1000 1000 + #define SPEED_2500 2500 ++#define SPEED_5000 5000 + #define SPEED_10000 10000 ++#define SPEED_14000 14000 ++#define SPEED_20000 20000 ++#define SPEED_25000 25000 ++#define SPEED_40000 40000 ++#define SPEED_50000 50000 ++#define SPEED_56000 56000 ++#define SPEED_100000 100000 ++#define SPEED_200000 200000 ++#define SPEED_400000 400000 ++#define SPEED_800000 800000 ++ ++#define SPEED_UNKNOWN -1 ++ ++static __inline__ int ethtool_validate_speed(__u32 speed) ++{ ++ return speed <= INT_MAX || speed == (__u32)SPEED_UNKNOWN; ++} + + /* Duplex, half or full. */ + #define DUPLEX_HALF 0x00 + #define DUPLEX_FULL 0x01 ++#define DUPLEX_UNKNOWN 0xff ++ ++static __inline__ int ethtool_validate_duplex(__u8 duplex) ++{ ++ switch (duplex) { ++ case DUPLEX_HALF: ++ case DUPLEX_FULL: ++ case DUPLEX_UNKNOWN: ++ return 1; ++ } ++ ++ return 0; ++} ++ ++#define MASTER_SLAVE_CFG_UNSUPPORTED 0 ++#define MASTER_SLAVE_CFG_UNKNOWN 1 ++#define MASTER_SLAVE_CFG_MASTER_PREFERRED 2 ++#define MASTER_SLAVE_CFG_SLAVE_PREFERRED 3 ++#define MASTER_SLAVE_CFG_MASTER_FORCE 4 ++#define MASTER_SLAVE_CFG_SLAVE_FORCE 5 ++#define MASTER_SLAVE_STATE_UNSUPPORTED 0 ++#define MASTER_SLAVE_STATE_UNKNOWN 1 ++#define MASTER_SLAVE_STATE_MASTER 2 ++#define MASTER_SLAVE_STATE_SLAVE 3 ++#define MASTER_SLAVE_STATE_ERR 4 ++ ++/* These are used to throttle the rate of data on the phy interface when the ++ * native speed of the interface is higher than the link speed. These should ++ * not be used for phy interfaces which natively support multiple speeds (e.g. ++ * MII or SGMII). ++ */ ++/* No rate matching performed. */ ++#define RATE_MATCH_NONE 0 ++/* The phy sends pause frames to throttle the MAC. */ ++#define RATE_MATCH_PAUSE 1 ++/* The phy asserts CRS to prevent the MAC from transmitting. */ ++#define RATE_MATCH_CRS 2 ++/* The MAC is programmed with a sufficiently-large IPG. */ ++#define RATE_MATCH_OPEN_LOOP 3 + + /* Which connector port. */ + #define PORT_TP 0x00 +@@ -575,22 +1960,23 @@ struct ethtool_flash { + #define PORT_OTHER 0xff + + /* Which transceiver to use. */ +-#define XCVR_INTERNAL 0x00 +-#define XCVR_EXTERNAL 0x01 ++#define XCVR_INTERNAL 0x00 /* PHY and MAC are in the same package */ ++#define XCVR_EXTERNAL 0x01 /* PHY and MAC are in different packages */ + #define XCVR_DUMMY1 0x02 + #define XCVR_DUMMY2 0x03 + #define XCVR_DUMMY3 0x04 + +-/* Enable or disable autonegotiation. If this is set to enable, +- * the forced link modes above are completely ignored. +- */ ++/* Enable or disable autonegotiation. */ + #define AUTONEG_DISABLE 0x00 + #define AUTONEG_ENABLE 0x01 + +-/* Mode MDI or MDI-X */ +-#define ETH_TP_MDI_INVALID 0x00 +-#define ETH_TP_MDI 0x01 +-#define ETH_TP_MDI_X 0x02 ++/* MDI or MDI-X status/control - if MDI/MDI_X/AUTO is set then ++ * the driver is required to renegotiate link ++ */ ++#define ETH_TP_MDI_INVALID 0x00 /* status: unknown; control: unsupported */ ++#define ETH_TP_MDI 0x01 /* status: MDI; control: force MDI */ ++#define ETH_TP_MDI_X 0x02 /* status: MDI-X; control: force MDI-X */ ++#define ETH_TP_MDI_AUTO 0x03 /* control: auto-select */ + + /* Wake-On-Lan options. */ + #define WAKE_PHY (1 << 0) +@@ -600,23 +1986,34 @@ struct ethtool_flash { + #define WAKE_ARP (1 << 4) + #define WAKE_MAGIC (1 << 5) + #define WAKE_MAGICSECURE (1 << 6) /* only meaningful if WAKE_MAGIC */ +- +-/* L3-L4 network traffic flow types */ +-#define TCP_V4_FLOW 0x01 +-#define UDP_V4_FLOW 0x02 +-#define SCTP_V4_FLOW 0x03 +-#define AH_ESP_V4_FLOW 0x04 +-#define TCP_V6_FLOW 0x05 +-#define UDP_V6_FLOW 0x06 +-#define SCTP_V6_FLOW 0x07 +-#define AH_ESP_V6_FLOW 0x08 +-#define AH_V4_FLOW 0x09 +-#define ESP_V4_FLOW 0x0a +-#define AH_V6_FLOW 0x0b +-#define ESP_V6_FLOW 0x0c +-#define IP_USER_FLOW 0x0d +-#define IPV4_FLOW 0x10 +-#define IPV6_FLOW 0x11 ++#define WAKE_FILTER (1 << 7) ++ ++#define WOL_MODE_COUNT 8 ++ ++/* L2-L4 network traffic flow types */ ++#define TCP_V4_FLOW 0x01 /* hash or spec (tcp_ip4_spec) */ ++#define UDP_V4_FLOW 0x02 /* hash or spec (udp_ip4_spec) */ ++#define SCTP_V4_FLOW 0x03 /* hash or spec (sctp_ip4_spec) */ ++#define AH_ESP_V4_FLOW 0x04 /* hash only */ ++#define TCP_V6_FLOW 0x05 /* hash or spec (tcp_ip6_spec; nfc only) */ ++#define UDP_V6_FLOW 0x06 /* hash or spec (udp_ip6_spec; nfc only) */ ++#define SCTP_V6_FLOW 0x07 /* hash or spec (sctp_ip6_spec; nfc only) */ ++#define AH_ESP_V6_FLOW 0x08 /* hash only */ ++#define AH_V4_FLOW 0x09 /* hash or spec (ah_ip4_spec) */ ++#define ESP_V4_FLOW 0x0a /* hash or spec (esp_ip4_spec) */ ++#define AH_V6_FLOW 0x0b /* hash or spec (ah_ip6_spec; nfc only) */ ++#define ESP_V6_FLOW 0x0c /* hash or spec (esp_ip6_spec; nfc only) */ ++#define IPV4_USER_FLOW 0x0d /* spec only (usr_ip4_spec) */ ++#define IP_USER_FLOW IPV4_USER_FLOW ++#define IPV6_USER_FLOW 0x0e /* spec only (usr_ip6_spec; nfc only) */ ++#define IPV4_FLOW 0x10 /* hash only */ ++#define IPV6_FLOW 0x11 /* hash only */ ++#define ETHER_FLOW 0x12 /* spec only (ether_spec) */ ++/* Flag to enable additional fields in struct ethtool_rx_flow_spec */ ++#define FLOW_EXT 0x80000000 ++#define FLOW_MAC_EXT 0x40000000 ++/* Flag to enable RSS spreading of traffic matching rule (nfc only) */ ++#define FLOW_RSS 0x20000000 + + /* L3-L4 network traffic flow hash options */ + #define RXH_L2DA (1 << 1) +@@ -629,6 +2026,26 @@ struct ethtool_flash { + #define RXH_DISCARD (1 << 31) + + #define RX_CLS_FLOW_DISC 0xffffffffffffffffULL ++#define RX_CLS_FLOW_WAKE 0xfffffffffffffffeULL ++ ++/* Special RX classification rule insert location values */ ++#define RX_CLS_LOC_SPECIAL 0x80000000 /* flag */ ++#define RX_CLS_LOC_ANY 0xffffffff ++#define RX_CLS_LOC_FIRST 0xfffffffe ++#define RX_CLS_LOC_LAST 0xfffffffd ++ ++/* EEPROM Standards for plug in modules */ ++#define ETH_MODULE_SFF_8079 0x1 ++#define ETH_MODULE_SFF_8079_LEN 256 ++#define ETH_MODULE_SFF_8472 0x2 ++#define ETH_MODULE_SFF_8472_LEN 512 ++#define ETH_MODULE_SFF_8636 0x3 ++#define ETH_MODULE_SFF_8636_LEN 256 ++#define ETH_MODULE_SFF_8436 0x4 ++#define ETH_MODULE_SFF_8436_LEN 256 ++ ++#define ETH_MODULE_SFF_8636_MAX_LEN 640 ++#define ETH_MODULE_SFF_8436_MAX_LEN 640 + + /* Reset flags */ + /* The reset() operation must clear the flags for the components which +@@ -652,6 +2069,7 @@ enum ethtool_reset_flags { + ETH_RESET_PHY = 1 << 6, /* Transceiver/PHY */ + ETH_RESET_RAM = 1 << 7, /* RAM shared between + * multiple components */ ++ ETH_RESET_AP = 1 << 8, /* Application processor */ + + ETH_RESET_DEDICATED = 0x0000ffff, /* All components dedicated to + * this interface */ +@@ -660,4 +2078,129 @@ enum ethtool_reset_flags { + }; + #define ETH_RESET_SHARED_SHIFT 16 + ++ ++/** ++ * struct ethtool_link_settings - link control and status ++ * ++ * IMPORTANT, Backward compatibility notice: When implementing new ++ * user-space tools, please first try %ETHTOOL_GLINKSETTINGS, and ++ * if it succeeds use %ETHTOOL_SLINKSETTINGS to change link ++ * settings; do not use %ETHTOOL_SSET if %ETHTOOL_GLINKSETTINGS ++ * succeeded: stick to %ETHTOOL_GLINKSETTINGS/%SLINKSETTINGS in ++ * that case. Conversely, if %ETHTOOL_GLINKSETTINGS fails, use ++ * %ETHTOOL_GSET to query and %ETHTOOL_SSET to change link ++ * settings; do not use %ETHTOOL_SLINKSETTINGS if ++ * %ETHTOOL_GLINKSETTINGS failed: stick to ++ * %ETHTOOL_GSET/%ETHTOOL_SSET in that case. ++ * ++ * @cmd: Command number = %ETHTOOL_GLINKSETTINGS or %ETHTOOL_SLINKSETTINGS ++ * @speed: Link speed (Mbps) ++ * @duplex: Duplex mode; one of %DUPLEX_* ++ * @port: Physical connector type; one of %PORT_* ++ * @phy_address: MDIO address of PHY (transceiver); 0 or 255 if not ++ * applicable. For clause 45 PHYs this is the PRTAD. ++ * @autoneg: Enable/disable autonegotiation and auto-detection; ++ * either %AUTONEG_DISABLE or %AUTONEG_ENABLE ++ * @mdio_support: Bitmask of %ETH_MDIO_SUPPORTS_* flags for the MDIO ++ * protocols supported by the interface; 0 if unknown. ++ * Read-only. ++ * @eth_tp_mdix: Ethernet twisted-pair MDI(-X) status; one of ++ * %ETH_TP_MDI_*. If the status is unknown or not applicable, the ++ * value will be %ETH_TP_MDI_INVALID. Read-only. ++ * @eth_tp_mdix_ctrl: Ethernet twisted pair MDI(-X) control; one of ++ * %ETH_TP_MDI_*. If MDI(-X) control is not implemented, reads ++ * yield %ETH_TP_MDI_INVALID and writes may be ignored or rejected. ++ * When written successfully, the link should be renegotiated if ++ * necessary. ++ * @link_mode_masks_nwords: Number of 32-bit words for each of the ++ * supported, advertising, lp_advertising link mode bitmaps. For ++ * %ETHTOOL_GLINKSETTINGS: on entry, number of words passed by user ++ * (>= 0); on return, if handshake in progress, negative if ++ * request size unsupported by kernel: absolute value indicates ++ * kernel expected size and all the other fields but cmd ++ * are 0; otherwise (handshake completed), strictly positive ++ * to indicate size used by kernel and cmd field stays ++ * %ETHTOOL_GLINKSETTINGS, all other fields populated by driver. For ++ * %ETHTOOL_SLINKSETTINGS: must be valid on entry, ie. a positive ++ * value returned previously by %ETHTOOL_GLINKSETTINGS, otherwise ++ * refused. For drivers: ignore this field (use kernel's ++ * __ETHTOOL_LINK_MODE_MASK_NBITS instead), any change to it will ++ * be overwritten by kernel. ++ * @supported: Bitmap with each bit meaning given by ++ * %ethtool_link_mode_bit_indices for the link modes, physical ++ * connectors and other link features for which the interface ++ * supports autonegotiation or auto-detection. Read-only. ++ * @advertising: Bitmap with each bit meaning given by ++ * %ethtool_link_mode_bit_indices for the link modes, physical ++ * connectors and other link features that are advertised through ++ * autonegotiation or enabled for auto-detection. ++ * @lp_advertising: Bitmap with each bit meaning given by ++ * %ethtool_link_mode_bit_indices for the link modes, and other ++ * link features that the link partner advertised through ++ * autonegotiation; 0 if unknown or not applicable. Read-only. ++ * @transceiver: Used to distinguish different possible PHY types, ++ * reported consistently by PHYLIB. Read-only. ++ * @master_slave_cfg: Master/slave port mode. ++ * @master_slave_state: Master/slave port state. ++ * @rate_matching: Rate adaptation performed by the PHY ++ * @reserved: Reserved for future use; see the note on reserved space. ++ * @link_mode_masks: Variable length bitmaps. ++ * ++ * 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 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. ++ * ++ * Some hardware interfaces may have multiple PHYs and/or physical ++ * connectors fitted or do not allow the driver to detect which are ++ * fitted. For these interfaces @port and/or @phy_address may be ++ * writable, possibly dependent on @autoneg being %AUTONEG_DISABLE. ++ * Otherwise, attempts to write different values may be ignored or ++ * rejected. ++ * ++ * Deprecated %ethtool_cmd fields transceiver, maxtxpkt and maxrxpkt ++ * are not available in %ethtool_link_settings. These fields will be ++ * always set to zero in %ETHTOOL_GSET reply and %ETHTOOL_SSET will ++ * fail if any of them is set to non-zero value. ++ * ++ * Users should assume that all fields not marked read-only are ++ * writable and subject to validation by the driver. They should use ++ * %ETHTOOL_GLINKSETTINGS to get the current values before making specific ++ * changes and then applying them with %ETHTOOL_SLINKSETTINGS. ++ * ++ * Drivers that implement %get_link_ksettings and/or ++ * %set_link_ksettings should ignore the @cmd ++ * and @link_mode_masks_nwords fields (any change to them overwritten ++ * by kernel), and rely only on kernel's internal ++ * %__ETHTOOL_LINK_MODE_MASK_NBITS and ++ * %ethtool_link_mode_mask_t. Drivers that implement ++ * %set_link_ksettings() should validate all fields other than @cmd ++ * and @link_mode_masks_nwords that are not described as read-only or ++ * deprecated, and must ignore all fields described as read-only. ++ */ ++struct ethtool_link_settings { ++ __u32 cmd; ++ __u32 speed; ++ __u8 duplex; ++ __u8 port; ++ __u8 phy_address; ++ __u8 autoneg; ++ __u8 mdio_support; ++ __u8 eth_tp_mdix; ++ __u8 eth_tp_mdix_ctrl; ++ __s8 link_mode_masks_nwords; ++ __u8 transceiver; ++ __u8 master_slave_cfg; ++ __u8 master_slave_state; ++ __u8 rate_matching; ++ __u32 reserved[7]; ++ __u32 link_mode_masks[]; ++ /* layout of link_mode_masks fields: ++ * __u32 map_supported[link_mode_masks_nwords]; ++ * __u32 map_advertising[link_mode_masks_nwords]; ++ * __u32 map_lp_advertising[link_mode_masks_nwords]; ++ */ ++}; + #endif /* _LINUX_ETHTOOL_H */ +diff --git a/include/linux/ethtool_netlink.h b/include/linux/ethtool_netlink.h +new file mode 100644 +index 000000000000..4cf91e54e246 +--- /dev/null ++++ b/include/linux/ethtool_netlink.h +@@ -0,0 +1,981 @@ ++/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ ++/* ++ * include/uapi/linux/ethtool_netlink.h - netlink interface for ethtool ++ * ++ * See Documentation/networking/ethtool-netlink.rst in kernel source tree for ++ * doucumentation of the interface. ++ */ ++ ++#ifndef _LINUX_ETHTOOL_NETLINK_H_ ++#define _LINUX_ETHTOOL_NETLINK_H_ ++ ++#include ++ ++/* message types - userspace to kernel */ ++enum { ++ ETHTOOL_MSG_USER_NONE, ++ ETHTOOL_MSG_STRSET_GET, ++ 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, ++ ++ /* add new constants above here */ ++ __ETHTOOL_MSG_USER_CNT, ++ ETHTOOL_MSG_USER_MAX = __ETHTOOL_MSG_USER_CNT - 1 ++}; ++ ++/* message types - kernel to userspace */ ++enum { ++ ETHTOOL_MSG_KERNEL_NONE, ++ ETHTOOL_MSG_STRSET_GET_REPLY, ++ 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, ++ ++ /* add new constants above here */ ++ __ETHTOOL_MSG_KERNEL_CNT, ++ ETHTOOL_MSG_KERNEL_MAX = __ETHTOOL_MSG_KERNEL_CNT - 1 ++}; ++ ++/* request header */ ++ ++/* use compact bitsets in reply */ ++#define ETHTOOL_FLAG_COMPACT_BITSETS (1 << 0) ++/* provide optional reply for SET or ACT requests */ ++#define ETHTOOL_FLAG_OMIT_REPLY (1 << 1) ++/* request statistics, if supported by the driver */ ++#define ETHTOOL_FLAG_STATS (1 << 2) ++ ++#define ETHTOOL_FLAG_ALL (ETHTOOL_FLAG_COMPACT_BITSETS | \ ++ ETHTOOL_FLAG_OMIT_REPLY | \ ++ ETHTOOL_FLAG_STATS) ++ ++enum { ++ ETHTOOL_A_HEADER_UNSPEC, ++ ETHTOOL_A_HEADER_DEV_INDEX, /* u32 */ ++ ETHTOOL_A_HEADER_DEV_NAME, /* string */ ++ ETHTOOL_A_HEADER_FLAGS, /* u32 - ETHTOOL_FLAG_* */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_HEADER_CNT, ++ ETHTOOL_A_HEADER_MAX = __ETHTOOL_A_HEADER_CNT - 1 ++}; ++ ++/* bit sets */ ++ ++enum { ++ ETHTOOL_A_BITSET_BIT_UNSPEC, ++ ETHTOOL_A_BITSET_BIT_INDEX, /* u32 */ ++ ETHTOOL_A_BITSET_BIT_NAME, /* string */ ++ ETHTOOL_A_BITSET_BIT_VALUE, /* flag */ ++ ++ /* add new constants above here */ ++ __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, /* nest - _A_BITSET_BIT_* */ ++ ++ /* add new constants above here */ ++ __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, /* flag */ ++ ETHTOOL_A_BITSET_SIZE, /* u32 */ ++ ETHTOOL_A_BITSET_BITS, /* nest - _A_BITSET_BITS_* */ ++ ETHTOOL_A_BITSET_VALUE, /* binary */ ++ ETHTOOL_A_BITSET_MASK, /* binary */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_BITSET_CNT, ++ ETHTOOL_A_BITSET_MAX = __ETHTOOL_A_BITSET_CNT - 1 ++}; ++ ++/* string sets */ ++ ++enum { ++ ETHTOOL_A_STRING_UNSPEC, ++ ETHTOOL_A_STRING_INDEX, /* u32 */ ++ ETHTOOL_A_STRING_VALUE, /* string */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_STRING_CNT, ++ ETHTOOL_A_STRING_MAX = __ETHTOOL_A_STRING_CNT - 1 ++}; ++ ++enum { ++ ETHTOOL_A_STRINGS_UNSPEC, ++ ETHTOOL_A_STRINGS_STRING, /* nest - _A_STRINGS_* */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_STRINGS_CNT, ++ ETHTOOL_A_STRINGS_MAX = __ETHTOOL_A_STRINGS_CNT - 1 ++}; ++ ++enum { ++ ETHTOOL_A_STRINGSET_UNSPEC, ++ ETHTOOL_A_STRINGSET_ID, /* u32 */ ++ ETHTOOL_A_STRINGSET_COUNT, /* u32 */ ++ ETHTOOL_A_STRINGSET_STRINGS, /* nest - _A_STRINGS_* */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_STRINGSET_CNT, ++ ETHTOOL_A_STRINGSET_MAX = __ETHTOOL_A_STRINGSET_CNT - 1 ++}; ++ ++enum { ++ ETHTOOL_A_STRINGSETS_UNSPEC, ++ ETHTOOL_A_STRINGSETS_STRINGSET, /* nest - _A_STRINGSET_* */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_STRINGSETS_CNT, ++ ETHTOOL_A_STRINGSETS_MAX = __ETHTOOL_A_STRINGSETS_CNT - 1 ++}; ++ ++/* STRSET */ ++ ++enum { ++ ETHTOOL_A_STRSET_UNSPEC, ++ ETHTOOL_A_STRSET_HEADER, /* nest - _A_HEADER_* */ ++ ETHTOOL_A_STRSET_STRINGSETS, /* nest - _A_STRINGSETS_* */ ++ ETHTOOL_A_STRSET_COUNTS_ONLY, /* flag */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_STRSET_CNT, ++ ETHTOOL_A_STRSET_MAX = __ETHTOOL_A_STRSET_CNT - 1 ++}; ++ ++/* LINKINFO */ ++ ++enum { ++ ETHTOOL_A_LINKINFO_UNSPEC, ++ ETHTOOL_A_LINKINFO_HEADER, /* nest - _A_HEADER_* */ ++ ETHTOOL_A_LINKINFO_PORT, /* u8 */ ++ ETHTOOL_A_LINKINFO_PHYADDR, /* u8 */ ++ ETHTOOL_A_LINKINFO_TP_MDIX, /* u8 */ ++ ETHTOOL_A_LINKINFO_TP_MDIX_CTRL, /* u8 */ ++ ETHTOOL_A_LINKINFO_TRANSCEIVER, /* u8 */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_LINKINFO_CNT, ++ ETHTOOL_A_LINKINFO_MAX = __ETHTOOL_A_LINKINFO_CNT - 1 ++}; ++ ++/* LINKMODES */ ++ ++enum { ++ ETHTOOL_A_LINKMODES_UNSPEC, ++ ETHTOOL_A_LINKMODES_HEADER, /* nest - _A_HEADER_* */ ++ ETHTOOL_A_LINKMODES_AUTONEG, /* u8 */ ++ ETHTOOL_A_LINKMODES_OURS, /* bitset */ ++ ETHTOOL_A_LINKMODES_PEER, /* bitset */ ++ ETHTOOL_A_LINKMODES_SPEED, /* u32 */ ++ ETHTOOL_A_LINKMODES_DUPLEX, /* u8 */ ++ ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG, /* u8 */ ++ ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE, /* u8 */ ++ ETHTOOL_A_LINKMODES_LANES, /* u32 */ ++ ETHTOOL_A_LINKMODES_RATE_MATCHING, /* u8 */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_LINKMODES_CNT, ++ ETHTOOL_A_LINKMODES_MAX = __ETHTOOL_A_LINKMODES_CNT - 1 ++}; ++ ++/* LINKSTATE */ ++ ++enum { ++ ETHTOOL_A_LINKSTATE_UNSPEC, ++ ETHTOOL_A_LINKSTATE_HEADER, /* nest - _A_HEADER_* */ ++ ETHTOOL_A_LINKSTATE_LINK, /* u8 */ ++ ETHTOOL_A_LINKSTATE_SQI, /* u32 */ ++ ETHTOOL_A_LINKSTATE_SQI_MAX, /* u32 */ ++ ETHTOOL_A_LINKSTATE_EXT_STATE, /* u8 */ ++ ETHTOOL_A_LINKSTATE_EXT_SUBSTATE, /* u8 */ ++ ETHTOOL_A_LINKSTATE_EXT_DOWN_CNT, /* u32 */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_LINKSTATE_CNT, ++ ETHTOOL_A_LINKSTATE_MAX = __ETHTOOL_A_LINKSTATE_CNT - 1 ++}; ++ ++/* DEBUG */ ++ ++enum { ++ ETHTOOL_A_DEBUG_UNSPEC, ++ ETHTOOL_A_DEBUG_HEADER, /* nest - _A_HEADER_* */ ++ ETHTOOL_A_DEBUG_MSGMASK, /* bitset */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_DEBUG_CNT, ++ ETHTOOL_A_DEBUG_MAX = __ETHTOOL_A_DEBUG_CNT - 1 ++}; ++ ++/* WOL */ ++ ++enum { ++ ETHTOOL_A_WOL_UNSPEC, ++ ETHTOOL_A_WOL_HEADER, /* nest - _A_HEADER_* */ ++ ETHTOOL_A_WOL_MODES, /* bitset */ ++ ETHTOOL_A_WOL_SOPASS, /* binary */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_WOL_CNT, ++ ETHTOOL_A_WOL_MAX = __ETHTOOL_A_WOL_CNT - 1 ++}; ++ ++/* FEATURES */ ++ ++enum { ++ ETHTOOL_A_FEATURES_UNSPEC, ++ ETHTOOL_A_FEATURES_HEADER, /* nest - _A_HEADER_* */ ++ ETHTOOL_A_FEATURES_HW, /* bitset */ ++ ETHTOOL_A_FEATURES_WANTED, /* bitset */ ++ ETHTOOL_A_FEATURES_ACTIVE, /* bitset */ ++ ETHTOOL_A_FEATURES_NOCHANGE, /* bitset */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_FEATURES_CNT, ++ ETHTOOL_A_FEATURES_MAX = __ETHTOOL_A_FEATURES_CNT - 1 ++}; ++ ++/* PRIVFLAGS */ ++ ++enum { ++ ETHTOOL_A_PRIVFLAGS_UNSPEC, ++ ETHTOOL_A_PRIVFLAGS_HEADER, /* nest - _A_HEADER_* */ ++ ETHTOOL_A_PRIVFLAGS_FLAGS, /* bitset */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_PRIVFLAGS_CNT, ++ ETHTOOL_A_PRIVFLAGS_MAX = __ETHTOOL_A_PRIVFLAGS_CNT - 1 ++}; ++ ++/* RINGS */ ++ ++enum { ++ ETHTOOL_TCP_DATA_SPLIT_UNKNOWN = 0, ++ ETHTOOL_TCP_DATA_SPLIT_DISABLED, ++ ETHTOOL_TCP_DATA_SPLIT_ENABLED, ++}; ++ ++enum { ++ ETHTOOL_A_RINGS_UNSPEC, ++ ETHTOOL_A_RINGS_HEADER, /* nest - _A_HEADER_* */ ++ ETHTOOL_A_RINGS_RX_MAX, /* u32 */ ++ ETHTOOL_A_RINGS_RX_MINI_MAX, /* u32 */ ++ ETHTOOL_A_RINGS_RX_JUMBO_MAX, /* u32 */ ++ ETHTOOL_A_RINGS_TX_MAX, /* u32 */ ++ ETHTOOL_A_RINGS_RX, /* u32 */ ++ ETHTOOL_A_RINGS_RX_MINI, /* u32 */ ++ ETHTOOL_A_RINGS_RX_JUMBO, /* u32 */ ++ ETHTOOL_A_RINGS_TX, /* u32 */ ++ ETHTOOL_A_RINGS_RX_BUF_LEN, /* u32 */ ++ ETHTOOL_A_RINGS_TCP_DATA_SPLIT, /* u8 */ ++ ETHTOOL_A_RINGS_CQE_SIZE, /* u32 */ ++ ETHTOOL_A_RINGS_TX_PUSH, /* u8 */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_RINGS_CNT, ++ ETHTOOL_A_RINGS_MAX = (__ETHTOOL_A_RINGS_CNT - 1) ++}; ++ ++/* CHANNELS */ ++ ++enum { ++ ETHTOOL_A_CHANNELS_UNSPEC, ++ ETHTOOL_A_CHANNELS_HEADER, /* nest - _A_HEADER_* */ ++ ETHTOOL_A_CHANNELS_RX_MAX, /* u32 */ ++ ETHTOOL_A_CHANNELS_TX_MAX, /* u32 */ ++ ETHTOOL_A_CHANNELS_OTHER_MAX, /* u32 */ ++ ETHTOOL_A_CHANNELS_COMBINED_MAX, /* u32 */ ++ ETHTOOL_A_CHANNELS_RX_COUNT, /* u32 */ ++ ETHTOOL_A_CHANNELS_TX_COUNT, /* u32 */ ++ ETHTOOL_A_CHANNELS_OTHER_COUNT, /* u32 */ ++ ETHTOOL_A_CHANNELS_COMBINED_COUNT, /* u32 */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_CHANNELS_CNT, ++ ETHTOOL_A_CHANNELS_MAX = (__ETHTOOL_A_CHANNELS_CNT - 1) ++}; ++ ++/* COALESCE */ ++ ++enum { ++ ETHTOOL_A_COALESCE_UNSPEC, ++ ETHTOOL_A_COALESCE_HEADER, /* nest - _A_HEADER_* */ ++ ETHTOOL_A_COALESCE_RX_USECS, /* u32 */ ++ ETHTOOL_A_COALESCE_RX_MAX_FRAMES, /* u32 */ ++ ETHTOOL_A_COALESCE_RX_USECS_IRQ, /* u32 */ ++ ETHTOOL_A_COALESCE_RX_MAX_FRAMES_IRQ, /* u32 */ ++ ETHTOOL_A_COALESCE_TX_USECS, /* u32 */ ++ ETHTOOL_A_COALESCE_TX_MAX_FRAMES, /* u32 */ ++ ETHTOOL_A_COALESCE_TX_USECS_IRQ, /* u32 */ ++ ETHTOOL_A_COALESCE_TX_MAX_FRAMES_IRQ, /* u32 */ ++ ETHTOOL_A_COALESCE_STATS_BLOCK_USECS, /* u32 */ ++ ETHTOOL_A_COALESCE_USE_ADAPTIVE_RX, /* u8 */ ++ ETHTOOL_A_COALESCE_USE_ADAPTIVE_TX, /* u8 */ ++ ETHTOOL_A_COALESCE_PKT_RATE_LOW, /* u32 */ ++ ETHTOOL_A_COALESCE_RX_USECS_LOW, /* u32 */ ++ ETHTOOL_A_COALESCE_RX_MAX_FRAMES_LOW, /* u32 */ ++ ETHTOOL_A_COALESCE_TX_USECS_LOW, /* u32 */ ++ ETHTOOL_A_COALESCE_TX_MAX_FRAMES_LOW, /* u32 */ ++ ETHTOOL_A_COALESCE_PKT_RATE_HIGH, /* u32 */ ++ ETHTOOL_A_COALESCE_RX_USECS_HIGH, /* u32 */ ++ ETHTOOL_A_COALESCE_RX_MAX_FRAMES_HIGH, /* u32 */ ++ ETHTOOL_A_COALESCE_TX_USECS_HIGH, /* u32 */ ++ ETHTOOL_A_COALESCE_TX_MAX_FRAMES_HIGH, /* u32 */ ++ ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL, /* u32 */ ++ ETHTOOL_A_COALESCE_USE_CQE_MODE_TX, /* u8 */ ++ ETHTOOL_A_COALESCE_USE_CQE_MODE_RX, /* u8 */ ++ ETHTOOL_A_COALESCE_TX_AGGR_MAX_BYTES, /* u32 */ ++ ETHTOOL_A_COALESCE_TX_AGGR_MAX_FRAMES, /* u32 */ ++ ETHTOOL_A_COALESCE_TX_AGGR_TIME_USECS, /* u32 */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_COALESCE_CNT, ++ ETHTOOL_A_COALESCE_MAX = (__ETHTOOL_A_COALESCE_CNT - 1) ++}; ++ ++/* PAUSE */ ++ ++enum { ++ ETHTOOL_A_PAUSE_UNSPEC, ++ ETHTOOL_A_PAUSE_HEADER, /* nest - _A_HEADER_* */ ++ ETHTOOL_A_PAUSE_AUTONEG, /* u8 */ ++ ETHTOOL_A_PAUSE_RX, /* u8 */ ++ ETHTOOL_A_PAUSE_TX, /* u8 */ ++ ETHTOOL_A_PAUSE_STATS, /* nest - _PAUSE_STAT_* */ ++ ETHTOOL_A_PAUSE_STATS_SRC, /* u32 */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_PAUSE_CNT, ++ ETHTOOL_A_PAUSE_MAX = (__ETHTOOL_A_PAUSE_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, ++ ++ /* add new constants above here ++ * adjust ETHTOOL_PAUSE_STAT_CNT if adding non-stats! ++ */ ++ __ETHTOOL_A_PAUSE_STAT_CNT, ++ ETHTOOL_A_PAUSE_STAT_MAX = (__ETHTOOL_A_PAUSE_STAT_CNT - 1) ++}; ++ ++/* EEE */ ++ ++enum { ++ ETHTOOL_A_EEE_UNSPEC, ++ ETHTOOL_A_EEE_HEADER, /* nest - _A_HEADER_* */ ++ ETHTOOL_A_EEE_MODES_OURS, /* bitset */ ++ ETHTOOL_A_EEE_MODES_PEER, /* bitset */ ++ ETHTOOL_A_EEE_ACTIVE, /* u8 */ ++ ETHTOOL_A_EEE_ENABLED, /* u8 */ ++ ETHTOOL_A_EEE_TX_LPI_ENABLED, /* u8 */ ++ ETHTOOL_A_EEE_TX_LPI_TIMER, /* u32 */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_EEE_CNT, ++ ETHTOOL_A_EEE_MAX = (__ETHTOOL_A_EEE_CNT - 1) ++}; ++ ++/* TSINFO */ ++ ++enum { ++ ETHTOOL_A_TSINFO_UNSPEC, ++ ETHTOOL_A_TSINFO_HEADER, /* nest - _A_HEADER_* */ ++ ETHTOOL_A_TSINFO_TIMESTAMPING, /* bitset */ ++ ETHTOOL_A_TSINFO_TX_TYPES, /* bitset */ ++ ETHTOOL_A_TSINFO_RX_FILTERS, /* bitset */ ++ ETHTOOL_A_TSINFO_PHC_INDEX, /* u32 */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_TSINFO_CNT, ++ ETHTOOL_A_TSINFO_MAX = (__ETHTOOL_A_TSINFO_CNT - 1) ++}; ++ ++/* PHC VCLOCKS */ ++ ++enum { ++ ETHTOOL_A_PHC_VCLOCKS_UNSPEC, ++ ETHTOOL_A_PHC_VCLOCKS_HEADER, /* nest - _A_HEADER_* */ ++ ETHTOOL_A_PHC_VCLOCKS_NUM, /* u32 */ ++ ETHTOOL_A_PHC_VCLOCKS_INDEX, /* array, s32 */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_PHC_VCLOCKS_CNT, ++ ETHTOOL_A_PHC_VCLOCKS_MAX = (__ETHTOOL_A_PHC_VCLOCKS_CNT - 1) ++}; ++ ++/* CABLE TEST */ ++ ++enum { ++ ETHTOOL_A_CABLE_TEST_UNSPEC, ++ ETHTOOL_A_CABLE_TEST_HEADER, /* nest - _A_HEADER_* */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_CABLE_TEST_CNT, ++ ETHTOOL_A_CABLE_TEST_MAX = __ETHTOOL_A_CABLE_TEST_CNT - 1 ++}; ++ ++/* CABLE TEST NOTIFY */ ++enum { ++ ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC, ++ ETHTOOL_A_CABLE_RESULT_CODE_OK, ++ ETHTOOL_A_CABLE_RESULT_CODE_OPEN, ++ ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT, ++ ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT, ++}; ++ ++enum { ++ ETHTOOL_A_CABLE_PAIR_A, ++ ETHTOOL_A_CABLE_PAIR_B, ++ ETHTOOL_A_CABLE_PAIR_C, ++ ETHTOOL_A_CABLE_PAIR_D, ++}; ++ ++enum { ++ ETHTOOL_A_CABLE_RESULT_UNSPEC, ++ ETHTOOL_A_CABLE_RESULT_PAIR, /* u8 ETHTOOL_A_CABLE_PAIR_ */ ++ ETHTOOL_A_CABLE_RESULT_CODE, /* u8 ETHTOOL_A_CABLE_RESULT_CODE_ */ ++ ++ __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, /* u8 ETHTOOL_A_CABLE_PAIR_ */ ++ ETHTOOL_A_CABLE_FAULT_LENGTH_CM, /* u32 */ ++ ++ __ETHTOOL_A_CABLE_FAULT_LENGTH_CNT, ++ ETHTOOL_A_CABLE_FAULT_LENGTH_MAX = (__ETHTOOL_A_CABLE_FAULT_LENGTH_CNT - 1) ++}; ++ ++enum { ++ ETHTOOL_A_CABLE_TEST_NTF_STATUS_UNSPEC, ++ ETHTOOL_A_CABLE_TEST_NTF_STATUS_STARTED, ++ ETHTOOL_A_CABLE_TEST_NTF_STATUS_COMPLETED ++}; ++ ++enum { ++ ETHTOOL_A_CABLE_NEST_UNSPEC, ++ ETHTOOL_A_CABLE_NEST_RESULT, /* nest - ETHTOOL_A_CABLE_RESULT_ */ ++ ETHTOOL_A_CABLE_NEST_FAULT_LENGTH, /* nest - ETHTOOL_A_CABLE_FAULT_LENGTH_ */ ++ __ETHTOOL_A_CABLE_NEST_CNT, ++ ETHTOOL_A_CABLE_NEST_MAX = (__ETHTOOL_A_CABLE_NEST_CNT - 1) ++}; ++ ++enum { ++ ETHTOOL_A_CABLE_TEST_NTF_UNSPEC, ++ ETHTOOL_A_CABLE_TEST_NTF_HEADER, /* nest - ETHTOOL_A_HEADER_* */ ++ ETHTOOL_A_CABLE_TEST_NTF_STATUS, /* u8 - _STARTED/_COMPLETE */ ++ ETHTOOL_A_CABLE_TEST_NTF_NEST, /* nest - of results: */ ++ ++ __ETHTOOL_A_CABLE_TEST_NTF_CNT, ++ ETHTOOL_A_CABLE_TEST_NTF_MAX = (__ETHTOOL_A_CABLE_TEST_NTF_CNT - 1) ++}; ++ ++/* CABLE TEST TDR */ ++ ++enum { ++ ETHTOOL_A_CABLE_TEST_TDR_CFG_UNSPEC, ++ ETHTOOL_A_CABLE_TEST_TDR_CFG_FIRST, /* u32 */ ++ ETHTOOL_A_CABLE_TEST_TDR_CFG_LAST, /* u32 */ ++ ETHTOOL_A_CABLE_TEST_TDR_CFG_STEP, /* u32 */ ++ ETHTOOL_A_CABLE_TEST_TDR_CFG_PAIR, /* u8 */ ++ ++ /* add new constants above here */ ++ __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_UNSPEC, ++ ETHTOOL_A_CABLE_TEST_TDR_HEADER, /* nest - _A_HEADER_* */ ++ ETHTOOL_A_CABLE_TEST_TDR_CFG, /* nest - *_TDR_CFG_* */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_CABLE_TEST_TDR_CNT, ++ ETHTOOL_A_CABLE_TEST_TDR_MAX = __ETHTOOL_A_CABLE_TEST_TDR_CNT - 1 ++}; ++ ++/* CABLE TEST TDR NOTIFY */ ++ ++enum { ++ ETHTOOL_A_CABLE_AMPLITUDE_UNSPEC, ++ ETHTOOL_A_CABLE_AMPLITUDE_PAIR, /* u8 */ ++ ETHTOOL_A_CABLE_AMPLITUDE_mV, /* s16 */ ++ ++ __ETHTOOL_A_CABLE_AMPLITUDE_CNT, ++ ETHTOOL_A_CABLE_AMPLITUDE_MAX = (__ETHTOOL_A_CABLE_AMPLITUDE_CNT - 1) ++}; ++ ++enum { ++ ETHTOOL_A_CABLE_PULSE_UNSPEC, ++ ETHTOOL_A_CABLE_PULSE_mV, /* s16 */ ++ ++ __ETHTOOL_A_CABLE_PULSE_CNT, ++ ETHTOOL_A_CABLE_PULSE_MAX = (__ETHTOOL_A_CABLE_PULSE_CNT - 1) ++}; ++ ++enum { ++ ETHTOOL_A_CABLE_STEP_UNSPEC, ++ ETHTOOL_A_CABLE_STEP_FIRST_DISTANCE, /* u32 */ ++ ETHTOOL_A_CABLE_STEP_LAST_DISTANCE, /* u32 */ ++ ETHTOOL_A_CABLE_STEP_STEP_DISTANCE, /* u32 */ ++ ++ __ETHTOOL_A_CABLE_STEP_CNT, ++ ETHTOOL_A_CABLE_STEP_MAX = (__ETHTOOL_A_CABLE_STEP_CNT - 1) ++}; ++ ++enum { ++ ETHTOOL_A_CABLE_TDR_NEST_UNSPEC, ++ ETHTOOL_A_CABLE_TDR_NEST_STEP, /* nest - ETHTTOOL_A_CABLE_STEP */ ++ ETHTOOL_A_CABLE_TDR_NEST_AMPLITUDE, /* nest - ETHTOOL_A_CABLE_AMPLITUDE */ ++ ETHTOOL_A_CABLE_TDR_NEST_PULSE, /* nest - ETHTOOL_A_CABLE_PULSE */ ++ ++ __ETHTOOL_A_CABLE_TDR_NEST_CNT, ++ ETHTOOL_A_CABLE_TDR_NEST_MAX = (__ETHTOOL_A_CABLE_TDR_NEST_CNT - 1) ++}; ++ ++enum { ++ ETHTOOL_A_CABLE_TEST_TDR_NTF_UNSPEC, ++ ETHTOOL_A_CABLE_TEST_TDR_NTF_HEADER, /* nest - ETHTOOL_A_HEADER_* */ ++ ETHTOOL_A_CABLE_TEST_TDR_NTF_STATUS, /* u8 - _STARTED/_COMPLETE */ ++ ETHTOOL_A_CABLE_TEST_TDR_NTF_NEST, /* nest - of results: */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_CABLE_TEST_TDR_NTF_CNT, ++ ETHTOOL_A_CABLE_TEST_TDR_NTF_MAX = __ETHTOOL_A_CABLE_TEST_TDR_NTF_CNT - 1 ++}; ++ ++/* TUNNEL INFO */ ++ ++enum { ++ ETHTOOL_UDP_TUNNEL_TYPE_VXLAN, ++ ETHTOOL_UDP_TUNNEL_TYPE_GENEVE, ++ ETHTOOL_UDP_TUNNEL_TYPE_VXLAN_GPE, ++ ++ __ETHTOOL_UDP_TUNNEL_TYPE_CNT ++}; ++ ++enum { ++ ETHTOOL_A_TUNNEL_UDP_ENTRY_UNSPEC, ++ ++ ETHTOOL_A_TUNNEL_UDP_ENTRY_PORT, /* be16 */ ++ ETHTOOL_A_TUNNEL_UDP_ENTRY_TYPE, /* u32 */ ++ ++ /* add new constants above here */ ++ __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, /* u32 */ ++ ETHTOOL_A_TUNNEL_UDP_TABLE_TYPES, /* bitset */ ++ ETHTOOL_A_TUNNEL_UDP_TABLE_ENTRY, /* nest - _UDP_ENTRY_* */ ++ ++ /* add new constants above here */ ++ __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, /* nest - _UDP_TABLE_* */ ++ ++ /* add new constants above here */ ++ __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, /* nest - _A_HEADER_* */ ++ ++ ETHTOOL_A_TUNNEL_INFO_UDP_PORTS, /* nest - _UDP_TABLE */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_TUNNEL_INFO_CNT, ++ ETHTOOL_A_TUNNEL_INFO_MAX = (__ETHTOOL_A_TUNNEL_INFO_CNT - 1) ++}; ++ ++/* FEC */ ++ ++enum { ++ ETHTOOL_A_FEC_UNSPEC, ++ ETHTOOL_A_FEC_HEADER, /* nest - _A_HEADER_* */ ++ ETHTOOL_A_FEC_MODES, /* bitset */ ++ ETHTOOL_A_FEC_AUTO, /* u8 */ ++ ETHTOOL_A_FEC_ACTIVE, /* u32 */ ++ ETHTOOL_A_FEC_STATS, /* nest - _A_FEC_STAT */ ++ ++ __ETHTOOL_A_FEC_CNT, ++ ETHTOOL_A_FEC_MAX = (__ETHTOOL_A_FEC_CNT - 1) ++}; ++ ++enum { ++ ETHTOOL_A_FEC_STAT_UNSPEC, ++ ETHTOOL_A_FEC_STAT_PAD, ++ ++ ETHTOOL_A_FEC_STAT_CORRECTED, /* array, u64 */ ++ ETHTOOL_A_FEC_STAT_UNCORR, /* array, u64 */ ++ ETHTOOL_A_FEC_STAT_CORR_BITS, /* array, u64 */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_FEC_STAT_CNT, ++ ETHTOOL_A_FEC_STAT_MAX = (__ETHTOOL_A_FEC_STAT_CNT - 1) ++}; ++ ++/* MODULE EEPROM */ ++ ++enum { ++ ETHTOOL_A_MODULE_EEPROM_UNSPEC, ++ ETHTOOL_A_MODULE_EEPROM_HEADER, /* nest - _A_HEADER_* */ ++ ++ ETHTOOL_A_MODULE_EEPROM_OFFSET, /* u32 */ ++ ETHTOOL_A_MODULE_EEPROM_LENGTH, /* u32 */ ++ ETHTOOL_A_MODULE_EEPROM_PAGE, /* u8 */ ++ ETHTOOL_A_MODULE_EEPROM_BANK, /* u8 */ ++ ETHTOOL_A_MODULE_EEPROM_I2C_ADDRESS, /* u8 */ ++ ETHTOOL_A_MODULE_EEPROM_DATA, /* binary */ ++ ++ __ETHTOOL_A_MODULE_EEPROM_CNT, ++ ETHTOOL_A_MODULE_EEPROM_MAX = (__ETHTOOL_A_MODULE_EEPROM_CNT - 1) ++}; ++ ++/* STATS */ ++ ++enum { ++ ETHTOOL_A_STATS_UNSPEC, ++ ETHTOOL_A_STATS_PAD, ++ ETHTOOL_A_STATS_HEADER, /* nest - _A_HEADER_* */ ++ ETHTOOL_A_STATS_GROUPS, /* bitset */ ++ ++ ETHTOOL_A_STATS_GRP, /* nest - _A_STATS_GRP_* */ ++ ++ ETHTOOL_A_STATS_SRC, /* u32 */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_STATS_CNT, ++ ETHTOOL_A_STATS_MAX = (__ETHTOOL_A_STATS_CNT - 1) ++}; ++ ++enum { ++ ETHTOOL_STATS_ETH_PHY, ++ ETHTOOL_STATS_ETH_MAC, ++ ETHTOOL_STATS_ETH_CTRL, ++ ETHTOOL_STATS_RMON, ++ ++ /* add new constants above here */ ++ __ETHTOOL_STATS_CNT ++}; ++ ++enum { ++ ETHTOOL_A_STATS_GRP_UNSPEC, ++ ETHTOOL_A_STATS_GRP_PAD, ++ ++ ETHTOOL_A_STATS_GRP_ID, /* u32 */ ++ ETHTOOL_A_STATS_GRP_SS_ID, /* u32 */ ++ ++ ETHTOOL_A_STATS_GRP_STAT, /* nest */ ++ ++ ETHTOOL_A_STATS_GRP_HIST_RX, /* nest */ ++ ETHTOOL_A_STATS_GRP_HIST_TX, /* nest */ ++ ++ ETHTOOL_A_STATS_GRP_HIST_BKT_LOW, /* u32 */ ++ ETHTOOL_A_STATS_GRP_HIST_BKT_HI, /* u32 */ ++ ETHTOOL_A_STATS_GRP_HIST_VAL, /* u64 */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_STATS_GRP_CNT, ++ ETHTOOL_A_STATS_GRP_MAX = (__ETHTOOL_A_STATS_CNT - 1) ++}; ++ ++enum { ++ /* 30.3.2.1.5 aSymbolErrorDuringCarrier */ ++ ETHTOOL_A_STATS_ETH_PHY_5_SYM_ERR, ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_STATS_ETH_PHY_CNT, ++ ETHTOOL_A_STATS_ETH_PHY_MAX = (__ETHTOOL_A_STATS_ETH_PHY_CNT - 1) ++}; ++ ++enum { ++ /* 30.3.1.1.2 aFramesTransmittedOK */ ++ ETHTOOL_A_STATS_ETH_MAC_2_TX_PKT, ++ /* 30.3.1.1.3 aSingleCollisionFrames */ ++ ETHTOOL_A_STATS_ETH_MAC_3_SINGLE_COL, ++ /* 30.3.1.1.4 aMultipleCollisionFrames */ ++ ETHTOOL_A_STATS_ETH_MAC_4_MULTI_COL, ++ /* 30.3.1.1.5 aFramesReceivedOK */ ++ ETHTOOL_A_STATS_ETH_MAC_5_RX_PKT, ++ /* 30.3.1.1.6 aFrameCheckSequenceErrors */ ++ ETHTOOL_A_STATS_ETH_MAC_6_FCS_ERR, ++ /* 30.3.1.1.7 aAlignmentErrors */ ++ ETHTOOL_A_STATS_ETH_MAC_7_ALIGN_ERR, ++ /* 30.3.1.1.8 aOctetsTransmittedOK */ ++ ETHTOOL_A_STATS_ETH_MAC_8_TX_BYTES, ++ /* 30.3.1.1.9 aFramesWithDeferredXmissions */ ++ ETHTOOL_A_STATS_ETH_MAC_9_TX_DEFER, ++ /* 30.3.1.1.10 aLateCollisions */ ++ ETHTOOL_A_STATS_ETH_MAC_10_LATE_COL, ++ /* 30.3.1.1.11 aFramesAbortedDueToXSColls */ ++ ETHTOOL_A_STATS_ETH_MAC_11_XS_COL, ++ /* 30.3.1.1.12 aFramesLostDueToIntMACXmitError */ ++ ETHTOOL_A_STATS_ETH_MAC_12_TX_INT_ERR, ++ /* 30.3.1.1.13 aCarrierSenseErrors */ ++ ETHTOOL_A_STATS_ETH_MAC_13_CS_ERR, ++ /* 30.3.1.1.14 aOctetsReceivedOK */ ++ ETHTOOL_A_STATS_ETH_MAC_14_RX_BYTES, ++ /* 30.3.1.1.15 aFramesLostDueToIntMACRcvError */ ++ ETHTOOL_A_STATS_ETH_MAC_15_RX_INT_ERR, ++ ++ /* 30.3.1.1.18 aMulticastFramesXmittedOK */ ++ ETHTOOL_A_STATS_ETH_MAC_18_TX_MCAST, ++ /* 30.3.1.1.19 aBroadcastFramesXmittedOK */ ++ ETHTOOL_A_STATS_ETH_MAC_19_TX_BCAST, ++ /* 30.3.1.1.20 aFramesWithExcessiveDeferral */ ++ ETHTOOL_A_STATS_ETH_MAC_20_XS_DEFER, ++ /* 30.3.1.1.21 aMulticastFramesReceivedOK */ ++ ETHTOOL_A_STATS_ETH_MAC_21_RX_MCAST, ++ /* 30.3.1.1.22 aBroadcastFramesReceivedOK */ ++ ETHTOOL_A_STATS_ETH_MAC_22_RX_BCAST, ++ /* 30.3.1.1.23 aInRangeLengthErrors */ ++ ETHTOOL_A_STATS_ETH_MAC_23_IR_LEN_ERR, ++ /* 30.3.1.1.24 aOutOfRangeLengthField */ ++ ETHTOOL_A_STATS_ETH_MAC_24_OOR_LEN, ++ /* 30.3.1.1.25 aFrameTooLongErrors */ ++ ETHTOOL_A_STATS_ETH_MAC_25_TOO_LONG_ERR, ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_STATS_ETH_MAC_CNT, ++ ETHTOOL_A_STATS_ETH_MAC_MAX = (__ETHTOOL_A_STATS_ETH_MAC_CNT - 1) ++}; ++ ++enum { ++ /* 30.3.3.3 aMACControlFramesTransmitted */ ++ ETHTOOL_A_STATS_ETH_CTRL_3_TX, ++ /* 30.3.3.4 aMACControlFramesReceived */ ++ ETHTOOL_A_STATS_ETH_CTRL_4_RX, ++ /* 30.3.3.5 aUnsupportedOpcodesReceived */ ++ ETHTOOL_A_STATS_ETH_CTRL_5_RX_UNSUP, ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_STATS_ETH_CTRL_CNT, ++ ETHTOOL_A_STATS_ETH_CTRL_MAX = (__ETHTOOL_A_STATS_ETH_CTRL_CNT - 1) ++}; ++ ++enum { ++ /* etherStatsUndersizePkts */ ++ ETHTOOL_A_STATS_RMON_UNDERSIZE, ++ /* etherStatsOversizePkts */ ++ ETHTOOL_A_STATS_RMON_OVERSIZE, ++ /* etherStatsFragments */ ++ ETHTOOL_A_STATS_RMON_FRAG, ++ /* etherStatsJabbers */ ++ ETHTOOL_A_STATS_RMON_JABBER, ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_STATS_RMON_CNT, ++ ETHTOOL_A_STATS_RMON_MAX = (__ETHTOOL_A_STATS_RMON_CNT - 1) ++}; ++ ++/* MODULE */ ++ ++enum { ++ ETHTOOL_A_MODULE_UNSPEC, ++ ETHTOOL_A_MODULE_HEADER, /* nest - _A_HEADER_* */ ++ ETHTOOL_A_MODULE_POWER_MODE_POLICY, /* u8 */ ++ ETHTOOL_A_MODULE_POWER_MODE, /* u8 */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_MODULE_CNT, ++ ETHTOOL_A_MODULE_MAX = (__ETHTOOL_A_MODULE_CNT - 1) ++}; ++ ++/* Power Sourcing Equipment */ ++enum { ++ ETHTOOL_A_PSE_UNSPEC, ++ ETHTOOL_A_PSE_HEADER, /* nest - _A_HEADER_* */ ++ ETHTOOL_A_PODL_PSE_ADMIN_STATE, /* u32 */ ++ ETHTOOL_A_PODL_PSE_ADMIN_CONTROL, /* u32 */ ++ ETHTOOL_A_PODL_PSE_PW_D_STATUS, /* u32 */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_PSE_CNT, ++ ETHTOOL_A_PSE_MAX = (__ETHTOOL_A_PSE_CNT - 1) ++}; ++ ++enum { ++ ETHTOOL_A_RSS_UNSPEC, ++ ETHTOOL_A_RSS_HEADER, ++ ETHTOOL_A_RSS_CONTEXT, /* u32 */ ++ ETHTOOL_A_RSS_HFUNC, /* u32 */ ++ ETHTOOL_A_RSS_INDIR, /* binary */ ++ ETHTOOL_A_RSS_HKEY, /* binary */ ++ ++ __ETHTOOL_A_RSS_CNT, ++ ETHTOOL_A_RSS_MAX = (__ETHTOOL_A_RSS_CNT - 1), ++}; ++ ++/* PLCA */ ++ ++enum { ++ ETHTOOL_A_PLCA_UNSPEC, ++ ETHTOOL_A_PLCA_HEADER, /* nest - _A_HEADER_* */ ++ ETHTOOL_A_PLCA_VERSION, /* u16 */ ++ ETHTOOL_A_PLCA_ENABLED, /* u8 */ ++ ETHTOOL_A_PLCA_STATUS, /* u8 */ ++ ETHTOOL_A_PLCA_NODE_CNT, /* u32 */ ++ ETHTOOL_A_PLCA_NODE_ID, /* u32 */ ++ ETHTOOL_A_PLCA_TO_TMR, /* u32 */ ++ ETHTOOL_A_PLCA_BURST_CNT, /* u32 */ ++ ETHTOOL_A_PLCA_BURST_TMR, /* u32 */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_PLCA_CNT, ++ ETHTOOL_A_PLCA_MAX = (__ETHTOOL_A_PLCA_CNT - 1) ++}; ++ ++/* MAC Merge (802.3) */ ++ ++enum { ++ ETHTOOL_A_MM_STAT_UNSPEC, ++ ETHTOOL_A_MM_STAT_PAD, ++ ++ /* aMACMergeFrameAssErrorCount */ ++ ETHTOOL_A_MM_STAT_REASSEMBLY_ERRORS, /* u64 */ ++ /* aMACMergeFrameSmdErrorCount */ ++ ETHTOOL_A_MM_STAT_SMD_ERRORS, /* u64 */ ++ /* aMACMergeFrameAssOkCount */ ++ ETHTOOL_A_MM_STAT_REASSEMBLY_OK, /* u64 */ ++ /* aMACMergeFragCountRx */ ++ ETHTOOL_A_MM_STAT_RX_FRAG_COUNT, /* u64 */ ++ /* aMACMergeFragCountTx */ ++ ETHTOOL_A_MM_STAT_TX_FRAG_COUNT, /* u64 */ ++ /* aMACMergeHoldCount */ ++ ETHTOOL_A_MM_STAT_HOLD_COUNT, /* u64 */ ++ ++ /* add new constants above here */ ++ __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, /* nest - _A_HEADER_* */ ++ ETHTOOL_A_MM_PMAC_ENABLED, /* u8 */ ++ ETHTOOL_A_MM_TX_ENABLED, /* u8 */ ++ ETHTOOL_A_MM_TX_ACTIVE, /* u8 */ ++ ETHTOOL_A_MM_TX_MIN_FRAG_SIZE, /* u32 */ ++ ETHTOOL_A_MM_RX_MIN_FRAG_SIZE, /* u32 */ ++ ETHTOOL_A_MM_VERIFY_ENABLED, /* u8 */ ++ ETHTOOL_A_MM_VERIFY_STATUS, /* u8 */ ++ ETHTOOL_A_MM_VERIFY_TIME, /* u32 */ ++ ETHTOOL_A_MM_MAX_VERIFY_TIME, /* u32 */ ++ ETHTOOL_A_MM_STATS, /* nest - _A_MM_STAT_* */ ++ ++ /* add new constants above here */ ++ __ETHTOOL_A_MM_CNT, ++ ETHTOOL_A_MM_MAX = (__ETHTOOL_A_MM_CNT - 1) ++}; ++ ++/* generic netlink info */ ++#define ETHTOOL_GENL_NAME "ethtool" ++#define ETHTOOL_GENL_VERSION 1 ++ ++#define ETHTOOL_MCGRP_MONITOR_NAME "monitor" ++ ++#endif /* _LINUX_ETHTOOL_NETLINK_H_ */ +diff --git a/include/linux/netlink.h b/include/linux/netlink.h +index 77e93b57d553..47bac97ec76b 100644 +--- a/include/linux/netlink.h ++++ b/include/linux/netlink.h +@@ -1,14 +1,16 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ + #ifndef __LINUX_NETLINK_H + #define __LINUX_NETLINK_H + +-#include /* for sa_family_t */ ++#include ++#include /* for __kernel_sa_family_t */ + #include + + #define NETLINK_ROUTE 0 /* Routing/device hook */ + #define NETLINK_UNUSED 1 /* Unused number */ + #define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */ +-#define NETLINK_FIREWALL 3 /* Firewalling hook */ +-#define NETLINK_INET_DIAG 4 /* INET socket monitoring */ ++#define NETLINK_FIREWALL 3 /* Unused number, formerly ip_queue */ ++#define NETLINK_SOCK_DIAG 4 /* socket monitoring */ + #define NETLINK_NFLOG 5 /* netfilter/iptables ULOG */ + #define NETLINK_XFRM 6 /* ipsec */ + #define NETLINK_SELINUX 7 /* SELinux event notifications */ +@@ -18,36 +20,51 @@ + #define NETLINK_CONNECTOR 11 + #define NETLINK_NETFILTER 12 /* netfilter subsystem */ + #define NETLINK_IP6_FW 13 +-#define NETLINK_DNRTMSG 14 /* DECnet routing messages */ ++#define NETLINK_DNRTMSG 14 /* DECnet routing messages (obsolete) */ + #define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */ + #define NETLINK_GENERIC 16 + /* leave room for NETLINK_DM (DM Events) */ + #define NETLINK_SCSITRANSPORT 18 /* SCSI Transports */ + #define NETLINK_ECRYPTFS 19 ++#define NETLINK_RDMA 20 ++#define NETLINK_CRYPTO 21 /* Crypto layer */ ++#define NETLINK_SMC 22 /* SMC monitoring */ ++ ++#define NETLINK_INET_DIAG NETLINK_SOCK_DIAG + + #define MAX_LINKS 32 + + struct sockaddr_nl { +- sa_family_t nl_family; /* AF_NETLINK */ ++ __kernel_sa_family_t nl_family; /* AF_NETLINK */ + unsigned short nl_pad; /* zero */ + __u32 nl_pid; /* port ID */ + __u32 nl_groups; /* multicast groups mask */ + }; + ++/** ++ * struct nlmsghdr - fixed format metadata header of Netlink messages ++ * @nlmsg_len: Length of message including header ++ * @nlmsg_type: Message content type ++ * @nlmsg_flags: Additional flags ++ * @nlmsg_seq: Sequence number ++ * @nlmsg_pid: Sending process port ID ++ */ + struct nlmsghdr { +- __u32 nlmsg_len; /* Length of message including header */ +- __u16 nlmsg_type; /* Message content */ +- __u16 nlmsg_flags; /* Additional flags */ +- __u32 nlmsg_seq; /* Sequence number */ +- __u32 nlmsg_pid; /* Sending process port ID */ ++ __u32 nlmsg_len; ++ __u16 nlmsg_type; ++ __u16 nlmsg_flags; ++ __u32 nlmsg_seq; ++ __u32 nlmsg_pid; + }; + + /* Flags values */ + +-#define NLM_F_REQUEST 1 /* It is request message. */ +-#define NLM_F_MULTI 2 /* Multipart message, terminated by NLMSG_DONE */ +-#define NLM_F_ACK 4 /* Reply with ack, with zero or error code */ +-#define NLM_F_ECHO 8 /* Echo this request */ ++#define NLM_F_REQUEST 0x01 /* It is request message. */ ++#define NLM_F_MULTI 0x02 /* Multipart message, terminated by NLMSG_DONE */ ++#define NLM_F_ACK 0x04 /* Reply with ack, with zero or error code */ ++#define NLM_F_ECHO 0x08 /* Receive resulting notifications */ ++#define NLM_F_DUMP_INTR 0x10 /* Dump was inconsistent due to sequence change */ ++#define NLM_F_DUMP_FILTERED 0x20 /* Dump was filtered as requested */ + + /* Modifiers to GET request */ + #define NLM_F_ROOT 0x100 /* specify tree root */ +@@ -61,6 +78,14 @@ struct nlmsghdr { + #define NLM_F_CREATE 0x400 /* Create, if it does not exist */ + #define NLM_F_APPEND 0x800 /* Add to end of list */ + ++/* Modifiers to DELETE request */ ++#define NLM_F_NONREC 0x100 /* Do not delete recursively */ ++#define NLM_F_BULK 0x200 /* Delete multiple objects */ ++ ++/* Flags for ACK message */ ++#define NLM_F_CAPPED 0x100 /* request was capped */ ++#define NLM_F_ACK_TLVS 0x200 /* extended ACK TVLs were included */ ++ + /* + 4.4BSD ADD NLM_F_CREATE|NLM_F_EXCL + 4.4BSD CHANGE NLM_F_REPLACE +@@ -70,14 +95,15 @@ struct nlmsghdr { + Check NLM_F_EXCL + */ + +-#define NLMSG_ALIGNTO 4 ++#define NLMSG_ALIGNTO 4U + #define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) ) + #define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr))) +-#define NLMSG_LENGTH(len) ((len)+NLMSG_ALIGN(NLMSG_HDRLEN)) ++#define NLMSG_LENGTH(len) ((len) + NLMSG_HDRLEN) + #define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len)) +-#define NLMSG_DATA(nlh) ((void*)(((char*)nlh) + NLMSG_LENGTH(0))) ++#define NLMSG_DATA(nlh) ((void *)(((char *)nlh) + NLMSG_HDRLEN)) + #define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \ +- (struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len))) ++ (struct nlmsghdr *)(((char *)(nlh)) + \ ++ NLMSG_ALIGN((nlh)->nlmsg_len))) + #define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \ + (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \ + (nlh)->nlmsg_len <= (len)) +@@ -93,18 +119,93 @@ struct nlmsghdr { + struct nlmsgerr { + int error; + struct nlmsghdr msg; ++ /* ++ * followed by the message contents unless NETLINK_CAP_ACK was set ++ * or the ACK indicates success (error == 0) ++ * message length is aligned with NLMSG_ALIGN() ++ */ ++ /* ++ * followed by TLVs defined in enum nlmsgerr_attrs ++ * if NETLINK_EXT_ACK was set ++ */ ++}; ++ ++/** ++ * enum nlmsgerr_attrs - nlmsgerr attributes ++ * @NLMSGERR_ATTR_UNUSED: unused ++ * @NLMSGERR_ATTR_MSG: error message string (string) ++ * @NLMSGERR_ATTR_OFFS: offset of the invalid attribute in the original ++ * message, counting from the beginning of the header (u32) ++ * @NLMSGERR_ATTR_COOKIE: arbitrary subsystem specific cookie to ++ * be used - in the success case - to identify a created ++ * object or operation or similar (binary) ++ * @NLMSGERR_ATTR_POLICY: policy for a rejected attribute ++ * @NLMSGERR_ATTR_MISS_TYPE: type of a missing required attribute, ++ * %NLMSGERR_ATTR_MISS_NEST will not be present if the attribute was ++ * missing at the message level ++ * @NLMSGERR_ATTR_MISS_NEST: offset of the nest where attribute was missing ++ * @__NLMSGERR_ATTR_MAX: number of attributes ++ * @NLMSGERR_ATTR_MAX: highest attribute number ++ */ ++enum nlmsgerr_attrs { ++ NLMSGERR_ATTR_UNUSED, ++ NLMSGERR_ATTR_MSG, ++ NLMSGERR_ATTR_OFFS, ++ NLMSGERR_ATTR_COOKIE, ++ NLMSGERR_ATTR_POLICY, ++ NLMSGERR_ATTR_MISS_TYPE, ++ NLMSGERR_ATTR_MISS_NEST, ++ ++ __NLMSGERR_ATTR_MAX, ++ NLMSGERR_ATTR_MAX = __NLMSGERR_ATTR_MAX - 1 + }; + +-#define NETLINK_ADD_MEMBERSHIP 1 +-#define NETLINK_DROP_MEMBERSHIP 2 +-#define NETLINK_PKTINFO 3 +-#define NETLINK_BROADCAST_ERROR 4 +-#define NETLINK_NO_ENOBUFS 5 ++#define NETLINK_ADD_MEMBERSHIP 1 ++#define NETLINK_DROP_MEMBERSHIP 2 ++#define NETLINK_PKTINFO 3 ++#define NETLINK_BROADCAST_ERROR 4 ++#define NETLINK_NO_ENOBUFS 5 ++#define NETLINK_RX_RING 6 ++#define NETLINK_TX_RING 7 ++#define NETLINK_LISTEN_ALL_NSID 8 ++#define NETLINK_LIST_MEMBERSHIPS 9 ++#define NETLINK_CAP_ACK 10 ++#define NETLINK_EXT_ACK 11 ++#define NETLINK_GET_STRICT_CHK 12 + + struct nl_pktinfo { + __u32 group; + }; + ++struct nl_mmap_req { ++ unsigned int nm_block_size; ++ unsigned int nm_block_nr; ++ unsigned int nm_frame_size; ++ unsigned int nm_frame_nr; ++}; ++ ++struct nl_mmap_hdr { ++ unsigned int nm_status; ++ unsigned int nm_len; ++ __u32 nm_group; ++ /* credentials */ ++ __u32 nm_pid; ++ __u32 nm_uid; ++ __u32 nm_gid; ++}; ++ ++enum nl_mmap_status { ++ NL_MMAP_STATUS_UNUSED, ++ NL_MMAP_STATUS_RESERVED, ++ NL_MMAP_STATUS_VALID, ++ NL_MMAP_STATUS_COPY, ++ NL_MMAP_STATUS_SKIP, ++}; ++ ++#define NL_MMAP_MSG_ALIGNMENT NLMSG_ALIGNTO ++#define NL_MMAP_MSG_ALIGN(sz) __ALIGN_KERNEL(sz, NL_MMAP_MSG_ALIGNMENT) ++#define NL_MMAP_HDRLEN NL_MMAP_MSG_ALIGN(sizeof(struct nl_mmap_hdr)) ++ + #define NET_MAJOR 36 /* Major 36 is reserved for networking */ + + enum { +@@ -144,4 +245,130 @@ struct nlattr { + #define NLA_ALIGN(len) (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1)) + #define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr))) + +-#endif /* __LINUX_NETLINK_H */ ++/* Generic 32 bitflags attribute content sent to the kernel. ++ * ++ * The value is a bitmap that defines the values being set ++ * The selector is a bitmask that defines which value is legit ++ * ++ * Examples: ++ * value = 0x0, and selector = 0x1 ++ * implies we are selecting bit 1 and we want to set its value to 0. ++ * ++ * value = 0x2, and selector = 0x2 ++ * implies we are selecting bit 2 and we want to set its value to 1. ++ * ++ */ ++struct nla_bitfield32 { ++ __u32 value; ++ __u32 selector; ++}; ++ ++/* ++ * policy descriptions - it's specific to each family how this is used ++ * Normally, it should be retrieved via a dump inside another attribute ++ * specifying where it applies. ++ */ ++ ++/** ++ * enum netlink_attribute_type - type of an attribute ++ * @NL_ATTR_TYPE_INVALID: unused ++ * @NL_ATTR_TYPE_FLAG: flag attribute (present/not present) ++ * @NL_ATTR_TYPE_U8: 8-bit unsigned attribute ++ * @NL_ATTR_TYPE_U16: 16-bit unsigned attribute ++ * @NL_ATTR_TYPE_U32: 32-bit unsigned attribute ++ * @NL_ATTR_TYPE_U64: 64-bit unsigned attribute ++ * @NL_ATTR_TYPE_S8: 8-bit signed attribute ++ * @NL_ATTR_TYPE_S16: 16-bit signed attribute ++ * @NL_ATTR_TYPE_S32: 32-bit signed attribute ++ * @NL_ATTR_TYPE_S64: 64-bit signed attribute ++ * @NL_ATTR_TYPE_BINARY: binary data, min/max length may be specified ++ * @NL_ATTR_TYPE_STRING: string, min/max length may be specified ++ * @NL_ATTR_TYPE_NUL_STRING: NUL-terminated string, ++ * min/max length may be specified ++ * @NL_ATTR_TYPE_NESTED: nested, i.e. the content of this attribute ++ * consists of sub-attributes. The nested policy and maxtype ++ * inside may be specified. ++ * @NL_ATTR_TYPE_NESTED_ARRAY: nested array, i.e. the content of this ++ * attribute contains sub-attributes whose type is irrelevant ++ * (just used to separate the array entries) and each such array ++ * entry has attributes again, the policy for those inner ones ++ * and the corresponding maxtype may be specified. ++ * @NL_ATTR_TYPE_BITFIELD32: &struct nla_bitfield32 attribute ++ */ ++enum netlink_attribute_type { ++ NL_ATTR_TYPE_INVALID, ++ ++ NL_ATTR_TYPE_FLAG, ++ ++ NL_ATTR_TYPE_U8, ++ NL_ATTR_TYPE_U16, ++ NL_ATTR_TYPE_U32, ++ NL_ATTR_TYPE_U64, ++ ++ NL_ATTR_TYPE_S8, ++ NL_ATTR_TYPE_S16, ++ NL_ATTR_TYPE_S32, ++ NL_ATTR_TYPE_S64, ++ ++ NL_ATTR_TYPE_BINARY, ++ NL_ATTR_TYPE_STRING, ++ NL_ATTR_TYPE_NUL_STRING, ++ ++ NL_ATTR_TYPE_NESTED, ++ NL_ATTR_TYPE_NESTED_ARRAY, ++ ++ NL_ATTR_TYPE_BITFIELD32, ++}; ++ ++/** ++ * enum netlink_policy_type_attr - policy type attributes ++ * @NL_POLICY_TYPE_ATTR_UNSPEC: unused ++ * @NL_POLICY_TYPE_ATTR_TYPE: type of the attribute, ++ * &enum netlink_attribute_type (U32) ++ * @NL_POLICY_TYPE_ATTR_MIN_VALUE_S: minimum value for signed ++ * integers (S64) ++ * @NL_POLICY_TYPE_ATTR_MAX_VALUE_S: maximum value for signed ++ * integers (S64) ++ * @NL_POLICY_TYPE_ATTR_MIN_VALUE_U: minimum value for unsigned ++ * integers (U64) ++ * @NL_POLICY_TYPE_ATTR_MAX_VALUE_U: maximum value for unsigned ++ * integers (U64) ++ * @NL_POLICY_TYPE_ATTR_MIN_LENGTH: minimum length for binary ++ * attributes, no minimum if not given (U32) ++ * @NL_POLICY_TYPE_ATTR_MAX_LENGTH: maximum length for binary ++ * attributes, no maximum if not given (U32) ++ * @NL_POLICY_TYPE_ATTR_POLICY_IDX: sub policy for nested and ++ * nested array types (U32) ++ * @NL_POLICY_TYPE_ATTR_POLICY_MAXTYPE: maximum sub policy ++ * attribute for nested and nested array types, this can ++ * in theory be < the size of the policy pointed to by ++ * the index, if limited inside the nesting (U32) ++ * @NL_POLICY_TYPE_ATTR_BITFIELD32_MASK: valid mask for the ++ * bitfield32 type (U32) ++ * @NL_POLICY_TYPE_ATTR_MASK: mask of valid bits for unsigned integers (U64) ++ * @NL_POLICY_TYPE_ATTR_PAD: pad attribute for 64-bit alignment ++ * ++ * @__NL_POLICY_TYPE_ATTR_MAX: number of attributes ++ * @NL_POLICY_TYPE_ATTR_MAX: highest attribute number ++ */ ++enum netlink_policy_type_attr { ++ NL_POLICY_TYPE_ATTR_UNSPEC, ++ NL_POLICY_TYPE_ATTR_TYPE, ++ NL_POLICY_TYPE_ATTR_MIN_VALUE_S, ++ NL_POLICY_TYPE_ATTR_MAX_VALUE_S, ++ NL_POLICY_TYPE_ATTR_MIN_VALUE_U, ++ NL_POLICY_TYPE_ATTR_MAX_VALUE_U, ++ NL_POLICY_TYPE_ATTR_MIN_LENGTH, ++ NL_POLICY_TYPE_ATTR_MAX_LENGTH, ++ NL_POLICY_TYPE_ATTR_POLICY_IDX, ++ NL_POLICY_TYPE_ATTR_POLICY_MAXTYPE, ++ NL_POLICY_TYPE_ATTR_BITFIELD32_MASK, ++ NL_POLICY_TYPE_ATTR_PAD, ++ NL_POLICY_TYPE_ATTR_MASK, ++ ++ /* keep last */ ++ __NL_POLICY_TYPE_ATTR_MAX, ++ NL_POLICY_TYPE_ATTR_MAX = __NL_POLICY_TYPE_ATTR_MAX - 1 ++}; ++ ++#endif /* __LINUX_NETLINK_H */ +diff --git a/include/lldp.h b/include/lldp.h +index de6a4adddc69..439c49aff8ab 100644 +--- a/include/lldp.h ++++ b/include/lldp.h +@@ -52,11 +52,29 @@ typedef __u64 u64; + }) + + /* Use strncpy with N-1 and ensure the string is terminated. */ ++#ifdef HAVE_STRLCPY ++#define STRNCPY_TERMINATED(DEST, SRC, N) \ ++ (void)strlcpy(DEST, SRC, N) ++#elif __GNUC__ >= 10 ++#define STRNCPY_TERMINATED(DEST, SRC, N) \ ++ do { \ ++ if((N) > 0) { \ ++ _Pragma("GCC diagnostic push") \ ++ _Pragma("GCC diagnostic ignored \"-Wstringop-truncation\"") \ ++ strncpy (DEST, SRC, (N) - 1); \ ++ _Pragma("GCC diagnostic pop") \ ++ DEST[(N) - 1] = '\0'; \ ++ } \ ++ } while (false) ++#else + #define STRNCPY_TERMINATED(DEST, SRC, N) \ + do { \ +- strncpy (DEST, SRC, N - 1); \ +- DEST[N - 1] = '\0'; \ ++ if((N) > 0) { \ ++ strncpy (DEST, SRC, (N) - 1); \ ++ DEST[(N) - 1] = '\0'; \ ++ } \ + } while (false) ++#endif + + /* + * Organizationally Unique Identifier (OUI) +@@ -228,12 +246,19 @@ enum { + #define LLDP_8023_POWER_VIA_MDI 2 + #define LLDP_8023_LINK_AGGREGATION 3 + #define LLDP_8023_MAXIMUM_FRAME_SIZE 4 ++#define LLDP_8023_ADD_ETH_CAPS 7 + /* 802.3AB-2005 G.2.1 Table G-2 */ + #define LLDP_8023_MACPHY_AUTONEG_SUPPORT (1 << 0) + #define LLDP_8023_MACPHY_AUTONEG_ENABLED (1 << 1) + /* 802.3AB-2005 G.4.1 Table G-4 */ + #define LLDP_8023_LINKAGG_CAPABLE (1 << 0) + #define LLDP_8023_LINKAGG_ENABLED (1 << 1) ++/* 802.3-2018 Table 79-8 */ ++#define LLDP_8023_ADD_ETH_CAPS_PREEMPT_SUPPORT (1 << 0) ++#define LLDP_8023_ADD_ETH_CAPS_PREEMPT_STATUS (1 << 1) ++#define LLDP_8023_ADD_ETH_CAPS_PREEMPT_ACTIVE (1 << 2) ++#define LLDP_8023_ADD_ETH_CAPS_ADD_FRAG_SIZE(x) (((x) & 0x3) << 3) ++#define LLDP_8023_ADD_ETH_CAPS_ADD_FRAG_SIZE_X(x) (((x) >> 3) & 0x3) + + /* IEEE 802.1Qbg subtype */ + #define LLDP_EVB_SUBTYPE 0 /* Draft 0.1 value */ +diff --git a/include/lldp_8023.h b/include/lldp_8023.h +index eead191e5d6e..61d5a1255fc2 100644 +--- a/include/lldp_8023.h ++++ b/include/lldp_8023.h +@@ -27,6 +27,7 @@ + #ifndef _LLDP_8023_H + #define _LLDP_8023_H + ++#include "lldp_ethtool.h" + #include "lldp_mod.h" + #include "lldp_tlv.h" + +@@ -39,10 +40,13 @@ struct ieee8023_data { + struct unpacked_tlv *powvmdi; + struct unpacked_tlv *linkagg; + struct unpacked_tlv *maxfs; ++ struct unpacked_tlv *add_eth_caps; ++ bool enabled_preemption; + LIST_ENTRY(ieee8023_data) entry; + }; + + struct ieee8023_user_data { ++ struct ethtool_sock *ethtool_sk; + LIST_HEAD(ieee8023_head, ieee8023_data) head; + }; + +@@ -51,5 +55,7 @@ void ieee8023_unregister(struct lldp_module *mod); + struct packed_tlv *ieee8023_gettlv(struct port *, struct lldp_agent *); + void ieee8023_ifdown(char *, struct lldp_agent *); + void ieee8023_ifup(char *, struct lldp_agent *); ++int ieee8023_rchange(struct port *port, struct lldp_agent *agent, ++ struct unpacked_tlv *tlv); + + #endif /* _LLDP_8023_H */ +diff --git a/include/lldp_8023_cmds.h b/include/lldp_8023_cmds.h +index 71f0641b00c7..f7e373b6544c 100644 +--- a/include/lldp_8023_cmds.h ++++ b/include/lldp_8023_cmds.h +@@ -27,6 +27,8 @@ + #ifndef _LLDP_8023_CMDS_H + #define _LLDP_8023_CMDS_H + ++#define ARG_8023_ADD_FRAG_SIZE "addFragSize" ++ + struct arg_handlers *ieee8023_get_arg_handlers(); + + #endif +diff --git a/include/lldp_ethtool.h b/include/lldp_ethtool.h +new file mode 100644 +index 000000000000..2b41328b6a92 +--- /dev/null ++++ b/include/lldp_ethtool.h +@@ -0,0 +1,58 @@ ++#ifndef _LLDP_ETHTOOL_H ++#define _LLDP_ETHTOOL_H ++ ++#include ++#include ++#include ++ ++struct ethtool_sock; ++ ++struct ethtool_sock *ethtool_sock_create(void); ++void ethtool_sock_destroy(struct ethtool_sock *sk); ++ ++struct ethtool_mm { ++ bool tx_enabled; ++ bool tx_active; ++ bool pmac_enabled; ++ bool verify_enabled; ++ __u8 verify_status; ++ __u32 verify_time; ++ __u32 max_verify_time; ++ __u32 tx_min_frag_size; ++ __u32 rx_min_frag_size; ++}; ++ ++int ethtool_mm_get_state(struct ethtool_sock *sk, const char *ifname, ++ struct ethtool_mm *mm); ++int ethtool_mm_change_tx_enabled(struct ethtool_sock *sk, const char *ifname, ++ bool enabled, bool verify, u32 verify_time); ++int ethtool_mm_change_pmac_enabled(struct ethtool_sock *sk, const char *ifname, ++ bool enabled); ++int ethtool_mm_change_tx_min_frag_size(struct ethtool_sock *sk, ++ const char *ifname, u32 min_frag_size); ++ ++/* Translate an advertised additional fragment size into a minimum fragment ++ * size in octets to pass to the kernel. ++ */ ++static inline int ethtool_mm_frag_size_add_to_min(int add_frag_size) ++{ ++ return 64 * (1 + add_frag_size) - 4; ++} ++ ++/* Translate the minimum RX fragment size requested by the kernel into an ++ * additional fragment size to advertise, that covers at least that value. ++ */ ++static inline int ethtool_mm_frag_size_min_to_add(int min_frag_size) ++{ ++ int add_frag_size, m; ++ ++ for (add_frag_size = 0; add_frag_size < 4; add_frag_size++) { ++ m = ethtool_mm_frag_size_add_to_min(add_frag_size); ++ if (m >= min_frag_size) ++ return add_frag_size; ++ } ++ ++ return -EINVAL; ++} ++ ++#endif +diff --git a/lldp/ports.c b/lldp/ports.c +index 9b681f7e58ab..3eab71f8eff1 100644 +--- a/lldp/ports.c ++++ b/lldp/ports.c +@@ -355,6 +355,9 @@ int remove_port(const char *ifname) + free(agent->tx.frameout); + + LIST_REMOVE(agent, entry); ++ ++ remove_config_device(ifname, agent->type); ++ + free(agent); + } + +diff --git a/lldp_8021qaz.c b/lldp_8021qaz.c +index 5fccbe4389d2..ef44508a5e9e 100644 +--- a/lldp_8021qaz.c ++++ b/lldp_8021qaz.c +@@ -210,6 +210,7 @@ static int read_cfg_file(char *ifname, struct lldp_agent *agent, + char arg_path[256]; + int res = 0, i; + int willing, pfc_mask, delay; ++ char *parse = NULL; + + if (agent->type != NEAREST_BRIDGE) + return 0; +@@ -354,7 +355,6 @@ static int read_cfg_file(char *ifname, struct lldp_agent *agent, + + /* Read and add APP data to internal lldpad APP ring */ + for (i = 0; i < MAX_APP_ENTRIES; i++) { +- char *parse; + char *app_tuple; + u8 prio, sel; + long pid; +@@ -391,8 +391,10 @@ static int read_cfg_file(char *ifname, struct lldp_agent *agent, + ieee8021qaz_mod_app(&tlvs->app_head, 0, + prio, sel, (u16) pid, 0); + free(parse); ++ parse = NULL; + } + ++ free(parse); + return 0; + } + +diff --git a/lldp_8021qaz_cmds.c b/lldp_8021qaz_cmds.c +index e017e2ab9ac8..6bc2bb88fa03 100644 +--- a/lldp_8021qaz_cmds.c ++++ b/lldp_8021qaz_cmds.c +@@ -538,9 +538,9 @@ _set_arg_up2tc(struct cmd *cmd, char *args, const char *arg_value, + } + + if (test) { ++ free(parse); + if (!is_dcbx_hw(cmd->ifname)) + return cmd_not_capable; +- free(parse); + return cmd_success; + } + +@@ -648,16 +648,15 @@ _set_arg_tcbw(struct cmd *cmd, char *args, const char *arg_value, + percent[i] = atoi(toked_bw); + toked_bw = strtok(NULL, ","); + } ++ free(parse); + + for (i = 0; i < 8; i++) + total += percent[i]; + if (total != 100) { +- err = cmd_invalid; +- goto invalid; ++ return cmd_invalid; + } else if (test) { + if (!is_dcbx_hw(cmd->ifname)) + return cmd_not_capable; +- free(parse); + return cmd_success; + } else if (tcbw) { + memcpy(tcbw, percent, sizeof(*tcbw) * MAX_TCS); +@@ -677,8 +676,7 @@ _set_arg_tcbw(struct cmd *cmd, char *args, const char *arg_value, + set_config_setting(cmd->ifname, cmd->type, arg_path, &arg_value, + CONFIG_TYPE_STRING); + somethingChangedLocal(cmd->ifname, cmd->type); +-invalid: +- free(parse); ++ + return err; + } + +@@ -805,9 +803,9 @@ _set_arg_tsa(struct cmd *cmd, char *args, const char *arg_value, + } + + if (test) { ++ free(parse); + if (!is_dcbx_hw(cmd->ifname)) + return cmd_not_capable; +- free(parse); + return cmd_success; + } + +@@ -935,11 +933,15 @@ static int _set_arg_enabled(struct cmd *cmd, char *args, + errno = 0; + prio = strtol(priority, &end, 10); + +- if (end == priority || *end != '\0') +- return cmd_invalid; ++ if (end == priority || *end != '\0') { ++ err = cmd_invalid; ++ goto invalid; ++ } + +- if (errno || prio < 0) +- return cmd_invalid; ++ if (errno || prio < 0) { ++ err = cmd_invalid; ++ goto invalid; ++ } + + if (prio > 7) { + err = cmd_invalid; +@@ -951,9 +953,9 @@ static int _set_arg_enabled(struct cmd *cmd, char *args, + } + + if (test) { ++ free(parse); + if (!is_dcbx_hw(cmd->ifname)) + return cmd_not_capable; +- free(parse); + return cmd_success; + } + +@@ -1121,6 +1123,7 @@ static int get_arg_app(struct cmd *cmd, char *args, UNUSED char *arg_value, + const char *app; + u8 prio, sel; + int proto, hw = -1, i; ++ char *parse = NULL; + + if (cmd->cmd != cmd_gettlv) + return cmd_invalid; +@@ -1137,7 +1140,7 @@ static int get_arg_app(struct cmd *cmd, char *args, UNUSED char *arg_value, + tlvs = ieee8021qaz_data(cmd->ifname); + for (i = 0; i < MAX_APP_ENTRIES; i++) { + char arg_path[256]; +- char *parse, *app_tuple; ++ char *app_tuple; + int err; + + snprintf(arg_path, sizeof(arg_path), "%s%08x.%s%i", +@@ -1191,8 +1194,13 @@ static int get_arg_app(struct cmd *cmd, char *args, UNUSED char *arg_value, + + arg_app_strncat_hw(new_app, hw); + strncat(app_buf, new_app, sizeof(app_buf) - strlen(app_buf) - 2); ++ ++ free(parse); ++ parse = NULL; + } + ++ free(parse); ++ + if (tlvs) { + LIST_FOREACH(np, &tlvs->app_head, entry) { + if (!np->peer) +diff --git a/lldp_8023.c b/lldp_8023.c +index 0fd48f06ecf2..a92df17c921c 100644 +--- a/lldp_8023.c ++++ b/lldp_8023.c +@@ -38,6 +38,8 @@ + #include "config.h" + #include "lldp_8023_clif.h" + #include "lldp_8023_cmds.h" ++#include "lldp_ethtool.h" ++#include "lldp_mand_clif.h" + + struct tlv_info_8023_maccfg { + u8 oui[3]; +@@ -68,21 +70,33 @@ struct tlv_info_8023_powvmdi { + u8 class; + } __attribute__ ((__packed__)); + ++struct tlv_info_8023_add_eth_caps { ++ u8 oui[3]; ++ u8 sub; ++ u16 preempt; ++} __attribute__ ((__packed__)); ++ + static const struct lldp_mod_ops ieee8023_ops = { + .lldp_mod_register = ieee8023_register, + .lldp_mod_unregister = ieee8023_unregister, + .lldp_mod_gettlv = ieee8023_gettlv, + .lldp_mod_ifup = ieee8023_ifup, + .lldp_mod_ifdown = ieee8023_ifdown, ++ .lldp_mod_rchange = ieee8023_rchange, + .get_arg_handler = ieee8023_get_arg_handlers, + }; + +-static struct ieee8023_data *ieee8023_data(const char *ifname, enum agent_type type) ++static struct ieee8023_data *ieee8023_data(const char *ifname, ++ enum agent_type type, ++ struct ieee8023_user_data **p_ud) + { + struct ieee8023_user_data *ud; + struct ieee8023_data *bd = NULL; + + ud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_8023); ++ if (p_ud) ++ *p_ud = ud; ++ + if (ud) { + LIST_FOREACH(bd, &ud->head, entry) { + if (!strncmp(ifname, bd->ifname, IFNAMSIZ) && +@@ -308,6 +322,129 @@ out_err: + return rc; + } + ++static int ieee8023_config_read_add_frag_size(const char *ifname, ++ struct lldp_agent *agent) ++{ ++ int add_frag_size, err; ++ char arg_path[256]; ++ ++ snprintf(arg_path, sizeof(arg_path), "%s%08x.%s", TLVID_PREFIX, ++ TLVID_8023(LLDP_8023_ADD_ETH_CAPS), ARG_8023_ADD_FRAG_SIZE); ++ ++ err = get_config_setting(ifname, agent->type, arg_path, &add_frag_size, ++ CONFIG_TYPE_INT); ++ if (err) ++ return 0; ++ ++ return add_frag_size; ++} ++ ++static u16 ieee8023_bld_preempt_status(struct ieee8023_data *bd, ++ struct lldp_agent *agent) ++{ ++ int err, add_frag_size, config_add_frag_size; ++ struct ieee8023_user_data *ud; ++ struct ethtool_mm mm; ++ u16 status = 0; ++ ++ ud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_8023); ++ ++ if (!ud->ethtool_sk) ++ return status; ++ ++ err = ethtool_mm_get_state(ud->ethtool_sk, bd->ifname, &mm); ++ if (err) { ++ LLDPAD_ERR("%s: Failed to query ethtool MAC merge support: %d\n", ++ bd->ifname, err); ++ return status; ++ } ++ ++ config_add_frag_size = ieee8023_config_read_add_frag_size(bd->ifname, ++ agent); ++ ++ add_frag_size = ethtool_mm_frag_size_min_to_add(mm.rx_min_frag_size); ++ if (add_frag_size < 0) { ++ LLDPAD_ERR("%s: Kernel requests an RX min fragment size of %d which is too large to advertise\n", ++ bd->ifname, mm.rx_min_frag_size); ++ return status; ++ } ++ ++ if (config_add_frag_size < add_frag_size) { ++ LLDPAD_WARN("%s: Configured addFragSize (%d) smaller than the minimum value requested by kernel (%d). Using the latter\n", ++ bd->ifname, config_add_frag_size, add_frag_size); ++ config_add_frag_size = add_frag_size; ++ } ++ ++ /* No error => supported */ ++ status |= LLDP_8023_ADD_ETH_CAPS_PREEMPT_SUPPORT | ++ LLDP_8023_ADD_ETH_CAPS_ADD_FRAG_SIZE(config_add_frag_size); ++ ++ if (mm.tx_enabled) ++ status |= LLDP_8023_ADD_ETH_CAPS_PREEMPT_STATUS; ++ ++ if (mm.tx_active) ++ status |= LLDP_8023_ADD_ETH_CAPS_PREEMPT_ACTIVE; ++ ++ return status; ++} ++ ++/* ++ * ieee8023_bld_add_eth_caps_tlv - build the Additional Ethernet Capabilities TLV ++ * @bd: the med data struct ++ * ++ * Returns 0 on success ++ */ ++static int ieee8023_bld_add_eth_caps_tlv(struct ieee8023_data *bd, ++ struct lldp_agent *agent) ++{ ++ struct tlv_info_8023_add_eth_caps add_eth_caps; ++ struct unpacked_tlv *tlv; ++ ++ /* free old one if it exists */ ++ FREE_UNPKD_TLV(bd, add_eth_caps); ++ ++ if (!is_tlv_txenabled(bd->ifname, agent->type, ++ TLVID_8023(LLDP_8023_ADD_ETH_CAPS))) ++ return 0; ++ ++ hton24(add_eth_caps.oui, OUI_IEEE_8023); ++ add_eth_caps.sub = LLDP_8023_ADD_ETH_CAPS; ++ add_eth_caps.preempt = htons(ieee8023_bld_preempt_status(bd, agent)); ++ ++ tlv = create_tlv(); ++ if (!tlv) ++ return -ENOMEM; ++ ++ tlv->type = ORG_SPECIFIC_TLV; ++ tlv->length = sizeof(add_eth_caps); ++ tlv->info = malloc(tlv->length); ++ if (!tlv->info) { ++ free(tlv); ++ return -ENOMEM; ++ } ++ ++ memcpy(tlv->info, &add_eth_caps, tlv->length); ++ bd->add_eth_caps = tlv; ++ ++ return 0; ++} ++ ++static void ieee8023_add_eth_caps_teardown(struct ieee8023_data *bd, ++ struct ieee8023_user_data *ud) ++{ ++ /* On link down, the link partner might change to another one which ++ * does not advertise support for preemption, so disable what we've ++ * applied. However, do not disable preemption if it wasn't enabled ++ * by lldpad in the first place. ++ */ ++ if (bd->enabled_preemption) { ++ ethtool_mm_change_tx_enabled(ud->ethtool_sk, bd->ifname, false, ++ false, 10); ++ ethtool_mm_change_pmac_enabled(ud->ethtool_sk, bd->ifname, ++ false); ++ } ++} ++ + static void ieee8023_free_tlv(struct ieee8023_data *bd) + { + if (bd) { +@@ -315,6 +452,7 @@ static void ieee8023_free_tlv(struct ieee8023_data *bd) + FREE_UNPKD_TLV(bd, powvmdi); + FREE_UNPKD_TLV(bd, linkagg); + FREE_UNPKD_TLV(bd, maxfs); ++ FREE_UNPKD_TLV(bd, add_eth_caps); + } + } + +@@ -343,19 +481,29 @@ static int ieee8023_bld_tlv(struct ieee8023_data *bd, struct lldp_agent *agent) + __func__, bd->ifname); + return 0; + } ++ if (ieee8023_bld_add_eth_caps_tlv(bd, agent)) { ++ LLDPAD_DBG("%s:%s:ieee8023_bld_add_eth_caps_tlv() failed\n", ++ __func__, bd->ifname); ++ return 0; ++ } + return 0; + } + + static void ieee8023_free_data(struct ieee8023_user_data *ud) + { + struct ieee8023_data *bd; ++ + if (ud) { + while (!LIST_EMPTY(&ud->head)) { + bd = LIST_FIRST(&ud->head); + LIST_REMOVE(bd, entry); ++ ieee8023_add_eth_caps_teardown(bd, ud); + ieee8023_free_tlv(bd); + free(bd); + } ++ ++ if (ud->ethtool_sk) ++ ethtool_sock_destroy(ud->ethtool_sk); + } + } + +@@ -366,7 +514,7 @@ struct packed_tlv *ieee8023_gettlv(struct port *port, + struct ieee8023_data *bd; + struct packed_tlv *ptlv = NULL; + +- bd = ieee8023_data(port->ifname, agent->type); ++ bd = ieee8023_data(port->ifname, agent->type, NULL); + if (!bd) + goto out_err; + +@@ -377,10 +525,11 @@ struct packed_tlv *ieee8023_gettlv(struct port *port, + goto out_err; + } + +- size = TLVSIZE(bd->maccfg) +- + TLVSIZE(bd->powvmdi) +- + TLVSIZE(bd->linkagg) +- + TLVSIZE(bd->maxfs); ++ size = TLVSIZE(bd->maccfg) + ++ TLVSIZE(bd->powvmdi) + ++ TLVSIZE(bd->linkagg) + ++ TLVSIZE(bd->maxfs) + ++ TLVSIZE(bd->add_eth_caps); + if (!size) + goto out_err; + +@@ -397,6 +546,7 @@ struct packed_tlv *ieee8023_gettlv(struct port *port, + PACK_TLV_AFTER(bd->powvmdi, ptlv, size, out_free); + PACK_TLV_AFTER(bd->linkagg, ptlv, size, out_free); + PACK_TLV_AFTER(bd->maxfs, ptlv, size, out_free); ++ PACK_TLV_AFTER(bd->add_eth_caps, ptlv, size, out_free); + return ptlv; + out_free: + free_pkd_tlv(ptlv); +@@ -409,13 +559,15 @@ out_err: + + void ieee8023_ifdown(char *ifname, struct lldp_agent *agent) + { ++ struct ieee8023_user_data *ud; + struct ieee8023_data *bd; + +- bd = ieee8023_data(ifname, agent->type); ++ bd = ieee8023_data(ifname, agent->type, &ud); + if (!bd) + goto out_err; + + LIST_REMOVE(bd, entry); ++ ieee8023_add_eth_caps_teardown(bd, ud); + ieee8023_free_tlv(bd); + free(bd); + LLDPAD_INFO("%s:port %s removed\n", __func__, ifname); +@@ -431,7 +583,7 @@ void ieee8023_ifup(char *ifname, struct lldp_agent *agent) + struct ieee8023_data *bd; + struct ieee8023_user_data *ud; + +- bd = ieee8023_data(ifname, agent->type); ++ bd = ieee8023_data(ifname, agent->type, NULL); + if (bd) { + LLDPAD_INFO("%s:%s exists\n", __func__, ifname); + goto out_err; +@@ -463,6 +615,152 @@ out_err: + return; + } + ++static void ieee8023_rchange_add_eth_caps(struct ieee8023_data *bd, ++ struct ieee8023_user_data *ud, ++ u8 *buf, int len) ++{ ++ bool lp_supported, lp_enabled, lp_active; ++ struct ethtool_mm mm; ++ u32 lp_min_frag_size; ++ u8 lp_add_frag_size; ++ u8 tmp[2] = {}; ++ u16 preempt; ++ int err; ++ ++ memcpy(tmp, buf, MIN(len, 2)); ++ preempt = ntohs(*((u16 *)tmp)); ++ ++ lp_supported = !!(preempt & LLDP_8023_ADD_ETH_CAPS_PREEMPT_SUPPORT); ++ lp_enabled = !!(preempt & LLDP_8023_ADD_ETH_CAPS_PREEMPT_STATUS); ++ lp_active = !!(preempt & LLDP_8023_ADD_ETH_CAPS_PREEMPT_ACTIVE); ++ lp_add_frag_size = LLDP_8023_ADD_ETH_CAPS_ADD_FRAG_SIZE_X(preempt); ++ lp_min_frag_size = ethtool_mm_frag_size_add_to_min(lp_add_frag_size); ++ ++ LLDPAD_INFO("%s: Link partner preemption capability %ssupported\n", ++ bd->ifname, lp_supported ? "" : "not "); ++ LLDPAD_INFO("%s: Link partner preemption capability %senabled\n", ++ bd->ifname, lp_enabled ? "" : "not "); ++ LLDPAD_INFO("%s: Link partner preemption capability %sactive\n", ++ bd->ifname, lp_active ? "" : "not "); ++ LLDPAD_INFO("%s: Link partner minimum fragment size: %d octets\n", ++ bd->ifname, lp_min_frag_size); ++ ++ if (!lp_supported || !ud->ethtool_sk) ++ return; ++ ++ err = ethtool_mm_get_state(ud->ethtool_sk, bd->ifname, &mm); ++ if (err) { ++ LLDPAD_ERR("%s: Failed to query ethtool MAC merge support: %d\n", ++ bd->ifname, err); ++ return; ++ } ++ ++ /* In case the pMAC is not powered on, power it up now so that ++ * it responds to SMD-V frames initiated by the link partner, ++ * who may have enabled their verification state machine upon ++ * seeing our advertisements ++ */ ++ if (!mm.pmac_enabled) { ++ err = ethtool_mm_change_pmac_enabled(ud->ethtool_sk, bd->ifname, ++ true); ++ if (err) { ++ LLDPAD_ERR("%s: Failed to enable pMAC RX: %d\n", ++ bd->ifname, err); ++ return; ++ } ++ } ++ ++ /* Make sure that our TX is configured to use what minimum fragment ++ * size the link partner has requested ++ */ ++ if (mm.tx_min_frag_size != lp_min_frag_size) { ++ err = ethtool_mm_change_tx_min_frag_size(ud->ethtool_sk, ++ bd->ifname, ++ lp_min_frag_size); ++ if (err) { ++ LLDPAD_ERR("%s: Failed to change TX min fragment size: %d\n", ++ bd->ifname, err); ++ return; ++ } ++ } ++ ++ /* If both we and the link partner support frame preemption, we ++ * automatically turn our TX side on regardless of what the link ++ * partner may do. Since we request verification, preemption will ++ * only become active once the verification process succeeds ++ * (the link partner ACKs our handshake). Using the largest interval ++ * between verification attempts permitted by our hardware allows ++ * the link partner a bit of wiggle room to delay enabling its pMAC ++ * (which responds to our verification requests). ++ */ ++ if (!mm.tx_enabled || !mm.verify_enabled || ++ mm.verify_time != mm.max_verify_time) { ++ LLDPAD_INFO("%s: initiating MM verification with a retry interval of %d ms...\n", ++ bd->ifname, mm.max_verify_time); ++ ++ err = ethtool_mm_change_tx_enabled(ud->ethtool_sk, bd->ifname, ++ true, true, ++ mm.max_verify_time); ++ if (err) { ++ LLDPAD_ERR("%s: Failed to enable TX preemption: %d\n", ++ bd->ifname, err); ++ return; ++ } ++ } ++ ++ bd->enabled_preemption = true; ++} ++ ++/* ++ * ieee8023_rchange: process received IEEE 802.3 TLV LLDPDU ++ * ++ * TLV not consumed on error ++ */ ++int ieee8023_rchange(struct port *port, struct lldp_agent *agent, ++ struct unpacked_tlv *tlv) ++{ ++ struct ieee8023_user_data *ud; ++ struct ieee8023_data *bd; ++ u8 subtype; ++ u8 *oui; ++ ++ if (agent->type != NEAREST_BRIDGE) ++ return SUBTYPE_INVALID; ++ ++ bd = ieee8023_data(port->ifname, agent->type, &ud); ++ if (!bd) ++ return SUBTYPE_INVALID; ++ ++ if (tlv->type != TYPE_127) ++ return SUBTYPE_INVALID; ++ ++ if (tlv->length < OUI_SUB_SIZE) ++ return TLV_ERR; ++ ++ oui = tlv->info; ++ if (ntoh24(oui) != OUI_IEEE_8023) ++ return SUBTYPE_INVALID; ++ ++ subtype = *(tlv->info + OUI_SIZE); ++ switch (subtype) { ++ case LLDP_8023_MACPHY_CONFIG_STATUS: ++ case LLDP_8023_POWER_VIA_MDI: ++ case LLDP_8023_LINK_AGGREGATION: ++ case LLDP_8023_MAXIMUM_FRAME_SIZE: ++ /* We don't need to store the TLV, so free it */ ++ free_unpkd_tlv(tlv); ++ return TLV_OK; ++ case LLDP_8023_ADD_ETH_CAPS: ++ ieee8023_rchange_add_eth_caps(bd, ud, tlv->info + OUI_SUB_SIZE, ++ tlv->length - OUI_SUB_SIZE); ++ /* We don't need to store the TLV, so free it */ ++ free_unpkd_tlv(tlv); ++ return TLV_OK; ++ } ++ ++ return SUBTYPE_INVALID; ++} ++ + struct lldp_module *ieee8023_register(void) + { + struct lldp_module *mod; +@@ -479,6 +777,14 @@ struct lldp_module *ieee8023_register(void) + LLDPAD_ERR("failed to malloc LLDP 802.3 module user data\n"); + goto out_err; + } ++ ++ /* May return NULL if CONFIG_ETHTOOL_NETLINK is disabled, ++ * which isn't fatal ++ */ ++ ud->ethtool_sk = ethtool_sock_create(); ++ if (!ud->ethtool_sk) ++ LLDPAD_WARN("Failed to create ethtool netlink socket\n"); ++ + LIST_INIT(&ud->head); + mod->id = LLDP_MOD_8023; + mod->ops = &ieee8023_ops; +diff --git a/lldp_8023_clif.c b/lldp_8023_clif.c +index 7b0dd52f6192..c25d45e2c22c 100644 +--- a/lldp_8023_clif.c ++++ b/lldp_8023_clif.c +@@ -35,12 +35,14 @@ + #include "lldp.h" + #include "lldp_8023.h" + #include "lldp_8023_clif.h" ++#include "lldp_ethtool.h" + #include "lldp_util.h" + + void print_mac_phy(u16, char *info); + void print_power_mdi(u16, char *info); + void print_link_agg(u16, char *info); + void print_mtu(u16, char *info); ++void print_add_eth_caps(u16, char *info); + int ieee8023_print_help(); + + u32 ieee8023_lookup_tlv_name(char *tlvid_str); +@@ -66,6 +68,10 @@ struct type_name_info ieee8023_tlv_names[] = { + { .type = (LLDP_MOD_8023 << 8) | LLDP_8023_MAXIMUM_FRAME_SIZE, + .name = "Maximum Frame Size TLV", .key = "MTU", + .print_info = print_mtu, }, ++ { .type = (LLDP_MOD_8023 << 8) | LLDP_8023_ADD_ETH_CAPS, ++ .name = "Additional Ethernet Capabilities TLV", ++ .key = "addEthCaps", ++ .print_info = print_add_eth_caps, }, + { .type = INVALID_TLVID, } + }; + +@@ -447,6 +453,26 @@ void print_mtu(UNUSED u16 len, char *info) + printf("%d\n", mtu); + } + ++void print_add_eth_caps(u16 len, char *info) ++{ ++ u8 add_frag_size; ++ u8 buf[2] = {}; ++ u16 preempt; ++ ++ hexstr2bin(info, buf, MIN(len, 2)); ++ preempt = ntohs(*((u16 *)buf)); ++ add_frag_size = LLDP_8023_ADD_ETH_CAPS_ADD_FRAG_SIZE_X(preempt); ++ ++ printf("Preemption capability %ssupported\n", ++ (preempt & LLDP_8023_ADD_ETH_CAPS_PREEMPT_SUPPORT) ? "" : "not "); ++ printf("\tPreemption capability %senabled\n", ++ (preempt & LLDP_8023_ADD_ETH_CAPS_PREEMPT_STATUS) ? "" : "not "); ++ printf("\tPreemption capability %sactive\n", ++ (preempt & LLDP_8023_ADD_ETH_CAPS_PREEMPT_ACTIVE) ? "" : "not "); ++ printf("\tAdditional fragment size: %d (%d octets)\n", ++ add_frag_size, ethtool_mm_frag_size_add_to_min(add_frag_size)); ++} ++ + /* return 1: if it printed the TLV + * 0: if it did not + */ +diff --git a/lldp_8023_cmds.c b/lldp_8023_cmds.c +index c175ce09e32b..3253f11f81a0 100644 +--- a/lldp_8023_cmds.c ++++ b/lldp_8023_cmds.c +@@ -24,7 +24,9 @@ + + *******************************************************************************/ + ++#include + #include ++#include + #include + #include + #include +@@ -35,6 +37,7 @@ + #include "lldp_8023.h" + #include "lldp_mand_clif.h" + #include "lldp_8023_clif.h" ++#include "lldp_8023_cmds.h" + #include "lldp/ports.h" + #include "libconfig.h" + #include "config.h" +@@ -42,11 +45,18 @@ + #include "lldpad_status.h" + #include "lldp/states.h" + ++static int get_arg_add_frag_size(struct cmd *, char *, char *, char *, int); ++static int set_arg_add_frag_size(struct cmd *, char *, char *, char *, int); ++static int test_arg_add_frag_size(struct cmd *, char *, char *, char *, int); + static int get_arg_tlvtxenable(struct cmd *, char *, char *, char *, int); + static int set_arg_tlvtxenable(struct cmd *, char *, char *, char *, int); + static int test_arg_tlvtxenable(struct cmd *, char *, char *, char *, int); + + static struct arg_handlers arg_handlers[] = { ++ { .arg = ARG_8023_ADD_FRAG_SIZE, .arg_class = TLV_ARG, ++ .handle_get = get_arg_add_frag_size, ++ .handle_set = set_arg_add_frag_size, ++ .handle_test = test_arg_add_frag_size, }, + { .arg = ARG_TLVTXENABLE, .arg_class = TLV_ARG, + .handle_get = get_arg_tlvtxenable, + .handle_set = set_arg_tlvtxenable, +@@ -70,6 +80,7 @@ get_arg_tlvtxenable(struct cmd *cmd, char *arg, UNUSED char *argvalue, + case (LLDP_MOD_8023 << 8) | LLDP_8023_POWER_VIA_MDI: + case (LLDP_MOD_8023 << 8) | LLDP_8023_LINK_AGGREGATION: + case (LLDP_MOD_8023 << 8) | LLDP_8023_MAXIMUM_FRAME_SIZE: ++ case (LLDP_MOD_8023 << 8) | LLDP_8023_ADD_ETH_CAPS: + snprintf(arg_path, sizeof(arg_path), "%s%08x.%s", + TLVID_PREFIX, cmd->tlvid, arg); + +@@ -108,6 +119,7 @@ static int _set_arg_tlvtxenable(struct cmd *cmd, char *arg, char *argvalue, + case (LLDP_MOD_8023 << 8) | LLDP_8023_POWER_VIA_MDI: + case (LLDP_MOD_8023 << 8) | LLDP_8023_LINK_AGGREGATION: + case (LLDP_MOD_8023 << 8) | LLDP_8023_MAXIMUM_FRAME_SIZE: ++ case (LLDP_MOD_8023 << 8) | LLDP_8023_ADD_ETH_CAPS: + break; + case INVALID_TLVID: + return cmd_invalid; +@@ -150,6 +162,96 @@ static int test_arg_tlvtxenable(struct cmd *cmd, char *arg, char *argvalue, + return _set_arg_tlvtxenable(cmd, arg, argvalue, obuf, obuf_len, true); + } + ++static int get_arg_add_frag_size(struct cmd *cmd, char *arg, ++ UNUSED char *argvalue, char *obuf, ++ int obuf_len) ++{ ++ int add_frag_size, err; ++ char arg_path[256]; ++ ++ if (cmd->cmd != cmd_gettlv) ++ return cmd_invalid; ++ ++ switch (cmd->tlvid) { ++ case (LLDP_MOD_8023 << 8) | LLDP_8023_ADD_ETH_CAPS: ++ break; ++ case INVALID_TLVID: ++ return cmd_invalid; ++ default: ++ return cmd_not_applicable; ++ } ++ ++ snprintf(arg_path, sizeof(arg_path), "%s%08x.%s", TLVID_PREFIX, ++ cmd->tlvid, arg); ++ ++ err = get_config_setting(cmd->ifname, cmd->type, arg_path, ++ &add_frag_size, CONFIG_TYPE_INT); ++ ++ if (!err) ++ snprintf(obuf, obuf_len, "%02x%s%04x%i", ++ (unsigned int) strlen(arg), arg, 1, add_frag_size); ++ else ++ snprintf(obuf, obuf_len, "%02x%s%04d", ++ (unsigned int) strlen(arg), arg, 0); ++ ++ return cmd_success; ++} ++ ++static int _set_arg_add_frag_size(struct cmd *cmd, char *arg, char *argvalue, ++ char *obuf, int obuf_len, bool test) ++{ ++ char arg_path[256]; ++ int add_frag_size; ++ unsigned long val; ++ ++ if (cmd->cmd != cmd_settlv) ++ return cmd_invalid; ++ ++ switch (cmd->tlvid) { ++ case (LLDP_MOD_8023 << 8) | LLDP_8023_ADD_ETH_CAPS: ++ break; ++ case INVALID_TLVID: ++ return cmd_invalid; ++ default: ++ return cmd_not_applicable; ++ } ++ ++ errno = 0; ++ val = strtoul(argvalue, NULL, 0); ++ if (errno || val >= 4) ++ return cmd_invalid; ++ ++ add_frag_size = val; ++ ++ if (test) ++ return cmd_success; ++ ++ snprintf(obuf, obuf_len, "%s = %d\n", arg, add_frag_size); ++ ++ snprintf(arg_path, sizeof(arg_path), "%s%08x.%s", TLVID_PREFIX, ++ cmd->tlvid, arg); ++ set_config_setting(cmd->ifname, cmd->type, arg_path, &add_frag_size, ++ CONFIG_TYPE_INT); ++ printf("arg_path \"%s\"\n", arg_path); ++ somethingChangedLocal(cmd->ifname, cmd->type); ++ ++ return cmd_success; ++} ++ ++static int set_arg_add_frag_size(struct cmd *cmd, char *arg, char *argvalue, ++ char *obuf, int obuf_len) ++{ ++ return _set_arg_add_frag_size(cmd, arg, argvalue, obuf, obuf_len, ++ false); ++} ++ ++static int test_arg_add_frag_size(struct cmd *cmd, char *arg, char *argvalue, ++ char *obuf, int obuf_len) ++{ ++ return _set_arg_add_frag_size(cmd, arg, argvalue, obuf, obuf_len, ++ true); ++} ++ + struct arg_handlers *ieee8023_get_arg_handlers() + { + return &arg_handlers[0]; +diff --git a/lldp_dcbx.c b/lldp_dcbx.c +index 4b555cc84d7d..850292cf0d40 100644 +--- a/lldp_dcbx.c ++++ b/lldp_dcbx.c +@@ -360,8 +360,8 @@ static void dcbx_free_data(struct dcbd_user_data *dud) + + struct lldp_module * dcbx_register(void) + { +- struct lldp_module *mod; +- struct dcbd_user_data *dud; ++ struct lldp_module *mod = NULL; ++ struct dcbd_user_data *dud = NULL; + int dcbx_version; + int i; + +@@ -385,7 +385,6 @@ struct lldp_module * dcbx_register(void) + } + dud = malloc(sizeof(*dud)); + if (!dud) { +- free(mod); + LLDPAD_ERR("failed to malloc LLDP DCBX module user data\n"); + goto out_err; + } +@@ -431,6 +430,8 @@ struct lldp_module * dcbx_register(void) + LLDPAD_DBG("%s: dcbx register done\n", __func__); + return mod; + out_err: ++ free(mod); ++ free(dud); + LLDPAD_DBG("%s: dcbx register failed\n", __func__); + return NULL; + } +diff --git a/lldp_dcbx_nl.c b/lldp_dcbx_nl.c +index 002944217ce0..f9a640590460 100644 +--- a/lldp_dcbx_nl.c ++++ b/lldp_dcbx_nl.c +@@ -279,7 +279,8 @@ static int get_state(char *ifname, __u8 *state) + NLMSG_ALIGN(sizeof(struct dcbmsg))); + + if (d->cmd != DCB_CMD_GSTATE) { +- return -EIO; ++ rval = -EIO; ++ goto out; + } + if (rta->rta_type != DCB_ATTR_STATE) { + rval = -EIO; +@@ -287,8 +288,8 @@ static int get_state(char *ifname, __u8 *state) + *state = *(__u8 *)NLA_DATA(rta); + } + ++out: + free(nlh); +- + return rval; + } + +@@ -493,11 +494,15 @@ int get_dcb_capabilities(char *ifname, + rta_parent = (struct rtattr *)(((char *)d) + + NLMSG_ALIGN(sizeof(struct dcbmsg))); + +- if (d->cmd != DCB_CMD_GCAP) +- return -EIO; ++ if (d->cmd != DCB_CMD_GCAP) { ++ rval = -EIO; ++ goto out; ++ } + +- if (rta_parent->rta_type != DCB_ATTR_CAP) +- return -EIO; ++ if (rta_parent->rta_type != DCB_ATTR_CAP) { ++ rval = -EIO; ++ goto out; ++ } + + rta_child = NLA_DATA(rta_parent); + rta_parent = (struct rtattr *)((char *)rta_parent + +@@ -540,6 +545,7 @@ int get_dcb_capabilities(char *ifname, + if (rta_parent != rta_child) + LLDPAD_DBG("rta pointers are off\n"); + ++out: + free(nlh); + return rval; + } +@@ -580,11 +586,15 @@ int get_dcb_numtcs(const char *ifname, u8 *pgtcs, u8 *pfctcs) + rta_parent = (struct rtattr *)(((char *)d) + + NLMSG_ALIGN(sizeof(struct dcbmsg))); + +- if (d->cmd != DCB_CMD_GNUMTCS) +- return -EIO; ++ if (d->cmd != DCB_CMD_GNUMTCS) { ++ rval = -EIO; ++ goto out; ++ } + +- if (rta_parent->rta_type != DCB_ATTR_NUMTCS) +- return -EIO; ++ if (rta_parent->rta_type != DCB_ATTR_NUMTCS) { ++ rval = -EIO; ++ goto out; ++ } + + rta_child = NLA_DATA(rta_parent); + rta_parent = (struct rtattr *)((char *)rta_parent + +@@ -618,9 +628,10 @@ int get_dcb_numtcs(const char *ifname, u8 *pgtcs, u8 *pfctcs) + if (rta_parent != rta_child) + LLDPAD_DBG("rta pointers are off\n"); + +- free(nlh); + if (found != 3) + rval = -EIO; ++out: ++ free(nlh); + return rval; + } + +diff --git a/lldp_ethtool.c b/lldp_ethtool.c +new file mode 100644 +index 000000000000..10b1b479fd89 +--- /dev/null ++++ b/lldp_ethtool.c +@@ -0,0 +1,355 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* Copyright 2023 NXP */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "lldp.h" ++#include "lldp_ethtool.h" ++#include "messages.h" ++ ++struct ethtool_sock { ++ struct nl_sock *nlsk; ++ int family_id; ++}; ++ ++struct ethtool_sock *ethtool_sock_create(void) ++{ ++ struct ethtool_sock *sk; ++ int err, opt; ++ ++ sk = calloc(1, sizeof(*sk)); ++ if (!sk) { ++ LLDPAD_ERR("Failed to allocate ethtool socket\n"); ++ return NULL; ++ } ++ ++ sk->nlsk = nl_socket_alloc(); ++ if (!sk->nlsk) { ++ LLDPAD_ERR("Failed to allocate netlink socket\n"); ++ goto out_free_sk; ++ } ++ ++ err = genl_connect(sk->nlsk); ++ if (err) { ++ LLDPAD_ERR("Failed to connect to netlink socket: %d\n", err); ++ goto out_free_nls; ++ } ++ ++ err = genl_ctrl_resolve(sk->nlsk, ETHTOOL_GENL_NAME); ++ if (err < 0) { ++ LLDPAD_ERR("Failed to resolve ethtool genl family id: %d\n", ++ err); ++ goto out_close; ++ } ++ ++ sk->family_id = err; ++ ++ /* try to set NETLINK_EXT_ACK to 1, ignoring errors */ ++ opt = 1; ++ setsockopt(nl_socket_get_fd(sk->nlsk), SOL_NETLINK, ++ NETLINK_EXT_ACK, &opt, sizeof(opt)); ++ ++ /* try to set NETLINK_CAP_ACK to 1, ignoring errors */ ++ opt = 1; ++ setsockopt(nl_socket_get_fd(sk->nlsk), SOL_NETLINK, ++ NETLINK_CAP_ACK, &opt, sizeof(opt)); ++ ++ return sk; ++ ++out_close: ++ nl_close(sk->nlsk); ++out_free_nls: ++ nl_socket_free(sk->nlsk); ++out_free_sk: ++ free(sk); ++ return NULL; ++} ++ ++void ethtool_sock_destroy(struct ethtool_sock *sk) ++{ ++ nl_close(sk->nlsk); ++ nl_socket_free(sk->nlsk); ++ free(sk); ++} ++ ++static struct nl_msg *ethtool_nlmsg_create(struct ethtool_sock *sk, int cmd, ++ int header_type, const char *ifname) ++{ ++ struct nlmsghdr *hdr; ++ struct nlattr *attr; ++ struct nl_msg *nlm; ++ ++ nlm = nlmsg_alloc(); ++ if (!nlm) { ++ LLDPAD_ERR("Failed to allocate netlink message\n"); ++ return NULL; ++ } ++ ++ hdr = genlmsg_put(nlm, NL_AUTO_PORT, NL_AUTO_SEQ, sk->family_id, 0, ++ NLM_F_REQUEST | NLM_F_ACK, cmd, ETHTOOL_GENL_VERSION); ++ if (!hdr) { ++ LLDPAD_ERR("genlmsg_put() failed\n"); ++ goto out_free_nlmsg; ++ } ++ ++ attr = nla_nest_start(nlm, header_type); ++ nla_put_string(nlm, ETHTOOL_A_HEADER_DEV_NAME, ifname); ++ nla_nest_end(nlm, attr); ++ ++ return nlm; ++ ++out_free_nlmsg: ++ nlmsg_free(nlm); ++ return NULL; ++} ++ ++static struct nla_policy ethtool_mm_genl_policy[ETHTOOL_A_MM_MAX + 1] = { ++ [ETHTOOL_A_MM_UNSPEC] = { .type = NLA_UNSPEC }, ++ [ETHTOOL_A_MM_HEADER] = { .type = NLA_NESTED }, ++ [ETHTOOL_A_MM_VERIFY_STATUS] = { .type = NLA_U8 }, ++ [ETHTOOL_A_MM_VERIFY_ENABLED] = { .type = NLA_U8 }, ++ [ETHTOOL_A_MM_VERIFY_TIME] = { .type = NLA_U32 }, ++ [ETHTOOL_A_MM_MAX_VERIFY_TIME] = { .type = NLA_U32 }, ++ [ETHTOOL_A_MM_TX_ENABLED] = { .type = NLA_U8 }, ++ [ETHTOOL_A_MM_TX_ACTIVE] = { .type = NLA_U8 }, ++ [ETHTOOL_A_MM_PMAC_ENABLED] = { .type = NLA_U8 }, ++ [ETHTOOL_A_MM_TX_MIN_FRAG_SIZE] = { .type = NLA_U32 }, ++ [ETHTOOL_A_MM_RX_MIN_FRAG_SIZE] = { .type = NLA_U32 }, ++ [ETHTOOL_A_MM_STATS] = { .type = NLA_NESTED }, ++}; ++ ++/* Reply callback for requests where no reply is expected (e.g. most "set" type ++ * commands) ++ */ ++static int ethtool_nomsg_reply_cb(struct nl_msg *nlm, UNUSED void *arg) ++{ ++ struct nlmsghdr *nlhdr = nlmsg_hdr(nlm); ++ struct genlmsghdr *ghdr = nlmsg_data(nlhdr); ++ ++ LLDPAD_ERR("received unexpected message: len=%u type=%u cmd=%u\n", ++ nlhdr->nlmsg_len, nlhdr->nlmsg_type, ghdr->cmd); ++ ++ return NL_STOP; ++} ++ ++static int error_handler(UNUSED struct sockaddr_nl *nla, struct nlmsgerr *err, ++ void *arg) ++{ ++ struct nlmsghdr *nlh = (struct nlmsghdr *) err - 1; ++ int ack_len = sizeof(*nlh) + sizeof(int) + sizeof(*nlh); ++ struct nlattr *tb[NLMSGERR_ATTR_MAX + 1]; ++ int len = nlh->nlmsg_len; ++ struct nlattr *attrs; ++ int *ret = arg; ++ ++ *ret = err->error; ++ ++ if (!(nlh->nlmsg_flags & NLM_F_ACK_TLVS)) ++ return NL_SKIP; ++ ++ if (!(nlh->nlmsg_flags & NLM_F_CAPPED)) ++ ack_len += err->msg.nlmsg_len - sizeof(*nlh); ++ ++ if (len <= ack_len) ++ return NL_STOP; ++ ++ attrs = (void *) ((unsigned char *) nlh + ack_len); ++ len -= ack_len; ++ ++ nla_parse(tb, NLMSGERR_ATTR_MAX, attrs, len, NULL); ++ if (tb[NLMSGERR_ATTR_MSG]) { ++ len = strnlen((char *) nla_data(tb[NLMSGERR_ATTR_MSG]), ++ nla_len(tb[NLMSGERR_ATTR_MSG])); ++ LLDPAD_ERR("ethtool: kernel reports: %*s\n", ++ len, (char *) nla_data(tb[NLMSGERR_ATTR_MSG])); ++ } ++ ++ return NL_SKIP; ++} ++ ++static int ack_handler(UNUSED struct nl_msg *msg, void *arg) ++{ ++ int *err = arg; ++ *err = 0; ++ return NL_STOP; ++} ++ ++static int ethtool_msg_mm_get_parse(struct nl_msg *nlm, void *arg) ++{ ++ struct genlmsghdr *hdr = nlmsg_data(nlmsg_hdr(nlm)); ++ struct nlattr *tb[ETHTOOL_A_MM_MAX + 1]; ++ struct ethtool_mm *mm = arg; ++ ++ if (nla_parse(tb, ETHTOOL_A_MM_MAX, genlmsg_attrdata(hdr, 0), ++ genlmsg_attrlen(hdr, 0), ethtool_mm_genl_policy)) { ++ printf("nla_parse() failed\n"); ++ return NL_STOP; ++ } ++ ++ if (tb[ETHTOOL_A_MM_VERIFY_STATUS]) ++ mm->verify_status = nla_get_u8(tb[ETHTOOL_A_MM_VERIFY_STATUS]); ++ ++ if (tb[ETHTOOL_A_MM_VERIFY_TIME]) ++ mm->verify_time = nla_get_u32(tb[ETHTOOL_A_MM_VERIFY_TIME]); ++ ++ if (tb[ETHTOOL_A_MM_MAX_VERIFY_TIME]) ++ mm->max_verify_time = ++ nla_get_u32(tb[ETHTOOL_A_MM_MAX_VERIFY_TIME]); ++ ++ if (tb[ETHTOOL_A_MM_TX_ENABLED]) ++ mm->tx_enabled = nla_get_u8(tb[ETHTOOL_A_MM_TX_ENABLED]); ++ ++ if (tb[ETHTOOL_A_MM_TX_ACTIVE]) ++ mm->tx_active = nla_get_u8(tb[ETHTOOL_A_MM_TX_ACTIVE]); ++ ++ if (tb[ETHTOOL_A_MM_PMAC_ENABLED]) ++ mm->pmac_enabled = nla_get_u8(tb[ETHTOOL_A_MM_PMAC_ENABLED]); ++ ++ if (tb[ETHTOOL_A_MM_VERIFY_ENABLED]) ++ mm->verify_enabled = nla_get_u8(tb[ETHTOOL_A_MM_VERIFY_ENABLED]); ++ ++ if (tb[ETHTOOL_A_MM_TX_MIN_FRAG_SIZE]) ++ mm->tx_min_frag_size = nla_get_u32(tb[ETHTOOL_A_MM_TX_MIN_FRAG_SIZE]); ++ ++ if (tb[ETHTOOL_A_MM_RX_MIN_FRAG_SIZE]) ++ mm->rx_min_frag_size = nla_get_u32(tb[ETHTOOL_A_MM_RX_MIN_FRAG_SIZE]); ++ ++ return NL_OK; ++} ++ ++static int ethtool_genl_txrx(struct ethtool_sock *sk, struct nl_msg *nlm, ++ nl_recvmsg_msg_cb_t func, void *arg) ++{ ++ struct nl_cb *cb = NULL, *orig; ++ int err, ret; ++ ++ orig = nl_socket_get_cb(sk->nlsk); ++ if (!orig) { ++ LLDPAD_ERR("nl_socket_get_cb() failed\n"); ++ return -ENOMEM; ++ } ++ ++ cb = nl_cb_clone(orig); ++ if (!cb) { ++ LLDPAD_ERR("nl_cb_clone() failed\n"); ++ err = -ENOMEM; ++ goto err_put_orig; ++ } ++ ++ nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, func, arg); ++ nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err); ++ nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err); ++ ++ err = nl_send_auto(sk->nlsk, nlm); ++ if (err < 0) { ++ LLDPAD_ERR("nl_send_auto() failed: %d (%s)\n", err, ++ nl_geterror(err)); ++ goto err_put_cb; ++ } ++ ++ err = 1; ++ ++ /* Wait until the ack_handler() has executed */ ++ while (err > 0) { ++ ret = nl_recvmsgs(sk->nlsk, cb); ++ if (ret < 0) { ++ LLDPAD_ERR("nl_recvmsgs_default() failed: %d (%s)\n", ++ ret, nl_geterror(ret)); ++ err = ret; ++ goto err_put_cb; ++ } ++ } ++ ++ nl_cb_put(cb); ++ nl_cb_put(orig); ++ ++ return 0; ++ ++err_put_cb: ++ nl_cb_put(cb); ++err_put_orig: ++ nl_cb_put(orig); ++ return err; ++} ++ ++int ethtool_mm_get_state(struct ethtool_sock *sk, const char *ifname, ++ struct ethtool_mm *mm) ++{ ++ struct nl_msg *nlm; ++ int err; ++ ++ nlm = ethtool_nlmsg_create(sk, ETHTOOL_MSG_MM_GET, ETHTOOL_A_MM_HEADER, ++ ifname); ++ if (!nlm) ++ return -ENOMEM; ++ ++ memset(mm, 0, sizeof(*mm)); ++ ++ err = ethtool_genl_txrx(sk, nlm, ethtool_msg_mm_get_parse, mm); ++ nlmsg_free(nlm); ++ ++ return err; ++} ++ ++int ethtool_mm_change_tx_enabled(struct ethtool_sock *sk, const char *ifname, ++ bool enabled, bool verify, u32 verify_time) ++{ ++ struct nl_msg *nlm; ++ int err; ++ ++ nlm = ethtool_nlmsg_create(sk, ETHTOOL_MSG_MM_SET, ETHTOOL_A_MM_HEADER, ++ ifname); ++ if (!nlm) ++ return -ENOMEM; ++ ++ nla_put_u8(nlm, ETHTOOL_A_MM_TX_ENABLED, enabled); ++ nla_put_u8(nlm, ETHTOOL_A_MM_VERIFY_ENABLED, verify); ++ nla_put_u32(nlm, ETHTOOL_A_MM_VERIFY_TIME, verify_time); ++ ++ err = ethtool_genl_txrx(sk, nlm, ethtool_nomsg_reply_cb, NULL); ++ nlmsg_free(nlm); ++ ++ return err; ++} ++ ++int ethtool_mm_change_pmac_enabled(struct ethtool_sock *sk, const char *ifname, ++ bool enabled) ++{ ++ struct nl_msg *nlm; ++ int err; ++ ++ nlm = ethtool_nlmsg_create(sk, ETHTOOL_MSG_MM_SET, ETHTOOL_A_MM_HEADER, ++ ifname); ++ if (!nlm) ++ return -ENOMEM; ++ ++ nla_put_u8(nlm, ETHTOOL_A_MM_PMAC_ENABLED, enabled); ++ ++ err = ethtool_genl_txrx(sk, nlm, ethtool_nomsg_reply_cb, NULL); ++ nlmsg_free(nlm); ++ ++ return err; ++} ++ ++int ethtool_mm_change_tx_min_frag_size(struct ethtool_sock *sk, ++ const char *ifname, u32 min_frag_size) ++{ ++ struct nl_msg *nlm; ++ int err; ++ ++ nlm = ethtool_nlmsg_create(sk, ETHTOOL_MSG_MM_SET, ETHTOOL_A_MM_HEADER, ++ ifname); ++ if (!nlm) ++ return -ENOMEM; ++ ++ nla_put_u32(nlm, ETHTOOL_A_MM_TX_MIN_FRAG_SIZE, min_frag_size); ++ ++ err = ethtool_genl_txrx(sk, nlm, ethtool_nomsg_reply_cb, NULL); ++ nlmsg_free(nlm); ++ ++ return err; ++} +diff --git a/lldp_util.c b/lldp_util.c +index be1333e674dc..d0e82643def1 100644 +--- a/lldp_util.c ++++ b/lldp_util.c +@@ -1092,7 +1092,8 @@ int get_ipaddrstr(const char *ifname, char *ipaddr, size_t size) + rc = get_saddr(ifname, &sa); + if (rc == 0) { + memset(ipaddr, 0, size); +- strncpy(ipaddr, inet_ntoa(sa.sin_addr), size); ++ if (inet_ntop(AF_INET, &sa.sin_addr, ipaddr, size) == NULL) ++ rc = errno; + } + return rc; + } +@@ -1279,16 +1280,16 @@ int get_arg_val_list(char *ibuf, int ilen, int *ioff, + p = (int *) realloc(arglens, + (i/NUM_ARGS + 1) * NUM_ARGS * sizeof(int)); + if (!p) { +- free(arglens); +- return 0; ++ numargs = 0; ++ goto out; + } else { + arglens = p; + } + p = (int *) realloc(argvallens, + (i/NUM_ARGS + 1) * NUM_ARGS * sizeof(int)); + if (!p) { +- free(argvallens); +- return 0; ++ numargs = 0; ++ goto out; + } else { + argvallens = p; + } +@@ -1311,14 +1312,12 @@ int get_arg_val_list(char *ibuf, int ilen, int *ioff, + *(argvallens+i) = argvalue_len; + } + } else { +- free(arglens); +- free(argvallens); +- return 0; ++ numargs = 0; ++ goto out; + } + } else { +- free(arglens); +- free(argvallens); +- return 0; ++ numargs = 0; ++ goto out; + } + } + numargs = i; +@@ -1326,6 +1325,8 @@ int get_arg_val_list(char *ibuf, int ilen, int *ioff, + args[i][*(arglens+i)] = '\0'; + argvals[i][*(argvallens+i)] = '\0'; + } ++ ++out: + free(arglens); + free(argvallens); + return numargs; +diff --git a/lldptool_cmds.c b/lldptool_cmds.c +index cff923a9c312..a6cf7f1d5fff 100644 +--- a/lldptool_cmds.c ++++ b/lldptool_cmds.c +@@ -540,7 +540,7 @@ void print_cmd_response(char *ibuf, int status) + if (len < sizeof(cmd.ifname)) { + memcpy(cmd.ifname, ibuf+CMD_IF, len); + } else { +- printf("Response ifname too long: %*s\n", (int)len, cmd.ifname); ++ printf("Response ifname too long: %*s\n", (int)len, ibuf + CMD_IF); + return; + } + cmd.ifname[len] = '\0'; +diff --git a/m4/openlldp.m4 b/m4/openlldp.m4 +index 0d358e307191..f7834cc4f31b 100644 +--- a/m4/openlldp.m4 ++++ b/m4/openlldp.m4 +@@ -31,6 +31,19 @@ AC_DEFUN([_CHECK_C_COMPILER_FLAG], [ + AC_LANG_POP() + ]) + ++AC_DEFUN([_CHECK_C_LINK_FLAG], [ ++ AC_LANG_PUSH([C]) ++ AC_MSG_CHECKING(for $CC support of $1) ++ old_LDFLAGS="$LDFLAGS" ++ LDFLAGS="$LDFLAGS $1" ++ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])], ++ AC_MSG_RESULT(yes), ++ AC_MSG_RESULT(no) ++ LDFLAGS="$old_LDFLAGS") ++ AC_LANG_POP() ++]) ++ ++ + dnl Check for the various warning flags + AC_DEFUN([OPENLLDP_CHECK_WARNINGS], [ + AC_MSG_CHECKING([checking for warnings flag]) +@@ -64,3 +77,35 @@ AC_DEFUN([OPENLLDP_CHECK_ERROR], [ + _CHECK_C_COMPILER_FLAG([-Werror]) + ]) + ]) ++ ++dnl Set up undefined sanitizer ++AC_DEFUN([OPENLLDP_CHECK_UBSAN], ++ [AC_MSG_CHECKING([checking for ubsan]) ++ AC_ARG_ENABLE([ubsan], ++ AS_HELP_STRING([--enable-ubsan], ++ [Build with undefined behavior sanitizer]), [ubsan=$enableval], [ubsan=no]) ++ AM_CONDITIONAL([UBSAN_ENABLED], [test "x$ubsan" = "xyes"]) ++ AC_SUBST([UBSAN_ENABLED], [$ubsan]) ++ AC_MSG_RESULT($ubsan) ++ ++ AS_IF([ test "x$ubsan" = "xyes"], [ ++ _CHECK_C_COMPILER_FLAG([-fsanitize=undefined]) ++ _CHECK_C_LINK_FLAG([-fsanitize=undefined]) ++ ]) ++]) ++ ++dnl Set up address sanitizer ++AC_DEFUN([OPENLLDP_CHECK_ASAN], ++ [AC_MSG_CHECKING([checking for asan]) ++ AC_ARG_ENABLE([asan], ++ AS_HELP_STRING([--enable-asan], ++ [Build with address sanitizer]), [asan=$enableval], [asan=no]) ++ AM_CONDITIONAL([ASAN_ENABLED], [test "x$asan" = "xyes"]) ++ AC_SUBST([ASAN_ENABLED], [$asan]) ++ AC_MSG_RESULT($asan) ++ ++ AS_IF([ test "x$asan" = "xyes"], [ ++ _CHECK_C_COMPILER_FLAG([-fsanitize=address]) ++ _CHECK_C_LINK_FLAG([-fsanitize=address]) ++ ]) ++]) +diff --git a/qbg/ecp.c b/qbg/ecp.c +index d1c68318c7af..0445819b3d22 100644 +--- a/qbg/ecp.c ++++ b/qbg/ecp.c +@@ -969,9 +969,9 @@ static void ecp_rx_ProcessFrame(struct vdp_data *vd) + if ((tlv->type != TYPE_0) && !tlv_stored) { + LLDPAD_DBG("%s:%s TLV (%u) was not stored (%p)\n", + __func__, vd->ecp.ifname, tlv->type, tlv); +- free_unpkd_tlv(tlv); + vd->ecp.stats.statsTLVsUnrecognizedTotal++; + } ++ free_unpkd_tlv(tlv); + tlv = NULL; + tlv_stored = false; + } while (tlv_offset < vd->ecp.rx.frame_len); +diff --git a/qbg/ecp22.c b/qbg/ecp22.c +index 83b2e621589e..941ebb61edb5 100644 +--- a/qbg/ecp22.c ++++ b/qbg/ecp22.c +@@ -932,25 +932,25 @@ static int ecp22_req2send(char *ifname, unsigned short subtype, + + LLDPAD_DBG("%s:%s subtype:%d\n", __func__, ifname, subtype); + +- eud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_ECP22); +- ecp = find_ecpdata(ifname, eud); +- if (!ecp) { +- rc = -ENODEV; +- goto out; +- } + if (!ptlv) { + rc = -ENOMEM; + goto out; + } + if (ptlv->size >= ECP22_MAXPAYLOAD_LEN) { + rc = -E2BIG; +- goto out; ++ goto err_out; ++ } ++ ++ eud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_ECP22); ++ ecp = find_ecpdata(ifname, eud); ++ if (!ecp) { ++ rc = -ENODEV; ++ goto err_out; + } + payda = ecp22_getnode(&ecp->isfree); + if (!payda) { +- free_pkd_tlv(ptlv); + rc = -ENOMEM; +- goto out; ++ goto err_out; + } + payda->ptlv = ptlv; + payda->subtype = subtype; +@@ -959,6 +959,9 @@ static int ecp22_req2send(char *ifname, unsigned short subtype, + out: + LLDPAD_DBG("%s:%s rc:%d\n", __func__, ifname, rc); + return rc; ++err_out: ++ free_pkd_tlv(ptlv); ++ goto out; + } + + /* +diff --git a/qbg/vdp22cisco_oui.c b/qbg/vdp22cisco_oui.c +index da6ce244bcce..f6e0ac619414 100644 +--- a/qbg/vdp22cisco_oui.c ++++ b/qbg/vdp22cisco_oui.c +@@ -130,13 +130,13 @@ bool cisco_str2vdpnl_hndlr(struct vdpnl_oui_data_s *vdp_oui_p, char *token) + return false; + } + strncpy(v4_addr_str, token, data_len); +- ret = inet_aton(v4_addr_str, ++ ret = inet_pton(AF_INET, v4_addr_str, + &vdp_cisco_oui_p->l3_addr.ipv4_address); + LLDPAD_DBG("V4adr %s 0x%lx\n", v4_addr_str, + (unsigned long) + vdp_cisco_oui_p->l3_addr.ipv4_address.s_addr); + free(v4_addr_str); +- if (!ret) { ++ if (ret <= 0) { + LLDPAD_ERR("%s: Incorrect addr\n", __func__); + return false; + } +diff --git a/vdptool.c b/vdptool.c +index e156cc43c07f..505ed1bfa907 100644 +--- a/vdptool.c ++++ b/vdptool.c +@@ -629,7 +629,7 @@ static void print_cmd_response(char *ibuf, int status) + if (len < sizeof(cmd.ifname)) { + memcpy(cmd.ifname, ibuf + CMD_IF, len); + } else { +- printf("Response ifname too long: %*s\n", (int)len, cmd.ifname); ++ printf("Response ifname too long: %*s\n", (int)len, ibuf + CMD_IF); + return; + } + cmd.ifname[len] = '\0'; +diff --git a/vdptool_cisco_oui.c b/vdptool_cisco_oui.c +index 3f88c764617c..da3baecb7843 100644 +--- a/vdptool_cisco_oui.c ++++ b/vdptool_cisco_oui.c +@@ -66,6 +66,7 @@ void cisco_oui_print_decode_hndlr(char *token) + u16 data_len; + u8 key_len; + enum oui_key_arg oui_argtype; ++ char addr[INET_ADDRSTRLEN]; + + if (token == NULL) + return; +@@ -99,8 +100,10 @@ void cisco_oui_print_decode_hndlr(char *token) + strncpy(v4_addr_str, token, data_len); + vm_ip_addr = strtoul(v4_addr_str, NULL, 10); + vm_inet.s_addr = vm_ip_addr; ++ if (inet_ntop(AF_INET, &vm_inet, addr, INET_ADDRSTRLEN) == NULL) ++ return; + printf("\t%s", "VM IP Address"); +- printf(" = %s\n", inet_ntoa(vm_inet)); ++ printf(" = %s\n", addr); + free(v4_addr_str); + break; + default: diff --git a/lldpad.spec b/lldpad.spec index 15c8da8..30f5132 100644 --- a/lldpad.spec +++ b/lldpad.spec @@ -7,17 +7,21 @@ %global branch branch-1.1 %global commit f1dd9eb961fab06723d2bedb2f7e2b81e45ee9ab %global shortcommit %(c=%{commit}; echo ${c:0:7}) -%global forgesetupargs -n openlldp-%{version} +%global forgesetupargs -n openlldp-%{version} -p1 Name: lldpad Version: 1.1.1 -Release: 2.git%{shortcommit}%{?dist} +Release: 3.git%{shortcommit}%{?dist} Summary: Intel LLDP Agent %forgemeta License: GPL-2.0-only URL: %{forgeurl} Source0: %{forgesource}#/%{name}-%{version}.tar.gz +# This is the upgrade package to latest upstream +# When 1.1.2 or later is released, simply remove this +# patch and generate a new one. +Patch1: 0001-patch-to-latest.patch BuildRequires: automake autoconf BuildRequires: flex @@ -92,6 +96,14 @@ rm -f %{buildroot}%{_libdir}/liblldp_clif.la %{_libdir}/liblldp_clif.so %changelog +* Mon Sep 9 2024 Hangbin Liu - 1.1.1-3.gitf1dd9eb +- Rebase to latest upstream code +- Remove interface configure if the interface deleted (RHEL-13242) +- Fix strdup is not freed (RHEL-37524) +- Fix using uninitialized value (RHEL-37548) +- Fix copy past error (RHEL-37679) +- Fix resource leak (RHEL-37685) + * Wed Sep 4 2024 Hangbin Liu - 1.1.1-2.gitf1dd9eb - Update gating test