From: Joe Stringer <joe@cilium.io>
To: bpf@vger.kernel.org
Cc: daniel@iogearbox.net, ast@kernel.org, linux-doc@vger.kernel.org,
linux-man@vger.kernel.org,
"Toke Høiland-Jørgensen" <toke@redhat.com>,
"Quentin Monnet" <quentin@isovalent.com>
Subject: [PATCHv2 bpf-next 10/15] scripts/bpf: Add syscall commands printer
Date: Tue, 2 Mar 2021 09:19:42 -0800 [thread overview]
Message-ID: <20210302171947.2268128-11-joe@cilium.io> (raw)
In-Reply-To: <20210302171947.2268128-1-joe@cilium.io>
Add a new target to bpf_doc.py to support generating the list of syscall
commands directly from the UAPI headers. Assuming that developer
submissions keep the main header up to date, this should allow the man
pages to be automatically generated based on the latest API changes
rather than requiring someone to separately go back through the API and
describe each command.
Acked-by: Toke Høiland-Jørgensen <toke@redhat.com>
Reviewed-by: Quentin Monnet <quentin@isovalent.com>
Signed-off-by: Joe Stringer <joe@cilium.io>
---
scripts/bpf_doc.py | 100 +++++++++++++++++++++++++++++++++++++++++----
1 file changed, 91 insertions(+), 9 deletions(-)
diff --git a/scripts/bpf_doc.py b/scripts/bpf_doc.py
index 5a4f68aab335..2d94025b38e9 100755
--- a/scripts/bpf_doc.py
+++ b/scripts/bpf_doc.py
@@ -14,6 +14,9 @@ import sys, os
class NoHelperFound(BaseException):
pass
+class NoSyscallCommandFound(BaseException):
+ pass
+
class ParsingError(BaseException):
def __init__(self, line='<line not provided>', reader=None):
if reader:
@@ -23,18 +26,27 @@ class ParsingError(BaseException):
else:
BaseException.__init__(self, 'Error parsing line: %s' % line)
-class Helper(object):
+
+class APIElement(object):
"""
- An object representing the description of an eBPF helper function.
- @proto: function prototype of the helper function
- @desc: textual description of the helper function
- @ret: description of the return value of the helper function
+ An object representing the description of an aspect of the eBPF API.
+ @proto: prototype of the API symbol
+ @desc: textual description of the symbol
+ @ret: (optional) description of any associated return value
"""
def __init__(self, proto='', desc='', ret=''):
self.proto = proto
self.desc = desc
self.ret = ret
+
+class Helper(APIElement):
+ """
+ An object representing the description of an eBPF helper function.
+ @proto: function prototype of the helper function
+ @desc: textual description of the helper function
+ @ret: description of the return value of the helper function
+ """
def proto_break_down(self):
"""
Break down helper function protocol into smaller chunks: return type,
@@ -61,6 +73,7 @@ class Helper(object):
return res
+
class HeaderParser(object):
"""
An object used to parse a file in order to extract the documentation of a
@@ -73,6 +86,13 @@ class HeaderParser(object):
self.reader = open(filename, 'r')
self.line = ''
self.helpers = []
+ self.commands = []
+
+ def parse_element(self):
+ proto = self.parse_symbol()
+ desc = self.parse_desc()
+ ret = self.parse_ret()
+ return APIElement(proto=proto, desc=desc, ret=ret)
def parse_helper(self):
proto = self.parse_proto()
@@ -80,6 +100,18 @@ class HeaderParser(object):
ret = self.parse_ret()
return Helper(proto=proto, desc=desc, ret=ret)
+ def parse_symbol(self):
+ p = re.compile(' \* ?(.+)$')
+ capture = p.match(self.line)
+ if not capture:
+ raise NoSyscallCommandFound
+ end_re = re.compile(' \* ?NOTES$')
+ end = end_re.match(self.line)
+ if end:
+ raise NoSyscallCommandFound
+ self.line = self.reader.readline()
+ return capture.group(1)
+
def parse_proto(self):
# Argument can be of shape:
# - "void"
@@ -141,16 +173,29 @@ class HeaderParser(object):
break
return ret
- def run(self):
- # Advance to start of helper function descriptions.
- offset = self.reader.read().find('* Start of BPF helper function descriptions:')
+ def seek_to(self, target, help_message):
+ self.reader.seek(0)
+ offset = self.reader.read().find(target)
if offset == -1:
- raise Exception('Could not find start of eBPF helper descriptions list')
+ raise Exception(help_message)
self.reader.seek(offset)
self.reader.readline()
self.reader.readline()
self.line = self.reader.readline()
+ def parse_syscall(self):
+ self.seek_to('* DOC: eBPF Syscall Commands',
+ 'Could not find start of eBPF syscall descriptions list')
+ while True:
+ try:
+ command = self.parse_element()
+ self.commands.append(command)
+ except NoSyscallCommandFound:
+ break
+
+ def parse_helpers(self):
+ self.seek_to('* Start of BPF helper function descriptions:',
+ 'Could not find start of eBPF helper descriptions list')
while True:
try:
helper = self.parse_helper()
@@ -158,6 +203,9 @@ class HeaderParser(object):
except NoHelperFound:
break
+ def run(self):
+ self.parse_syscall()
+ self.parse_helpers()
self.reader.close()
###############################################################################
@@ -420,6 +468,37 @@ SEE ALSO
self.print_elem(helper)
+class PrinterSyscallRST(PrinterRST):
+ """
+ A printer for dumping collected information about the syscall API as a
+ ReStructured Text page compatible with the rst2man program, which can be
+ used to generate a manual page for the syscall.
+ @parser: A HeaderParser with APIElement objects to print to standard
+ output
+ """
+ def __init__(self, parser):
+ self.elements = parser.commands
+
+ def print_header(self):
+ header = '''\
+===
+bpf
+===
+-------------------------------------------------------------------------------
+Perform a command on an extended BPF object
+-------------------------------------------------------------------------------
+
+:Manual section: 2
+
+COMMANDS
+========
+'''
+ PrinterRST.print_license(self)
+ print(header)
+
+ def print_one(self, command):
+ print('**%s**' % (command.proto))
+ self.print_elem(command)
class PrinterHelpers(Printer):
@@ -620,6 +699,7 @@ bpfh = os.path.join(linuxRoot, 'include/uapi/linux/bpf.h')
printers = {
'helpers': PrinterHelpersRST,
+ 'syscall': PrinterSyscallRST,
}
argParser = argparse.ArgumentParser(description="""
@@ -644,6 +724,8 @@ headerParser.run()
# Print formatted output to standard output.
if args.header:
+ if args.target != 'helpers':
+ raise NotImplementedError('Only helpers header generation is supported')
printer = PrinterHelpers(headerParser)
else:
printer = printers[args.target](headerParser)
--
2.27.0
next prev parent reply other threads:[~2021-03-02 18:08 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-03-02 17:19 [PATCHv2 bpf-next 00/15] Improve BPF syscall command documentation Joe Stringer
2021-03-02 17:19 ` [PATCHv2 bpf-next 01/15] bpf: Import syscall arg documentation Joe Stringer
2021-03-03 19:38 ` Yonghong Song
2021-03-03 20:20 ` Yonghong Song
2021-03-02 17:19 ` [PATCHv2 bpf-next 02/15] bpf: Add minimal bpf() command documentation Joe Stringer
2021-03-03 19:44 ` Yonghong Song
2021-03-02 17:19 ` [PATCHv2 bpf-next 03/15] bpf: Document BPF_F_LOCK in syscall commands Joe Stringer
2021-03-03 20:16 ` Yonghong Song
2021-03-02 17:19 ` [PATCHv2 bpf-next 04/15] bpf: Document BPF_PROG_PIN syscall command Joe Stringer
2021-03-03 20:21 ` Yonghong Song
2021-03-02 17:19 ` [PATCHv2 bpf-next 05/15] bpf: Document BPF_PROG_ATTACH " Joe Stringer
2021-03-03 20:23 ` Yonghong Song
2021-03-02 17:19 ` [PATCHv2 bpf-next 06/15] bpf: Document BPF_PROG_TEST_RUN " Joe Stringer
2021-03-03 20:29 ` Yonghong Song
2021-03-03 23:53 ` Joe Stringer
2021-04-10 18:12 ` Joe Stringer
2021-03-02 17:19 ` [PATCHv2 bpf-next 07/15] bpf: Document BPF_PROG_QUERY " Joe Stringer
2021-03-03 20:31 ` Yonghong Song
2021-03-02 17:19 ` [PATCHv2 bpf-next 08/15] bpf: Document BPF_MAP_*_BATCH syscall commands Joe Stringer
2021-03-03 17:38 ` Brian Vazquez
2021-03-03 20:44 ` Yonghong Song
2021-03-02 17:19 ` [PATCHv2 bpf-next 09/15] scripts/bpf: Abstract eBPF API target parameter Joe Stringer
2021-03-02 17:19 ` Joe Stringer [this message]
2021-03-02 17:19 ` [PATCHv2 bpf-next 11/15] tools/bpf: Remove bpf-helpers from bpftool docs Joe Stringer
2021-03-02 17:19 ` [PATCHv2 bpf-next 12/15] selftests/bpf: Templatize man page generation Joe Stringer
2021-03-02 17:19 ` [PATCHv2 bpf-next 13/15] selftests/bpf: Test syscall command parsing Joe Stringer
2021-03-03 22:23 ` Yonghong Song
2021-03-03 23:50 ` Joe Stringer
2021-03-02 17:19 ` [PATCHv2 bpf-next 14/15] docs/bpf: Add bpf() syscall command reference Joe Stringer
2021-03-02 17:19 ` [PATCHv2 bpf-next 15/15] tools: Sync uapi bpf.h header with latest changes Joe Stringer
2021-03-03 17:25 ` [PATCHv2 bpf-next 00/15] Improve BPF syscall command documentation Jonathan Corbet
2021-03-03 18:50 ` Joe Stringer
2021-03-05 2:51 ` Alexei Starovoitov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210302171947.2268128-11-joe@cilium.io \
--to=joe@cilium.io \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=linux-doc@vger.kernel.org \
--cc=linux-man@vger.kernel.org \
--cc=quentin@isovalent.com \
--cc=toke@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox