^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) #!/usr/bin/env python3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) # SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) # Copyright (C) 2018-2019 Netronome Systems, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) # In case user attempts to run with Python 2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) from __future__ import print_function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) import argparse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) import re
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) import sys, os
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) class NoHelperFound(BaseException):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) pass
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) class ParsingError(BaseException):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) def __init__(self, line='<line not provided>', reader=None):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) if reader:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) BaseException.__init__(self,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) 'Error at file offset %d, parsing line: %s' %
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) (reader.tell(), line))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) BaseException.__init__(self, 'Error parsing line: %s' % line)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) class Helper(object):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) An object representing the description of an eBPF helper function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) @proto: function prototype of the helper function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) @desc: textual description of the helper function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) @ret: description of the return value of the helper function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) def __init__(self, proto='', desc='', ret=''):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) self.proto = proto
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) self.desc = desc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) self.ret = ret
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) def proto_break_down(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) Break down helper function protocol into smaller chunks: return type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) name, distincts arguments.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) arg_re = re.compile('((\w+ )*?(\w+|...))( (\**)(\w+))?$')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) res = {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) proto_re = re.compile('(.+) (\**)(\w+)\(((([^,]+)(, )?){1,5})\)$')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) capture = proto_re.match(self.proto)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) res['ret_type'] = capture.group(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) res['ret_star'] = capture.group(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) res['name'] = capture.group(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) res['args'] = []
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) args = capture.group(4).split(', ')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) for a in args:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) capture = arg_re.match(a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) res['args'].append({
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) 'type' : capture.group(1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) 'star' : capture.group(5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) 'name' : capture.group(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return res
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) class HeaderParser(object):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) An object used to parse a file in order to extract the documentation of a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) list of eBPF helper functions. All the helpers that can be retrieved are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) stored as Helper object, in the self.helpers() array.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) @filename: name of file to parse, usually include/uapi/linux/bpf.h in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) kernel tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) def __init__(self, filename):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) self.reader = open(filename, 'r')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) self.line = ''
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) self.helpers = []
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) def parse_helper(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) proto = self.parse_proto()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) desc = self.parse_desc()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) ret = self.parse_ret()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return Helper(proto=proto, desc=desc, ret=ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) def parse_proto(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) # Argument can be of shape:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) # - "void"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) # - "type name"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) # - "type *name"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) # - Same as above, with "const" and/or "struct" in front of type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) # - "..." (undefined number of arguments, for bpf_trace_printk())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) # There is at least one term ("void"), and at most five arguments.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) p = re.compile(' \* ?((.+) \**\w+\((((const )?(struct )?(\w+|\.\.\.)( \**\w+)?)(, )?){1,5}\))$')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) capture = p.match(self.line)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if not capture:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) raise NoHelperFound
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) self.line = self.reader.readline()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return capture.group(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) def parse_desc(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) p = re.compile(' \* ?(?:\t| {5,8})Description$')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) capture = p.match(self.line)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if not capture:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) # Helper can have empty description and we might be parsing another
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) # attribute: return but do not consume.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return ''
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) # Description can be several lines, some of them possibly empty, and it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) # stops when another subsection title is met.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) desc = ''
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) while True:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) self.line = self.reader.readline()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if self.line == ' *\n':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) desc += '\n'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) p = re.compile(' \* ?(?:\t| {5,8})(?:\t| {8})(.*)')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) capture = p.match(self.line)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if capture:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) desc += capture.group(1) + '\n'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) break
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return desc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) def parse_ret(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) p = re.compile(' \* ?(?:\t| {5,8})Return$')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) capture = p.match(self.line)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if not capture:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) # Helper can have empty retval and we might be parsing another
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) # attribute: return but do not consume.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) return ''
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) # Return value description can be several lines, some of them possibly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) # empty, and it stops when another subsection title is met.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) ret = ''
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) while True:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) self.line = self.reader.readline()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if self.line == ' *\n':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) ret += '\n'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) p = re.compile(' \* ?(?:\t| {5,8})(?:\t| {8})(.*)')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) capture = p.match(self.line)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if capture:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) ret += capture.group(1) + '\n'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) break
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return ret
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) def run(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) # Advance to start of helper function descriptions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) offset = self.reader.read().find('* Start of BPF helper function descriptions:')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if offset == -1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) raise Exception('Could not find start of eBPF helper descriptions list')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) self.reader.seek(offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) self.reader.readline()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) self.reader.readline()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) self.line = self.reader.readline()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) while True:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) try:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) helper = self.parse_helper()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) self.helpers.append(helper)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) except NoHelperFound:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) break
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) self.reader.close()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) ###############################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) class Printer(object):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) A generic class for printers. Printers should be created with an array of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) Helper objects, and implement a way to print them in the desired fashion.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) @helpers: array of Helper objects to print to standard output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) def __init__(self, helpers):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) self.helpers = helpers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) def print_header(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) pass
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) def print_footer(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) pass
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) def print_one(self, helper):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) pass
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) def print_all(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) self.print_header()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) for helper in self.helpers:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) self.print_one(helper)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) self.print_footer()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) class PrinterRST(Printer):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) A printer for dumping collected information about helpers as a ReStructured
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) Text page compatible with the rst2man program, which can be used to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) generate a manual page for the helpers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) @helpers: array of Helper objects to print to standard output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) def print_header(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) header = '''\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) .. Copyright (C) All BPF authors and contributors from 2014 to present.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) .. See git log include/uapi/linux/bpf.h in kernel tree for details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) ..
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) .. %%%LICENSE_START(VERBATIM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) .. Permission is granted to make and distribute verbatim copies of this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) .. manual provided the copyright notice and this permission notice are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) .. preserved on all copies.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) ..
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) .. Permission is granted to copy and distribute modified versions of this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) .. manual under the conditions for verbatim copying, provided that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) .. entire resulting derived work is distributed under the terms of a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) .. permission notice identical to this one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) ..
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) .. Since the Linux kernel and libraries are constantly changing, this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) .. manual page may be incorrect or out-of-date. The author(s) assume no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) .. responsibility for errors or omissions, or for damages resulting from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) .. the use of the information contained herein. The author(s) may not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) .. have taken the same level of care in the production of this manual,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) .. which is licensed free of charge, as they might when working
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) .. professionally.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) ..
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) .. Formatted or processed versions of this manual, if unaccompanied by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) .. the source, must acknowledge the copyright and authors of this work.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) .. %%%LICENSE_END
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) ..
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) .. Please do not edit this file. It was generated from the documentation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) .. located in file include/uapi/linux/bpf.h of the Linux kernel sources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) .. (helpers description), and from scripts/bpf_helpers_doc.py in the same
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) .. repository (header and footer).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) ===========
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) BPF-HELPERS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) ===========
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) list of eBPF helper functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) :Manual section: 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) DESCRIPTION
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) ===========
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) The extended Berkeley Packet Filter (eBPF) subsystem consists in programs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) written in a pseudo-assembly language, then attached to one of the several
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) kernel hooks and run in reaction of specific events. This framework differs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) from the older, "classic" BPF (or "cBPF") in several aspects, one of them being
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) the ability to call special functions (or "helpers") from within a program.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) These functions are restricted to a white-list of helpers defined in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) kernel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) These helpers are used by eBPF programs to interact with the system, or with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) the context in which they work. For instance, they can be used to print
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) debugging messages, to get the time since the system was booted, to interact
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) with eBPF maps, or to manipulate network packets. Since there are several eBPF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) program types, and that they do not run in the same context, each program type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) can only call a subset of those helpers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) Due to eBPF conventions, a helper can not have more than five arguments.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) Internally, eBPF programs call directly into the compiled helper functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) without requiring any foreign-function interface. As a result, calling helpers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) introduces no overhead, thus offering excellent performance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) This document is an attempt to list and document the helpers available to eBPF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) developers. They are sorted by chronological order (the oldest helpers in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) kernel at the top).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) HELPERS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) =======
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) '''
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) print(header)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) def print_footer(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) footer = '''
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) EXAMPLES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) ========
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) Example usage for most of the eBPF helpers listed in this manual page are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) available within the Linux kernel sources, at the following locations:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) * *samples/bpf/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) * *tools/testing/selftests/bpf/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) LICENSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) =======
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) eBPF programs can have an associated license, passed along with the bytecode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) instructions to the kernel when the programs are loaded. The format for that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) string is identical to the one in use for kernel modules (Dual licenses, such
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) as "Dual BSD/GPL", may be used). Some helper functions are only accessible to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) programs that are compatible with the GNU Privacy License (GPL).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) In order to use such helpers, the eBPF program must be loaded with the correct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) license string passed (via **attr**) to the **bpf**\ () system call, and this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) generally translates into the C source code of the program containing a line
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) similar to the following:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) ::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) char ____license[] __attribute__((section("license"), used)) = "GPL";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) IMPLEMENTATION
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) ==============
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) This manual page is an effort to document the existing eBPF helper functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) But as of this writing, the BPF sub-system is under heavy development. New eBPF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) program or map types are added, along with new helper functions. Some helpers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) are occasionally made available for additional program types. So in spite of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) the efforts of the community, this page might not be up-to-date. If you want to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) check by yourself what helper functions exist in your kernel, or what types of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) programs they can support, here are some files among the kernel tree that you
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) may be interested in:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) * *include/uapi/linux/bpf.h* is the main BPF header. It contains the full list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) of all helper functions, as well as many other BPF definitions including most
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) of the flags, structs or constants used by the helpers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * *net/core/filter.c* contains the definition of most network-related helper
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) functions, and the list of program types from which they can be used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) * *kernel/trace/bpf_trace.c* is the equivalent for most tracing program-related
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) helpers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) * *kernel/bpf/verifier.c* contains the functions used to check that valid types
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) of eBPF maps are used with a given helper function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) * *kernel/bpf/* directory contains other files in which additional helpers are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) defined (for cgroups, sockmaps, etc.).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) * The bpftool utility can be used to probe the availability of helper functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) on the system (as well as supported program and map types, and a number of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) other parameters). To do so, run **bpftool feature probe** (see
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) **bpftool-feature**\ (8) for details). Add the **unprivileged** keyword to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) list features available to unprivileged users.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) Compatibility between helper functions and program types can generally be found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) in the files where helper functions are defined. Look for the **struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) bpf_func_proto** objects and for functions returning them: these functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) contain a list of helpers that a given program type can call. Note that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) **default:** label of the **switch ... case** used to filter helpers can call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) other functions, themselves allowing access to additional helpers. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) requirement for GPL license is also in those **struct bpf_func_proto**.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) Compatibility between helper functions and map types can be found in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) **check_map_func_compatibility**\ () function in file *kernel/bpf/verifier.c*.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) Helper functions that invalidate the checks on **data** and **data_end**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) pointers for network processing are listed in function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) **bpf_helper_changes_pkt_data**\ () in file *net/core/filter.c*.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) SEE ALSO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) ========
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) **bpf**\ (2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) **bpftool**\ (8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) **cgroups**\ (7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) **ip**\ (8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) **perf_event_open**\ (2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) **sendmsg**\ (2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) **socket**\ (7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) **tc-bpf**\ (8)'''
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) print(footer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) def print_proto(self, helper):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) Format function protocol with bold and italics markers. This makes RST
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) file less readable, but gives nice results in the manual page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) proto = helper.proto_break_down()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) print('**%s %s%s(' % (proto['ret_type'],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) proto['ret_star'].replace('*', '\\*'),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) proto['name']),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) end='')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) comma = ''
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) for a in proto['args']:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) one_arg = '{}{}'.format(comma, a['type'])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if a['name']:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if a['star']:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) one_arg += ' {}**\ '.format(a['star'].replace('*', '\\*'))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) one_arg += '** '
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) one_arg += '*{}*\\ **'.format(a['name'])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) comma = ', '
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) print(one_arg, end='')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) print(')**')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) def print_one(self, helper):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) self.print_proto(helper)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if (helper.desc):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) print('\tDescription')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) # Do not strip all newline characters: formatted code at the end of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) # a section must be followed by a blank line.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) for line in re.sub('\n$', '', helper.desc, count=1).split('\n'):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) print('{}{}'.format('\t\t' if line else '', line))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (helper.ret):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) print('\tReturn')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) for line in helper.ret.rstrip().split('\n'):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) print('{}{}'.format('\t\t' if line else '', line))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) print('')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) class PrinterHelpers(Printer):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) A printer for dumping collected information about helpers as C header to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) be included from BPF program.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) @helpers: array of Helper objects to print to standard output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) type_fwds = [
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 'struct bpf_fib_lookup',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 'struct bpf_sk_lookup',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 'struct bpf_perf_event_data',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 'struct bpf_perf_event_value',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 'struct bpf_pidns_info',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 'struct bpf_redir_neigh',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 'struct bpf_sock',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 'struct bpf_sock_addr',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 'struct bpf_sock_ops',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 'struct bpf_sock_tuple',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 'struct bpf_spin_lock',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 'struct bpf_sysctl',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 'struct bpf_tcp_sock',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 'struct bpf_tunnel_key',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 'struct bpf_xfrm_state',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 'struct pt_regs',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 'struct sk_reuseport_md',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 'struct sockaddr',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 'struct tcphdr',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 'struct seq_file',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 'struct tcp6_sock',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 'struct tcp_sock',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 'struct tcp_timewait_sock',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 'struct tcp_request_sock',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 'struct udp6_sock',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 'struct task_struct',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 'struct __sk_buff',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 'struct sk_msg_md',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 'struct xdp_md',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 'struct path',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 'struct btf_ptr',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) ]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) known_types = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) '...',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 'void',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 'const void',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 'char',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 'const char',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 'int',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 'long',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 'unsigned long',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) '__be16',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) '__be32',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) '__wsum',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 'struct bpf_fib_lookup',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 'struct bpf_perf_event_data',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 'struct bpf_perf_event_value',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 'struct bpf_pidns_info',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 'struct bpf_redir_neigh',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 'struct bpf_sk_lookup',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 'struct bpf_sock',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 'struct bpf_sock_addr',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 'struct bpf_sock_ops',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 'struct bpf_sock_tuple',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 'struct bpf_spin_lock',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 'struct bpf_sysctl',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 'struct bpf_tcp_sock',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 'struct bpf_tunnel_key',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 'struct bpf_xfrm_state',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 'struct pt_regs',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 'struct sk_reuseport_md',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 'struct sockaddr',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 'struct tcphdr',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 'struct seq_file',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 'struct tcp6_sock',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 'struct tcp_sock',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 'struct tcp_timewait_sock',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 'struct tcp_request_sock',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 'struct udp6_sock',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 'struct task_struct',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 'struct path',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 'struct btf_ptr',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) mapped_types = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 'u8': '__u8',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 'u16': '__u16',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 'u32': '__u32',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 'u64': '__u64',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 's8': '__s8',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 's16': '__s16',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 's32': '__s32',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 's64': '__s64',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 'size_t': 'unsigned long',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 'struct bpf_map': 'void',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 'struct sk_buff': 'struct __sk_buff',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 'const struct sk_buff': 'const struct __sk_buff',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 'struct sk_msg_buff': 'struct sk_msg_md',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 'struct xdp_buff': 'struct xdp_md',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) # Helpers overloaded for different context types.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) overloaded_helpers = [
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 'bpf_get_socket_cookie',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 'bpf_sk_assign',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) ]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) def print_header(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) header = '''\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) /* This is auto-generated file. See bpf_helpers_doc.py for details. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) /* Forward declarations of BPF structs */'''
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) print(header)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) for fwd in self.type_fwds:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) print('%s;' % fwd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) print('')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) def print_footer(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) footer = ''
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) print(footer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) def map_type(self, t):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if t in self.known_types:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) return t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) if t in self.mapped_types:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) return self.mapped_types[t]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) print("Unrecognized type '%s', please add it to known types!" % t,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) file=sys.stderr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) sys.exit(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) seen_helpers = set()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) def print_one(self, helper):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) proto = helper.proto_break_down()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) if proto['name'] in self.seen_helpers:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) self.seen_helpers.add(proto['name'])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) print('/*')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) print(" * %s" % proto['name'])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) print(" *")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) if (helper.desc):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) # Do not strip all newline characters: formatted code at the end of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) # a section must be followed by a blank line.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) for line in re.sub('\n$', '', helper.desc, count=1).split('\n'):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) print(' *{}{}'.format(' \t' if line else '', line))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) if (helper.ret):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) print(' *')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) print(' * Returns')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) for line in helper.ret.rstrip().split('\n'):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) print(' *{}{}'.format(' \t' if line else '', line))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) print(' */')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) print('static %s %s(*%s)(' % (self.map_type(proto['ret_type']),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) proto['ret_star'], proto['name']), end='')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) comma = ''
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) for i, a in enumerate(proto['args']):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) t = a['type']
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) n = a['name']
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if proto['name'] in self.overloaded_helpers and i == 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) t = 'void'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) n = 'ctx'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) one_arg = '{}{}'.format(comma, self.map_type(t))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if n:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) if a['star']:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) one_arg += ' {}'.format(a['star'])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) one_arg += ' '
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) one_arg += '{}'.format(n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) comma = ', '
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) print(one_arg, end='')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) print(') = (void *) %d;' % len(self.seen_helpers))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) print('')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) ###############################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) # If script is launched from scripts/ from kernel tree and can access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) # ../include/uapi/linux/bpf.h, use it as a default name for the file to parse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) # otherwise the --filename argument will be required from the command line.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) script = os.path.abspath(sys.argv[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) linuxRoot = os.path.dirname(os.path.dirname(script))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) bpfh = os.path.join(linuxRoot, 'include/uapi/linux/bpf.h')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) argParser = argparse.ArgumentParser(description="""
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) Parse eBPF header file and generate documentation for eBPF helper functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) The RST-formatted output produced can be turned into a manual page with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) rst2man utility.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) """)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) argParser.add_argument('--header', action='store_true',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) help='generate C header file')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) if (os.path.isfile(bpfh)):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) argParser.add_argument('--filename', help='path to include/uapi/linux/bpf.h',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) default=bpfh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) argParser.add_argument('--filename', help='path to include/uapi/linux/bpf.h')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) args = argParser.parse_args()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) # Parse file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) headerParser = HeaderParser(args.filename)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) headerParser.run()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) # Print formatted output to standard output.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) if args.header:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) printer = PrinterHelpers(headerParser.helpers)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) printer = PrinterRST(headerParser.helpers)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) printer.print_all()