Commit 26071913 authored by Donald Hunter's avatar Donald Hunter Committed by Jakub Kicinski
Browse files

tools: ynl: Add struct attr decoding to ynl



Add support for decoding attributes that contain C structs.

Signed-off-by: default avatarDonald Hunter <donald.hunter@gmail.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent b423c3c8
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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:
+2 −0
Original line number Diff line number Diff line
@@ -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):
@@ -160,6 +161,7 @@ class SpecAttr(SpecElement):
        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')


+14 −1
Original line number Diff line number Diff line
@@ -102,6 +102,17 @@ class NlAttr:
        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}"

@@ -377,7 +388,9 @@ class YnlFamily(SpecFamily):
        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()