2025-05-07 11:28 UTC-0700 ~ Ihor Solodrai <isolodrai@xxxxxxxx> > bpf_doc.py parses bpf.h header to collect information about various > API elements (such as BPF helpers) and then dump them in one of the > supported formats: rst docs and a C header. > > It's useful for external tools to be able to consume this information > in an easy-to-parse format such as JSON. Implement JSON printers and > add --json command line argument. > > v1: https://lore.kernel.org/bpf/20250506000605.497296-1-isolodrai@xxxxxxxx/ > > Signed-off-by: Ihor Solodrai <isolodrai@xxxxxxxx> > --- > scripts/bpf_doc.py | 112 +++++++++++++++++++++++++++++++++++++++------ > 1 file changed, 98 insertions(+), 14 deletions(-) > > diff --git a/scripts/bpf_doc.py b/scripts/bpf_doc.py > index e74a01a85070..d669a0e16bf2 100755 > --- a/scripts/bpf_doc.py > +++ b/scripts/bpf_doc.py > @@ -8,6 +8,7 @@ > from __future__ import print_function > > import argparse > +import json > import re > import sys, os > import subprocess > @@ -43,6 +44,14 @@ class APIElement(object): > self.ret = ret > self.attrs = attrs > > + def to_dict(self): > + return { > + 'proto': self.proto, > + 'desc': self.desc, > + 'ret': self.ret, > + 'attrs': self.attrs > + } > + > > class Helper(APIElement): > """ > @@ -81,6 +90,11 @@ class Helper(APIElement): > > return res > > + def to_dict(self): > + d = super().to_dict() > + d.update(self.proto_break_down()) > + return d > + > > ATTRS = { > '__bpf_fastcall': 'bpf_fastcall' > @@ -675,7 +689,7 @@ COMMANDS > self.print_elem(command) > > > -class PrinterHelpers(Printer): > +class PrinterHelpersHeader(Printer): > """ > A printer for dumping collected information about helpers as C header to > be included from BPF program. > @@ -896,6 +910,43 @@ class PrinterHelpers(Printer): > print(') = (void *) %d;' % helper.enum_val) > print('') > > + > +class PrinterHelpersJSON(Printer): > + """ > + A printer for dumping collected information about helpers as a JSON file. > + @parser: A HeaderParser with Helper objects > + """ > + > + def __init__(self, parser): > + self.elements = parser.helpers > + self.elem_number_check( > + parser.desc_unique_helpers, > + parser.define_unique_helpers, > + "helper", > + "___BPF_FUNC_MAPPER", > + ) > + > + def print_all(self): > + helper_dicts = [helper.to_dict() for helper in self.elements] > + out_dict = {'helpers': helper_dicts} > + print(json.dumps(out_dict, indent=4)) > + > + > +class PrinterSyscallJSON(Printer): > + """ > + A printer for dumping collected syscall information as a JSON file. > + @parser: A HeaderParser with APIElement objects > + """ > + > + def __init__(self, parser): > + self.elements = parser.commands > + self.elem_number_check(parser.desc_syscalls, parser.enum_syscalls, 'syscall', 'bpf_cmd') > + > + def print_all(self): > + syscall_dicts = [syscall.to_dict() for syscall in self.elements] > + out_dict = {'syscall': syscall_dicts} > + print(json.dumps(out_dict, indent=4)) > + > ############################################################################### > > # If script is launched from scripts/ from kernel tree and can access > @@ -910,6 +961,19 @@ printers = { > 'syscall': PrinterSyscallRST, > } Can you please remove the old "printers" dict that is right above? It's no longer used now that you redefine it below. pw-bot: cr > > +# target -> output format -> printer > +printers = { > + 'helpers': { > + 'rst': PrinterHelpersRST, > + 'json': PrinterHelpersJSON, > + 'header': PrinterHelpersHeader, > + }, > + 'syscall': { > + 'rst': PrinterSyscallRST, > + 'json': PrinterSyscallJSON > + }, > +} > + > argParser = argparse.ArgumentParser(description=""" > Parse eBPF header file and generate documentation for the eBPF API. > The RST-formatted output produced can be turned into a manual page with the [...]