diff options
Diffstat (limited to 'scripts/bpf_doc.py')
| -rwxr-xr-x | scripts/bpf_doc.py | 119 | 
1 files changed, 99 insertions, 20 deletions
| diff --git a/scripts/bpf_doc.py b/scripts/bpf_doc.py index e74a01a85070..c77dc40f7689 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 @@ -37,11 +38,17 @@ class APIElement(object):      @desc: textual description of the symbol      @ret: (optional) description of any associated return value      """ -    def __init__(self, proto='', desc='', ret='', attrs=[]): +    def __init__(self, proto='', desc='', ret=''):          self.proto = proto          self.desc = desc          self.ret = ret -        self.attrs = attrs + +    def to_dict(self): +        return { +            'proto': self.proto, +            'desc': self.desc, +            'ret': self.ret +        }  class Helper(APIElement): @@ -51,8 +58,9 @@ class Helper(APIElement):      @desc: textual description of the helper function      @ret: description of the return value of the helper function      """ -    def __init__(self, *args, **kwargs): -        super().__init__(*args, **kwargs) +    def __init__(self, proto='', desc='', ret='', attrs=[]): +        super().__init__(proto, desc, ret) +        self.attrs = attrs          self.enum_val = None      def proto_break_down(self): @@ -81,6 +89,12 @@ class Helper(APIElement):          return res +    def to_dict(self): +        d = super().to_dict() +        d["attrs"] = self.attrs +        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] +        out_dict = {'syscall': syscall_dicts} +        print(json.dumps(out_dict, indent=4)) +  ###############################################################################  # If script is launched from scripts/ from kernel tree and can access @@ -905,9 +956,17 @@ script = os.path.abspath(sys.argv[0])  linuxRoot = os.path.dirname(os.path.dirname(script))  bpfh = os.path.join(linuxRoot, 'include/uapi/linux/bpf.h') +# target -> output format -> printer  printers = { -        'helpers': PrinterHelpersRST, -        'syscall': PrinterSyscallRST, +    'helpers': { +        'rst': PrinterHelpersRST, +        'json': PrinterHelpersJSON, +        'header': PrinterHelpersHeader, +    }, +    'syscall': { +        'rst': PrinterSyscallRST, +        'json': PrinterSyscallJSON +    },  }  argParser = argparse.ArgumentParser(description=""" @@ -917,6 +976,8 @@ rst2man utility.  """)  argParser.add_argument('--header', action='store_true',                         help='generate C header file') +argParser.add_argument('--json', action='store_true', +                       help='generate a JSON')  if (os.path.isfile(bpfh)):      argParser.add_argument('--filename', help='path to include/uapi/linux/bpf.h',                             default=bpfh) @@ -924,17 +985,35 @@ else:      argParser.add_argument('--filename', help='path to include/uapi/linux/bpf.h')  argParser.add_argument('target', nargs='?', default='helpers',                         choices=printers.keys(), help='eBPF API target') -args = argParser.parse_args() - -# Parse file. -headerParser = HeaderParser(args.filename) -headerParser.run() -# Print formatted output to standard output. -if args.header: -    if args.target != 'helpers': -        raise NotImplementedError('Only helpers header generation is supported') -    printer = PrinterHelpers(headerParser) -else: -    printer = printers[args.target](headerParser) -printer.print_all() +def error_die(message: str): +    argParser.print_usage(file=sys.stderr) +    print('Error: {}'.format(message), file=sys.stderr) +    exit(1) + +def parse_and_dump(): +    args = argParser.parse_args() + +    # Parse file. +    headerParser = HeaderParser(args.filename) +    headerParser.run() + +    if args.header and args.json: +        error_die('Use either --header or --json, not both') + +    output_format = 'rst' +    if args.header: +        output_format = 'header' +    elif args.json: +        output_format = 'json' + +    try: +        printer = printers[args.target][output_format](headerParser) +        # Print formatted output to standard output. +        printer.print_all() +    except KeyError: +        error_die('Unsupported target/format combination: "{}", "{}"' +                    .format(args.target, output_format)) + +if __name__ == "__main__": +    parse_and_dump() | 
