Re: [PATCH bpf-next v2 2/3] selftests/bpf: support array presets in veristat

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Jun 5, 2025 at 11:36 AM Mykyta Yatsenko
<mykyta.yatsenko5@xxxxxxxxx> wrote:
>
> From: Mykyta Yatsenko <yatsenko@xxxxxxxx>
>
> Implement support for presetting values for array elements in veristat.
> For example:
> ```
> sudo ./veristat set_global_vars.bpf.o -G "arr[3] = 1"
> ```
> Arrays of structures and structure of arrays work, but each individual
> scalar value has to be set separately: `foo[1].bar[2] = value`.
>
> Signed-off-by: Mykyta Yatsenko <yatsenko@xxxxxxxx>
> ---
>  tools/testing/selftests/bpf/veristat.c | 145 +++++++++++++++++++++----
>  1 file changed, 126 insertions(+), 19 deletions(-)
>

[...]

> @@ -1440,7 +1458,7 @@ static int append_var_preset(struct var_preset **presets, int *cnt, const char *
>         memset(cur, 0, sizeof(*cur));
>         (*cnt)++;
>
> -       if (sscanf(expr, "%s = %s %n", var, val, &n) != 2 || n != strlen(expr)) {
> +       if (sscanf(expr, "%[][a-zA-Z0-9_.] = %s %n", var, val, &n) != 2 || n != strlen(expr)) {
>                 fprintf(stderr, "Failed to parse expression '%s'\n", expr);
>                 return -EINVAL;
>         }
> @@ -1533,6 +1551,74 @@ static bool is_preset_supported(const struct btf_type *t)
>         return btf_is_int(t) || btf_is_enum(t) || btf_is_enum64(t);
>  }
>
> +static int find_enum_value(const struct btf *btf, const char *name, int *value)

shouldn't value be long long or u64?

> +{
> +       const struct btf_type *t;
> +       int cnt, i;
> +       long long lvalue;
> +
> +       cnt = btf__type_cnt(btf);
> +       for (i = 1; i != cnt; ++i) {
> +               t = btf__type_by_id(btf, i);
> +
> +               if (!btf_is_any_enum(t))
> +                       continue;
> +
> +               if (enum_value_from_name(btf, t, name, &lvalue) == 0) {
> +                       *value = (int)lvalue;

why truncating here?

> +                       return 0;
> +               }
> +       }
> +       return -ESRCH;
> +}
> +
> +static int adjust_array_secinfo(const struct btf *btf, const struct btf_type *t,
> +                               const struct var_preset_atom *var_atom,
> +                               struct btf_var_secinfo *sinfo)
> +{
> +       struct btf_array *barr;
> +       const struct btf_type *type;
> +       int tid, index;
> +
> +       if (!btf_is_array(t))
> +               return -EINVAL;
> +
> +       barr = btf_array(t);
> +       tid = btf__resolve_type(btf, barr->type);
> +       type = btf__type_by_id(btf, tid);
> +       if (!btf_is_int(type) && !btf_is_any_enum(type) && !btf_is_composite(type)) {
> +               fprintf(stderr,
> +                       "Unsupported array type for variable %s. Only int, enum, struct, union are supported\n",

array element type?

> +                       var_atom->name);
> +               return -EINVAL;
> +       }
> +       switch (var_atom->index.type) {
> +       case INTEGRAL:
> +               index = var_atom->index.ivalue;
> +               break;
> +       case ENUMERATOR:
> +               if (find_enum_value(btf, var_atom->index.svalue, &index) != 0) {
> +                       fprintf(stderr, "Could not find array index as enum value %s",

nit: maybe "Can't resolve %s enum as an array index"?

> +                               var_atom->index.svalue);
> +                       return -EINVAL;
> +               }
> +               break;
> +       case NONE:
> +               fprintf(stderr, "Array index is expected for %s\n", var_atom->name);
> +               return -EINVAL;
> +       }
> +
> +       if (index < 0 || index >= barr->nelems) {
> +               fprintf(stderr, "Preset index %d is invalid or out of bounds [0, %d]\n",

nelems is u32, so %u

> +                       index, barr->nelems);
> +               return -EINVAL;
> +       }
> +       sinfo->size = type->size;
> +       sinfo->type = tid;
> +       sinfo->offset += index * type->size;
> +       return 0;
> +}
> +
>  const int btf_find_member(const struct btf *btf,
>                           const struct btf_type *parent_type,
>                           __u32 parent_offset,
> @@ -1540,7 +1626,7 @@ const int btf_find_member(const struct btf *btf,
>                           int *member_tid,
>                           __u32 *member_offset)
>  {
> -       int i;
> +       int i, err;
>
>         if (!btf_is_composite(parent_type))
>                 return -EINVAL;
> @@ -1559,16 +1645,27 @@ const int btf_find_member(const struct btf *btf,
>                 if (member->name_off) {
>                         const char *name = btf__name_by_offset(btf, member->name_off);
>
> -                       if (strcmp(var_atom->name, name) == 0) {
> -                               if (btf_member_bitfield_size(parent_type, i) != 0) {
> -                                       fprintf(stderr, "Bitfield presets are not supported %s\n",
> -                                               name);
> -                                       return -EINVAL;
> -                               }
> -                               *member_offset = parent_offset + member->offset;
> -                               *member_tid = tid;
> -                               return 0;
> +                       if (strcmp(var_atom->name, name) != 0)
> +                               continue;
> +
> +                       if (btf_member_bitfield_size(parent_type, i) != 0) {
> +                               fprintf(stderr, "Bitfield presets are not supported %s\n",
> +                                       name);
> +                               return -EINVAL;
> +                       }
> +                       *member_offset = parent_offset + member->offset;
> +                       *member_tid = tid;
> +                       if (btf_is_array(member_type)) {
> +                               struct btf_var_secinfo sinfo = {.offset = 0};
> +
> +                               err = adjust_array_secinfo(btf, member_type,
> +                                                          var_atom, &sinfo);
> +                               if (err)
> +                                       return err;
> +                               *member_tid = sinfo.type;
> +                               *member_offset += sinfo.offset * 8;
>                         }
> +                       return 0;
>                 } else if (btf_is_composite(member_type)) {
>                         int err;

error message if array index is specified for non-array type?

please check again my comments around this functions from [0]

  [0] https://lore.kernel.org/bpf/CAEf4Bzb3=brMXMBZ-AGj8xdr80XEs2Og0XeZ1zuiHnFNWWPJJQ@xxxxxxxxxxxxxx/

>
> @@ -1579,7 +1676,7 @@ const int btf_find_member(const struct btf *btf,
>                 }
>         }
>
> -       return -EINVAL;
> +       return -ESRCH;
>  }
>
>  static int adjust_var_secinfo(struct btf *btf, const struct btf_type *t,
> @@ -1590,6 +1687,12 @@ static int adjust_var_secinfo(struct btf *btf, const struct btf_type *t,
>         __u32 member_offset = 0;
>
>         base_type = btf__type_by_id(btf, btf__resolve_type(btf, t->type));
> +       if (btf_is_array(base_type)) {
> +               err = adjust_array_secinfo(btf, base_type, &preset->atoms[0], sinfo);
> +               if (err)
> +                       return err;
> +               base_type = btf__type_by_id(btf, sinfo->type);
> +       }
>
>         for (i = 1; i < preset->atom_count; ++i) {
>                 err = btf_find_member(btf, base_type, 0, &preset->atoms[i],
> @@ -1739,8 +1842,9 @@ static int set_global_vars(struct bpf_object *obj, struct var_preset *presets, i
>         }
>         for (i = 0; i < npresets; ++i) {
>                 if (!presets[i].applied) {
> -                       fprintf(stderr, "Global variable preset %s has not been applied\n",
> -                               presets[i].full_name);
> +                       fprintf(stderr, "Global variable preset %s has not been applied %s\n",

is this a debugging leftover? not sure why logging both full name and
just first atom?..


> +                               presets[i].full_name, presets[i].atoms[0].name);
> +                       err = -EINVAL;
>                 }
>                 presets[i].applied = false;
>         }
> @@ -2928,8 +3032,11 @@ int main(int argc, char **argv)
>         free(env.deny_filters);
>         for (i = 0; i < env.npresets; ++i) {
>                 free(env.presets[i].full_name);
> -               for (j = 0; j < env.presets[i].atom_count; ++j)
> +               for (j = 0; j < env.presets[i].atom_count; ++j) {
>                         free(env.presets[i].atoms[j].name);
> +                       if (env.presets[i].atoms[j].index.type == ENUMERATOR)
> +                               free(env.presets[i].atoms[j].index.svalue);
> +               }
>                 free(env.presets[i].atoms);
>                 if (env.presets[i].value.type == ENUMERATOR)
>                         free(env.presets[i].value.svalue);
> --
> 2.49.0
>





[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux