From patchwork Fri Sep 6 14:57:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Chevallier X-Patchwork-Id: 13794329 X-Patchwork-Delegate: mkubecek+ethtool@suse.cz Received: from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net [217.70.183.197]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 898DA1D1F51; Fri, 6 Sep 2024 14:57:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.197 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725634654; cv=none; b=Qx0vqt9cHS5Y6uICUimHc6GRLNr4R/sz9G2yJ8hMfksboIHymHk4TQCoAp0cuhPtV1DT1tsNk4l7FwD/p6FUpNTRnlhvYALJWsSsyPHHb+YW0dDlppZH9SzEBK/AUATMjjIccK5L450ttBBOdpNlxzB1qGuL+bGRRy8/ZH0OMGU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725634654; c=relaxed/simple; bh=PpVyvJ+6obkJ5qxezW8mKyk+C0rTLkddD4Srgus//wg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=UNthlJjvGRPVgZG//OF3CRl3+DTZ4JOpY39wSGDNfBGq6FmJZszMIwIYEGGFgkpnPlK7p+Uy0w03Wf5ZvULzNJpjKsuTDBCotBqUpt7xRywaSE2zkQfm9jiTgmtj2UAzVyc/kKt1j8W9xyuibO8MJCQeFQhg72RAUSFdl2QMpE8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=TMfa7Nh6; arc=none smtp.client-ip=217.70.183.197 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="TMfa7Nh6" Received: by mail.gandi.net (Postfix) with ESMTPSA id 56BD61C0008; Fri, 6 Sep 2024 14:57:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1725634645; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=o3/+RiR2Da19F7SNi6Bb4iuBExsu9lB2F6BMRdI3YPw=; b=TMfa7Nh691jiB1caJ0PBNE3xwUbEReF5z+zm779pM3CiQ+OVYvnNxPRQci0TAWZzJyTkcj cuHMvo3b8/GmAyqjkYf7/xskLLTwlAieTxVBXColvowI1MiYHG9dlLlijgal1FA42nUW2N Q3RAtuc92smM8LfG9ER8ctQwv0zg0Ln2Ac5D7q152oE15TYJdD/O8Qj/vnI1H51M0+Dosl vShUM/mkkLAa1NXYkmjPLEr1TSqIycttp0fRN4Bh8fid/jN8XpeASTt1NRQ0LlnJ0Cllju IDcSV1pn0cPUYkQhWmF/d0exDVD+167flupaHGuxl8HSH1MyHvydlWckaRruXg== From: Maxime Chevallier To: davem@davemloft.net, Michal Kubecek Cc: Maxime Chevallier , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, Andrew Lunn , Jakub Kicinski , Eric Dumazet , Paolo Abeni , Russell King , Christophe Leroy , Herve Codina , Florian Fainelli , Heiner Kallweit , Oleksij Rempel , Simon Horman Subject: [PATCH ethtool-next v4 1/3] update UAPI header copies Date: Fri, 6 Sep 2024 16:57:16 +0200 Message-ID: <20240906145719.387824-2-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20240906145719.387824-1-maxime.chevallier@bootlin.com> References: <20240906145719.387824-1-maxime.chevallier@bootlin.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-GND-Sasl: maxime.chevallier@bootlin.com X-Patchwork-Delegate: mkubecek+ethtool@suse.cz Update to kernel commit 7d3aed652d09. Signed-off-by: Maxime Chevallier --- uapi/linux/ethtool.h | 16 ++++++++++++++++ uapi/linux/ethtool_netlink.h | 25 +++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/uapi/linux/ethtool.h b/uapi/linux/ethtool.h index fef07da..7022fcc 100644 --- a/uapi/linux/ethtool.h +++ b/uapi/linux/ethtool.h @@ -2531,4 +2531,20 @@ struct ethtool_link_settings { * __u32 map_lp_advertising[link_mode_masks_nwords]; */ }; + +/** + * enum phy_upstream - Represents the upstream component a given PHY device + * is connected to, as in what is on the other end of the MII bus. Most PHYs + * will be attached to an Ethernet MAC controller, but in some cases, there's + * an intermediate PHY used as a media-converter, which will driver another + * MII interface as its output. + * @PHY_UPSTREAM_MAC: Upstream component is a MAC (a switch port, + * or ethernet controller) + * @PHY_UPSTREAM_PHY: Upstream component is a PHY (likely a media converter) + */ +enum phy_upstream { + PHY_UPSTREAM_MAC, + PHY_UPSTREAM_PHY, +}; + #endif /* _LINUX_ETHTOOL_H */ diff --git a/uapi/linux/ethtool_netlink.h b/uapi/linux/ethtool_netlink.h index dfc25a0..f865c7c 100644 --- a/uapi/linux/ethtool_netlink.h +++ b/uapi/linux/ethtool_netlink.h @@ -58,6 +58,7 @@ enum { ETHTOOL_MSG_MM_GET, ETHTOOL_MSG_MM_SET, ETHTOOL_MSG_MODULE_FW_FLASH_ACT, + ETHTOOL_MSG_PHY_GET, /* add new constants above here */ __ETHTOOL_MSG_USER_CNT, @@ -111,6 +112,8 @@ enum { ETHTOOL_MSG_MM_GET_REPLY, ETHTOOL_MSG_MM_NTF, ETHTOOL_MSG_MODULE_FW_FLASH_NTF, + ETHTOOL_MSG_PHY_GET_REPLY, + ETHTOOL_MSG_PHY_NTF, /* add new constants above here */ __ETHTOOL_MSG_KERNEL_CNT, @@ -134,6 +137,7 @@ enum { ETHTOOL_A_HEADER_DEV_INDEX, /* u32 */ ETHTOOL_A_HEADER_DEV_NAME, /* string */ ETHTOOL_A_HEADER_FLAGS, /* u32 - ETHTOOL_FLAG_* */ + ETHTOOL_A_HEADER_PHY_INDEX, /* u32 */ /* add new constants above here */ __ETHTOOL_A_HEADER_CNT, @@ -556,6 +560,10 @@ enum { * a regular 100 Ohm cable and a part with the abnormal impedance value */ ETHTOOL_A_CABLE_RESULT_CODE_IMPEDANCE_MISMATCH, + /* TDR not possible due to high noise level */ + ETHTOOL_A_CABLE_RESULT_CODE_NOISE, + /* TDR resolution not possible / out of distance */ + ETHTOOL_A_CABLE_RESULT_CODE_RESOLUTION_NOT_POSSIBLE, }; enum { @@ -965,6 +973,7 @@ enum { ETHTOOL_A_RSS_INDIR, /* binary */ ETHTOOL_A_RSS_HKEY, /* binary */ ETHTOOL_A_RSS_INPUT_XFRM, /* u32 */ + ETHTOOL_A_RSS_START_CONTEXT, /* u32 */ __ETHTOOL_A_RSS_CNT, ETHTOOL_A_RSS_MAX = (__ETHTOOL_A_RSS_CNT - 1), @@ -1049,6 +1058,22 @@ enum { ETHTOOL_A_MODULE_FW_FLASH_MAX = (__ETHTOOL_A_MODULE_FW_FLASH_CNT - 1) }; +enum { + ETHTOOL_A_PHY_UNSPEC, + ETHTOOL_A_PHY_HEADER, /* nest - _A_HEADER_* */ + ETHTOOL_A_PHY_INDEX, /* u32 */ + ETHTOOL_A_PHY_DRVNAME, /* string */ + ETHTOOL_A_PHY_NAME, /* string */ + ETHTOOL_A_PHY_UPSTREAM_TYPE, /* u32 */ + ETHTOOL_A_PHY_UPSTREAM_INDEX, /* u32 */ + ETHTOOL_A_PHY_UPSTREAM_SFP_NAME, /* string */ + ETHTOOL_A_PHY_DOWNSTREAM_SFP_NAME, /* string */ + + /* add new constants above here */ + __ETHTOOL_A_PHY_CNT, + ETHTOOL_A_PHY_MAX = (__ETHTOOL_A_PHY_CNT - 1) +}; + /* generic netlink info */ #define ETHTOOL_GENL_NAME "ethtool" #define ETHTOOL_GENL_VERSION 1 From patchwork Fri Sep 6 14:57:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Chevallier X-Patchwork-Id: 13794330 X-Patchwork-Delegate: mkubecek+ethtool@suse.cz Received: from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net [217.70.183.197]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5525D1D1F70; Fri, 6 Sep 2024 14:57:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.197 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725634655; cv=none; b=fhNY6ChD9q6DM6FFXJWfDR9Ns1UeZzcvMW9JJmKRCBh63uRzBTER3vEXv9izvGS7NYtIyKn/2r/33tAIFT8KHF91NRCt22gJY4gN08i3YXJx8jaPY0yXlMBY6u2O1URjblAPttquBti4owOAYUrdRSR59bzlWkbqzmQga+LP+DI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725634655; c=relaxed/simple; bh=dbqPb1VEUqjrkp5tIRjbloP34ygnXymNUnZt42oVgKo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rZmHar8qqAEqJTmsnnXcWdqMVmDLQDcZWw+Y62CSiPRSUvscW0bwhWHXShmwjsrnnLjdoUi9FTLIZULTjRpLyJeFlOpGb4a0oJK2mD2q0/wFq59bSN0E+0QNh3UpI6QswEX6azXhBj5346UmTJoODgBUpV0DJeb7fTWyvZWjFEw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=hAgVrvq3; arc=none smtp.client-ip=217.70.183.197 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="hAgVrvq3" Received: by mail.gandi.net (Postfix) with ESMTPSA id 4D08F1C0002; Fri, 6 Sep 2024 14:57:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1725634646; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=grEyzTHGkHhLankOV/hQ2IHe64hUAeaH7W8DoxhvTQ8=; b=hAgVrvq3R7IaNQyw6z5a5Ri1A8BmZX7ZuygOTRrysTIt0Y+nQRVSDTOxHNA71JjnKsv4u7 9ZPbTUK+SoAOynWYHPCVAUhuGnHfYmdRtAq9MVxQ4T/hMKmz4Qbqar4yJIQ/edwXQpoixn NmTdYuZfeWSTawPGKwgwcCLQhVT9qN5Ci5gqu43eP2/592ZHwbUWWzDIkMp/WXRGzYcdeR 2KxTxLMgqnp02/37ID3yZ0pvG/A7F6VTxTmVgThDYZqFx38DhbHbKtf1JZEFaG2NvEHSbc r1QRa1yL3sWVrNhfCp6ODHvcMlNHkIR1QlOIA0JmRtUofc30zO/DnoLKAqWf0A== From: Maxime Chevallier To: davem@davemloft.net, Michal Kubecek Cc: Maxime Chevallier , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, Andrew Lunn , Jakub Kicinski , Eric Dumazet , Paolo Abeni , Russell King , Christophe Leroy , Herve Codina , Florian Fainelli , Heiner Kallweit , Oleksij Rempel , Simon Horman Subject: [PATCH ethtool-next v4 2/3] ethtool: Allow passing a PHY index for phy-targetting commands Date: Fri, 6 Sep 2024 16:57:17 +0200 Message-ID: <20240906145719.387824-3-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20240906145719.387824-1-maxime.chevallier@bootlin.com> References: <20240906145719.387824-1-maxime.chevallier@bootlin.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-GND-Sasl: maxime.chevallier@bootlin.com X-Patchwork-Delegate: mkubecek+ethtool@suse.cz With the introduction of PHY topology and the ability to list PHYs, we can now target some netlink commands to specific PHYs. This is done by passing a PHY index as a request parameter in the netlink GET command. This is useful for PSE-PD, PLCA and Cable-testing operations when multiple PHYs are on the link (e.g. when a PHY is used as an SFP upstream controller, and when there's another PHY within the SFP module). Introduce a new, generic, option "--phy N" that can be used in conjunction with PHY-targetting commands to pass the PHY index for the targetted PHY. Signed-off-by: Maxime Chevallier --- ethtool.8.in | 21 ++++++++++++++++++ ethtool.c | 28 +++++++++++++++++++++++- internal.h | 1 + netlink/cable_test.c | 4 ++-- netlink/msgbuff.c | 52 ++++++++++++++++++++++++++++++++++---------- netlink/msgbuff.h | 3 +++ netlink/nlsock.c | 3 ++- netlink/plca.c | 4 ++-- netlink/pse-pd.c | 4 ++-- 9 files changed, 100 insertions(+), 20 deletions(-) diff --git a/ethtool.8.in b/ethtool.8.in index 11bb0f9..f16cdbd 100644 --- a/ethtool.8.in +++ b/ethtool.8.in @@ -143,6 +143,10 @@ ethtool \- query or control network driver and hardware settings .B ethtool [-I | --include-statistics] .I args .HP +.B ethtool +.BN --phy +.I args +.HP .B ethtool \-\-monitor [ .I command @@ -588,6 +592,23 @@ plain text in the presence of this option. Include command-related statistics in the output. This option allows displaying relevant device statistics for selected get commands. .TP +.BI \-\-phy \ N +Target a PHY within the interface. The PHY index can be retrieved with +.B \-\-show\-phys. PHY index 0 targets the phy device directly attached to +the ethernet MAC, if any. +The following commands can accept a PHY index: +.TS +nokeep; +lB l. +\-\-cable\-test +\-\-cable\-test\-tdr +\-\-get\-plca\-cfg +\-\-set\-plca\-cfg +\-\-get\-plca\-status +\-\-show-pse +\-\-set-pse +.TE +.TP .B \-a \-\-show\-pause Queries the specified Ethernet device for pause parameter information. .RS 4 diff --git a/ethtool.c b/ethtool.c index 7f47407..4dc05c2 100644 --- a/ethtool.c +++ b/ethtool.c @@ -5739,6 +5739,7 @@ struct option { const char *opts; bool no_dev; bool json; + bool targets_phy; int (*func)(struct cmd_context *); nl_chk_t nlchk; nl_func_t nlfunc; @@ -6158,12 +6159,14 @@ static const struct option args[] = { }, { .opts = "--cable-test", + .targets_phy = true, .json = true, .nlfunc = nl_cable_test, .help = "Perform a cable test", }, { .opts = "--cable-test-tdr", + .targets_phy = true, .json = true, .nlfunc = nl_cable_test_tdr, .help = "Print cable test time domain reflectrometery data", @@ -6191,11 +6194,13 @@ static const struct option args[] = { }, { .opts = "--get-plca-cfg", + .targets_phy = true, .nlfunc = nl_plca_get_cfg, .help = "Get PLCA configuration", }, { .opts = "--set-plca-cfg", + .targets_phy = true, .nlfunc = nl_plca_set_cfg, .help = "Set PLCA configuration", .xhelp = " [ enable on|off ]\n" @@ -6207,6 +6212,7 @@ static const struct option args[] = { }, { .opts = "--get-plca-status", + .targets_phy = true, .nlfunc = nl_plca_get_status, .help = "Get PLCA status information", }, @@ -6228,12 +6234,14 @@ static const struct option args[] = { }, { .opts = "--show-pse", + .targets_phy = true, .json = true, .nlfunc = nl_gpse, .help = "Show settings for Power Sourcing Equipment", }, { .opts = "--set-pse", + .targets_phy = true, .nlfunc = nl_spse, .help = "Set Power Sourcing Equipment settings", .xhelp = " [ podl-pse-admin-control enable|disable ]\n" @@ -6270,7 +6278,8 @@ static int show_usage(struct cmd_context *ctx __maybe_unused) fprintf(stdout, "Usage:\n"); for (i = 0; args[i].opts; i++) { fputs(" ethtool [ FLAGS ] ", stdout); - fprintf(stdout, "%s %s\t%s\n", + fprintf(stdout, "%s%s %s\t%s\n", + args[i].targets_phy ? "[ --phy PHY ] " : "", args[i].opts, args[i].no_dev ? "\t" : "DEVNAME", args[i].help); @@ -6550,6 +6559,19 @@ int main(int argc, char **argp) argc -= 1; continue; } + if (*argp && !strcmp(*argp, "--phy")) { + char *eptr; + + if (argc < 2) + exit_bad_args_info("--phy parameters expects a phy index"); + + ctx.phy_index = strtoul(argp[1], &eptr, 0); + if (!argp[1][0] || *eptr) + exit_bad_args_info("invalid phy index"); + argp += 2; + argc -= 2; + continue; + } break; } if (*argp && !strcmp(*argp, "--monitor")) { @@ -6585,6 +6607,10 @@ int main(int argc, char **argp) } if (ctx.json && !args[k].json) exit_bad_args_info("JSON output not available for this subcommand"); + + if (!args[k].targets_phy && ctx.phy_index) + exit_bad_args_info("Unexpected --phy parameter"); + ctx.argc = argc; ctx.argp = argp; netlink_run_handler(&ctx, args[k].nlchk, args[k].nlfunc, !args[k].func); diff --git a/internal.h b/internal.h index 4b994f5..afb8121 100644 --- a/internal.h +++ b/internal.h @@ -222,6 +222,7 @@ struct cmd_context { unsigned long debug; /* debugging mask */ bool json; /* Output JSON, if supported */ bool show_stats; /* include command-specific stats */ + uint32_t phy_index; /* the phy index this command targets */ #ifdef ETHTOOL_ENABLE_NETLINK struct nl_context *nlctx; /* netlink context (opaque) */ #endif diff --git a/netlink/cable_test.c b/netlink/cable_test.c index 9305a47..ba21c6c 100644 --- a/netlink/cable_test.c +++ b/netlink/cable_test.c @@ -572,8 +572,8 @@ int nl_cable_test_tdr(struct cmd_context *ctx) if (ret < 0) return 2; - if (ethnla_fill_header(msgbuff, ETHTOOL_A_CABLE_TEST_TDR_HEADER, - ctx->devname, 0)) + if (ethnla_fill_header_phy(msgbuff, ETHTOOL_A_CABLE_TEST_TDR_HEADER, + ctx->devname, ctx->phy_index, 0)) return -EMSGSIZE; ret = nl_parser(nlctx, tdr_params, NULL, PARSER_GROUP_NEST, NULL); diff --git a/netlink/msgbuff.c b/netlink/msgbuff.c index 216f5b9..2275840 100644 --- a/netlink/msgbuff.c +++ b/netlink/msgbuff.c @@ -138,17 +138,9 @@ struct nlattr *ethnla_nest_start(struct nl_msg_buff *msgbuff, uint16_t type) return NULL; } -/** - * ethnla_fill_header() - write standard ethtool request header to message - * @msgbuff: message buffer - * @type: attribute type for header nest - * @devname: device name (NULL to omit) - * @flags: request flags (omitted if 0) - * - * Return: pointer to the nest attribute or null of error - */ -bool ethnla_fill_header(struct nl_msg_buff *msgbuff, uint16_t type, - const char *devname, uint32_t flags) +static bool __ethnla_fill_header_phy(struct nl_msg_buff *msgbuff, uint16_t type, + const char *devname, uint32_t phy_index, + uint32_t flags) { struct nlattr *nest; @@ -159,7 +151,9 @@ bool ethnla_fill_header(struct nl_msg_buff *msgbuff, uint16_t type, if ((devname && ethnla_put_strz(msgbuff, ETHTOOL_A_HEADER_DEV_NAME, devname)) || (flags && - ethnla_put_u32(msgbuff, ETHTOOL_A_HEADER_FLAGS, flags))) + ethnla_put_u32(msgbuff, ETHTOOL_A_HEADER_FLAGS, flags)) || + (phy_index && + ethnla_put_u32(msgbuff, ETHTOOL_A_HEADER_PHY_INDEX, phy_index))) goto err; ethnla_nest_end(msgbuff, nest); @@ -170,6 +164,40 @@ err: return true; } +/** + * ethnla_fill_header() - write standard ethtool request header to message + * @msgbuff: message buffer + * @type: attribute type for header nest + * @devname: device name (NULL to omit) + * @flags: request flags (omitted if 0) + * + * Return: pointer to the nest attribute or null of error + */ +bool ethnla_fill_header(struct nl_msg_buff *msgbuff, uint16_t type, + const char *devname, uint32_t flags) +{ + return __ethnla_fill_header_phy(msgbuff, type, devname, 0, flags); +} + +/** + * ethnla_fill_header_phy() - write standard ethtool request header to message, + * targetting a device's phy + * @msgbuff: message buffer + * @type: attribute type for header nest + * @devname: device name (NULL to omit) + * @phy_index: phy index to target (0 to omit) + * @flags: request flags (omitted if 0) + * + * Return: pointer to the nest attribute or null of error + */ +bool ethnla_fill_header_phy(struct nl_msg_buff *msgbuff, uint16_t type, + const char *devname, uint32_t phy_index, + uint32_t flags) +{ + return __ethnla_fill_header_phy(msgbuff, type, devname, phy_index, + flags); +} + /** * __msg_init() - init a genetlink message, fill netlink and genetlink header * @msgbuff: message buffer diff --git a/netlink/msgbuff.h b/netlink/msgbuff.h index 7d6731f..7df19fc 100644 --- a/netlink/msgbuff.h +++ b/netlink/msgbuff.h @@ -47,6 +47,9 @@ bool ethnla_put(struct nl_msg_buff *msgbuff, uint16_t type, size_t len, struct nlattr *ethnla_nest_start(struct nl_msg_buff *msgbuff, uint16_t type); bool ethnla_fill_header(struct nl_msg_buff *msgbuff, uint16_t type, const char *devname, uint32_t flags); +bool ethnla_fill_header_phy(struct nl_msg_buff *msgbuff, uint16_t type, + const char *devname, uint32_t phy_index, + uint32_t flags); /* length of current message */ static inline unsigned int msgbuff_len(const struct nl_msg_buff *msgbuff) diff --git a/netlink/nlsock.c b/netlink/nlsock.c index 0ec2738..0b873a3 100644 --- a/netlink/nlsock.c +++ b/netlink/nlsock.c @@ -291,7 +291,8 @@ int nlsock_prep_get_request(struct nl_socket *nlsk, unsigned int nlcmd, ret = msg_init(nlctx, &nlsk->msgbuff, nlcmd, nlm_flags); if (ret < 0) return ret; - if (ethnla_fill_header(&nlsk->msgbuff, hdr_attrtype, devname, flags)) + if (ethnla_fill_header_phy(&nlsk->msgbuff, hdr_attrtype, devname, + nlctx->ctx->phy_index, flags)) return -EMSGSIZE; return 0; diff --git a/netlink/plca.c b/netlink/plca.c index 7d61e3b..7dc30a3 100644 --- a/netlink/plca.c +++ b/netlink/plca.c @@ -211,8 +211,8 @@ int nl_plca_set_cfg(struct cmd_context *ctx) NLM_F_REQUEST | NLM_F_ACK); if (ret < 0) return 2; - if (ethnla_fill_header(msgbuff, ETHTOOL_A_PLCA_HEADER, - ctx->devname, 0)) + if (ethnla_fill_header_phy(msgbuff, ETHTOOL_A_PLCA_HEADER, + ctx->devname, ctx->phy_index, 0)) return -EMSGSIZE; ret = nl_parser(nlctx, set_plca_params, NULL, PARSER_GROUP_NONE, NULL); diff --git a/netlink/pse-pd.c b/netlink/pse-pd.c index 2c8dd89..3f6b6aa 100644 --- a/netlink/pse-pd.c +++ b/netlink/pse-pd.c @@ -240,8 +240,8 @@ int nl_spse(struct cmd_context *ctx) NLM_F_REQUEST | NLM_F_ACK); if (ret < 0) return 2; - if (ethnla_fill_header(msgbuff, ETHTOOL_A_PSE_HEADER, - ctx->devname, 0)) + if (ethnla_fill_header_phy(msgbuff, ETHTOOL_A_PSE_HEADER, + ctx->devname, ctx->phy_index, 0)) return -EMSGSIZE; ret = nl_parser(nlctx, spse_params, NULL, PARSER_GROUP_NONE, NULL); From patchwork Fri Sep 6 14:57:18 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Chevallier X-Patchwork-Id: 13794331 X-Patchwork-Delegate: mkubecek+ethtool@suse.cz Received: from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net [217.70.183.197]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2DED71D27B3; Fri, 6 Sep 2024 14:57:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.197 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725634657; cv=none; b=UVULJXByr0rnFXuZ3bhXauLjm3LhHsbld1Qm/sTA4RgvSvR1qtNBNdZjPkPeohXSjroQdwH52Op0rM4vD+/s3IojMhmY/sI7k/QMBYQWcd/8NZuUlwK7UiRBXqfiaB3Ju/iU1Nq5O28eBJKLXBus7NqdMF2vic6x6cBDNdyT1O0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725634657; c=relaxed/simple; bh=HoJmyTyeTW6WSfJH/Bf8lDBuHJMQrA7FT1tqfqZiE90=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KnXPzWM6/lRdyBgbfKFmPUP/LdzfPLG9Qxh9wEz/++72E3hgKAeU6n17mmfxKpUObkr1nCMeMrT7Z/GyPvZiR7RBnOnW8oFuld2XqrGJThzRD89KYSoDeYsexsqINyjjqb1S/pjpklabX3y4TBlvU2GX5tFBNBVSCbr20W+UL3M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=drmrCLFD; arc=none smtp.client-ip=217.70.183.197 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="drmrCLFD" Received: by mail.gandi.net (Postfix) with ESMTPSA id 4D9051C0003; Fri, 6 Sep 2024 14:57:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1725634647; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=c3IvLprXjI8wsVwe9o5a2Lk8t4x1m7+YcAeH88sOiCc=; b=drmrCLFDc0VRYSGONWGnHijdZ4CX22tkeyXnq7oit+87HW2TP+SbUvzdsd+Xqn2n8kKvrr pynDTbVkVgT3ga2CDbUHOCl0uSvy1OxAznqnujeCN6VswnkPsuiCUm1EL7gcthoKiwCI8w eMwusQWRxAgx4QhotRBWGbwEvcSpo0qlhC87gCKQ5r3Eeei8Bnfzdfsge+ErP8Ows+Qp6X qx2VYFA0/MejqpMgwIXfVEJCa5M+Gtb2VCZdTFNPfLwRp4t/td5wIOVn2IKWSb6KhUjAkC coK/EZ1DqqKYFkIuN0/DR3MvX7iWnPnhjkasq2wpAPLaVFM/ILMZs9ubN0FGXg== From: Maxime Chevallier To: davem@davemloft.net, Michal Kubecek Cc: Maxime Chevallier , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, Andrew Lunn , Jakub Kicinski , Eric Dumazet , Paolo Abeni , Russell King , Christophe Leroy , Herve Codina , Florian Fainelli , Heiner Kallweit , Oleksij Rempel , Simon Horman Subject: [PATCH ethtool-next v4 3/3] ethtool: Introduce a command to list PHYs Date: Fri, 6 Sep 2024 16:57:18 +0200 Message-ID: <20240906145719.387824-4-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20240906145719.387824-1-maxime.chevallier@bootlin.com> References: <20240906145719.387824-1-maxime.chevallier@bootlin.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-GND-Sasl: maxime.chevallier@bootlin.com X-Patchwork-Delegate: mkubecek+ethtool@suse.cz It is now possible to list all Ethernet PHYs that are present behind a given interface, since the following linux commit : 63d5eaf35ac3 ("net: ethtool: Introduce a command to list PHYs on an interface") This command relies on the netlink DUMP command to list them, by allowing to pass an interface name/id as a parameter in the DUMP request to only list PHYs on one interface. Therefore, we introduce a new helper function to prepare a interface-filtered dump request (the filter can be empty, to perform an unfiltered dump), and then uses it to implement PHY enumeration through the --show-phys command. Signed-off-by: Maxime Chevallier --- Makefile.am | 1 + ethtool.8.in | 36 +++++++++++++++ ethtool.c | 5 ++ netlink/extapi.h | 2 + netlink/nlsock.c | 37 +++++++++++++++ netlink/nlsock.h | 2 + netlink/phy.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 199 insertions(+) create mode 100644 netlink/phy.c diff --git a/Makefile.am b/Makefile.am index 5a61a9a..862886b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -48,6 +48,7 @@ ethtool_SOURCES += \ netlink/desc-rtnl.c netlink/cable_test.c netlink/tunnels.c \ netlink/plca.c \ netlink/pse-pd.c \ + netlink/phy.c \ uapi/linux/ethtool_netlink.h \ uapi/linux/netlink.h uapi/linux/genetlink.h \ uapi/linux/rtnetlink.h uapi/linux/if_link.h \ diff --git a/ethtool.8.in b/ethtool.8.in index f16cdbd..5b8b8d6 100644 --- a/ethtool.8.in +++ b/ethtool.8.in @@ -547,6 +547,9 @@ ethtool \- query or control network driver and hardware settings .IR FILE .RB [ pass .IR PASS ] +.HP +.B ethtool \-\-show\-phys +.I devname . .\" Adjust lines (i.e. full justification) and hyphenate. .ad @@ -1823,6 +1826,39 @@ is downloaded to the transceiver module, validated, run and committed. Optional transceiver module password that might be required as part of the transceiver module firmware update process. +.RE +.TP +.B \-\-show\-phys +Show the PHY devices attached to an interface, and the way they link together. +.RS 4 +.TP +.B phy_index +The PHY's index, that identifies it within the network interface. If the +interface has multiple PHYs, they will each have a unique index on that +interface. This index can then be used for commands that targets PHYs. +.TP +.B drvname +The name of the driver bound to this PHY device. +.TP +.B name +The PHY's device name, matching the name found in sysfs. +.TP +.B downstream_sfp_name +If the PHY drives an SFP cage, this field contains the name of the associated +SFP bus. +.TP +.B upstream_type \ mac | phy +Indicates the nature of the device the PHY is attached to. +.TP +.B upstream_index +If the PHY's upstream_type is +.B phy +, this field indicates the phy_index of the upstream phy. +.TP +.B upstream_sfp_name +If the PHY is withing an SFP/SFF module, this field contains the name of the +upstream SFP bus. + .SH BUGS Not supported (in part or whole) on all network drivers. .SH AUTHOR diff --git a/ethtool.c b/ethtool.c index 4dc05c2..eb3aa50 100644 --- a/ethtool.c +++ b/ethtool.c @@ -6254,6 +6254,11 @@ static const struct option args[] = { .xhelp = " file FILE\n" " [ pass PASS ]\n" }, + { + .opts = "--show-phys", + .nlfunc = nl_get_phy, + .help = "List PHYs" + }, { .opts = "-h|--help", .no_dev = true, diff --git a/netlink/extapi.h b/netlink/extapi.h index c882295..9d6eddf 100644 --- a/netlink/extapi.h +++ b/netlink/extapi.h @@ -56,6 +56,7 @@ int nl_set_mm(struct cmd_context *ctx); int nl_gpse(struct cmd_context *ctx); int nl_spse(struct cmd_context *ctx); int nl_flash_module_fw(struct cmd_context *ctx); +int nl_get_phy(struct cmd_context *ctx); void nl_monitor_usage(void); @@ -132,6 +133,7 @@ nl_get_eeprom_page(struct cmd_context *ctx __maybe_unused, #define nl_gpse NULL #define nl_spse NULL #define nl_flash_module_fw NULL +#define nl_get_phy NULL #endif /* ETHTOOL_ENABLE_NETLINK */ diff --git a/netlink/nlsock.c b/netlink/nlsock.c index 0b873a3..5450c9b 100644 --- a/netlink/nlsock.c +++ b/netlink/nlsock.c @@ -298,6 +298,43 @@ int nlsock_prep_get_request(struct nl_socket *nlsk, unsigned int nlcmd, return 0; } +/** + * nlsock_prep_filtered_dump_request() - Initialize a filtered DUMP request + * @nlsk: netlink socket + * @nlcmd: netlink command + * @hdr_attrtype: netlink command header attribute + * @flags: netlink command header flags + * + * Prepare a DUMP request that may include the device index as a filtering + * attribute in the header. + * + * Return: 0 on success, or a negative number on error + */ +int nlsock_prep_filtered_dump_request(struct nl_socket *nlsk, + unsigned int nlcmd, uint16_t hdr_attrtype, + u32 flags) +{ + struct nl_context *nlctx = nlsk->nlctx; + const char *devname = nlctx->ctx->devname; + unsigned int nlm_flags; + int ret; + + nlctx->is_dump = true; + nlm_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP; + + if (devname && !strcmp(devname, WILDCARD_DEVNAME)) + devname = NULL; + + ret = msg_init(nlctx, &nlsk->msgbuff, nlcmd, nlm_flags); + if (ret < 0) + return ret; + + if (ethnla_fill_header(&nlsk->msgbuff, hdr_attrtype, devname, flags)) + return -EMSGSIZE; + + return 0; +} + #ifndef TEST_ETHTOOL /** * nlsock_sendmsg() - send a netlink message to kernel diff --git a/netlink/nlsock.h b/netlink/nlsock.h index b015f86..6a72966 100644 --- a/netlink/nlsock.h +++ b/netlink/nlsock.h @@ -38,6 +38,8 @@ int nlsock_init(struct nl_context *nlctx, struct nl_socket **__nlsk, void nlsock_done(struct nl_socket *nlsk); int nlsock_prep_get_request(struct nl_socket *nlsk, unsigned int nlcmd, uint16_t hdr_attrtype, u32 flags); +int nlsock_prep_filtered_dump_request(struct nl_socket *nlsk, unsigned int nlcmd, + uint16_t hdr_attrtype, u32 flags); ssize_t nlsock_sendmsg(struct nl_socket *nlsk, struct nl_msg_buff *__msgbuff); int nlsock_send_get_request(struct nl_socket *nlsk, mnl_cb_t cb); int nlsock_process_reply(struct nl_socket *nlsk, mnl_cb_t reply_cb, void *data); diff --git a/netlink/phy.c b/netlink/phy.c new file mode 100644 index 0000000..7578191 --- /dev/null +++ b/netlink/phy.c @@ -0,0 +1,116 @@ +/* + * phy.c - List PHYs on an interface and their parameters + * + * Implementation of "ethtool --show-phys " + */ + +#include +#include +#include +#include + +#include "../internal.h" +#include "../common.h" +#include "netlink.h" + +/* PHY_GET / PHY_DUMP */ + +static const char * phy_upstream_type_to_str(uint8_t upstream_type) +{ + switch (upstream_type) { + case PHY_UPSTREAM_PHY: return "phy"; + case PHY_UPSTREAM_MAC: return "mac"; + default: return "Unknown"; + } +} + +int phy_reply_cb(const struct nlmsghdr *nlhdr, void *data) +{ + const struct nlattr *tb[ETHTOOL_A_PHY_MAX + 1] = {}; + struct nl_context *nlctx = data; + DECLARE_ATTR_TB_INFO(tb); + uint8_t upstream_type; + bool silent; + int err_ret; + int ret; + + silent = nlctx->is_dump || nlctx->is_monitor; + err_ret = silent ? MNL_CB_OK : MNL_CB_ERROR; + ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info); + if (ret < 0) + return err_ret; + nlctx->devname = get_dev_name(tb[ETHTOOL_A_PHY_HEADER]); + if (!dev_ok(nlctx)) + return err_ret; + + if (silent) + print_nl(); + + open_json_object(NULL); + + print_string(PRINT_ANY, "ifname", "PHY for %s:\n", nlctx->devname); + + show_u32("phy_index", "PHY index: ", tb[ETHTOOL_A_PHY_INDEX]); + + if (tb[ETHTOOL_A_PHY_DRVNAME]) + print_string(PRINT_ANY, "drvname", "Driver name: %s\n", + mnl_attr_get_str(tb[ETHTOOL_A_PHY_DRVNAME])); + + if (tb[ETHTOOL_A_PHY_NAME]) + print_string(PRINT_ANY, "name", "PHY device name: %s\n", + mnl_attr_get_str(tb[ETHTOOL_A_PHY_NAME])); + + if (tb[ETHTOOL_A_PHY_DOWNSTREAM_SFP_NAME]) + print_string(PRINT_ANY, "downstream_sfp_name", + "Downstream SFP bus name: %s\n", + mnl_attr_get_str(tb[ETHTOOL_A_PHY_DOWNSTREAM_SFP_NAME])); + + if (tb[ETHTOOL_A_PHY_UPSTREAM_TYPE]) { + upstream_type = mnl_attr_get_u8(tb[ETHTOOL_A_PHY_UPSTREAM_TYPE]); + print_string(PRINT_ANY, "upstream_type", "Upstream type: %s\n", + phy_upstream_type_to_str(upstream_type)); + } + + if (tb[ETHTOOL_A_PHY_UPSTREAM_INDEX]) + show_u32("upstream_index", "Upstream PHY index: ", + tb[ETHTOOL_A_PHY_UPSTREAM_INDEX]); + + if (tb[ETHTOOL_A_PHY_UPSTREAM_SFP_NAME]) + print_string(PRINT_ANY, "upstream_sfp_name", "Upstream SFP name: %s\n", + mnl_attr_get_str(tb[ETHTOOL_A_PHY_UPSTREAM_SFP_NAME])); + + if (!silent) + print_nl(); + + close_json_object(); + + return MNL_CB_OK; + + close_json_object(); + return err_ret; +} + +int nl_get_phy(struct cmd_context *ctx) +{ + struct nl_context *nlctx = ctx->nlctx; + struct nl_socket *nlsk = nlctx->ethnl_socket; + int ret; + + if (netlink_cmd_check(ctx, ETHTOOL_MSG_PHY_GET, true)) + return -EOPNOTSUPP; + if (ctx->argc > 0) { + fprintf(stderr, "ethtool: unexpected parameter '%s'\n", + *ctx->argp); + return 1; + } + + ret = nlsock_prep_filtered_dump_request(nlsk, ETHTOOL_MSG_PHY_GET, + ETHTOOL_A_PHY_HEADER, 0); + if (ret) + return ret; + + new_json_obj(ctx->json); + ret = nlsock_send_get_request(nlsk, phy_reply_cb); + delete_json_obj(); + return ret; +}