pax_global_header00006660000000000000000000000064115510370560014515gustar00rootroot0000000000000052 comment=1680cbeb40e76dd975bc8ace756e74771901d607 python-ethtool-0.7/000077500000000000000000000000001155103705600143605ustar00rootroot00000000000000python-ethtool-0.7/COPYING000066400000000000000000000430761155103705600154250ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program 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; either version 2 of the License, or (at your option) any later version. This program 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. python-ethtool-0.7/MANIFEST000066400000000000000000000005131155103705600155100ustar00rootroot00000000000000COPYING pethtool.py pifconfig.py python-ethtool/ethtool.c python-ethtool/ethtool-copy.h python-ethtool/etherinfo.c python-ethtool/etherinfo_obj.c python-ethtool/etherinfo_ipv6_obj.c python-ethtool/etherinfo_struct.h python-ethtool/etherinfo.h python-ethtool/etherinfo_obj.h setup.py rpm/SPECS/python-ethtool.spec MANIFEST Makefile python-ethtool-0.7/Makefile000066400000000000000000000015731155103705600160260ustar00rootroot00000000000000PACKAGE := python-ethtool VERSION := $(shell rpm -q --qf '%{VERSION} ' --specfile rpm/SPECS/$(PACKAGE).spec | cut -d' ' -f1) rpmdirs: @[ -d rpm/BUILD ] || mkdir rpm/BUILD @[ -d rpm/RPMS ] || mkdir rpm/RPMS @[ -d rpm/SRPMS ] || mkdir rpm/SRPMS @[ -d rpm/SOURCES ] || mkdir rpm/SOURCES bz2: rpmdirs git archive --format=tar --prefix=$(PACKAGE)-$(VERSION)/ HEAD | \ bzip2 -9 > rpm/SOURCES/$(PACKAGE)-$(VERSION).tar.bz2 install: python setup.py install --root=$(DESTDIR) rpm: bz2 rpmdirs rpmbuild -ba --define "_topdir $(PWD)/rpm" rpm/SPECS/$(PACKAGE).spec bz2dev: rpmdirs @mkdir -p /tmp/$(PACKAGE)-$(VERSION) @tar cf - `cat MANIFEST` | (cd /tmp/$(PACKAGE)-$(VERSION) ; tar xf -) @(cd /tmp; tar cf - $(PACKAGE)-$(VERSION)) | bzip2 -9 > rpm/SOURCES/$(PACKAGE)-$(VERSION).tar.bz2 rpmdev: bz2dev rpmdirs rpmbuild -ba --define "_topdir $(PWD)/rpm" rpm/SPECS/$(PACKAGE).spec python-ethtool-0.7/man/000077500000000000000000000000001155103705600151335ustar00rootroot00000000000000python-ethtool-0.7/man/pethtool.8.asciidoc000066400000000000000000000027241155103705600206440ustar00rootroot00000000000000pethtool(8) =========== NAME ---- pethtool - Display or change ethernet card settings SYNOPSIS -------- pethtool [OPTIONS] [] DESCRIPTION ----------- This script mimic ethtool behavior, but is written purely in python and python module ethtool. OPTIONS ------- INTERFACE:: Is the name of the ethernet device on which pethtool should operate. -h, --help:: Show help message and exit. -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 ] SEE ALSO -------- ethtool(8) AUTHORS ------- Arnaldo Carvalho de Melo Man page written by Miroslav Suchý python-ethtool-0.7/man/pifconfig.8.asciidoc000066400000000000000000000011171155103705600207450ustar00rootroot00000000000000pifconfig(8) ============ NAME ---- pifconfig - display information about a network interface SYNOPSIS -------- pifconfig [INTERFACE] DESCRIPTION ----------- This script mimic ifconfig behavior, but is written purely in python and python module ethtool. OPTIONS ------- INTERFACE:: Display information about only this interface. If no interface is given then all interfaces are displayed. -h, --help:: Show help message and exit. SEE ALSO -------- ifconfig(8) AUTHORS ------- Arnaldo Carvalho de Melo Man page written by Miroslav Suchý python-ethtool-0.7/pethtool.py000077500000000000000000000217041155103705600165770ustar00rootroot00000000000000#! /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() python-ethtool-0.7/pifconfig.py000077500000000000000000000047361155103705600167130ustar00rootroot00000000000000#! /usr/bin/python # -*- python -*- # -*- coding: utf-8 -*- # Copyright (C) 2008 Red Hat Inc. # # Arnaldo Carvalho de Melo # # 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: pifconfig ''' def flags2str(flags): string = "" if flags & ethtool.IFF_UP: string += "UP " if flags & ethtool.IFF_BROADCAST: string += "BROADCAST " if flags & ethtool.IFF_DEBUG: string += "DEBUG " if flags & ethtool.IFF_LOOPBACK: string += "LOOPBACK " if flags & ethtool.IFF_POINTOPOINT: string += "POINTOPOINT " if flags & ethtool.IFF_NOTRAILERS: string += "NOTRAILERS " if flags & ethtool.IFF_RUNNING: string += "RUNNING " if flags & ethtool.IFF_NOARP: string += "NOARP " if flags & ethtool.IFF_PROMISC: string += "PROMISC " if flags & ethtool.IFF_ALLMULTI: string += "ALLMULTI " if flags & ethtool.IFF_MASTER: string += "MASTER " if flags & ethtool.IFF_SLAVE: string += "SLAVE " if flags & ethtool.IFF_MULTICAST: string += "MULTICAST " if flags & ethtool.IFF_PORTSEL: string += "PORTSEL " if flags & ethtool.IFF_AUTOMEDIA: string += "AUTOMEDIA " if flags & ethtool.IFF_DYNAMIC: string += "DYNAMIC " return string.strip() def show_config(device): ipaddr = ethtool.get_ipaddr(device) netmask = ethtool.get_netmask(device) flags = ethtool.get_flags(device) print '%-9.9s' % device, if not (flags & ethtool.IFF_LOOPBACK): print "HWaddr %s" % ethtool.get_hwaddr(device), print ''' inet addr:%s''' % ipaddr, if not (flags & (ethtool.IFF_LOOPBACK | ethtool.IFF_POINTOPOINT)): print "Bcast:%s" % ethtool.get_broadcast(device), print ''' Mask:%s %s ''' % (netmask, flags2str(flags)) def main(): global all_devices try: opts, args = getopt.getopt(sys.argv[1:], "h", ("help",)) except getopt.GetoptError, err: usage() print str(err) sys.exit(2) for o, a in opts: if o in ("-h", "--help"): usage() return active_devices = ethtool.get_active_devices() for device in active_devices: show_config(device) if __name__ == '__main__': main() python-ethtool-0.7/python-ethtool/000077500000000000000000000000001155103705600173555ustar00rootroot00000000000000python-ethtool-0.7/python-ethtool/etherinfo.c000066400000000000000000000261061155103705600215110ustar00rootroot00000000000000/* etherinfo.c - Retrieve ethernet interface info via NETLINK * * Copyright (C) 2009-2011 Red Hat Inc. * * David Sommerseth * Parts of this code is based on ideas and solutions in iproute2 * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "etherinfo_struct.h" #include "etherinfo.h" pthread_mutex_t nlc_counter_mtx = PTHREAD_MUTEX_INITIALIZER; /* * * Internal functions for working with struct etherinfo * */ /** * Simple macro which makes sure the destination string is freed if used earlier. * * @param dst Destination pointer * @param src Source pointer * */ #define SET_STR_VALUE(dst, src) { \ if( dst ) { \ free(dst); \ }; \ dst = strdup(src); \ } /** * Frees the memory used by a struct ipv6address pointer chain. All elements are freed * * @param ptr Pointer to a struct ipv6address chain. */ void free_ipv6addresses(struct ipv6address *ptr) { struct ipv6address *ipv6ptr = ptr; while( ipv6ptr ) { struct ipv6address *tmp = ipv6ptr->next; if( ipv6ptr->address ) { free(ipv6ptr->address); ipv6ptr->address = NULL; } memset(ipv6ptr, 0, sizeof(struct ipv6address)); free(ipv6ptr); ipv6ptr = tmp; } } /** * Frees the memory used by struct etherinfo, including all struct ipv6address children. * * @param ptr Pointer to a struct etherninfo element */ void free_etherinfo(struct etherinfo *ptr) { if( ptr == NULL ) { // Just for safety return; } free(ptr->device); if( ptr->hwaddress ) { free(ptr->hwaddress); } if( ptr->ipv4_address ) { free(ptr->ipv4_address); } if( ptr->ipv4_broadcast ) { free(ptr->ipv4_broadcast); } if( ptr->ipv6_addresses ) { free_ipv6addresses(ptr->ipv6_addresses); } free(ptr); } /** * Add a new IPv6 address record to a struct ipv6address chain * * @param addrptr Pointer to the current IPv6 address chain. * @param addr IPv6 address, represented as char * string * @param netmask IPv6 netmask, as returned by libnl rtnl_addr_get_prefixlen() * @param scope IPV6 address scope, as returned by libnl rtnl_addr_get_scope() * * @return Returns a new pointer to the chain containing the new element */ struct ipv6address * etherinfo_add_ipv6(struct ipv6address *addrptr, const char *addr, int netmask, int scope) { struct ipv6address *newaddr = NULL; newaddr = calloc(1, sizeof(struct ipv6address)+2); if( !newaddr ) { fprintf(stderr, "** ERROR ** Could not allocate memory for a new IPv6 address record (%s/%i [%i])", addr, netmask, scope); return addrptr; } SET_STR_VALUE(newaddr->address, addr); newaddr->netmask = netmask; newaddr->scope = scope; newaddr->next = addrptr; return newaddr; } /** * libnl callback function. Does the real parsing of a record returned by NETLINK. This function * parses LINK related packets * * @param obj Pointer to a struct nl_object response * @param arg Pointer to a struct etherinfo element where the parse result will be saved */ static void callback_nl_link(struct nl_object *obj, void *arg) { struct etherinfo *ethi = (struct etherinfo *) arg; struct rtnl_link *link = (struct rtnl_link *) obj; struct nl_addr *addr = rtnl_link_get_addr(link); unsigned int i, len; unsigned char *binaddr; char hwaddr[130], *ptr; if( (ethi == NULL) || (ethi->hwaddress != NULL) || (addr == NULL) ) { return; } binaddr = nl_addr_get_binary_addr(addr); memset(&hwaddr, 0, 130); len = 20; ptr = (char *)&hwaddr; for( i = 0; i < 6; i++ ) { if( i == 0 ) { snprintf(ptr, len, "%02X", *(binaddr+i)); len -= 2; ptr += 2; } else { snprintf(ptr, len, ":%02X", *(binaddr+i)); len -= 3; ptr += 3; } } SET_STR_VALUE(ethi->hwaddress, hwaddr); } /** * libnl callback function. Does the real parsing of a record returned by NETLINK. This function * parses ADDRESS related packets * * @param obj Pointer to a struct nl_object response * @param arg Pointer to a struct etherinfo element where the parse result will be saved */ static void callback_nl_address(struct nl_object *obj, void *arg) { struct etherinfo *ethi = (struct etherinfo *) arg; struct nl_addr *addr; char ip_str[66]; int family; if( ethi == NULL ) { return; } addr = rtnl_addr_get_local((struct rtnl_addr *)obj); family = nl_addr_get_family(addr); switch( family ) { case AF_INET: case AF_INET6: memset(&ip_str, 0, 66); inet_ntop(family, nl_addr_get_binary_addr(addr), (char *)&ip_str, 64); if( family == AF_INET ) { struct nl_addr *brdcst = rtnl_addr_get_broadcast((struct rtnl_addr *)obj); char brdcst_str[66]; SET_STR_VALUE(ethi->ipv4_address, ip_str); ethi->ipv4_netmask = rtnl_addr_get_prefixlen((struct rtnl_addr*) obj); if( brdcst ) { memset(&brdcst_str, 0, 66); inet_ntop(family, nl_addr_get_binary_addr(brdcst), (char *)&brdcst_str, 64); SET_STR_VALUE(ethi->ipv4_broadcast, brdcst_str); } } else { ethi->ipv6_addresses = etherinfo_add_ipv6(ethi->ipv6_addresses, ip_str, rtnl_addr_get_prefixlen((struct rtnl_addr*) obj), rtnl_addr_get_scope((struct rtnl_addr*) obj)); } return; default: return; } } /* * * Exported functions - API frontend * */ /** * Dumps the contents of a struct etherinfo element to file * * @param fp FILE pointer where to dump * @param ptr Pointer to a struct etherinfo element */ void dump_etherinfo(FILE *fp, struct etherinfo *ptr) { fprintf(fp, "*** Interface [%i] %s ", ptr->index, ptr->device); if( ptr->hwaddress ) { fprintf(fp, "MAC address: %s", ptr->hwaddress); } fprintf(fp, "\n"); if( ptr->ipv4_address ) { fprintf(fp, "\tIPv4 Address: %s/%i", ptr->ipv4_address, ptr->ipv4_netmask); if( ptr->ipv4_broadcast ) { fprintf(fp, " - Broadcast: %s", ptr->ipv4_broadcast); } fprintf(fp, "\n"); } if( ptr->ipv6_addresses ) { struct ipv6address *ipv6 = ptr->ipv6_addresses; fprintf(fp, "\tIPv6 addresses:\n"); for(; ipv6; ipv6 = ipv6->next) { char scope[66]; rtnl_scope2str(ipv6->scope, scope, 64); fprintf(fp, "\t [%s] %s/%i\n", scope, ipv6->address, ipv6->netmask); } } fprintf(fp, "\n"); } /** * Query NETLINK for ethernet configuration * * @param ethinf Pointer to an available struct etherinfo element. The 'device' member * must contain a valid string to the device to query for information * @param nlc Pointer to the libnl handle, which is used for the query against NETLINK * @param query What to query for. Must be NLQRY_LINK or NLQRY_ADDR. * * @return Returns 1 on success, otherwise 0. */ int get_etherinfo(struct etherinfo_obj_data *data, nlQuery query) { struct nl_cache *link_cache; struct nl_cache *addr_cache; struct rtnl_addr *addr; struct rtnl_link *link; struct etherinfo *ethinf = NULL; int ret = 0; if( !data || !data->ethinfo ) { return 0; } ethinf = data->ethinfo; /* Open a NETLINK connection on-the-fly */ if( !open_netlink(data) ) { PyErr_Format(PyExc_RuntimeError, "Could not open a NETLINK connection for %s", ethinf->device); return 0; } /* Find the interface index we're looking up. * As we don't expect it to change, we're reusing a "cached" * interface index if we have that */ if( ethinf->index < 0 ) { link_cache = rtnl_link_alloc_cache(*data->nlc); ethinf->index = rtnl_link_name2i(link_cache, ethinf->device); if( ethinf->index < 0 ) { return 0; } nl_cache_free(link_cache); } /* Query the for requested info vai NETLINK */ switch( query ) { case NLQRY_LINK: /* Extract MAC/hardware address of the interface */ link_cache = rtnl_link_alloc_cache(*data->nlc); link = rtnl_link_alloc(); rtnl_link_set_ifindex(link, ethinf->index); nl_cache_foreach_filter(link_cache, (struct nl_object *)link, callback_nl_link, ethinf); rtnl_link_put(link); nl_cache_free(link_cache); ret = 1; break; case NLQRY_ADDR: /* Extract IP address information */ addr_cache = rtnl_addr_alloc_cache(*data->nlc); addr = rtnl_addr_alloc(); rtnl_addr_set_ifindex(addr, ethinf->index); /* Make sure we don't have any old IPv6 addresses saved */ if( ethinf->ipv6_addresses ) { free_ipv6addresses(ethinf->ipv6_addresses); ethinf->ipv6_addresses = NULL; } /* Retrieve all address information */ nl_cache_foreach_filter(addr_cache, (struct nl_object *)addr, callback_nl_address, ethinf); rtnl_addr_put(addr); nl_cache_free(addr_cache); ret = 1; break; default: ret = 0; } return ret; } /** * Connects to the NETLINK interface. This will be called * for each etherinfo object being generated, and it will * keep a separate file descriptor open for each object * * @param data etherinfo_obj_data structure * * @return Returns 1 on success, otherwise 0. */ int open_netlink(struct etherinfo_obj_data *data) { if( !data ) { return 0; } /* Reuse already established NETLINK connection, if a connection exists */ if( *data->nlc ) { /* If this object has not used NETLINK earlier, tag it as a user */ if( !data->nlc_active ) { pthread_mutex_lock(&nlc_counter_mtx); (*data->nlc_users)++; pthread_mutex_unlock(&nlc_counter_mtx); } data->nlc_active = 1; return 1; } /* No earlier connections exists, establish a new one */ *data->nlc = nl_handle_alloc(); nl_connect(*data->nlc, NETLINK_ROUTE); if( (*data->nlc != NULL) ) { /* Force O_CLOEXEC flag on the NETLINK socket */ if( fcntl(nl_socket_get_fd(*data->nlc), F_SETFD, FD_CLOEXEC) == -1 ) { fprintf(stderr, "**WARNING** Failed to set O_CLOEXEC on NETLINK socket: %s\n", strerror(errno)); } /* Tag this object as an active user */ pthread_mutex_lock(&nlc_counter_mtx); (*data->nlc_users)++; pthread_mutex_unlock(&nlc_counter_mtx); data->nlc_active = 1; return 1; } else { return 0; } } /** * Closes the NETLINK connection. This should be called automatically whenever * the corresponding etherinfo object is deleted. * * @param ptr Pointer to the pointer of struct nl_handle, which contains the NETLINK connection */ void close_netlink(struct etherinfo_obj_data *data) { if( !data || !(*data->nlc) ) { return; } /* Untag this object as a NETLINK user */ data->nlc_active = 0; pthread_mutex_lock(&nlc_counter_mtx); (*data->nlc_users)--; pthread_mutex_unlock(&nlc_counter_mtx); /* Don't close the connection if there are more users */ if( *data->nlc_users > 0) { return; } /* Close NETLINK connection */ nl_close(*data->nlc); nl_handle_destroy(*data->nlc); *data->nlc = NULL; } python-ethtool-0.7/python-ethtool/etherinfo.h000066400000000000000000000023221155103705600215100ustar00rootroot00000000000000/* etherinfo.h - Retrieve ethernet interface info via NETLINK * * Copyright (C) 2009-2011 Red Hat Inc. * * David Sommerseth * * 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. */ #ifndef _ETHERINFO_H #define _ETHERINFO_H #include #include #include #include #include #include typedef enum {NLQRY_LINK, NLQRY_ADDR} nlQuery; /**< Supported query types in the etherinfo code */ int get_etherinfo(struct etherinfo_obj_data *data, nlQuery query); void free_etherinfo(struct etherinfo *ptr); void dump_etherinfo(FILE *, struct etherinfo *); void free_ipv6addresses(struct ipv6address *ptr); int open_netlink(struct etherinfo_obj_data *); void close_netlink(struct etherinfo_obj_data *); #endif python-ethtool-0.7/python-ethtool/etherinfo_ipv6_obj.c000066400000000000000000000155061155103705600233110ustar00rootroot00000000000000/* * Copyright (C) 2009-2010 Red Hat Inc. * * David Sommerseth * * 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. */ /** * @file etherinfo_ipv6_obj.c * @author David Sommerseth * @date Thu Jul 29 17:51:28 2010 * * @brief Python ethtool.etherinfo class functions. * */ #include #include "structmember.h" #include #include "etherinfo_struct.h" #include "etherinfo.h" /** * ethtool.etherinfo_ipv6addr deallocator - cleans up when a object is deleted * * @param self etherinfo_ipv6addr_py object structure */ void _ethtool_etherinfo_ipv6_dealloc(etherinfo_ipv6addr_py *self) { if( self->addrdata ) { free_ipv6addresses(self->addrdata); } self->ob_type->tp_free((PyObject*)self); } /** * ethtool.etherinfo_ipv6addr function, creating a new etherinfo object * * @param type * @param args * @param kwds * * @return Returns in PyObject with the new object on success, otherwise NULL */ PyObject *_ethtool_etherinfo_ipv6_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { etherinfo_ipv6addr_py *self; self = (etherinfo_ipv6addr_py *)type->tp_alloc(type, 0); return (PyObject *)self; } /** * ethtool.etherinfo_ipv6addr init (constructor) method. Makes sure the object is initialised correctly. * * @param self * @param args * @param kwds * * @return Returns 0 on success. */ int _ethtool_etherinfo_ipv6_init(etherinfo_ipv6addr_py *self, PyObject *args, PyObject *kwds) { static char *etherinfo_kwlist[] = {"etherinfo_ipv6_ptr", NULL}; PyObject *ethinf_ptr = NULL; if( !PyArg_ParseTupleAndKeywords(args, kwds, "O", etherinfo_kwlist, ðinf_ptr)) { PyErr_SetString(PyExc_AttributeError, "Invalid data pointer to constructor"); return -1; } self->addrdata = (struct ipv6address *) PyCObject_AsVoidPtr(ethinf_ptr); return 0; } /** * ethtool.etherinfo_ipv6addr function for retrieving data from a Python object. * * @param self * @param attr_o contains the object member request (which element to return) * * @return Returns a PyObject with the value requested on success, otherwise NULL */ PyObject *_ethtool_etherinfo_ipv6_getter(etherinfo_ipv6addr_py *self, PyObject *attr_o) { PyObject *ret; char *attr = PyString_AsString(attr_o); if( !self || !self->addrdata ) { PyErr_SetString(PyExc_AttributeError, "No data available"); return NULL; } if( strcmp(attr, "address") == 0 ) { ret = RETURN_STRING(self->addrdata->address); } else if( strcmp(attr, "netmask") == 0 ) { ret = PyInt_FromLong(self->addrdata->netmask); } else if( strcmp(attr, "scope") == 0 ) { char scope[66]; rtnl_scope2str(self->addrdata->scope, scope, 66); ret = PyString_FromString(scope); } else { ret = PyObject_GenericGetAttr((PyObject *)self, attr_o); } return ret; } /** * ethtool.etherinfo_ipv6addr function for setting a value to a object member. This feature is * disabled by always returning -1, as the values are read-only by the user. * * @param self * @param attr_o * @param val_o * * @return Returns always -1 (failure). */ int _ethtool_etherinfo_ipv6_setter(etherinfo_ipv6addr_py *self, PyObject *attr_o, PyObject *val_o) { PyErr_SetString(PyExc_AttributeError, "etherinfo_ipv6addr member values are read-only."); return -1; } /** * Creates a human readable format of the information when object is being treated as a string * * @param self * * @return Returns a PyObject with a string with all of the information */ PyObject *_ethtool_etherinfo_ipv6_str(etherinfo_ipv6addr_py *self) { char scope[66]; if( !self || !self->addrdata ) { PyErr_SetString(PyExc_AttributeError, "No data available"); return NULL; } rtnl_scope2str(self->addrdata->scope, scope, 64); return PyString_FromFormat("[%s] %s/%i", scope, self->addrdata->address, self->addrdata->netmask); } /** * This is required by Python, which lists all accessible methods * in the object. But no methods are provided. * */ static PyMethodDef _ethtool_etherinfo_ipv6_methods[] = { {NULL} /**< No methods defined */ }; /** * Defines all accessible object members * */ static PyMemberDef _ethtool_etherinfo_ipv6_members[] = { {"address", T_OBJECT_EX, offsetof(etherinfo_ipv6addr_py, addrdata), 0, "IPv6 address"}, {"netmask", T_OBJECT_EX, offsetof(etherinfo_ipv6addr_py, addrdata), 0, "IPv6 netmask"}, {"scope", T_OBJECT_EX, offsetof(etherinfo_ipv6addr_py, addrdata), 0, "IPv6 IP address scope"}, {NULL} /* End of member list */ }; /** * Definition of the functions a Python class/object requires. * */ PyTypeObject ethtool_etherinfoIPv6Type = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "ethtool.etherinfo_ipv6addr", /*tp_name*/ sizeof(etherinfo_ipv6addr_py), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)_ethtool_etherinfo_ipv6_dealloc,/*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ (reprfunc)_ethtool_etherinfo_ipv6_str, /*tp_str*/ (getattrofunc)_ethtool_etherinfo_ipv6_getter, /*tp_getattro*/ (setattrofunc)_ethtool_etherinfo_ipv6_setter, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ "IPv6 address information", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ _ethtool_etherinfo_ipv6_methods, /* tp_methods */ _ethtool_etherinfo_ipv6_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)_ethtool_etherinfo_ipv6_init, /* tp_init */ 0, /* tp_alloc */ _ethtool_etherinfo_ipv6_new, /* tp_new */ }; python-ethtool-0.7/python-ethtool/etherinfo_obj.c000066400000000000000000000245601155103705600223450ustar00rootroot00000000000000/* * Copyright (C) 2009-2011 Red Hat Inc. * * David Sommerseth * * 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. */ /** * @file etherinfo_obj.c * @author David Sommerseth * @date Fri Sep 4 18:41:28 2009 * * @brief Python ethtool.etherinfo class functions. * */ #include #include "structmember.h" #include #include "etherinfo_struct.h" #include "etherinfo.h" extern PyTypeObject ethtool_etherinfoIPv6Type; /** * ethtool.etherinfo deallocator - cleans up when a object is deleted * * @param self etherinfo_py object structure */ void _ethtool_etherinfo_dealloc(etherinfo_py *self) { if( self->data ) { close_netlink(self->data); if( self->data->ethinfo ) { free_etherinfo(self->data->ethinfo); } free(self->data); } self->ob_type->tp_free((PyObject*)self); } /** * ethtool.etherinfo function, creating a new etherinfo object * * @param type * @param args * @param kwds * * @return Returns in PyObject with the new object on success, otherwise NULL */ PyObject *_ethtool_etherinfo_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { etherinfo_py *self; self = (etherinfo_py *)type->tp_alloc(type, 0); return (PyObject *)self; } /** * ethtool.etherinfo init (constructor) method. Makes sure the object is initialised correctly. * * @param self * @param args * @param kwds * * @return Returns 0 on success. */ int _ethtool_etherinfo_init(etherinfo_py *self, PyObject *args, PyObject *kwds) { static char *etherinfo_kwlist[] = {"etherinfo_ptr", NULL}; PyObject *ethinf_ptr = NULL; if( !PyArg_ParseTupleAndKeywords(args, kwds, "O", etherinfo_kwlist, ðinf_ptr)) { PyErr_SetString(PyExc_AttributeError, "Invalid data pointer to constructor"); return -1; } self->data = (struct etherinfo_obj_data *) PyCObject_AsVoidPtr(ethinf_ptr); return 0; } /** * ethtool.etherinfo function for retrieving data from a Python object. * * @param self * @param attr_o contains the object member request (which element to return) * * @return Returns a PyObject with the value requested on success, otherwise NULL */ PyObject *_ethtool_etherinfo_getter(etherinfo_py *self, PyObject *attr_o) { PyObject *ret; char *attr = PyString_AsString(attr_o); if( !self || !self->data ) { PyErr_SetString(PyExc_AttributeError, "No data available"); return NULL; } if( strcmp(attr, "device") == 0 ) { ret = RETURN_STRING(self->data->ethinfo->device); } else if( strcmp(attr, "mac_address") == 0 ) { get_etherinfo(self->data, NLQRY_LINK); ret = RETURN_STRING(self->data->ethinfo->hwaddress); } else if( strcmp(attr, "ipv4_address") == 0 ) { get_etherinfo(self->data, NLQRY_ADDR); ret = RETURN_STRING(self->data->ethinfo->ipv4_address); } else if( strcmp(attr, "ipv4_netmask") == 0 ) { get_etherinfo(self->data, NLQRY_ADDR); ret = PyInt_FromLong(self->data->ethinfo->ipv4_netmask); } else if( strcmp(attr, "ipv4_broadcast") == 0 ) { get_etherinfo(self->data, NLQRY_ADDR); ret = RETURN_STRING(self->data->ethinfo->ipv4_broadcast); } else { ret = PyObject_GenericGetAttr((PyObject *)self, attr_o); } return ret; } /** * ethtool.etherinfo function for setting a value to a object member. This feature is * disabled by always returning -1, as the values are read-only by the user. * * @param self * @param attr_o * @param val_o * * @return Returns always -1 (failure). */ int _ethtool_etherinfo_setter(etherinfo_py *self, PyObject *attr_o, PyObject *val_o) { PyErr_SetString(PyExc_AttributeError, "etherinfo member values are read-only."); return -1; } /** * Creates a human readable format of the information when object is being treated as a string * * @param self * * @return Returns a PyObject with a string with all of the information */ PyObject *_ethtool_etherinfo_str(etherinfo_py *self) { PyObject *ret = NULL; if( !self || !self->data || !self->data->nlc || !self->data->ethinfo ) { PyErr_SetString(PyExc_AttributeError, "No data available"); return NULL; } get_etherinfo(self->data, NLQRY_LINK); get_etherinfo(self->data, NLQRY_ADDR); ret = PyString_FromFormat("Device %s:\n", self->data->ethinfo->device); if( self->data->ethinfo->hwaddress ) { PyObject *tmp = PyString_FromFormat("\tMAC address: %s\n", self->data->ethinfo->hwaddress); PyString_Concat(&ret, tmp); Py_DECREF(tmp); } if( self->data->ethinfo->ipv4_address ) { PyObject *tmp = PyString_FromFormat("\tIPv4 address: %s/%i", self->data->ethinfo->ipv4_address, self->data->ethinfo->ipv4_netmask); if( self->data->ethinfo->ipv4_broadcast ) { PyObject *tmp2 = PyString_FromFormat(" Broadcast: %s", self->data->ethinfo->ipv4_broadcast); PyString_Concat(&tmp, tmp2); Py_DECREF(tmp2); } PyString_Concat(&tmp, PyString_FromString("\n")); PyString_Concat(&ret, tmp); Py_DECREF(tmp); } if( self->data->ethinfo->ipv6_addresses ) { struct ipv6address *ipv6 = self->data->ethinfo->ipv6_addresses; PyObject *tmp = PyString_FromFormat("\tIPv6 addresses:\n"); PyString_Concat(&ret, tmp); Py_DECREF(tmp); for( ; ipv6; ipv6 = ipv6->next) { char scope[66]; rtnl_scope2str(ipv6->scope, scope, 64); PyObject *addr = PyString_FromFormat("\t [%s] %s/%i\n", scope, ipv6->address, ipv6->netmask); PyString_Concat(&ret, addr); Py_DECREF(addr); } } return ret; } /** * Returns a tuple list of ethertool.etherinfo_ipv6addr objects, containing configured * IPv6 addresses * * @param self * @param notused * * @return Returns a Python tuple list of ethertool.etherinfo_ipv6addr objects */ PyObject * _ethtool_etherinfo_get_ipv6_addresses(etherinfo_py *self, PyObject *notused) { PyObject *ret; struct ipv6address *ipv6 = NULL; int i = 0; if( !self || !self->data ) { PyErr_SetString(PyExc_AttributeError, "No data available"); return NULL; } get_etherinfo(self->data, NLQRY_ADDR); ipv6 = self->data->ethinfo->ipv6_addresses; ret = PyTuple_New(1); if( !ret ) { PyErr_SetString(PyExc_MemoryError, "[INTERNAL] Failed to allocate tuple list for " "IPv6 address objects"); return NULL; } while( ipv6 ) { PyObject *ipv6_pyobj = NULL, *ipv6_pydata = NULL, *args = NULL; struct ipv6address *next = ipv6->next; ipv6->next = NULL; ipv6_pydata = PyCObject_FromVoidPtr(ipv6, NULL); if( !ipv6_pydata ) { PyErr_SetString(PyExc_MemoryError, "[INTERNAL] Failed to create python object " "containing IPv6 address"); return NULL; } args = PyTuple_New(1); if( !args ) { PyErr_SetString(PyExc_MemoryError, "[INTERNAL] Failed to allocate argument list " "a new IPv6 address object"); return NULL; } PyTuple_SetItem(args, 0, ipv6_pydata); ipv6_pyobj = PyObject_CallObject((PyObject *)ðtool_etherinfoIPv6Type, args); Py_DECREF(args); if( ipv6_pyobj ) { PyTuple_SetItem(ret, i++, ipv6_pyobj); _PyTuple_Resize(&ret, i+1); } else { PyErr_SetString(PyExc_RuntimeError, "[INTERNAL] Failed to initialise the new " "IPv6 address object"); return NULL; } ipv6 = next; } _PyTuple_Resize(&ret, i); self->data->ethinfo->ipv6_addresses = NULL; return ret; } /** * Defines all available methods in the ethtool.etherinfo class * */ static PyMethodDef _ethtool_etherinfo_methods[] = { {"get_ipv6_addresses", _ethtool_etherinfo_get_ipv6_addresses, METH_NOARGS, "Retrieve configured IPv6 addresses. Returns a tuple list of etherinfo_ipv6addr objects"}, {NULL} /**< No methods defined */ }; /** * Defines all accessible object members * */ static PyMemberDef _ethtool_etherinfo_members[] = { {"device", T_OBJECT_EX, offsetof(etherinfo_py, data), 0, "Device name of the interface"}, {"mac_address", T_OBJECT_EX, offsetof(etherinfo_py, data), 0, "MAC address / hardware address of the interface"}, {"ipv4_address", T_OBJECT_EX, offsetof(etherinfo_py, data), 0, "IPv4 address"}, {"ipv4_netmask", T_INT, offsetof(etherinfo_py, data), 0, "IPv4 netmask in bits"}, {"ipv4_broadcast", T_OBJECT_EX, offsetof(etherinfo_py, data), 0, "IPv4 broadcast address"}, {NULL} /* End of member list */ }; /** * Definition of the functions a Python class/object requires. * */ PyTypeObject ethtool_etherinfoType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "ethtool.etherinfo", /*tp_name*/ sizeof(etherinfo_py), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)_ethtool_etherinfo_dealloc,/*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ (reprfunc)_ethtool_etherinfo_str, /*tp_str*/ (getattrofunc)_ethtool_etherinfo_getter, /*tp_getattro*/ (setattrofunc)_ethtool_etherinfo_setter, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ "Contains information about a specific ethernet device", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ _ethtool_etherinfo_methods, /* tp_methods */ _ethtool_etherinfo_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)_ethtool_etherinfo_init, /* tp_init */ 0, /* tp_alloc */ _ethtool_etherinfo_new, /* tp_new */ }; python-ethtool-0.7/python-ethtool/etherinfo_obj.h000066400000000000000000000023131155103705600223420ustar00rootroot00000000000000/* * Copyright (C) 2009-2010 Red Hat Inc. * * David Sommerseth * * 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. */ /** * @file etherinfo_obj.c * @author David Sommerseth * @date Fri Sep 4 18:41:28 2009 * * @brief Python ethtool.etherinfo class functions (header file). * */ #ifndef __ETHERINFO_OBJ_H #define __ETHERINFO_OBJ_H #include #include "etherinfo_struct.h" void _ethtool_etherinfo_dealloc(etherinfo_py *); PyObject *_ethtool_etherinfo_new(PyTypeObject *, PyObject *, PyObject *); int _ethtool_etherinfo_init(etherinfo_py *, PyObject *, PyObject *); PyObject *_ethtool_etherinfo_getter(etherinfo_py *, PyObject *); int _ethtool_etherinfo_setter(etherinfo_py *, PyObject *, PyObject *); PyObject *_ethtool_etherinfo_str(etherinfo_py *self); #endif python-ethtool-0.7/python-ethtool/etherinfo_struct.h000066400000000000000000000057221155103705600231230ustar00rootroot00000000000000/* * Copyright (C) 2009-2011 Red Hat Inc. * * David Sommerseth * * 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. */ /** * @file etherinfo_struct.h * @author David Sommerseth * @date Fri Sep 4 19:06:06 2009 * * @brief Contains the internal ethtool.etherinfo data structure * */ #ifndef _ETHERINFO_STRUCT_H #define _ETHERINFO_STRUCT_H /** * Contains IP address information about a particular ethernet device * */ struct etherinfo { char *device; /**< Device name */ int index; /**< NETLINK index reference */ char *hwaddress; /**< HW address / MAC address of device */ char *ipv4_address; /**< Configured IPv4 address */ int ipv4_netmask; /**< Configured IPv4 netmask */ char *ipv4_broadcast; /**< Configured IPv4 broadcast address */ struct ipv6address *ipv6_addresses; /**< Configured IPv6 addresses (as a pointer chain) */ }; /** * Pointer chain with IPv6 addresses associated with a ethernet interface. Used * by struct etherinfo */ struct ipv6address { char *address; /**< Configured IPv6 address */ int netmask; /**< Configured IPv6 netmask */ int scope; /**< Scope for the IPv6 address */ struct ipv6address *next; /**< Pointer to next configured IPv6 address */ }; /** * Contains the internal data structure of the * ethtool.etherinfo object. * */ struct etherinfo_obj_data { struct nl_handle **nlc; /**< Contains NETLINK connection info (global) */ unsigned int *nlc_users; /**< Resource counter for the NETLINK connection (global) */ unsigned short nlc_active; /**< Is this instance using NETLINK? */ struct etherinfo *ethinfo; /**< Contains info about our current interface */ }; /** * A Python object of struct etherinfo_obj_data * */ typedef struct { PyObject_HEAD struct etherinfo_obj_data *data; /* IPv4 and IPv6 address information, only one element used */ } etherinfo_py; /** * A Python object of struct ipv6address * */ typedef struct { PyObject_HEAD struct ipv6address *addrdata; /**< IPv6 address, only one element is used in this case */ } etherinfo_ipv6addr_py; /** * NULL safe PyString_FromString() wrapper. If input string is NULL, None will be returned * * @param str Input C string (char *) * * @return Returns a PyObject with either the input string wrapped up, or a Python None value. */ #define RETURN_STRING(str) (str ? PyString_FromString(str) : (Py_INCREF(Py_None), Py_None)) #endif python-ethtool-0.7/python-ethtool/ethtool-copy.h000066400000000000000000000300651155103705600221600ustar00rootroot00000000000000/* * ethtool.h: Defines for Linux ethtool. * * Copyright (C) 1998 David S. Miller (davem@redhat.com) * Copyright 2001 Jeff Garzik * Portions Copyright 2001 Sun Microsystems (thockin@sun.com) * Portions Copyright 2002 Intel (eli.kupermann@intel.com, * christopher.leech@intel.com, * scott.feldman@intel.com) */ #ifndef _LINUX_ETHTOOL_H #define _LINUX_ETHTOOL_H #ifndef __unused #define __unused __attribute__ ((unused)) #endif /* This should work for both 32 and 64 bit userland. */ struct ethtool_cmd { u32 cmd; u32 supported; /* Features this interface supports */ u32 advertising; /* Features this interface advertises */ u16 speed; /* The forced speed, 10Mb, 100Mb, gigabit */ u8 duplex; /* Duplex, half or full */ u8 port; /* Which connector port */ u8 phy_address; u8 transceiver; /* Which tranceiver to use */ u8 autoneg; /* Enable or disable autonegotiation */ u32 maxtxpkt; /* Tx pkts before generating tx int */ u32 maxrxpkt; /* Rx pkts before generating rx int */ u32 reserved[4]; }; #define ETHTOOL_BUSINFO_LEN 32 /* these strings are set to whatever the driver author decides... */ struct ethtool_drvinfo { u32 cmd; char driver[32]; /* driver short name, "tulip", "eepro100" */ char version[32]; /* driver version string */ char fw_version[32]; /* firmware version string, if applicable */ char bus_info[ETHTOOL_BUSINFO_LEN]; /* Bus info for this IF. */ /* For PCI devices, use pci_dev->slot_name. */ char reserved1[32]; char reserved2[16]; u32 n_stats; /* number of u64's from ETHTOOL_GSTATS */ u32 testinfo_len; u32 eedump_len; /* Size of data from ETHTOOL_GEEPROM (bytes) */ u32 regdump_len; /* Size of data from ETHTOOL_GREGS (bytes) */ }; #define SOPASS_MAX 6 /* wake-on-lan settings */ struct ethtool_wolinfo { u32 cmd; u32 supported; u32 wolopts; u8 sopass[SOPASS_MAX]; /* SecureOn(tm) password */ }; /* for passing single values */ struct ethtool_value { u32 cmd; u32 data; }; /* for passing big chunks of data */ struct ethtool_regs { u32 cmd; u32 version; /* driver-specific, indicates different chips/revs */ u32 len; /* bytes */ u8 data[0]; }; /* for passing EEPROM chunks */ struct ethtool_eeprom { u32 cmd; u32 magic; u32 offset; /* in bytes */ u32 len; /* in bytes */ u8 data[0]; }; /* for configuring coalescing parameters of chip */ struct ethtool_coalesce { u32 cmd; /* ETHTOOL_{G,S}COALESCE */ /* How many usecs to delay an RX interrupt after * a packet arrives. If 0, only rx_max_coalesced_frames * is used. */ u32 rx_coalesce_usecs; /* How many packets to delay an RX interrupt after * a packet arrives. If 0, only rx_coalesce_usecs is * used. It is illegal to set both usecs and max frames * to zero as this would cause RX interrupts to never be * generated. */ u32 rx_max_coalesced_frames; /* Same as above two parameters, except that these values * apply while an IRQ is being services by the host. Not * all cards support this feature and the values are ignored * in that case. */ u32 rx_coalesce_usecs_irq; u32 rx_max_coalesced_frames_irq; /* How many usecs to delay a TX interrupt after * a packet is sent. If 0, only tx_max_coalesced_frames * is used. */ u32 tx_coalesce_usecs; /* How many packets to delay a TX interrupt after * a packet is sent. If 0, only tx_coalesce_usecs is * used. It is illegal to set both usecs and max frames * to zero as this would cause TX interrupts to never be * generated. */ u32 tx_max_coalesced_frames; /* Same as above two parameters, except that these values * apply while an IRQ is being services by the host. Not * all cards support this feature and the values are ignored * in that case. */ u32 tx_coalesce_usecs_irq; u32 tx_max_coalesced_frames_irq; /* How many usecs to delay in-memory statistics * block updates. Some drivers do not have an in-memory * statistic block, and in such cases this value is ignored. * This value must not be zero. */ u32 stats_block_coalesce_usecs; /* Adaptive RX/TX coalescing is an algorithm implemented by * some drivers to improve latency under low packet rates and * improve throughput under high packet rates. Some drivers * only implement one of RX or TX adaptive coalescing. Anything * not implemented by the driver causes these values to be * silently ignored. */ u32 use_adaptive_rx_coalesce; u32 use_adaptive_tx_coalesce; /* When the packet rate (measured in packets per second) * is below pkt_rate_low, the {rx,tx}_*_low parameters are * used. */ u32 pkt_rate_low; u32 rx_coalesce_usecs_low; u32 rx_max_coalesced_frames_low; u32 tx_coalesce_usecs_low; u32 tx_max_coalesced_frames_low; /* When the packet rate is below pkt_rate_high but above * pkt_rate_low (both measured in packets per second) the * normal {rx,tx}_* coalescing parameters are used. */ /* When the packet rate is (measured in packets per second) * is above pkt_rate_high, the {rx,tx}_*_high parameters are * used. */ u32 pkt_rate_high; u32 rx_coalesce_usecs_high; u32 rx_max_coalesced_frames_high; u32 tx_coalesce_usecs_high; u32 tx_max_coalesced_frames_high; /* How often to do adaptive coalescing packet rate sampling, * measured in seconds. Must not be zero. */ u32 rate_sample_interval; }; /* for configuring RX/TX ring parameters */ struct ethtool_ringparam { u32 cmd; /* ETHTOOL_{G,S}RINGPARAM */ /* Read only attributes. These indicate the maximum number * of pending RX/TX ring entries the driver will allow the * user to set. */ u32 rx_max_pending; u32 rx_mini_max_pending; u32 rx_jumbo_max_pending; u32 tx_max_pending; /* Values changeable by the user. The valid values are * in the range 1 to the "*_max_pending" counterpart above. */ u32 rx_pending; u32 rx_mini_pending; u32 rx_jumbo_pending; u32 tx_pending; }; /* for configuring link flow control parameters */ struct ethtool_pauseparam { u32 cmd; /* ETHTOOL_{G,S}PAUSEPARAM */ /* If the link is being auto-negotiated (via ethtool_cmd.autoneg * being true) the user may set 'autonet' here non-zero to have the * pause parameters be auto-negotiated too. In such a case, the * {rx,tx}_pause values below determine what capabilities are * advertised. * * If 'autoneg' is zero or the link is not being auto-negotiated, * then {rx,tx}_pause force the driver to use/not-use pause * flow control. */ u32 autoneg; u32 rx_pause; u32 tx_pause; }; #define ETH_GSTRING_LEN 32 enum ethtool_stringset { ETH_SS_TEST = 0, ETH_SS_STATS, }; /* for passing string sets for data tagging */ struct ethtool_gstrings { u32 cmd; /* ETHTOOL_GSTRINGS */ u32 string_set; /* string set id e.c. ETH_SS_TEST, etc*/ u32 len; /* number of strings in the string set */ u8 data[0]; }; enum ethtool_test_flags { ETH_TEST_FL_OFFLINE = (1 << 0), /* online / offline */ ETH_TEST_FL_FAILED = (1 << 1), /* test passed / failed */ }; /* for requesting NIC test and getting results*/ struct ethtool_test { u32 cmd; /* ETHTOOL_TEST */ u32 flags; /* ETH_TEST_FL_xxx */ u32 reserved; u32 len; /* result length, in number of u64 elements */ u64 data[0]; }; /* for dumping NIC-specific statistics */ struct ethtool_stats { u32 cmd; /* ETHTOOL_GSTATS */ u32 n_stats; /* number of u64's being returned */ u64 data[0]; }; /* CMDs currently supported */ #define ETHTOOL_GSET 0x00000001 /* Get settings. */ #define ETHTOOL_SSET 0x00000002 /* Set settings, privileged. */ #define ETHTOOL_GDRVINFO 0x00000003 /* Get driver info. */ #define ETHTOOL_GREGS 0x00000004 /* Get NIC registers, privileged. */ #define ETHTOOL_GWOL 0x00000005 /* Get wake-on-lan options. */ #define ETHTOOL_SWOL 0x00000006 /* Set wake-on-lan options, priv. */ #define ETHTOOL_GMSGLVL 0x00000007 /* Get driver message level */ #define ETHTOOL_SMSGLVL 0x00000008 /* Set driver msg level, priv. */ #define ETHTOOL_NWAY_RST 0x00000009 /* Restart autonegotiation, priv. */ #define ETHTOOL_GLINK 0x0000000a /* Get link status (ethtool_value) */ #define ETHTOOL_GEEPROM 0x0000000b /* Get EEPROM data */ #define ETHTOOL_SEEPROM 0x0000000c /* Set EEPROM data, priv. */ #define ETHTOOL_GCOALESCE 0x0000000e /* Get coalesce config */ #define ETHTOOL_SCOALESCE 0x0000000f /* Set coalesce config, priv. */ #define ETHTOOL_GRINGPARAM 0x00000010 /* Get ring parameters */ #define ETHTOOL_SRINGPARAM 0x00000011 /* Set ring parameters, priv. */ #define ETHTOOL_GPAUSEPARAM 0x00000012 /* Get pause parameters */ #define ETHTOOL_SPAUSEPARAM 0x00000013 /* Set pause parameters, priv. */ #define ETHTOOL_GRXCSUM 0x00000014 /* Get RX hw csum enable (ethtool_value) */ #define ETHTOOL_SRXCSUM 0x00000015 /* Set RX hw csum enable (ethtool_value) */ #define ETHTOOL_GTXCSUM 0x00000016 /* Get TX hw csum enable (ethtool_value) */ #define ETHTOOL_STXCSUM 0x00000017 /* Set TX hw csum enable (ethtool_value) */ #define ETHTOOL_GSG 0x00000018 /* Get scatter-gather enable * (ethtool_value) */ #define ETHTOOL_SSG 0x00000019 /* Set scatter-gather enable * (ethtool_value), priv. */ #define ETHTOOL_TEST 0x0000001a /* execute NIC self-test, priv. */ #define ETHTOOL_GSTRINGS 0x0000001b /* get specified string set */ #define ETHTOOL_PHYS_ID 0x0000001c /* identify the NIC */ #define ETHTOOL_GSTATS 0x0000001d /* get NIC-specific statistics */ #define ETHTOOL_GTSO 0x0000001e /* Get TSO enable (ethtool_value) */ #define ETHTOOL_STSO 0x0000001f /* Set TSO enable (ethtool_value) */ #define ETHTOOL_GUFO 0x00000021 /* Get UFO enable (ethtool_value) */ #define ETHTOOL_SUFO 0x00000022 /* Set UFO enable (ethtool_value) */ #define ETHTOOL_GGSO 0x00000023 /* Get GSO enable (ethtool_value) */ #define ETHTOOL_SGSO 0x00000024 /* Set GSO enable (ethtool_value) */ /* compatibility with older code */ #define SPARC_ETH_GSET ETHTOOL_GSET #define SPARC_ETH_SSET ETHTOOL_SSET /* Indicates what features are supported by the interface. */ #define SUPPORTED_10baseT_Half (1 << 0) #define SUPPORTED_10baseT_Full (1 << 1) #define SUPPORTED_100baseT_Half (1 << 2) #define SUPPORTED_100baseT_Full (1 << 3) #define SUPPORTED_1000baseT_Half (1 << 4) #define SUPPORTED_1000baseT_Full (1 << 5) #define SUPPORTED_Autoneg (1 << 6) #define SUPPORTED_TP (1 << 7) #define SUPPORTED_AUI (1 << 8) #define SUPPORTED_MII (1 << 9) #define SUPPORTED_FIBRE (1 << 10) #define SUPPORTED_BNC (1 << 11) #define SUPPORTED_10000baseT_Full (1 << 12) /* Indicates what features are advertised by the interface. */ #define ADVERTISED_10baseT_Half (1 << 0) #define ADVERTISED_10baseT_Full (1 << 1) #define ADVERTISED_100baseT_Half (1 << 2) #define ADVERTISED_100baseT_Full (1 << 3) #define ADVERTISED_1000baseT_Half (1 << 4) #define ADVERTISED_1000baseT_Full (1 << 5) #define ADVERTISED_Autoneg (1 << 6) #define ADVERTISED_TP (1 << 7) #define ADVERTISED_AUI (1 << 8) #define ADVERTISED_MII (1 << 9) #define ADVERTISED_FIBRE (1 << 10) #define ADVERTISED_BNC (1 << 11) #define ADVERTISED_10000baseT_Full (1 << 12) /* The following are all involved in forcing a particular link * mode for the device for setting things. When getting the * devices settings, these indicate the current mode and whether * it was foced up into this mode or autonegotiated. */ /* The forced speed, 10Mb, 100Mb, gigabit, 10GbE. */ #define SPEED_10 10 #define SPEED_100 100 #define SPEED_1000 1000 #define SPEED_10000 10000 /* Duplex, half or full. */ #define DUPLEX_HALF 0x00 #define DUPLEX_FULL 0x01 /* Which connector port. */ #define PORT_TP 0x00 #define PORT_AUI 0x01 #define PORT_MII 0x02 #define PORT_FIBRE 0x03 #define PORT_BNC 0x04 /* Which tranceiver to use. */ #define XCVR_INTERNAL 0x00 #define XCVR_EXTERNAL 0x01 #define XCVR_DUMMY1 0x02 #define XCVR_DUMMY2 0x03 #define XCVR_DUMMY3 0x04 /* Enable or disable autonegotiation. If this is set to enable, * the forced link modes above are completely ignored. */ #define AUTONEG_DISABLE 0x00 #define AUTONEG_ENABLE 0x01 /* Wake-On-Lan options. */ #define WAKE_PHY (1 << 0) #define WAKE_UCAST (1 << 1) #define WAKE_MCAST (1 << 2) #define WAKE_BCAST (1 << 3) #define WAKE_ARP (1 << 4) #define WAKE_MAGIC (1 << 5) #define WAKE_MAGICSECURE (1 << 6) /* only meaningful if WAKE_MAGIC */ #endif /* _LINUX_ETHTOOL_H */ python-ethtool-0.7/python-ethtool/ethtool.c000066400000000000000000000633511155103705600212070ustar00rootroot00000000000000/* * Copyright (C) 2008-2011 Red Hat Inc. * * Arnaldo Carvalho de Melo * David Sommerseth * * First bits from a Red Hat config tool by Harald Hoyer. * * 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. */ #include #include #include #include #include #include #include #include #include #include #include "etherinfo_struct.h" #include "etherinfo_obj.h" #include "etherinfo.h" static struct nl_handle *nlconnection = NULL; unsigned int nlconnection_users = 0; /* How many NETLINK users are active? */ extern PyTypeObject ethtool_etherinfoType; extern PyTypeObject ethtool_etherinfoIPv6Type; #ifndef IFF_DYNAMIC #define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses*/ #endif typedef unsigned long long u64; typedef __uint32_t u32; typedef __uint16_t u16; typedef __uint8_t u8; #include "ethtool-copy.h" #include /* for SIOCETHTOOL */ #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) #define _PATH_PROCNET_DEV "/proc/net/dev" static PyObject *get_active_devices(PyObject *self __unused, PyObject *args __unused) { PyObject *list; int numreqs = 30; struct ifconf ifc; struct ifreq *ifr; int n; /* SIOCGIFCONF currently seems to only work properly on AF_INET sockets (as of 2.1.128) */ /* Open control socket. */ int skfd = socket(AF_INET, SOCK_DGRAM, 0); if (skfd < 0) { PyErr_SetString(PyExc_OSError, strerror(errno)); return NULL; } ifc.ifc_buf = NULL; for (;;) { ifc.ifc_len = sizeof(struct ifreq) * numreqs; ifc.ifc_buf = realloc(ifc.ifc_buf, ifc.ifc_len); if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) { PyErr_SetString(PyExc_OSError, strerror(errno)); free(ifc.ifc_buf); close(skfd); return NULL; } if (ifc.ifc_len == (int)sizeof(struct ifreq) * numreqs) { /* assume it overflowed and try again */ numreqs += 10; continue; } break; } list = PyList_New(0); ifr = ifc.ifc_req; for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) { if (!(ioctl(skfd, SIOCGIFFLAGS, ifr) < 0)) if (ifr->ifr_flags & IFF_UP) { PyObject *str = PyString_FromString(ifr->ifr_name); PyList_Append(list, str); Py_DECREF(str); } ifr++; } free(ifc.ifc_buf); close(skfd); return list; } static PyObject *get_devices(PyObject *self __unused, PyObject *args __unused) { char buffer[256]; char *ret;; PyObject *list = PyList_New(0); FILE *fd = fopen(_PATH_PROCNET_DEV, "r"); if (fd == NULL) { PyErr_SetString(PyExc_OSError, strerror(errno)); return NULL; } /* skip over first two lines */ ret = fgets(buffer, 256, fd); ret = fgets(buffer, 256, fd); while (!feof(fd)) { PyObject *str; char *name = buffer; char *end = buffer; if (fgets(buffer, 256, fd) == NULL) break; /* find colon */ while (end && *end != ':') end++; *end = 0; /* terminate where colon was */ while (*name == ' ') name++; /* skip over leading whitespace if any */ str = PyString_FromString(name); PyList_Append(list, str); Py_DECREF(str); } fclose(fd); return list; } static PyObject *get_hwaddress(PyObject *self __unused, PyObject *args) { struct ifreq ifr; int fd, err; char *devname; char hwaddr[20]; if (!PyArg_ParseTuple(args, "s", &devname)) return NULL; /* Setup our request structure. */ memset(&ifr, 0, sizeof(ifr)); strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ); ifr.ifr_name[IFNAMSIZ - 1] = 0; /* Open control socket. */ fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { PyErr_SetString(PyExc_OSError, strerror(errno)); return NULL; } /* Get current settings. */ err = ioctl(fd, SIOCGIFHWADDR, &ifr); if (err < 0) { char buf[2048]; int eno = errno; snprintf(buf, sizeof(buf), "[Errno %d] %s", eno, strerror(eno)); PyErr_SetString(PyExc_IOError, buf); close(fd); return NULL; } close(fd); sprintf(hwaddr, "%02x:%02x:%02x:%02x:%02x:%02x", (unsigned int)ifr.ifr_hwaddr.sa_data[0] % 256, (unsigned int)ifr.ifr_hwaddr.sa_data[1] % 256, (unsigned int)ifr.ifr_hwaddr.sa_data[2] % 256, (unsigned int)ifr.ifr_hwaddr.sa_data[3] % 256, (unsigned int)ifr.ifr_hwaddr.sa_data[4] % 256, (unsigned int)ifr.ifr_hwaddr.sa_data[5] % 256); return PyString_FromString(hwaddr); } static PyObject *get_ipaddress(PyObject *self __unused, PyObject *args) { struct ifreq ifr; int fd, err; char *devname; char ipaddr[20]; if (!PyArg_ParseTuple(args, "s", &devname)) return NULL; /* Setup our request structure. */ memset(&ifr, 0, sizeof(ifr)); strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ); ifr.ifr_name[IFNAMSIZ - 1] = 0; /* Open control socket. */ fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { PyErr_SetString(PyExc_OSError, strerror(errno)); return NULL; } /* Get current settings. */ err = ioctl(fd, SIOCGIFADDR, &ifr); if (err < 0) { char buf[2048]; int eno = errno; snprintf(buf, sizeof(buf), "[Errno %d] %s", eno, strerror(eno)); PyErr_SetString(PyExc_IOError, buf); close(fd); return NULL; } close(fd); sprintf(ipaddr, "%u.%u.%u.%u", (unsigned int)ifr.ifr_addr.sa_data[2] % 256, (unsigned int)ifr.ifr_addr.sa_data[3] % 256, (unsigned int)ifr.ifr_addr.sa_data[4] % 256, (unsigned int)ifr.ifr_addr.sa_data[5] % 256); return PyString_FromString(ipaddr); } /** * Retrieves the current information about all interfaces. All interfaces will be * returned as a list of objects per interface. * * @param self Not used * @param args Python arguments * * @return Python list of objects on success, otherwise NULL. */ static PyObject *get_interfaces_info(PyObject *self __unused, PyObject *args) { PyObject *devlist = NULL, *ethinf_py = NULL; PyObject *inargs = NULL; char **fetch_devs; int i = 0, fetch_devs_len = 0; if (!PyArg_ParseTuple(args, "|O", &inargs)) { PyErr_SetString(PyExc_LookupError, "Argument must be either a string, list or a tuple"); return NULL; } /* Parse input arguments if we got them */ if( inargs != NULL ) { if( PyString_Check(inargs) ) { /* Input argument is just a string */ fetch_devs_len = 1; fetch_devs = calloc(1, sizeof(char *)); fetch_devs[0] = PyString_AsString(inargs); } else if( PyTuple_Check(inargs) ) { /* Input argument is a tuple list with devices */ int j = 0; fetch_devs_len = PyTuple_Size(inargs); fetch_devs = calloc(fetch_devs_len+1, sizeof(char *)); for( i = 0; i < fetch_devs_len; i++ ) { PyObject *elmt = PyTuple_GetItem(inargs, i); if( elmt && PyString_Check(elmt) ) { fetch_devs[j++] = PyString_AsString(elmt); } } fetch_devs_len = j; } else if( PyList_Check(inargs) ) { /* Input argument is a list with devices */ int j = 0; fetch_devs_len = PyList_Size(inargs); fetch_devs = calloc(fetch_devs_len+1, sizeof(char *)); for( i = 0; i < fetch_devs_len; i++ ) { PyObject *elmt = PyList_GetItem(inargs, i); if( elmt && PyString_Check(elmt) ) { fetch_devs[j++] = PyString_AsString(elmt); } } fetch_devs_len = j; } else { PyErr_SetString(PyExc_LookupError, "Argument must be either a string, list or a tuple"); return NULL; } } devlist = PyList_New(0); for( i = 0; i < fetch_devs_len; i++ ) { struct etherinfo_obj_data *objdata = NULL; /* Allocate memory for data structures for each device */ objdata = calloc(1, sizeof(struct etherinfo_obj_data)); if( !objdata ) { PyErr_SetString(PyExc_OSError, strerror(errno)); return NULL; } objdata->ethinfo = calloc(1, sizeof(struct etherinfo)); if( !objdata->ethinfo ) { PyErr_SetString(PyExc_OSError, strerror(errno)); return NULL; } /* Store the device name and a reference to the NETLINK connection for * objects to use when quering for device info */ objdata->ethinfo->device = strdup(fetch_devs[i]); objdata->ethinfo->index = -1; objdata->nlc = &nlconnection; objdata->nlc_users = &nlconnection_users; /* Instantiate a new etherinfo object with the device information */ ethinf_py = PyCObject_FromVoidPtr(objdata, NULL); if( ethinf_py ) { /* Prepare the argument list for the object constructor */ PyObject *args = PyTuple_New(1); PyTuple_SetItem(args, 0, ethinf_py); /* Create the object */ PyObject *dev = PyObject_CallObject((PyObject *)ðtool_etherinfoType, args); if( dev ) { PyList_Append(devlist, dev); Py_DECREF(dev); } Py_DECREF(args); } } if( fetch_devs_len > 0 ) { free(fetch_devs); } return devlist; } static PyObject *get_flags (PyObject *self __unused, PyObject *args) { struct ifreq ifr; char *devname; int fd, err; if (!PyArg_ParseTuple(args, "s", &devname)) return NULL; /* Setup our request structure. */ memset(&ifr, 0, sizeof(ifr)); strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ); ifr.ifr_name[IFNAMSIZ - 1] = 0; /* Open control socket. */ fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { PyErr_SetString(PyExc_OSError, strerror(errno)); return NULL; } err = ioctl(fd, SIOCGIFFLAGS, &ifr); if(err < 0) { char buf[2048]; int eno = errno; snprintf(buf, sizeof(buf), "[Errno %d] %s", eno, strerror(eno)); PyErr_SetString(PyExc_IOError, buf); close(fd); return NULL; } close(fd); return Py_BuildValue("h", ifr.ifr_flags); } static PyObject *get_netmask (PyObject *self __unused, PyObject *args) { struct ifreq ifr; int fd, err; char *devname; char netmask[20]; if (!PyArg_ParseTuple(args, "s", &devname)) return NULL; /* Setup our request structure. */ memset(&ifr, 0, sizeof(ifr)); strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ); ifr.ifr_name[IFNAMSIZ - 1] = 0; /* Open control socket. */ fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { PyErr_SetString(PyExc_OSError, strerror(errno)); return NULL; } /* Get current settings. */ err = ioctl(fd, SIOCGIFNETMASK, &ifr); if (err < 0) { char buf[2048]; int eno = errno; snprintf(buf, sizeof(buf), "[Errno %d] %s", eno, strerror(eno)); PyErr_SetString(PyExc_IOError, buf); close(fd); return NULL; } close(fd); sprintf(netmask, "%u.%u.%u.%u", (unsigned int)ifr.ifr_netmask.sa_data[2] % 256, (unsigned int)ifr.ifr_netmask.sa_data[3] % 256, (unsigned int)ifr.ifr_netmask.sa_data[4] % 256, (unsigned int)ifr.ifr_netmask.sa_data[5] % 256); return PyString_FromString(netmask); } static PyObject *get_broadcast(PyObject *self __unused, PyObject *args) { struct ifreq ifr; int fd, err; char *devname; char broadcast[20]; if (!PyArg_ParseTuple(args, "s", &devname)) return NULL; /* Setup our request structure. */ memset(&ifr, 0, sizeof(ifr)); strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ); ifr.ifr_name[IFNAMSIZ - 1] = 0; /* Open control socket. */ fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { PyErr_SetString(PyExc_OSError, strerror(errno)); return NULL; } /* Get current settings. */ err = ioctl(fd, SIOCGIFBRDADDR, &ifr); if (err < 0) { char buf[2048]; int eno = errno; snprintf(buf, sizeof(buf), "[Errno %d] %s", eno, strerror(eno)); PyErr_SetString(PyExc_IOError, buf); close(fd); return NULL; } close(fd); sprintf(broadcast, "%u.%u.%u.%u", (unsigned int)ifr.ifr_broadaddr.sa_data[2] % 256, (unsigned int)ifr.ifr_broadaddr.sa_data[3] % 256, (unsigned int)ifr.ifr_broadaddr.sa_data[4] % 256, (unsigned int)ifr.ifr_broadaddr.sa_data[5] % 256); return PyString_FromString(broadcast); } static PyObject *get_module(PyObject *self __unused, PyObject *args) { struct ethtool_cmd ecmd; struct ifreq ifr; int fd, err; char buf[2048]; char *devname; if (!PyArg_ParseTuple(args, "s", &devname)) return NULL; /* Setup our control structures. */ memset(&ecmd, 0, sizeof(ecmd)); memset(&ifr, 0, sizeof(ifr)); strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ); ifr.ifr_name[IFNAMSIZ - 1] = 0; ifr.ifr_data = (caddr_t) &buf; ecmd.cmd = ETHTOOL_GDRVINFO; memcpy(&buf, &ecmd, sizeof(ecmd)); /* Open control socket. */ fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { PyErr_SetString(PyExc_OSError, strerror(errno)); return NULL; } /* Get current settings. */ err = ioctl(fd, SIOCETHTOOL, &ifr); if (err < 0) { /* failed? */ int eno = errno; FILE *file; int found = 0; char driver[100], dev[100]; close(fd); /* Before bailing, maybe it is a PCMCIA/PC Card? */ file = fopen("/var/lib/pcmcia/stab", "r"); if (file == NULL) { sprintf(buf, "[Errno %d] %s", eno, strerror(eno)); PyErr_SetString(PyExc_IOError, buf); return NULL; } while (!feof(file)) { if (fgets(buf, 2048, file) == NULL) break; buf[2047] = '\0'; if (strncmp(buf, "Socket", 6) != 0) { if (sscanf(buf, "%*d\t%*s\t%100s\t%*d\t%100s\n", driver, dev) > 0) { driver[99] = '\0'; dev[99] = '\0'; if (strcmp(devname, dev) == 0) { found = 1; break; } } } } fclose(file); if (!found) { sprintf(buf, "[Errno %d] %s", eno, strerror(eno)); PyErr_SetString(PyExc_IOError, buf); return NULL; } else return PyString_FromString(driver); } close(fd); return PyString_FromString(((struct ethtool_drvinfo *)buf)->driver); } static PyObject *get_businfo(PyObject *self __unused, PyObject *args) { struct ethtool_cmd ecmd; struct ifreq ifr; int fd, err; char buf[1024]; char *devname; if (!PyArg_ParseTuple(args, "s", &devname)) return NULL; /* Setup our control structures. */ memset(&ecmd, 0, sizeof(ecmd)); memset(&ifr, 0, sizeof(ifr)); strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ); ifr.ifr_name[IFNAMSIZ - 1] = 0; ifr.ifr_data = (caddr_t) &buf; ecmd.cmd = ETHTOOL_GDRVINFO; memcpy(&buf, &ecmd, sizeof(ecmd)); /* Open control socket. */ fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { PyErr_SetString(PyExc_OSError, strerror(errno)); return NULL; } /* Get current settings. */ err = ioctl(fd, SIOCETHTOOL, &ifr); if (err < 0) { /* failed? */ int eno = errno; close(fd); sprintf(buf, "[Errno %d] %s", eno, strerror(eno)); PyErr_SetString(PyExc_IOError, buf); return NULL; } close(fd); return PyString_FromString(((struct ethtool_drvinfo *)buf)->bus_info); } static int send_command(int cmd, char *devname, void *value) { /* Setup our request structure. */ int fd, err; struct ifreq ifr; struct ethtool_value *eval = value; memset(&ifr, 0, sizeof(ifr)); strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ); ifr.ifr_name[IFNAMSIZ - 1] = 0; ifr.ifr_data = (caddr_t)eval; eval->cmd = cmd; /* Open control socket. */ fd = socket(AF_INET, SOCK_DGRAM, 0), err; if (fd < 0) { PyErr_SetString(PyExc_OSError, strerror(errno)); return -1; } /* Get current settings. */ err = ioctl(fd, SIOCETHTOOL, &ifr); if (err < 0) { char buf[2048]; sprintf(buf, "[Errno %d] %s", errno, strerror(errno)); PyErr_SetString(PyExc_IOError, buf); } close(fd); return err; } static int get_dev_value(int cmd, PyObject *args, void *value) { char *devname; int err = -1; if (PyArg_ParseTuple(args, "s", &devname)) err = send_command(cmd, devname, value); return err; } static int get_dev_int_value(int cmd, PyObject *args, int *value) { struct ethtool_value eval; int rc = get_dev_value(cmd, args, &eval); if (rc == 0) *value = *(int *)&eval.data; return rc; } static int dev_set_int_value(int cmd, PyObject *args) { struct ethtool_value eval; char *devname; if (!PyArg_ParseTuple(args, "si", &devname, &eval.data)) return -1; return send_command(cmd, devname, &eval); } static PyObject *get_tso(PyObject *self __unused, PyObject *args) { int value = 0; if (get_dev_int_value(ETHTOOL_GTSO, args, &value) < 0) return NULL; return Py_BuildValue("b", value); } static PyObject *set_tso(PyObject *self __unused, PyObject *args) { if (dev_set_int_value(ETHTOOL_STSO, args) < 0) return NULL; Py_INCREF(Py_None); return Py_None; } static PyObject *get_ufo(PyObject *self __unused, PyObject *args) { int value = 0; if (get_dev_int_value(ETHTOOL_GUFO, args, &value) < 0) return NULL; return Py_BuildValue("b", value); } static PyObject *get_gso(PyObject *self __unused, PyObject *args) { int value = 0; if (get_dev_int_value(ETHTOOL_GGSO, args, &value) < 0) return NULL; return Py_BuildValue("b", value); } static PyObject *get_sg(PyObject *self __unused, PyObject *args) { int value = 0; if (get_dev_int_value(ETHTOOL_GSG, args, &value) < 0) return NULL; return Py_BuildValue("b", value); } struct struct_desc { char *name; unsigned short offset; unsigned short size; }; #define member_desc(type, member_name) { \ .name = #member_name, \ .offset = offsetof(type, member_name), \ .size = sizeof(((type *)0)->member_name), } struct struct_desc ethtool_coalesce_desc[] = { member_desc(struct ethtool_coalesce, rx_coalesce_usecs), member_desc(struct ethtool_coalesce, rx_max_coalesced_frames), member_desc(struct ethtool_coalesce, rx_coalesce_usecs_irq), member_desc(struct ethtool_coalesce, rx_max_coalesced_frames_irq), member_desc(struct ethtool_coalesce, tx_coalesce_usecs), member_desc(struct ethtool_coalesce, tx_max_coalesced_frames), member_desc(struct ethtool_coalesce, tx_coalesce_usecs_irq), member_desc(struct ethtool_coalesce, tx_max_coalesced_frames_irq), member_desc(struct ethtool_coalesce, stats_block_coalesce_usecs), member_desc(struct ethtool_coalesce, use_adaptive_rx_coalesce), member_desc(struct ethtool_coalesce, use_adaptive_tx_coalesce), member_desc(struct ethtool_coalesce, pkt_rate_low), member_desc(struct ethtool_coalesce, rx_coalesce_usecs_low), member_desc(struct ethtool_coalesce, rx_max_coalesced_frames_low), member_desc(struct ethtool_coalesce, tx_coalesce_usecs_low), member_desc(struct ethtool_coalesce, tx_max_coalesced_frames_low), member_desc(struct ethtool_coalesce, pkt_rate_high), member_desc(struct ethtool_coalesce, rx_coalesce_usecs_high), member_desc(struct ethtool_coalesce, rx_max_coalesced_frames_high), member_desc(struct ethtool_coalesce, tx_coalesce_usecs_high), member_desc(struct ethtool_coalesce, tx_max_coalesced_frames_high), member_desc(struct ethtool_coalesce, rate_sample_interval), }; static PyObject *__struct_desc_create_dict(struct struct_desc *table, int nr_entries, void *values) { int i; PyObject *dict = PyDict_New(); if (dict == NULL) goto out; for (i = 0; i < nr_entries; ++i) { struct struct_desc *d = &table[i]; PyObject *objval = NULL; void *val = values + d->offset; switch (d->size) { case sizeof(uint32_t): objval = PyInt_FromLong(*(uint32_t *)val); break; } if (objval == NULL) goto free_dict; if (PyDict_SetItemString(dict, d->name, objval) != 0) { Py_DECREF(objval); goto free_dict; } Py_DECREF(objval); } out: return dict; free_dict: goto out; dict = NULL; } #define struct_desc_create_dict(table, values) \ __struct_desc_create_dict(table, ARRAY_SIZE(table), values) static int __struct_desc_from_dict(struct struct_desc *table, int nr_entries, void *to, PyObject *dict) { char buf[2048]; int i; for (i = 0; i < nr_entries; ++i) { struct struct_desc *d = &table[i]; void *val = to + d->offset; PyObject *obj; switch (d->size) { case sizeof(uint32_t): obj = PyDict_GetItemString(dict, d->name); if (obj == NULL) { snprintf(buf, sizeof(buf), "Missing dict entry for field %s", d->name); PyErr_SetString(PyExc_IOError, buf); return -1; } *(uint32_t *)val = PyInt_AsLong(obj); break; default: snprintf(buf, sizeof(buf), "Invalid type size %d for field %s", d->size, d->name); PyErr_SetString(PyExc_IOError, buf); return -1; } } return 0; } #define struct_desc_from_dict(table, to, dict) \ __struct_desc_from_dict(table, ARRAY_SIZE(table), to, dict) static PyObject *get_coalesce(PyObject *self __unused, PyObject *args) { struct ethtool_coalesce coal; if (get_dev_value(ETHTOOL_GCOALESCE, args, &coal) < 0) return NULL; return struct_desc_create_dict(ethtool_coalesce_desc, &coal); } static PyObject *set_coalesce(PyObject *self __unused, PyObject *args) { struct ethtool_coalesce coal; char *devname; PyObject *dict; if (!PyArg_ParseTuple(args, "sO", &devname, &dict)) return NULL; if (struct_desc_from_dict(ethtool_coalesce_desc, &coal, dict) != 0) return NULL; if (send_command(ETHTOOL_SCOALESCE, devname, &coal)) return NULL; Py_INCREF(Py_None); return Py_None; } struct struct_desc ethtool_ringparam_desc[] = { member_desc(struct ethtool_ringparam, rx_max_pending), member_desc(struct ethtool_ringparam, rx_mini_max_pending), member_desc(struct ethtool_ringparam, rx_jumbo_max_pending), member_desc(struct ethtool_ringparam, tx_max_pending), member_desc(struct ethtool_ringparam, rx_pending), member_desc(struct ethtool_ringparam, rx_mini_pending), member_desc(struct ethtool_ringparam, rx_jumbo_pending), member_desc(struct ethtool_ringparam, tx_pending), }; static PyObject *get_ringparam(PyObject *self __unused, PyObject *args) { struct ethtool_ringparam ring; if (get_dev_value(ETHTOOL_GRINGPARAM, args, &ring) < 0) return NULL; return struct_desc_create_dict(ethtool_ringparam_desc, &ring); } static PyObject *set_ringparam(PyObject *self __unused, PyObject *args) { struct ethtool_ringparam ring; char *devname; PyObject *dict; if (!PyArg_ParseTuple(args, "sO", &devname, &dict)) return NULL; if (struct_desc_from_dict(ethtool_ringparam_desc, &ring, dict) != 0) return NULL; if (send_command(ETHTOOL_SRINGPARAM, devname, &ring)) return NULL; Py_INCREF(Py_None); return Py_None; } static struct PyMethodDef PyEthModuleMethods[] = { { .ml_name = "get_module", .ml_meth = (PyCFunction)get_module, .ml_flags = METH_VARARGS, }, { .ml_name = "get_businfo", .ml_meth = (PyCFunction)get_businfo, .ml_flags = METH_VARARGS, }, { .ml_name = "get_hwaddr", .ml_meth = (PyCFunction)get_hwaddress, .ml_flags = METH_VARARGS, }, { .ml_name = "get_ipaddr", .ml_meth = (PyCFunction)get_ipaddress, .ml_flags = METH_VARARGS, }, { .ml_name = "get_interfaces_info", .ml_meth = (PyCFunction)get_interfaces_info, .ml_flags = METH_VARARGS, .ml_doc = "Accepts a string, list or tupples of interface names. " "Returns a list of ethtool.etherinfo objets with device information." }, { .ml_name = "get_netmask", .ml_meth = (PyCFunction)get_netmask, .ml_flags = METH_VARARGS, }, { .ml_name = "get_broadcast", .ml_meth = (PyCFunction)get_broadcast, .ml_flags = METH_VARARGS, }, { .ml_name = "get_coalesce", .ml_meth = (PyCFunction)get_coalesce, .ml_flags = METH_VARARGS, }, { .ml_name = "set_coalesce", .ml_meth = (PyCFunction)set_coalesce, .ml_flags = METH_VARARGS, }, { .ml_name = "get_devices", .ml_meth = (PyCFunction)get_devices, .ml_flags = METH_VARARGS, }, { .ml_name = "get_active_devices", .ml_meth = (PyCFunction)get_active_devices, .ml_flags = METH_VARARGS, }, { .ml_name = "get_ringparam", .ml_meth = (PyCFunction)get_ringparam, .ml_flags = METH_VARARGS, }, { .ml_name = "set_ringparam", .ml_meth = (PyCFunction)set_ringparam, .ml_flags = METH_VARARGS, }, { .ml_name = "get_tso", .ml_meth = (PyCFunction)get_tso, .ml_flags = METH_VARARGS, }, { .ml_name = "set_tso", .ml_meth = (PyCFunction)set_tso, .ml_flags = METH_VARARGS, }, { .ml_name = "get_ufo", .ml_meth = (PyCFunction)get_ufo, .ml_flags = METH_VARARGS, }, { .ml_name = "get_gso", .ml_meth = (PyCFunction)get_gso, .ml_flags = METH_VARARGS, }, { .ml_name = "get_sg", .ml_meth = (PyCFunction)get_sg, .ml_flags = METH_VARARGS, }, { .ml_name = "get_flags", .ml_meth = (PyCFunction)get_flags, .ml_flags = METH_VARARGS, }, { .ml_name = NULL, }, }; PyMODINIT_FUNC initethtool(void) { PyObject *m; m = Py_InitModule3("ethtool", PyEthModuleMethods, "Python ethtool module"); // Prepare the ethtool.etherinfo class if (PyType_Ready(ðtool_etherinfoType) < 0) return; Py_INCREF(ðtool_etherinfoType); PyModule_AddObject(m, "etherinfo", (PyObject *)ðtool_etherinfoType); // Prepare the ethtool.etherinfo_ipv6addr class if (PyType_Ready(ðtool_etherinfoIPv6Type) < 0) return; Py_INCREF(ðtool_etherinfoIPv6Type); PyModule_AddObject(m, "etherinfo_ipv6addr", (PyObject *)ðtool_etherinfoIPv6Type); // Setup constants PyModule_AddIntConstant(m, "IFF_UP", IFF_UP); /* Interface is up. */ PyModule_AddIntConstant(m, "IFF_BROADCAST", IFF_BROADCAST); /* Broadcast address valid. */ PyModule_AddIntConstant(m, "IFF_DEBUG", IFF_DEBUG); /* Turn on debugging. */ PyModule_AddIntConstant(m, "IFF_LOOPBACK", IFF_LOOPBACK); /* Is a loopback net */ PyModule_AddIntConstant(m, "IFF_POINTOPOINT", IFF_POINTOPOINT); /* Is a point-to-point link */ PyModule_AddIntConstant(m, "IFF_NOTRAILERS", IFF_NOTRAILERS); /* Avoid use of trailers */ PyModule_AddIntConstant(m, "IFF_RUNNING", IFF_RUNNING); /* Resources allocated */ PyModule_AddIntConstant(m, "IFF_NOARP", IFF_NOARP); /* No address resolution protocol. */ PyModule_AddIntConstant(m, "IFF_PROMISC", IFF_PROMISC); /* Receive all packets. */ PyModule_AddIntConstant(m, "IFF_ALLMULTI", IFF_ALLMULTI); /* Receive all multicast packets. */ PyModule_AddIntConstant(m, "IFF_MASTER", IFF_MASTER); /* Master of a load balancer. */ PyModule_AddIntConstant(m, "IFF_SLAVE", IFF_SLAVE); /* Slave of a load balancer. */ PyModule_AddIntConstant(m, "IFF_MULTICAST", IFF_MULTICAST); /* Supports multicast. */ PyModule_AddIntConstant(m, "IFF_PORTSEL", IFF_PORTSEL); /* Can set media type. */ PyModule_AddIntConstant(m, "IFF_AUTOMEDIA", IFF_AUTOMEDIA); /* Auto media select active. */ PyModule_AddIntConstant(m, "IFF_DYNAMIC", IFF_DYNAMIC); /* Dialup device with changing addresses. */ PyModule_AddIntConstant(m, "AF_INET", AF_INET); /* IPv4 interface */ PyModule_AddIntConstant(m, "AF_INET6", AF_INET6); /* IPv6 interface */ PyModule_AddStringConstant(m, "version", "python-ethtool v" VERSION); } python-ethtool-0.7/rpm/000077500000000000000000000000001155103705600151565ustar00rootroot00000000000000python-ethtool-0.7/rpm/SPECS/000077500000000000000000000000001155103705600160335ustar00rootroot00000000000000python-ethtool-0.7/rpm/SPECS/python-ethtool.spec000066400000000000000000000056221155103705600217110ustar00rootroot00000000000000%{!?python_sitearch: %define python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")} %{!?python_ver: %define python_ver %(%{__python} -c "import sys ; print sys.version[:3]")} Summary: Ethernet settings python bindings Name: python-ethtool Version: 0.6 Release: 1%{?dist} URL: http://fedorapeople.org/gitweb?p=dsommers/public_git/python-ethtool.git;a=summary Source: http://dsommers.fedorapeople.org/python-ethtool/%{name}-%{version}.tar.bz2 License: GPLv2 Group: System Environment/Libraries BuildRequires: python-devel libnl-devel BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) %description Python bindings for the ethtool kernel interface, that allows querying and changing of Ethernet card settings, such as speed, port, auto-negotiation, and PCI locations. %prep %setup -q %build %{__python} setup.py build %install rm -rf %{buildroot} %{__python} setup.py install --skip-build --root %{buildroot} mkdir -p %{buildroot}%{_sbindir} cp -p pethtool.py %{buildroot}%{_sbindir}/pethtool cp -p pifconfig.py %{buildroot}%{_sbindir}/pifconfig %clean rm -rf %{buildroot} %files %defattr(-,root,root) %doc COPYING %{_sbindir}/pethtool %{_sbindir}/pifconfig %{python_sitearch}/ethtool.so %if "%{python_ver}" >= "2.5" %{python_sitearch}/*.egg-info %endif %changelog * Wed Jan 19 2011 David Sommerseth - 0.6-1 - Don't segfault if we don't receive any address from rtnl_link_get_addr() - Remove errornous file from MANIFEST - Added ethtool.version string constant - Avoid duplicating IPv6 address information - import sys module in setup.py (Miroslav Suchy) * Mon Aug 9 2010 David Sommerseth - 0.5-1 - Fixed double free issue (commit c52ed2cbdc5b851ebc7b) * Wed Apr 28 2010 David Sommerseth - 0.4-1 - David Sommerseth is now taking over the maintenance of python-ethtool - New URLs for upstream source code - Added new API: ethtool.get_interfaces_info() - returns list of etherinfo objects - Added support retrieving for IPv6 address, using etherinfo::get_ipv6_addresses() * Fri Sep 5 2008 Arnaldo Carvalho de Melo - 0.3-2 - Rewrote build and install sections as part of the fedora review process BZ #459549 * Tue Aug 26 2008 Arnaldo Carvalho de Melo - 0.3-1 - Add get_flags method from the first python-ethtool contributor, yay - Add pifconfig command, that mimics the ifconfig tool using the bindings available * Wed Aug 20 2008 Arnaldo Carvalho de Melo - 0.2-1 - Expand description and summary fields, as part of the fedora review process. * Tue Jun 10 2008 Arnaldo Carvalho de Melo - 0.1-3 - add dist to the release tag * Tue Dec 18 2007 Arnaldo Carvalho de Melo - 0.1-2 - First build into MRG repo * Tue Dec 18 2007 Arnaldo Carvalho de Melo - 0.1-1 - Get ethtool code from rhpl 0.212 python-ethtool-0.7/setup.py000066400000000000000000000045111155103705600160730ustar00rootroot00000000000000#!/usr/bin/python2 from distutils.core import setup, Extension import commands import sys version = '0.7' ethtool = Extension('ethtool', sources = ['python-ethtool/ethtool.c', 'python-ethtool/etherinfo.c', 'python-ethtool/etherinfo_obj.c']) def pkgconfig(pkg): def _str2list(pkgstr, onlystr): res = [] for l in pkgstr.split(" "): if l.find(onlystr) == 0: res.append(l.replace(onlystr, "", 1)) return res (res, cflags) = commands.getstatusoutput('pkg-config --cflags-only-other %s' % pkg) if res != 0: print 'Failed to query pkg-config --cflags-only-other %s' % pkg sys.exit(1) (res, includes) = commands.getstatusoutput('pkg-config --cflags-only-I %s' % pkg) if res != 0: print 'Failed to query pkg-config --cflags-only-I %s' % pkg sys.exit(1) (res, libs) = commands.getstatusoutput('pkg-config --libs-only-l %s' % pkg) if res != 0: print 'Failed to query pkg-config --libs-only-l %s' % pkg sys.exit(1) (res, libdirs) = commands.getstatusoutput('pkg-config --libs-only-L %s' % pkg) if res != 0: print 'Failed to query pkg-config --libs-only-L %s' % pkg sys.exit(1) # Clean up the results and return what we've extracted from pkg-config return {'cflags': cflags, 'include': _str2list(includes, '-I'), 'libs': _str2list(libs, '-l'), 'libdirs': _str2list(libdirs, '-L') } libnl = pkgconfig('libnl-1') # don't reformat this line, Makefile parses it setup(name='ethtool', version=version, description='Python module to interface with ethtool', author='Harald Hoyer, Arnaldo Carvalho de Melo, David Sommerseth', author_email='davids@redhat.com', url='http://fedoraproject.org/wiki/python-ethtool', ext_modules=[ Extension( 'ethtool', sources = [ 'python-ethtool/ethtool.c', 'python-ethtool/etherinfo.c', 'python-ethtool/etherinfo_obj.c', 'python-ethtool/etherinfo_ipv6_obj.c'], include_dirs = libnl['include'], library_dirs = libnl['libdirs'], libraries = libnl['libs'], define_macros = [('VERSION', '"%s"' % version)] ) ] )