Skip to content

Commit

Permalink
tools: ynl: Add struct attr decoding to ynl
Browse files Browse the repository at this point in the history
Add support for decoding attributes that contain C structs.

Signed-off-by: Donald Hunter <donald.hunter@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Donald Hunter authored and Jakub Kicinski committed Mar 29, 2023
1 parent b423c3c commit 2607191
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 1 deletion.
5 changes: 5 additions & 0 deletions Documentation/netlink/genetlink-legacy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,11 @@ properties:
description: Max length for a string or a binary attribute.
$ref: '#/$defs/len-or-define'
sub-type: *attr-type
# Start genetlink-legacy
struct:
description: Name of the struct type used for the attribute.
type: string
# End genetlink-legacy

# Make sure name-prefix does not appear in subsets (subsets inherit naming)
dependencies:
Expand Down
2 changes: 2 additions & 0 deletions tools/net/ynl/lib/nlspec.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ class SpecAttr(SpecElement):
value numerical ID when serialized
attr_set Attribute Set containing this attr
is_multi bool, attr may repeat multiple times
struct_name string, name of struct definition
sub_type string, name of sub type
"""
def __init__(self, family, attr_set, yaml, value):
Expand All @@ -160,6 +161,7 @@ def __init__(self, family, attr_set, yaml, value):
self.value = value
self.attr_set = attr_set
self.is_multi = yaml.get('multi-attr', False)
self.struct_name = yaml.get('struct')
self.sub_type = yaml.get('sub-type')


Expand Down
15 changes: 14 additions & 1 deletion tools/net/ynl/lib/ynl.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,17 @@ def as_c_array(self, type):
format, _ = self.type_formats[type]
return list({ x[0] for x in struct.iter_unpack(format, self.raw) })

def as_struct(self, members):
value = dict()
offset = 0
for m in members:
# TODO: handle non-scalar members
format, size = self.type_formats[m.type]
decoded = struct.unpack_from(format, self.raw, offset)
offset += size
value[m.name] = decoded[0]
return value

def __repr__(self):
return f"[type:{self.type} len:{self._len}] {self.raw}"

Expand Down Expand Up @@ -377,7 +388,9 @@ def _decode_enum(self, rsp, attr_spec):
rsp[attr_spec['name']] = value

def _decode_binary(self, attr, attr_spec):
if attr_spec.sub_type:
if attr_spec.struct_name:
decoded = attr.as_struct(self.consts[attr_spec.struct_name])
elif attr_spec.sub_type:
decoded = attr.as_c_array(attr_spec.sub_type)
else:
decoded = attr.as_bin()
Expand Down

0 comments on commit 2607191

Please sign in to comment.