From patchwork Wed Feb 17 01:08:15 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joe Stringer X-Patchwork-Id: 12090823 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AC4FAC433DB for ; Wed, 17 Feb 2021 01:10:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7B6AB64E2E for ; Wed, 17 Feb 2021 01:10:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231516AbhBQBKR (ORCPT ); Tue, 16 Feb 2021 20:10:17 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47590 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231462AbhBQBJv (ORCPT ); Tue, 16 Feb 2021 20:09:51 -0500 Received: from mail-pf1-x436.google.com (mail-pf1-x436.google.com [IPv6:2607:f8b0:4864:20::436]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C5583C061797; Tue, 16 Feb 2021 17:08:53 -0800 (PST) Received: by mail-pf1-x436.google.com with SMTP id x136so7366519pfc.2; Tue, 16 Feb 2021 17:08:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=sHn1TcXA40LLznUdfZ0EnywfCC8GI0Od3igBD7EM/qA=; b=inLrmew4Cded46OMVXm440//MhXtGm/AFsHnPkZUJZ0Si7ZBGly2nyrIYt4eVXqxcT PMpocNArusisJd0qlkPyA3DTH1dMjPlc23YjUa59l22XmiX8bb++C+G9mUAB7/Y31a3i 7tF1TNy/soSno0eOqnG9ONKxyK1t+ZnYoeJ5JD+asBwyi+8nZyAfVvSsgF8iDcMlxFgF HYwyuDVU1n4fV+WPPd2J69Hd5bzAA4Z/gM5k8ibY7+sCJKopV8UlUlObq/GRXNutCuyl KM2QCoLQcV3hiZyzV1b7pmIryruBGrWvM5b0WqO1nVw+JmREvaQMKM8CEcv/rd1vR4QQ JiqA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=sHn1TcXA40LLznUdfZ0EnywfCC8GI0Od3igBD7EM/qA=; b=N61xoY9htilY5c24HLVrFUqB+YiTZ+p12u5UwUyc59EQx94ZY8CcTHBwQfYHPeDuvC EEXzWehBWXKXe6Ua3Kz23XZAljZPuPH+tMPJTMhbROfuhlJQOkxS6YGbq7tDzxoTGgke 0+4LUgczSybcrIuGBBSWdHsaTXkLSHao/IviMZYlZM0yy5gGlxBdFepgT+Gzf+Hi5smQ XobsvgiJaW/qUaTEiQmkO700TOyavshZ7BruZvXln3D/Ls5wor/jOurP/v0qdN5W1+4R OMnI48P6Sqz4pOKe+9TP5onpqOt4CPOxTzY5DG8umGOLipzEdsUq83+yhJ0OWJcK8GJE 9e0A== X-Gm-Message-State: AOAM531J5inh5hrxGyRKyy64etzkuawxG100MWwTflcyTeyG1s8pCKZB mXqDoeK2or0akqIaHD0w7UaZHquE5OtROA== X-Google-Smtp-Source: ABdhPJys71FeVg+7o5aVJCeZX3Mu9fkvHyCeuAc359Q8UbtC07NsulXwihDGuXTSL8QRccUrb/aD7A== X-Received: by 2002:a63:4507:: with SMTP id s7mr21678588pga.390.1613524132973; Tue, 16 Feb 2021 17:08:52 -0800 (PST) Received: from localhost.localdomain (c-73-93-5-123.hsd1.ca.comcast.net. [73.93.5.123]) by smtp.gmail.com with ESMTPSA id c22sm175770pfc.12.2021.02.16.17.08.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 16 Feb 2021 17:08:52 -0800 (PST) Sender: Joe Stringer From: Joe Stringer To: bpf@vger.kernel.org Cc: Joe Stringer , netdev@vger.kernel.org, daniel@iogearbox.net, ast@kernel.org, mtk.manpages@gmail.com, Quentin Monnet Subject: [PATCH bpf-next 11/17] scripts/bpf: Add syscall commands printer Date: Tue, 16 Feb 2021 17:08:15 -0800 Message-Id: <20210217010821.1810741-12-joe@wand.net.nz> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210217010821.1810741-1-joe@wand.net.nz> References: <20210217010821.1810741-1-joe@wand.net.nz> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net From: Joe Stringer 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. Reviewed-by: Quentin Monnet Signed-off-by: Joe Stringer --- scripts/bpf_doc.py | 98 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 89 insertions(+), 9 deletions(-) diff --git a/scripts/bpf_doc.py b/scripts/bpf_doc.py index 5a4f68aab335..72a2ba323692 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='', 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('* Start of BPF 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="""