[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20231016110222.465453-1-jiri@resnulli.us>
Date: Mon, 16 Oct 2023 13:02:22 +0200
From: Jiri Pirko <jiri@...nulli.us>
To: netdev@...r.kernel.org
Cc: kuba@...nel.org,
pabeni@...hat.com,
davem@...emloft.net,
edumazet@...gle.com
Subject: [patch net-next v2] tools: ynl: introduce option to process unknown attributes or types
From: Jiri Pirko <jiri@...dia.com>
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
{'129': {'0': b'\x00\x00\x00\x00\x00\x00\x00\x00',
'1': b'\x00\x00\x00\x00\x00\x00\x00\x00',
'2': b'(\x00\x00\x00\x00\x00\x00\x00'},
'132': b'\x00',
'133': b'',
'134': {'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@...dia.com>
---
v1->v2:
- changed to process unknown attributes and type instead of ignoring them
---
tools/net/ynl/cli.py | 3 ++-
tools/net/ynl/lib/ynl.py | 32 +++++++++++++++++++++++++++-----
2 files changed, 29 insertions(+), 6 deletions(-)
diff --git a/tools/net/ynl/cli.py b/tools/net/ynl/cli.py
index 564ecf07cd2c..2ad9ec0f5545 100755
--- a/tools/net/ynl/cli.py
+++ b/tools/net/ynl/cli.py
@@ -27,6 +27,7 @@ def main():
const=Netlink.NLM_F_CREATE)
parser.add_argument('--append', dest='flags', action='append_const',
const=Netlink.NLM_F_APPEND)
+ parser.add_argument('--process-unknown', action=argparse.BooleanOptionalAction)
args = parser.parse_args()
if args.no_schema:
@@ -36,7 +37,7 @@ def main():
if args.json_text:
attrs = json.loads(args.json_text)
- ynl = YnlFamily(args.spec, args.schema)
+ ynl = YnlFamily(args.spec, args.schema, args.process_unknown)
if args.ntf:
ynl.ntf_subscribe(args.ntf)
diff --git a/tools/net/ynl/lib/ynl.py b/tools/net/ynl/lib/ynl.py
index 13c4b019a881..fe63e66694bb 100644
--- a/tools/net/ynl/lib/ynl.py
+++ b/tools/net/ynl/lib/ynl.py
@@ -403,11 +403,24 @@ class GenlProtocol(NetlinkProtocol):
#
+class FakeSpecAttr:
+ def __init__(self, name):
+ self.dict = {"name": name, "type": None}
+ self.is_multi = False
+
+ def __getitem__(self, key):
+ return self.dict[key]
+
+ def __contains__(self, key):
+ return key in self.dict
+
+
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":
@@ -513,13 +526,16 @@ class YnlFamily(SpecFamily):
return 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_spec = FakeSpecAttr(str(attr.type))
if attr_spec["type"] == 'nest':
subdict = self._decode(NlAttrs(attr.raw), attr_spec['nested-attributes'])
decoded = subdict
@@ -534,7 +550,13 @@ class YnlFamily(SpecFamily):
elif attr_spec["type"] == 'array-nest':
decoded = self._decode_array_nest(attr, attr_spec)
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"]}')
+ if attr._type & Netlink.NLA_F_NESTED:
+ subdict = self._decode(NlAttrs(attr.raw), None)
+ decoded = subdict
+ else:
+ decoded = attr.as_bin()
if 'enum' in attr_spec:
decoded = self._decode_enum(decoded, attr_spec)
--
2.41.0
Powered by blists - more mailing lists