Re: [PATCH bpf-next,v3] bpf/scripts: assert helper enum value is aligned with comment order

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 24/08/2022 13:26, Eyal Birger wrote:
> The helper value is ABI as defined by enum bpf_func_id.
> As bpf_helper_defs.h is used for the userpace part, it must be consistent
> with this enum.
> 
> Before this change the comments order was used by the bpf_doc script in
> order to set the helper values defined in the helpers file.
> 
> When adding new helpers it is very puzzling when the userspace application
> breaks in weird places if the comment is inserted instead of appended -
> because the generated helper ABI is incorrect and shifted.
> 
> This commit sets the helper value to the enum value.
> 
> In addition it is currently the practice to have the comments appended
> and kept in the same order as the enum. As such, add an assertion
> validating the comment order is consistent with enum value.
> 
> In case a different comments ordering is desired, this assertion can
> be lifted.
> 
> Signed-off-by: Eyal Birger <eyal.birger@xxxxxxxxx>
> 
> ---
> v3: based on feedback from Quentin Monnet:
> - move assertion to parser
> - avoid using define_unique_helpers as elem_number_check() relies on
>   it being an array
> - set enum_val in helper object instead of passing as a dict to the
>   printer
> 
> v2: based on feedback from Quentin Monnet:
> - assert the current comment ordering
> - match only one FN in each line
> ---
>  scripts/bpf_doc.py | 39 ++++++++++++++++++++++++++++++++++-----
>  1 file changed, 34 insertions(+), 5 deletions(-)
> 
> diff --git a/scripts/bpf_doc.py b/scripts/bpf_doc.py
> index f4f3e7ec6d44..114b2a60afc8 100755
> --- a/scripts/bpf_doc.py
> +++ b/scripts/bpf_doc.py
> @@ -50,6 +50,10 @@ class Helper(APIElement):
>      @desc: textual description of the helper function
>      @ret: description of the return value of the helper function
>      """
> +    def __init__(self, *args, **kwargs):
> +        super().__init__(*args, **kwargs)
> +        self.enum_value = None

Should this be self.enum_val?
Looks good otherwise.

> +
>      def proto_break_down(self):
>          """
>          Break down helper function protocol into smaller chunks: return type,
> @@ -92,6 +96,7 @@ class HeaderParser(object):
>          self.commands = []
>          self.desc_unique_helpers = set()
>          self.define_unique_helpers = []
> +        self.helper_enum_vals = {}
>          self.desc_syscalls = []
>          self.enum_syscalls = []
>  
> @@ -248,30 +253,54 @@ class HeaderParser(object):
>                  break
>  
>      def parse_define_helpers(self):
> -        # Parse the number of FN(...) in #define __BPF_FUNC_MAPPER to compare
> -        # later with the number of unique function names present in description.
> +        # Parse FN(...) in #define __BPF_FUNC_MAPPER to compare later with the
> +        # number of unique function names present in description and use the
> +        # correct enumeration value.
>          # Note: seek_to(..) discards the first line below the target search text,
>          # resulting in FN(unspec) being skipped and not added to self.define_unique_helpers.
>          self.seek_to('#define __BPF_FUNC_MAPPER(FN)',
>                       'Could not find start of eBPF helper definition list')
> -        # Searches for either one or more FN(\w+) defines or a backslash for newline
> -        p = re.compile('\s*(FN\(\w+\))+|\\\\')
> +        # Searches for one FN(\w+) define or a backslash for newline
> +        p = re.compile('\s*FN\((\w+)\)|\\\\')
>          fn_defines_str = ''
> +        i = 1  # 'unspec' is skipped as mentioned above
>          while True:
>              capture = p.match(self.line)
>              if capture:
>                  fn_defines_str += self.line
> +                self.helper_enum_vals[capture.expand(r'bpf_\1')] = i
> +                i += 1
>              else:
>                  break
>              self.line = self.reader.readline()
>          # Find the number of occurences of FN(\w+)
>          self.define_unique_helpers = re.findall('FN\(\w+\)', fn_defines_str)
>  
> +    def assign_helper_values(self):
> +        seen_helpers = set()
> +        for helper in self.helpers:
> +            proto = helper.proto_break_down()
> +            name = proto['name']
> +            try:
> +                enum_val = self.helper_enum_vals[name]
> +            except KeyError:
> +                raise Exception("Helper %s is missing from enum bpf_func_id" % name)
> +
> +            # Enforce current practice of having the descriptions ordered
> +            # by enum value.
> +            seen_helpers.add(name)
> +            desc_val = len(seen_helpers)
> +            if desc_val != enum_val:
> +                raise Exception("Helper %s comment order (#%d) must be aligned with its position (#%d) in enum bpf_func_id" % (name, desc_val, enum_val))
> +
> +            helper.enum_val = enum_val
> +
>      def run(self):
>          self.parse_desc_syscall()
>          self.parse_enum_syscall()
>          self.parse_desc_helpers()
>          self.parse_define_helpers()
> +        self.assign_helper_values()
>          self.reader.close()
>  
>  ###############################################################################
> @@ -796,7 +825,7 @@ class PrinterHelpers(Printer):
>              comma = ', '
>              print(one_arg, end='')
>  
> -        print(') = (void *) %d;' % len(self.seen_helpers))
> +        print(') = (void *) %d;' % helper.enum_val)
>          print('')
>  
>  ###############################################################################




[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux