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]
Date:   Mon, 14 Jan 2019 16:50:04 -0800
From:   Jakub Kicinski <jakub.kicinski@...ronome.com>
To:     davem@...emloft.net
Cc:     netdev@...r.kernel.org, oss-drivers@...ronome.com,
        jiri@...nulli.us, Jakub Kicinski <jakub.kicinski@...ronome.com>
Subject: [RFC net-next 2/6] devlink: add version reporting API

ethtool -i has a few fixed-size fields which can be used to report
firmware version and expansion ROM version.  Unfortunately, modern
hardware has more firmware components.  There is usually some
datapath microcode, management controller, PXE drivers, and a
CPLD load.  Running ethtool -i on modern controllers reveals the
fact that vendors cram multiple values into firmware version field.

Here are some examples from systems I could lay my hands on quickly:

tg3:  "FFV20.2.17 bc 5720-v1.39"
i40e: "6.01 0x800034a4 1.1747.0"
nfp:  "0.0.3.5 0.25 sriov-2.1.16 nic"

Add a new devlink API to allow retrieving multiple versions, and
provide user-readable name for those versions.

While at it break down the versions into three categories:
 - fixed - this is the board/fixed component version, usually vendors
           report information like the board version in the PCI VPD,
           but it will benefit from naming and common API as well;
 - running - this is the running firmware version;
 - stored - this is firmware in the flash, after firmware update
            this value will reflect the flashed version, while the
            running version may only be updated after reboot.

Signed-off-by: Jakub Kicinski <jakub.kicinski@...ronome.com>
---
 include/net/devlink.h        | 13 +++++++
 include/uapi/linux/devlink.h |  6 ++++
 net/core/devlink.c           | 67 +++++++++++++++++++++++++++++++++++-
 3 files changed, 85 insertions(+), 1 deletion(-)

diff --git a/include/net/devlink.h b/include/net/devlink.h
index 4358c111ce83..51f08edb1138 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -477,6 +477,8 @@ struct devlink_ops {
 				      struct netlink_ext_ack *extack);
 	int (*serial_get)(struct devlink *devlink, u8 *buf, size_t buf_len,
 			  size_t *len, struct netlink_ext_ack *extack);
+	int (*versions_get)(struct devlink *devlink, struct sk_buff *skb,
+			    struct netlink_ext_ack *extack);
 };
 
 static inline void *devlink_priv(struct devlink *devlink)
@@ -586,6 +588,10 @@ int devlink_region_snapshot_create(struct devlink_region *region, u64 data_len,
 				   u8 *data, u32 snapshot_id,
 				   devlink_snapshot_data_dest_t *data_destructor);
 
+int devlink_versions_report(struct sk_buff *skb, enum devlink_attr attr,
+			    const char *version_name,
+			    const char *version_value);
+
 #else
 
 static inline struct devlink *devlink_alloc(const struct devlink_ops *ops,
@@ -846,6 +852,13 @@ devlink_region_snapshot_create(struct devlink_region *region, u64 data_len,
 	return 0;
 }
 
+static inline int
+devlink_versions_report(struct sk_buff *skb, enum devlink_attr attr,
+			const char *version_name, const char *version_value)
+{
+	return 0;
+}
+
 #endif
 
 #endif /* _NET_DEVLINK_H_ */
diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h
index 760c9c360330..eb97a52246ef 100644
--- a/include/uapi/linux/devlink.h
+++ b/include/uapi/linux/devlink.h
@@ -288,6 +288,12 @@ enum devlink_attr {
 	DEVLINK_ATTR_REGION_CHUNK_LEN,          /* u64 */
 
 	DEVLINK_ATTR_INFO_SERIAL_NUMBER,	/* binary */
+	DEVLINK_ATTR_INFO_VERSIONS,		/* nested */
+	DEVLINK_ATTR_INFO_VERSIONS_FIXED,	/* nested */
+	DEVLINK_ATTR_INFO_VERSIONS_RUNNING,	/* nested */
+	DEVLINK_ATTR_INFO_VERSIONS_STORED,	/* nested */
+	DEVLINK_ATTR_INFO_VERSIONS_NAME,	/* string */
+	DEVLINK_ATTR_INFO_VERSIONS_VALUE,	/* string */
 
 	/* add new attributes above here, update the policy in devlink.c */
 
diff --git a/net/core/devlink.c b/net/core/devlink.c
index 55b7b006df28..f35d917da7f2 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -3615,6 +3615,32 @@ static int devlink_nl_info_sn_fill(struct sk_buff *msg, struct devlink *devlink,
 	return nla_put(msg, DEVLINK_ATTR_INFO_SERIAL_NUMBER, len, sn);
 }
 
+static int devlink_nl_info_versions_fill(struct sk_buff *msg,
+					 struct devlink *devlink,
+					 struct netlink_ext_ack *extack)
+{
+	struct nlattr *attr;
+	int err;
+
+	if (!devlink->ops->versions_get)
+		return 0;
+
+	attr = nla_nest_start(msg, DEVLINK_ATTR_INFO_VERSIONS);
+	if (!attr)
+		return -EMSGSIZE;
+
+	err = devlink->ops->versions_get(devlink, msg, extack);
+	if (err)
+		goto err_cancel;
+
+	nla_nest_end(msg, attr);
+	return 0;
+
+err_cancel:
+	nla_nest_cancel(msg, attr);
+	return err;
+}
+
 static int
 devlink_nl_info_fill(struct sk_buff *msg, struct devlink *devlink,
 		     enum devlink_command cmd, u32 portid,
@@ -3635,6 +3661,10 @@ devlink_nl_info_fill(struct sk_buff *msg, struct devlink *devlink,
 	if (err)
 		goto err_cancel_msg;
 
+	err = devlink_nl_info_versions_fill(msg, devlink, extack);
+	if (err)
+		goto err_cancel_msg;
+
 	genlmsg_end(msg, hdr);
 	return 0;
 
@@ -3650,7 +3680,8 @@ static int devlink_nl_cmd_info_get_doit(struct sk_buff *skb,
 	struct sk_buff *msg;
 	int err;
 
-	if (!devlink->ops || !devlink->ops->serial_get)
+	if (!devlink->ops ||
+	    (!devlink->ops->serial_get && !devlink->ops->versions_get))
 		return -EOPNOTSUPP;
 
 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
@@ -3701,6 +3732,40 @@ static int devlink_nl_cmd_info_get_dumpit(struct sk_buff *msg,
 	return msg->len;
 }
 
+int devlink_versions_report(struct sk_buff *skb, enum devlink_attr attr,
+			    const char *version_name, const char *version_value)
+{
+	struct nlattr *nest;
+	int err;
+
+	if (attr < DEVLINK_ATTR_INFO_VERSIONS_FIXED ||
+	    attr > DEVLINK_ATTR_INFO_VERSIONS_STORED)
+		return -EINVAL;
+
+	nest = nla_nest_start(skb, attr);
+	if (!nest)
+		return -EMSGSIZE;
+
+	err = nla_put_string(skb, DEVLINK_ATTR_INFO_VERSIONS_NAME,
+			     version_name);
+	if (err)
+		goto nla_put_failure;
+
+	err = nla_put_string(skb, DEVLINK_ATTR_INFO_VERSIONS_VALUE,
+			     version_value);
+	if (err)
+		goto nla_put_failure;
+
+	nla_nest_end(skb, nest);
+
+	return 0;
+
+nla_put_failure:
+	nla_nest_cancel(skb, nest);
+	return err;
+}
+EXPORT_SYMBOL_GPL(devlink_versions_report);
+
 static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING },
-- 
2.19.2

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ