summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Poessinger <christian@poessinger.com>2021-08-31 23:03:01 +0200
committerChristian Poessinger <christian@poessinger.com>2021-08-31 23:36:14 +0200
commitb0d4112bd6073e4a947869c3bd80f8e87783fbfa (patch)
treec8266c7b3c60625072eec0706d89ad0ab37cf4a5
parent56fa0d4baaeb7624918d77172fa7e1500d694b93 (diff)
downloadvyos-1x-b0d4112bd6073e4a947869c3bd80f8e87783fbfa.tar.gz
vyos-1x-b0d4112bd6073e4a947869c3bd80f8e87783fbfa.zip
vyos.ethtool: T3163: purify code to read and change flow-control settings
It makes no sense to have a parser for the ethtool values in ethtool.py and ethernet.py - one instance ios more then enough! (cherry picked from commit 0229645c8248decb5664056df8aa5cd5dff41802)
-rw-r--r--python/vyos/ethtool.py23
-rw-r--r--python/vyos/ifconfig/ethernet.py42
-rwxr-xr-xsrc/conf_mode/interfaces-ethernet.py4
-rwxr-xr-xsrc/migration-scripts/interfaces/20-to-218
4 files changed, 45 insertions, 32 deletions
diff --git a/python/vyos/ethtool.py b/python/vyos/ethtool.py
index f5796358d..87b9d7dd0 100644
--- a/python/vyos/ethtool.py
+++ b/python/vyos/ethtool.py
@@ -46,6 +46,8 @@ class Ethtool:
_ring_buffers_max = { }
_driver_name = None
_auto_negotiation = None
+ _flow_control = None
+ _flow_control_enabled = None
def __init__(self, ifname):
# Get driver used for interface
@@ -123,6 +125,15 @@ class Ethtool:
if value.isdigit():
self._ring_buffers[key] = int(value)
+ # 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}')
+ 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]
+
def _get_generic(self, feature):
"""
Generic method to read self._features and return a tuple for feature
@@ -186,5 +197,17 @@ class Ethtool:
return True
return False
+ def check_flow_control(self):
+ """ Check if the NIC supports flow-control """
+ if self._driver_name in ['vmxnet3', 'virtio_net', 'xen_netfront']:
+ return False
+ return self._flow_control
+
+ def get_flow_control(self):
+ if self._flow_control_enabled == None:
+ raise ValueError('Interface does not support changing '\
+ 'flow-control settings!')
+ return self._flow_control_enabled
+
def get_auto_negotiation(self):
return self._auto_negotiation
diff --git a/python/vyos/ifconfig/ethernet.py b/python/vyos/ifconfig/ethernet.py
index 5974a3d8f..cb07693c3 100644
--- a/python/vyos/ifconfig/ethernet.py
+++ b/python/vyos/ifconfig/ethernet.py
@@ -122,38 +122,16 @@ class EthernetIf(Interface):
'flow control settings!')
return
- # Get current flow control settings:
- cmd = f'ethtool --show-pause {ifname}'
- output, code = self._popen(cmd)
- if code == 76:
- # the interface does not support it
- return ''
- if code:
- # never fail here as it prevent vyos to boot
- print(f'unexpected return code {code} from {cmd}')
- return ''
-
- # The above command returns - with tabs:
- #
- # Pause parameters for eth0:
- # Autonegotiate: on
- # RX: off
- # TX: off
- if re.search("Autonegotiate:\ton", output):
- if enable == "on":
- # flowcontrol is already enabled - no need to re-enable it again
- # this will prevent the interface from flapping as applying the
- # flow-control settings will take the interface down and bring
- # it back up every time.
- return ''
-
- # Assemble command executed on system. Unfortunately there is no way
- # to change this setting via sysfs
- cmd = f'ethtool --pause {ifname} autoneg {enable} tx {enable} rx {enable}'
- output, code = self._popen(cmd)
- if code:
- print(f'could not set flowcontrol for {ifname}')
- return output
+ current = self.ethtool.get_flow_control()
+ if current != enable:
+ # Assemble command executed on system. Unfortunately there is no way
+ # to change this setting via sysfs
+ cmd = f'ethtool --pause {ifname} autoneg {enable} tx {enable} rx {enable}'
+ output, code = self._popen(cmd)
+ if code:
+ print(f'Could not set flowcontrol for {ifname}')
+ return output
+ return None
def set_speed_duplex(self, speed, duplex):
"""
diff --git a/src/conf_mode/interfaces-ethernet.py b/src/conf_mode/interfaces-ethernet.py
index f3f3fede8..6e0d8c4e8 100755
--- a/src/conf_mode/interfaces-ethernet.py
+++ b/src/conf_mode/interfaces-ethernet.py
@@ -78,6 +78,10 @@ def verify(ethernet):
raise ConfigError(f'Adapter does not support changing speed and duplex '\
f'settings to: {speed}/{duplex}!')
+ if 'disable_flow_control' in ethernet:
+ if not ethtool.check_flow_control():
+ raise ConfigError('Adapter does not support changing flow-control settings!')
+
if 'ring_buffer' in ethernet:
max_rx = ethtool.get_ring_buffer_max('rx')
if not max_rx:
diff --git a/src/migration-scripts/interfaces/20-to-21 b/src/migration-scripts/interfaces/20-to-21
index bd89dcdb4..0bd858760 100755
--- a/src/migration-scripts/interfaces/20-to-21
+++ b/src/migration-scripts/interfaces/20-to-21
@@ -104,6 +104,14 @@ for ifname in config.list_nodes(base):
config.delete(speed_path)
config.delete(duplex_path)
+ # Also while processing the interface configuration, not all adapters support
+ # changing disabling flow-control - or change this setting. If disabling
+ # flow-control is not supported by the NIC, we remove the setting from CLI
+ flow_control_path = base + [ifname, 'disable-flow-control']
+ if config.exists(flow_control_path):
+ if not eth.check_flow_control():
+ config.delete(flow_control_path)
+
try:
with open(file_name, 'w') as f:
f.write(config.to_string())