Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tools: ynl-gen: fix parse multi-attr enum attribute

When attribute is enum type and marked as multi-attr, the netlink
respond is not parsed, fails with stack trace:
Traceback (most recent call last):
File "/net-next/tools/net/ynl/./test.py", line 520, in <module>
main()
File "/net-next/tools/net/ynl/./test.py", line 488, in main
dplls=dplls_get(282574471561216)
File "/net-next/tools/net/ynl/./test.py", line 48, in dplls_get
reply=act(args)
File "/net-next/tools/net/ynl/./test.py", line 41, in act
reply = ynl.dump(args.dump, attrs)
File "/net-next/tools/net/ynl/lib/ynl.py", line 598, in dump
return self._op(method, vals, dump=True)
File "/net-next/tools/net/ynl/lib/ynl.py", line 584, in _op
rsp_msg = self._decode(gm.raw_attrs, op.attr_set.name)
File "/net-next/tools/net/ynl/lib/ynl.py", line 451, in _decode
self._decode_enum(rsp, attr_spec)
File "/net-next/tools/net/ynl/lib/ynl.py", line 408, in _decode_enum
value = enum.entries_by_val[raw].name
TypeError: unhashable type: 'list'
error: 1

Redesign _decode_enum(..) to take a enum int value and translate
it to either a bitmask or enum name as expected.

Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
Reviewed-by: Donald Hunter <donald.hunter@gmail.com>
Link: https://lore.kernel.org/r/20230725101642.267248-3-arkadiusz.kubalewski@intel.com
Reviewed-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Arkadiusz Kubalewski and committed by
Jakub Kicinski
df15c15e d7ddf5f4

+6 -6
+6 -6
tools/net/ynl/lib/ynl.py
··· 417 417 pad = b'\x00' * ((4 - len(attr_payload) % 4) % 4) 418 418 return struct.pack('HH', len(attr_payload) + 4, nl_type) + attr_payload + pad 419 419 420 - def _decode_enum(self, rsp, attr_spec): 421 - raw = rsp[attr_spec['name']] 420 + def _decode_enum(self, raw, attr_spec): 422 421 enum = self.consts[attr_spec['enum']] 423 422 if 'enum-as-flags' in attr_spec and attr_spec['enum-as-flags']: 424 423 i = 0 ··· 429 430 i += 1 430 431 else: 431 432 value = enum.entries_by_val[raw].name 432 - rsp[attr_spec['name']] = value 433 + return value 433 434 434 435 def _decode_binary(self, attr, attr_spec): 435 436 if attr_spec.struct_name: ··· 437 438 decoded = attr.as_struct(members) 438 439 for m in members: 439 440 if m.enum: 440 - self._decode_enum(decoded, m) 441 + decoded[m.name] = self._decode_enum(decoded[m.name], m) 441 442 elif attr_spec.sub_type: 442 443 decoded = attr.as_c_array(attr_spec.sub_type) 443 444 else: ··· 465 466 else: 466 467 raise Exception(f'Unknown {attr_spec["type"]} with name {attr_spec["name"]}') 467 468 469 + if 'enum' in attr_spec: 470 + decoded = self._decode_enum(decoded, attr_spec) 471 + 468 472 if not attr_spec.is_multi: 469 473 rsp[attr_spec['name']] = decoded 470 474 elif attr_spec.name in rsp: ··· 475 473 else: 476 474 rsp[attr_spec.name] = [decoded] 477 475 478 - if 'enum' in attr_spec: 479 - self._decode_enum(rsp, attr_spec) 480 476 return rsp 481 477 482 478 def _decode_extack_path(self, attrs, attr_set, offset, target):