forked from mirrors/linux
		
	scripts/bpf: teach bpf_helpers_doc.py to dump BPF helper definitions
Enhance scripts/bpf_helpers_doc.py to emit C header with BPF helper definitions (to be included from libbpf's bpf_helpers.h). Signed-off-by: Andrii Nakryiko <andriin@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
		
							parent
							
								
									5f0e541278
								
							
						
					
					
						commit
						7a387bed47
					
				
					 1 changed files with 154 additions and 1 deletions
				
			
		| 
						 | 
				
			
			@ -391,6 +391,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 xpd_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("")
 | 
			
		||||
        print("Unrecognized type '%s', please add it to known types!" % t)
 | 
			
		||||
        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 +553,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 +567,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()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue