netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Donald Hunter <donald.hunter@gmail.com>
To: netdev@vger.kernel.org, Jakub Kicinski <kuba@kernel.org>,
	"David S. Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@google.com>,
	Paolo Abeni <pabeni@redhat.com>, Jonathan Corbet <corbet@lwn.net>,
	linux-doc@vger.kernel.org
Cc: donald.hunter@redhat.com, Donald Hunter <donald.hunter@gmail.com>
Subject: [RFC PATCH net-next v1 3/6] tools/net/ynl: Add dynamic attribute decoding to ynl
Date: Wed, 29 Nov 2023 10:11:56 +0000	[thread overview]
Message-ID: <20231129101159.99197-4-donald.hunter@gmail.com> (raw)
In-Reply-To: <20231129101159.99197-1-donald.hunter@gmail.com>

Implement dynamic attribute space selection and decoding to
the ynl library.

Encode support is not yet implemented. Support for dynamic selectors
at a different nest level from the key attribute is not yet supported.

Signed-off-by: Donald Hunter <donald.hunter@gmail.com>
---
 tools/net/ynl/lib/nlspec.py | 27 +++++++++++++++++++++++++++
 tools/net/ynl/lib/ynl.py    | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+)

diff --git a/tools/net/ynl/lib/nlspec.py b/tools/net/ynl/lib/nlspec.py
index 92889298b197..c32c85ddf8fb 100644
--- a/tools/net/ynl/lib/nlspec.py
+++ b/tools/net/ynl/lib/nlspec.py
@@ -142,6 +142,29 @@ class SpecEnumSet(SpecElement):
             mask += e.user_value(as_flags)
         return mask
 
+class SpecDynAttr(SpecElement):
+    """ Single Dynamic Netlink atttribute type
+
+    Represents a choice of dynamic attribute type within an attr space.
+
+    Attributes:
+        value         attribute value to match against dynamic type selector
+        struct_name   string, name of struct definition
+        sub_type      string, name of sub type
+        len           integer, optional byte length of binary types
+        display_hint  string, hint to help choose format specifier
+                      when displaying the value
+    """
+    def __init__(self, family, parent, yaml):
+        super().__init__(family, yaml)
+
+        self.value = yaml.get('value')
+        self.struct_name = yaml.get('struct')
+        self.sub_type = yaml.get('sub-type')
+        self.byte_order = yaml.get('byte-order')
+        self.len = yaml.get('len')
+        self.display_hint = yaml.get('display-hint')
+
 
 class SpecAttr(SpecElement):
     """ Single Netlink atttribute type
@@ -173,9 +196,13 @@ class SpecAttr(SpecElement):
         self.byte_order = yaml.get('byte-order')
         self.len = yaml.get('len')
         self.display_hint = yaml.get('display-hint')
+        self.dynamic_types = {}
 
         self.is_auto_scalar = self.type == "sint" or self.type == "uint"
 
+        if 'selector' in yaml:
+            for item in yaml.get('selector').get('list', []):
+                self.dynamic_types[item['value']] = SpecDynAttr(family, self, item)
 
 class SpecAttrSet(SpecElement):
     """ Netlink Attribute Set class.
diff --git a/tools/net/ynl/lib/ynl.py b/tools/net/ynl/lib/ynl.py
index 92995bca14e1..5ce01ce37573 100644
--- a/tools/net/ynl/lib/ynl.py
+++ b/tools/net/ynl/lib/ynl.py
@@ -549,6 +549,36 @@ class YnlFamily(SpecFamily):
         else:
             rsp[name] = [decoded]
 
+    def _resolve_selector(self, attr_spec, vals):
+        if 'selector' in attr_spec:
+            selector = attr_spec['selector']
+            key = selector['attribute']
+            if key in vals:
+                value = vals[key]
+                if value in attr_spec.dynamic_types:
+                    spec = attr_spec.dynamic_types[value]
+                    return spec
+                else:
+                    raise Exception(f"No entry for {key}={value} in selector for '{attr_spec['name']}'")
+            else:
+                raise Exception(f"There is no value for {key} to use in selector for '{attr_spec['name']}'")
+        else:
+            raise Exception("type=dynamic requires a selector in '{attr_spec['name']}'")
+
+    def _decode_dynamic(self, attr, attr_spec, rsp):
+        dyn_spec = self._resolve_selector(attr_spec, rsp)
+        if dyn_spec['type'] == 'binary':
+            decoded = self._decode_binary(attr, dyn_spec)
+        elif dyn_spec['type'] == 'nest':
+            attr_space = dyn_spec['nested-attributes']
+            if attr_space in self.attr_sets:
+                decoded = self._decode(NlAttrs(attr.raw), attr_space)
+            else:
+                raise Exception(f"Unknown attribute-set '{attr_space}'")
+        else:
+            raise Exception(f"Unknown type '{spec['type']}' for value '{value}'")
+        return decoded
+
     def _decode(self, attrs, space):
         if space:
             attr_space = self.attr_sets[space]
@@ -586,6 +616,8 @@ class YnlFamily(SpecFamily):
                     value = self._decode_enum(value, attr_spec)
                     selector = self._decode_enum(selector, attr_spec)
                 decoded = {"value": value, "selector": selector}
+            elif attr_spec["type"] == 'dynamic':
+                decoded = self._decode_dynamic(attr, attr_spec, rsp)
             else:
                 if not self.process_unknown:
                     raise Exception(f'Unknown {attr_spec["type"]} with name {attr_spec["name"]}')
-- 
2.42.0


  parent reply	other threads:[~2023-11-29 10:12 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-11-29 10:11 [RFC PATCH net-next v1 0/6] tools/net/ynl: Add dynamic selector for options attrs Donald Hunter
2023-11-29 10:11 ` [RFC PATCH net-next v1 1/6] doc/netlink: Add bitfield32, s8, s16 to the netlink-raw schema Donald Hunter
2023-11-29 10:11 ` [RFC PATCH net-next v1 2/6] doc/netlink: Add a nest selector to " Donald Hunter
2023-11-29 10:11 ` Donald Hunter [this message]
2023-11-29 10:11 ` [RFC PATCH net-next v1 4/6] doc/netlink/specs: add dynamic nest selector for rt_link data Donald Hunter
2023-11-29 10:11 ` [RFC PATCH net-next v1 5/6] doc/netlink/specs: Add a spec for tc Donald Hunter
2023-11-29 10:11 ` [RFC PATCH net-next v1 6/6] tools/net/ynl: Add optional fixed-header to dynamic nests Donald Hunter
2023-11-29 16:09 ` [RFC PATCH net-next v1 0/6] tools/net/ynl: Add dynamic selector for options attrs Jakub Kicinski
2023-11-29 16:58   ` Donald Hunter
2023-11-29 17:49     ` Jakub Kicinski
2023-11-30  8:48       ` Donald Hunter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20231129101159.99197-4-donald.hunter@gmail.com \
    --to=donald.hunter@gmail.com \
    --cc=corbet@lwn.net \
    --cc=davem@davemloft.net \
    --cc=donald.hunter@redhat.com \
    --cc=edumazet@google.com \
    --cc=kuba@kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).