Re: [PATCH RFC 01/20] ctlv: Add the schema language and generator
From: Jonathan Cameron
Date: Tue Oct 20 2026 - 18:31:57 EST
On Thu, 15 Oct 2026 16:50:34 +0200
Jiri Pirko <jiri@xxxxxxxxxxx> wrote:
> From: Jiri Pirko <jiri@xxxxxxxxxx>
>
> Define the YAML schema and append-only family registry. Add ctlvgen to
> validate specifications and emit kernel and UAPI outputs.
>
> Assisted-by: Cursor: GPT-5.6 Sol
> Assisted-by: Cursor: Claude Opus 5.5
> Signed-off-by: Jiri Pirko <jiri@xxxxxxxxxx>
Obviously you asked for broad structural review and this isn't that. I'm terrible
at reading code for just the big picture but feel free to ignore the small stuff
in this reply.
My python being even worse than my yaml I'll only say that
part looked plausible to me!
> diff --git a/Documentation/ctlv/ctlv-schema.yaml b/Documentation/ctlv/ctlv-schema.yaml
> new file mode 100644
> index 000000000000..38fd56e6627c
> --- /dev/null
> +++ b/Documentation/ctlv/ctlv-schema.yaml
> @@ -0,0 +1,359 @@
> +# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
> +%YAML 1.2
> +---
> +$id: http://kernel.org/schemas/ctlv/ctlv-schema.yaml#
> +$schema: https://json-schema.org/draft-07/schema
> +
> +# The syntax gate for a CTLV family specification: permitted keys, their shapes
> +# and the closed sets of keywords. Anything needing more than one declaration at
> +# a time is checked by tools/ctlv/ctlvgen/lib/semantics.py.
> +
> +$defs:
> + name:
> + description: Kebab-case identifier. A dot is reserved for selectors.
> + type: string
> + pattern: ^[a-z0-9]+(-[a-z0-9]+)*$
> +
> + family-name:
> + description: Name carried by family discovery.
> + allOf:
> + - $ref: '#/$defs/name'
> + - maxLength: 63
> +
> + selector:
> + description: |
Really trivial but nice to drop | where it doesn't make sense to
force line break preservation like here.
> + A named attr set, a whole attr group, or one exact attr as
> + "group.attr". There are no tuple selectors and no cross-family
> + qualification.
> + type: string
> + pattern: ^[a-z0-9]+(-[a-z0-9]+)*(\.[a-z0-9]+(-[a-z0-9]+)*)?$
> +
> + selectors:
> + oneOf:
> + - $ref: '#/$defs/selector'
> + - type: array
> + minItems: 1
> + items:
> + $ref: '#/$defs/selector'
My yaml is terrible (and all learnt form reviewing DT bindings which are
undoubtedly perfect :) but random LLM agrees with me that you can simplify
this as it's a local definition. I think doing so makes life a little
easier for reader by indicating it is thing defined a few lines up.
$ref: 'selector'
I don't care that much though.
> +
> + uint:
> + type: integer
> + minimum: 0
> + maximum: 4294967295
> +
> + integer-bound:
> + type: integer
> + minimum: -9223372036854775808
> + maximum: 18446744073709551615
> +
> + max-occurrences:
> + description: |
> + A finite positive count, or unlimited, which is reachable only from
> + query replies.
> + oneOf:
> + - type: integer
> + minimum: 1
> + maximum: 4294967295
> + - const: unlimited
> +
> + unit:
> + description: CTLV-owned unit, matching enum ctlv_unit.
> + enum: [ seconds, hertz, bytes, celsius ]
These are used in here? I'm sure some are but guessing not
all of them yet.
> + attr:
> + description: |
> + One attr declaration. Exactly one primary form out of type, enum,
> + flags, attrs and blob must be present. optional-attrs and recursive
> + may only accompany attrs.
Maybe worth the yaml gynastics needed to enforce this rather than
just putting it in the description? An LLM fed me something when
I sanity checked how bad it would be and it's only somewhat nasty...
Bunch of:
oneOf:
- required: [ type ]
not: { anyOf: [ { required: [ enum ] }, { required: [ flags ] }, { required: [ attrs ] }, { required: [ blob ] } ] }
lines, though I thought there was a more compact way to do it.
> + type: object
> + required: [ name ]
> + additionalProperties: false
> + properties:
> + name:
> + $ref: '#/$defs/name'
> + type:
> + description: |
> + Primitive payload. Integers are always 64-bit, and a bool is one
> + byte holding zero or one.
> + enum: [ uint, sint, bool, string, binary ]
> + enum:
> + description: Name of an enum definition; implies an unsigned payload.
> + $ref: '#/$defs/name'
> + flags:
> + description: Name of a flags definition; implies an unsigned payload.
> + $ref: '#/$defs/name'
> + attrs:
> + description: Nested payload, given as selectors.
> + $ref: '#/$defs/selectors'
> + optional-attrs:
> + description: Further nested payload whose placements are optional.
> + $ref: '#/$defs/selectors'
> + recursive:
> + description: |
> + The nested payload is one attr set that may contain this attr
> + again, describing a structure of any depth. Only a query reply can
> + hold one, since such a nest has no maximum length.
> + const: true
> + blob:
> + $ref: '#/$defs/blob'
> + min:
> + description: Inclusive minimum of an integer payload.
> + $ref: '#/$defs/integer-bound'
> + max:
> + description: Inclusive maximum of an integer payload.
> + $ref: '#/$defs/integer-bound'
> + length:
> + description: Exact payload length of a binary attr.
> + $ref: '#/$defs/uint'
> + min-length:
> + description: |
> + Minimum payload length, excluding the terminator of a string.
> + $ref: '#/$defs/uint'
> + max-length:
> + description: |
> + Maximum payload length, excluding the terminator of a string.
> + $ref: '#/$defs/uint'
> + unit:
> + $ref: '#/$defs/unit'
> + scale:
> + description: Decimal exponent applied to the payload.
> + type: integer
> + minimum: -128
> + maximum: 127
> + max-occurrences:
> + $ref: '#/$defs/max-occurrences'
> +