Blame libnmstate/ethtool.py

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