diff mbox series

[bpf-next,v2,11/18] bpftool: Add btf enum64 support

Message ID 20220514031319.3245326-1-yhs@fb.com (mailing list archive)
State Superseded
Delegated to: BPF
Headers show
Series bpf: Add 64bit enum value support | expand

Checks

Context Check Description
bpf/vmtest-bpf-next-PR fail PR summary
netdev/tree_selection success Clearly marked for bpf-next, async
netdev/fixes_present success Fixes tag not required for -next series
netdev/subject_prefix success Link
netdev/cover_letter success Series has a cover letter
netdev/patch_count fail Series longer than 15 patches (and no cover letter)
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 0 this patch: 0
netdev/cc_maintainers warning 14 maintainers not CCed: netdev@vger.kernel.org larysa.zaremba@intel.com nathan@kernel.org kafai@fb.com delyank@fb.com trix@redhat.com john.fastabend@gmail.com kpsingh@kernel.org ndesaulniers@google.com davemarchevsky@fb.com quentin@isovalent.com llvm@lists.linux.dev songliubraving@fb.com mauricio@kinvolk.io
netdev/build_clang success Errors and warnings before: 0 this patch: 0
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 0 this patch: 0
netdev/checkpatch warning WARNING: line length of 85 exceeds 80 columns
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
bpf/vmtest-bpf-next-VM_Test-1 fail Logs for Kernel LATEST on ubuntu-latest with gcc
bpf/vmtest-bpf-next-VM_Test-2 fail Logs for Kernel LATEST on ubuntu-latest with llvm-15
bpf/vmtest-bpf-next-VM_Test-3 fail Logs for Kernel LATEST on z15 with gcc

Commit Message

Yonghong Song May 14, 2022, 3:13 a.m. UTC
Add BTF_KIND_ENUM64 support.
For example, the following enum is defined in uapi bpf.h.
  $ cat core.c
  enum A {
        BPF_F_INDEX_MASK                = 0xffffffffULL,
        BPF_F_CURRENT_CPU               = BPF_F_INDEX_MASK,
        BPF_F_CTXLEN_MASK               = (0xfffffULL << 32),
  } g;
Compiled with
  clang -target bpf -O2 -g -c core.c
Using bpftool to dump types and generate format C file:
  $ bpftool btf dump file core.o
  ...
  [1] ENUM64 'A' size=8 vlen=3
        'BPF_F_INDEX_MASK' val=4294967295ULL
        'BPF_F_CURRENT_CPU' val=4294967295ULL
        'BPF_F_CTXLEN_MASK' val=4503595332403200ULL
  $ bpftool btf dump file core.o format c
  ...
  enum A {
        BPF_F_INDEX_MASK = 4294967295ULL,
        BPF_F_CURRENT_CPU = 4294967295ULL,
        BPF_F_CTXLEN_MASK = 4503595332403200ULL,
  };
  ...

The 64bit value is represented properly in BTF and C dump.

Acked-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Yonghong Song <yhs@fb.com>
---
 tools/bpf/bpftool/btf.c        | 49 ++++++++++++++++++++++++++++++++--
 tools/bpf/bpftool/btf_dumper.c | 29 ++++++++++++++++++++
 tools/bpf/bpftool/gen.c        |  1 +
 3 files changed, 77 insertions(+), 2 deletions(-)

Comments

Andrii Nakryiko May 17, 2022, 11:38 p.m. UTC | #1
On Fri, May 13, 2022 at 8:13 PM Yonghong Song <yhs@fb.com> wrote:
>
> Add BTF_KIND_ENUM64 support.
> For example, the following enum is defined in uapi bpf.h.
>   $ cat core.c
>   enum A {
>         BPF_F_INDEX_MASK                = 0xffffffffULL,
>         BPF_F_CURRENT_CPU               = BPF_F_INDEX_MASK,
>         BPF_F_CTXLEN_MASK               = (0xfffffULL << 32),
>   } g;
> Compiled with
>   clang -target bpf -O2 -g -c core.c
> Using bpftool to dump types and generate format C file:
>   $ bpftool btf dump file core.o
>   ...
>   [1] ENUM64 'A' size=8 vlen=3
>         'BPF_F_INDEX_MASK' val=4294967295ULL
>         'BPF_F_CURRENT_CPU' val=4294967295ULL
>         'BPF_F_CTXLEN_MASK' val=4503595332403200ULL
>   $ bpftool btf dump file core.o format c
>   ...
>   enum A {
>         BPF_F_INDEX_MASK = 4294967295ULL,
>         BPF_F_CURRENT_CPU = 4294967295ULL,
>         BPF_F_CTXLEN_MASK = 4503595332403200ULL,
>   };
>   ...
>
> The 64bit value is represented properly in BTF and C dump.
>
> Acked-by: Andrii Nakryiko <andrii@kernel.org>
> Signed-off-by: Yonghong Song <yhs@fb.com>
> ---
>  tools/bpf/bpftool/btf.c        | 49 ++++++++++++++++++++++++++++++++--
>  tools/bpf/bpftool/btf_dumper.c | 29 ++++++++++++++++++++
>  tools/bpf/bpftool/gen.c        |  1 +
>  3 files changed, 77 insertions(+), 2 deletions(-)
>
> diff --git a/tools/bpf/bpftool/btf.c b/tools/bpf/bpftool/btf.c
> index a2c665beda87..9e5db870fe53 100644
> --- a/tools/bpf/bpftool/btf.c
> +++ b/tools/bpf/bpftool/btf.c
> @@ -40,6 +40,7 @@ static const char * const btf_kind_str[NR_BTF_KINDS] = {
>         [BTF_KIND_FLOAT]        = "FLOAT",
>         [BTF_KIND_DECL_TAG]     = "DECL_TAG",
>         [BTF_KIND_TYPE_TAG]     = "TYPE_TAG",
> +       [BTF_KIND_ENUM64]       = "ENUM64",
>  };
>
>  struct btf_attach_point {
> @@ -228,10 +229,54 @@ static int dump_btf_type(const struct btf *btf, __u32 id,
>                         if (json_output) {
>                                 jsonw_start_object(w);
>                                 jsonw_string_field(w, "name", name);
> -                               jsonw_uint_field(w, "val", v->val);
> +                               if (btf_kflag(t))
> +                                       jsonw_int_field(w, "val", v->val);
> +                               else
> +                                       jsonw_uint_field(w, "val", v->val);
>                                 jsonw_end_object(w);
>                         } else {
> -                               printf("\n\t'%s' val=%u", name, v->val);
> +                               if (btf_kflag(t))
> +                                       printf("\n\t'%s' val=%d", name, v->val);
> +                               else
> +                                       printf("\n\t'%s' val=%u", name, v->val);
> +                       }
> +               }
> +               if (json_output)
> +                       jsonw_end_array(w);
> +               break;
> +       }
> +       case BTF_KIND_ENUM64: {
> +               const struct btf_enum64 *v = btf_enum64(t);
> +               __u16 vlen = btf_vlen(t);
> +               int i;
> +
> +               if (json_output) {
> +                       jsonw_uint_field(w, "size", t->size);
> +                       jsonw_uint_field(w, "vlen", vlen);
> +                       jsonw_name(w, "values");
> +                       jsonw_start_array(w);
> +               } else {
> +                       printf(" size=%u vlen=%u", t->size, vlen);
> +               }
> +               for (i = 0; i < vlen; i++, v++) {
> +                       const char *name = btf_str(btf, v->name_off);
> +                       __u64 val = ((__u64)v->val_hi32 << 32) | v->val_lo32;
> +
> +                       if (json_output) {
> +                               jsonw_start_object(w);
> +                               jsonw_string_field(w, "name", name);

forgot emitting kflag itself (both in bpftool and in selftests), let's
add that for both enum and enum64?

> +                               if (btf_kflag(t))
> +                                       jsonw_int_field(w, "val", val);
> +                               else
> +                                       jsonw_uint_field(w, "val", val);
> +                               jsonw_end_object(w);
> +                       } else {
> +                               if (btf_kflag(t))
> +                                       printf("\n\t'%s' val=%lldLL", name,
> +                                              (unsigned long long)val);
> +                               else
> +                                       printf("\n\t'%s' val=%lluULL", name,
> +                                              (unsigned long long)val);
>                         }
>                 }
>                 if (json_output)

[...]
Yonghong Song May 18, 2022, 9:10 p.m. UTC | #2
On 5/17/22 4:38 PM, Andrii Nakryiko wrote:
> On Fri, May 13, 2022 at 8:13 PM Yonghong Song <yhs@fb.com> wrote:
>>
>> Add BTF_KIND_ENUM64 support.
>> For example, the following enum is defined in uapi bpf.h.
>>    $ cat core.c
>>    enum A {
>>          BPF_F_INDEX_MASK                = 0xffffffffULL,
>>          BPF_F_CURRENT_CPU               = BPF_F_INDEX_MASK,
>>          BPF_F_CTXLEN_MASK               = (0xfffffULL << 32),
>>    } g;
>> Compiled with
>>    clang -target bpf -O2 -g -c core.c
>> Using bpftool to dump types and generate format C file:
>>    $ bpftool btf dump file core.o
>>    ...
>>    [1] ENUM64 'A' size=8 vlen=3
>>          'BPF_F_INDEX_MASK' val=4294967295ULL
>>          'BPF_F_CURRENT_CPU' val=4294967295ULL
>>          'BPF_F_CTXLEN_MASK' val=4503595332403200ULL
>>    $ bpftool btf dump file core.o format c
>>    ...
>>    enum A {
>>          BPF_F_INDEX_MASK = 4294967295ULL,
>>          BPF_F_CURRENT_CPU = 4294967295ULL,
>>          BPF_F_CTXLEN_MASK = 4503595332403200ULL,
>>    };
>>    ...
>>
>> The 64bit value is represented properly in BTF and C dump.
>>
>> Acked-by: Andrii Nakryiko <andrii@kernel.org>
>> Signed-off-by: Yonghong Song <yhs@fb.com>
>> ---
>>   tools/bpf/bpftool/btf.c        | 49 ++++++++++++++++++++++++++++++++--
>>   tools/bpf/bpftool/btf_dumper.c | 29 ++++++++++++++++++++
>>   tools/bpf/bpftool/gen.c        |  1 +
>>   3 files changed, 77 insertions(+), 2 deletions(-)
>>
>> diff --git a/tools/bpf/bpftool/btf.c b/tools/bpf/bpftool/btf.c
>> index a2c665beda87..9e5db870fe53 100644
>> --- a/tools/bpf/bpftool/btf.c
>> +++ b/tools/bpf/bpftool/btf.c
>> @@ -40,6 +40,7 @@ static const char * const btf_kind_str[NR_BTF_KINDS] = {
>>          [BTF_KIND_FLOAT]        = "FLOAT",
>>          [BTF_KIND_DECL_TAG]     = "DECL_TAG",
>>          [BTF_KIND_TYPE_TAG]     = "TYPE_TAG",
>> +       [BTF_KIND_ENUM64]       = "ENUM64",
>>   };
>>
>>   struct btf_attach_point {
>> @@ -228,10 +229,54 @@ static int dump_btf_type(const struct btf *btf, __u32 id,
>>                          if (json_output) {
>>                                  jsonw_start_object(w);
>>                                  jsonw_string_field(w, "name", name);
>> -                               jsonw_uint_field(w, "val", v->val);
>> +                               if (btf_kflag(t))
>> +                                       jsonw_int_field(w, "val", v->val);
>> +                               else
>> +                                       jsonw_uint_field(w, "val", v->val);
>>                                  jsonw_end_object(w);
>>                          } else {
>> -                               printf("\n\t'%s' val=%u", name, v->val);
>> +                               if (btf_kflag(t))
>> +                                       printf("\n\t'%s' val=%d", name, v->val);
>> +                               else
>> +                                       printf("\n\t'%s' val=%u", name, v->val);
>> +                       }
>> +               }
>> +               if (json_output)
>> +                       jsonw_end_array(w);
>> +               break;
>> +       }
>> +       case BTF_KIND_ENUM64: {
>> +               const struct btf_enum64 *v = btf_enum64(t);
>> +               __u16 vlen = btf_vlen(t);
>> +               int i;
>> +
>> +               if (json_output) {
>> +                       jsonw_uint_field(w, "size", t->size);
>> +                       jsonw_uint_field(w, "vlen", vlen);
>> +                       jsonw_name(w, "values");
>> +                       jsonw_start_array(w);
>> +               } else {
>> +                       printf(" size=%u vlen=%u", t->size, vlen);
>> +               }
>> +               for (i = 0; i < vlen; i++, v++) {
>> +                       const char *name = btf_str(btf, v->name_off);
>> +                       __u64 val = ((__u64)v->val_hi32 << 32) | v->val_lo32;
>> +
>> +                       if (json_output) {
>> +                               jsonw_start_object(w);
>> +                               jsonw_string_field(w, "name", name);
> 
> forgot emitting kflag itself (both in bpftool and in selftests), let's
> add that for both enum and enum64?

will do. I will also check other places whether I missed or not.

> 
>> +                               if (btf_kflag(t))
>> +                                       jsonw_int_field(w, "val", val);
>> +                               else
>> +                                       jsonw_uint_field(w, "val", val);
>> +                               jsonw_end_object(w);
>> +                       } else {
>> +                               if (btf_kflag(t))
>> +                                       printf("\n\t'%s' val=%lldLL", name,
>> +                                              (unsigned long long)val);
>> +                               else
>> +                                       printf("\n\t'%s' val=%lluULL", name,
>> +                                              (unsigned long long)val);
>>                          }
>>                  }
>>                  if (json_output)
> 
> [...]
diff mbox series

Patch

diff --git a/tools/bpf/bpftool/btf.c b/tools/bpf/bpftool/btf.c
index a2c665beda87..9e5db870fe53 100644
--- a/tools/bpf/bpftool/btf.c
+++ b/tools/bpf/bpftool/btf.c
@@ -40,6 +40,7 @@  static const char * const btf_kind_str[NR_BTF_KINDS] = {
 	[BTF_KIND_FLOAT]	= "FLOAT",
 	[BTF_KIND_DECL_TAG]	= "DECL_TAG",
 	[BTF_KIND_TYPE_TAG]	= "TYPE_TAG",
+	[BTF_KIND_ENUM64]	= "ENUM64",
 };
 
 struct btf_attach_point {
@@ -228,10 +229,54 @@  static int dump_btf_type(const struct btf *btf, __u32 id,
 			if (json_output) {
 				jsonw_start_object(w);
 				jsonw_string_field(w, "name", name);
-				jsonw_uint_field(w, "val", v->val);
+				if (btf_kflag(t))
+					jsonw_int_field(w, "val", v->val);
+				else
+					jsonw_uint_field(w, "val", v->val);
 				jsonw_end_object(w);
 			} else {
-				printf("\n\t'%s' val=%u", name, v->val);
+				if (btf_kflag(t))
+					printf("\n\t'%s' val=%d", name, v->val);
+				else
+					printf("\n\t'%s' val=%u", name, v->val);
+			}
+		}
+		if (json_output)
+			jsonw_end_array(w);
+		break;
+	}
+	case BTF_KIND_ENUM64: {
+		const struct btf_enum64 *v = btf_enum64(t);
+		__u16 vlen = btf_vlen(t);
+		int i;
+
+		if (json_output) {
+			jsonw_uint_field(w, "size", t->size);
+			jsonw_uint_field(w, "vlen", vlen);
+			jsonw_name(w, "values");
+			jsonw_start_array(w);
+		} else {
+			printf(" size=%u vlen=%u", t->size, vlen);
+		}
+		for (i = 0; i < vlen; i++, v++) {
+			const char *name = btf_str(btf, v->name_off);
+			__u64 val = ((__u64)v->val_hi32 << 32) | v->val_lo32;
+
+			if (json_output) {
+				jsonw_start_object(w);
+				jsonw_string_field(w, "name", name);
+				if (btf_kflag(t))
+					jsonw_int_field(w, "val", val);
+				else
+					jsonw_uint_field(w, "val", val);
+				jsonw_end_object(w);
+			} else {
+				if (btf_kflag(t))
+					printf("\n\t'%s' val=%lldLL", name,
+					       (unsigned long long)val);
+				else
+					printf("\n\t'%s' val=%lluULL", name,
+					       (unsigned long long)val);
 			}
 		}
 		if (json_output)
diff --git a/tools/bpf/bpftool/btf_dumper.c b/tools/bpf/bpftool/btf_dumper.c
index f5dddf8ef404..125798b0bc5d 100644
--- a/tools/bpf/bpftool/btf_dumper.c
+++ b/tools/bpf/bpftool/btf_dumper.c
@@ -182,6 +182,32 @@  static int btf_dumper_enum(const struct btf_dumper *d,
 	return 0;
 }
 
+static int btf_dumper_enum64(const struct btf_dumper *d,
+			     const struct btf_type *t,
+			     const void *data)
+{
+	const struct btf_enum64 *enums = btf_enum64(t);
+	__u32 val_lo32, val_hi32;
+	__u64 value;
+	__u16 i;
+
+	value = *(__u64 *)data;
+	val_lo32 = (__u32)value;
+	val_hi32 = value >> 32;
+
+	for (i = 0; i < btf_vlen(t); i++) {
+		if (val_lo32 == enums[i].val_lo32 && val_hi32 == enums[i].val_hi32) {
+			jsonw_string(d->jw,
+				     btf__name_by_offset(d->btf,
+							 enums[i].name_off));
+			return 0;
+		}
+	}
+
+	jsonw_int(d->jw, value);
+	return 0;
+}
+
 static bool is_str_array(const struct btf *btf, const struct btf_array *arr,
 			 const char *s)
 {
@@ -542,6 +568,8 @@  static int btf_dumper_do_type(const struct btf_dumper *d, __u32 type_id,
 		return btf_dumper_array(d, type_id, data);
 	case BTF_KIND_ENUM:
 		return btf_dumper_enum(d, t, data);
+	case BTF_KIND_ENUM64:
+		return btf_dumper_enum64(d, t, data);
 	case BTF_KIND_PTR:
 		btf_dumper_ptr(d, t, data);
 		return 0;
@@ -618,6 +646,7 @@  static int __btf_dumper_type_only(const struct btf *btf, __u32 type_id,
 			      btf__name_by_offset(btf, t->name_off));
 		break;
 	case BTF_KIND_ENUM:
+	case BTF_KIND_ENUM64:
 		BTF_PRINT_ARG("enum %s ",
 			      btf__name_by_offset(btf, t->name_off));
 		break;
diff --git a/tools/bpf/bpftool/gen.c b/tools/bpf/bpftool/gen.c
index 4c9477ff748d..14f5fe7f570e 100644
--- a/tools/bpf/bpftool/gen.c
+++ b/tools/bpf/bpftool/gen.c
@@ -1747,6 +1747,7 @@  btfgen_mark_type(struct btfgen_info *info, unsigned int type_id, bool follow_poi
 	case BTF_KIND_INT:
 	case BTF_KIND_FLOAT:
 	case BTF_KIND_ENUM:
+	case BTF_KIND_ENUM64:
 	case BTF_KIND_STRUCT:
 	case BTF_KIND_UNION:
 		break;