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 a731132424
("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: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2024-03-08 11:03:19 -08:00
parent a0d942960d
commit ba980f8dff
5 changed files with 69 additions and 0 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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:

View file

@ -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>')