uapi/bpf: Add missing description and returns for helper documentation
[linux-block.git] / scripts / bpf_doc.py
CommitLineData
3cd046f1 1#!/usr/bin/env python3
56a092c8
QM
2# SPDX-License-Identifier: GPL-2.0-only
3#
748c7c82 4# Copyright (C) 2018-2019 Netronome Systems, Inc.
923a932c 5# Copyright (C) 2021 Isovalent, Inc.
56a092c8
QM
6
7# In case user attempts to run with Python 2.
8from __future__ import print_function
9
10import argparse
11import re
12import sys, os
13
14class NoHelperFound(BaseException):
15 pass
16
a67882a2
JS
17class NoSyscallCommandFound(BaseException):
18 pass
19
56a092c8
QM
20class ParsingError(BaseException):
21 def __init__(self, line='<line not provided>', reader=None):
22 if reader:
23 BaseException.__init__(self,
24 'Error at file offset %d, parsing line: %s' %
25 (reader.tell(), line))
26 else:
27 BaseException.__init__(self, 'Error parsing line: %s' % line)
28
a67882a2
JS
29
30class APIElement(object):
56a092c8 31 """
a67882a2
JS
32 An object representing the description of an aspect of the eBPF API.
33 @proto: prototype of the API symbol
34 @desc: textual description of the symbol
35 @ret: (optional) description of any associated return value
56a092c8
QM
36 """
37 def __init__(self, proto='', desc='', ret=''):
38 self.proto = proto
39 self.desc = desc
40 self.ret = ret
41
a67882a2
JS
42
43class Helper(APIElement):
44 """
45 An object representing the description of an eBPF helper function.
46 @proto: function prototype of the helper function
47 @desc: textual description of the helper function
48 @ret: description of the return value of the helper function
49 """
56a092c8
QM
50 def proto_break_down(self):
51 """
52 Break down helper function protocol into smaller chunks: return type,
53 name, distincts arguments.
54 """
748c7c82 55 arg_re = re.compile('((\w+ )*?(\w+|...))( (\**)(\w+))?$')
56a092c8 56 res = {}
6f96674d 57 proto_re = re.compile('(.+) (\**)(\w+)\(((([^,]+)(, )?){1,5})\)$')
56a092c8
QM
58
59 capture = proto_re.match(self.proto)
60 res['ret_type'] = capture.group(1)
61 res['ret_star'] = capture.group(2)
62 res['name'] = capture.group(3)
63 res['args'] = []
64
65 args = capture.group(4).split(', ')
66 for a in args:
67 capture = arg_re.match(a)
68 res['args'].append({
69 'type' : capture.group(1),
748c7c82
QM
70 'star' : capture.group(5),
71 'name' : capture.group(6)
56a092c8
QM
72 })
73
74 return res
75
a67882a2 76
56a092c8
QM
77class HeaderParser(object):
78 """
79 An object used to parse a file in order to extract the documentation of a
80 list of eBPF helper functions. All the helpers that can be retrieved are
81 stored as Helper object, in the self.helpers() array.
82 @filename: name of file to parse, usually include/uapi/linux/bpf.h in the
83 kernel tree
84 """
85 def __init__(self, filename):
86 self.reader = open(filename, 'r')
87 self.line = ''
88 self.helpers = []
a67882a2 89 self.commands = []
71a3cdf8
UA
90 self.desc_unique_helpers = set()
91 self.define_unique_helpers = []
a67882a2
JS
92
93 def parse_element(self):
94 proto = self.parse_symbol()
95 desc = self.parse_desc()
96 ret = self.parse_ret()
97 return APIElement(proto=proto, desc=desc, ret=ret)
56a092c8
QM
98
99 def parse_helper(self):
100 proto = self.parse_proto()
101 desc = self.parse_desc()
102 ret = self.parse_ret()
103 return Helper(proto=proto, desc=desc, ret=ret)
104
a67882a2
JS
105 def parse_symbol(self):
106 p = re.compile(' \* ?(.+)$')
107 capture = p.match(self.line)
108 if not capture:
109 raise NoSyscallCommandFound
110 end_re = re.compile(' \* ?NOTES$')
111 end = end_re.match(self.line)
112 if end:
113 raise NoSyscallCommandFound
114 self.line = self.reader.readline()
115 return capture.group(1)
116
56a092c8
QM
117 def parse_proto(self):
118 # Argument can be of shape:
119 # - "void"
120 # - "type name"
121 # - "type *name"
122 # - Same as above, with "const" and/or "struct" in front of type
123 # - "..." (undefined number of arguments, for bpf_trace_printk())
124 # There is at least one term ("void"), and at most five arguments.
6f96674d 125 p = re.compile(' \* ?((.+) \**\w+\((((const )?(struct )?(\w+|\.\.\.)( \**\w+)?)(, )?){1,5}\))$')
56a092c8
QM
126 capture = p.match(self.line)
127 if not capture:
128 raise NoHelperFound
129 self.line = self.reader.readline()
130 return capture.group(1)
131
132 def parse_desc(self):
eeacb716 133 p = re.compile(' \* ?(?:\t| {5,8})Description$')
56a092c8
QM
134 capture = p.match(self.line)
135 if not capture:
136 # Helper can have empty description and we might be parsing another
137 # attribute: return but do not consume.
138 return ''
139 # Description can be several lines, some of them possibly empty, and it
140 # stops when another subsection title is met.
141 desc = ''
142 while True:
143 self.line = self.reader.readline()
144 if self.line == ' *\n':
145 desc += '\n'
146 else:
eeacb716 147 p = re.compile(' \* ?(?:\t| {5,8})(?:\t| {8})(.*)')
56a092c8
QM
148 capture = p.match(self.line)
149 if capture:
150 desc += capture.group(1) + '\n'
151 else:
152 break
153 return desc
154
155 def parse_ret(self):
eeacb716 156 p = re.compile(' \* ?(?:\t| {5,8})Return$')
56a092c8
QM
157 capture = p.match(self.line)
158 if not capture:
159 # Helper can have empty retval and we might be parsing another
160 # attribute: return but do not consume.
161 return ''
162 # Return value description can be several lines, some of them possibly
163 # empty, and it stops when another subsection title is met.
164 ret = ''
165 while True:
166 self.line = self.reader.readline()
167 if self.line == ' *\n':
168 ret += '\n'
169 else:
eeacb716 170 p = re.compile(' \* ?(?:\t| {5,8})(?:\t| {8})(.*)')
56a092c8
QM
171 capture = p.match(self.line)
172 if capture:
173 ret += capture.group(1) + '\n'
174 else:
175 break
176 return ret
177
a67882a2
JS
178 def seek_to(self, target, help_message):
179 self.reader.seek(0)
180 offset = self.reader.read().find(target)
56a092c8 181 if offset == -1:
a67882a2 182 raise Exception(help_message)
56a092c8
QM
183 self.reader.seek(offset)
184 self.reader.readline()
185 self.reader.readline()
186 self.line = self.reader.readline()
187
a67882a2
JS
188 def parse_syscall(self):
189 self.seek_to('* DOC: eBPF Syscall Commands',
190 'Could not find start of eBPF syscall descriptions list')
191 while True:
192 try:
193 command = self.parse_element()
194 self.commands.append(command)
195 except NoSyscallCommandFound:
196 break
197
71a3cdf8 198 def parse_desc_helpers(self):
a67882a2
JS
199 self.seek_to('* Start of BPF helper function descriptions:',
200 'Could not find start of eBPF helper descriptions list')
56a092c8
QM
201 while True:
202 try:
203 helper = self.parse_helper()
204 self.helpers.append(helper)
71a3cdf8
UA
205 proto = helper.proto_break_down()
206 self.desc_unique_helpers.add(proto['name'])
56a092c8
QM
207 except NoHelperFound:
208 break
209
71a3cdf8
UA
210 def parse_define_helpers(self):
211 # Parse the number of FN(...) in #define __BPF_FUNC_MAPPER to compare
212 # later with the number of unique function names present in description.
213 # Note: seek_to(..) discards the first line below the target search text,
214 # resulting in FN(unspec) being skipped and not added to self.define_unique_helpers.
215 self.seek_to('#define __BPF_FUNC_MAPPER(FN)',
216 'Could not find start of eBPF helper definition list')
217 # Searches for either one or more FN(\w+) defines or a backslash for newline
218 p = re.compile('\s*(FN\(\w+\))+|\\\\')
219 fn_defines_str = ''
220 while True:
221 capture = p.match(self.line)
222 if capture:
223 fn_defines_str += self.line
224 else:
225 break
226 self.line = self.reader.readline()
227 # Find the number of occurences of FN(\w+)
228 self.define_unique_helpers = re.findall('FN\(\w+\)', fn_defines_str)
229
a67882a2
JS
230 def run(self):
231 self.parse_syscall()
71a3cdf8
UA
232 self.parse_desc_helpers()
233 self.parse_define_helpers()
56a092c8 234 self.reader.close()
56a092c8
QM
235
236###############################################################################
237
238class Printer(object):
239 """
240 A generic class for printers. Printers should be created with an array of
241 Helper objects, and implement a way to print them in the desired fashion.
923a932c 242 @parser: A HeaderParser with objects to print to standard output
56a092c8 243 """
923a932c
JS
244 def __init__(self, parser):
245 self.parser = parser
246 self.elements = []
56a092c8
QM
247
248 def print_header(self):
249 pass
250
251 def print_footer(self):
252 pass
253
254 def print_one(self, helper):
255 pass
256
257 def print_all(self):
258 self.print_header()
923a932c
JS
259 for elem in self.elements:
260 self.print_one(elem)
56a092c8
QM
261 self.print_footer()
262
923a932c 263
56a092c8
QM
264class PrinterRST(Printer):
265 """
923a932c
JS
266 A generic class for printers that print ReStructured Text. Printers should
267 be created with a HeaderParser object, and implement a way to print API
268 elements in the desired fashion.
269 @parser: A HeaderParser with objects to print to standard output
56a092c8 270 """
923a932c
JS
271 def __init__(self, parser):
272 self.parser = parser
273
274 def print_license(self):
275 license = '''\
56a092c8
QM
276.. Copyright (C) All BPF authors and contributors from 2014 to present.
277.. See git log include/uapi/linux/bpf.h in kernel tree for details.
278..
279.. %%%LICENSE_START(VERBATIM)
280.. Permission is granted to make and distribute verbatim copies of this
281.. manual provided the copyright notice and this permission notice are
282.. preserved on all copies.
283..
284.. Permission is granted to copy and distribute modified versions of this
285.. manual under the conditions for verbatim copying, provided that the
286.. entire resulting derived work is distributed under the terms of a
287.. permission notice identical to this one.
288..
289.. Since the Linux kernel and libraries are constantly changing, this
290.. manual page may be incorrect or out-of-date. The author(s) assume no
291.. responsibility for errors or omissions, or for damages resulting from
292.. the use of the information contained herein. The author(s) may not
293.. have taken the same level of care in the production of this manual,
294.. which is licensed free of charge, as they might when working
295.. professionally.
296..
297.. Formatted or processed versions of this manual, if unaccompanied by
298.. the source, must acknowledge the copyright and authors of this work.
299.. %%%LICENSE_END
300..
301.. Please do not edit this file. It was generated from the documentation
302.. located in file include/uapi/linux/bpf.h of the Linux kernel sources
923a932c 303.. (helpers description), and from scripts/bpf_doc.py in the same
56a092c8 304.. repository (header and footer).
923a932c
JS
305'''
306 print(license)
307
308 def print_elem(self, elem):
309 if (elem.desc):
310 print('\tDescription')
311 # Do not strip all newline characters: formatted code at the end of
312 # a section must be followed by a blank line.
313 for line in re.sub('\n$', '', elem.desc, count=1).split('\n'):
314 print('{}{}'.format('\t\t' if line else '', line))
315
316 if (elem.ret):
317 print('\tReturn')
318 for line in elem.ret.rstrip().split('\n'):
319 print('{}{}'.format('\t\t' if line else '', line))
320
321 print('')
56a092c8 322
71a3cdf8
UA
323def helper_number_check(desc_unique_helpers, define_unique_helpers):
324 """
325 Checks the number of functions documented within the header file
326 with those present as part of #define __BPF_FUNC_MAPPER and raise an
327 Exception if they don't match.
328 """
329 nr_desc_unique_helpers = len(desc_unique_helpers)
330 nr_define_unique_helpers = len(define_unique_helpers)
331 if nr_desc_unique_helpers != nr_define_unique_helpers:
332 helper_exception = '''
333The number of unique helpers in description (%d) doesn\'t match the number of unique helpers defined in __BPF_FUNC_MAPPER (%d)
334''' % (nr_desc_unique_helpers, nr_define_unique_helpers)
335 if nr_desc_unique_helpers < nr_define_unique_helpers:
336 # Function description is parsed until no helper is found (which can be due to
337 # misformatting). Hence, only print the first missing/misformatted function.
338 helper_exception += '''
339The description for %s is not present or formatted correctly.
340''' % (define_unique_helpers[nr_desc_unique_helpers])
341 raise Exception(helper_exception)
923a932c
JS
342
343class PrinterHelpersRST(PrinterRST):
344 """
345 A printer for dumping collected information about helpers as a ReStructured
346 Text page compatible with the rst2man program, which can be used to
347 generate a manual page for the helpers.
348 @parser: A HeaderParser with Helper objects to print to standard output
349 """
350 def __init__(self, parser):
351 self.elements = parser.helpers
71a3cdf8 352 helper_number_check(parser.desc_unique_helpers, parser.define_unique_helpers)
923a932c
JS
353
354 def print_header(self):
355 header = '''\
56a092c8
QM
356===========
357BPF-HELPERS
358===========
359-------------------------------------------------------------------------------
360list of eBPF helper functions
361-------------------------------------------------------------------------------
362
363:Manual section: 7
364
365DESCRIPTION
366===========
367
368The extended Berkeley Packet Filter (eBPF) subsystem consists in programs
369written in a pseudo-assembly language, then attached to one of the several
370kernel hooks and run in reaction of specific events. This framework differs
371from the older, "classic" BPF (or "cBPF") in several aspects, one of them being
372the ability to call special functions (or "helpers") from within a program.
373These functions are restricted to a white-list of helpers defined in the
374kernel.
375
376These helpers are used by eBPF programs to interact with the system, or with
377the context in which they work. For instance, they can be used to print
378debugging messages, to get the time since the system was booted, to interact
379with eBPF maps, or to manipulate network packets. Since there are several eBPF
380program types, and that they do not run in the same context, each program type
381can only call a subset of those helpers.
382
383Due to eBPF conventions, a helper can not have more than five arguments.
384
385Internally, eBPF programs call directly into the compiled helper functions
386without requiring any foreign-function interface. As a result, calling helpers
387introduces no overhead, thus offering excellent performance.
388
389This document is an attempt to list and document the helpers available to eBPF
390developers. They are sorted by chronological order (the oldest helpers in the
391kernel at the top).
392
393HELPERS
394=======
395'''
923a932c 396 PrinterRST.print_license(self)
56a092c8
QM
397 print(header)
398
399 def print_footer(self):
400 footer = '''
401EXAMPLES
402========
403
404Example usage for most of the eBPF helpers listed in this manual page are
405available within the Linux kernel sources, at the following locations:
406
407* *samples/bpf/*
408* *tools/testing/selftests/bpf/*
409
410LICENSE
411=======
412
413eBPF programs can have an associated license, passed along with the bytecode
414instructions to the kernel when the programs are loaded. The format for that
415string is identical to the one in use for kernel modules (Dual licenses, such
416as "Dual BSD/GPL", may be used). Some helper functions are only accessible to
417programs that are compatible with the GNU Privacy License (GPL).
418
419In order to use such helpers, the eBPF program must be loaded with the correct
420license string passed (via **attr**) to the **bpf**\ () system call, and this
421generally translates into the C source code of the program containing a line
422similar to the following:
423
424::
425
426 char ____license[] __attribute__((section("license"), used)) = "GPL";
427
428IMPLEMENTATION
429==============
430
431This manual page is an effort to document the existing eBPF helper functions.
432But as of this writing, the BPF sub-system is under heavy development. New eBPF
433program or map types are added, along with new helper functions. Some helpers
434are occasionally made available for additional program types. So in spite of
435the efforts of the community, this page might not be up-to-date. If you want to
436check by yourself what helper functions exist in your kernel, or what types of
437programs they can support, here are some files among the kernel tree that you
438may be interested in:
439
440* *include/uapi/linux/bpf.h* is the main BPF header. It contains the full list
441 of all helper functions, as well as many other BPF definitions including most
442 of the flags, structs or constants used by the helpers.
443* *net/core/filter.c* contains the definition of most network-related helper
444 functions, and the list of program types from which they can be used.
445* *kernel/trace/bpf_trace.c* is the equivalent for most tracing program-related
446 helpers.
447* *kernel/bpf/verifier.c* contains the functions used to check that valid types
448 of eBPF maps are used with a given helper function.
449* *kernel/bpf/* directory contains other files in which additional helpers are
450 defined (for cgroups, sockmaps, etc.).
ab8d7809
QM
451* The bpftool utility can be used to probe the availability of helper functions
452 on the system (as well as supported program and map types, and a number of
453 other parameters). To do so, run **bpftool feature probe** (see
454 **bpftool-feature**\ (8) for details). Add the **unprivileged** keyword to
455 list features available to unprivileged users.
56a092c8
QM
456
457Compatibility between helper functions and program types can generally be found
458in the files where helper functions are defined. Look for the **struct
459bpf_func_proto** objects and for functions returning them: these functions
460contain a list of helpers that a given program type can call. Note that the
461**default:** label of the **switch ... case** used to filter helpers can call
462other functions, themselves allowing access to additional helpers. The
463requirement for GPL license is also in those **struct bpf_func_proto**.
464
465Compatibility between helper functions and map types can be found in the
466**check_map_func_compatibility**\ () function in file *kernel/bpf/verifier.c*.
467
468Helper functions that invalidate the checks on **data** and **data_end**
469pointers for network processing are listed in function
470**bpf_helper_changes_pkt_data**\ () in file *net/core/filter.c*.
471
472SEE ALSO
473========
474
475**bpf**\ (2),
ab8d7809 476**bpftool**\ (8),
56a092c8
QM
477**cgroups**\ (7),
478**ip**\ (8),
479**perf_event_open**\ (2),
480**sendmsg**\ (2),
481**socket**\ (7),
482**tc-bpf**\ (8)'''
483 print(footer)
484
485 def print_proto(self, helper):
486 """
487 Format function protocol with bold and italics markers. This makes RST
488 file less readable, but gives nice results in the manual page.
489 """
490 proto = helper.proto_break_down()
491
492 print('**%s %s%s(' % (proto['ret_type'],
493 proto['ret_star'].replace('*', '\\*'),
494 proto['name']),
495 end='')
496
497 comma = ''
498 for a in proto['args']:
499 one_arg = '{}{}'.format(comma, a['type'])
500 if a['name']:
501 if a['star']:
502 one_arg += ' {}**\ '.format(a['star'].replace('*', '\\*'))
503 else:
504 one_arg += '** '
505 one_arg += '*{}*\\ **'.format(a['name'])
506 comma = ', '
507 print(one_arg, end='')
508
509 print(')**')
510
511 def print_one(self, helper):
512 self.print_proto(helper)
923a932c 513 self.print_elem(helper)
56a092c8 514
56a092c8 515
a67882a2
JS
516class PrinterSyscallRST(PrinterRST):
517 """
518 A printer for dumping collected information about the syscall API as a
519 ReStructured Text page compatible with the rst2man program, which can be
520 used to generate a manual page for the syscall.
521 @parser: A HeaderParser with APIElement objects to print to standard
522 output
523 """
524 def __init__(self, parser):
525 self.elements = parser.commands
526
527 def print_header(self):
528 header = '''\
529===
530bpf
531===
532-------------------------------------------------------------------------------
533Perform a command on an extended BPF object
534-------------------------------------------------------------------------------
535
536:Manual section: 2
537
538COMMANDS
539========
540'''
541 PrinterRST.print_license(self)
542 print(header)
543
544 def print_one(self, command):
545 print('**%s**' % (command.proto))
546 self.print_elem(command)
56a092c8 547
56a092c8 548
7a387bed
AN
549class PrinterHelpers(Printer):
550 """
551 A printer for dumping collected information about helpers as C header to
552 be included from BPF program.
923a932c 553 @parser: A HeaderParser with Helper objects to print to standard output
7a387bed 554 """
923a932c
JS
555 def __init__(self, parser):
556 self.elements = parser.helpers
71a3cdf8 557 helper_number_check(parser.desc_unique_helpers, parser.define_unique_helpers)
7a387bed
AN
558
559 type_fwds = [
560 'struct bpf_fib_lookup',
e9ddbb77 561 'struct bpf_sk_lookup',
7a387bed
AN
562 'struct bpf_perf_event_data',
563 'struct bpf_perf_event_value',
5996a587 564 'struct bpf_pidns_info',
821f5c90 565 'struct bpf_redir_neigh',
7a387bed
AN
566 'struct bpf_sock',
567 'struct bpf_sock_addr',
568 'struct bpf_sock_ops',
569 'struct bpf_sock_tuple',
570 'struct bpf_spin_lock',
571 'struct bpf_sysctl',
572 'struct bpf_tcp_sock',
573 'struct bpf_tunnel_key',
574 'struct bpf_xfrm_state',
3f6719c7 575 'struct linux_binprm',
7a387bed
AN
576 'struct pt_regs',
577 'struct sk_reuseport_md',
578 'struct sockaddr',
579 'struct tcphdr',
492e639f 580 'struct seq_file',
af7ec138 581 'struct tcp6_sock',
478cfbdf
YS
582 'struct tcp_sock',
583 'struct tcp_timewait_sock',
584 'struct tcp_request_sock',
0d4fad3e 585 'struct udp6_sock',
9eeb3aa3 586 'struct unix_sock',
fa28dcb8 587 'struct task_struct',
7a387bed
AN
588
589 'struct __sk_buff',
590 'struct sk_msg_md',
e0b68fb1 591 'struct xdp_md',
6e22ab9d 592 'struct path',
c4d0bfb4 593 'struct btf_ptr',
27672f0d 594 'struct inode',
4f19cab7
FR
595 'struct socket',
596 'struct file',
b00628b1 597 'struct bpf_timer',
7a387bed
AN
598 ]
599 known_types = {
600 '...',
601 'void',
602 'const void',
603 'char',
604 'const char',
605 'int',
606 'long',
607 'unsigned long',
608
609 '__be16',
610 '__be32',
611 '__wsum',
612
613 'struct bpf_fib_lookup',
614 'struct bpf_perf_event_data',
615 'struct bpf_perf_event_value',
b4490c5c 616 'struct bpf_pidns_info',
ba452c9e 617 'struct bpf_redir_neigh',
e9ddbb77 618 'struct bpf_sk_lookup',
7a387bed
AN
619 'struct bpf_sock',
620 'struct bpf_sock_addr',
621 'struct bpf_sock_ops',
622 'struct bpf_sock_tuple',
623 'struct bpf_spin_lock',
624 'struct bpf_sysctl',
625 'struct bpf_tcp_sock',
626 'struct bpf_tunnel_key',
627 'struct bpf_xfrm_state',
3f6719c7 628 'struct linux_binprm',
7a387bed
AN
629 'struct pt_regs',
630 'struct sk_reuseport_md',
631 'struct sockaddr',
632 'struct tcphdr',
492e639f 633 'struct seq_file',
af7ec138 634 'struct tcp6_sock',
478cfbdf
YS
635 'struct tcp_sock',
636 'struct tcp_timewait_sock',
637 'struct tcp_request_sock',
0d4fad3e 638 'struct udp6_sock',
9eeb3aa3 639 'struct unix_sock',
fa28dcb8 640 'struct task_struct',
6e22ab9d 641 'struct path',
c4d0bfb4 642 'struct btf_ptr',
27672f0d 643 'struct inode',
4f19cab7
FR
644 'struct socket',
645 'struct file',
b00628b1 646 'struct bpf_timer',
7a387bed
AN
647 }
648 mapped_types = {
649 'u8': '__u8',
650 'u16': '__u16',
651 'u32': '__u32',
652 'u64': '__u64',
653 's8': '__s8',
654 's16': '__s16',
655 's32': '__s32',
656 's64': '__s64',
657 'size_t': 'unsigned long',
658 'struct bpf_map': 'void',
659 'struct sk_buff': 'struct __sk_buff',
660 'const struct sk_buff': 'const struct __sk_buff',
661 'struct sk_msg_buff': 'struct sk_msg_md',
662 'struct xdp_buff': 'struct xdp_md',
663 }
e9ddbb77
JS
664 # Helpers overloaded for different context types.
665 overloaded_helpers = [
666 'bpf_get_socket_cookie',
667 'bpf_sk_assign',
668 ]
7a387bed
AN
669
670 def print_header(self):
671 header = '''\
923a932c 672/* This is auto-generated file. See bpf_doc.py for details. */
7a387bed
AN
673
674/* Forward declarations of BPF structs */'''
675
676 print(header)
677 for fwd in self.type_fwds:
678 print('%s;' % fwd)
679 print('')
680
681 def print_footer(self):
682 footer = ''
683 print(footer)
684
685 def map_type(self, t):
686 if t in self.known_types:
687 return t
688 if t in self.mapped_types:
689 return self.mapped_types[t]
ab81e203
JS
690 print("Unrecognized type '%s', please add it to known types!" % t,
691 file=sys.stderr)
7a387bed
AN
692 sys.exit(1)
693
694 seen_helpers = set()
695
696 def print_one(self, helper):
697 proto = helper.proto_break_down()
698
699 if proto['name'] in self.seen_helpers:
700 return
701 self.seen_helpers.add(proto['name'])
702
703 print('/*')
704 print(" * %s" % proto['name'])
705 print(" *")
706 if (helper.desc):
707 # Do not strip all newline characters: formatted code at the end of
708 # a section must be followed by a blank line.
709 for line in re.sub('\n$', '', helper.desc, count=1).split('\n'):
710 print(' *{}{}'.format(' \t' if line else '', line))
711
712 if (helper.ret):
713 print(' *')
714 print(' * Returns')
715 for line in helper.ret.rstrip().split('\n'):
716 print(' *{}{}'.format(' \t' if line else '', line))
717
718 print(' */')
719 print('static %s %s(*%s)(' % (self.map_type(proto['ret_type']),
720 proto['ret_star'], proto['name']), end='')
721 comma = ''
722 for i, a in enumerate(proto['args']):
723 t = a['type']
724 n = a['name']
e9ddbb77 725 if proto['name'] in self.overloaded_helpers and i == 0:
7a387bed
AN
726 t = 'void'
727 n = 'ctx'
728 one_arg = '{}{}'.format(comma, self.map_type(t))
729 if n:
730 if a['star']:
731 one_arg += ' {}'.format(a['star'])
732 else:
733 one_arg += ' '
734 one_arg += '{}'.format(n)
735 comma = ', '
736 print(one_arg, end='')
737
738 print(') = (void *) %d;' % len(self.seen_helpers))
739 print('')
740
56a092c8
QM
741###############################################################################
742
743# If script is launched from scripts/ from kernel tree and can access
744# ../include/uapi/linux/bpf.h, use it as a default name for the file to parse,
745# otherwise the --filename argument will be required from the command line.
746script = os.path.abspath(sys.argv[0])
747linuxRoot = os.path.dirname(os.path.dirname(script))
748bpfh = os.path.join(linuxRoot, 'include/uapi/linux/bpf.h')
749
923a932c
JS
750printers = {
751 'helpers': PrinterHelpersRST,
a67882a2 752 'syscall': PrinterSyscallRST,
923a932c
JS
753}
754
56a092c8 755argParser = argparse.ArgumentParser(description="""
923a932c 756Parse eBPF header file and generate documentation for the eBPF API.
56a092c8
QM
757The RST-formatted output produced can be turned into a manual page with the
758rst2man utility.
759""")
7a387bed
AN
760argParser.add_argument('--header', action='store_true',
761 help='generate C header file')
56a092c8
QM
762if (os.path.isfile(bpfh)):
763 argParser.add_argument('--filename', help='path to include/uapi/linux/bpf.h',
764 default=bpfh)
765else:
766 argParser.add_argument('--filename', help='path to include/uapi/linux/bpf.h')
923a932c
JS
767argParser.add_argument('target', nargs='?', default='helpers',
768 choices=printers.keys(), help='eBPF API target')
56a092c8
QM
769args = argParser.parse_args()
770
771# Parse file.
772headerParser = HeaderParser(args.filename)
773headerParser.run()
774
775# Print formatted output to standard output.
7a387bed 776if args.header:
a67882a2
JS
777 if args.target != 'helpers':
778 raise NotImplementedError('Only helpers header generation is supported')
923a932c 779 printer = PrinterHelpers(headerParser)
7a387bed 780else:
923a932c 781 printer = printers[args.target](headerParser)
56a092c8 782printer.print_all()