]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
libbpf: Allow specifying 64-bit integers in map BTF.
authorAlexei Starovoitov <ast@kernel.org>
Thu, 7 Mar 2024 03:12:26 +0000 (19:12 -0800)
committerMartin KaFai Lau <martin.lau@kernel.org>
Thu, 7 Mar 2024 22:58:48 +0000 (14:58 -0800)
__uint() macro that is used to specify map attributes like:
  __uint(type, BPF_MAP_TYPE_ARRAY);
  __uint(map_flags, BPF_F_MMAPABLE);
It is limited to 32-bit, since BTF_KIND_ARRAY has u32 "number of elements"
field in "struct btf_array".

Introduce __ulong() macro that allows specifying values bigger than 32-bit.
In map definition "map_extra" is the only u64 field, so far.

Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/r/20240307031228.42896-5-alexei.starovoitov@gmail.com
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
tools/lib/bpf/bpf_helpers.h
tools/lib/bpf/libbpf.c

index 79eaa581be98a1c4d5273829cdf28014a8e56cbc..112b1504e072dc73a3e23f787af0b606fad93ad5 100644 (file)
@@ -13,6 +13,7 @@
 #define __uint(name, val) int (*name)[val]
 #define __type(name, val) typeof(val) *name
 #define __array(name, val) typeof(val) *name[]
+#define __ulong(name, val) enum { ___bpf_concat(__unique_value, __COUNTER__) = val } name
 
 /*
  * Helper macro to place programs, maps, license in
index 672fca94ff534b03baa8ab51dd8dfbc33c529f3b..567ad367e7aa7a95d4ef8830fdb3a6a995a75792 100644 (file)
@@ -2335,6 +2335,46 @@ static bool get_map_field_int(const char *map_name, const struct btf *btf,
        return true;
 }
 
+static bool get_map_field_long(const char *map_name, const struct btf *btf,
+                              const struct btf_member *m, __u64 *res)
+{
+       const struct btf_type *t = skip_mods_and_typedefs(btf, m->type, NULL);
+       const char *name = btf__name_by_offset(btf, m->name_off);
+
+       if (btf_is_ptr(t)) {
+               __u32 res32;
+               bool ret;
+
+               ret = get_map_field_int(map_name, btf, m, &res32);
+               if (ret)
+                       *res = (__u64)res32;
+               return ret;
+       }
+
+       if (!btf_is_enum(t) && !btf_is_enum64(t)) {
+               pr_warn("map '%s': attr '%s': expected ENUM or ENUM64, got %s.\n",
+                       map_name, name, btf_kind_str(t));
+               return false;
+       }
+
+       if (btf_vlen(t) != 1) {
+               pr_warn("map '%s': attr '%s': invalid __ulong\n",
+                       map_name, name);
+               return false;
+       }
+
+       if (btf_is_enum(t)) {
+               const struct btf_enum *e = btf_enum(t);
+
+               *res = e->val;
+       } else {
+               const struct btf_enum64 *e = btf_enum64(t);
+
+               *res = btf_enum64_value(e);
+       }
+       return true;
+}
+
 static int pathname_concat(char *buf, size_t buf_sz, const char *path, const char *name)
 {
        int len;
@@ -2568,9 +2608,9 @@ int parse_btf_map_def(const char *map_name, struct btf *btf,
                        map_def->pinning = val;
                        map_def->parts |= MAP_DEF_PINNING;
                } else if (strcmp(name, "map_extra") == 0) {
-                       __u32 map_extra;
+                       __u64 map_extra;
 
-                       if (!get_map_field_int(map_name, btf, m, &map_extra))
+                       if (!get_map_field_long(map_name, btf, m, &map_extra))
                                return -EINVAL;
                        map_def->map_extra = map_extra;
                        map_def->parts |= MAP_DEF_MAP_EXTRA;