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 | name: exception | 202 | name: exception |
| 203 | - | 203 | - |
| 204 | name: control | 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 | attribute-sets: | 228 | attribute-sets: |
| 207 | - | 229 | - |
| @@ -498,6 +520,7 @@ attribute-sets: · 290 unmodified lines | |||
| 498 | - | 520 | - |
| 499 | name: param-type | 521 | name: param-type |
| 500 | type: u8 | 522 | type: u8 |
| 523 | enum: var-attr-type | ||
| 501 | 524 | ||
| 502 | # TODO: fill in the attributes in between | 525 | # TODO: fill in the attributes in between |
| 503 | 526 | ||
| @@ -592,6 +615,7 @@ attribute-sets: · 88 unmodified lines | |||
| 592 | - | 615 | - |
| 593 | name: fmsg-obj-value-type | 616 | name: fmsg-obj-value-type |
| 594 | type: u8 | 617 | type: u8 |
| 618 | enum: var-attr-type | ||
| 595 | 619 | ||
| 596 | # TODO: fill in the attributes in between | 620 | # TODO: fill in the attributes in between |
| 597 | 621 | ||
| @@ -385,6 +385,21 @@ enum devlink_linecard_state { · 384 unmodified lines | |||
| 385 | DEVLINK_LINECARD_STATE_MAX = __DEVLINK_LINECARD_STATE_MAX - 1 | 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 | enum devlink_attr { | 403 | enum devlink_attr { |
| 389 | /* don't change the order or add anything between, this is ABI! */ | 404 | /* don't change the order or add anything between, this is ABI! */ |
| 390 | DEVLINK_ATTR_UNSPEC, | 405 | DEVLINK_ATTR_UNSPEC, |
| @@ -930,18 +930,31 @@ EXPORT_SYMBOL_GPL(devlink_fmsg_binary_pair_put); · 929 unmodified lines | |||
| 930 | static int | 930 | static int |
| 931 | devlink_fmsg_item_fill_type(struct devlink_fmsg_item *msg, struct sk_buff *skb) | 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 | switch (msg->nla_type) { | 935 | switch (msg->nla_type) { |
| 934 | case NLA_FLAG: | 936 | case NLA_FLAG: |
| 937 | var_attr_type = DEVLINK_VAR_ATTR_TYPE_FLAG; | ||
| 938 | break; | ||
| 935 | case NLA_U8: | 939 | case NLA_U8: |
| 940 | var_attr_type = DEVLINK_VAR_ATTR_TYPE_U8; | ||
| 941 | break; | ||
| 936 | case NLA_U32: | 942 | case NLA_U32: |
| 943 | var_attr_type = DEVLINK_VAR_ATTR_TYPE_U32; | ||
| 944 | break; | ||
| 937 | case NLA_U64: | 945 | case NLA_U64: |
| 946 | var_attr_type = DEVLINK_VAR_ATTR_TYPE_U64; | ||
| 947 | break; | ||
| 938 | case NLA_NUL_STRING: | 948 | case NLA_NUL_STRING: |
| 949 | var_attr_type = DEVLINK_VAR_ATTR_TYPE_NUL_STRING; | ||
| 950 | break; | ||
| 939 | case NLA_BINARY: | 951 | case NLA_BINARY: |
| 940 | return nla_put_u8(skb, DEVLINK_ATTR_FMSG_OBJ_VALUE_TYPE, | 952 | var_attr_type = DEVLINK_VAR_ATTR_TYPE_BINARY; |
| 941 | msg->nla_type); | 953 | break; |
| 942 | default: | 954 | default: |
| 943 | return -EINVAL; | 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 | static int | 960 | static int |
| @@ -10,6 +10,33 @@ · 9 unmodified lines | |||
| 10 | 10 | ||
| 11 | #include <uapi/linux/devlink.h> | 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 | /* Common nested types */ | 40 | /* Common nested types */ |
| 14 | const struct nla_policy devlink_dl_port_function_nl_policy[DEVLINK_PORT_FN_ATTR_CAPS + 1] = { | 41 | const struct nla_policy devlink_dl_port_function_nl_policy[DEVLINK_PORT_FN_ATTR_CAPS + 1] = { |
| 15 | [DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR] = { .type = NLA_BINARY, }, | 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 | [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, }, | 300 | [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, }, |
| 274 | [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, }, | 301 | [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, }, |
| 275 | [DEVLINK_ATTR_PARAM_NAME] = { .type = NLA_NUL_STRING, }, | 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 | [DEVLINK_ATTR_PARAM_VALUE_CMODE] = NLA_POLICY_MAX(NLA_U8, 2), | 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 | static int | 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 | switch (param_type) { | 172 | switch (param_type) { |
| 173 | case DEVLINK_PARAM_TYPE_U8: | 173 | case DEVLINK_PARAM_TYPE_U8: |
| 174 | return NLA_U8; | 174 | return DEVLINK_VAR_ATTR_TYPE_U8; |
| 175 | case DEVLINK_PARAM_TYPE_U16: | 175 | case DEVLINK_PARAM_TYPE_U16: |
| 176 | return NLA_U16; | 176 | return DEVLINK_VAR_ATTR_TYPE_U16; |
| 177 | case DEVLINK_PARAM_TYPE_U32: | 177 | case DEVLINK_PARAM_TYPE_U32: |
| 178 | return NLA_U32; | 178 | return DEVLINK_VAR_ATTR_TYPE_U32; |
| 179 | case DEVLINK_PARAM_TYPE_STRING: | 179 | case DEVLINK_PARAM_TYPE_STRING: |
| 180 | return NLA_STRING; | 180 | return DEVLINK_VAR_ATTR_TYPE_STRING; |
| 181 | case DEVLINK_PARAM_TYPE_BOOL: | 181 | case DEVLINK_PARAM_TYPE_BOOL: |
| 182 | return NLA_FLAG; | 182 | return DEVLINK_VAR_ATTR_TYPE_FLAG; |
| 183 | default: | 183 | default: |
| 184 | return -EINVAL; | 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 | struct devlink_param_gset_ctx ctx; | 247 | struct devlink_param_gset_ctx ctx; |
| 248 | struct nlattr *param_values_list; | 248 | struct nlattr *param_values_list; |
| 249 | struct nlattr *param_attr; | 249 | struct nlattr *param_attr; |
| 250 | int nla_type; | 250 | int var_attr_type; |
| 251 | void *hdr; | 251 | void *hdr; |
| 252 | int err; | 252 | int err; |
| 253 | int i; | 253 | int i; |
| @@ -294,10 +294,10 @@ static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink, · 40 unmodified lines | |||
| 294 | if (param->generic && nla_put_flag(msg, DEVLINK_ATTR_PARAM_GENERIC)) | 294 | if (param->generic && nla_put_flag(msg, DEVLINK_ATTR_PARAM_GENERIC)) |
| 295 | goto param_nest_cancel; | 295 | goto param_nest_cancel; |
| 296 | 296 | ||
| 297 | nla_type = devlink_param_type_to_nla_type(param->type); | 297 | var_attr_type = devlink_param_type_to_var_attr_type(param->type); |
| 298 | if (nla_type < 0) | 298 | if (var_attr_type < 0) |
| 299 | goto param_nest_cancel; | 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 | goto param_nest_cancel; | 301 | goto param_nest_cancel; |
| 302 | 302 | ||
| 303 | param_values_list = nla_nest_start_noflag(msg, | 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 | return -EINVAL; | 420 | return -EINVAL; |
| 421 | 421 | ||
| 422 | switch (nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_TYPE])) { | 422 | switch (nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_TYPE])) { |
| 423 | case NLA_U8: | 423 | case DEVLINK_VAR_ATTR_TYPE_U8: |
| 424 | *param_type = DEVLINK_PARAM_TYPE_U8; | 424 | *param_type = DEVLINK_PARAM_TYPE_U8; |
| 425 | break; | 425 | break; |
| 426 | case NLA_U16: | 426 | case DEVLINK_VAR_ATTR_TYPE_U16: |
| 427 | *param_type = DEVLINK_PARAM_TYPE_U16; | 427 | *param_type = DEVLINK_PARAM_TYPE_U16; |
| 428 | break; | 428 | break; |
| 429 | case NLA_U32: | 429 | case DEVLINK_VAR_ATTR_TYPE_U32: |
| 430 | *param_type = DEVLINK_PARAM_TYPE_U32; | 430 | *param_type = DEVLINK_PARAM_TYPE_U32; |
| 431 | break; | 431 | break; |
| 432 | case NLA_STRING: | 432 | case DEVLINK_VAR_ATTR_TYPE_STRING: |
| 433 | *param_type = DEVLINK_PARAM_TYPE_STRING; | 433 | *param_type = DEVLINK_PARAM_TYPE_STRING; |
| 434 | break; | 434 | break; |
| 435 | case NLA_FLAG: | 435 | case DEVLINK_VAR_ATTR_TYPE_FLAG: |
| 436 | *param_type = DEVLINK_PARAM_TYPE_BOOL; | 436 | *param_type = DEVLINK_PARAM_TYPE_BOOL; |
| 437 | break; | 437 | break; |
| 438 | default: | 438 | default: |