blob: 5a4f68aab335c67dedf841cddc545d9b9946d79c [file] [log] [blame]
Scott Branden3cd046f2020-02-25 12:54:26 -08001#!/usr/bin/env python3
Quentin Monnet56a092c2018-04-25 18:16:52 +01002# SPDX-License-Identifier: GPL-2.0-only
3#
Quentin Monnet748c7c82019-05-10 15:51:22 +01004# Copyright (C) 2018-2019 Netronome Systems, Inc.
Joe Stringer923a9322021-03-02 09:19:41 -08005# Copyright (C) 2021 Isovalent, Inc.
Quentin Monnet56a092c2018-04-25 18:16:52 +01006
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
17class ParsingError(BaseException):
18 def __init__(self, line='<line not provided>', reader=None):
19 if reader:
20 BaseException.__init__(self,
21 'Error at file offset %d, parsing line: %s' %
22 (reader.tell(), line))
23 else:
24 BaseException.__init__(self, 'Error parsing line: %s' % line)
25
26class Helper(object):
27 """
28 An object representing the description of an eBPF helper function.
29 @proto: function prototype of the helper function
30 @desc: textual description of the helper function
31 @ret: description of the return value of the helper function
32 """
33 def __init__(self, proto='', desc='', ret=''):
34 self.proto = proto
35 self.desc = desc
36 self.ret = ret
37
38 def proto_break_down(self):
39 """
40 Break down helper function protocol into smaller chunks: return type,
41 name, distincts arguments.
42 """
Quentin Monnet748c7c82019-05-10 15:51:22 +010043 arg_re = re.compile('((\w+ )*?(\w+|...))( (\**)(\w+))?$')
Quentin Monnet56a092c2018-04-25 18:16:52 +010044 res = {}
Quentin Monnet6f966742018-05-02 14:20:24 +010045 proto_re = re.compile('(.+) (\**)(\w+)\(((([^,]+)(, )?){1,5})\)$')
Quentin Monnet56a092c2018-04-25 18:16:52 +010046
47 capture = proto_re.match(self.proto)
48 res['ret_type'] = capture.group(1)
49 res['ret_star'] = capture.group(2)
50 res['name'] = capture.group(3)
51 res['args'] = []
52
53 args = capture.group(4).split(', ')
54 for a in args:
55 capture = arg_re.match(a)
56 res['args'].append({
57 'type' : capture.group(1),
Quentin Monnet748c7c82019-05-10 15:51:22 +010058 'star' : capture.group(5),
59 'name' : capture.group(6)
Quentin Monnet56a092c2018-04-25 18:16:52 +010060 })
61
62 return res
63
64class HeaderParser(object):
65 """
66 An object used to parse a file in order to extract the documentation of a
67 list of eBPF helper functions. All the helpers that can be retrieved are
68 stored as Helper object, in the self.helpers() array.
69 @filename: name of file to parse, usually include/uapi/linux/bpf.h in the
70 kernel tree
71 """
72 def __init__(self, filename):
73 self.reader = open(filename, 'r')
74 self.line = ''
75 self.helpers = []
76
77 def parse_helper(self):
78 proto = self.parse_proto()
79 desc = self.parse_desc()
80 ret = self.parse_ret()
81 return Helper(proto=proto, desc=desc, ret=ret)
82
83 def parse_proto(self):
84 # Argument can be of shape:
85 # - "void"
86 # - "type name"
87 # - "type *name"
88 # - Same as above, with "const" and/or "struct" in front of type
89 # - "..." (undefined number of arguments, for bpf_trace_printk())
90 # There is at least one term ("void"), and at most five arguments.
Quentin Monnet6f966742018-05-02 14:20:24 +010091 p = re.compile(' \* ?((.+) \**\w+\((((const )?(struct )?(\w+|\.\.\.)( \**\w+)?)(, )?){1,5}\))$')
Quentin Monnet56a092c2018-04-25 18:16:52 +010092 capture = p.match(self.line)
93 if not capture:
94 raise NoHelperFound
95 self.line = self.reader.readline()
96 return capture.group(1)
97
98 def parse_desc(self):
Quentin Monneteeacb712018-05-17 13:43:56 +010099 p = re.compile(' \* ?(?:\t| {5,8})Description$')
Quentin Monnet56a092c2018-04-25 18:16:52 +0100100 capture = p.match(self.line)
101 if not capture:
102 # Helper can have empty description and we might be parsing another
103 # attribute: return but do not consume.
104 return ''
105 # Description can be several lines, some of them possibly empty, and it
106 # stops when another subsection title is met.
107 desc = ''
108 while True:
109 self.line = self.reader.readline()
110 if self.line == ' *\n':
111 desc += '\n'
112 else:
Quentin Monneteeacb712018-05-17 13:43:56 +0100113 p = re.compile(' \* ?(?:\t| {5,8})(?:\t| {8})(.*)')
Quentin Monnet56a092c2018-04-25 18:16:52 +0100114 capture = p.match(self.line)
115 if capture:
116 desc += capture.group(1) + '\n'
117 else:
118 break
119 return desc
120
121 def parse_ret(self):
Quentin Monneteeacb712018-05-17 13:43:56 +0100122 p = re.compile(' \* ?(?:\t| {5,8})Return$')
Quentin Monnet56a092c2018-04-25 18:16:52 +0100123 capture = p.match(self.line)
124 if not capture:
125 # Helper can have empty retval and we might be parsing another
126 # attribute: return but do not consume.
127 return ''
128 # Return value description can be several lines, some of them possibly
129 # empty, and it stops when another subsection title is met.
130 ret = ''
131 while True:
132 self.line = self.reader.readline()
133 if self.line == ' *\n':
134 ret += '\n'
135 else:
Quentin Monneteeacb712018-05-17 13:43:56 +0100136 p = re.compile(' \* ?(?:\t| {5,8})(?:\t| {8})(.*)')
Quentin Monnet56a092c2018-04-25 18:16:52 +0100137 capture = p.match(self.line)
138 if capture:
139 ret += capture.group(1) + '\n'
140 else:
141 break
142 return ret
143
144 def run(self):
145 # Advance to start of helper function descriptions.
146 offset = self.reader.read().find('* Start of BPF helper function descriptions:')
147 if offset == -1:
148 raise Exception('Could not find start of eBPF helper descriptions list')
149 self.reader.seek(offset)
150 self.reader.readline()
151 self.reader.readline()
152 self.line = self.reader.readline()
153
154 while True:
155 try:
156 helper = self.parse_helper()
157 self.helpers.append(helper)
158 except NoHelperFound:
159 break
160
161 self.reader.close()
Quentin Monnet56a092c2018-04-25 18:16:52 +0100162
163###############################################################################
164
165class Printer(object):
166 """
167 A generic class for printers. Printers should be created with an array of
168 Helper objects, and implement a way to print them in the desired fashion.
Joe Stringer923a9322021-03-02 09:19:41 -0800169 @parser: A HeaderParser with objects to print to standard output
Quentin Monnet56a092c2018-04-25 18:16:52 +0100170 """
Joe Stringer923a9322021-03-02 09:19:41 -0800171 def __init__(self, parser):
172 self.parser = parser
173 self.elements = []
Quentin Monnet56a092c2018-04-25 18:16:52 +0100174
175 def print_header(self):
176 pass
177
178 def print_footer(self):
179 pass
180
181 def print_one(self, helper):
182 pass
183
184 def print_all(self):
185 self.print_header()
Joe Stringer923a9322021-03-02 09:19:41 -0800186 for elem in self.elements:
187 self.print_one(elem)
Quentin Monnet56a092c2018-04-25 18:16:52 +0100188 self.print_footer()
189
Joe Stringer923a9322021-03-02 09:19:41 -0800190
Quentin Monnet56a092c2018-04-25 18:16:52 +0100191class PrinterRST(Printer):
192 """
Joe Stringer923a9322021-03-02 09:19:41 -0800193 A generic class for printers that print ReStructured Text. Printers should
194 be created with a HeaderParser object, and implement a way to print API
195 elements in the desired fashion.
196 @parser: A HeaderParser with objects to print to standard output
Quentin Monnet56a092c2018-04-25 18:16:52 +0100197 """
Joe Stringer923a9322021-03-02 09:19:41 -0800198 def __init__(self, parser):
199 self.parser = parser
200
201 def print_license(self):
202 license = '''\
Quentin Monnet56a092c2018-04-25 18:16:52 +0100203.. Copyright (C) All BPF authors and contributors from 2014 to present.
204.. See git log include/uapi/linux/bpf.h in kernel tree for details.
205..
206.. %%%LICENSE_START(VERBATIM)
207.. Permission is granted to make and distribute verbatim copies of this
208.. manual provided the copyright notice and this permission notice are
209.. preserved on all copies.
210..
211.. Permission is granted to copy and distribute modified versions of this
212.. manual under the conditions for verbatim copying, provided that the
213.. entire resulting derived work is distributed under the terms of a
214.. permission notice identical to this one.
215..
216.. Since the Linux kernel and libraries are constantly changing, this
217.. manual page may be incorrect or out-of-date. The author(s) assume no
218.. responsibility for errors or omissions, or for damages resulting from
219.. the use of the information contained herein. The author(s) may not
220.. have taken the same level of care in the production of this manual,
221.. which is licensed free of charge, as they might when working
222.. professionally.
223..
224.. Formatted or processed versions of this manual, if unaccompanied by
225.. the source, must acknowledge the copyright and authors of this work.
226.. %%%LICENSE_END
227..
228.. Please do not edit this file. It was generated from the documentation
229.. located in file include/uapi/linux/bpf.h of the Linux kernel sources
Joe Stringer923a9322021-03-02 09:19:41 -0800230.. (helpers description), and from scripts/bpf_doc.py in the same
Quentin Monnet56a092c2018-04-25 18:16:52 +0100231.. repository (header and footer).
Joe Stringer923a9322021-03-02 09:19:41 -0800232'''
233 print(license)
Quentin Monnet56a092c2018-04-25 18:16:52 +0100234
Joe Stringer923a9322021-03-02 09:19:41 -0800235 def print_elem(self, elem):
236 if (elem.desc):
237 print('\tDescription')
238 # Do not strip all newline characters: formatted code at the end of
239 # a section must be followed by a blank line.
240 for line in re.sub('\n$', '', elem.desc, count=1).split('\n'):
241 print('{}{}'.format('\t\t' if line else '', line))
242
243 if (elem.ret):
244 print('\tReturn')
245 for line in elem.ret.rstrip().split('\n'):
246 print('{}{}'.format('\t\t' if line else '', line))
247
248 print('')
249
250
251class PrinterHelpersRST(PrinterRST):
252 """
253 A printer for dumping collected information about helpers as a ReStructured
254 Text page compatible with the rst2man program, which can be used to
255 generate a manual page for the helpers.
256 @parser: A HeaderParser with Helper objects to print to standard output
257 """
258 def __init__(self, parser):
259 self.elements = parser.helpers
260
261 def print_header(self):
262 header = '''\
Quentin Monnet56a092c2018-04-25 18:16:52 +0100263===========
264BPF-HELPERS
265===========
266-------------------------------------------------------------------------------
267list of eBPF helper functions
268-------------------------------------------------------------------------------
269
270:Manual section: 7
271
272DESCRIPTION
273===========
274
275The extended Berkeley Packet Filter (eBPF) subsystem consists in programs
276written in a pseudo-assembly language, then attached to one of the several
277kernel hooks and run in reaction of specific events. This framework differs
278from the older, "classic" BPF (or "cBPF") in several aspects, one of them being
279the ability to call special functions (or "helpers") from within a program.
280These functions are restricted to a white-list of helpers defined in the
281kernel.
282
283These helpers are used by eBPF programs to interact with the system, or with
284the context in which they work. For instance, they can be used to print
285debugging messages, to get the time since the system was booted, to interact
286with eBPF maps, or to manipulate network packets. Since there are several eBPF
287program types, and that they do not run in the same context, each program type
288can only call a subset of those helpers.
289
290Due to eBPF conventions, a helper can not have more than five arguments.
291
292Internally, eBPF programs call directly into the compiled helper functions
293without requiring any foreign-function interface. As a result, calling helpers
294introduces no overhead, thus offering excellent performance.
295
296This document is an attempt to list and document the helpers available to eBPF
297developers. They are sorted by chronological order (the oldest helpers in the
298kernel at the top).
299
300HELPERS
301=======
302'''
Joe Stringer923a9322021-03-02 09:19:41 -0800303 PrinterRST.print_license(self)
Quentin Monnet56a092c2018-04-25 18:16:52 +0100304 print(header)
305
306 def print_footer(self):
307 footer = '''
308EXAMPLES
309========
310
311Example usage for most of the eBPF helpers listed in this manual page are
312available within the Linux kernel sources, at the following locations:
313
314* *samples/bpf/*
315* *tools/testing/selftests/bpf/*
316
317LICENSE
318=======
319
320eBPF programs can have an associated license, passed along with the bytecode
321instructions to the kernel when the programs are loaded. The format for that
322string is identical to the one in use for kernel modules (Dual licenses, such
323as "Dual BSD/GPL", may be used). Some helper functions are only accessible to
324programs that are compatible with the GNU Privacy License (GPL).
325
326In order to use such helpers, the eBPF program must be loaded with the correct
327license string passed (via **attr**) to the **bpf**\ () system call, and this
328generally translates into the C source code of the program containing a line
329similar to the following:
330
331::
332
333 char ____license[] __attribute__((section("license"), used)) = "GPL";
334
335IMPLEMENTATION
336==============
337
338This manual page is an effort to document the existing eBPF helper functions.
339But as of this writing, the BPF sub-system is under heavy development. New eBPF
340program or map types are added, along with new helper functions. Some helpers
341are occasionally made available for additional program types. So in spite of
342the efforts of the community, this page might not be up-to-date. If you want to
343check by yourself what helper functions exist in your kernel, or what types of
344programs they can support, here are some files among the kernel tree that you
345may be interested in:
346
347* *include/uapi/linux/bpf.h* is the main BPF header. It contains the full list
348 of all helper functions, as well as many other BPF definitions including most
349 of the flags, structs or constants used by the helpers.
350* *net/core/filter.c* contains the definition of most network-related helper
351 functions, and the list of program types from which they can be used.
352* *kernel/trace/bpf_trace.c* is the equivalent for most tracing program-related
353 helpers.
354* *kernel/bpf/verifier.c* contains the functions used to check that valid types
355 of eBPF maps are used with a given helper function.
356* *kernel/bpf/* directory contains other files in which additional helpers are
357 defined (for cgroups, sockmaps, etc.).
Quentin Monnetab8d7802020-05-11 17:15:35 +0100358* The bpftool utility can be used to probe the availability of helper functions
359 on the system (as well as supported program and map types, and a number of
360 other parameters). To do so, run **bpftool feature probe** (see
361 **bpftool-feature**\ (8) for details). Add the **unprivileged** keyword to
362 list features available to unprivileged users.
Quentin Monnet56a092c2018-04-25 18:16:52 +0100363
364Compatibility between helper functions and program types can generally be found
365in the files where helper functions are defined. Look for the **struct
366bpf_func_proto** objects and for functions returning them: these functions
367contain a list of helpers that a given program type can call. Note that the
368**default:** label of the **switch ... case** used to filter helpers can call
369other functions, themselves allowing access to additional helpers. The
370requirement for GPL license is also in those **struct bpf_func_proto**.
371
372Compatibility between helper functions and map types can be found in the
373**check_map_func_compatibility**\ () function in file *kernel/bpf/verifier.c*.
374
375Helper functions that invalidate the checks on **data** and **data_end**
376pointers for network processing are listed in function
377**bpf_helper_changes_pkt_data**\ () in file *net/core/filter.c*.
378
379SEE ALSO
380========
381
382**bpf**\ (2),
Quentin Monnetab8d7802020-05-11 17:15:35 +0100383**bpftool**\ (8),
Quentin Monnet56a092c2018-04-25 18:16:52 +0100384**cgroups**\ (7),
385**ip**\ (8),
386**perf_event_open**\ (2),
387**sendmsg**\ (2),
388**socket**\ (7),
389**tc-bpf**\ (8)'''
390 print(footer)
391
392 def print_proto(self, helper):
393 """
394 Format function protocol with bold and italics markers. This makes RST
395 file less readable, but gives nice results in the manual page.
396 """
397 proto = helper.proto_break_down()
398
399 print('**%s %s%s(' % (proto['ret_type'],
400 proto['ret_star'].replace('*', '\\*'),
401 proto['name']),
402 end='')
403
404 comma = ''
405 for a in proto['args']:
406 one_arg = '{}{}'.format(comma, a['type'])
407 if a['name']:
408 if a['star']:
409 one_arg += ' {}**\ '.format(a['star'].replace('*', '\\*'))
410 else:
411 one_arg += '** '
412 one_arg += '*{}*\\ **'.format(a['name'])
413 comma = ', '
414 print(one_arg, end='')
415
416 print(')**')
417
418 def print_one(self, helper):
419 self.print_proto(helper)
Joe Stringer923a9322021-03-02 09:19:41 -0800420 self.print_elem(helper)
Quentin Monnet56a092c2018-04-25 18:16:52 +0100421
Quentin Monnet56a092c2018-04-25 18:16:52 +0100422
Quentin Monnet56a092c2018-04-25 18:16:52 +0100423
Quentin Monnet56a092c2018-04-25 18:16:52 +0100424
Andrii Nakryiko7a387be2019-10-06 20:07:37 -0700425class PrinterHelpers(Printer):
426 """
427 A printer for dumping collected information about helpers as C header to
428 be included from BPF program.
Joe Stringer923a9322021-03-02 09:19:41 -0800429 @parser: A HeaderParser with Helper objects to print to standard output
Andrii Nakryiko7a387be2019-10-06 20:07:37 -0700430 """
Joe Stringer923a9322021-03-02 09:19:41 -0800431 def __init__(self, parser):
432 self.elements = parser.helpers
Andrii Nakryiko7a387be2019-10-06 20:07:37 -0700433
434 type_fwds = [
435 'struct bpf_fib_lookup',
Jakub Sitnickie9ddbb72020-07-17 12:35:23 +0200436 'struct bpf_sk_lookup',
Andrii Nakryiko7a387be2019-10-06 20:07:37 -0700437 'struct bpf_perf_event_data',
438 'struct bpf_perf_event_value',
Carlos Neira5996a582020-03-13 12:46:50 -0300439 'struct bpf_pidns_info',
Andrii Nakryiko821f5c92020-10-28 11:12:04 -0700440 'struct bpf_redir_neigh',
Andrii Nakryiko7a387be2019-10-06 20:07:37 -0700441 'struct bpf_sock',
442 'struct bpf_sock_addr',
443 'struct bpf_sock_ops',
444 'struct bpf_sock_tuple',
445 'struct bpf_spin_lock',
446 'struct bpf_sysctl',
447 'struct bpf_tcp_sock',
448 'struct bpf_tunnel_key',
449 'struct bpf_xfrm_state',
KP Singh3f6719c2020-11-17 23:29:28 +0000450 'struct linux_binprm',
Andrii Nakryiko7a387be2019-10-06 20:07:37 -0700451 'struct pt_regs',
452 'struct sk_reuseport_md',
453 'struct sockaddr',
454 'struct tcphdr',
Yonghong Song492e6392020-05-09 10:59:14 -0700455 'struct seq_file',
Yonghong Songaf7ec132020-06-23 16:08:09 -0700456 'struct tcp6_sock',
Yonghong Song478cfbd2020-06-23 16:08:11 -0700457 'struct tcp_sock',
458 'struct tcp_timewait_sock',
459 'struct tcp_request_sock',
Yonghong Song0d4fad32020-06-23 16:08:15 -0700460 'struct udp6_sock',
Song Liufa28dcb2020-06-29 23:28:44 -0700461 'struct task_struct',
Andrii Nakryiko7a387be2019-10-06 20:07:37 -0700462
463 'struct __sk_buff',
464 'struct sk_msg_md',
Andrii Nakryikoe0b68fb2019-10-09 21:25:34 -0700465 'struct xdp_md',
Jiri Olsa6e22ab92020-08-25 21:21:20 +0200466 'struct path',
Alan Maguirec4d0bfb2020-09-28 12:31:05 +0100467 'struct btf_ptr',
KP Singh27672f02020-11-24 15:12:09 +0000468 'struct inode',
Florent Revest4f19cab2020-12-04 12:36:05 +0100469 'struct socket',
470 'struct file',
Andrii Nakryiko7a387be2019-10-06 20:07:37 -0700471 ]
472 known_types = {
473 '...',
474 'void',
475 'const void',
476 'char',
477 'const char',
478 'int',
479 'long',
480 'unsigned long',
481
482 '__be16',
483 '__be32',
484 '__wsum',
485
486 'struct bpf_fib_lookup',
487 'struct bpf_perf_event_data',
488 'struct bpf_perf_event_value',
Carlos Neirab4490c52020-03-04 17:41:56 -0300489 'struct bpf_pidns_info',
Toke Høiland-Jørgensenba452c92020-10-20 23:25:56 +0200490 'struct bpf_redir_neigh',
Jakub Sitnickie9ddbb72020-07-17 12:35:23 +0200491 'struct bpf_sk_lookup',
Andrii Nakryiko7a387be2019-10-06 20:07:37 -0700492 'struct bpf_sock',
493 'struct bpf_sock_addr',
494 'struct bpf_sock_ops',
495 'struct bpf_sock_tuple',
496 'struct bpf_spin_lock',
497 'struct bpf_sysctl',
498 'struct bpf_tcp_sock',
499 'struct bpf_tunnel_key',
500 'struct bpf_xfrm_state',
KP Singh3f6719c2020-11-17 23:29:28 +0000501 'struct linux_binprm',
Andrii Nakryiko7a387be2019-10-06 20:07:37 -0700502 'struct pt_regs',
503 'struct sk_reuseport_md',
504 'struct sockaddr',
505 'struct tcphdr',
Yonghong Song492e6392020-05-09 10:59:14 -0700506 'struct seq_file',
Yonghong Songaf7ec132020-06-23 16:08:09 -0700507 'struct tcp6_sock',
Yonghong Song478cfbd2020-06-23 16:08:11 -0700508 'struct tcp_sock',
509 'struct tcp_timewait_sock',
510 'struct tcp_request_sock',
Yonghong Song0d4fad32020-06-23 16:08:15 -0700511 'struct udp6_sock',
Song Liufa28dcb2020-06-29 23:28:44 -0700512 'struct task_struct',
Jiri Olsa6e22ab92020-08-25 21:21:20 +0200513 'struct path',
Alan Maguirec4d0bfb2020-09-28 12:31:05 +0100514 'struct btf_ptr',
KP Singh27672f02020-11-24 15:12:09 +0000515 'struct inode',
Florent Revest4f19cab2020-12-04 12:36:05 +0100516 'struct socket',
517 'struct file',
Andrii Nakryiko7a387be2019-10-06 20:07:37 -0700518 }
519 mapped_types = {
520 'u8': '__u8',
521 'u16': '__u16',
522 'u32': '__u32',
523 'u64': '__u64',
524 's8': '__s8',
525 's16': '__s16',
526 's32': '__s32',
527 's64': '__s64',
528 'size_t': 'unsigned long',
529 'struct bpf_map': 'void',
530 'struct sk_buff': 'struct __sk_buff',
531 'const struct sk_buff': 'const struct __sk_buff',
532 'struct sk_msg_buff': 'struct sk_msg_md',
533 'struct xdp_buff': 'struct xdp_md',
534 }
Jakub Sitnickie9ddbb72020-07-17 12:35:23 +0200535 # Helpers overloaded for different context types.
536 overloaded_helpers = [
537 'bpf_get_socket_cookie',
538 'bpf_sk_assign',
539 ]
Andrii Nakryiko7a387be2019-10-06 20:07:37 -0700540
541 def print_header(self):
542 header = '''\
Joe Stringer923a9322021-03-02 09:19:41 -0800543/* This is auto-generated file. See bpf_doc.py for details. */
Andrii Nakryiko7a387be2019-10-06 20:07:37 -0700544
545/* Forward declarations of BPF structs */'''
546
547 print(header)
548 for fwd in self.type_fwds:
549 print('%s;' % fwd)
550 print('')
551
552 def print_footer(self):
553 footer = ''
554 print(footer)
555
556 def map_type(self, t):
557 if t in self.known_types:
558 return t
559 if t in self.mapped_types:
560 return self.mapped_types[t]
Jakub Sitnickiab81e202019-10-20 13:23:44 +0200561 print("Unrecognized type '%s', please add it to known types!" % t,
562 file=sys.stderr)
Andrii Nakryiko7a387be2019-10-06 20:07:37 -0700563 sys.exit(1)
564
565 seen_helpers = set()
566
567 def print_one(self, helper):
568 proto = helper.proto_break_down()
569
570 if proto['name'] in self.seen_helpers:
571 return
572 self.seen_helpers.add(proto['name'])
573
574 print('/*')
575 print(" * %s" % proto['name'])
576 print(" *")
577 if (helper.desc):
578 # Do not strip all newline characters: formatted code at the end of
579 # a section must be followed by a blank line.
580 for line in re.sub('\n$', '', helper.desc, count=1).split('\n'):
581 print(' *{}{}'.format(' \t' if line else '', line))
582
583 if (helper.ret):
584 print(' *')
585 print(' * Returns')
586 for line in helper.ret.rstrip().split('\n'):
587 print(' *{}{}'.format(' \t' if line else '', line))
588
589 print(' */')
590 print('static %s %s(*%s)(' % (self.map_type(proto['ret_type']),
591 proto['ret_star'], proto['name']), end='')
592 comma = ''
593 for i, a in enumerate(proto['args']):
594 t = a['type']
595 n = a['name']
Jakub Sitnickie9ddbb72020-07-17 12:35:23 +0200596 if proto['name'] in self.overloaded_helpers and i == 0:
Andrii Nakryiko7a387be2019-10-06 20:07:37 -0700597 t = 'void'
598 n = 'ctx'
599 one_arg = '{}{}'.format(comma, self.map_type(t))
600 if n:
601 if a['star']:
602 one_arg += ' {}'.format(a['star'])
603 else:
604 one_arg += ' '
605 one_arg += '{}'.format(n)
606 comma = ', '
607 print(one_arg, end='')
608
609 print(') = (void *) %d;' % len(self.seen_helpers))
610 print('')
611
Quentin Monnet56a092c2018-04-25 18:16:52 +0100612###############################################################################
613
614# If script is launched from scripts/ from kernel tree and can access
615# ../include/uapi/linux/bpf.h, use it as a default name for the file to parse,
616# otherwise the --filename argument will be required from the command line.
617script = os.path.abspath(sys.argv[0])
618linuxRoot = os.path.dirname(os.path.dirname(script))
619bpfh = os.path.join(linuxRoot, 'include/uapi/linux/bpf.h')
620
Joe Stringer923a9322021-03-02 09:19:41 -0800621printers = {
622 'helpers': PrinterHelpersRST,
623}
624
Quentin Monnet56a092c2018-04-25 18:16:52 +0100625argParser = argparse.ArgumentParser(description="""
Joe Stringer923a9322021-03-02 09:19:41 -0800626Parse eBPF header file and generate documentation for the eBPF API.
Quentin Monnet56a092c2018-04-25 18:16:52 +0100627The RST-formatted output produced can be turned into a manual page with the
628rst2man utility.
629""")
Andrii Nakryiko7a387be2019-10-06 20:07:37 -0700630argParser.add_argument('--header', action='store_true',
631 help='generate C header file')
Quentin Monnet56a092c2018-04-25 18:16:52 +0100632if (os.path.isfile(bpfh)):
633 argParser.add_argument('--filename', help='path to include/uapi/linux/bpf.h',
634 default=bpfh)
635else:
636 argParser.add_argument('--filename', help='path to include/uapi/linux/bpf.h')
Joe Stringer923a9322021-03-02 09:19:41 -0800637argParser.add_argument('target', nargs='?', default='helpers',
638 choices=printers.keys(), help='eBPF API target')
Quentin Monnet56a092c2018-04-25 18:16:52 +0100639args = argParser.parse_args()
640
641# Parse file.
642headerParser = HeaderParser(args.filename)
643headerParser.run()
644
645# Print formatted output to standard output.
Andrii Nakryiko7a387be2019-10-06 20:07:37 -0700646if args.header:
Joe Stringer923a9322021-03-02 09:19:41 -0800647 printer = PrinterHelpers(headerParser)
Andrii Nakryiko7a387be2019-10-06 20:07:37 -0700648else:
Joe Stringer923a9322021-03-02 09:19:41 -0800649 printer = printers[args.target](headerParser)
Quentin Monnet56a092c2018-04-25 18:16:52 +0100650printer.print_all()