Thread (13 messages) 13 messages, 2 authors, 2d ago

[PATCH net-next v4 2/6] tools: ynl: convert enum selector to string for sub-message parsing

flat view
WARM2d

From: Hangbin Liu <hidden>
Date: 2026-10-08 08:24:25
Also in: bpf, lkml
Subsystem: networking [general], the rest, yaml netlink (ynl) · Maintainers: "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds, Donald Hunter

From: Hangbin Liu <redacted>

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 <redacted>
---

For sashiko:

1. For the extack error-walking path in ynl.c that doesn't handle
   enum-keyed selectors. This series doesn't modify ynl.c, it changes
   the code generator to emit the _str() conversion in generated parsing
   code. The run time error-walking path is a separate concern.

   Since rt-route encap is the first enum-keyed sub-message in the YNL
   specs, this is a new limitation rather than a regression in existing
   functionality. It can be addressed as a follow-up patch to ynl.c.

2. For the selector byte-order issue. This doesn't affect the current
   series. The encap-type selector is type: u16 with no byte-order
   specified (native order), so the raw value passed to _str() is already
   host-order. nftables is in GENS_UNSUP today, so no in-tree generated
   family hits this yet. We address this as a follow-up.
---
 tools/net/ynl/pyynl/ynl_gen_c.py | 34 +++++++++++++++++++++++++++++-----
 1 file 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,
-- 
2.55.0
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help