diff options
author | Jakub Kicinski <kuba@kernel.org> | 2025-05-16 02:16:48 +0300 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2025-05-17 02:32:06 +0300 |
commit | 0939a418b3b092aa8a97a59752084896e4a7c813 (patch) | |
tree | 2857d5de4c531837c244a7000903e5d3472d2bd4 /tools/net/ynl/pyynl | |
parent | b9e03e263610a8d872c753bc882676d3cba1797b (diff) | |
download | linux-0939a418b3b092aa8a97a59752084896e4a7c813.tar.xz |
tools: ynl: submsg: reverse parse / error reporting
Reverse parsing lets YNL convert bad and missing attr pointers
from extack into a string like "missing attribute nest1.nest2.attr_name".
It's a feature that's unique to YNL C AFAIU (even the Python YNL
can't do nested reverse parsing). Add support for reverse-parsing
of sub-messages.
To simplify the logic and the code annotate the type policies
with extra metadata. Mark the selectors and the messages with
the information we need. We assume that key / selector always
precedes the sub-message while parsing (and also if there are
multiple sub-messages like in rt-link they are interleaved
selector 1 ... submsg 1 ... selector 2 .. submsg 2, not
selector 1 ... selector 2 ... submsg 1 ... submsg 2).
The rt-link sample in a subsequent changes shows reverse parsing
of sub-messages in action.
Reviewed-by: Donald Hunter <donald.hunter@gmail.com>
Link: https://patch.msgid.link/20250515231650.1325372-8-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'tools/net/ynl/pyynl')
-rwxr-xr-x | tools/net/ynl/pyynl/ynl_gen_c.py | 29 |
1 files changed, 28 insertions, 1 deletions
diff --git a/tools/net/ynl/pyynl/ynl_gen_c.py b/tools/net/ynl/pyynl/ynl_gen_c.py index b6b54d6fa906..1f8cc34ab3f0 100755 --- a/tools/net/ynl/pyynl/ynl_gen_c.py +++ b/tools/net/ynl/pyynl/ynl_gen_c.py @@ -57,6 +57,8 @@ class Type(SpecAttr): self.request = False self.reply = False + self.is_selector = False + if 'len' in attr: self.len = attr['len'] @@ -484,7 +486,10 @@ class TypeString(Type): ri.cw.p(f"char *{self.c_name};") def _attr_typol(self): - return f'.type = YNL_PT_NUL_STR, ' + typol = f'.type = YNL_PT_NUL_STR, ' + if self.is_selector: + typol += '.is_selector = 1, ' + return typol def _attr_policy(self, policy): if 'exact-len' in self.checks: @@ -878,6 +883,16 @@ class TypeNestTypeValue(Type): class TypeSubMessage(TypeNest): + def __init__(self, family, attr_set, attr, value): + super().__init__(family, attr_set, attr, value) + + self.selector = Selector(attr, attr_set) + + def _attr_typol(self): + typol = f'.type = YNL_PT_NEST, .nest = &{self.nested_render_name}_nest, ' + typol += f'.is_submsg = 1, .selector_type = {self.attr_set[self["selector"]].value} ' + return typol + def _attr_get(self, ri, var): sel = c_lower(self['selector']) get_lines = [f'if (!{var}->{sel})', @@ -890,6 +905,18 @@ class TypeSubMessage(TypeNest): return get_lines, init_lines, None +class Selector: + def __init__(self, msg_attr, attr_set): + self.name = msg_attr["selector"] + + if self.name in attr_set: + self.attr = attr_set[self.name] + self.attr.is_selector = True + self._external = False + else: + raise Exception("Passing selectors from external nests not supported") + + class Struct: def __init__(self, family, space_name, type_list=None, inherited=None, submsg=None): |