#! /usr/bin/python # -*- python -*- # -*- coding: utf-8 -*- # Copyright (C) 2008 Red Hat Inc. # # This application is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; version 2. # # This application is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. import getopt, ethtool, sys def usage(): print '''Usage: pethtool [OPTIONS] [] -h|--help Give this help list -c|--show-coalesce Show coalesce options -C|--coalesce Set coalesce options [adaptive-rx on|off] [adaptive-tx on|off] [rx-usecs N] [rx-frames N] [rx-usecs-irq N] [rx-frames-irq N] [tx-usecs N] [tx-frames N] [tx-usecs-irq N] [tx-frames-irq N] [stats-block-usecs N] [pkt-rate-low N] [rx-usecs-low N] [rx-frames-low N] [tx-usecs-low N] [tx-frames-low N] [pkt-rate-high N] [rx-usecs-high N] [rx-frames-high N] [tx-usecs-high N] [tx-frames-high N] [sample-interval N] -i|--driver Show driver information -k|--show-offload Get protocol offload information -K|--offload Set protocol offload [ tso on|off ]''' tab = "" def printtab(msg): print tab + msg all_devices = [] ethtool_coalesce_msgs = ( ( "stats-block-usecs", "stats_block_coalesce_usecs" ), ( "sample-interval", "rate_sample_interval" ), ( "pkt-rate-low", "pkt_rate_low"), ( "pkt-rate-high", "pkt_rate_high"), ( "\n" ), ( "rx-usecs", "rx_coalesce_usecs"), ( "rx-frames", "rx_max_coalesced_frames"), ( "rx-usecs-irq", "rx_coalesce_usecs_irq"), ( "rx-frames-irq", "rx_max_coalesced_frames_irq"), ( "\n" ), ( "tx-usecs", "tx_coalesce_usecs"), ( "tx-frames", "tx_max_coalesced_frames"), ( "tx-usecs-irq", "tx_coalesce_usecs_irq"), ( "tx-frames-irq", "tx_max_coalesced_frames_irq"), ( "\n" ), ( "rx-usecs-low", "rx_coalesce_usecs_low"), ( "rx-frame-low", "rx_max_coalesced_frames_low"), ( "tx-usecs-low", "tx_coalesce_usecs_low"), ( "tx-frame-low", "tx_max_coalesced_frames_low"), ( "\n" ), ( "rx-usecs-high", "rx_coalesce_usecs_high"), ( "rx-frame-high", "rx_max_coalesced_frames_high"), ( "tx-usecs-high", "tx_coalesce_usecs_high"), ( "tx-frame-high", "tx_max_coalesced_frames_high"), ) def get_coalesce_dict_entry(ethtool_name): if ethtool_name == "adaptive-rx": return "use_adaptive_rx_coalesce" if ethtool_name == "adaptive-tx": return "use_adaptive_tx_coalesce" for name in ethtool_coalesce_msgs: if name[0] == ethtool_name: return name[1] return None def show_coalesce(interface, args = None): printtab("Coalesce parameters for %s:" % interface) try: coal = ethtool.get_coalesce(interface) except IOError: printtab(" NOT supported!") return printtab("Adaptive RX: %s TX: %s" % (coal["use_adaptive_rx_coalesce"] and "on" or "off", coal["use_adaptive_tx_coalesce"] and "on" or "off")) printed = [ "use_adaptive_rx_coalesce", "use_adaptive_tx_coalesce" ] for tunable in ethtool_coalesce_msgs: if tunable[0] == '\n': print else: printtab("%s: %s" % (tunable[0], coal[tunable[1]])) printed.append(tunable[1]) coalkeys = coal.keys() if len(coalkeys) != len(printed): print for tunable in coalkeys: if tunable not in printed: printtab("%s %s" % (tunable, coal[tunable])) def set_coalesce(interface, args): try: coal = ethtool.get_coalesce(interface) except IOError: printtab("Interrupt coalescing NOT supported on %s!" % interface) return changed = False args = [a.lower() for a in args] for arg, value in [ ( args[i], args[i + 1] ) for i in range(0, len(args), 2) ]: real_arg = get_coalesce_dict_entry(arg) if not real_arg: continue if value == "on": value = 1 elif value == "off": value = 0 else: try: value = int(value) except: continue if coal[real_arg] != value: coal[real_arg] = value changed = True if not changed: return ethtool.set_coalesce(interface, coal) def show_offload(interface, args = None): try: sg = ethtool.get_sg(interface) and "on" or "off" except IOError: sg = "not supported" try: tso = ethtool.get_tso(interface) and "on" or "off" except IOError: tso = "not supported" try: ufo = ethtool.get_ufo(interface) and "on" or "off" except IOError: ufo = "not supported" try: gso = ethtool.get_gso(interface) and "on" or "off" except IOError: gso = "not supported" printtab("scatter-gather: %s" % sg) printtab("tcp segmentation offload: %s" % tso) printtab("udp fragmentation offload: %s" % ufo) printtab("generic segmentation offload: %s" % gso) def set_offload(interface, args): cmd, value = [a.lower() for a in args] if cmd == "tso": value = value == "on" and 1 or 0 try: ethtool.set_tso(interface, value) except: pass ethtool_ringparam_msgs = ( ( "Pre-set maximums", ), ( "RX:\t\t", "rx_max_pending" ), ( "RX Mini:\t", "rx_mini_max_pending" ), ( "RX Jumbo:\t", "rx_jumbo_max_pending" ), ( "TX:\t\t", "tx_max_pending" ), ( "Current hardware settings", ), ( "RX:\t\t", "rx_pending" ), ( "RX Mini:\t", "rx_mini_pending" ), ( "RX Jumbo:\t", "rx_jumbo_pending" ), ( "TX:\t\t", "tx_pending" ), ) def show_ring(interface, args = None): printtab("Ring parameters for %s:" % interface) try: ring = ethtool.get_ringparam(interface) except IOError: printtab(" NOT supported!") return printed = [] for tunable in ethtool_ringparam_msgs: if len(tunable) == 1: printtab("%s:" % tunable[0]) else: printtab("%s %s" % (tunable[0], ring[tunable[1]])) printed.append(tunable[1]) ringkeys = ring.keys() if len(ringkeys) != len(printed): print for tunable in ringkeys: if tunable not in printed: printtab("%s %s" % (tunable, ring[tunable])) ethtool_ringparam_map = { "rx": "rx_pending", "rx-mini": "rx_mini_pending", "rx-jumbo": "rx_jumbo_pending", "tx": "tx_pending", } def set_ringparam(interface, args): try: ring = ethtool.get_ringparam(interface) except IOError: printtab("ring parameters NOT supported on %s!" % interface) return changed = False args = [a.lower() for a in args] for arg, value in [ ( args[i], args[i + 1] ) for i in range(0, len(args), 2) ]: if not ethtool_ringparam_map.has_key(arg): continue try: value = int(value) except: continue real_arg = ethtool_ringparam_map[arg] if ring[real_arg] != value: ring[real_arg] = value changed = True if not changed: return ethtool.set_ringparam(interface, ring) def show_driver(interface, args = None): try: driver = ethtool.get_module(interface) except IOError: driver = "not implemented" try: bus = ethtool.get_businfo(interface) except IOError: bus = "not available" printtab("driver: %s" % driver) printtab("bus-info: %s" % bus) def run_cmd(cmd, interface, args): global tab, all_devices active_devices = ethtool.get_active_devices() if not interface: tab = " " for interface in all_devices: inactive = " (not active)" if interface in active_devices: inactive = "" print "%s%s:" % (interface, inactive) cmd(interface, args) else: cmd(interface, args) def run_cmd_noargs(cmd, args): if args: run_cmd(cmd, args[0], None) else: global all_devices all_devices = ethtool.get_devices() run_cmd(cmd, None, None) def main(): global all_devices try: opts, args = getopt.getopt(sys.argv[1:], "hcCgGikK", ("help", "show-coalesce", "coalesce", "show-ring", "set-ring", "driver", "show-offload", "offload")) except getopt.GetoptError, err: usage() print str(err) sys.exit(2) if not opts: usage() sys.exit(0) for o, a in opts: if o in ("-h", "--help"): usage() return elif o in ("-c", "--show-coalesce"): run_cmd_noargs(show_coalesce, args) break elif o in ("-i", "--driver"): run_cmd_noargs(show_driver, args) break elif o in ("-k", "--show-offload"): run_cmd_noargs(show_offload, args) break elif o in ("-g", "--show-ring"): run_cmd_noargs(show_ring, args) break elif o in ("-K", "--offload", "-C", "--coalesce", "-G", "--set-ring"): all_devices = ethtool.get_devices() if len(args) < 2: usage() sys.exit(1) if args[0] not in all_devices: interface = None else: interface = args[0] args = args[1:] if o in ("-K", "--offload"): cmd = set_offload elif o in ("-C", "--coalesce"): cmd = set_coalesce elif o in ("-G", "--set-ring"): cmd = set_ringparam run_cmd(cmd, interface, args) break if __name__ == '__main__': main()