Skip to content

Commit

Permalink
ethernet: T5566: disable energy efficient ethernet (EEE) for interfaces
Browse files Browse the repository at this point in the history
VyOS is a routing (packet pushing) platform, thus supporting EEE which
potentially causes issues is not a good idea. Some recent Intel drivers enable
EEE by default, thus we will disable this for every NIC supporting EEE.

(cherry picked from commit ab30509)
  • Loading branch information
c-po authored and mergify[bot] committed Dec 25, 2023
1 parent 7f16fff commit 1d1b303
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 5 deletions.
34 changes: 29 additions & 5 deletions python/vyos/ethtool.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
_drivers_without_speed_duplex_flow = ['vmxnet3', 'virtio_net', 'xen_netfront',
'iavf', 'ice', 'i40e', 'hv_netvsc', 'veth', 'ixgbevf',
'tun']
_drivers_without_eee = ['vmxnet3', 'virtio_net', 'xen_netfront', 'hv_netvsc']

class Ethtool:
"""
Expand Down Expand Up @@ -55,16 +56,18 @@ class Ethtool:
_auto_negotiation_supported = None
_flow_control = False
_flow_control_enabled = None
_eee = False
_eee_enabled = None

def __init__(self, ifname):
# Get driver used for interface
out, err = popen(f'ethtool --driver {ifname}')
out, _ = popen(f'ethtool --driver {ifname}')
driver = re.search(r'driver:\s(\w+)', out)
if driver:
self._driver_name = driver.group(1)

# Build a dictinary of supported link-speed and dupley settings.
out, err = popen(f'ethtool {ifname}')
out, _ = popen(f'ethtool {ifname}')
reading = False
pattern = re.compile(r'\d+base.*')
for line in out.splitlines()[1:]:
Expand Down Expand Up @@ -95,7 +98,7 @@ def __init__(self, ifname):
self._auto_negotiation = bool(tmp == 'on')

# Now populate features dictionaty
out, err = popen(f'ethtool --show-features {ifname}')
out, _ = popen(f'ethtool --show-features {ifname}')
# skip the first line, it only says: "Features for eth0":
for line in out.splitlines()[1:]:
if ":" in line:
Expand All @@ -108,7 +111,7 @@ def __init__(self, ifname):
'fixed' : fixed
}

out, err = popen(f'ethtool --show-ring {ifname}')
out, _ = popen(f'ethtool --show-ring {ifname}')
# We are only interested in line 2-5 which contains the device maximum
# ringbuffers
for line in out.splitlines()[2:6]:
Expand All @@ -133,13 +136,22 @@ def __init__(self, ifname):

# Get current flow control settings, but this is not supported by
# all NICs (e.g. vmxnet3 does not support is)
out, err = popen(f'ethtool --show-pause {ifname}')
out, _ = popen(f'ethtool --show-pause {ifname}')
if len(out.splitlines()) > 1:
self._flow_control = True
# read current flow control setting, this returns:
# ['Autonegotiate:', 'on']
self._flow_control_enabled = out.splitlines()[1].split()[-1]

# Get current Energy Efficient Ethernet (EEE) settings, but this is
# not supported by all NICs (e.g. vmxnet3 does not support is)
out, _ = popen(f'ethtool --show-eee {ifname}')
if len(out.splitlines()) > 1:
self._eee = True
# read current EEE setting, this returns:
# EEE status: disabled || EEE status: enabled - inactive || EEE status: enabled - active
self._eee_enabled = bool('enabled' in out.splitlines()[2])

def check_auto_negotiation_supported(self):
""" Check if the NIC supports changing auto-negotiation """
return self._auto_negotiation_supported
Expand Down Expand Up @@ -227,3 +239,15 @@ def get_flow_control(self):
raise ValueError('Interface does not support changing '\
'flow-control settings!')
return self._flow_control_enabled

def check_eee(self):
""" Check if the NIC supports eee """
if self.get_driver_name() in _drivers_without_eee:
return False
return self._eee

def get_eee(self):
if self._eee_enabled == None:
raise ValueError('Interface does not support changing '\
'EEE settings!')
return self._eee_enabled
31 changes: 31 additions & 0 deletions python/vyos/ifconfig/ethernet.py
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,34 @@ def set_ring_buffer(self, rx_tx, size):
print(f'could not set "{rx_tx}" ring-buffer for {ifname}')
return output

def set_eee(self, enable):
"""
Enable/Disable Energy Efficient Ethernet (EEE) settings
Example:
>>> from vyos.ifconfig import EthernetIf
>>> i = EthernetIf('eth0')
>>> i.set_eee(enable=False)
"""
if not isinstance(enable, bool):
raise ValueError('Value out of range')

if not self.ethtool.check_eee():
self._debug_msg(f'NIC driver does not support changing EEE settings!')
return False

current = self.ethtool.get_eee()
if current != enable:
# Assemble command executed on system. Unfortunately there is no way
# to change this setting via sysfs
cmd = f'ethtool --set-eee {self.ifname} eee '
cmd += 'on' if enable else 'off'
output, code = self._popen(cmd)
if code:
Warning(f'could not change "{self.ifname}" EEE setting!')
return output
return None

def update(self, config):
""" General helper function which works on a dictionary retrived by
get_config_dict(). It's main intention is to consolidate the scattered
Expand All @@ -409,6 +437,9 @@ def update(self, config):
value = 'off' if 'disable_flow_control' in config else 'on'
self.set_flow_control(value)

# Always disable Energy Efficient Ethernet
self.set_eee(False)

# GRO (generic receive offload)
self.set_gro(dict_search('offload.gro', config) != None)

Expand Down

0 comments on commit 1d1b303

Please sign in to comment.