summaryrefslogtreecommitdiff
path: root/tools/net/ynl/lib/ynl.py
diff options
context:
space:
mode:
authorDonald Hunter <donald.hunter@gmail.com>2023-12-15 09:37:11 +0000
committerJakub Kicinski <kuba@kernel.org>2023-12-18 14:39:43 -0800
commit1769e2be4baaa3273b56d1137bf67a6a747222ed (patch)
tree92bea0a62eca2ecbebbf1ec9b429ef28feec7d50 /tools/net/ynl/lib/ynl.py
parent17ed5c1a9e3674a7e6b3e7bd66824ecd79ecce02 (diff)
tools/net/ynl: Add 'sub-message' attribute decoding to ynl
Implement the 'sub-message' attribute type in ynl. Encode support is not yet implemented. Support for sub-message selectors at a different nest level from the key attribute is not yet supported. Reviewed-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Donald Hunter <donald.hunter@gmail.com> Link: https://lore.kernel.org/r/20231215093720.18774-5-donald.hunter@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'tools/net/ynl/lib/ynl.py')
-rw-r--r--tools/net/ynl/lib/ynl.py48
1 files changed, 40 insertions, 8 deletions
diff --git a/tools/net/ynl/lib/ynl.py b/tools/net/ynl/lib/ynl.py
index df7b1547de1f..a8db71441634 100644
--- a/tools/net/ynl/lib/ynl.py
+++ b/tools/net/ynl/lib/ynl.py
@@ -170,10 +170,9 @@ class NlAttr:
class NlAttrs:
- def __init__(self, msg):
+ def __init__(self, msg, offset=0):
self.attrs = []
- offset = 0
while offset < len(msg):
attr = NlAttr(msg, offset)
offset += attr.full_len
@@ -371,8 +370,8 @@ class NetlinkProtocol:
fixed_header_size = 0
if ynl:
op = ynl.rsp_by_value[msg.cmd()]
- fixed_header_size = ynl._fixed_header_size(op)
- msg.raw_attrs = NlAttrs(msg.raw[fixed_header_size:])
+ fixed_header_size = ynl._fixed_header_size(op.fixed_header)
+ msg.raw_attrs = NlAttrs(msg.raw, fixed_header_size)
return msg
def get_mcast_id(self, mcast_name, mcast_groups):
@@ -549,6 +548,37 @@ class YnlFamily(SpecFamily):
else:
rsp[name] = [decoded]
+ def _resolve_selector(self, attr_spec, vals):
+ sub_msg = attr_spec.sub_message
+ if sub_msg not in self.sub_msgs:
+ raise Exception(f"No sub-message spec named {sub_msg} for {attr_spec.name}")
+ sub_msg_spec = self.sub_msgs[sub_msg]
+
+ selector = attr_spec.selector
+ if selector not in vals:
+ raise Exception(f"There is no value for {selector} to resolve '{attr_spec.name}'")
+ value = vals[selector]
+ if value not in sub_msg_spec.formats:
+ raise Exception(f"No message format for '{value}' in sub-message spec '{sub_msg}'")
+
+ spec = sub_msg_spec.formats[value]
+ return spec
+
+ def _decode_sub_msg(self, attr, attr_spec, rsp):
+ msg_format = self._resolve_selector(attr_spec, rsp)
+ decoded = {}
+ offset = 0
+ if msg_format.fixed_header:
+ decoded.update(self._decode_fixed_header(attr, msg_format.fixed_header));
+ offset = self._fixed_header_size(msg_format.fixed_header)
+ if msg_format.attr_set:
+ if msg_format.attr_set in self.attr_sets:
+ subdict = self._decode(NlAttrs(attr.raw, offset), msg_format.attr_set)
+ decoded.update(subdict)
+ else:
+ raise Exception(f"Unknown attribute-set '{attr_space}' when decoding '{attr_spec.name}'")
+ 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"] == 'sub-message':
+ decoded = self._decode_sub_msg(attr, attr_spec, rsp)
else:
if not self.process_unknown:
raise Exception(f'Unknown {attr_spec["type"]} with name {attr_spec["name"]}')
@@ -626,16 +658,16 @@ class YnlFamily(SpecFamily):
return
msg = self.nlproto.decode(self, NlMsg(request, 0, op.attr_set))
- offset = 20 + self._fixed_header_size(op)
+ offset = 20 + self._fixed_header_size(op.fixed_header)
path = self._decode_extack_path(msg.raw_attrs, op.attr_set, offset,
extack['bad-attr-offs'])
if path:
del extack['bad-attr-offs']
extack['bad-attr'] = path
- def _fixed_header_size(self, op):
- if op.fixed_header:
- fixed_header_members = self.consts[op.fixed_header].members
+ def _fixed_header_size(self, name):
+ if name:
+ fixed_header_members = self.consts[name].members
size = 0
for m in fixed_header_members:
format = NlAttr.get_format(m.type, m.byte_order)