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

tools/net/ynl: Add support for nested structs



Make it possible for struct definitions to reference other struct
definitions ofr binary members. For example, the tbf qdisc uses this
struct definition for its parms attribute:

  -
    name: tc-tbf-qopt
    type: struct
    members:
      -
        name: rate
        type: binary
        struct: tc-ratespec
      -
        name: peakrate
        type: binary
        struct: tc-ratespec
      -
        name: limit
        type: u32
      -
        name: buffer
        type: u32
      -
        name: mtu
        type: u32

This adds the necessary schema changes and adds nested struct encoding
and decoding to ynl.

Signed-off-by: default avatarDonald Hunter <donald.hunter@gmail.com>
Reviewed-by: default avatarJiri Pirko <jiri@nvidia.com>
Link: https://lore.kernel.org/r/20240129223458.52046-11-donald.hunter@gmail.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 971c3eea
Loading
Loading
Loading
Loading
+12 −3
Original line number Diff line number Diff line
@@ -152,14 +152,23 @@ properties:
                  the right formatting mechanism when displaying values of this
                  type.
                enum: [ hex, mac, fddi, ipv4, ipv6, uuid ]
              struct:
                description: Name of the nested struct type.
                type: string
            if:
              properties:
                type:
                  oneOf:
                    - const: binary
                    - const: pad
                  const: pad
            then:
              required: [ len ]
            if:
              properties:
                type:
                  const: binary
            then:
              oneOf:
                - required: [ len ]
                - required: [ struct ]
        # End genetlink-legacy

  attribute-sets:
+2 −0
Original line number Diff line number Diff line
@@ -248,6 +248,7 @@ class SpecStructMember(SpecElement):
        len         integer, optional byte length of binary types
        display_hint  string, hint to help choose format specifier
                      when displaying the value
        struct      string, name of nested struct type
    """
    def __init__(self, family, yaml):
        super().__init__(family, yaml)
@@ -256,6 +257,7 @@ class SpecStructMember(SpecElement):
        self.enum = yaml.get('enum')
        self.len = yaml.get('len')
        self.display_hint = yaml.get('display-hint')
        self.struct = yaml.get('struct')


class SpecStruct(SpecElement):
+20 −6
Original line number Diff line number Diff line
@@ -674,6 +674,9 @@ class YnlFamily(SpecFamily):
            size = 0
            for m in members:
                if m.type in ['pad', 'binary']:
                    if m.struct:
                        size += self._struct_size(m.struct)
                    else:
                        size += m.len
                else:
                    format = NlAttr.get_format(m.type, m.byte_order)
@@ -691,6 +694,12 @@ class YnlFamily(SpecFamily):
            if m.type == 'pad':
                offset += m.len
            elif m.type == 'binary':
                if m.struct:
                    len = self._struct_size(m.struct)
                    value = self._decode_struct(data[offset : offset + len],
                                                m.struct)
                    offset += len
                else:
                    value = data[offset : offset + m.len]
                    offset += m.len
            else:
@@ -713,6 +722,11 @@ class YnlFamily(SpecFamily):
            if m.type == 'pad':
                attr_payload += bytearray(m.len)
            elif m.type == 'binary':
                if m.struct:
                    if value is None:
                        value = dict()
                    attr_payload += self._encode_struct(m.struct, value)
                else:
                    if value is None:
                        attr_payload += bytearray(m.len)
                    else: