Blame libnmstate/ethtool.py

Packit b9ca78
#
Packit b9ca78
# Copyright (c) 2018-2019 Red Hat, Inc.
Packit b9ca78
#
Packit b9ca78
# This file is part of nmstate
Packit b9ca78
#
Packit b9ca78
# This program is free software: you can redistribute it and/or modify
Packit b9ca78
# it under the terms of the GNU Lesser General Public License as published by
Packit b9ca78
# the Free Software Foundation, either version 2.1 of the License, or
Packit b9ca78
# (at your option) any later version.
Packit b9ca78
#
Packit b9ca78
# This program is distributed in the hope that it will be useful,
Packit b9ca78
# but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit b9ca78
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit b9ca78
# GNU Lesser General Public License for more details.
Packit b9ca78
#
Packit b9ca78
# You should have received a copy of the GNU Lesser General Public License
Packit b9ca78
# along with this program. If not, see <https://www.gnu.org/licenses/>.
Packit b9ca78
#
Packit b9ca78
""" Minimal wrapper around the SIOCETHTOOL IOCTL to provide data that Network
Packit b9ca78
Manager is not yet providing.
Packit b9ca78
Packit b9ca78
https://bugzilla.redhat.com/show_bug.cgi?id=1621188
Packit b9ca78
"""
Packit b9ca78
Packit b9ca78
import array
Packit b9ca78
import struct
Packit b9ca78
import fcntl
Packit b9ca78
import socket
Packit b9ca78
Packit b9ca78
ETHTOOL_GSET = 0x00000001  # Get settings
Packit b9ca78
SIOCETHTOOL = 0x8946
Packit b9ca78
Packit b9ca78
Packit b9ca78
def minimal_ethtool(interface):
Packit b9ca78
    """
Packit b9ca78
    Return dictionary with speed, duplex and auto-negotiation settings for the
Packit b9ca78
    specified interface using the ETHTOOL_GSET command. The speed is returned n
Packit b9ca78
    MBit/s, 0 means that the speed could not be determined. The duplex setting
Packit b9ca78
    is 'unknown', 'full' or 'half. The auto-negotiation setting True or False
Packit b9ca78
    or None if it could not be determined.
Packit b9ca78
Packit b9ca78
    Based on:
Packit b9ca78
    https://github.com/rlisagor/pynetlinux/blob/master/pynetlinux/ifconfig.py
Packit b9ca78
    https://elixir.bootlin.com/linux/v4.19-rc1/source/include/uapi/linux/ethtool.h
Packit b9ca78
Packit b9ca78
    :param interface str: Name of interface
Packit b9ca78
    :returns dict: Dictionary with the keys speed, duplex, auto-negotiation
Packit b9ca78
Packit b9ca78
    """
Packit b9ca78
    try:
Packit b9ca78
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Packit b9ca78
        sockfd = sock.fileno()
Packit b9ca78
Packit b9ca78
        ecmd = array.array(
Packit b9ca78
            "B", struct.pack("I39s", ETHTOOL_GSET, b"\x00" * 39)
Packit b9ca78
        )
Packit b9ca78
Packit b9ca78
        interface = interface.encode("utf-8")
Packit b9ca78
        ifreq = struct.pack("16sP", interface, ecmd.buffer_info()[0])
Packit b9ca78
Packit b9ca78
        fcntl.ioctl(sockfd, SIOCETHTOOL, ifreq)
Packit b9ca78
        res = ecmd.tobytes()
Packit b9ca78
        speed, duplex, auto = struct.unpack("12xHB3xB24x", res)
Packit b9ca78
    except IOError:
Packit b9ca78
        speed, duplex, auto = 65535, 255, 255
Packit b9ca78
    finally:
Packit b9ca78
        sock.close()
Packit b9ca78
Packit b9ca78
    if speed == 65535:
Packit b9ca78
        speed = 0
Packit b9ca78
Packit b9ca78
    if duplex == 255:
Packit b9ca78
        duplex = "unknown"
Packit b9ca78
    else:
Packit b9ca78
        duplex = "full" if bool(duplex) else "half"
Packit b9ca78
Packit b9ca78
    if auto == 255:
Packit b9ca78
        auto = None
Packit b9ca78
    else:
Packit b9ca78
        auto = bool(auto)
Packit b9ca78
Packit b9ca78
    return {"speed": speed, "duplex": duplex, "auto-negotiation": auto}