[PATCH iproute2-next] devlink: support u32-array values in devlink param show/set
From: Ratheesh Kannoth
Date: Mon Jun 15 2026 - 00:12:00 EST
Teach param value printing about MNL type 129 by walking nested attributes,
collecting u32 elements, and formatting them for output
For param set, accept a space- or comma-separated list of integers and encode
it as multiple DEVLINK_ATTR_PARAM_VALUE_DATA u32 attributes.
Pass the enclosing netlink attribute into pr_out_param_value_print so nested
payloads can be parsed alongside the existing scalar types.
- Show search order
devlink dev param show pci/0002:01:00.0 name npc_srch_order
pci/0002:01:00.0:
name npc_srch_order type driver-specific
values:
cmode runtime value value 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
- Set search order
devlink dev param set pci/0002:01:00.0 name npc_srch_order value 31,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,\
22,23,24,25,26,27,28,29,30 cmode runtime
Signed-off-by: Ratheesh Kannoth <rkannoth@xxxxxxxxxxx>
---
devlink/devlink.c | 47 +++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 43 insertions(+), 4 deletions(-)
diff --git a/devlink/devlink.c b/devlink/devlink.c
index b4deba30..efb558c5 100644
--- a/devlink/devlink.c
+++ b/devlink/devlink.c
@@ -3497,12 +3497,28 @@ static const struct param_val_conv param_val_conv[] = {
#define PARAM_VAL_CONV_LEN ARRAY_SIZE(param_val_conv)
+struct devlink_param_u32_array {
+ uint32_t size;
+ uint32_t val[32];
+};
+
+static int param_value_nested_u32_attr_cb(const struct nlattr *attr, void *data)
+{
+ struct devlink_param_u32_array *arr = data;
+
+ arr->val[arr->size++] = mnl_attr_get_u32(attr);
+
+ return MNL_CB_OK;
+}
+
static int pr_out_param_value_print(const char *nla_name, int nla_type,
struct nlattr *val_attr, bool conv_exists,
- const char *label, bool flag_as_u8)
+ const char *label, bool flag_as_u8, struct nlattr *nl)
{
+ struct devlink_param_u32_array u32_arr = { };
const char *vstr;
- int err;
+ char buffer[1024];
+ int err, cnt = 0;
print_string(PRINT_FP, NULL, " %s ", label);
@@ -3563,6 +3579,18 @@ static int pr_out_param_value_print(const char *nla_name, int nla_type,
else
print_bool(PRINT_ANY, label, "%s", val_attr);
break;
+ case 129:
+ err = mnl_attr_parse_nested(nl, param_value_nested_u32_attr_cb,
+ (void *)&u32_arr);
+ if (err != MNL_CB_OK)
+ return -EINVAL;
+
+ for (int i = 1; i < u32_arr.size; i++)
+ cnt += snprintf(buffer + cnt, sizeof(buffer) - cnt, "%u ", u32_arr.val[i]);
+
+ print_string(PRINT_ANY, "value def", " value %s", buffer);
+
+ break;
}
return 0;
@@ -3595,14 +3623,14 @@ static void pr_out_param_value(struct dl *dl, const char *nla_name,
nla_name);
err = pr_out_param_value_print(nla_name, nla_type, val_attr,
- conv_exists, "value", false);
+ conv_exists, "value", false, nl);
if (err)
return;
val_attr = nla_value[DEVLINK_ATTR_PARAM_VALUE_DEFAULT];
if (val_attr) {
err = pr_out_param_value_print(nla_name, nla_type, val_attr,
- conv_exists, "default", true);
+ conv_exists, "default", true, nl);
if (err)
return;
}
@@ -3685,6 +3713,7 @@ struct param_ctx {
uint64_t vu64;
const char *vstr;
bool vbool;
+ struct devlink_param_u32_array u32arr;
} value;
};
@@ -3764,12 +3793,14 @@ static int cmd_dev_param_set(struct dl *dl)
{
struct param_ctx ctx = {};
struct nlmsghdr *nlh;
+ char delim[] = " ,";
bool conv_exists;
uint64_t val_u64 = 0;
uint32_t val_u32;
uint16_t val_u16;
uint8_t val_u8;
bool val_bool;
+ char *token, *buf;
int err;
err = dl_argv_parse(dl, DL_OPT_HANDLE |
@@ -3904,6 +3935,14 @@ static int cmd_dev_param_set(struct dl *dl)
if (!strcmp(dl->opts.param_value, ctx.value.vstr))
return 0;
break;
+ case 129:
+ buf = (char *)dl->opts.param_value;
+ token = strtok(buf, delim);
+ while (token) {
+ mnl_attr_put_u32(nlh, DEVLINK_ATTR_PARAM_VALUE_DATA, atoi(token));
+ token = strtok(NULL, delim);
+ }
+ break;
default:
printf("Value type not supported\n");
return -ENOTSUP;
--
2.43.0