From 0d67b6270831589ce447aabb6cd2a3aeaa633066 Mon Sep 17 00:00:00 2001 From: Damjan Marion Date: Mon, 29 Sep 2025 14:50:49 +0200 Subject: [PATCH] dev: add enum arg type Type: improvement Change-Id: Iafae917a52b848f146f8a9651e26812702501751 Signed-off-by: Damjan Marion --- src/vnet/dev/args.c | 71 ++++++++++++++++++++++++++++++++++++++---------- src/vnet/dev/args.h | 36 +++++++++++++++++++++--- src/vnet/dev/dev_funcs.h | 10 ++++++- 3 files changed, 98 insertions(+), 19 deletions(-) diff --git a/src/vnet/dev/args.c b/src/vnet/dev/args.c index 07d10787618..4366965e88d 100644 --- a/src/vnet/dev/args.c +++ b/src/vnet/dev/args.c @@ -79,7 +79,8 @@ vnet_dev_arg_parse (vlib_main_t *vm, vnet_dev_t *dev, vnet_dev_arg_t *args, goto done; } } - else if (a->type == VNET_DEV_ARG_TYPE_UINT32) + else if (a->type == VNET_DEV_ARG_TYPE_UINT32 || + a->type == VNET_DEV_ARG_TYPE_HEX32) { u32 val, min = 0, max = CLIB_U32_MAX; if (!unformat (&in, "0x%x", &val) && !unformat (&in, "%u", &val)) @@ -107,6 +108,36 @@ vnet_dev_arg_parse (vlib_main_t *vm, vnet_dev_t *dev, vnet_dev_arg_t *args, } a->val.uint32 = val; } + else if (a->type == VNET_DEV_ARG_TYPE_ENUM) + { + u8 *s; + if (!unformat (&in, "%U", unformat_token, "a-zA-Z0-9_", &s)) + { + err = format ( + 0, "enum string expected for argument '%s', found '%U'", + a->name, format_unformat_error, &in); + goto done; + } + + vec_add1 (s, 0); + + for (vnet_dev_arg_enum_val_t *ev = a->enum_vals; ev && ev->name; + ev++) + if (strcmp (ev->name, (char *) s) == 0) + { + a->val.enum_val = ev->val; + vec_free (s); + break; + } + + if (s) + { + err = format (0, "unknown enum value '%s' for argument '%s'", s, + a->name); + vec_free (s); + goto done; + } + } else if (a->type == VNET_DEV_ARG_TYPE_STRING) { if (!unformat (&in, "%U", unformat_double_quoted_string, @@ -143,7 +174,7 @@ vnet_dev_arg_parse (vlib_main_t *vm, vnet_dev_t *dev, vnet_dev_arg_t *args, a->val_set = 1; log_debug (dev, "name '%s' type %U value %U", name, format_vnet_dev_arg_type, a->type, format_vnet_dev_arg_value, - a->type, &a->val); + a, &a->val); vec_free (name); unformat (&in, ","); } @@ -174,7 +205,7 @@ format_vnet_dev_arg_type (u8 *s, va_list *args) vnet_dev_arg_type_t t = va_arg (*args, u32); switch (t) { -#define _(n, f, val) \ +#define _(n) \ case VNET_DEV_ARG_TYPE_##n: \ return format (s, #n); foreach_vnet_dev_arg_type @@ -188,19 +219,31 @@ format_vnet_dev_arg_type (u8 *s, va_list *args) u8 * format_vnet_dev_arg_value (u8 *s, va_list *args) { - vnet_dev_arg_type_t t = va_arg (*args, u32); + vnet_dev_arg_t *a = va_arg (*args, vnet_dev_arg_t *); vnet_dev_arg_value_t *v = va_arg (*args, vnet_dev_arg_value_t *); - switch (t) + if (a->type == VNET_DEV_ARG_TYPE_ENUM) { -#define _(n, f, value) \ - case VNET_DEV_ARG_TYPE_##n: \ - s = format (s, f, v->value); \ - break; - foreach_vnet_dev_arg_type -#undef _ - default : break; + for (vnet_dev_arg_enum_val_t *ev = a->enum_vals; ev && ev->name; ev++) + if (ev->val == v->enum_val) + return format (s, "%s", ev->name); + return format (s, "%d", v->enum_val); } + + if (a->type == VNET_DEV_ARG_TYPE_UINT32) + return format (s, "%u", v->uint32); + + if (a->type == VNET_DEV_ARG_TYPE_HEX32) + return format (s, "0x%08x", v->uint32); + + if (a->type == VNET_DEV_ARG_TYPE_BOOL) + return format (s, "%s", v->boolean ? "true" : "false"); + + if (a->type == VNET_DEV_ARG_TYPE_STRING) + return format (s, "'%v'", v->string); + + ASSERT (0); + return s; } @@ -218,12 +261,12 @@ format_vnet_dev_args (u8 *s, va_list *va) int r = a - args; table_format_cell (&t, r, 0, "%s", a->name); if (a->val_set) - table_format_cell (&t, r, 1, "%U", format_vnet_dev_arg_value, a->type, + table_format_cell (&t, r, 1, "%U", format_vnet_dev_arg_value, a, &a->val); else table_format_cell (&t, r, 1, ""); - table_format_cell (&t, r, 2, "%U", format_vnet_dev_arg_value, a->type, + table_format_cell (&t, r, 2, "%U", format_vnet_dev_arg_value, a, &a->default_val); table_format_cell (&t, r, 3, "%s", a->desc); table_set_cell_align (&t, r, 0, TTAA_LEFT); diff --git a/src/vnet/dev/args.h b/src/vnet/dev/args.h index a256cfe8e0e..c16d6d6a43f 100644 --- a/src/vnet/dev/args.h +++ b/src/vnet/dev/args.h @@ -9,14 +9,16 @@ #include #define foreach_vnet_dev_arg_type \ - _ (BOOL, "%u", boolean) \ - _ (UINT32, "%u", uint32) \ - _ (STRING, "\'%v\'", string) + _ (BOOL) \ + _ (UINT32) \ + _ (HEX32) \ + _ (STRING) \ + _ (ENUM) typedef enum { VNET_DEV_ARG_END, -#define _(n, f, v) VNET_DEV_ARG_TYPE_##n, +#define _(n) VNET_DEV_ARG_TYPE_##n, foreach_vnet_dev_arg_type #undef _ } __clib_packed vnet_dev_arg_type_t; @@ -25,9 +27,16 @@ typedef union { u8 boolean; u32 uint32; + int enum_val; u8 *string; } vnet_dev_arg_value_t; +typedef struct +{ + char *name; + int val; +} vnet_dev_arg_enum_val_t; + typedef struct { char *name; @@ -37,10 +46,19 @@ typedef struct u32 min; u32 max; u64 id; + vnet_dev_arg_enum_val_t *enum_vals; vnet_dev_arg_value_t val; vnet_dev_arg_value_t default_val; } vnet_dev_arg_t; +#define VNET_DEV_ARG_ENUM_VALS(...) \ + (vnet_dev_arg_enum_val_t[]) \ + { \ + __VA_ARGS__ \ + { \ + } \ + } + #define VNET_DEV_ARG_BOOL(ud, n, d, ...) \ { \ .type = VNET_DEV_ARG_TYPE_BOOL, .id = ud, .name = n, .desc = d, \ @@ -51,6 +69,16 @@ typedef struct .type = VNET_DEV_ARG_TYPE_UINT32, .id = ud, .name = n, .desc = d, \ __VA_ARGS__ \ } +#define VNET_DEV_ARG_HEX32(ud, n, d, ...) \ + { \ + .type = VNET_DEV_ARG_TYPE_HEX32, .id = ud, .name = n, .desc = d, \ + __VA_ARGS__ \ + } +#define VNET_DEV_ARG_ENUM(ud, n, d, ...) \ + { \ + .type = VNET_DEV_ARG_TYPE_ENUM, .id = ud, .name = n, .desc = d, \ + __VA_ARGS__ \ + } #define VNET_DEV_ARG_STRING(ud, n, d, ...) \ { \ .type = VNET_DEV_ARG_TYPE_STRING, .id = ud, .name = n, .desc = d, \ diff --git a/src/vnet/dev/dev_funcs.h b/src/vnet/dev/dev_funcs.h index 27172f7da2c..aa50017a5cd 100644 --- a/src/vnet/dev/dev_funcs.h +++ b/src/vnet/dev/dev_funcs.h @@ -422,10 +422,18 @@ vnet_dev_arg_get_bool (vnet_dev_arg_t *arg) static_always_inline u32 vnet_dev_arg_get_uint32 (vnet_dev_arg_t *arg) { - ASSERT (arg->type == VNET_DEV_ARG_TYPE_UINT32); + ASSERT (arg->type == VNET_DEV_ARG_TYPE_UINT32 || + arg->type == VNET_DEV_ARG_TYPE_HEX32); return arg->val_set ? arg->val.uint32 : arg->default_val.uint32; } +static_always_inline int +vnet_dev_arg_get_enum (vnet_dev_arg_t *arg) +{ + ASSERT (arg->type == VNET_DEV_ARG_TYPE_ENUM); + return arg->val_set ? arg->val.enum_val : arg->default_val.enum_val; +} + static_always_inline u8 * vnet_dev_arg_get_string (vnet_dev_arg_t *arg) { -- 2.16.6