diff options
Diffstat (limited to 'scripts/bpf_helpers_doc.py')
| -rwxr-xr-x | scripts/bpf_helpers_doc.py | 157 | 
1 files changed, 154 insertions, 3 deletions
| diff --git a/scripts/bpf_helpers_doc.py b/scripts/bpf_helpers_doc.py index 894cc58c1a03..90baf7d70911 100755 --- a/scripts/bpf_helpers_doc.py +++ b/scripts/bpf_helpers_doc.py @@ -158,8 +158,6 @@ class HeaderParser(object):                  break          self.reader.close() -        print('Parsed description of %d helper function(s)' % len(self.helpers), -              file=sys.stderr)  ############################################################################### @@ -391,6 +389,154 @@ SEE ALSO          print('') +class PrinterHelpers(Printer): +    """ +    A printer for dumping collected information about helpers as C header to +    be included from BPF program. +    @helpers: array of Helper objects to print to standard output +    """ + +    type_fwds = [ +            'struct bpf_fib_lookup', +            'struct bpf_perf_event_data', +            'struct bpf_perf_event_value', +            'struct bpf_sock', +            'struct bpf_sock_addr', +            'struct bpf_sock_ops', +            'struct bpf_sock_tuple', +            'struct bpf_spin_lock', +            'struct bpf_sysctl', +            'struct bpf_tcp_sock', +            'struct bpf_tunnel_key', +            'struct bpf_xfrm_state', +            'struct pt_regs', +            'struct sk_reuseport_md', +            'struct sockaddr', +            'struct tcphdr', + +            'struct __sk_buff', +            'struct sk_msg_md', +            'struct xdp_md', +    ] +    known_types = { +            '...', +            'void', +            'const void', +            'char', +            'const char', +            'int', +            'long', +            'unsigned long', + +            '__be16', +            '__be32', +            '__wsum', + +            'struct bpf_fib_lookup', +            'struct bpf_perf_event_data', +            'struct bpf_perf_event_value', +            'struct bpf_sock', +            'struct bpf_sock_addr', +            'struct bpf_sock_ops', +            'struct bpf_sock_tuple', +            'struct bpf_spin_lock', +            'struct bpf_sysctl', +            'struct bpf_tcp_sock', +            'struct bpf_tunnel_key', +            'struct bpf_xfrm_state', +            'struct pt_regs', +            'struct sk_reuseport_md', +            'struct sockaddr', +            'struct tcphdr', +    } +    mapped_types = { +            'u8': '__u8', +            'u16': '__u16', +            'u32': '__u32', +            'u64': '__u64', +            's8': '__s8', +            's16': '__s16', +            's32': '__s32', +            's64': '__s64', +            'size_t': 'unsigned long', +            'struct bpf_map': 'void', +            'struct sk_buff': 'struct __sk_buff', +            'const struct sk_buff': 'const struct __sk_buff', +            'struct sk_msg_buff': 'struct sk_msg_md', +            'struct xdp_buff': 'struct xdp_md', +    } + +    def print_header(self): +        header = '''\ +/* This is auto-generated file. See bpf_helpers_doc.py for details. */ + +/* Forward declarations of BPF structs */''' + +        print(header) +        for fwd in self.type_fwds: +            print('%s;' % fwd) +        print('') + +    def print_footer(self): +        footer = '' +        print(footer) + +    def map_type(self, t): +        if t in self.known_types: +            return t +        if t in self.mapped_types: +            return self.mapped_types[t] +        print("Unrecognized type '%s', please add it to known types!" % t, +              file=sys.stderr) +        sys.exit(1) + +    seen_helpers = set() + +    def print_one(self, helper): +        proto = helper.proto_break_down() + +        if proto['name'] in self.seen_helpers: +            return +        self.seen_helpers.add(proto['name']) + +        print('/*') +        print(" * %s" % proto['name']) +        print(" *") +        if (helper.desc): +            # Do not strip all newline characters: formatted code at the end of +            # a section must be followed by a blank line. +            for line in re.sub('\n$', '', helper.desc, count=1).split('\n'): +                print(' *{}{}'.format(' \t' if line else '', line)) + +        if (helper.ret): +            print(' *') +            print(' * Returns') +            for line in helper.ret.rstrip().split('\n'): +                print(' *{}{}'.format(' \t' if line else '', line)) + +        print(' */') +        print('static %s %s(*%s)(' % (self.map_type(proto['ret_type']), +                                      proto['ret_star'], proto['name']), end='') +        comma = '' +        for i, a in enumerate(proto['args']): +            t = a['type'] +            n = a['name'] +            if proto['name'] == 'bpf_get_socket_cookie' and i == 0: +                    t = 'void' +                    n = 'ctx' +            one_arg = '{}{}'.format(comma, self.map_type(t)) +            if n: +                if a['star']: +                    one_arg += ' {}'.format(a['star']) +                else: +                    one_arg += ' ' +                one_arg += '{}'.format(n) +            comma = ', ' +            print(one_arg, end='') + +        print(') = (void *) %d;' % len(self.seen_helpers)) +        print('') +  ###############################################################################  # If script is launched from scripts/ from kernel tree and can access @@ -405,6 +551,8 @@ Parse eBPF header file and generate documentation for eBPF helper functions.  The RST-formatted output produced can be turned into a manual page with the  rst2man utility.  """) +argParser.add_argument('--header', action='store_true', +                       help='generate C header file')  if (os.path.isfile(bpfh)):      argParser.add_argument('--filename', help='path to include/uapi/linux/bpf.h',                             default=bpfh) @@ -417,5 +565,8 @@ headerParser = HeaderParser(args.filename)  headerParser.run()  # Print formatted output to standard output. -printer = PrinterRST(headerParser.helpers) +if args.header: +    printer = PrinterHelpers(headerParser.helpers) +else: +    printer = PrinterRST(headerParser.helpers)  printer.print_all() |