summaryrefslogtreecommitdiff
path: root/tools/net/ynl/pyynl
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2025-05-16 02:16:48 +0300
committerJakub Kicinski <kuba@kernel.org>2025-05-17 02:32:06 +0300
commit0939a418b3b092aa8a97a59752084896e4a7c813 (patch)
tree2857d5de4c531837c244a7000903e5d3472d2bd4 /tools/net/ynl/pyynl
parentb9e03e263610a8d872c753bc882676d3cba1797b (diff)
downloadlinux-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-xtools/net/ynl/pyynl/ynl_gen_c.py29
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):