2023-01-30 18:33:54 -08:00
#!/usr/bin/env python3
2023-03-06 12:04:57 -08:00
# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2023-01-20 09:50:41 -08:00
import argparse
import json
import pprint
import time
tools/net/ynl: Report netlink errors without stacktrace
ynl does not handle NlError exceptions so they get reported like program
failures. Handle the NlError exceptions and report the netlink errors
more cleanly.
Example now:
Netlink error: No such file or directory
nl_len = 44 (28) nl_flags = 0x300 nl_type = 2
error: -2 extack: {'bad-attr': '.op'}
Example before:
Traceback (most recent call last):
File "/home/donaldh/net-next/./tools/net/ynl/cli.py", line 81, in <module>
main()
File "/home/donaldh/net-next/./tools/net/ynl/cli.py", line 69, in main
reply = ynl.dump(args.dump, attrs)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/donaldh/net-next/tools/net/ynl/lib/ynl.py", line 906, in dump
return self._op(method, vals, [], dump=True)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/donaldh/net-next/tools/net/ynl/lib/ynl.py", line 872, in _op
raise NlError(nl_msg)
lib.ynl.NlError: Netlink error: No such file or directory
nl_len = 44 (28) nl_flags = 0x300 nl_type = 2
error: -2 extack: {'bad-attr': '.op'}
Signed-off-by: Donald Hunter <donald.hunter@gmail.com>
Link: https://lore.kernel.org/r/20240306231046.97158-3-donald.hunter@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-03-06 23:10:42 +00:00
from lib import YnlFamily , Netlink , NlError
2023-01-20 09:50:41 -08:00
2024-01-29 22:34:46 +00:00
class YnlEncoder ( json . JSONEncoder ) :
def default ( self , obj ) :
if isinstance ( obj , bytes ) :
return bytes . hex ( obj )
if isinstance ( obj , set ) :
return list ( obj )
return json . JSONEncoder . default ( self , obj )
2023-01-20 09:50:41 -08:00
def main ( ) :
parser = argparse . ArgumentParser ( description = ' YNL CLI sample ' )
parser . add_argument ( ' --spec ' , dest = ' spec ' , type = str , required = True )
parser . add_argument ( ' --schema ' , dest = ' schema ' , type = str )
2023-01-30 18:33:50 -08:00
parser . add_argument ( ' --no-schema ' , action = ' store_true ' )
2023-01-20 09:50:41 -08:00
parser . add_argument ( ' --json ' , dest = ' json_text ' , type = str )
parser . add_argument ( ' --do ' , dest = ' do ' , type = str )
parser . add_argument ( ' --dump ' , dest = ' dump ' , type = str )
parser . add_argument ( ' --sleep ' , dest = ' sleep ' , type = int )
parser . add_argument ( ' --subscribe ' , dest = ' ntf ' , type = str )
2023-08-25 13:27:52 +01:00
parser . add_argument ( ' --replace ' , dest = ' flags ' , action = ' append_const ' ,
const = Netlink . NLM_F_REPLACE )
parser . add_argument ( ' --excl ' , dest = ' flags ' , action = ' append_const ' ,
const = Netlink . NLM_F_EXCL )
parser . add_argument ( ' --create ' , dest = ' flags ' , action = ' append_const ' ,
const = Netlink . NLM_F_CREATE )
parser . add_argument ( ' --append ' , dest = ' flags ' , action = ' append_const ' ,
const = Netlink . NLM_F_APPEND )
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>
2023-10-27 11:25:25 +02:00
parser . add_argument ( ' --process-unknown ' , action = argparse . BooleanOptionalAction )
2024-01-29 22:34:46 +00:00
parser . add_argument ( ' --output-json ' , action = ' store_true ' )
2024-03-04 21:33:10 -08:00
parser . add_argument ( ' --dbg-small-recv ' , default = 0 , const = 4000 ,
action = ' store ' , nargs = ' ? ' , type = int )
2023-01-20 09:50:41 -08:00
args = parser . parse_args ( )
2024-01-29 22:34:46 +00:00
def output ( msg ) :
if args . output_json :
print ( json . dumps ( msg , cls = YnlEncoder ) )
else :
pprint . PrettyPrinter ( ) . pprint ( msg )
2023-01-30 18:33:50 -08:00
if args . no_schema :
args . schema = ' '
2023-01-20 09:50:41 -08:00
attrs = { }
if args . json_text :
attrs = json . loads ( args . json_text )
2024-03-04 21:33:10 -08:00
ynl = YnlFamily ( args . spec , args . schema , args . process_unknown ,
recv_size = args . dbg_small_recv )
if args . dbg_small_recv :
ynl . set_recv_dbg ( True )
2023-01-20 09:50:41 -08:00
if args . ntf :
ynl . ntf_subscribe ( args . ntf )
if args . sleep :
time . sleep ( args . sleep )
tools/net/ynl: Report netlink errors without stacktrace
ynl does not handle NlError exceptions so they get reported like program
failures. Handle the NlError exceptions and report the netlink errors
more cleanly.
Example now:
Netlink error: No such file or directory
nl_len = 44 (28) nl_flags = 0x300 nl_type = 2
error: -2 extack: {'bad-attr': '.op'}
Example before:
Traceback (most recent call last):
File "/home/donaldh/net-next/./tools/net/ynl/cli.py", line 81, in <module>
main()
File "/home/donaldh/net-next/./tools/net/ynl/cli.py", line 69, in main
reply = ynl.dump(args.dump, attrs)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/donaldh/net-next/tools/net/ynl/lib/ynl.py", line 906, in dump
return self._op(method, vals, [], dump=True)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/donaldh/net-next/tools/net/ynl/lib/ynl.py", line 872, in _op
raise NlError(nl_msg)
lib.ynl.NlError: Netlink error: No such file or directory
nl_len = 44 (28) nl_flags = 0x300 nl_type = 2
error: -2 extack: {'bad-attr': '.op'}
Signed-off-by: Donald Hunter <donald.hunter@gmail.com>
Link: https://lore.kernel.org/r/20240306231046.97158-3-donald.hunter@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-03-06 23:10:42 +00:00
try :
if args . do :
reply = ynl . do ( args . do , attrs , args . flags )
output ( reply )
if args . dump :
reply = ynl . dump ( args . dump , attrs )
output ( reply )
except NlError as e :
print ( e )
exit ( 1 )
2023-01-20 09:50:41 -08:00
if args . ntf :
ynl . check_ntf ( )
2024-01-29 22:34:46 +00:00
output ( ynl . async_msg_queue )
2023-01-20 09:50:41 -08:00
if __name__ == " __main__ " :
main ( )