Devlink param and health reporter fmsg use attributes with dynamic type which is determined according to a different type. Currently used values are NLA_*. The problem is, they are not part of UAPI. They may change which would cause a break. To make this future safe, introduce a enum that shadows NLA_* values in it and is part of UAPI. Also, this allows to possibly carry types that are unrelated to NLA_* values.
Unified · Split
| @@ -202,6 +202,28 @@ definitions: · 201 unmodified lines | ||
| 202 | 202 | name: exception |
| 203 | 203 | - |
| 204 | 204 | name: control |
| 205 | + - | |
| 206 | + type: enum | |
| 207 | + name: var-attr-type | |
| 208 | + entries: | |
| 209 | + - | |
| 210 | + name: u8 | |
| 211 | + value: 1 | |
| 212 | + - | |
| 213 | + name: u16 | |
| 214 | + - | |
| 215 | + name: u32 | |
| 216 | + - | |
| 217 | + name: u64 | |
| 218 | + - | |
| 219 | + name: string | |
| 220 | + - | |
| 221 | + name: flag | |
| 222 | + - | |
| 223 | + name: nul_string | |
| 224 | + value: 10 | |
| 225 | + - | |
| 226 | + name: binary | |
| 205 | 227 | |
| 206 | 228 | attribute-sets: |
| 207 | 229 | - |
| @@ -498,6 +520,7 @@ attribute-sets: · 290 unmodified lines | ||
| 498 | 520 | - |
| 499 | 521 | name: param-type |
| 500 | 522 | type: u8 |
| 523 | + enum: var-attr-type | |
| 501 | 524 | |
| 502 | 525 | # TODO: fill in the attributes in between |
| 503 | 526 | |
| @@ -592,6 +615,7 @@ attribute-sets: · 88 unmodified lines | ||
| 592 | 615 | - |
| 593 | 616 | name: fmsg-obj-value-type |
| 594 | 617 | type: u8 |
| 618 | + enum: var-attr-type | |
| 595 | 619 | |
| 596 | 620 | # TODO: fill in the attributes in between |
| 597 | 621 | |
| @@ -385,6 +385,21 @@ enum devlink_linecard_state { · 384 unmodified lines | ||
| 385 | 385 | DEVLINK_LINECARD_STATE_MAX = __DEVLINK_LINECARD_STATE_MAX - 1 |
| 386 | 386 | }; |
| 387 | 387 | |
| 388 | +/* Variable attribute type. */ | |
| 389 | +enum devlink_var_attr_type { | |
| 390 | + /* Following values relate to the internal NLA_* values */ | |
| 391 | + DEVLINK_VAR_ATTR_TYPE_U8 = 1, | |
| 392 | + DEVLINK_VAR_ATTR_TYPE_U16, | |
| 393 | + DEVLINK_VAR_ATTR_TYPE_U32, | |
| 394 | + DEVLINK_VAR_ATTR_TYPE_U64, | |
| 395 | + DEVLINK_VAR_ATTR_TYPE_STRING, | |
| 396 | + DEVLINK_VAR_ATTR_TYPE_FLAG, | |
| 397 | + DEVLINK_VAR_ATTR_TYPE_NUL_STRING = 10, | |
| 398 | + DEVLINK_VAR_ATTR_TYPE_BINARY, | |
| 399 | + __DEVLINK_VAR_ATTR_TYPE_CUSTOM_BASE = 0x80, | |
| 400 | + /* Any possible custom types, unrelated to NLA_* values go below */ | |
| 401 | +}; | |
| 402 | + | |
| 388 | 403 | enum devlink_attr { |
| 389 | 404 | /* don't change the order or add anything between, this is ABI! */ |
| 390 | 405 | DEVLINK_ATTR_UNSPEC, |
| @@ -930,18 +930,31 @@ EXPORT_SYMBOL_GPL(devlink_fmsg_binary_pair_put); · 929 unmodified lines | ||
| 930 | 930 | static int |
| 931 | 931 | devlink_fmsg_item_fill_type(struct devlink_fmsg_item *msg, struct sk_buff *skb) |
| 932 | 932 | { |
| 933 | + enum devlink_var_attr_type var_attr_type; | |
| 934 | + | |
| 933 | 935 | switch (msg->nla_type) { |
| 934 | 936 | case NLA_FLAG: |
| 937 | + var_attr_type = DEVLINK_VAR_ATTR_TYPE_FLAG; | |
| 938 | + break; | |
| 935 | 939 | case NLA_U8: |
| 940 | + var_attr_type = DEVLINK_VAR_ATTR_TYPE_U8; | |
| 941 | + break; | |
| 936 | 942 | case NLA_U32: |
| 943 | + var_attr_type = DEVLINK_VAR_ATTR_TYPE_U32; | |
| 944 | + break; | |
| 937 | 945 | case NLA_U64: |
| 946 | + var_attr_type = DEVLINK_VAR_ATTR_TYPE_U64; | |
| 947 | + break; | |
| 938 | 948 | case NLA_NUL_STRING: |
| 949 | + var_attr_type = DEVLINK_VAR_ATTR_TYPE_NUL_STRING; | |
| 950 | + break; | |
| 939 | 951 | case NLA_BINARY: |
| 940 | − return nla_put_u8(skb, DEVLINK_ATTR_FMSG_OBJ_VALUE_TYPE, | |
| 941 | − msg->nla_type); | |
| 952 | + var_attr_type = DEVLINK_VAR_ATTR_TYPE_BINARY; | |
| 953 | + break; | |
| 942 | 954 | default: |
| 943 | 955 | return -EINVAL; |
| 944 | 956 | } |
| 957 | + return nla_put_u8(skb, DEVLINK_ATTR_FMSG_OBJ_VALUE_TYPE, var_attr_type); | |
| 945 | 958 | } |
| 946 | 959 | |
| 947 | 960 | static int |
| @@ -10,6 +10,33 @@ · 9 unmodified lines | ||
| 10 | 10 | |
| 11 | 11 | #include <uapi/linux/devlink.h> |
| 12 | 12 | |
| 13 | +/* Sparse enums validation callbacks */ | |
| 14 | +static int | |
| 15 | +devlink_attr_param_type_validate(const struct nlattr *attr, | |
| 16 | + struct netlink_ext_ack *extack) | |
| 17 | +{ | |
| 18 | + switch (nla_get_u8(attr)) { | |
| 19 | + case DEVLINK_VAR_ATTR_TYPE_U8: | |
| 20 | + fallthrough; | |
| 21 | + case DEVLINK_VAR_ATTR_TYPE_U16: | |
| 22 | + fallthrough; | |
| 23 | + case DEVLINK_VAR_ATTR_TYPE_U32: | |
| 24 | + fallthrough; | |
| 25 | + case DEVLINK_VAR_ATTR_TYPE_U64: | |
| 26 | + fallthrough; | |
| 27 | + case DEVLINK_VAR_ATTR_TYPE_STRING: | |
| 28 | + fallthrough; | |
| 29 | + case DEVLINK_VAR_ATTR_TYPE_FLAG: | |
| 30 | + fallthrough; | |
| 31 | + case DEVLINK_VAR_ATTR_TYPE_NUL_STRING: | |
| 32 | + fallthrough; | |
| 33 | + case DEVLINK_VAR_ATTR_TYPE_BINARY: | |
| 34 | + return 0; | |
| 35 | + } | |
| 36 | + NL_SET_ERR_MSG_ATTR(extack, attr, "invalid enum value"); | |
| 37 | + return -EINVAL; | |
| 38 | +} | |
| 39 | + | |
| 13 | 40 | /* Common nested types */ |
| 14 | 41 | const struct nla_policy devlink_dl_port_function_nl_policy[DEVLINK_PORT_FN_ATTR_CAPS + 1] = { |
| 15 | 42 | [DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR] = { .type = NLA_BINARY, }, |
| @@ -273,7 +300,7 @@ static const struct nla_policy devlink_param_set_nl_policy[DEVLINK_ATTR_PARAM_VA · 257 unmodified lines | ||
| 273 | 300 | [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, }, |
| 274 | 301 | [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, }, |
| 275 | 302 | [DEVLINK_ATTR_PARAM_NAME] = { .type = NLA_NUL_STRING, }, |
| 276 | − [DEVLINK_ATTR_PARAM_TYPE] = { .type = NLA_U8, }, | |
| 303 | + [DEVLINK_ATTR_PARAM_TYPE] = NLA_POLICY_VALIDATE_FN(NLA_U8, &devlink_attr_param_type_validate), | |
| 277 | 304 | [DEVLINK_ATTR_PARAM_VALUE_CMODE] = NLA_POLICY_MAX(NLA_U8, 2), |
| 278 | 305 | }; |
| 279 | 306 | |
| @@ -167,19 +167,19 @@ static int devlink_param_set(struct devlink *devlink, · 166 unmodified lines | ||
| 167 | 167 | } |
| 168 | 168 | |
| 169 | 169 | static int |
| 170 | −devlink_param_type_to_nla_type(enum devlink_param_type param_type) | |
| 170 | +devlink_param_type_to_var_attr_type(enum devlink_param_type param_type) | |
| 171 | 171 | { |
| 172 | 172 | switch (param_type) { |
| 173 | 173 | case DEVLINK_PARAM_TYPE_U8: |
| 174 | − return NLA_U8; | |
| 174 | + return DEVLINK_VAR_ATTR_TYPE_U8; | |
| 175 | 175 | case DEVLINK_PARAM_TYPE_U16: |
| 176 | − return NLA_U16; | |
| 176 | + return DEVLINK_VAR_ATTR_TYPE_U16; | |
| 177 | 177 | case DEVLINK_PARAM_TYPE_U32: |
| 178 | − return NLA_U32; | |
| 178 | + return DEVLINK_VAR_ATTR_TYPE_U32; | |
| 179 | 179 | case DEVLINK_PARAM_TYPE_STRING: |
| 180 | − return NLA_STRING; | |
| 180 | + return DEVLINK_VAR_ATTR_TYPE_STRING; | |
| 181 | 181 | case DEVLINK_PARAM_TYPE_BOOL: |
| 182 | − return NLA_FLAG; | |
| 182 | + return DEVLINK_VAR_ATTR_TYPE_FLAG; | |
| 183 | 183 | default: |
| 184 | 184 | return -EINVAL; |
| 185 | 185 | } |
| @@ -247,7 +247,7 @@ static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink, · 61 unmodified lines | ||
| 247 | 247 | struct devlink_param_gset_ctx ctx; |
| 248 | 248 | struct nlattr *param_values_list; |
| 249 | 249 | struct nlattr *param_attr; |
| 250 | − int nla_type; | |
| 250 | + int var_attr_type; | |
| 251 | 251 | void *hdr; |
| 252 | 252 | int err; |
| 253 | 253 | int i; |
| @@ -294,10 +294,10 @@ static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink, · 40 unmodified lines | ||
| 294 | 294 | if (param->generic && nla_put_flag(msg, DEVLINK_ATTR_PARAM_GENERIC)) |
| 295 | 295 | goto param_nest_cancel; |
| 296 | 296 | |
| 297 | − nla_type = devlink_param_type_to_nla_type(param->type); | |
| 298 | − if (nla_type < 0) | |
| 297 | + var_attr_type = devlink_param_type_to_var_attr_type(param->type); | |
| 298 | + if (var_attr_type < 0) | |
| 299 | 299 | goto param_nest_cancel; |
| 300 | − if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_TYPE, nla_type)) | |
| 300 | + if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_TYPE, var_attr_type)) | |
| 301 | 301 | goto param_nest_cancel; |
| 302 | 302 | |
| 303 | 303 | param_values_list = nla_nest_start_noflag(msg, |
| @@ -420,19 +420,19 @@ devlink_param_type_get_from_info(struct genl_info *info, · 116 unmodified lines | ||
| 420 | 420 | return -EINVAL; |
| 421 | 421 | |
| 422 | 422 | switch (nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_TYPE])) { |
| 423 | − case NLA_U8: | |
| 423 | + case DEVLINK_VAR_ATTR_TYPE_U8: | |
| 424 | 424 | *param_type = DEVLINK_PARAM_TYPE_U8; |
| 425 | 425 | break; |
| 426 | − case NLA_U16: | |
| 426 | + case DEVLINK_VAR_ATTR_TYPE_U16: | |
| 427 | 427 | *param_type = DEVLINK_PARAM_TYPE_U16; |
| 428 | 428 | break; |
| 429 | − case NLA_U32: | |
| 429 | + case DEVLINK_VAR_ATTR_TYPE_U32: | |
| 430 | 430 | *param_type = DEVLINK_PARAM_TYPE_U32; |
| 431 | 431 | break; |
| 432 | − case NLA_STRING: | |
| 432 | + case DEVLINK_VAR_ATTR_TYPE_STRING: | |
| 433 | 433 | *param_type = DEVLINK_PARAM_TYPE_STRING; |
| 434 | 434 | break; |
| 435 | − case NLA_FLAG: | |
| 435 | + case DEVLINK_VAR_ATTR_TYPE_FLAG: | |
| 436 | 436 | *param_type = DEVLINK_PARAM_TYPE_BOOL; |
| 437 | 437 | break; |
| 438 | 438 | default: |