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: Donald Hunter <donald.hunter@gmail.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Link: https://lore.kernel.org/r/20240129223458.52046-11-donald.hunter@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Donald Hunter
2024-01-29 22:34:55 +00:00
committed by Jakub Kicinski
parent 971c3eeaf6
commit bf08f32c8c
3 changed files with 34 additions and 9 deletions

View File

@@ -674,7 +674,10 @@ class YnlFamily(SpecFamily):
size = 0
for m in members:
if m.type in ['pad', 'binary']:
size += m.len
if m.struct:
size += self._struct_size(m.struct)
else:
size += m.len
else:
format = NlAttr.get_format(m.type, m.byte_order)
size += format.size
@@ -691,8 +694,14 @@ class YnlFamily(SpecFamily):
if m.type == 'pad':
offset += m.len
elif m.type == 'binary':
value = data[offset : offset + m.len]
offset += m.len
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:
format = NlAttr.get_format(m.type, m.byte_order)
[ value ] = format.unpack_from(data, offset)
@@ -713,10 +722,15 @@ class YnlFamily(SpecFamily):
if m.type == 'pad':
attr_payload += bytearray(m.len)
elif m.type == 'binary':
if value is None:
attr_payload += bytearray(m.len)
if m.struct:
if value is None:
value = dict()
attr_payload += self._encode_struct(m.struct, value)
else:
attr_payload += bytes.fromhex(value)
if value is None:
attr_payload += bytearray(m.len)
else:
attr_payload += bytes.fromhex(value)
else:
if value is None:
value = 0