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