dev: add enum arg type 90/43790/4
authorDamjan Marion <[email protected]>
Mon, 29 Sep 2025 12:50:49 +0000 (14:50 +0200)
committerMohammed HAWARI <[email protected]>
Tue, 30 Sep 2025 09:18:46 +0000 (09:18 +0000)
Type: improvement
Change-Id: Iafae917a52b848f146f8a9651e26812702501751
Signed-off-by: Damjan Marion <[email protected]>
src/vnet/dev/args.c
src/vnet/dev/args.h
src/vnet/dev/dev_funcs.h

index 07d1078..4366965 100644 (file)
@@ -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, "<not set>");
 
-      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);
index a256cfe..c16d6d6 100644 (file)
@@ -9,14 +9,16 @@
 #include <vnet/dev/errors.h>
 
 #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,         \
index 27172f7..aa50017 100644 (file)
@@ -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)
 {