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:
committed by
Jakub Kicinski
parent
971c3eeaf6
commit
bf08f32c8c
@@ -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:
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user