Commit ba980f8d authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

netlink: specs: support generating code for genl socket priv

The family struct is auto-generated for new families, support
use of the sock_priv_* mechanism added in commit a7311324
("genetlink: introduce per-sock family private storage").

For example if the family wants to use struct sk_buff as its
private struct (unrealistic but just for illustration), it would
add to its spec:

  kernel-family:
    headers: [ "linux/skbuff.h" ]
    sock-priv: struct sk_buff

ynl-gen-c will declare the appropriate priv size and hook
in function prototypes to be implemented by the family.

Link: https://lore.kernel.org/r/20240308190319.2523704-1-kuba@kernel.org


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent a0d94296
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -378,3 +378,22 @@ properties:
              type: string
            # End genetlink-c
            flags: *cmd_flags

  kernel-family:
    description: Additional global attributes used for kernel C code generation.
    type: object
    additionalProperties: False
    properties:
      headers:
        description: |
          List of extra headers which should be included in the source
          of the generated code.
        type: array
        items:
          type: string
      sock-priv:
        description: |
          Literal name of the type which is used within the kernel
          to store the socket state. The type / structure is internal
          to the kernel, and is not defined in the spec.
        type: string
+19 −0
Original line number Diff line number Diff line
@@ -439,3 +439,22 @@ properties:
              type: string
            # End genetlink-c
            flags: *cmd_flags

  kernel-family:
    description: Additional global attributes used for kernel C code generation.
    type: object
    additionalProperties: False
    properties:
      headers:
        description: |
          List of extra headers which should be included in the source
          of the generated code.
        type: array
        items:
          type: string
      sock-priv:
        description: |
          Literal name of the type which is used within the kernel
          to store the socket state. The type / structure is internal
          to the kernel, and is not defined in the spec.
        type: string
+19 −0
Original line number Diff line number Diff line
@@ -328,3 +328,22 @@ properties:
                The name for the group, used to form the define and the value of the define.
              type: string
            flags: *cmd_flags

  kernel-family:
    description: Additional global attributes used for kernel C code generation.
    type: object
    additionalProperties: False
    properties:
      headers:
        description: |
          List of extra headers which should be included in the source
          of the generated code.
        type: array
        items:
          type: string
      sock-priv:
        description: |
          Literal name of the type which is used within the kernel
          to store the socket state. The type / structure is internal
          to the kernel, and is not defined in the spec.
        type: string
+2 −0
Original line number Diff line number Diff line
@@ -418,6 +418,7 @@ class SpecFamily(SpecElement):
        consts     dict of all constants/enums
        fixed_header  string, optional name of family default fixed header struct
        mcast_groups  dict of all multicast groups (index by name)
        kernel_family   dict of kernel family attributes
    """
    def __init__(self, spec_path, schema_path=None, exclude_ops=None):
        with open(spec_path, "r") as stream:
@@ -461,6 +462,7 @@ class SpecFamily(SpecElement):
        self.ntfs = collections.OrderedDict()
        self.consts = collections.OrderedDict()
        self.mcast_groups = collections.OrderedDict()
        self.kernel_family = collections.OrderedDict(self.yaml.get('kernel-family', {}))

        last_exception = None
        while len(self._resolution_list) > 0:
+10 −0
Original line number Diff line number Diff line
@@ -2342,6 +2342,10 @@ def print_kernel_family_struct_hdr(family, cw):

    cw.p(f"extern struct genl_family {family.c_name}_nl_family;")
    cw.nl()
    if 'sock-priv' in family.kernel_family:
        cw.p(f'void {family.c_name}_nl_sock_priv_init({family.kernel_family["sock-priv"]} *priv);')
        cw.p(f'void {family.c_name}_nl_sock_priv_destroy({family.kernel_family["sock-priv"]} *priv);')
        cw.nl()


def print_kernel_family_struct_src(family, cw):
@@ -2363,6 +2367,11 @@ def print_kernel_family_struct_src(family, cw):
    if family.mcgrps['list']:
        cw.p(f'.mcgrps\t\t= {family.c_name}_nl_mcgrps,')
        cw.p(f'.n_mcgrps\t= ARRAY_SIZE({family.c_name}_nl_mcgrps),')
    if 'sock-priv' in family.kernel_family:
        cw.p(f'.sock_priv_size\t= sizeof({family.kernel_family["sock-priv"]}),')
        # Force cast here, actual helpers take pointer to the real type.
        cw.p(f'.sock_priv_init\t= (void *){family.c_name}_nl_sock_priv_init,')
        cw.p(f'.sock_priv_destroy = (void *){family.c_name}_nl_sock_priv_destroy,')
    cw.block_end(';')


@@ -2659,6 +2668,7 @@ def main():
                cw.p(f'#include "{os.path.basename(args.out_file[:-2])}.h"')
            cw.nl()
        headers = ['uapi/' + parsed.uapi_header]
        headers += parsed.kernel_family.get('headers', [])
    else:
        cw.p('#include <stdlib.h>')
        cw.p('#include <string.h>')