122ef8a26SHangbin Liu#!/usr/bin/env python3 222ef8a26SHangbin Liu# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 322ef8a26SHangbin Liu# 422ef8a26SHangbin Liu# pylint: disable=too-many-locals, too-many-branches, too-many-statements 522ef8a26SHangbin Liu# pylint: disable=too-many-return-statements 622ef8a26SHangbin Liu 722ef8a26SHangbin Liu""" YNL ethtool utility """ 822ef8a26SHangbin Liu 922ef8a26SHangbin Liuimport argparse 1022ef8a26SHangbin Liuimport pathlib 1122ef8a26SHangbin Liuimport pprint 1222ef8a26SHangbin Liuimport sys 1322ef8a26SHangbin Liuimport re 1422ef8a26SHangbin Liuimport os 1522ef8a26SHangbin Liu 1622ef8a26SHangbin Liu# pylint: disable=no-name-in-module,wrong-import-position 1722ef8a26SHangbin Liusys.path.append(pathlib.Path(__file__).resolve().parent.parent.joinpath('pyynl').as_posix()) 1822ef8a26SHangbin Liu# pylint: disable=import-error 1922ef8a26SHangbin Liufrom cli import schema_dir, spec_dir 2022ef8a26SHangbin Liufrom lib import YnlFamily 2122ef8a26SHangbin Liu 2222ef8a26SHangbin Liu 2322ef8a26SHangbin Liudef args_to_req(ynl, op_name, args, req): 2422ef8a26SHangbin Liu """ 2522ef8a26SHangbin Liu Verify and convert command-line arguments to the ynl-compatible request. 2622ef8a26SHangbin Liu """ 2722ef8a26SHangbin Liu valid_attrs = ynl.operation_do_attributes(op_name) 2822ef8a26SHangbin Liu valid_attrs.remove('header') # not user-provided 2922ef8a26SHangbin Liu 3022ef8a26SHangbin Liu if len(args) == 0: 3122ef8a26SHangbin Liu print(f'no attributes, expected: {valid_attrs}') 3222ef8a26SHangbin Liu sys.exit(1) 3322ef8a26SHangbin Liu 3422ef8a26SHangbin Liu i = 0 3522ef8a26SHangbin Liu while i < len(args): 3622ef8a26SHangbin Liu attr = args[i] 3722ef8a26SHangbin Liu if i + 1 >= len(args): 3822ef8a26SHangbin Liu print(f'expected value for \'{attr}\'') 3922ef8a26SHangbin Liu sys.exit(1) 4022ef8a26SHangbin Liu 4122ef8a26SHangbin Liu if attr not in valid_attrs: 4222ef8a26SHangbin Liu print(f'invalid attribute \'{attr}\', expected: {valid_attrs}') 4322ef8a26SHangbin Liu sys.exit(1) 4422ef8a26SHangbin Liu 4522ef8a26SHangbin Liu val = args[i+1] 4622ef8a26SHangbin Liu i += 2 4722ef8a26SHangbin Liu 4822ef8a26SHangbin Liu req[attr] = val 4922ef8a26SHangbin Liu 5022ef8a26SHangbin Liudef print_field(reply, *desc): 5122ef8a26SHangbin Liu """ 5222ef8a26SHangbin Liu Pretty-print a set of fields from the reply. desc specifies the 5322ef8a26SHangbin Liu fields and the optional type (bool/yn). 5422ef8a26SHangbin Liu """ 5522ef8a26SHangbin Liu if not reply: 5622ef8a26SHangbin Liu return 5722ef8a26SHangbin Liu 5822ef8a26SHangbin Liu if len(desc) == 0: 5922ef8a26SHangbin Liu print_field(reply, *zip(reply.keys(), reply.keys())) 6022ef8a26SHangbin Liu return 6122ef8a26SHangbin Liu 6222ef8a26SHangbin Liu for spec in desc: 6322ef8a26SHangbin Liu try: 6422ef8a26SHangbin Liu field, name, tp = spec 6522ef8a26SHangbin Liu except ValueError: 6622ef8a26SHangbin Liu field, name = spec 6722ef8a26SHangbin Liu tp = 'int' 6822ef8a26SHangbin Liu 6922ef8a26SHangbin Liu value = reply.get(field, None) 7022ef8a26SHangbin Liu if tp == 'yn': 7122ef8a26SHangbin Liu value = 'yes' if value else 'no' 7222ef8a26SHangbin Liu elif tp == 'bool' or isinstance(value, bool): 7322ef8a26SHangbin Liu value = 'on' if value else 'off' 7422ef8a26SHangbin Liu else: 7522ef8a26SHangbin Liu value = 'n/a' if value is None else value 7622ef8a26SHangbin Liu 7722ef8a26SHangbin Liu print(f'{name}: {value}') 7822ef8a26SHangbin Liu 7922ef8a26SHangbin Liudef print_speed(name, value): 8022ef8a26SHangbin Liu """ 8122ef8a26SHangbin Liu Print out the speed-like strings from the value dict. 8222ef8a26SHangbin Liu """ 8322ef8a26SHangbin Liu speed_re = re.compile(r'[0-9]+base[^/]+/.+') 8422ef8a26SHangbin Liu speed = [ k for k, v in value.items() if v and speed_re.match(k) ] 8522ef8a26SHangbin Liu print(f'{name}: {" ".join(speed)}') 8622ef8a26SHangbin Liu 871c43d471SHangbin Liudef do_set(ynl, args, op_name): 8822ef8a26SHangbin Liu """ 891c43d471SHangbin Liu Prepare request header, parse arguments and do a set operation. 9022ef8a26SHangbin Liu """ 9122ef8a26SHangbin Liu req = { 9222ef8a26SHangbin Liu 'header': { 9322ef8a26SHangbin Liu 'dev-name': args.device, 9422ef8a26SHangbin Liu }, 9522ef8a26SHangbin Liu } 9622ef8a26SHangbin Liu 9722ef8a26SHangbin Liu args_to_req(ynl, op_name, args.args, req) 9822ef8a26SHangbin Liu ynl.do(op_name, req) 9922ef8a26SHangbin Liu 1001c43d471SHangbin Liudef do_get(ynl, args, op_name, extra=None): 10122ef8a26SHangbin Liu """ 1021c43d471SHangbin Liu Prepare request header and get info for a specific device using doit. 10322ef8a26SHangbin Liu """ 10422ef8a26SHangbin Liu extra = extra or {} 1051c43d471SHangbin Liu req = {'header': {'dev-name': args.device}} 1061c43d471SHangbin Liu req['header'].update(extra.pop('header', {})) 1071c43d471SHangbin Liu req.update(extra) 1081c43d471SHangbin Liu 1091c43d471SHangbin Liu reply = ynl.do(op_name, req) 11022ef8a26SHangbin Liu if not reply: 11122ef8a26SHangbin Liu return {} 11222ef8a26SHangbin Liu 11322ef8a26SHangbin Liu if args.json: 1141c43d471SHangbin Liu pprint.PrettyPrinter().pprint(reply) 11522ef8a26SHangbin Liu sys.exit(0) 1161c43d471SHangbin Liu reply.pop('header', None) 1171c43d471SHangbin Liu return reply 11822ef8a26SHangbin Liu 11922ef8a26SHangbin Liudef bits_to_dict(attr): 12022ef8a26SHangbin Liu """ 12122ef8a26SHangbin Liu Convert ynl-formatted bitmask to a dict of bit=value. 12222ef8a26SHangbin Liu """ 12322ef8a26SHangbin Liu ret = {} 12422ef8a26SHangbin Liu if 'bits' not in attr: 12522ef8a26SHangbin Liu return {} 12622ef8a26SHangbin Liu if 'bit' not in attr['bits']: 12722ef8a26SHangbin Liu return {} 12822ef8a26SHangbin Liu for bit in attr['bits']['bit']: 12922ef8a26SHangbin Liu if bit['name'] == '': 13022ef8a26SHangbin Liu continue 13122ef8a26SHangbin Liu name = bit['name'] 13222ef8a26SHangbin Liu value = bit.get('value', False) 13322ef8a26SHangbin Liu ret[name] = value 13422ef8a26SHangbin Liu return ret 13522ef8a26SHangbin Liu 13622ef8a26SHangbin Liudef main(): 13722ef8a26SHangbin Liu """ YNL ethtool utility """ 13822ef8a26SHangbin Liu 13922ef8a26SHangbin Liu parser = argparse.ArgumentParser(description='ethtool wannabe') 14022ef8a26SHangbin Liu parser.add_argument('--json', action=argparse.BooleanOptionalAction) 14122ef8a26SHangbin Liu parser.add_argument('--show-priv-flags', action=argparse.BooleanOptionalAction) 14222ef8a26SHangbin Liu parser.add_argument('--set-priv-flags', action=argparse.BooleanOptionalAction) 14322ef8a26SHangbin Liu parser.add_argument('--show-eee', action=argparse.BooleanOptionalAction) 14422ef8a26SHangbin Liu parser.add_argument('--set-eee', action=argparse.BooleanOptionalAction) 14522ef8a26SHangbin Liu parser.add_argument('-a', '--show-pause', action=argparse.BooleanOptionalAction) 14622ef8a26SHangbin Liu parser.add_argument('-A', '--set-pause', action=argparse.BooleanOptionalAction) 14722ef8a26SHangbin Liu parser.add_argument('-c', '--show-coalesce', action=argparse.BooleanOptionalAction) 14822ef8a26SHangbin Liu parser.add_argument('-C', '--set-coalesce', action=argparse.BooleanOptionalAction) 14922ef8a26SHangbin Liu parser.add_argument('-g', '--show-ring', action=argparse.BooleanOptionalAction) 15022ef8a26SHangbin Liu parser.add_argument('-G', '--set-ring', action=argparse.BooleanOptionalAction) 15122ef8a26SHangbin Liu parser.add_argument('-k', '--show-features', action=argparse.BooleanOptionalAction) 15222ef8a26SHangbin Liu parser.add_argument('-K', '--set-features', action=argparse.BooleanOptionalAction) 15322ef8a26SHangbin Liu parser.add_argument('-l', '--show-channels', action=argparse.BooleanOptionalAction) 15422ef8a26SHangbin Liu parser.add_argument('-L', '--set-channels', action=argparse.BooleanOptionalAction) 15522ef8a26SHangbin Liu parser.add_argument('-T', '--show-time-stamping', action=argparse.BooleanOptionalAction) 15622ef8a26SHangbin Liu parser.add_argument('-S', '--statistics', action=argparse.BooleanOptionalAction) 15722ef8a26SHangbin Liu # TODO: --show-tunnels tunnel-info-get 15822ef8a26SHangbin Liu # TODO: --show-module module-get 15922ef8a26SHangbin Liu # TODO: --get-plca-cfg plca-get 16022ef8a26SHangbin Liu # TODO: --get-plca-status plca-get-status 16122ef8a26SHangbin Liu # TODO: --show-mm mm-get 16222ef8a26SHangbin Liu # TODO: --show-fec fec-get 16322ef8a26SHangbin Liu # TODO: --dump-module-eerpom module-eeprom-get 16422ef8a26SHangbin Liu # TODO: pse-get 16522ef8a26SHangbin Liu # TODO: rss-get 16622ef8a26SHangbin Liu parser.add_argument('device', metavar='device', type=str) 16722ef8a26SHangbin Liu parser.add_argument('args', metavar='args', type=str, nargs='*') 16822ef8a26SHangbin Liu 169*594ba447SHangbin Liu dbg_group = parser.add_argument_group('Debug options') 170*594ba447SHangbin Liu dbg_group.add_argument('--dbg-small-recv', default=0, const=4000, 171*594ba447SHangbin Liu action='store', nargs='?', type=int, metavar='INT', 172*594ba447SHangbin Liu help="Length of buffers used for recv()") 173*594ba447SHangbin Liu 17422ef8a26SHangbin Liu args = parser.parse_args() 17522ef8a26SHangbin Liu 17622ef8a26SHangbin Liu spec = os.path.join(spec_dir(), 'ethtool.yaml') 17722ef8a26SHangbin Liu schema = os.path.join(schema_dir(), 'genetlink-legacy.yaml') 17822ef8a26SHangbin Liu 179*594ba447SHangbin Liu ynl = YnlFamily(spec, schema, recv_size=args.dbg_small_recv) 180*594ba447SHangbin Liu if args.dbg_small_recv: 181*594ba447SHangbin Liu ynl.set_recv_dbg(True) 18222ef8a26SHangbin Liu 18322ef8a26SHangbin Liu if args.set_priv_flags: 18422ef8a26SHangbin Liu # TODO: parse the bitmask 18522ef8a26SHangbin Liu print("not implemented") 18622ef8a26SHangbin Liu return 18722ef8a26SHangbin Liu 18822ef8a26SHangbin Liu if args.set_eee: 1891c43d471SHangbin Liu do_set(ynl, args, 'eee-set') 19022ef8a26SHangbin Liu return 19122ef8a26SHangbin Liu 19222ef8a26SHangbin Liu if args.set_pause: 1931c43d471SHangbin Liu do_set(ynl, args, 'pause-set') 19422ef8a26SHangbin Liu return 19522ef8a26SHangbin Liu 19622ef8a26SHangbin Liu if args.set_coalesce: 1971c43d471SHangbin Liu do_set(ynl, args, 'coalesce-set') 19822ef8a26SHangbin Liu return 19922ef8a26SHangbin Liu 20022ef8a26SHangbin Liu if args.set_features: 20122ef8a26SHangbin Liu # TODO: parse the bitmask 20222ef8a26SHangbin Liu print("not implemented") 20322ef8a26SHangbin Liu return 20422ef8a26SHangbin Liu 20522ef8a26SHangbin Liu if args.set_channels: 2061c43d471SHangbin Liu do_set(ynl, args, 'channels-set') 20722ef8a26SHangbin Liu return 20822ef8a26SHangbin Liu 20922ef8a26SHangbin Liu if args.set_ring: 2101c43d471SHangbin Liu do_set(ynl, args, 'rings-set') 21122ef8a26SHangbin Liu return 21222ef8a26SHangbin Liu 21322ef8a26SHangbin Liu if args.show_priv_flags: 2141c43d471SHangbin Liu flags = bits_to_dict(do_get(ynl, args, 'privflags-get')['flags']) 21522ef8a26SHangbin Liu print_field(flags) 21622ef8a26SHangbin Liu return 21722ef8a26SHangbin Liu 21822ef8a26SHangbin Liu if args.show_eee: 2191c43d471SHangbin Liu eee = do_get(ynl, args, 'eee-get') 22022ef8a26SHangbin Liu ours = bits_to_dict(eee['modes-ours']) 22122ef8a26SHangbin Liu peer = bits_to_dict(eee['modes-peer']) 22222ef8a26SHangbin Liu 22322ef8a26SHangbin Liu if 'enabled' in eee: 22422ef8a26SHangbin Liu status = 'enabled' if eee['enabled'] else 'disabled' 22522ef8a26SHangbin Liu if 'active' in eee and eee['active']: 22622ef8a26SHangbin Liu status = status + ' - active' 22722ef8a26SHangbin Liu else: 22822ef8a26SHangbin Liu status = status + ' - inactive' 22922ef8a26SHangbin Liu else: 23022ef8a26SHangbin Liu status = 'not supported' 23122ef8a26SHangbin Liu 23222ef8a26SHangbin Liu print(f'EEE status: {status}') 23322ef8a26SHangbin Liu print_field(eee, ('tx-lpi-timer', 'Tx LPI')) 23422ef8a26SHangbin Liu print_speed('Advertised EEE link modes', ours) 23522ef8a26SHangbin Liu print_speed('Link partner advertised EEE link modes', peer) 23622ef8a26SHangbin Liu 23722ef8a26SHangbin Liu return 23822ef8a26SHangbin Liu 23922ef8a26SHangbin Liu if args.show_pause: 2401c43d471SHangbin Liu print_field(do_get(ynl, args, 'pause-get'), 24122ef8a26SHangbin Liu ('autoneg', 'Autonegotiate', 'bool'), 24222ef8a26SHangbin Liu ('rx', 'RX', 'bool'), 24322ef8a26SHangbin Liu ('tx', 'TX', 'bool')) 24422ef8a26SHangbin Liu return 24522ef8a26SHangbin Liu 24622ef8a26SHangbin Liu if args.show_coalesce: 2471c43d471SHangbin Liu print_field(do_get(ynl, args, 'coalesce-get')) 24822ef8a26SHangbin Liu return 24922ef8a26SHangbin Liu 25022ef8a26SHangbin Liu if args.show_features: 2511c43d471SHangbin Liu reply = do_get(ynl, args, 'features-get') 25222ef8a26SHangbin Liu available = bits_to_dict(reply['hw']) 25322ef8a26SHangbin Liu requested = bits_to_dict(reply['wanted']).keys() 25422ef8a26SHangbin Liu active = bits_to_dict(reply['active']).keys() 25522ef8a26SHangbin Liu never_changed = bits_to_dict(reply['nochange']).keys() 25622ef8a26SHangbin Liu 25722ef8a26SHangbin Liu for f in sorted(available): 25822ef8a26SHangbin Liu value = "off" 25922ef8a26SHangbin Liu if f in active: 26022ef8a26SHangbin Liu value = "on" 26122ef8a26SHangbin Liu 26222ef8a26SHangbin Liu fixed = "" 26322ef8a26SHangbin Liu if f not in available or f in never_changed: 26422ef8a26SHangbin Liu fixed = " [fixed]" 26522ef8a26SHangbin Liu 26622ef8a26SHangbin Liu req = "" 26722ef8a26SHangbin Liu if f in requested: 26822ef8a26SHangbin Liu if f in active: 26922ef8a26SHangbin Liu req = " [requested on]" 27022ef8a26SHangbin Liu else: 27122ef8a26SHangbin Liu req = " [requested off]" 27222ef8a26SHangbin Liu 27322ef8a26SHangbin Liu print(f'{f}: {value}{fixed}{req}') 27422ef8a26SHangbin Liu 27522ef8a26SHangbin Liu return 27622ef8a26SHangbin Liu 27722ef8a26SHangbin Liu if args.show_channels: 2781c43d471SHangbin Liu reply = do_get(ynl, args, 'channels-get') 27922ef8a26SHangbin Liu print(f'Channel parameters for {args.device}:') 28022ef8a26SHangbin Liu 28122ef8a26SHangbin Liu print('Pre-set maximums:') 28222ef8a26SHangbin Liu print_field(reply, 28322ef8a26SHangbin Liu ('rx-max', 'RX'), 28422ef8a26SHangbin Liu ('tx-max', 'TX'), 28522ef8a26SHangbin Liu ('other-max', 'Other'), 28622ef8a26SHangbin Liu ('combined-max', 'Combined')) 28722ef8a26SHangbin Liu 28822ef8a26SHangbin Liu print('Current hardware settings:') 28922ef8a26SHangbin Liu print_field(reply, 29022ef8a26SHangbin Liu ('rx-count', 'RX'), 29122ef8a26SHangbin Liu ('tx-count', 'TX'), 29222ef8a26SHangbin Liu ('other-count', 'Other'), 29322ef8a26SHangbin Liu ('combined-count', 'Combined')) 29422ef8a26SHangbin Liu 29522ef8a26SHangbin Liu return 29622ef8a26SHangbin Liu 29722ef8a26SHangbin Liu if args.show_ring: 2981c43d471SHangbin Liu reply = do_get(ynl, args, 'channels-get') 29922ef8a26SHangbin Liu 30022ef8a26SHangbin Liu print(f'Ring parameters for {args.device}:') 30122ef8a26SHangbin Liu 30222ef8a26SHangbin Liu print('Pre-set maximums:') 30322ef8a26SHangbin Liu print_field(reply, 30422ef8a26SHangbin Liu ('rx-max', 'RX'), 30522ef8a26SHangbin Liu ('rx-mini-max', 'RX Mini'), 30622ef8a26SHangbin Liu ('rx-jumbo-max', 'RX Jumbo'), 30722ef8a26SHangbin Liu ('tx-max', 'TX')) 30822ef8a26SHangbin Liu 30922ef8a26SHangbin Liu print('Current hardware settings:') 31022ef8a26SHangbin Liu print_field(reply, 31122ef8a26SHangbin Liu ('rx', 'RX'), 31222ef8a26SHangbin Liu ('rx-mini', 'RX Mini'), 31322ef8a26SHangbin Liu ('rx-jumbo', 'RX Jumbo'), 31422ef8a26SHangbin Liu ('tx', 'TX')) 31522ef8a26SHangbin Liu 31622ef8a26SHangbin Liu print_field(reply, 31722ef8a26SHangbin Liu ('rx-buf-len', 'RX Buf Len'), 31822ef8a26SHangbin Liu ('cqe-size', 'CQE Size'), 31922ef8a26SHangbin Liu ('tx-push', 'TX Push', 'bool')) 32022ef8a26SHangbin Liu 32122ef8a26SHangbin Liu return 32222ef8a26SHangbin Liu 32322ef8a26SHangbin Liu if args.statistics: 32422ef8a26SHangbin Liu print('NIC statistics:') 32522ef8a26SHangbin Liu 32622ef8a26SHangbin Liu # TODO: pass id? 3271c43d471SHangbin Liu strset = do_get(ynl, args, 'strset-get') 32822ef8a26SHangbin Liu pprint.PrettyPrinter().pprint(strset) 32922ef8a26SHangbin Liu 33022ef8a26SHangbin Liu req = { 33122ef8a26SHangbin Liu 'groups': { 33222ef8a26SHangbin Liu 'size': 1, 33322ef8a26SHangbin Liu 'bits': { 33422ef8a26SHangbin Liu 'bit': 33522ef8a26SHangbin Liu # TODO: support passing the bitmask 33622ef8a26SHangbin Liu #[ 33722ef8a26SHangbin Liu #{ 'name': 'eth-phy', 'value': True }, 33822ef8a26SHangbin Liu { 'name': 'eth-mac', 'value': True }, 33922ef8a26SHangbin Liu #{ 'name': 'eth-ctrl', 'value': True }, 34022ef8a26SHangbin Liu #{ 'name': 'rmon', 'value': True }, 34122ef8a26SHangbin Liu #], 34222ef8a26SHangbin Liu }, 34322ef8a26SHangbin Liu }, 34422ef8a26SHangbin Liu } 34522ef8a26SHangbin Liu 3461c43d471SHangbin Liu rsp = do_get(ynl, args, 'stats-get', req) 34722ef8a26SHangbin Liu pprint.PrettyPrinter().pprint(rsp) 34822ef8a26SHangbin Liu return 34922ef8a26SHangbin Liu 35022ef8a26SHangbin Liu if args.show_time_stamping: 35122ef8a26SHangbin Liu req = { 35222ef8a26SHangbin Liu 'header': { 35322ef8a26SHangbin Liu 'flags': 'stats', 35422ef8a26SHangbin Liu }, 35522ef8a26SHangbin Liu } 35622ef8a26SHangbin Liu 3571c43d471SHangbin Liu tsinfo = do_get(ynl, args, 'tsinfo-get', req) 35822ef8a26SHangbin Liu 35922ef8a26SHangbin Liu print(f'Time stamping parameters for {args.device}:') 36022ef8a26SHangbin Liu 36122ef8a26SHangbin Liu print('Capabilities:') 36222ef8a26SHangbin Liu _ = [print(f'\t{v}') for v in bits_to_dict(tsinfo['timestamping'])] 36322ef8a26SHangbin Liu 36422ef8a26SHangbin Liu print(f'PTP Hardware Clock: {tsinfo.get("phc-index", "none")}') 36522ef8a26SHangbin Liu 36622ef8a26SHangbin Liu if 'tx-types' in tsinfo: 36722ef8a26SHangbin Liu print('Hardware Transmit Timestamp Modes:') 36822ef8a26SHangbin Liu _ = [print(f'\t{v}') for v in bits_to_dict(tsinfo['tx-types'])] 36922ef8a26SHangbin Liu else: 37022ef8a26SHangbin Liu print('Hardware Transmit Timestamp Modes: none') 37122ef8a26SHangbin Liu 37222ef8a26SHangbin Liu if 'rx-filters' in tsinfo: 37322ef8a26SHangbin Liu print('Hardware Receive Filter Modes:') 37422ef8a26SHangbin Liu _ = [print(f'\t{v}') for v in bits_to_dict(tsinfo['rx-filters'])] 37522ef8a26SHangbin Liu else: 37622ef8a26SHangbin Liu print('Hardware Receive Filter Modes: none') 37722ef8a26SHangbin Liu 37822ef8a26SHangbin Liu if 'stats' in tsinfo and tsinfo['stats']: 37922ef8a26SHangbin Liu print('Statistics:') 38022ef8a26SHangbin Liu _ = [print(f'\t{k}: {v}') for k, v in tsinfo['stats'].items()] 38122ef8a26SHangbin Liu 38222ef8a26SHangbin Liu return 38322ef8a26SHangbin Liu 38422ef8a26SHangbin Liu print(f'Settings for {args.device}:') 3851c43d471SHangbin Liu linkmodes = do_get(ynl, args, 'linkmodes-get') 38622ef8a26SHangbin Liu ours = bits_to_dict(linkmodes['ours']) 38722ef8a26SHangbin Liu 38822ef8a26SHangbin Liu supported_ports = ('TP', 'AUI', 'BNC', 'MII', 'FIBRE', 'Backplane') 38922ef8a26SHangbin Liu ports = [ p for p in supported_ports if ours.get(p, False)] 39022ef8a26SHangbin Liu print(f'Supported ports: [ {" ".join(ports)} ]') 39122ef8a26SHangbin Liu 39222ef8a26SHangbin Liu print_speed('Supported link modes', ours) 39322ef8a26SHangbin Liu 39422ef8a26SHangbin Liu print_field(ours, ('Pause', 'Supported pause frame use', 'yn')) 39522ef8a26SHangbin Liu print_field(ours, ('Autoneg', 'Supports auto-negotiation', 'yn')) 39622ef8a26SHangbin Liu 39722ef8a26SHangbin Liu supported_fec = ('None', 'PS', 'BASER', 'LLRS') 39822ef8a26SHangbin Liu fec = [ p for p in supported_fec if ours.get(p, False)] 39922ef8a26SHangbin Liu fec_str = " ".join(fec) 40022ef8a26SHangbin Liu if len(fec) == 0: 40122ef8a26SHangbin Liu fec_str = "Not reported" 40222ef8a26SHangbin Liu 40322ef8a26SHangbin Liu print(f'Supported FEC modes: {fec_str}') 40422ef8a26SHangbin Liu 40522ef8a26SHangbin Liu speed = 'Unknown!' 40622ef8a26SHangbin Liu if linkmodes['speed'] > 0 and linkmodes['speed'] < 0xffffffff: 40722ef8a26SHangbin Liu speed = f'{linkmodes["speed"]}Mb/s' 40822ef8a26SHangbin Liu print(f'Speed: {speed}') 40922ef8a26SHangbin Liu 41022ef8a26SHangbin Liu duplex_modes = { 41122ef8a26SHangbin Liu 0: 'Half', 41222ef8a26SHangbin Liu 1: 'Full', 41322ef8a26SHangbin Liu } 41422ef8a26SHangbin Liu duplex = duplex_modes.get(linkmodes["duplex"], None) 41522ef8a26SHangbin Liu if not duplex: 41622ef8a26SHangbin Liu duplex = f'Unknown! ({linkmodes["duplex"]})' 41722ef8a26SHangbin Liu print(f'Duplex: {duplex}') 41822ef8a26SHangbin Liu 41922ef8a26SHangbin Liu autoneg = "off" 42022ef8a26SHangbin Liu if linkmodes.get("autoneg", 0) != 0: 42122ef8a26SHangbin Liu autoneg = "on" 42222ef8a26SHangbin Liu print(f'Auto-negotiation: {autoneg}') 42322ef8a26SHangbin Liu 42422ef8a26SHangbin Liu ports = { 42522ef8a26SHangbin Liu 0: 'Twisted Pair', 42622ef8a26SHangbin Liu 1: 'AUI', 42722ef8a26SHangbin Liu 2: 'MII', 42822ef8a26SHangbin Liu 3: 'FIBRE', 42922ef8a26SHangbin Liu 4: 'BNC', 43022ef8a26SHangbin Liu 5: 'Directly Attached Copper', 43122ef8a26SHangbin Liu 0xef: 'None', 43222ef8a26SHangbin Liu } 4331c43d471SHangbin Liu linkinfo = do_get(ynl, args, 'linkinfo-get') 43422ef8a26SHangbin Liu print(f'Port: {ports.get(linkinfo["port"], "Other")}') 43522ef8a26SHangbin Liu 43622ef8a26SHangbin Liu print_field(linkinfo, ('phyaddr', 'PHYAD')) 43722ef8a26SHangbin Liu 43822ef8a26SHangbin Liu transceiver = { 43922ef8a26SHangbin Liu 0: 'Internal', 44022ef8a26SHangbin Liu 1: 'External', 44122ef8a26SHangbin Liu } 44222ef8a26SHangbin Liu print(f'Transceiver: {transceiver.get(linkinfo["transceiver"], "Unknown")}') 44322ef8a26SHangbin Liu 44422ef8a26SHangbin Liu mdix_ctrl = { 44522ef8a26SHangbin Liu 1: 'off', 44622ef8a26SHangbin Liu 2: 'on', 44722ef8a26SHangbin Liu } 44822ef8a26SHangbin Liu mdix = mdix_ctrl.get(linkinfo['tp-mdix-ctrl'], None) 44922ef8a26SHangbin Liu if mdix: 45022ef8a26SHangbin Liu mdix = mdix + ' (forced)' 45122ef8a26SHangbin Liu else: 45222ef8a26SHangbin Liu mdix = mdix_ctrl.get(linkinfo['tp-mdix'], 'Unknown (auto)') 45322ef8a26SHangbin Liu print(f'MDI-X: {mdix}') 45422ef8a26SHangbin Liu 4551c43d471SHangbin Liu debug = do_get(ynl, args, 'debug-get') 45622ef8a26SHangbin Liu msgmask = bits_to_dict(debug.get("msgmask", [])).keys() 45722ef8a26SHangbin Liu print(f'Current message level: {" ".join(msgmask)}') 45822ef8a26SHangbin Liu 4591c43d471SHangbin Liu linkstate = do_get(ynl, args, 'linkstate-get') 46022ef8a26SHangbin Liu detected_states = { 46122ef8a26SHangbin Liu 0: 'no', 46222ef8a26SHangbin Liu 1: 'yes', 46322ef8a26SHangbin Liu } 46422ef8a26SHangbin Liu # TODO: wol-get 46522ef8a26SHangbin Liu detected = detected_states.get(linkstate['link'], 'unknown') 46622ef8a26SHangbin Liu print(f'Link detected: {detected}') 46722ef8a26SHangbin Liu 46822ef8a26SHangbin Liuif __name__ == '__main__': 46922ef8a26SHangbin Liu main() 470