diff mbox series

[iproute2,03/10] devlink: param show: handle multi-attribute values

Message ID 20250228021837.880041-4-saeed@kernel.org (mailing list archive)
State New, archived
Delegated to: David Ahern
Headers show
Series devlink params nested multi-attribute values | expand

Checks

Context Check Description
netdev/tree_selection success Not a local patch

Commit Message

Saeed Mahameed Feb. 28, 2025, 2:18 a.m. UTC
From: Saeed Mahameed <saeedm@nvidia.com>

Param value attribute DEVLINK_ATTR_PARAM_VALUE_DATA can be passed to/from
kernel as with type DEVLINK_DYN_ATTR_TYPE_U32_ARRAY, as such encoded data
would be U32 list of values.

Handle this case by outputting the value as comma separated list or
json list objects for get/dump requests.

example:
$ devlink dev param show <dev> name foo
<dev>
  name foo type driver-specific
   values:
     cmode permanent value: 1,2,3,4,5,6,7,8

Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
---
 devlink/devlink.c            | 77 ++++++++++++++++++++++++++++++++++++
 include/uapi/linux/devlink.h |  1 +
 2 files changed, 78 insertions(+)
diff mbox series

Patch

diff --git a/devlink/devlink.c b/devlink/devlink.c
index 777f769c..d659b769 100644
--- a/devlink/devlink.c
+++ b/devlink/devlink.c
@@ -556,6 +556,30 @@  static void pr_out_array_end(struct dl *dl)
 	}
 }
 
+static void pr_out_val_array_start(struct dl *dl, const char *name,
+				   const char *delimeter)
+{
+	if (dl->json_output) {
+		open_json_array(PRINT_JSON, name);
+	} else {
+		__pr_out_indent_inc();
+		pr_out(" %s:", name);
+		if (delimeter)
+			pr_out("%s", delimeter);
+		__pr_out_indent_inc();
+	}
+}
+
+static void pr_out_val_array_end(struct dl *dl)
+{
+	if (dl->json_output) {
+		close_json_array(PRINT_JSON, NULL);
+	} else {
+		__pr_out_indent_dec();
+		__pr_out_indent_dec();
+	}
+}
+
 static void pr_out_object_start(struct dl *dl, const char *name)
 {
 	if (dl->json_output) {
@@ -3396,6 +3420,41 @@  static const struct param_val_conv param_val_conv[] = {
 	},
 };
 
+struct dl_param_val_list {
+	size_t len;
+	uint32_t vu32[];
+};
+
+/* Parse nested param value list
+ * @val_list_attr: nested attribute containing the list of values
+ *         usually : val_list_attr = nla_value[DEVLINK_ATTR_PARAM_VALUE_DATA]
+ * @list: pointer to the list of values, reallocated to the new size
+ * Returns: 0 on success, -errno on failure
+ */
+static int
+dl_mnl_parse_param_val_nested(struct nlattr *val_list_attr,
+			      struct dl_param_val_list **list)
+{
+	struct dl_param_val_list *new_list;
+	struct nlattr *val_attr;
+	int i = 0, len = 0;
+
+	len = mnl_attr_get_payload_len(val_list_attr)/(MNL_ATTR_HDRLEN + sizeof(uint32_t));
+	if (!len)
+		return -EINVAL;
+
+	new_list = realloc(*list, sizeof(new_list) + len * sizeof(uint32_t));
+	if (!new_list)
+		return -ENOMEM;
+
+	mnl_attr_for_each_nested(val_attr, val_list_attr)
+		new_list->vu32[i++] = mnl_attr_get_u32(val_attr);
+
+	new_list->len = i;
+	*list = new_list;
+	return 0;
+}
+
 #define PARAM_VAL_CONV_LEN ARRAY_SIZE(param_val_conv)
 
 static void pr_out_param_value(struct dl *dl, const char *nla_name,
@@ -3479,6 +3538,24 @@  static void pr_out_param_value(struct dl *dl, const char *nla_name,
 	case DEVLINK_DYN_ATTR_TYPE_FLAG:
 		print_bool(PRINT_ANY, "value", " value %s", val_attr);
 		break;
+	case DEVLINK_DYN_ATTR_TYPE_U32_ARRAY: {
+			struct dl_param_val_list *list = NULL;
+			int err;
+			int i;
+
+			err = dl_mnl_parse_param_val_nested(val_attr, &list);
+			if (err)
+				return;
+
+			pr_out_val_array_start(dl, "value", " ");
+
+			for (i = 0; i < list->len - 1; i++)
+				print_uint(PRINT_ANY, NULL, "%u,", list->vu32[i]);
+			print_uint(PRINT_ANY, NULL, "%u", list->vu32[i]);
+			pr_out_val_array_end(dl);
+			free(list);
+			break;
+		}
 	default:
 		break;
 	}
diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h
index b822baf9..5338db89 100644
--- a/include/uapi/linux/devlink.h
+++ b/include/uapi/linux/devlink.h
@@ -400,6 +400,7 @@  enum devlink_dyn_attr_type {
 	DEVLINK_DYN_ATTR_TYPE_BINARY,
 	__DEVLINK_DYN_ATTR_TYPE_CUSTOM_BASE = 0x80,
 	/* Any possible custom types, unrelated to NLA_* values go below */
+	DEVLINK_DYN_ATTR_TYPE_U32_ARRAY,
 };
 
 enum devlink_attr {