forked from mirrors/linux
		
	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>
		
	
			
		
			
				
	
	
		
			86 lines
		
	
	
	
		
			2.7 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			86 lines
		
	
	
	
		
			2.7 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
#!/usr/bin/env python3
 | 
						|
# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
 | 
						|
 | 
						|
import argparse
 | 
						|
import json
 | 
						|
import pprint
 | 
						|
import time
 | 
						|
 | 
						|
from lib import YnlFamily, Netlink, NlError
 | 
						|
 | 
						|
 | 
						|
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)
 | 
						|
 | 
						|
 | 
						|
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)
 | 
						|
    parser.add_argument('--no-schema', action='store_true')
 | 
						|
    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)
 | 
						|
    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)
 | 
						|
    parser.add_argument('--process-unknown', action=argparse.BooleanOptionalAction)
 | 
						|
    parser.add_argument('--output-json', action='store_true')
 | 
						|
    parser.add_argument('--dbg-small-recv', default=0, const=4000,
 | 
						|
                        action='store', nargs='?', type=int)
 | 
						|
    args = parser.parse_args()
 | 
						|
 | 
						|
    def output(msg):
 | 
						|
        if args.output_json:
 | 
						|
            print(json.dumps(msg, cls=YnlEncoder))
 | 
						|
        else:
 | 
						|
            pprint.PrettyPrinter().pprint(msg)
 | 
						|
 | 
						|
    if args.no_schema:
 | 
						|
        args.schema = ''
 | 
						|
 | 
						|
    attrs = {}
 | 
						|
    if args.json_text:
 | 
						|
        attrs = json.loads(args.json_text)
 | 
						|
 | 
						|
    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)
 | 
						|
 | 
						|
    if args.ntf:
 | 
						|
        ynl.ntf_subscribe(args.ntf)
 | 
						|
 | 
						|
    if args.sleep:
 | 
						|
        time.sleep(args.sleep)
 | 
						|
 | 
						|
    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)
 | 
						|
 | 
						|
    if args.ntf:
 | 
						|
        ynl.check_ntf()
 | 
						|
        output(ynl.async_msg_queue)
 | 
						|
 | 
						|
 | 
						|
if __name__ == "__main__":
 | 
						|
    main()
 |