mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
tools: ynl: introduce option to process unknown attributes or types
In case the kernel sends message back containing attribute not defined
in family spec, following exception is raised to the user:
$ sudo ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/devlink.yaml --do trap-get --json '{"bus-name": "netdevsim", "dev-name": "netdevsim1", "trap-name": "source_mac_is_multicast"}'
Traceback (most recent call last):
File "/home/jiri/work/linux/tools/net/ynl/lib/ynl.py", line 521, in _decode
attr_spec = attr_space.attrs_by_val[attr.type]
~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^
KeyError: 132
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/jiri/work/linux/./tools/net/ynl/cli.py", line 61, in <module>
main()
File "/home/jiri/work/linux/./tools/net/ynl/cli.py", line 49, in main
reply = ynl.do(args.do, attrs, args.flags)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/jiri/work/linux/tools/net/ynl/lib/ynl.py", line 731, in do
return self._op(method, vals, flags)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/jiri/work/linux/tools/net/ynl/lib/ynl.py", line 719, in _op
rsp_msg = self._decode(decoded.raw_attrs, op.attr_set.name)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/jiri/work/linux/tools/net/ynl/lib/ynl.py", line 525, in _decode
raise Exception(f"Space '{space}' has no attribute with value '{attr.type}'")
Exception: Space 'devlink' has no attribute with value '132'
Introduce a command line option "process-unknown" and pass it down to
YnlFamily class constructor to allow user to process unknown
attributes and types and print them as binaries.
$ sudo ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/devlink.yaml --do trap-get --json '{"bus-name": "netdevsim", "dev-name": "netdevsim1", "trap-name": "source_mac_is_multicast"}' --process-unknown
{'UnknownAttr(129)': {'UnknownAttr(0)': b'\x00\x00\x00\x00\x00\x00\x00\x00',
'UnknownAttr(1)': b'\x00\x00\x00\x00\x00\x00\x00\x00',
'UnknownAttr(2)': b'\x0e\x00\x00\x00\x00\x00\x00\x00'},
'UnknownAttr(132)': b'\x00',
'UnknownAttr(133)': b'',
'UnknownAttr(134)': {'UnknownAttr(0)': b''},
'bus-name': 'netdevsim',
'dev-name': 'netdevsim1',
'trap-action': 'drop',
'trap-group-name': 'l2_drops',
'trap-name': 'source_mac_is_multicast'}
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
Link: https://lore.kernel.org/r/20231027092525.956172-1-jiri@resnulli.us
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
committed by
Jakub Kicinski
parent
ff672b9ffe
commit
d96e48a3d5
@@ -100,6 +100,7 @@ class NlAttr:
|
||||
def __init__(self, raw, offset):
|
||||
self._len, self._type = struct.unpack("HH", raw[offset:offset + 4])
|
||||
self.type = self._type & ~Netlink.NLA_TYPE_MASK
|
||||
self.is_nest = self._type & Netlink.NLA_F_NESTED
|
||||
self.payload_len = self._len
|
||||
self.full_len = (self.payload_len + 3) & ~3
|
||||
self.raw = raw[offset + 4:offset + self.payload_len]
|
||||
@@ -411,10 +412,11 @@ class GenlProtocol(NetlinkProtocol):
|
||||
|
||||
|
||||
class YnlFamily(SpecFamily):
|
||||
def __init__(self, def_path, schema=None):
|
||||
def __init__(self, def_path, schema=None, process_unknown=False):
|
||||
super().__init__(def_path, schema)
|
||||
|
||||
self.include_raw = False
|
||||
self.process_unknown = process_unknown
|
||||
|
||||
try:
|
||||
if self.proto == "netlink-raw":
|
||||
@@ -526,14 +528,41 @@ class YnlFamily(SpecFamily):
|
||||
decoded.append({ item.type: subattrs })
|
||||
return decoded
|
||||
|
||||
def _decode_unknown(self, attr):
|
||||
if attr.is_nest:
|
||||
return self._decode(NlAttrs(attr.raw), None)
|
||||
else:
|
||||
return attr.as_bin()
|
||||
|
||||
def _rsp_add(self, rsp, name, is_multi, decoded):
|
||||
if is_multi == None:
|
||||
if name in rsp and type(rsp[name]) is not list:
|
||||
rsp[name] = [rsp[name]]
|
||||
is_multi = True
|
||||
else:
|
||||
is_multi = False
|
||||
|
||||
if not is_multi:
|
||||
rsp[name] = decoded
|
||||
elif name in rsp:
|
||||
rsp[name].append(decoded)
|
||||
else:
|
||||
rsp[name] = [decoded]
|
||||
|
||||
def _decode(self, attrs, space):
|
||||
attr_space = self.attr_sets[space]
|
||||
if space:
|
||||
attr_space = self.attr_sets[space]
|
||||
rsp = dict()
|
||||
for attr in attrs:
|
||||
try:
|
||||
attr_spec = attr_space.attrs_by_val[attr.type]
|
||||
except KeyError:
|
||||
raise Exception(f"Space '{space}' has no attribute with value '{attr.type}'")
|
||||
except (KeyError, UnboundLocalError):
|
||||
if not self.process_unknown:
|
||||
raise Exception(f"Space '{space}' has no attribute with value '{attr.type}'")
|
||||
attr_name = f"UnknownAttr({attr.type})"
|
||||
self._rsp_add(rsp, attr_name, None, self._decode_unknown(attr))
|
||||
continue
|
||||
|
||||
if attr_spec["type"] == 'nest':
|
||||
subdict = self._decode(NlAttrs(attr.raw), attr_spec['nested-attributes'])
|
||||
decoded = subdict
|
||||
@@ -558,14 +587,11 @@ class YnlFamily(SpecFamily):
|
||||
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 not self.process_unknown:
|
||||
raise Exception(f'Unknown {attr_spec["type"]} with name {attr_spec["name"]}')
|
||||
decoded = self._decode_unknown(attr)
|
||||
|
||||
if not attr_spec.is_multi:
|
||||
rsp[attr_spec['name']] = decoded
|
||||
elif attr_spec.name in rsp:
|
||||
rsp[attr_spec.name].append(decoded)
|
||||
else:
|
||||
rsp[attr_spec.name] = [decoded]
|
||||
self._rsp_add(rsp, attr_spec["name"], attr_spec.is_multi, decoded)
|
||||
|
||||
return rsp
|
||||
|
||||
|
||||
Reference in New Issue
Block a user