0001
0002
0003
0004
0005
0006
0007
0008 from __future__ import print_function
0009
0010 import argparse
0011 import re
0012 import sys, os
0013
0014 class NoHelperFound(BaseException):
0015 pass
0016
0017 class NoSyscallCommandFound(BaseException):
0018 pass
0019
0020 class ParsingError(BaseException):
0021 def __init__(self, line='<line not provided>', reader=None):
0022 if reader:
0023 BaseException.__init__(self,
0024 'Error at file offset %d, parsing line: %s' %
0025 (reader.tell(), line))
0026 else:
0027 BaseException.__init__(self, 'Error parsing line: %s' % line)
0028
0029
0030 class APIElement(object):
0031 """
0032 An object representing the description of an aspect of the eBPF API.
0033 @proto: prototype of the API symbol
0034 @desc: textual description of the symbol
0035 @ret: (optional) description of any associated return value
0036 """
0037 def __init__(self, proto='', desc='', ret=''):
0038 self.proto = proto
0039 self.desc = desc
0040 self.ret = ret
0041
0042
0043 class Helper(APIElement):
0044 """
0045 An object representing the description of an eBPF helper function.
0046 @proto: function prototype of the helper function
0047 @desc: textual description of the helper function
0048 @ret: description of the return value of the helper function
0049 """
0050 def proto_break_down(self):
0051 """
0052 Break down helper function protocol into smaller chunks: return type,
0053 name, distincts arguments.
0054 """
0055 arg_re = re.compile('((\w+ )*?(\w+|...))( (\**)(\w+))?$')
0056 res = {}
0057 proto_re = re.compile('(.+) (\**)(\w+)\(((([^,]+)(, )?){1,5})\)$')
0058
0059 capture = proto_re.match(self.proto)
0060 res['ret_type'] = capture.group(1)
0061 res['ret_star'] = capture.group(2)
0062 res['name'] = capture.group(3)
0063 res['args'] = []
0064
0065 args = capture.group(4).split(', ')
0066 for a in args:
0067 capture = arg_re.match(a)
0068 res['args'].append({
0069 'type' : capture.group(1),
0070 'star' : capture.group(5),
0071 'name' : capture.group(6)
0072 })
0073
0074 return res
0075
0076
0077 class HeaderParser(object):
0078 """
0079 An object used to parse a file in order to extract the documentation of a
0080 list of eBPF helper functions. All the helpers that can be retrieved are
0081 stored as Helper object, in the self.helpers() array.
0082 @filename: name of file to parse, usually include/uapi/linux/bpf.h in the
0083 kernel tree
0084 """
0085 def __init__(self, filename):
0086 self.reader = open(filename, 'r')
0087 self.line = ''
0088 self.helpers = []
0089 self.commands = []
0090 self.desc_unique_helpers = set()
0091 self.define_unique_helpers = []
0092 self.desc_syscalls = []
0093 self.enum_syscalls = []
0094
0095 def parse_element(self):
0096 proto = self.parse_symbol()
0097 desc = self.parse_desc(proto)
0098 ret = self.parse_ret(proto)
0099 return APIElement(proto=proto, desc=desc, ret=ret)
0100
0101 def parse_helper(self):
0102 proto = self.parse_proto()
0103 desc = self.parse_desc(proto)
0104 ret = self.parse_ret(proto)
0105 return Helper(proto=proto, desc=desc, ret=ret)
0106
0107 def parse_symbol(self):
0108 p = re.compile(' \* ?(BPF\w+)$')
0109 capture = p.match(self.line)
0110 if not capture:
0111 raise NoSyscallCommandFound
0112 end_re = re.compile(' \* ?NOTES$')
0113 end = end_re.match(self.line)
0114 if end:
0115 raise NoSyscallCommandFound
0116 self.line = self.reader.readline()
0117 return capture.group(1)
0118
0119 def parse_proto(self):
0120
0121
0122
0123
0124
0125
0126
0127 p = re.compile(' \* ?((.+) \**\w+\((((const )?(struct )?(\w+|\.\.\.)( \**\w+)?)(, )?){1,5}\))$')
0128 capture = p.match(self.line)
0129 if not capture:
0130 raise NoHelperFound
0131 self.line = self.reader.readline()
0132 return capture.group(1)
0133
0134 def parse_desc(self, proto):
0135 p = re.compile(' \* ?(?:\t| {5,8})Description$')
0136 capture = p.match(self.line)
0137 if not capture:
0138 raise Exception("No description section found for " + proto)
0139
0140
0141 desc = ''
0142 desc_present = False
0143 while True:
0144 self.line = self.reader.readline()
0145 if self.line == ' *\n':
0146 desc += '\n'
0147 else:
0148 p = re.compile(' \* ?(?:\t| {5,8})(?:\t| {8})(.*)')
0149 capture = p.match(self.line)
0150 if capture:
0151 desc_present = True
0152 desc += capture.group(1) + '\n'
0153 else:
0154 break
0155
0156 if not desc_present:
0157 raise Exception("No description found for " + proto)
0158 return desc
0159
0160 def parse_ret(self, proto):
0161 p = re.compile(' \* ?(?:\t| {5,8})Return$')
0162 capture = p.match(self.line)
0163 if not capture:
0164 raise Exception("No return section found for " + proto)
0165
0166
0167 ret = ''
0168 ret_present = False
0169 while True:
0170 self.line = self.reader.readline()
0171 if self.line == ' *\n':
0172 ret += '\n'
0173 else:
0174 p = re.compile(' \* ?(?:\t| {5,8})(?:\t| {8})(.*)')
0175 capture = p.match(self.line)
0176 if capture:
0177 ret_present = True
0178 ret += capture.group(1) + '\n'
0179 else:
0180 break
0181
0182 if not ret_present:
0183 raise Exception("No return found for " + proto)
0184 return ret
0185
0186 def seek_to(self, target, help_message, discard_lines = 1):
0187 self.reader.seek(0)
0188 offset = self.reader.read().find(target)
0189 if offset == -1:
0190 raise Exception(help_message)
0191 self.reader.seek(offset)
0192 self.reader.readline()
0193 for _ in range(discard_lines):
0194 self.reader.readline()
0195 self.line = self.reader.readline()
0196
0197 def parse_desc_syscall(self):
0198 self.seek_to('* DOC: eBPF Syscall Commands',
0199 'Could not find start of eBPF syscall descriptions list')
0200 while True:
0201 try:
0202 command = self.parse_element()
0203 self.commands.append(command)
0204 self.desc_syscalls.append(command.proto)
0205
0206 except NoSyscallCommandFound:
0207 break
0208
0209 def parse_enum_syscall(self):
0210 self.seek_to('enum bpf_cmd {',
0211 'Could not find start of bpf_cmd enum', 0)
0212
0213 bpf_p = re.compile('\s*(BPF\w+)+')
0214
0215
0216
0217
0218 assign_p = re.compile('\s*(BPF\w+)\s*=\s*(BPF\w+)')
0219 bpf_cmd_str = ''
0220 while True:
0221 capture = assign_p.match(self.line)
0222 if capture:
0223
0224 self.line = self.reader.readline()
0225 continue
0226 capture = bpf_p.match(self.line)
0227 if capture:
0228 bpf_cmd_str += self.line
0229 else:
0230 break
0231 self.line = self.reader.readline()
0232
0233 self.enum_syscalls = re.findall('(BPF\w+)+', bpf_cmd_str)
0234
0235 def parse_desc_helpers(self):
0236 self.seek_to('* Start of BPF helper function descriptions:',
0237 'Could not find start of eBPF helper descriptions list')
0238 while True:
0239 try:
0240 helper = self.parse_helper()
0241 self.helpers.append(helper)
0242 proto = helper.proto_break_down()
0243 self.desc_unique_helpers.add(proto['name'])
0244 except NoHelperFound:
0245 break
0246
0247 def parse_define_helpers(self):
0248
0249
0250
0251
0252 self.seek_to('#define __BPF_FUNC_MAPPER(FN)',
0253 'Could not find start of eBPF helper definition list')
0254
0255 p = re.compile('\s*(FN\(\w+\))+|\\\\')
0256 fn_defines_str = ''
0257 while True:
0258 capture = p.match(self.line)
0259 if capture:
0260 fn_defines_str += self.line
0261 else:
0262 break
0263 self.line = self.reader.readline()
0264
0265 self.define_unique_helpers = re.findall('FN\(\w+\)', fn_defines_str)
0266
0267 def run(self):
0268 self.parse_desc_syscall()
0269 self.parse_enum_syscall()
0270 self.parse_desc_helpers()
0271 self.parse_define_helpers()
0272 self.reader.close()
0273
0274
0275
0276 class Printer(object):
0277 """
0278 A generic class for printers. Printers should be created with an array of
0279 Helper objects, and implement a way to print them in the desired fashion.
0280 @parser: A HeaderParser with objects to print to standard output
0281 """
0282 def __init__(self, parser):
0283 self.parser = parser
0284 self.elements = []
0285
0286 def print_header(self):
0287 pass
0288
0289 def print_footer(self):
0290 pass
0291
0292 def print_one(self, helper):
0293 pass
0294
0295 def print_all(self):
0296 self.print_header()
0297 for elem in self.elements:
0298 self.print_one(elem)
0299 self.print_footer()
0300
0301 def elem_number_check(self, desc_unique_elem, define_unique_elem, type, instance):
0302 """
0303 Checks the number of helpers/syscalls documented within the header file
0304 description with those defined as part of enum/macro and raise an
0305 Exception if they don't match.
0306 """
0307 nr_desc_unique_elem = len(desc_unique_elem)
0308 nr_define_unique_elem = len(define_unique_elem)
0309 if nr_desc_unique_elem != nr_define_unique_elem:
0310 exception_msg = '''
0311 The number of unique %s in description (%d) doesn\'t match the number of unique %s defined in %s (%d)
0312 ''' % (type, nr_desc_unique_elem, type, instance, nr_define_unique_elem)
0313 if nr_desc_unique_elem < nr_define_unique_elem:
0314
0315
0316 exception_msg += '''
0317 The description for %s is not present or formatted correctly.
0318 ''' % (define_unique_elem[nr_desc_unique_elem])
0319 raise Exception(exception_msg)
0320
0321 class PrinterRST(Printer):
0322 """
0323 A generic class for printers that print ReStructured Text. Printers should
0324 be created with a HeaderParser object, and implement a way to print API
0325 elements in the desired fashion.
0326 @parser: A HeaderParser with objects to print to standard output
0327 """
0328 def __init__(self, parser):
0329 self.parser = parser
0330
0331 def print_license(self):
0332 license = '''\
0333 .. Copyright (C) All BPF authors and contributors from 2014 to present.
0334 .. See git log include/uapi/linux/bpf.h in kernel tree for details.
0335 ..
0336 .. SPDX-License-Identifier: Linux-man-pages-copyleft
0337 ..
0338 .. Please do not edit this file. It was generated from the documentation
0339 .. located in file include/uapi/linux/bpf.h of the Linux kernel sources
0340 .. (helpers description), and from scripts/bpf_doc.py in the same
0341 .. repository (header and footer).
0342 '''
0343 print(license)
0344
0345 def print_elem(self, elem):
0346 if (elem.desc):
0347 print('\tDescription')
0348
0349
0350 for line in re.sub('\n$', '', elem.desc, count=1).split('\n'):
0351 print('{}{}'.format('\t\t' if line else '', line))
0352
0353 if (elem.ret):
0354 print('\tReturn')
0355 for line in elem.ret.rstrip().split('\n'):
0356 print('{}{}'.format('\t\t' if line else '', line))
0357
0358 print('')
0359
0360 class PrinterHelpersRST(PrinterRST):
0361 """
0362 A printer for dumping collected information about helpers as a ReStructured
0363 Text page compatible with the rst2man program, which can be used to
0364 generate a manual page for the helpers.
0365 @parser: A HeaderParser with Helper objects to print to standard output
0366 """
0367 def __init__(self, parser):
0368 self.elements = parser.helpers
0369 self.elem_number_check(parser.desc_unique_helpers, parser.define_unique_helpers, 'helper', '__BPF_FUNC_MAPPER')
0370
0371 def print_header(self):
0372 header = '''\
0373 ===========
0374 BPF-HELPERS
0375 ===========
0376 -------------------------------------------------------------------------------
0377 list of eBPF helper functions
0378 -------------------------------------------------------------------------------
0379
0380 :Manual section: 7
0381
0382 DESCRIPTION
0383 ===========
0384
0385 The extended Berkeley Packet Filter (eBPF) subsystem consists in programs
0386 written in a pseudo-assembly language, then attached to one of the several
0387 kernel hooks and run in reaction of specific events. This framework differs
0388 from the older, "classic" BPF (or "cBPF") in several aspects, one of them being
0389 the ability to call special functions (or "helpers") from within a program.
0390 These functions are restricted to a white-list of helpers defined in the
0391 kernel.
0392
0393 These helpers are used by eBPF programs to interact with the system, or with
0394 the context in which they work. For instance, they can be used to print
0395 debugging messages, to get the time since the system was booted, to interact
0396 with eBPF maps, or to manipulate network packets. Since there are several eBPF
0397 program types, and that they do not run in the same context, each program type
0398 can only call a subset of those helpers.
0399
0400 Due to eBPF conventions, a helper can not have more than five arguments.
0401
0402 Internally, eBPF programs call directly into the compiled helper functions
0403 without requiring any foreign-function interface. As a result, calling helpers
0404 introduces no overhead, thus offering excellent performance.
0405
0406 This document is an attempt to list and document the helpers available to eBPF
0407 developers. They are sorted by chronological order (the oldest helpers in the
0408 kernel at the top).
0409
0410 HELPERS
0411 =======
0412 '''
0413 PrinterRST.print_license(self)
0414 print(header)
0415
0416 def print_footer(self):
0417 footer = '''
0418 EXAMPLES
0419 ========
0420
0421 Example usage for most of the eBPF helpers listed in this manual page are
0422 available within the Linux kernel sources, at the following locations:
0423
0424 * *samples/bpf/*
0425 * *tools/testing/selftests/bpf/*
0426
0427 LICENSE
0428 =======
0429
0430 eBPF programs can have an associated license, passed along with the bytecode
0431 instructions to the kernel when the programs are loaded. The format for that
0432 string is identical to the one in use for kernel modules (Dual licenses, such
0433 as "Dual BSD/GPL", may be used). Some helper functions are only accessible to
0434 programs that are compatible with the GNU Privacy License (GPL).
0435
0436 In order to use such helpers, the eBPF program must be loaded with the correct
0437 license string passed (via **attr**) to the **bpf**\ () system call, and this
0438 generally translates into the C source code of the program containing a line
0439 similar to the following:
0440
0441 ::
0442
0443 char ____license[] __attribute__((section("license"), used)) = "GPL";
0444
0445 IMPLEMENTATION
0446 ==============
0447
0448 This manual page is an effort to document the existing eBPF helper functions.
0449 But as of this writing, the BPF sub-system is under heavy development. New eBPF
0450 program or map types are added, along with new helper functions. Some helpers
0451 are occasionally made available for additional program types. So in spite of
0452 the efforts of the community, this page might not be up-to-date. If you want to
0453 check by yourself what helper functions exist in your kernel, or what types of
0454 programs they can support, here are some files among the kernel tree that you
0455 may be interested in:
0456
0457 * *include/uapi/linux/bpf.h* is the main BPF header. It contains the full list
0458 of all helper functions, as well as many other BPF definitions including most
0459 of the flags, structs or constants used by the helpers.
0460 * *net/core/filter.c* contains the definition of most network-related helper
0461 functions, and the list of program types from which they can be used.
0462 * *kernel/trace/bpf_trace.c* is the equivalent for most tracing program-related
0463 helpers.
0464 * *kernel/bpf/verifier.c* contains the functions used to check that valid types
0465 of eBPF maps are used with a given helper function.
0466 * *kernel/bpf/* directory contains other files in which additional helpers are
0467 defined (for cgroups, sockmaps, etc.).
0468 * The bpftool utility can be used to probe the availability of helper functions
0469 on the system (as well as supported program and map types, and a number of
0470 other parameters). To do so, run **bpftool feature probe** (see
0471 **bpftool-feature**\ (8) for details). Add the **unprivileged** keyword to
0472 list features available to unprivileged users.
0473
0474 Compatibility between helper functions and program types can generally be found
0475 in the files where helper functions are defined. Look for the **struct
0476 bpf_func_proto** objects and for functions returning them: these functions
0477 contain a list of helpers that a given program type can call. Note that the
0478 **default:** label of the **switch ... case** used to filter helpers can call
0479 other functions, themselves allowing access to additional helpers. The
0480 requirement for GPL license is also in those **struct bpf_func_proto**.
0481
0482 Compatibility between helper functions and map types can be found in the
0483 **check_map_func_compatibility**\ () function in file *kernel/bpf/verifier.c*.
0484
0485 Helper functions that invalidate the checks on **data** and **data_end**
0486 pointers for network processing are listed in function
0487 **bpf_helper_changes_pkt_data**\ () in file *net/core/filter.c*.
0488
0489 SEE ALSO
0490 ========
0491
0492 **bpf**\ (2),
0493 **bpftool**\ (8),
0494 **cgroups**\ (7),
0495 **ip**\ (8),
0496 **perf_event_open**\ (2),
0497 **sendmsg**\ (2),
0498 **socket**\ (7),
0499 **tc-bpf**\ (8)'''
0500 print(footer)
0501
0502 def print_proto(self, helper):
0503 """
0504 Format function protocol with bold and italics markers. This makes RST
0505 file less readable, but gives nice results in the manual page.
0506 """
0507 proto = helper.proto_break_down()
0508
0509 print('**%s %s%s(' % (proto['ret_type'],
0510 proto['ret_star'].replace('*', '\\*'),
0511 proto['name']),
0512 end='')
0513
0514 comma = ''
0515 for a in proto['args']:
0516 one_arg = '{}{}'.format(comma, a['type'])
0517 if a['name']:
0518 if a['star']:
0519 one_arg += ' {}**\ '.format(a['star'].replace('*', '\\*'))
0520 else:
0521 one_arg += '** '
0522 one_arg += '*{}*\\ **'.format(a['name'])
0523 comma = ', '
0524 print(one_arg, end='')
0525
0526 print(')**')
0527
0528 def print_one(self, helper):
0529 self.print_proto(helper)
0530 self.print_elem(helper)
0531
0532
0533 class PrinterSyscallRST(PrinterRST):
0534 """
0535 A printer for dumping collected information about the syscall API as a
0536 ReStructured Text page compatible with the rst2man program, which can be
0537 used to generate a manual page for the syscall.
0538 @parser: A HeaderParser with APIElement objects to print to standard
0539 output
0540 """
0541 def __init__(self, parser):
0542 self.elements = parser.commands
0543 self.elem_number_check(parser.desc_syscalls, parser.enum_syscalls, 'syscall', 'bpf_cmd')
0544
0545 def print_header(self):
0546 header = '''\
0547 ===
0548 bpf
0549 ===
0550 -------------------------------------------------------------------------------
0551 Perform a command on an extended BPF object
0552 -------------------------------------------------------------------------------
0553
0554 :Manual section: 2
0555
0556 COMMANDS
0557 ========
0558 '''
0559 PrinterRST.print_license(self)
0560 print(header)
0561
0562 def print_one(self, command):
0563 print('**%s**' % (command.proto))
0564 self.print_elem(command)
0565
0566
0567 class PrinterHelpers(Printer):
0568 """
0569 A printer for dumping collected information about helpers as C header to
0570 be included from BPF program.
0571 @parser: A HeaderParser with Helper objects to print to standard output
0572 """
0573 def __init__(self, parser):
0574 self.elements = parser.helpers
0575 self.elem_number_check(parser.desc_unique_helpers, parser.define_unique_helpers, 'helper', '__BPF_FUNC_MAPPER')
0576
0577 type_fwds = [
0578 'struct bpf_fib_lookup',
0579 'struct bpf_sk_lookup',
0580 'struct bpf_perf_event_data',
0581 'struct bpf_perf_event_value',
0582 'struct bpf_pidns_info',
0583 'struct bpf_redir_neigh',
0584 'struct bpf_sock',
0585 'struct bpf_sock_addr',
0586 'struct bpf_sock_ops',
0587 'struct bpf_sock_tuple',
0588 'struct bpf_spin_lock',
0589 'struct bpf_sysctl',
0590 'struct bpf_tcp_sock',
0591 'struct bpf_tunnel_key',
0592 'struct bpf_xfrm_state',
0593 'struct linux_binprm',
0594 'struct pt_regs',
0595 'struct sk_reuseport_md',
0596 'struct sockaddr',
0597 'struct tcphdr',
0598 'struct seq_file',
0599 'struct tcp6_sock',
0600 'struct tcp_sock',
0601 'struct tcp_timewait_sock',
0602 'struct tcp_request_sock',
0603 'struct udp6_sock',
0604 'struct unix_sock',
0605 'struct task_struct',
0606
0607 'struct __sk_buff',
0608 'struct sk_msg_md',
0609 'struct xdp_md',
0610 'struct path',
0611 'struct btf_ptr',
0612 'struct inode',
0613 'struct socket',
0614 'struct file',
0615 'struct bpf_timer',
0616 'struct mptcp_sock',
0617 'struct bpf_dynptr',
0618 'struct iphdr',
0619 'struct ipv6hdr',
0620 ]
0621 known_types = {
0622 '...',
0623 'void',
0624 'const void',
0625 'char',
0626 'const char',
0627 'int',
0628 'long',
0629 'unsigned long',
0630
0631 '__be16',
0632 '__be32',
0633 '__wsum',
0634
0635 'struct bpf_fib_lookup',
0636 'struct bpf_perf_event_data',
0637 'struct bpf_perf_event_value',
0638 'struct bpf_pidns_info',
0639 'struct bpf_redir_neigh',
0640 'struct bpf_sk_lookup',
0641 'struct bpf_sock',
0642 'struct bpf_sock_addr',
0643 'struct bpf_sock_ops',
0644 'struct bpf_sock_tuple',
0645 'struct bpf_spin_lock',
0646 'struct bpf_sysctl',
0647 'struct bpf_tcp_sock',
0648 'struct bpf_tunnel_key',
0649 'struct bpf_xfrm_state',
0650 'struct linux_binprm',
0651 'struct pt_regs',
0652 'struct sk_reuseport_md',
0653 'struct sockaddr',
0654 'struct tcphdr',
0655 'struct seq_file',
0656 'struct tcp6_sock',
0657 'struct tcp_sock',
0658 'struct tcp_timewait_sock',
0659 'struct tcp_request_sock',
0660 'struct udp6_sock',
0661 'struct unix_sock',
0662 'struct task_struct',
0663 'struct path',
0664 'struct btf_ptr',
0665 'struct inode',
0666 'struct socket',
0667 'struct file',
0668 'struct bpf_timer',
0669 'struct mptcp_sock',
0670 'struct bpf_dynptr',
0671 'struct iphdr',
0672 'struct ipv6hdr',
0673 }
0674 mapped_types = {
0675 'u8': '__u8',
0676 'u16': '__u16',
0677 'u32': '__u32',
0678 'u64': '__u64',
0679 's8': '__s8',
0680 's16': '__s16',
0681 's32': '__s32',
0682 's64': '__s64',
0683 'size_t': 'unsigned long',
0684 'struct bpf_map': 'void',
0685 'struct sk_buff': 'struct __sk_buff',
0686 'const struct sk_buff': 'const struct __sk_buff',
0687 'struct sk_msg_buff': 'struct sk_msg_md',
0688 'struct xdp_buff': 'struct xdp_md',
0689 }
0690
0691 overloaded_helpers = [
0692 'bpf_get_socket_cookie',
0693 'bpf_sk_assign',
0694 ]
0695
0696 def print_header(self):
0697 header = '''\
0698 /* This is auto-generated file. See bpf_doc.py for details. */
0699
0700 /* Forward declarations of BPF structs */'''
0701
0702 print(header)
0703 for fwd in self.type_fwds:
0704 print('%s;' % fwd)
0705 print('')
0706
0707 def print_footer(self):
0708 footer = ''
0709 print(footer)
0710
0711 def map_type(self, t):
0712 if t in self.known_types:
0713 return t
0714 if t in self.mapped_types:
0715 return self.mapped_types[t]
0716 print("Unrecognized type '%s', please add it to known types!" % t,
0717 file=sys.stderr)
0718 sys.exit(1)
0719
0720 seen_helpers = set()
0721
0722 def print_one(self, helper):
0723 proto = helper.proto_break_down()
0724
0725 if proto['name'] in self.seen_helpers:
0726 return
0727 self.seen_helpers.add(proto['name'])
0728
0729 print('/*')
0730 print(" * %s" % proto['name'])
0731 print(" *")
0732 if (helper.desc):
0733
0734
0735 for line in re.sub('\n$', '', helper.desc, count=1).split('\n'):
0736 print(' *{}{}'.format(' \t' if line else '', line))
0737
0738 if (helper.ret):
0739 print(' *')
0740 print(' * Returns')
0741 for line in helper.ret.rstrip().split('\n'):
0742 print(' *{}{}'.format(' \t' if line else '', line))
0743
0744 print(' */')
0745 print('static %s %s(*%s)(' % (self.map_type(proto['ret_type']),
0746 proto['ret_star'], proto['name']), end='')
0747 comma = ''
0748 for i, a in enumerate(proto['args']):
0749 t = a['type']
0750 n = a['name']
0751 if proto['name'] in self.overloaded_helpers and i == 0:
0752 t = 'void'
0753 n = 'ctx'
0754 one_arg = '{}{}'.format(comma, self.map_type(t))
0755 if n:
0756 if a['star']:
0757 one_arg += ' {}'.format(a['star'])
0758 else:
0759 one_arg += ' '
0760 one_arg += '{}'.format(n)
0761 comma = ', '
0762 print(one_arg, end='')
0763
0764 print(') = (void *) %d;' % len(self.seen_helpers))
0765 print('')
0766
0767
0768
0769
0770
0771
0772 script = os.path.abspath(sys.argv[0])
0773 linuxRoot = os.path.dirname(os.path.dirname(script))
0774 bpfh = os.path.join(linuxRoot, 'include/uapi/linux/bpf.h')
0775
0776 printers = {
0777 'helpers': PrinterHelpersRST,
0778 'syscall': PrinterSyscallRST,
0779 }
0780
0781 argParser = argparse.ArgumentParser(description="""
0782 Parse eBPF header file and generate documentation for the eBPF API.
0783 The RST-formatted output produced can be turned into a manual page with the
0784 rst2man utility.
0785 """)
0786 argParser.add_argument('--header', action='store_true',
0787 help='generate C header file')
0788 if (os.path.isfile(bpfh)):
0789 argParser.add_argument('--filename', help='path to include/uapi/linux/bpf.h',
0790 default=bpfh)
0791 else:
0792 argParser.add_argument('--filename', help='path to include/uapi/linux/bpf.h')
0793 argParser.add_argument('target', nargs='?', default='helpers',
0794 choices=printers.keys(), help='eBPF API target')
0795 args = argParser.parse_args()
0796
0797
0798 headerParser = HeaderParser(args.filename)
0799 headerParser.run()
0800
0801
0802 if args.header:
0803 if args.target != 'helpers':
0804 raise NotImplementedError('Only helpers header generation is supported')
0805 printer = PrinterHelpers(headerParser)
0806 else:
0807 printer = printers[args.target](headerParser)
0808 printer.print_all()