Commit 459e0b81 authored by Michal Kubecek's avatar Michal Kubecek Committed by David S. Miller
Browse files

ethtool: provide link settings with LINKINFO_GET request



Implement LINKINFO_GET netlink request to get basic link settings provided
by ETHTOOL_GLINKSETTINGS and ETHTOOL_GSET ioctl commands.

This request provides settings not directly related to autonegotiation and
link mode selection: physical port, phy MDIO address, MDI(-X) status,
MDI(-X) control and transceiver.

LINKINFO_GET request can be used with NLM_F_DUMP (without device
identification) to request the information for all devices in current
network namespace providing the data.

Signed-off-by: default avatarMichal Kubecek <mkubecek@suse.cz>
Reviewed-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 71921690
Loading
Loading
Loading
Loading
+35 −2
Original line number Diff line number Diff line
@@ -180,12 +180,14 @@ Userspace to kernel:

  ===================================== ================================
  ``ETHTOOL_MSG_STRSET_GET``            get string set
  ``ETHTOOL_MSG_LINKINFO_GET``          get link settings
  ===================================== ================================

Kernel to userspace:

  ===================================== ================================
  ``ETHTOOL_MSG_STRSET_GET_REPLY``      string set contents
  ``ETHTOOL_MSG_LINKINFO_GET_REPLY``    link settings
  ===================================== ================================

``GET`` requests are sent by userspace applications to retrieve device
@@ -278,6 +280,37 @@ Flag ``ETHTOOL_A_STRSET_COUNTS_ONLY`` tells kernel to only return string
counts of the sets, not the actual strings.


LINKINFO_GET
============

Requests link settings as provided by ``ETHTOOL_GLINKSETTINGS`` except for
link modes and autonegotiation related information. The request does not use
any attributes.

Request contents:

  ====================================  ======  ==========================
  ``ETHTOOL_A_LINKINFO_HEADER``         nested  request header
  ====================================  ======  ==========================

Kernel response contents:

  ====================================  ======  ==========================
  ``ETHTOOL_A_LINKINFO_HEADER``         nested  reply header
  ``ETHTOOL_A_LINKINFO_PORT``           u8      physical port
  ``ETHTOOL_A_LINKINFO_PHYADDR``        u8      phy MDIO address
  ``ETHTOOL_A_LINKINFO_TP_MDIX``        u8      MDI(-X) status
  ``ETHTOOL_A_LINKINFO_TP_MDIX_CTRL``   u8      MDI(-X) control
  ``ETHTOOL_A_LINKINFO_TRANSCEIVER``    u8      transceiver
  ====================================  ======  ==========================

Attributes and their values have the same meaning as matching members of the
corresponding ioctl structures.

``LINKINFO_GET`` allows dump requests (kernel returns reply message for all
devices supporting the request).


Request translation
===================

@@ -288,7 +321,7 @@ have their netlink replacement yet.
  =================================== =====================================
  ioctl command                       netlink command
  =================================== =====================================
  ``ETHTOOL_GSET``                    n/a
  ``ETHTOOL_GSET``                    ``ETHTOOL_MSG_LINKINFO_GET``
  ``ETHTOOL_SSET``                    n/a
  ``ETHTOOL_GDRVINFO``                n/a
  ``ETHTOOL_GREGS``                   n/a
@@ -362,7 +395,7 @@ have their netlink replacement yet.
  ``ETHTOOL_STUNABLE``                n/a
  ``ETHTOOL_GPHYSTATS``               n/a
  ``ETHTOOL_PERQUEUE``                n/a
  ``ETHTOOL_GLINKSETTINGS``           n/a
  ``ETHTOOL_GLINKSETTINGS``           ``ETHTOOL_MSG_LINKINFO_GET``
  ``ETHTOOL_SLINKSETTINGS``           n/a
  ``ETHTOOL_PHY_GTUNABLE``            n/a
  ``ETHTOOL_PHY_STUNABLE``            n/a
+18 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
enum {
	ETHTOOL_MSG_USER_NONE,
	ETHTOOL_MSG_STRSET_GET,
	ETHTOOL_MSG_LINKINFO_GET,

	/* add new constants above here */
	__ETHTOOL_MSG_USER_CNT,
@@ -25,6 +26,7 @@ enum {
enum {
	ETHTOOL_MSG_KERNEL_NONE,
	ETHTOOL_MSG_STRSET_GET_REPLY,
	ETHTOOL_MSG_LINKINFO_GET_REPLY,

	/* add new constants above here */
	__ETHTOOL_MSG_KERNEL_CNT,
@@ -141,6 +143,22 @@ enum {
	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
};

/* generic netlink info */
#define ETHTOOL_GENL_NAME "ethtool"
#define ETHTOOL_GENL_VERSION 1
+1 −1
Original line number Diff line number Diff line
@@ -4,4 +4,4 @@ obj-y += ioctl.o common.o

obj-$(CONFIG_ETHTOOL_NETLINK)	+= ethtool_nl.o

ethtool_nl-y	:= netlink.o bitset.o strset.o
ethtool_nl-y	:= netlink.o bitset.o strset.o linkinfo.o
+48 −0
Original line number Diff line number Diff line
@@ -169,3 +169,51 @@ const char link_mode_names[][ETH_GSTRING_LEN] = {
	__DEFINE_LINK_MODE_NAME(400000, CR8, Full),
};
static_assert(ARRAY_SIZE(link_mode_names) == __ETHTOOL_LINK_MODE_MASK_NBITS);

/* return false if legacy contained non-0 deprecated fields
 * maxtxpkt/maxrxpkt. rest of ksettings always updated
 */
bool
convert_legacy_settings_to_link_ksettings(
	struct ethtool_link_ksettings *link_ksettings,
	const struct ethtool_cmd *legacy_settings)
{
	bool retval = true;

	memset(link_ksettings, 0, sizeof(*link_ksettings));

	/* This is used to tell users that driver is still using these
	 * deprecated legacy fields, and they should not use
	 * %ETHTOOL_GLINKSETTINGS/%ETHTOOL_SLINKSETTINGS
	 */
	if (legacy_settings->maxtxpkt ||
	    legacy_settings->maxrxpkt)
		retval = false;

	ethtool_convert_legacy_u32_to_link_mode(
		link_ksettings->link_modes.supported,
		legacy_settings->supported);
	ethtool_convert_legacy_u32_to_link_mode(
		link_ksettings->link_modes.advertising,
		legacy_settings->advertising);
	ethtool_convert_legacy_u32_to_link_mode(
		link_ksettings->link_modes.lp_advertising,
		legacy_settings->lp_advertising);
	link_ksettings->base.speed
		= ethtool_cmd_speed(legacy_settings);
	link_ksettings->base.duplex
		= legacy_settings->duplex;
	link_ksettings->base.port
		= legacy_settings->port;
	link_ksettings->base.phy_address
		= legacy_settings->phy_address;
	link_ksettings->base.autoneg
		= legacy_settings->autoneg;
	link_ksettings->base.mdio_support
		= legacy_settings->mdio_support;
	link_ksettings->base.eth_tp_mdix
		= legacy_settings->eth_tp_mdix;
	link_ksettings->base.eth_tp_mdix_ctrl
		= legacy_settings->eth_tp_mdix_ctrl;
	return retval;
}
+4 −0
Original line number Diff line number Diff line
@@ -19,4 +19,8 @@ extern const char
phy_tunable_strings[__ETHTOOL_PHY_TUNABLE_COUNT][ETH_GSTRING_LEN];
extern const char link_mode_names[][ETH_GSTRING_LEN];

bool convert_legacy_settings_to_link_ksettings(
	struct ethtool_link_ksettings *link_ksettings,
	const struct ethtool_cmd *legacy_settings);

#endif /* _ETHTOOL_COMMON_H */
Loading