Commit fbf5df34 authored by Jakub Kicinski's avatar Jakub Kicinski Committed by Paolo Abeni
Browse files

tools: ynl: add scope qualifier for definitions



Using definitions in kernel policies is awkward right now.
On one hand we want defines for max values and such.
On the other we don't have a way of adding kernel-only defines.
Adding unnecessary defines to uAPI is a bad idea, we won't
be able to delete them. And when it comes to policy user
space should just query it via the policy dump, not use
hard coded defines.

Add a "scope" property to definitions, which will let us tell
the codegen that a definition is for kernel use only. Support
following values:
  - uapi: render into the uAPI header (default, today's behavior)
  - kernel: render to kernel header only
  - user: same as kernel but for the user-side generated header

Definitions may have a header property (definition is "external",
provided by existing header). Extend the scope to headers, too.
If definition has both scope and header properties we will only
generate the includes in the right scope.

Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
Link: https://patch.msgid.link/20260510192904.3987113-8-kuba@kernel.org


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 0f9a857e
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -69,6 +69,15 @@ properties:
        header:
          description: For C-compatible languages, header which already defines this value.
          type: string
        scope:
          description: |
            Visibility of this definition. "uapi" (default) renders into
            the uAPI header, "kernel" renders into the kernel-side
            generated header, "user" renders into the user-side
            generated header. When combined with `header:`, the
            definition is not rendered, and the named header is
            included only by code matching the scope.
          enum: [ uapi, kernel, user ]
        type:
          enum: [ const, enum, flags ]
        doc:
+9 −0
Original line number Diff line number Diff line
@@ -83,6 +83,15 @@ properties:
        header:
          description: For C-compatible languages, header which already defines this value.
          type: string
        scope:
          description: |
            Visibility of this definition. "uapi" (default) renders into
            the uAPI header, "kernel" renders into the kernel-side
            generated header, "user" renders into the user-side
            generated header. When combined with `header:`, the
            definition is not rendered, and the named header is
            included only by code matching the scope.
          enum: [ uapi, kernel, user ]
        type:
          enum: [ const, enum, flags, struct ] # Trim
        doc:
+9 −0
Original line number Diff line number Diff line
@@ -55,6 +55,15 @@ properties:
        header:
          description: For C-compatible languages, header which already defines this value.
          type: string
        scope:
          description: |
            Visibility of this definition. "uapi" (default) renders into
            the uAPI header, "kernel" renders into the kernel-side
            generated header, "user" renders into the user-side
            generated header. When combined with `header:`, the
            definition is not rendered, and the named header is
            included only by code matching the scope.
          enum: [ uapi, kernel, user ]
        type:
          enum: [ const, enum, flags ]
        doc:
+9 −0
Original line number Diff line number Diff line
@@ -87,6 +87,15 @@ properties:
        header:
          description: For C-compatible languages, header which already defines this value.
          type: string
        scope:
          description: |
            Visibility of this definition. "uapi" (default) renders into
            the uAPI header, "kernel" renders into the kernel-side
            generated header, "user" renders into the user-side
            generated header. When combined with `header:`, the
            definition is not rendered, and the named header is
            included only by code matching the scope.
          enum: [ uapi, kernel, user ]
        type:
          enum: [ const, enum, flags, struct ] # Trim
        doc:
+29 −2
Original line number Diff line number Diff line
@@ -3212,6 +3212,8 @@ def render_uapi(family, cw):
    for const in family['definitions']:
        if const.get('header'):
            continue
        if const.get('scope', 'uapi') != 'uapi':
            continue

        if const['type'] != 'const':
            cw.writes_defines(defines)
@@ -3339,6 +3341,25 @@ def render_uapi(family, cw):
    cw.p(f'#endif /* {hdr_prot} */')


def render_scoped_consts(family, cw, scope):
    defines = []
    for const in family['definitions']:
        if const['type'] != 'const':
            continue
        if const.get('header'):
            continue
        if const.get('scope') != scope:
            continue
        name_pfx = const.get('name-prefix', f"{family.ident_name}-")
        defines.append([
            c_upper(family.get('c-define-name',
                               f"{name_pfx}{const['name']}")),
            const['value']])
    if defines:
        cw.writes_defines(defines)
        cw.nl()


def _render_user_ntf_entry(ri, op):
    if not ri.family.is_classic():
        ri.cw.block_start(line=f"[{op.enum_name}] = ")
@@ -3504,7 +3525,11 @@ def main():
            cw.p('#include "ynl.h"')
        headers = []
    for definition in parsed['definitions'] + parsed['attribute-sets']:
        if 'header' in definition:
        if 'header' not in definition:
            continue
        scope = definition.get('scope', 'uapi')
        if scope != 'uapi' and scope != args.mode:
            continue
        headers.append(definition['header'])
    if args.mode == 'user':
        headers.append(parsed.uapi_header)
@@ -3522,6 +3547,7 @@ def main():
            for one in args.user_header:
                cw.p(f'#include "{one}"')
        else:
            render_scoped_consts(parsed, cw, 'user')
            cw.p('struct ynl_sock;')
            cw.nl()
            render_user_family(parsed, cw, True)
@@ -3529,6 +3555,7 @@ def main():

    if args.mode == "kernel":
        if args.header:
            render_scoped_consts(parsed, cw, 'kernel')
            for _, struct in sorted(parsed.pure_nested_structs.items()):
                if struct.request:
                    cw.p('/* Common nested types */')