All of lore.kernel.org
 help / color / mirror / Atom feed
From: Saeed Mahameed <saeed@kernel.org>
To: stephen@networkplumber.org, dsahern@gmail.com,
	Jiri Pirko <jiri@nvidia.com>,
	jiri@resnulli.us
Cc: netdev@vger.kernel.org, Saeed Mahameed <saeedm@nvidia.com>
Subject: [PATCH iproute2 10/10] devlink: params set: add support for nested attributes values
Date: Thu, 27 Feb 2025 18:18:37 -0800	[thread overview]
Message-ID: <20250228021837.880041-11-saeed@kernel.org> (raw)
In-Reply-To: <20250228021837.880041-1-saeed@kernel.org>

From: Saeed Mahameed <saeedm@nvidia.com>

Update the dl_params helper functions to proccess nested value
attributes of the type DEVLINK_ATTR_PARAM_VALUE_DATA. Vlaues are of the
type u32.

Add command line parssing to parse comma separted u32 user inputs and
fill the nlmsg accordingly, check for size mistmach between
current kernel value and user input.

example:
$ devlink dev param set <dev> name foo value 1,2,3,4,5,6,7,8 cmode ...

Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
---
 devlink/devlink.c | 102 ++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 90 insertions(+), 12 deletions(-)

diff --git a/devlink/devlink.c b/devlink/devlink.c
index 2ad15b45..15883a1c 100644
--- a/devlink/devlink.c
+++ b/devlink/devlink.c
@@ -3426,29 +3426,29 @@ struct dl_param_val_list {
 };
 
 /* 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]
+ * @val_nest_attr: nested attribute containing the list of values
+ *                 val_nest_attr = nla_value[DEVLINK_ATTR_PARAM_VALUE]
  * @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,
+dl_mnl_parse_param_val_nested(struct nlattr *val_nest_attr,
 			      struct dl_param_val_list **list)
 {
 	struct dl_param_val_list *new_list;
-	struct nlattr *val_attr;
+	struct nlattr *val_data_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;
-
+	mnl_attr_for_each_nested(val_data_attr, val_nest_attr)
+		if (mnl_attr_get_type(val_data_attr) == DEVLINK_ATTR_PARAM_VALUE_DATA)
+			len++;
 	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);
+	mnl_attr_for_each_nested(val_data_attr, val_nest_attr)
+		if (mnl_attr_get_type(val_data_attr) == DEVLINK_ATTR_PARAM_VALUE_DATA)
+			new_list->vu32[i++] = mnl_attr_get_u32(val_data_attr);
 
 	new_list->len = i;
 	*list = new_list;
@@ -3543,7 +3543,7 @@ static void pr_out_param_value(struct dl *dl, const char *nla_name,
 			int err;
 			int i;
 
-			err = dl_mnl_parse_param_val_nested(val_attr, &list);
+			err = dl_mnl_parse_param_val_nested(nl, &list);
 			if (err)
 				return;
 
@@ -3637,9 +3637,53 @@ struct dl_param {
 		uint32_t vu32;
 		const char *vstr;
 		bool vbool;
+		struct dl_param_val_list *vlist;
 	} value;
 };
 
+/* Get the parameter value from the options and fill the param struct
+ * @dl: dl struct
+ * @nla_type: type of the parameter value
+ * @param: parameter struct to store the value
+ *
+ * Note:
+ *    param->value.vlist reallocated to the new size
+ *
+ * Returns: 0 on success, -errno on failure
+ */
+static int dl_param_opts_get_arr(struct dl *dl, struct dl_param *param)
+{
+	char *tmp = strdup(dl->opts.param_value);
+	struct dl_param_val_list *list;
+	const char *p = NULL;
+	int err = 0, i = 1;
+
+	if (!tmp) {
+		pr_err("Memory allocation failed\n");
+		return -ENOMEM;
+	}
+	for (p = tmp; *p; p++)
+		i += (*p == ',');
+
+	list = realloc(param->value.vlist, sizeof(*list) + i * sizeof(uint32_t));
+	if (!list) {
+		pr_err("Memory allocation failed\n");
+		err = -ENOMEM;
+		goto out;
+	}
+	param->value.vlist = list; /* update vlist to new size */
+	i = list->len = 0; /* reset len */
+	for (p = strtok(tmp, ","); p; p = strtok(NULL, ",")) {
+		err = get_u32(&list->vu32[i++], p, 10);
+		if (err)
+			goto out;
+	}
+	/* update len only when all values are filled */
+	list->len = i;
+out:
+	free(tmp);
+	return err;
+}
 /* Get the parameter value from the options and convert it to the
  * appropriate type.
  * @dl: dl struct
@@ -3678,6 +3722,9 @@ static int dl_param_opts_get(struct dl *dl, enum devlink_dyn_attr_type type,
 			param->value.vstr = dl->opts.param_value;
 			err = 0;
 			break;
+		case DEVLINK_DYN_ATTR_TYPE_U32_ARRAY:
+			err = dl_param_opts_get_arr(dl, param);
+			break;
 		default:
 			err = -ENOTSUP;
 		}
@@ -3735,6 +3782,18 @@ static int dl_param_cmp(struct dl_param *p1, struct dl_param *p2)
 		if (strcmp(p1->value.vstr, p2->value.vstr))
 			return 1;
 		break;
+	case DEVLINK_DYN_ATTR_TYPE_U32_ARRAY:
+		if (!p1->value.vlist || !p2->value.vlist)
+			return -EINVAL;
+		if (p1->value.vlist->len != p2->value.vlist->len) {
+			pr_err("Error: expecting value list of legnth %ld\n",
+				p2->value.vlist->len);
+			return -EINVAL; /* different lengths is not expected */
+		}
+		if (memcmp(p1->value.vlist->vu32, p2->value.vlist->vu32,
+			   p1->value.vlist->len * sizeof(uint32_t)))
+			return 1;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -3766,6 +3825,18 @@ static int dl_param_mnl_put(struct nlmsghdr *nlh, struct dl_param *param)
 	case DEVLINK_DYN_ATTR_TYPE_STRING:
 		mnl_attr_put_strz(nlh, DEVLINK_ATTR_PARAM_VALUE_DATA, param->value.vstr);
 		break;
+	case DEVLINK_DYN_ATTR_TYPE_U32_ARRAY: {
+		struct dl_param_val_list *list = param->value.vlist;
+		int i;
+
+		if (!list)
+			return -EINVAL;
+
+		for (i = 0; i < list->len; i++)
+			mnl_attr_put_u32(nlh, DEVLINK_ATTR_PARAM_VALUE_DATA, list->vu32[i]);
+
+		break;
+	}
 	default:
 		pr_err("Value type(%d) not supported\n", param->type);
 		return -ENOTSUP;
@@ -3776,11 +3847,13 @@ static int dl_param_mnl_put(struct nlmsghdr *nlh, struct dl_param *param)
 /* dl_param_val_attr_parse: parse the value attribute and store the value
  * in the dl_param struct
  * @data_attr: value data attribute
+ * @val_nest_attr: parent attribute containing the values
  * @nla_type: type of the value attribute
  * @param: dl_param struct to store the value
  */
 static int
 dl_param_val_attr_parse(struct nlattr *data_attr,
+			struct nlattr *val_nest_attr,
 			enum devlink_dyn_attr_type type,
 			struct dl_param *param)
 {
@@ -3800,6 +3873,11 @@ dl_param_val_attr_parse(struct nlattr *data_attr,
 	case DEVLINK_DYN_ATTR_TYPE_FLAG:
 		param->value.vbool = data_attr ? true : false;
 		break;
+	case DEVLINK_DYN_ATTR_TYPE_U32_ARRAY:
+		if(dl_mnl_parse_param_val_nested(val_nest_attr,
+						 &param->value.vlist))
+			return -ENOMEM;
+		break;
 	default:
 		pr_err("Value type(%d) not supported\n", type);
 		return -ENOTSUP;
@@ -3857,7 +3935,7 @@ static int cmd_param_set_cb(const struct nlmsghdr *nlh, void *data)
 
 		param->cmode_found = true;
 		data_attr = nla_value[DEVLINK_ATTR_PARAM_VALUE_DATA];
-		if (dl_param_val_attr_parse(data_attr, type, param))
+		if (dl_param_val_attr_parse(data_attr, param_value_attr, type, param))
 			return MNL_CB_ERROR;
 		break;
 	}
-- 
2.48.1


      parent reply	other threads:[~2025-02-28  2:19 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-02-28  2:18 [PATCH iproute2 00/10] devlink params nested multi-attribute values Saeed Mahameed
2025-02-28  2:18 ` [PATCH iproute2 01/10] update kernel headers Saeed Mahameed
2025-02-28  2:18 ` [PATCH iproute2 02/10] devlink: use dynamic attributes enum Saeed Mahameed
2025-02-28  2:18 ` [PATCH iproute2 03/10] devlink: param show: handle multi-attribute values Saeed Mahameed
2025-02-28  2:18 ` [PATCH iproute2 04/10] devlink: param set: reuse cmd_dev_param_set_cb for port params set Saeed Mahameed
2025-02-28  2:18 ` [PATCH iproute2 05/10] devlink: rename param_ctx to dl_param Saeed Mahameed
2025-02-28  2:18 ` [PATCH iproute2 06/10] devlink: helper function to read user param input into dl_param Saeed Mahameed
2025-02-28  2:18 ` [PATCH iproute2 07/10] devlink: helper function to compare dl_params Saeed Mahameed
2025-02-28  2:18 ` [PATCH iproute2 08/10] devlink: helper function to put param value mnl attributes from dl_params Saeed Mahameed
2025-02-28  2:18 ` [PATCH iproute2 09/10] devlink: helper function to parse param vlaue attributes into dl_param Saeed Mahameed
2025-02-28  2:18 ` Saeed Mahameed [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250228021837.880041-11-saeed@kernel.org \
    --to=saeed@kernel.org \
    --cc=dsahern@gmail.com \
    --cc=jiri@nvidia.com \
    --cc=jiri@resnulli.us \
    --cc=netdev@vger.kernel.org \
    --cc=saeedm@nvidia.com \
    --cc=stephen@networkplumber.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.