diff options
Diffstat (limited to 'tools/net/ynl/lib/ynl.py')
-rw-r--r-- | tools/net/ynl/lib/ynl.py | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/tools/net/ynl/lib/ynl.py b/tools/net/ynl/lib/ynl.py index 13c4b019a881..b1da4aea9336 100644 --- a/tools/net/ynl/lib/ynl.py +++ b/tools/net/ynl/lib/ynl.py @@ -130,6 +130,13 @@ class NlAttr: format = self.get_format(attr_type, byte_order) return format.unpack(self.raw)[0] + def as_auto_scalar(self, attr_type, byte_order=None): + if len(self.raw) != 4 and len(self.raw) != 8: + raise Exception(f"Auto-scalar len payload be 4 or 8 bytes, got {len(self.raw)}") + real_type = attr_type[0] + str(len(self.raw) * 8) + format = self.get_format(real_type, byte_order) + return format.unpack(self.raw)[0] + def as_strz(self): return self.raw.decode('ascii')[:-1] @@ -463,9 +470,16 @@ class YnlFamily(SpecFamily): attr_payload = bytes.fromhex(value) else: raise Exception(f'Unknown type for binary attribute, value: {value}') + elif attr.is_auto_scalar: + scalar = int(value) + real_type = attr["type"][0] + ('32' if scalar.bit_length() <= 32 else '64') + format = NlAttr.get_format(real_type, attr.byte_order) + attr_payload = format.pack(int(value)) elif attr['type'] in NlAttr.type_formats: format = NlAttr.get_format(attr['type'], attr.byte_order) attr_payload = format.pack(int(value)) + elif attr['type'] in "bitfield32": + attr_payload = struct.pack("II", int(value["value"]), int(value["selector"])) else: raise Exception(f'Unknown type at {space} {name} {value} {attr["type"]}') @@ -474,7 +488,7 @@ class YnlFamily(SpecFamily): def _decode_enum(self, raw, attr_spec): enum = self.consts[attr_spec['enum']] - if 'enum-as-flags' in attr_spec and attr_spec['enum-as-flags']: + if enum.type == 'flags' or attr_spec.get('enum-as-flags', False): i = 0 value = set() while raw: @@ -529,16 +543,23 @@ class YnlFamily(SpecFamily): decoded = self._decode_binary(attr, attr_spec) elif attr_spec["type"] == 'flag': decoded = True + elif attr_spec.is_auto_scalar: + decoded = attr.as_auto_scalar(attr_spec['type'], attr_spec.byte_order) elif attr_spec["type"] in NlAttr.type_formats: decoded = attr.as_scalar(attr_spec['type'], attr_spec.byte_order) + if 'enum' in attr_spec: + decoded = self._decode_enum(decoded, attr_spec) elif attr_spec["type"] == 'array-nest': decoded = self._decode_array_nest(attr, attr_spec) + elif attr_spec["type"] == 'bitfield32': + value, selector = struct.unpack("II", attr.raw) + if 'enum' in attr_spec: + value = self._decode_enum(value, attr_spec) + selector = self._decode_enum(selector, attr_spec) + decoded = {"value": value, "selector": selector} else: raise Exception(f'Unknown {attr_spec["type"]} with name {attr_spec["name"]}') - if 'enum' in attr_spec: - decoded = self._decode_enum(decoded, attr_spec) - if not attr_spec.is_multi: rsp[attr_spec['name']] = decoded elif attr_spec.name in rsp: |