1 #!/usr/bin/env python3 1 #!/usr/bin/env python3 2 # SPDX-License-Identifier: GPL-2.0 OR BSD-3-Cl 2 # SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 3 3 4 import argparse 4 import argparse 5 import json 5 import json 6 import pprint 6 import pprint 7 import sys 7 import sys 8 import re 8 import re 9 import os 9 import os 10 10 11 from lib import YnlFamily 11 from lib import YnlFamily 12 12 13 def args_to_req(ynl, op_name, args, req): 13 def args_to_req(ynl, op_name, args, req): 14 """ 14 """ 15 Verify and convert command-line arguments 15 Verify and convert command-line arguments to the ynl-compatible request. 16 """ 16 """ 17 valid_attrs = ynl.operation_do_attributes( 17 valid_attrs = ynl.operation_do_attributes(op_name) 18 valid_attrs.remove('header') # not user-pr 18 valid_attrs.remove('header') # not user-provided 19 19 20 if len(args) == 0: 20 if len(args) == 0: 21 print(f'no attributes, expected: {vali 21 print(f'no attributes, expected: {valid_attrs}') 22 sys.exit(1) 22 sys.exit(1) 23 23 24 i = 0 24 i = 0 25 while i < len(args): 25 while i < len(args): 26 attr = args[i] 26 attr = args[i] 27 if i + 1 >= len(args): 27 if i + 1 >= len(args): 28 print(f'expected value for \'{attr 28 print(f'expected value for \'{attr}\'') 29 sys.exit(1) 29 sys.exit(1) 30 30 31 if attr not in valid_attrs: 31 if attr not in valid_attrs: 32 print(f'invalid attribute \'{attr} 32 print(f'invalid attribute \'{attr}\', expected: {valid_attrs}') 33 sys.exit(1) 33 sys.exit(1) 34 34 35 val = args[i+1] 35 val = args[i+1] 36 i += 2 36 i += 2 37 37 38 req[attr] = val 38 req[attr] = val 39 39 40 def print_field(reply, *desc): 40 def print_field(reply, *desc): 41 """ 41 """ 42 Pretty-print a set of fields from the repl 42 Pretty-print a set of fields from the reply. desc specifies the 43 fields and the optional type (bool/yn). 43 fields and the optional type (bool/yn). 44 """ 44 """ 45 if len(desc) == 0: 45 if len(desc) == 0: 46 return print_field(reply, *zip(reply.k 46 return print_field(reply, *zip(reply.keys(), reply.keys())) 47 47 48 for spec in desc: 48 for spec in desc: 49 try: 49 try: 50 field, name, tp = spec 50 field, name, tp = spec 51 except: 51 except: 52 field, name = spec 52 field, name = spec 53 tp = 'int' 53 tp = 'int' 54 54 55 value = reply.get(field, None) 55 value = reply.get(field, None) 56 if tp == 'yn': 56 if tp == 'yn': 57 value = 'yes' if value else 'no' 57 value = 'yes' if value else 'no' 58 elif tp == 'bool' or isinstance(value, 58 elif tp == 'bool' or isinstance(value, bool): 59 value = 'on' if value else 'off' 59 value = 'on' if value else 'off' 60 else: 60 else: 61 value = 'n/a' if value is None els 61 value = 'n/a' if value is None else value 62 62 63 print(f'{name}: {value}') 63 print(f'{name}: {value}') 64 64 65 def print_speed(name, value): 65 def print_speed(name, value): 66 """ 66 """ 67 Print out the speed-like strings from the 67 Print out the speed-like strings from the value dict. 68 """ 68 """ 69 speed_re = re.compile(r'[0-9]+base[^/]+/.+ 69 speed_re = re.compile(r'[0-9]+base[^/]+/.+') 70 speed = [ k for k, v in value.items() if v 70 speed = [ k for k, v in value.items() if v and speed_re.match(k) ] 71 print(f'{name}: {" ".join(speed)}') 71 print(f'{name}: {" ".join(speed)}') 72 72 73 def doit(ynl, args, op_name): 73 def doit(ynl, args, op_name): 74 """ 74 """ 75 Prepare request header, parse arguments an 75 Prepare request header, parse arguments and doit. 76 """ 76 """ 77 req = { 77 req = { 78 'header': { 78 'header': { 79 'dev-name': args.device, 79 'dev-name': args.device, 80 }, 80 }, 81 } 81 } 82 82 83 args_to_req(ynl, op_name, args.args, req) 83 args_to_req(ynl, op_name, args.args, req) 84 ynl.do(op_name, req) 84 ynl.do(op_name, req) 85 85 86 def dumpit(ynl, args, op_name, extra = {}): 86 def dumpit(ynl, args, op_name, extra = {}): 87 """ 87 """ 88 Prepare request header, parse arguments an 88 Prepare request header, parse arguments and dumpit (filtering out the 89 devices we're not interested in). 89 devices we're not interested in). 90 """ 90 """ 91 reply = ynl.dump(op_name, { 'header': {} } 91 reply = ynl.dump(op_name, { 'header': {} } | extra) 92 if not reply: 92 if not reply: 93 return {} 93 return {} 94 94 95 for msg in reply: 95 for msg in reply: 96 if msg['header']['dev-name'] == args.d 96 if msg['header']['dev-name'] == args.device: 97 if args.json: 97 if args.json: 98 pprint.PrettyPrinter().pprint( 98 pprint.PrettyPrinter().pprint(msg) 99 sys.exit(0) 99 sys.exit(0) 100 msg.pop('header', None) 100 msg.pop('header', None) 101 return msg 101 return msg 102 102 103 print(f"Not supported for device {args.dev 103 print(f"Not supported for device {args.device}") 104 sys.exit(1) 104 sys.exit(1) 105 105 106 def bits_to_dict(attr): 106 def bits_to_dict(attr): 107 """ 107 """ 108 Convert ynl-formatted bitmask to a dict of 108 Convert ynl-formatted bitmask to a dict of bit=value. 109 """ 109 """ 110 ret = {} 110 ret = {} 111 if 'bits' not in attr: 111 if 'bits' not in attr: 112 return dict() 112 return dict() 113 if 'bit' not in attr['bits']: 113 if 'bit' not in attr['bits']: 114 return dict() 114 return dict() 115 for bit in attr['bits']['bit']: 115 for bit in attr['bits']['bit']: 116 if bit['name'] == '': 116 if bit['name'] == '': 117 continue 117 continue 118 name = bit['name'] 118 name = bit['name'] 119 value = bit.get('value', False) 119 value = bit.get('value', False) 120 ret[name] = value 120 ret[name] = value 121 return ret 121 return ret 122 122 123 def main(): 123 def main(): 124 parser = argparse.ArgumentParser(descripti 124 parser = argparse.ArgumentParser(description='ethtool wannabe') 125 parser.add_argument('--json', action=argpa 125 parser.add_argument('--json', action=argparse.BooleanOptionalAction) 126 parser.add_argument('--show-priv-flags', a 126 parser.add_argument('--show-priv-flags', action=argparse.BooleanOptionalAction) 127 parser.add_argument('--set-priv-flags', ac 127 parser.add_argument('--set-priv-flags', action=argparse.BooleanOptionalAction) 128 parser.add_argument('--show-eee', action=a 128 parser.add_argument('--show-eee', action=argparse.BooleanOptionalAction) 129 parser.add_argument('--set-eee', action=ar 129 parser.add_argument('--set-eee', action=argparse.BooleanOptionalAction) 130 parser.add_argument('-a', '--show-pause', 130 parser.add_argument('-a', '--show-pause', action=argparse.BooleanOptionalAction) 131 parser.add_argument('-A', '--set-pause', a 131 parser.add_argument('-A', '--set-pause', action=argparse.BooleanOptionalAction) 132 parser.add_argument('-c', '--show-coalesce 132 parser.add_argument('-c', '--show-coalesce', action=argparse.BooleanOptionalAction) 133 parser.add_argument('-C', '--set-coalesce' 133 parser.add_argument('-C', '--set-coalesce', action=argparse.BooleanOptionalAction) 134 parser.add_argument('-g', '--show-ring', a 134 parser.add_argument('-g', '--show-ring', action=argparse.BooleanOptionalAction) 135 parser.add_argument('-G', '--set-ring', ac 135 parser.add_argument('-G', '--set-ring', action=argparse.BooleanOptionalAction) 136 parser.add_argument('-k', '--show-features 136 parser.add_argument('-k', '--show-features', action=argparse.BooleanOptionalAction) 137 parser.add_argument('-K', '--set-features' 137 parser.add_argument('-K', '--set-features', action=argparse.BooleanOptionalAction) 138 parser.add_argument('-l', '--show-channels 138 parser.add_argument('-l', '--show-channels', action=argparse.BooleanOptionalAction) 139 parser.add_argument('-L', '--set-channels' 139 parser.add_argument('-L', '--set-channels', action=argparse.BooleanOptionalAction) 140 parser.add_argument('-T', '--show-time-sta 140 parser.add_argument('-T', '--show-time-stamping', action=argparse.BooleanOptionalAction) 141 parser.add_argument('-S', '--statistics', 141 parser.add_argument('-S', '--statistics', action=argparse.BooleanOptionalAction) 142 # TODO: --show-tunnels tunnel-info- 142 # TODO: --show-tunnels tunnel-info-get 143 # TODO: --show-module module-get 143 # TODO: --show-module module-get 144 # TODO: --get-plca-cfg plca-get 144 # TODO: --get-plca-cfg plca-get 145 # TODO: --get-plca-status plca-get-sta 145 # TODO: --get-plca-status plca-get-status 146 # TODO: --show-mm mm-get 146 # TODO: --show-mm mm-get 147 # TODO: --show-fec fec-get 147 # TODO: --show-fec fec-get 148 # TODO: --dump-module-eerpom module-eepro 148 # TODO: --dump-module-eerpom module-eeprom-get 149 # TODO: pse-get 149 # TODO: pse-get 150 # TODO: rss-get 150 # TODO: rss-get 151 parser.add_argument('device', metavar='dev 151 parser.add_argument('device', metavar='device', type=str) 152 parser.add_argument('args', metavar='args' 152 parser.add_argument('args', metavar='args', type=str, nargs='*') 153 global args 153 global args 154 args = parser.parse_args() 154 args = parser.parse_args() 155 155 156 script_abs_dir = os.path.dirname(os.path.a 156 script_abs_dir = os.path.dirname(os.path.abspath(sys.argv[0])) 157 spec = os.path.join(script_abs_dir, 157 spec = os.path.join(script_abs_dir, 158 '../../../Documentatio 158 '../../../Documentation/netlink/specs/ethtool.yaml') 159 schema = os.path.join(script_abs_dir, 159 schema = os.path.join(script_abs_dir, 160 '../../../Documentat 160 '../../../Documentation/netlink/genetlink-legacy.yaml') 161 161 162 ynl = YnlFamily(spec, schema) 162 ynl = YnlFamily(spec, schema) 163 163 164 if args.set_priv_flags: 164 if args.set_priv_flags: 165 # TODO: parse the bitmask 165 # TODO: parse the bitmask 166 print("not implemented") 166 print("not implemented") 167 return 167 return 168 168 169 if args.set_eee: 169 if args.set_eee: 170 return doit(ynl, args, 'eee-set') 170 return doit(ynl, args, 'eee-set') 171 171 172 if args.set_pause: 172 if args.set_pause: 173 return doit(ynl, args, 'pause-set') 173 return doit(ynl, args, 'pause-set') 174 174 175 if args.set_coalesce: 175 if args.set_coalesce: 176 return doit(ynl, args, 'coalesce-set') 176 return doit(ynl, args, 'coalesce-set') 177 177 178 if args.set_features: 178 if args.set_features: 179 # TODO: parse the bitmask 179 # TODO: parse the bitmask 180 print("not implemented") 180 print("not implemented") 181 return 181 return 182 182 183 if args.set_channels: 183 if args.set_channels: 184 return doit(ynl, args, 'channels-set') 184 return doit(ynl, args, 'channels-set') 185 185 186 if args.set_ring: 186 if args.set_ring: 187 return doit(ynl, args, 'rings-set') 187 return doit(ynl, args, 'rings-set') 188 188 189 if args.show_priv_flags: 189 if args.show_priv_flags: 190 flags = bits_to_dict(dumpit(ynl, args, 190 flags = bits_to_dict(dumpit(ynl, args, 'privflags-get')['flags']) 191 print_field(flags) 191 print_field(flags) 192 return 192 return 193 193 194 if args.show_eee: 194 if args.show_eee: 195 eee = dumpit(ynl, args, 'eee-get') 195 eee = dumpit(ynl, args, 'eee-get') 196 ours = bits_to_dict(eee['modes-ours']) 196 ours = bits_to_dict(eee['modes-ours']) 197 peer = bits_to_dict(eee['modes-peer']) 197 peer = bits_to_dict(eee['modes-peer']) 198 198 199 if 'enabled' in eee: 199 if 'enabled' in eee: 200 status = 'enabled' if eee['enabled 200 status = 'enabled' if eee['enabled'] else 'disabled' 201 if 'active' in eee and eee['active 201 if 'active' in eee and eee['active']: 202 status = status + ' - active' 202 status = status + ' - active' 203 else: 203 else: 204 status = status + ' - inactive 204 status = status + ' - inactive' 205 else: 205 else: 206 status = 'not supported' 206 status = 'not supported' 207 207 208 print(f'EEE status: {status}') 208 print(f'EEE status: {status}') 209 print_field(eee, ('tx-lpi-timer', 'Tx 209 print_field(eee, ('tx-lpi-timer', 'Tx LPI')) 210 print_speed('Advertised EEE link modes 210 print_speed('Advertised EEE link modes', ours) 211 print_speed('Link partner advertised E 211 print_speed('Link partner advertised EEE link modes', peer) 212 212 213 return 213 return 214 214 215 if args.show_pause: 215 if args.show_pause: 216 print_field(dumpit(ynl, args, 'pause-g 216 print_field(dumpit(ynl, args, 'pause-get'), 217 ('autoneg', 'Autonegotiate', ' 217 ('autoneg', 'Autonegotiate', 'bool'), 218 ('rx', 'RX', 'bool'), 218 ('rx', 'RX', 'bool'), 219 ('tx', 'TX', 'bool')) 219 ('tx', 'TX', 'bool')) 220 return 220 return 221 221 222 if args.show_coalesce: 222 if args.show_coalesce: 223 print_field(dumpit(ynl, args, 'coalesc 223 print_field(dumpit(ynl, args, 'coalesce-get')) 224 return 224 return 225 225 226 if args.show_features: 226 if args.show_features: 227 reply = dumpit(ynl, args, 'features-ge 227 reply = dumpit(ynl, args, 'features-get') 228 available = bits_to_dict(reply['hw']) 228 available = bits_to_dict(reply['hw']) 229 requested = bits_to_dict(reply['wanted 229 requested = bits_to_dict(reply['wanted']).keys() 230 active = bits_to_dict(reply['active']) 230 active = bits_to_dict(reply['active']).keys() 231 never_changed = bits_to_dict(reply['no 231 never_changed = bits_to_dict(reply['nochange']).keys() 232 232 233 for f in sorted(available): 233 for f in sorted(available): 234 value = "off" 234 value = "off" 235 if f in active: 235 if f in active: 236 value = "on" 236 value = "on" 237 237 238 fixed = "" 238 fixed = "" 239 if f not in available or f in neve 239 if f not in available or f in never_changed: 240 fixed = " [fixed]" 240 fixed = " [fixed]" 241 241 242 req = "" 242 req = "" 243 if f in requested: 243 if f in requested: 244 if f in active: 244 if f in active: 245 req = " [requested on]" 245 req = " [requested on]" 246 else: 246 else: 247 req = " [requested off]" 247 req = " [requested off]" 248 248 249 print(f'{f}: {value}{fixed}{req}') 249 print(f'{f}: {value}{fixed}{req}') 250 250 251 return 251 return 252 252 253 if args.show_channels: 253 if args.show_channels: 254 reply = dumpit(ynl, args, 'channels-ge 254 reply = dumpit(ynl, args, 'channels-get') 255 print(f'Channel parameters for {args.d 255 print(f'Channel parameters for {args.device}:') 256 256 257 print(f'Pre-set maximums:') 257 print(f'Pre-set maximums:') 258 print_field(reply, 258 print_field(reply, 259 ('rx-max', 'RX'), 259 ('rx-max', 'RX'), 260 ('tx-max', 'TX'), 260 ('tx-max', 'TX'), 261 ('other-max', 'Other'), 261 ('other-max', 'Other'), 262 ('combined-max', 'Combined')) 262 ('combined-max', 'Combined')) 263 263 264 print(f'Current hardware settings:') 264 print(f'Current hardware settings:') 265 print_field(reply, 265 print_field(reply, 266 ('rx-count', 'RX'), 266 ('rx-count', 'RX'), 267 ('tx-count', 'TX'), 267 ('tx-count', 'TX'), 268 ('other-count', 'Other'), 268 ('other-count', 'Other'), 269 ('combined-count', 'Combined')) 269 ('combined-count', 'Combined')) 270 270 271 return 271 return 272 272 273 if args.show_ring: 273 if args.show_ring: 274 reply = dumpit(ynl, args, 'channels-ge 274 reply = dumpit(ynl, args, 'channels-get') 275 275 276 print(f'Ring parameters for {args.devi 276 print(f'Ring parameters for {args.device}:') 277 277 278 print(f'Pre-set maximums:') 278 print(f'Pre-set maximums:') 279 print_field(reply, 279 print_field(reply, 280 ('rx-max', 'RX'), 280 ('rx-max', 'RX'), 281 ('rx-mini-max', 'RX Mini'), 281 ('rx-mini-max', 'RX Mini'), 282 ('rx-jumbo-max', 'RX Jumbo'), 282 ('rx-jumbo-max', 'RX Jumbo'), 283 ('tx-max', 'TX')) 283 ('tx-max', 'TX')) 284 284 285 print(f'Current hardware settings:') 285 print(f'Current hardware settings:') 286 print_field(reply, 286 print_field(reply, 287 ('rx', 'RX'), 287 ('rx', 'RX'), 288 ('rx-mini', 'RX Mini'), 288 ('rx-mini', 'RX Mini'), 289 ('rx-jumbo', 'RX Jumbo'), 289 ('rx-jumbo', 'RX Jumbo'), 290 ('tx', 'TX')) 290 ('tx', 'TX')) 291 291 292 print_field(reply, 292 print_field(reply, 293 ('rx-buf-len', 'RX Buf Len'), 293 ('rx-buf-len', 'RX Buf Len'), 294 ('cqe-size', 'CQE Size'), 294 ('cqe-size', 'CQE Size'), 295 ('tx-push', 'TX Push', 'bool')) 295 ('tx-push', 'TX Push', 'bool')) 296 296 297 return 297 return 298 298 299 if args.statistics: 299 if args.statistics: 300 print(f'NIC statistics:') 300 print(f'NIC statistics:') 301 301 302 # TODO: pass id? 302 # TODO: pass id? 303 strset = dumpit(ynl, args, 'strset-get 303 strset = dumpit(ynl, args, 'strset-get') 304 pprint.PrettyPrinter().pprint(strset) 304 pprint.PrettyPrinter().pprint(strset) 305 305 306 req = { 306 req = { 307 'groups': { 307 'groups': { 308 'size': 1, 308 'size': 1, 309 'bits': { 309 'bits': { 310 'bit': 310 'bit': 311 # TODO: support passing the bi 311 # TODO: support passing the bitmask 312 #[ 312 #[ 313 #{ 'name': 'eth-phy', 'value 313 #{ 'name': 'eth-phy', 'value': True }, 314 { 'name': 'eth-mac', 'value' 314 { 'name': 'eth-mac', 'value': True }, 315 #{ 'name': 'eth-ctrl', 'valu 315 #{ 'name': 'eth-ctrl', 'value': True }, 316 #{ 'name': 'rmon', 'value': 316 #{ 'name': 'rmon', 'value': True }, 317 #], 317 #], 318 }, 318 }, 319 }, 319 }, 320 } 320 } 321 321 322 rsp = dumpit(ynl, args, 'stats-get', r 322 rsp = dumpit(ynl, args, 'stats-get', req) 323 pprint.PrettyPrinter().pprint(rsp) 323 pprint.PrettyPrinter().pprint(rsp) 324 return 324 return 325 325 326 if args.show_time_stamping: 326 if args.show_time_stamping: 327 req = { 327 req = { 328 'header': { 328 'header': { 329 'flags': 'stats', 329 'flags': 'stats', 330 }, 330 }, 331 } 331 } 332 332 333 tsinfo = dumpit(ynl, args, 'tsinfo-get 333 tsinfo = dumpit(ynl, args, 'tsinfo-get', req) 334 334 335 print(f'Time stamping parameters for { 335 print(f'Time stamping parameters for {args.device}:') 336 336 337 print('Capabilities:') 337 print('Capabilities:') 338 [print(f'\t{v}') for v in bits_to_dict 338 [print(f'\t{v}') for v in bits_to_dict(tsinfo['timestamping'])] 339 339 340 print(f'PTP Hardware Clock: {tsinfo["p 340 print(f'PTP Hardware Clock: {tsinfo["phc-index"]}') 341 341 342 print('Hardware Transmit Timestamp Mod 342 print('Hardware Transmit Timestamp Modes:') 343 [print(f'\t{v}') for v in bits_to_dict 343 [print(f'\t{v}') for v in bits_to_dict(tsinfo['tx-types'])] 344 344 345 print('Hardware Receive Filter Modes:' 345 print('Hardware Receive Filter Modes:') 346 [print(f'\t{v}') for v in bits_to_dict 346 [print(f'\t{v}') for v in bits_to_dict(tsinfo['rx-filters'])] 347 347 348 print('Statistics:') 348 print('Statistics:') 349 [print(f'\t{k}: {v}') for k, v in tsin 349 [print(f'\t{k}: {v}') for k, v in tsinfo['stats'].items()] 350 return 350 return 351 351 352 print(f'Settings for {args.device}:') 352 print(f'Settings for {args.device}:') 353 linkmodes = dumpit(ynl, args, 'linkmodes-g 353 linkmodes = dumpit(ynl, args, 'linkmodes-get') 354 ours = bits_to_dict(linkmodes['ours']) 354 ours = bits_to_dict(linkmodes['ours']) 355 355 356 supported_ports = ('TP', 'AUI', 'BNC', 'M 356 supported_ports = ('TP', 'AUI', 'BNC', 'MII', 'FIBRE', 'Backplane') 357 ports = [ p for p in supported_ports if ou 357 ports = [ p for p in supported_ports if ours.get(p, False)] 358 print(f'Supported ports: [ {" ".join(ports 358 print(f'Supported ports: [ {" ".join(ports)} ]') 359 359 360 print_speed('Supported link modes', ours) 360 print_speed('Supported link modes', ours) 361 361 362 print_field(ours, ('Pause', 'Supported pau 362 print_field(ours, ('Pause', 'Supported pause frame use', 'yn')) 363 print_field(ours, ('Autoneg', 'Supports au 363 print_field(ours, ('Autoneg', 'Supports auto-negotiation', 'yn')) 364 364 365 supported_fec = ('None', 'PS', 'BASER', ' 365 supported_fec = ('None', 'PS', 'BASER', 'LLRS') 366 fec = [ p for p in supported_fec if ours.g 366 fec = [ p for p in supported_fec if ours.get(p, False)] 367 fec_str = " ".join(fec) 367 fec_str = " ".join(fec) 368 if len(fec) == 0: 368 if len(fec) == 0: 369 fec_str = "Not reported" 369 fec_str = "Not reported" 370 370 371 print(f'Supported FEC modes: {fec_str}') 371 print(f'Supported FEC modes: {fec_str}') 372 372 373 speed = 'Unknown!' 373 speed = 'Unknown!' 374 if linkmodes['speed'] > 0 and linkmodes['s 374 if linkmodes['speed'] > 0 and linkmodes['speed'] < 0xffffffff: 375 speed = f'{linkmodes["speed"]}Mb/s' 375 speed = f'{linkmodes["speed"]}Mb/s' 376 print(f'Speed: {speed}') 376 print(f'Speed: {speed}') 377 377 378 duplex_modes = { 378 duplex_modes = { 379 0: 'Half', 379 0: 'Half', 380 1: 'Full', 380 1: 'Full', 381 } 381 } 382 duplex = duplex_modes.get(linkmodes["duple 382 duplex = duplex_modes.get(linkmodes["duplex"], None) 383 if not duplex: 383 if not duplex: 384 duplex = f'Unknown! ({linkmodes["duple 384 duplex = f'Unknown! ({linkmodes["duplex"]})' 385 print(f'Duplex: {duplex}') 385 print(f'Duplex: {duplex}') 386 386 387 autoneg = "off" 387 autoneg = "off" 388 if linkmodes.get("autoneg", 0) != 0: 388 if linkmodes.get("autoneg", 0) != 0: 389 autoneg = "on" 389 autoneg = "on" 390 print(f'Auto-negotiation: {autoneg}') 390 print(f'Auto-negotiation: {autoneg}') 391 391 392 ports = { 392 ports = { 393 0: 'Twisted Pair', 393 0: 'Twisted Pair', 394 1: 'AUI', 394 1: 'AUI', 395 2: 'MII', 395 2: 'MII', 396 3: 'FIBRE', 396 3: 'FIBRE', 397 4: 'BNC', 397 4: 'BNC', 398 5: 'Directly Attached Copper', 398 5: 'Directly Attached Copper', 399 0xef: 'None', 399 0xef: 'None', 400 } 400 } 401 linkinfo = dumpit(ynl, args, 'linkinfo-get 401 linkinfo = dumpit(ynl, args, 'linkinfo-get') 402 print(f'Port: {ports.get(linkinfo["port"], 402 print(f'Port: {ports.get(linkinfo["port"], "Other")}') 403 403 404 print_field(linkinfo, ('phyaddr', 'PHYAD') 404 print_field(linkinfo, ('phyaddr', 'PHYAD')) 405 405 406 transceiver = { 406 transceiver = { 407 0: 'Internal', 407 0: 'Internal', 408 1: 'External', 408 1: 'External', 409 } 409 } 410 print(f'Transceiver: {transceiver.get(link 410 print(f'Transceiver: {transceiver.get(linkinfo["transceiver"], "Unknown")}') 411 411 412 mdix_ctrl = { 412 mdix_ctrl = { 413 1: 'off', 413 1: 'off', 414 2: 'on', 414 2: 'on', 415 } 415 } 416 mdix = mdix_ctrl.get(linkinfo['tp-mdix-ctr 416 mdix = mdix_ctrl.get(linkinfo['tp-mdix-ctrl'], None) 417 if mdix: 417 if mdix: 418 mdix = mdix + ' (forced)' 418 mdix = mdix + ' (forced)' 419 else: 419 else: 420 mdix = mdix_ctrl.get(linkinfo['tp-mdix 420 mdix = mdix_ctrl.get(linkinfo['tp-mdix'], 'Unknown (auto)') 421 print(f'MDI-X: {mdix}') 421 print(f'MDI-X: {mdix}') 422 422 423 debug = dumpit(ynl, args, 'debug-get') 423 debug = dumpit(ynl, args, 'debug-get') 424 msgmask = bits_to_dict(debug.get("msgmask" 424 msgmask = bits_to_dict(debug.get("msgmask", [])).keys() 425 print(f'Current message level: {" ".join(m 425 print(f'Current message level: {" ".join(msgmask)}') 426 426 427 linkstate = dumpit(ynl, args, 'linkstate-g 427 linkstate = dumpit(ynl, args, 'linkstate-get') 428 detected_states = { 428 detected_states = { 429 0: 'no', 429 0: 'no', 430 1: 'yes', 430 1: 'yes', 431 } 431 } 432 # TODO: wol-get 432 # TODO: wol-get 433 detected = detected_states.get(linkstate[' 433 detected = detected_states.get(linkstate['link'], 'unknown') 434 print(f'Link detected: {detected}') 434 print(f'Link detected: {detected}') 435 435 436 if __name__ == '__main__': 436 if __name__ == '__main__': 437 main() 437 main()
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.