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: <20250228021837.880041-11-saeed@kernel.org>
Date: Thu, 27 Feb 2025 18:18:37 -0800
From: Saeed Mahameed <saeed@...nel.org>
To: stephen@...workplumber.org,
	dsahern@...il.com,
	Jiri Pirko <jiri@...dia.com>,
	jiri@...nulli.us
Cc: netdev@...r.kernel.org,
	Saeed Mahameed <saeedm@...dia.com>
Subject: [PATCH iproute2 10/10] devlink: params set: add support for nested attributes values

From: Saeed Mahameed <saeedm@...dia.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@...dia.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


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ