lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20240329092321.16843-3-wojciech.drewek@intel.com>
Date: Fri, 29 Mar 2024 10:23:20 +0100
From: Wojciech Drewek <wojciech.drewek@...el.com>
To: netdev@...r.kernel.org
Cc: intel-wired-lan@...ts.osuosl.org,
	simon.horman@...igine.com,
	anthony.l.nguyen@...el.com,
	edumazet@...gle.com,
	kuba@...nel.org,
	pabeni@...hat.com,
	idosch@...dia.com,
	przemyslaw.kitszel@...el.com,
	marcin.szycik@...ux.intel.com
Subject: [PATCH net-next 2/3] ethtool: Introduce max power support

Some modules use nonstandard power levels. Adjust ethtool
module implementation to support new attributes that will allow user
to change maximum power.

Add three new get attributes:
ETHTOOL_A_MODULE_MAX_POWER_SET (used for set as well) - currently set
  maximum power in the cage
ETHTOOL_A_MODULE_MIN_POWER_ALLOWED - minimum power allowed in the
  cage reported by device
ETHTOOL_A_MODULE_MAX_POWER_ALLOWED - maximum power allowed in the
  cage reported by device

Add two new set attributes:
ETHTOOL_A_MODULE_MAX_POWER_SET (used for get as well) - change
  maximum power in the cage to the given value (milliwatts)
ETHTOOL_A_MODULE_MAX_POWER_RESET - reset maximum power setting to the
  default value

Reviewed-by: Marcin Szycik <marcin.szycik@...ux.intel.com>
Signed-off-by: Wojciech Drewek <wojciech.drewek@...el.com>
---
 include/linux/ethtool.h              | 17 +++++--
 include/uapi/linux/ethtool_netlink.h |  4 ++
 net/ethtool/module.c                 | 74 ++++++++++++++++++++++++++--
 net/ethtool/netlink.h                |  2 +-
 4 files changed, 87 insertions(+), 10 deletions(-)

diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index f3af6b31c9f1..74ed8997443a 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -510,10 +510,18 @@ struct ethtool_module_eeprom {
  * @policy: The power mode policy enforced by the host for the plug-in module.
  * @mode: The operational power mode of the plug-in module. Should be filled by
  *	device drivers on get operations.
+ * @min_pwr_allowed: minimum power allowed in the cage reported by device
+ * @max_pwr_allowed: maximum power allowed in the cage reported by device
+ * @max_pwr_set: maximum power currently set in the cage
+ * @max_pwr_reset: restore default minimum power
  */
 struct ethtool_module_power_params {
 	enum ethtool_module_power_mode_policy policy;
 	enum ethtool_module_power_mode mode;
+	u32 min_pwr_allowed;
+	u32 max_pwr_allowed;
+	u32 max_pwr_set;
+	u8 max_pwr_reset;
 };
 
 /**
@@ -804,11 +812,12 @@ struct ethtool_rxfh_param {
  * @get_eth_ctrl_stats: Query some of the IEEE 802.3 MAC Ctrl statistics.
  * @get_rmon_stats: Query some of the RMON (RFC 2819) statistics.
  *	Set %ranges to a pointer to zero-terminated array of byte ranges.
- * @get_module_power_cfg: Get the power mode policy for the plug-in module
- *	used by the network device and its operational power mode, if
- *	plugged-in.
+ * @get_module_power_cfg: Get the power configuration for the plug-in module
+ *	used by the network device which includes: its power mode policy and
+ *	operational power mode, if plugged-in; maximum power settings
+ *	(min and max allowed power and max power currently set)
  * @set_module_power_cfg: Set the power mode policy for the plug-in module
- *	used by the network device.
+ *	used by the network device and its maximum power.
  * @get_mm: Query the 802.3 MAC Merge layer state.
  * @set_mm: Set the 802.3 MAC Merge layer parameters.
  * @get_mm_stats: Query the 802.3 MAC Merge layer statistics.
diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h
index 3f89074aa06c..f7cd446b2a83 100644
--- a/include/uapi/linux/ethtool_netlink.h
+++ b/include/uapi/linux/ethtool_netlink.h
@@ -882,6 +882,10 @@ enum {
 	ETHTOOL_A_MODULE_HEADER,		/* nest - _A_HEADER_* */
 	ETHTOOL_A_MODULE_POWER_MODE_POLICY,	/* u8 */
 	ETHTOOL_A_MODULE_POWER_MODE,		/* u8 */
+	ETHTOOL_A_MODULE_MAX_POWER_SET,		/* u32 */
+	ETHTOOL_A_MODULE_MIN_POWER_ALLOWED,	/* u32 */
+	ETHTOOL_A_MODULE_MAX_POWER_ALLOWED,	/* u32 */
+	ETHTOOL_A_MODULE_MAX_POWER_RESET,	/* u8 */
 
 	/* add new constants above here */
 	__ETHTOOL_A_MODULE_CNT,
diff --git a/net/ethtool/module.c b/net/ethtool/module.c
index 193ca4642e04..9f63a276357e 100644
--- a/net/ethtool/module.c
+++ b/net/ethtool/module.c
@@ -69,6 +69,15 @@ static int module_reply_size(const struct ethnl_req_info *req_base,
 	if (data->power.mode)
 		len += nla_total_size(sizeof(u8));	/* _MODULE_POWER_MODE */
 
+	if (data->power.min_pwr_allowed)
+		len += nla_total_size(sizeof(u32));	/* _MIN_POWER_ALLOWED */
+
+	if (data->power.max_pwr_allowed)
+		len += nla_total_size(sizeof(u32));	/* _MAX_POWER_ALLOWED */
+
+	if (data->power.max_pwr_set)
+		len += nla_total_size(sizeof(u32));	/* _MAX_POWER_SET */
+
 	return len;
 }
 
@@ -77,6 +86,7 @@ static int module_fill_reply(struct sk_buff *skb,
 			     const struct ethnl_reply_data *reply_base)
 {
 	const struct module_reply_data *data = MODULE_REPDATA(reply_base);
+	u32 temp;
 
 	if (data->power.policy &&
 	    nla_put_u8(skb, ETHTOOL_A_MODULE_POWER_MODE_POLICY,
@@ -87,16 +97,30 @@ static int module_fill_reply(struct sk_buff *skb,
 	    nla_put_u8(skb, ETHTOOL_A_MODULE_POWER_MODE, data->power.mode))
 		return -EMSGSIZE;
 
+	temp = data->power.min_pwr_allowed;
+	if (temp && nla_put_u32(skb, ETHTOOL_A_MODULE_MIN_POWER_ALLOWED, temp))
+		return -EMSGSIZE;
+
+	temp = data->power.max_pwr_allowed;
+	if (temp && nla_put_u32(skb, ETHTOOL_A_MODULE_MAX_POWER_ALLOWED, temp))
+		return -EMSGSIZE;
+
+	temp = data->power.max_pwr_set;
+	if (temp && nla_put_u32(skb, ETHTOOL_A_MODULE_MAX_POWER_SET, temp))
+		return -EMSGSIZE;
+
 	return 0;
 }
 
 /* MODULE_SET */
 
-const struct nla_policy ethnl_module_set_policy[ETHTOOL_A_MODULE_POWER_MODE_POLICY + 1] = {
+const struct nla_policy ethnl_module_set_policy[ETHTOOL_A_MODULE_MAX + 1] = {
 	[ETHTOOL_A_MODULE_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy),
 	[ETHTOOL_A_MODULE_POWER_MODE_POLICY] =
 		NLA_POLICY_RANGE(NLA_U8, ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH,
 				 ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO),
+	[ETHTOOL_A_MODULE_MAX_POWER_SET] = { .type = NLA_U32 },
+	[ETHTOOL_A_MODULE_MAX_POWER_RESET] = { .type = NLA_U8 },
 };
 
 static int
@@ -106,7 +130,9 @@ ethnl_set_module_validate(struct ethnl_req_info *req_info,
 	const struct ethtool_ops *ops = req_info->dev->ethtool_ops;
 	struct nlattr **tb = info->attrs;
 
-	if (!tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY])
+	if (!tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY] &&
+	    !tb[ETHTOOL_A_MODULE_MAX_POWER_SET] &&
+	    !tb[ETHTOOL_A_MODULE_MAX_POWER_RESET])
 		return 0;
 
 	if (!ops->get_module_power_cfg || !ops->set_module_power_cfg) {
@@ -117,26 +143,64 @@ ethnl_set_module_validate(struct ethnl_req_info *req_info,
 	return 1;
 }
 
+static void
+ethnl_update_policy(enum ethtool_module_power_mode_policy *dst,
+		    const struct nlattr *attr, bool *mod)
+{
+	u8 val = *dst;
+
+	ethnl_update_u8(&val, attr, mod);
+
+	if (mod)
+		*dst = val;
+}
+
 static int
 ethnl_set_module(struct ethnl_req_info *req_info, struct genl_info *info)
 {
 	struct ethtool_module_power_params power = {};
 	struct ethtool_module_power_params power_new;
-	const struct ethtool_ops *ops;
 	struct net_device *dev = req_info->dev;
 	struct nlattr **tb = info->attrs;
+	const struct ethtool_ops *ops;
 	int ret;
+	bool mod;
 
 	ops = dev->ethtool_ops;
 
-	power_new.policy = nla_get_u8(tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY]);
 	ret = ops->get_module_power_cfg(dev, &power, info->extack);
 	if (ret < 0)
 		return ret;
 
-	if (power_new.policy == power.policy)
+	power_new.max_pwr_set = power.max_pwr_set;
+	power_new.policy = power.policy;
+
+	ethnl_update_u32(&power_new.max_pwr_set,
+			 tb[ETHTOOL_A_MODULE_MAX_POWER_SET], &mod);
+
+	if (mod) {
+		if (power_new.max_pwr_set > power.max_pwr_allowed) {
+			NL_SET_ERR_MSG(info->extack, "Provided value is higher than maximum allowed");
+			return -EINVAL;
+		} else if (power_new.max_pwr_set < power.min_pwr_allowed) {
+			NL_SET_ERR_MSG(info->extack, "Provided value is lower than minimum allowed");
+			return -EINVAL;
+		}
+	}
+
+	ethnl_update_policy(&power_new.policy,
+			    tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY], &mod);
+	ethnl_update_u8(&power_new.max_pwr_reset,
+			tb[ETHTOOL_A_MODULE_MAX_POWER_RESET], &mod);
+
+	if (!mod)
 		return 0;
 
+	if (power_new.max_pwr_reset && power_new.max_pwr_set) {
+		NL_SET_ERR_MSG(info->extack, "Maximum power set and reset cannot be used at the same time");
+		return 0;
+	}
+
 	ret = ops->set_module_power_cfg(dev, &power_new, info->extack);
 	return ret < 0 ? ret : 1;
 }
diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
index 9a333a8d04c1..6282f84811ce 100644
--- a/net/ethtool/netlink.h
+++ b/net/ethtool/netlink.h
@@ -432,7 +432,7 @@ extern const struct nla_policy ethnl_module_eeprom_get_policy[ETHTOOL_A_MODULE_E
 extern const struct nla_policy ethnl_stats_get_policy[ETHTOOL_A_STATS_SRC + 1];
 extern const struct nla_policy ethnl_phc_vclocks_get_policy[ETHTOOL_A_PHC_VCLOCKS_HEADER + 1];
 extern const struct nla_policy ethnl_module_get_policy[ETHTOOL_A_MODULE_HEADER + 1];
-extern const struct nla_policy ethnl_module_set_policy[ETHTOOL_A_MODULE_POWER_MODE_POLICY + 1];
+extern const struct nla_policy ethnl_module_set_policy[ETHTOOL_A_MODULE_MAX + 1];
 extern const struct nla_policy ethnl_pse_get_policy[ETHTOOL_A_PSE_HEADER + 1];
 extern const struct nla_policy ethnl_pse_set_policy[ETHTOOL_A_PSE_MAX + 1];
 extern const struct nla_policy ethnl_rss_get_policy[ETHTOOL_A_RSS_CONTEXT + 1];
-- 
2.40.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ