summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHangbin Liu <liuhangbin@kylinos.cn>2026-10-08 16:24:02 +0800
committerJakub Kicinski <kuba@kernel.org>2026-10-15 16:59:58 -0700
commit05d3030eff5b73f6fe7f86dafa3eeae004e2ede1 (patch)
tree9d70453c7ef40be598294fa86ba271144b7b88ba
parent499f32f0eb56603af2930ba67b4eb82fc1437264 (diff)
tools: ynl: convert enum selector to string for sub-message parsing
YNL sub-message parsing expects a string selector for strcmp(). So for non-external enum selectors, convert the integer value to its string form via the family's {enum}_str() helper. This enables correct decoding of sub-messages keyed by enum values. After the change, if there is no encap_type (e.g. previous ordering on older kernels), or a new encap_type is missing from the spec file in future kernel, the code will report "Sub-message key not set", the same with string lookup fails. With the subsequent rt-route encap spec update, the newly generated code will look like: if (!dst->_present.encap_type) return ynl_submsg_failed(yarg, "encap", "encap-type"); encap_type_str = rt_route_encap_type_str(dst->encap_type); if (!encap_type_str) return ynl_submsg_failed(yarg, "encap", "enum-lookup-failed"); if (rt_route_encap_data_parse(&parg, encap_type_str, attr)) return YNL_PARSE_CB_ERROR; Signed-off-by: Hangbin Liu <liuhangbin@kylinos.cn> Link: https://patch.msgid.link/20261008-ynl_rt_encap-v4-2-4ed2ccf7f949@kylinos.cn Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rwxr-xr-xtools/net/ynl/pyynl/ynl_gen_c.py34
1 files changed, 29 insertions, 5 deletions
diff --git a/tools/net/ynl/pyynl/ynl_gen_c.py b/tools/net/ynl/pyynl/ynl_gen_c.py
index 15c79849c609..4aca51396a9e 100755
--- a/tools/net/ynl/pyynl/ynl_gen_c.py
+++ b/tools/net/ynl/pyynl/ynl_gen_c.py
@@ -951,13 +951,31 @@ class TypeSubMessage(TypeNest):
sel_var = f"_sel_{sel}"
else:
sel_var = f"{var}->{sel}"
- get_lines = [f'if (!{sel_var})',
- f'return ynl_submsg_failed(yarg, "{self.name}", "{selector}");',
- f"if ({self.nested_render_name}_parse(&parg, {sel_var}, attr))",
- "return YNL_PARSE_CB_ERROR;"]
+
+ local_vars = None
+
+ if self.selector.is_enum_val() and not self.selector.is_external():
+ enum = self.family.consts[self.selector.get_enum_name()]
+ pres_var = f"{var}->_present.{sel}"
+ parse_sel = f"{sel}_str"
+ local_vars = [f'const char *{parse_sel};']
+
+ get_lines = [
+ f'if (!{pres_var})',
+ f'return ynl_submsg_failed(yarg, "{self.name}", "{selector}");',
+ f'{parse_sel} = {enum.render_name}_str({sel_var});',
+ f'if (!{parse_sel})',
+ f'return ynl_submsg_failed(yarg, "{self.name}", "enum-lookup-failed");']
+ else:
+ parse_sel = sel_var
+ get_lines = [f'if (!{parse_sel})',
+ f'return ynl_submsg_failed(yarg, "{self.name}", "{selector}");']
+
+ get_lines += [f"if ({self.nested_render_name}_parse(&parg, {parse_sel}, attr))",
+ "return YNL_PARSE_CB_ERROR;"]
init_lines = [f"parg.rsp_policy = &{self.nested_render_name}_nest;",
f"parg.data = &{var}->{self.c_name};"]
- return get_lines, init_lines, None
+ return get_lines, init_lines, local_vars
class Selector:
@@ -979,6 +997,12 @@ class Selector:
def is_external(self):
return self._external
+ def is_enum_val(self):
+ return self.get_enum_name() is not None
+
+ def get_enum_name(self):
+ return self.attr and self.attr.attr.get("enum")
+
class Struct:
def __init__(self, family, space_name, type_list=None, fixed_header=None,