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: