Re: [PATCH bpf-next v3] scripts/bpf_doc.py: implement json output format

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

 



2025-05-07 13:30 UTC-0700 ~ Ihor Solodrai <isolodrai@xxxxxxxx>
> bpf_doc.py parses bpf.h header to collect information about various
> API elements (such as BPF helpers) and then dump them in one of the
> supported formats: rst docs and a C header.
> 
> It's useful for external tools to be able to consume this information
> in an easy-to-parse format such as JSON. Implement JSON printers and
> add --json command line argument.
> 
> v2->v3: nit cleanup
> v1->v2: add json printer for syscall target
> 
> v2: https://lore.kernel.org/bpf/20250507182802.3833349-1-isolodrai@xxxxxxxx/
> v1: https://lore.kernel.org/bpf/20250506000605.497296-1-isolodrai@xxxxxxxx/
> 
> Signed-off-by: Ihor Solodrai <isolodrai@xxxxxxxx>
> ---
>  scripts/bpf_doc.py | 111 ++++++++++++++++++++++++++++++++++++++-------
>  1 file changed, 95 insertions(+), 16 deletions(-)
> 
> diff --git a/scripts/bpf_doc.py b/scripts/bpf_doc.py
> index e74a01a85070..b157fab016a3 100755
> --- a/scripts/bpf_doc.py
> +++ b/scripts/bpf_doc.py
> @@ -8,6 +8,7 @@
>  from __future__ import print_function
>  
>  import argparse
> +import json
>  import re
>  import sys, os
>  import subprocess
> @@ -43,6 +44,14 @@ class APIElement(object):
>          self.ret = ret
>          self.attrs = attrs
>  
> +    def to_dict(self):
> +        return {
> +            'proto': self.proto,
> +            'desc': self.desc,
> +            'ret': self.ret,
> +            'attrs': self.attrs
> +        }
> +
>  
>  class Helper(APIElement):
>      """
> @@ -81,6 +90,11 @@ class Helper(APIElement):
>  
>          return res
>  
> +    def to_dict(self):
> +        d = super().to_dict()
> +        d.update(self.proto_break_down())
> +        return d
> +
>  
>  ATTRS = {
>      '__bpf_fastcall': 'bpf_fastcall'
> @@ -675,7 +689,7 @@ COMMANDS
>          self.print_elem(command)
>  
>  
> -class PrinterHelpers(Printer):
> +class PrinterHelpersHeader(Printer):
>      """
>      A printer for dumping collected information about helpers as C header to
>      be included from BPF program.
> @@ -896,6 +910,43 @@ class PrinterHelpers(Printer):
>          print(') = (void *) %d;' % helper.enum_val)
>          print('')
>  
> +
> +class PrinterHelpersJSON(Printer):
> +    """
> +    A printer for dumping collected information about helpers as a JSON file.
> +    @parser: A HeaderParser with Helper objects
> +    """
> +
> +    def __init__(self, parser):
> +        self.elements = parser.helpers
> +        self.elem_number_check(
> +            parser.desc_unique_helpers,
> +            parser.define_unique_helpers,
> +            "helper",
> +            "___BPF_FUNC_MAPPER",
> +        )
> +
> +    def print_all(self):
> +        helper_dicts = [helper.to_dict() for helper in self.elements]
> +        out_dict = {'helpers': helper_dicts}
> +        print(json.dumps(out_dict, indent=4))
> +
> +
> +class PrinterSyscallJSON(Printer):
> +    """
> +    A printer for dumping collected syscall information as a JSON file.
> +    @parser: A HeaderParser with APIElement objects
> +    """
> +
> +    def __init__(self, parser):
> +        self.elements = parser.commands
> +        self.elem_number_check(parser.desc_syscalls, parser.enum_syscalls, 'syscall', 'bpf_cmd')
> +
> +    def print_all(self):
> +        syscall_dicts = [syscall.to_dict() for syscall in self.elements]


Looks good and works well, thanks! I tested it and have one more nit:
for syscalls, with JSON, we print an empty "attrs" array for each
syscall subcommand, because the attributes are used with helpers only.
Could we avoid printing these, please? We could refactor the attribute
parsing code to make it apply to helpers only, but the easiest approach
is probably to just discard the attributes from JSON right here, before
we print the dict:

           # Attributes do not apply to syscall subcommands docs
           for syscall in syscall_dicts:
               del syscall['attrs']


> +        out_dict = {'syscall': syscall_dicts}
> +        print(json.dumps(out_dict, indent=4))
> +
>  ###############################################################################
>  




[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