tools: ynl: add schema checking

Add a --validate flag to pyynl for explicit schema check with error
reporting and add a schema_check make target to check all YNL specs.

make -C tools/net/ynl schema_check
make: Entering directory '/home/donaldh/net-next/tools/net/ynl'
ok 1 binder.yaml schema validation
not ok 2 conntrack.yaml schema validation
'labels mask' does not match '^[0-9a-z-]+$'

Failed validating 'pattern' in schema['properties']['attribute-sets']['items']['properties']['attributes']['items']['properties']['name']:
    {'type': 'string', 'pattern': '^[0-9a-z-]+$'}

On instance['attribute-sets'][14]['attributes'][22]['name']:
    'labels mask'

ok 3 devlink.yaml schema validation
[...]

Signed-off-by: Donald Hunter <donald.hunter@gmail.com>
Link: https://patch.msgid.link/20251127123502.89142-2-donald.hunter@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Donald Hunter
2025-11-27 12:34:59 +00:00
committed by Jakub Kicinski
parent 2c80116b50
commit 362d051c90
2 changed files with 35 additions and 6 deletions

View File

@@ -12,6 +12,8 @@ endif
libdir ?= $(prefix)/$(libdir_relative)
includedir ?= $(prefix)/include
SPECDIR=../../../Documentation/netlink/specs
SUBDIRS = lib generated samples ynltool tests
all: $(SUBDIRS) libynl.a
@@ -54,4 +56,20 @@ install: libynl.a lib/*.h
run_tests:
@$(MAKE) -C tests run_tests
.PHONY: all clean distclean install run_tests $(SUBDIRS)
schema_check:
@N=1; \
for spec in $(SPECDIR)/*.yaml ; do \
NAME=$$(basename $$spec) ; \
OUTPUT=$$(./pyynl/cli.py --spec $$spec --validate) ; \
if [ $$? -eq 0 ] ; then \
echo "ok $$N $$NAME schema validation" ; \
else \
echo "not ok $$N $$NAME schema validation" ; \
echo "$$OUTPUT" ; \
echo ; \
fi ; \
N=$$((N+1)) ; \
done
.PHONY: all clean distclean install run_tests schema_check $(SUBDIRS)

View File

@@ -10,7 +10,7 @@ import sys
import textwrap
sys.path.append(pathlib.Path(__file__).resolve().parent.as_posix())
from lib import YnlFamily, Netlink, NlError
from lib import YnlFamily, Netlink, NlError, SpecFamily
sys_schema_dir='/usr/share/ynl'
relative_schema_dir='../../../../Documentation/netlink'
@@ -127,6 +127,7 @@ def main():
group.add_argument('--list-msgs', action='store_true')
group.add_argument('--list-attrs', dest='list_attrs', metavar='OPERATION', type=str,
help='List attributes for an operation')
group.add_argument('--validate', action='store_true')
parser.add_argument('--duration', dest='duration', type=int,
help='when subscribed, watch for DURATION seconds')
@@ -168,15 +169,25 @@ def main():
if args.family:
spec = f"{spec_dir()}/{args.family}.yaml"
if args.schema is None and spec.startswith(sys_schema_dir):
args.schema = '' # disable schema validation when installed
if args.process_unknown is None:
args.process_unknown = True
else:
spec = args.spec
if not os.path.isfile(spec):
raise Exception(f"Spec file {spec} does not exist")
if args.validate:
try:
SpecFamily(spec, args.schema)
except Exception as error:
print(error)
exit(1)
return
if args.family: # set behaviour when using installed specs
if args.schema is None and spec.startswith(sys_schema_dir):
args.schema = '' # disable schema validation when installed
if args.process_unknown is None:
args.process_unknown = True
ynl = YnlFamily(spec, args.schema, args.process_unknown,
recv_size=args.dbg_small_recv)
if args.dbg_small_recv: