Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  ethtool.py

  Sprache: Python
 

#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause

import argparse
import json
import pathlib
import pprint
import sys
import re
import os

sys.path.append(pathlib.Path(__file__).resolve().parent.as_posix())
from lib import YnlFamily
from cli import schema_dir, spec_dir

def args_to_req(ynl, op_name, args, req):
    """
    Verify and convert command-line arguments to the ynl-compatible request.
    """
    valid_attrs = ynl.operation_do_attributes(op_name)
    valid_attrs.remove('header'# not user-provided

    if len(args) == 0:
        print(f'no attributes, expected: {valid_attrs}')
        sys.exit(1)

    i = 0
    while i < len(args):
        attr = args[i]
        if i + 1 >= len(args):
            print(f'expected value for \'{attr}\'')
            sys.exit(1)

        if attr not in valid_attrs:
            print(f'invalid attribute \'{attr}\', expected: {valid_attrs}')
            sys.exit(1)

        val = args[i+1]
        i += 2

        req[attr] = val

def print_field(reply, *desc):
    """
    Pretty-print a set of fields from the reply. desc specifies the
    fields and the optional type (bool/yn).
    """
    if not reply:
        return

    if len(desc) == 0:
        return print_field(reply, *zip(reply.keys(), reply.keys()))

    for spec in desc:
        try:
            field, name, tp = spec
        except:
            field, name = spec
            tp = 'int'

        value = reply.get(field, None)
        if tp == 'yn':
            value = 'yes' if value else 'no'
        elif tp == 'bool' or isinstance(value, bool):
            value = 'on' if value else 'off'
        else:
            value = 'n/a' if value is None else value

        print(f'{name}: {value}')

def print_speed(name, value):
    """
    Print out the speed-like strings from the value dict.
    """
    speed_re = re.compile(r'[0-9]+base[^/]+/.+')
    speed = [ k for k, v in value.items() if v and speed_re.match(k) ]
    print(f'{name}: {" ".join(speed)}')

def doit(ynl, args, op_name):
    """
    Prepare request header, parse arguments and doit.
    """
    req = {
        'header': {
          'dev-name': args.device,
        },
    }

    args_to_req(ynl, op_name, args.args, req)
    ynl.do(op_name, req)

def dumpit(ynl, args, op_name, extra = {}):
    """
    Prepare request header, parse arguments and dumpit (filtering out the
    devices we're not interested in).
    """
    reply = ynl.dump(op_name, { 'header': {} } | extra)
    if not reply:
        return {}

    for msg in reply:
        if msg['header']['dev-name'] == args.device:
            if args.json:
                pprint.PrettyPrinter().pprint(msg)
                sys.exit(0)
            msg.pop('header'None)
            return msg

    print(f"Not supported for device {args.device}")
    sys.exit(1)

def bits_to_dict(attr):
    """
    Convert ynl-formatted bitmask to a dict of bit=value.
    """
    ret = {}
    if 'bits' not in attr:
        return dict()
    if 'bit' not in attr['bits']:
        return dict()
    for bit in attr['bits']['bit']:
        if bit['name'] == '':
            continue
        name = bit['name']
        value = bit.get('value'False)
        ret[name] = value
    return ret

def main():
    parser = argparse.ArgumentParser(description='ethtool wannabe')
    parser.add_argument('--json', action=argparse.BooleanOptionalAction)
    parser.add_argument('--show-priv-flags', action=argparse.BooleanOptionalAction)
    parser.add_argument('--set-priv-flags', action=argparse.BooleanOptionalAction)
    parser.add_argument('--show-eee', action=argparse.BooleanOptionalAction)
    parser.add_argument('--set-eee', action=argparse.BooleanOptionalAction)
    parser.add_argument('-a''--show-pause', action=argparse.BooleanOptionalAction)
    parser.add_argument('-A''--set-pause', action=argparse.BooleanOptionalAction)
    parser.add_argument('-c''--show-coalesce', action=argparse.BooleanOptionalAction)
    parser.add_argument('-C''--set-coalesce', action=argparse.BooleanOptionalAction)
    parser.add_argument('-g''--show-ring', action=argparse.BooleanOptionalAction)
    parser.add_argument('-G''--set-ring', action=argparse.BooleanOptionalAction)
    parser.add_argument('-k''--show-features', action=argparse.BooleanOptionalAction)
    parser.add_argument('-K''--set-features', action=argparse.BooleanOptionalAction)
    parser.add_argument('-l''--show-channels', action=argparse.BooleanOptionalAction)
    parser.add_argument('-L''--set-channels', action=argparse.BooleanOptionalAction)
    parser.add_argument('-T''--show-time-stamping', action=argparse.BooleanOptionalAction)
    parser.add_argument('-S''--statistics', action=argparse.BooleanOptionalAction)
    # TODO: --show-tunnels        tunnel-info-get
    # TODO: --show-module         module-get
    # TODO: --get-plca-cfg        plca-get
    # TODO: --get-plca-status     plca-get-status
    # TODO: --show-mm             mm-get
    # TODO: --show-fec            fec-get
    # TODO: --dump-module-eerpom  module-eeprom-get
    # TODO:                       pse-get
    # TODO:                       rss-get
    parser.add_argument('device', metavar='device', type=str)
    parser.add_argument('args', metavar='args', type=str, nargs='*')
    global args
    args = parser.parse_args()

    script_abs_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
    spec = os.path.join(spec_dir(), 'ethtool.yaml')
    schema = os.path.join(schema_dir(), 'genetlink-legacy.yaml')

    ynl = YnlFamily(spec, schema)

    if args.set_priv_flags:
        # TODO: parse the bitmask
        print("not implemented")
        return

    if args.set_eee:
        return doit(ynl, args, 'eee-set')

    if args.set_pause:
        return doit(ynl, args, 'pause-set')

    if args.set_coalesce:
        return doit(ynl, args, 'coalesce-set')

    if args.set_features:
        # TODO: parse the bitmask
        print("not implemented")
        return

    if args.set_channels:
        return doit(ynl, args, 'channels-set')

    if args.set_ring:
        return doit(ynl, args, 'rings-set')

    if args.show_priv_flags:
        flags = bits_to_dict(dumpit(ynl, args, 'privflags-get')['flags'])
        print_field(flags)
        return

    if args.show_eee:
        eee = dumpit(ynl, args, 'eee-get')
        ours = bits_to_dict(eee['modes-ours'])
        peer = bits_to_dict(eee['modes-peer'])

        if 'enabled' in eee:
            status = 'enabled' if eee['enabled'else 'disabled'
            if 'active' in eee and eee['active']:
                status = status + ' - active'
            else:
                status = status + ' - inactive'
        else:
            status = 'not supported'

        print(f'EEE status: {status}')
        print_field(eee, ('tx-lpi-timer''Tx LPI'))
        print_speed('Advertised EEE link modes', ours)
        print_speed('Link partner advertised EEE link modes', peer)

        return

    if args.show_pause:
        print_field(dumpit(ynl, args, 'pause-get'),
                ('autoneg''Autonegotiate''bool'),
                ('rx''RX''bool'),
                ('tx''TX''bool'))
        return

    if args.show_coalesce:
        print_field(dumpit(ynl, args, 'coalesce-get'))
        return

    if args.show_features:
        reply = dumpit(ynl, args, 'features-get')
        available = bits_to_dict(reply['hw'])
        requested = bits_to_dict(reply['wanted']).keys()
        active = bits_to_dict(reply['active']).keys()
        never_changed = bits_to_dict(reply['nochange']).keys()

        for f in sorted(available):
            value = "off"
            if f in active:
                value = "on"

            fixed = ""
            if f not in available or f in never_changed:
                fixed = " [fixed]"

            req = ""
            if f in requested:
                if f in active:
                    req = " [requested on]"
                else:
                    req = " [requested off]"

            print(f'{f}: {value}{fixed}{req}')

        return

    if args.show_channels:
        reply = dumpit(ynl, args, 'channels-get')
        print(f'Channel parameters for {args.device}:')

        print(f'Pre-set maximums:')
        print_field(reply,
            ('rx-max''RX'),
            ('tx-max''TX'),
            ('other-max''Other'),
            ('combined-max''Combined'))

        print(f'Current hardware settings:')
        print_field(reply,
            ('rx-count''RX'),
            ('tx-count''TX'),
            ('other-count''Other'),
            ('combined-count''Combined'))

        return

    if args.show_ring:
        reply = dumpit(ynl, args, 'channels-get')

        print(f'Ring parameters for {args.device}:')

        print(f'Pre-set maximums:')
        print_field(reply,
            ('rx-max''RX'),
            ('rx-mini-max''RX Mini'),
            ('rx-jumbo-max''RX Jumbo'),
            ('tx-max''TX'))

        print(f'Current hardware settings:')
        print_field(reply,
            ('rx''RX'),
            ('rx-mini''RX Mini'),
            ('rx-jumbo''RX Jumbo'),
            ('tx''TX'))

        print_field(reply,
            ('rx-buf-len''RX Buf Len'),
            ('cqe-size''CQE Size'),
            ('tx-push''TX Push''bool'))

        return

    if args.statistics:
        print(f'NIC statistics:')

        # TODO: pass id?
        strset = dumpit(ynl, args, 'strset-get')
        pprint.PrettyPrinter().pprint(strset)

        req = {
          'groups': {
            'size': 1,
            'bits': {
              'bit':
                # TODO: support passing the bitmask
                #[
                  #{ 'name': 'eth-phy', 'value': True },
                  { 'name''eth-mac''value'True },
                  #{ 'name': 'eth-ctrl', 'value': True },
                  #{ 'name': 'rmon', 'value': True },
                #],
            },
          },
        }

        rsp = dumpit(ynl, args, 'stats-get', req)
        pprint.PrettyPrinter().pprint(rsp)
        return

    if args.show_time_stamping:
        req = {
          'header': {
            'flags''stats',
          },
        }

        tsinfo = dumpit(ynl, args, 'tsinfo-get', req)

        print(f'Time stamping parameters for {args.device}:')

        print('Capabilities:')
        [print(f'\t{v}'for v in bits_to_dict(tsinfo['timestamping'])]

        print(f'PTP Hardware Clock: {tsinfo.get("phc-index", "none")}')

        if 'tx-types' in tsinfo:
            print('Hardware Transmit Timestamp Modes:')
            [print(f'\t{v}'for v in bits_to_dict(tsinfo['tx-types'])]
        else:
            print('Hardware Transmit Timestamp Modes: none')

        if 'rx-filters' in tsinfo:
            print('Hardware Receive Filter Modes:')
            [print(f'\t{v}'for v in bits_to_dict(tsinfo['rx-filters'])]
        else:
            print('Hardware Receive Filter Modes: none')

        if 'stats' in tsinfo and tsinfo['stats']:
            print('Statistics:')
            [print(f'\t{k}: {v}'for k, v in tsinfo['stats'].items()]

        return

    print(f'Settings for {args.device}:')
    linkmodes = dumpit(ynl, args, 'linkmodes-get')
    ours = bits_to_dict(linkmodes['ours'])

    supported_ports = ('TP',  'AUI''BNC''MII''FIBRE''Backplane')
    ports = [ p for p in supported_ports if ours.get(p, False)]
    print(f'Supported ports: [ {" ".join(ports)} ]')

    print_speed('Supported link modes', ours)

    print_field(ours, ('Pause''Supported pause frame use''yn'))
    print_field(ours, ('Autoneg''Supports auto-negotiation''yn'))

    supported_fec = ('None',  'PS''BASER''LLRS')
    fec = [ p for p in supported_fec if ours.get(p, False)]
    fec_str = " ".join(fec)
    if len(fec) == 0:
        fec_str = "Not reported"

    print(f'Supported FEC modes: {fec_str}')

    speed = 'Unknown!'
    if linkmodes['speed'] > 0 and linkmodes['speed'] < 0xffffffff:
        speed = f'{linkmodes["speed"]}Mb/s'
    print(f'Speed: {speed}')

    duplex_modes = {
            0: 'Half',
            1: 'Full',
    }
    duplex = duplex_modes.get(linkmodes["duplex"], None)
    if not duplex:
        duplex = f'Unknown! ({linkmodes["duplex"]})'
    print(f'Duplex: {duplex}')

    autoneg = "off"
    if linkmodes.get("autoneg", 0) != 0:
        autoneg = "on"
    print(f'Auto-negotiation: {autoneg}')

    ports = {
            0: 'Twisted Pair',
            1: 'AUI',
            2: 'MII',
            3: 'FIBRE',
            4: 'BNC',
            5: 'Directly Attached Copper',
            0xef: 'None',
    }
    linkinfo = dumpit(ynl, args, 'linkinfo-get')
    print(f'Port: {ports.get(linkinfo["port"], "Other")}')

    print_field(linkinfo, ('phyaddr''PHYAD'))

    transceiver = {
            0: 'Internal',
            1: 'External',
    }
    print(f'Transceiver: {transceiver.get(linkinfo["transceiver"], "Unknown")}')

    mdix_ctrl = {
            1: 'off',
            2: 'on',
    }
    mdix = mdix_ctrl.get(linkinfo['tp-mdix-ctrl'], None)
    if mdix:
        mdix = mdix + ' (forced)'
    else:
        mdix = mdix_ctrl.get(linkinfo['tp-mdix'], 'Unknown (auto)')
    print(f'MDI-X: {mdix}')

    debug = dumpit(ynl, args, 'debug-get')
    msgmask = bits_to_dict(debug.get("msgmask", [])).keys()
    print(f'Current message level: {" ".join(msgmask)}')

    linkstate = dumpit(ynl, args, 'linkstate-get')
    detected_states = {
            0: 'no',
            1: 'yes',
    }
    # TODO: wol-get
    detected = detected_states.get(linkstate['link'], 'unknown')
    print(f'Link detected: {detected}')

if __name__ == '__main__':
    main()

Messung V0.5 in Prozent
C=94 H=94 G=93

¤ Dauer der Verarbeitung: 0.21 Sekunden  (vorverarbeitet am  2026-04-29) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge