Page MenuHomeVyOS Platform

No OneTemporary

Size
25 KB
Referenced Files
None
Subscribers
None
diff --git a/op-mode-definitions/show-interfaces-ethernet.xml.in b/op-mode-definitions/show-interfaces-ethernet.xml.in
index fc79f44bf..6d50d6e90 100644
--- a/op-mode-definitions/show-interfaces-ethernet.xml.in
+++ b/op-mode-definitions/show-interfaces-ethernet.xml.in
@@ -1,97 +1,97 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="show">
<children>
<node name="interfaces">
<children>
<tagNode name="ethernet">
<properties>
<help>Show ethernet interface information</help>
<completionHelp>
<path>interfaces ethernet</path>
</completionHelp>
</properties>
<command>${vyos_op_scripts_dir}/show_interfaces.py --intf="$4"</command>
<children>
<leafNode name="brief">
<properties>
<help>Show summary of the specified ethernet interface information</help>
</properties>
<command>${vyos_op_scripts_dir}/show_interfaces.py --intf="$4" --action=show-brief</command>
</leafNode>
<leafNode name="identify">
<properties>
<help>Visually identify specified ethernet interface</help>
</properties>
- <command>echo "Blinking interface $4 for 30 seconds."; /sbin/ethtool --identify "$4" 30</command>
+ <command>echo "Blinking interface $4 for 30 seconds."; ethtool --identify "$4" 30</command>
</leafNode>
<node name="physical">
<properties>
<help>Show physical device information for specified ethernet interface</help>
</properties>
- <command>/sbin/ethtool "$4"; /sbin/ethtool -i "$4"</command>
+ <command>ethtool "$4"; ethtool --driver "$4"</command>
<children>
<leafNode name="offload">
<properties>
<help>Show physical device offloading capabilities</help>
</properties>
- <command>/sbin/ethtool -k "$4" | sed -e 1d -e '/fixed/d' -e 's/^\t*//g' -e 's/://' | column -t -s' '</command>
+ <command>ethtool --show-features "$4" | sed -e 1d -e '/fixed/d' -e 's/^\t*//g' -e 's/://' | column -t -s' '</command>
</leafNode>
</children>
</node>
<leafNode name="statistics">
<properties>
<help>Show physical device statistics for specified ethernet interface</help>
</properties>
- <command>/sbin/ethtool -S "$4"</command>
+ <command>ethtool --statistics "$4"</command>
</leafNode>
<leafNode name="transceiver">
<properties>
<help>Show transceiver information from modules (e.g SFP+, QSFP)</help>
</properties>
- <command>/sbin/ethtool -m "$4"</command>
+ <command>ethtool --module-info "$4"</command>
</leafNode>
<tagNode name="vif">
<properties>
<help>Show specified virtual network interface (vif) information</help>
<completionHelp>
<path>interfaces ethernet ${COMP_WORDS[3]} vif</path>
</completionHelp>
</properties>
<command>${vyos_op_scripts_dir}/show_interfaces.py --intf="$4.$6"</command>
<children>
<leafNode name="brief">
<properties>
<help>Show summary of specified virtual network interface (vif) information</help>
</properties>
<command>${vyos_op_scripts_dir}/show_interfaces.py --intf="$4.$6" --action=show-brief</command>
</leafNode>
</children>
</tagNode>
<leafNode name="xdp">
<properties>
<help>Show eXpress Data Path statistics</help>
</properties>
<command>sudo ${vyos_op_scripts_dir}/show_xdp_stats.sh ethernet "$4"</command>
</leafNode>
</children>
</tagNode>
<node name="ethernet">
<properties>
<help>Show ethernet interface information</help>
</properties>
<command>${vyos_op_scripts_dir}/show_interfaces.py --intf-type=ethernet --action=show-brief</command>
<children>
<leafNode name="detail">
<properties>
<help>Show detailed ethernet interface information</help>
</properties>
<command>${vyos_op_scripts_dir}/show_interfaces.py --intf-type=ethernet --action=show</command>
</leafNode>
</children>
</node>
</children>
</node>
</children>
</node>
</interfaceDefinition>
diff --git a/python/vyos/ethtool.py b/python/vyos/ethtool.py
index 5a5d84bed..7dcb68346 100644
--- a/python/vyos/ethtool.py
+++ b/python/vyos/ethtool.py
@@ -1,149 +1,149 @@
# Copyright 2021 VyOS maintainers and contributors <maintainers@vyos.io>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
import re
from vyos.util import popen
class Ethtool:
"""
Class is used to retrive and cache information about an ethernet adapter
"""
# dictionary containing driver featurs, it will be populated on demand and
# the content will look like:
# {
# 'tls-hw-tx-offload': {'fixed': True, 'enabled': False},
# 'tx-checksum-fcoe-crc': {'fixed': True, 'enabled': False},
# 'tx-checksum-ip-generic': {'fixed': False, 'enabled': True},
# 'tx-checksum-ipv4': {'fixed': True, 'enabled': False},
# 'tx-checksum-ipv6': {'fixed': True, 'enabled': False},
# 'tx-checksum-sctp': {'fixed': True, 'enabled': False},
# 'tx-checksumming': {'fixed': False, 'enabled': True},
# 'tx-esp-segmentation': {'fixed': True, 'enabled': False},
# }
_features = { }
# dictionary containing available interface speed and duplex settings
# {
# '10' : {'full': '', 'half': ''},
# '100' : {'full': '', 'half': ''},
# '1000': {'full': ''}
# }
_speed_duplex = { }
_ring_buffers = { }
def __init__(self, ifname):
# Build a dictinary of supported link-speed and dupley settings.
out, err = popen(f'ethtool {ifname}')
reading = False
pattern = re.compile(r'\d+base.*')
for line in out.splitlines()[1:]:
line = line.lstrip()
if 'Supported link modes:' in line:
reading = True
if 'Supported pause frame use:' in line:
reading = False
break
if reading:
for block in line.split():
if pattern.search(block):
speed = block.split('base')[0]
duplex = block.split('/')[-1].lower()
if speed not in self._speed_duplex:
self._speed_duplex.update({ speed : {}})
if duplex not in self._speed_duplex[speed]:
self._speed_duplex[speed].update({ duplex : ''})
# Now populate features dictionaty
- out, err = popen(f'ethtool -k {ifname}')
+ out, err = 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:
key, value = [s.strip() for s in line.strip().split(":", 1)]
fixed = bool('fixed' in value)
if fixed:
value = value.split()[0].strip()
self._features[key.strip()] = {
'enabled' : bool(value == 'on'),
'fixed' : fixed
}
out, err = popen(f'ethtool -g {ifname}')
# We are only interested in line 2-5 which contains the device maximum
# ringbuffers
for line in out.splitlines()[2:6]:
if ':' in line:
key, value = [s.strip() for s in line.strip().split(":", 1)]
key = key.lower().replace(' ', '_')
# T3645: ethtool version used on Debian Bullseye changed the
# output format from 0 -> n/a. As we are only interested in the
# tx/rx keys we do not care about RX Mini/Jumbo.
if value.isdigit():
self._ring_buffers[key] = int(value)
def _get_generic(self, feature):
"""
Generic method to read self._features and return a tuple for feature
enabled and feature is fixed.
In case of a missing key, return "fixed = True and enabled = False"
"""
fixed = True
enabled = False
if feature in self._features:
if 'enabled' in self._features[feature]:
enabled = self._features[feature]['enabled']
if 'fixed' in self._features[feature]:
fixed = self._features[feature]['fixed']
return enabled, fixed
def get_generic_receive_offload(self):
return self._get_generic('generic-receive-offload')
def get_generic_segmentation_offload(self):
return self._get_generic('generic-segmentation-offload')
def get_large_receive_offload(self):
return self._get_generic('large-receive-offload')
def get_scatter_gather(self):
return self._get_generic('scatter-gather')
def get_tcp_segmentation_offload(self):
return self._get_generic('tcp-segmentation-offload')
def get_rx_buffer(self):
# Configuration of RX ring-buffers is not supported on every device,
# thus when it's impossible return None
return self._ring_buffers.get('rx', None)
def get_tx_buffer(self):
# Configuration of TX ring-buffers is not supported on every device,
# thus when it's impossible return None
return self._ring_buffers.get('tx', None)
def check_speed_duplex(self, speed, duplex):
""" Check if the passed speed and duplex combination is supported by
the underlaying network adapter. """
if isinstance(speed, int):
speed = str(speed)
if not speed.isdigit():
raise ValueError(f'Value "{speed}" for speed is invalid!')
if duplex not in ['full', 'half']:
raise ValueError(f'Value "{duplex}" for duplex is invalid!')
if speed in self._speed_duplex:
if duplex in self._speed_duplex[speed]:
return True
return False
diff --git a/python/vyos/ifconfig/ethernet.py b/python/vyos/ifconfig/ethernet.py
index 7d29da8fc..76ed3fd92 100644
--- a/python/vyos/ifconfig/ethernet.py
+++ b/python/vyos/ifconfig/ethernet.py
@@ -1,393 +1,388 @@
# Copyright 2019-2021 VyOS maintainers and contributors <maintainers@vyos.io>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
import os
import re
from vyos.ethtool import Ethtool
from vyos.ifconfig.interface import Interface
from vyos.util import run
from vyos.util import dict_search
from vyos.validate import assert_list
@Interface.register
class EthernetIf(Interface):
"""
Abstraction of a Linux Ethernet Interface
"""
iftype = 'ethernet'
definition = {
**Interface.definition,
**{
'section': 'ethernet',
'prefixes': ['lan', 'eth', 'eno', 'ens', 'enp', 'enx'],
'bondable': True,
'broadcast': True,
'bridgeable': True,
'eternal': '(lan|eth|eno|ens|enp|enx)[0-9]+$',
}
}
@staticmethod
def feature(ifname, option, value):
- run(f'ethtool -K {ifname} {option} {value}')
+ run(f'ethtool --features {ifname} {option} {value}')
return False
_command_set = {**Interface._command_set, **{
'gro': {
'validate': lambda v: assert_list(v, ['on', 'off']),
'possible': lambda i, v: EthernetIf.feature(i, 'gro', v),
- # 'shellcmd': 'ethtool -K {ifname} gro {value}',
},
'gso': {
'validate': lambda v: assert_list(v, ['on', 'off']),
'possible': lambda i, v: EthernetIf.feature(i, 'gso', v),
- # 'shellcmd': 'ethtool -K {ifname} gso {value}',
},
'lro': {
'validate': lambda v: assert_list(v, ['on', 'off']),
'possible': lambda i, v: EthernetIf.feature(i, 'lro', v),
- # 'shellcmd': 'ethtool -K {ifname} lro {value}',
},
'sg': {
'validate': lambda v: assert_list(v, ['on', 'off']),
'possible': lambda i, v: EthernetIf.feature(i, 'sg', v),
- # 'shellcmd': 'ethtool -K {ifname} sg {value}',
},
'tso': {
'validate': lambda v: assert_list(v, ['on', 'off']),
'possible': lambda i, v: EthernetIf.feature(i, 'tso', v),
- # 'shellcmd': 'ethtool -K {ifname} tso {value}',
},
}}
_sysfs_set = {**Interface._sysfs_set, **{
'rps': {
'convert': lambda cpus: cpus if cpus else '0',
'location': '/sys/class/net/{ifname}/queues/rx-0/rps_cpus',
},
}}
def __init__(self, ifname, **kargs):
super().__init__(ifname, **kargs)
self.ethtool = Ethtool(ifname)
def get_driver_name(self):
"""
Return the driver name used by NIC. Some NICs don't support all
features e.g. changing link-speed, duplex
Example:
>>> from vyos.ifconfig import EthernetIf
>>> i = EthernetIf('eth0')
>>> i.get_driver_name()
'vmxnet3'
"""
ifname = self.config['ifname']
sysfs_file = f'/sys/class/net/{ifname}/device/driver/module'
if os.path.exists(sysfs_file):
link = os.readlink(sysfs_file)
return os.path.basename(link)
else:
return None
def set_flow_control(self, enable):
"""
Changes the pause parameters of the specified Ethernet device.
@param enable: true -> enable pause frames, false -> disable pause frames
Example:
>>> from vyos.ifconfig import EthernetIf
>>> i = EthernetIf('eth0')
>>> i.set_flow_control(True)
"""
ifname = self.config['ifname']
if enable not in ['on', 'off']:
raise ValueError("Value out of range")
driver_name = self.get_driver_name()
if driver_name in ['vmxnet3', 'virtio_net', 'xen_netfront']:
self._debug_msg(f'{driver_name} driver does not support changing '\
'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
def set_speed_duplex(self, speed, duplex):
"""
Set link speed in Mbit/s and duplex.
@speed can be any link speed in MBit/s, e.g. 10, 100, 1000 auto
@duplex can be half, full, auto
Example:
>>> from vyos.ifconfig import EthernetIf
>>> i = EthernetIf('eth0')
>>> i.set_speed_duplex('auto', 'auto')
"""
if speed not in ['auto', '10', '100', '1000', '2500', '5000', '10000',
'25000', '40000', '50000', '100000', '400000']:
raise ValueError("Value out of range (speed)")
if duplex not in ['auto', 'full', 'half']:
raise ValueError("Value out of range (duplex)")
driver_name = self.get_driver_name()
if driver_name in ['vmxnet3', 'virtio_net', 'xen_netfront']:
self._debug_msg(f'{driver_name} driver does not support changing '\
'speed/duplex settings!')
return
# Get current speed and duplex settings:
ifname = self.config['ifname']
cmd = f'ethtool {ifname}'
tmp = self._cmd(cmd)
if re.search("\tAuto-negotiation: on", tmp):
if speed == 'auto' and duplex == 'auto':
# bail out early as nothing is to change
return
else:
# read in current speed and duplex settings
cur_speed = 0
cur_duplex = ''
for line in tmp.splitlines():
if line.lstrip().startswith("Speed:"):
non_decimal = re.compile(r'[^\d.]+')
cur_speed = non_decimal.sub('', line)
continue
if line.lstrip().startswith("Duplex:"):
cur_duplex = line.split()[-1].lower()
break
if (cur_speed == speed) and (cur_duplex == duplex):
# bail out early as nothing is to change
return
cmd = f'ethtool -s {ifname}'
if speed == 'auto' or duplex == 'auto':
cmd += ' autoneg on'
else:
cmd += f' speed {speed} duplex {duplex} autoneg off'
return self._cmd(cmd)
def set_gro(self, state):
"""
Enable Generic Receive Offload. State can be either True or False.
Example:
>>> from vyos.ifconfig import EthernetIf
>>> i = EthernetIf('eth0')
>>> i.set_gro(True)
"""
if not isinstance(state, bool):
raise ValueError('Value out of range')
enabled, fixed = self.ethtool.get_generic_receive_offload()
if enabled != state:
if not fixed:
return self.set_interface('gro', 'on' if state else 'off')
else:
print('Adapter does not support changing generic-receive-offload settings!')
return False
def set_gso(self, state):
"""
Enable Generic Segmentation offload. State can be either True or False.
Example:
>>> from vyos.ifconfig import EthernetIf
>>> i = EthernetIf('eth0')
>>> i.set_gso(True)
"""
if not isinstance(state, bool):
raise ValueError('Value out of range')
enabled, fixed = self.ethtool.get_generic_segmentation_offload()
if enabled != state:
if not fixed:
return self.set_interface('gso', 'on' if state else 'off')
else:
print('Adapter does not support changing generic-segmentation-offload settings!')
return False
def set_lro(self, state):
"""
Enable Large Receive offload. State can be either True or False.
Example:
>>> from vyos.ifconfig import EthernetIf
>>> i = EthernetIf('eth0')
>>> i.set_lro(True)
"""
if not isinstance(state, bool):
raise ValueError('Value out of range')
enabled, fixed = self.ethtool.get_large_receive_offload()
if enabled != state:
if not fixed:
return self.set_interface('gro', 'on' if state else 'off')
else:
print('Adapter does not support changing large-receive-offload settings!')
return False
def set_rps(self, state):
if not isinstance(state, bool):
raise ValueError('Value out of range')
rps_cpus = '0'
if state:
# Enable RPS on all available CPUs except CPU0 which we will not
# utilize so the system has one spare core when it's under high
# preasure to server other means. Linux sysfs excepts a bitmask
# representation of the CPUs which should participate on RPS, we
# can enable more CPUs that are physically present on the system,
# Linux will clip that internally!
rps_cpus = 'ffffffff,ffffffff,ffffffff,fffffffe'
# send bitmask representation as hex string without leading '0x'
return self.set_interface('rps', rps_cpus)
def set_sg(self, state):
"""
Enable Scatter-Gather support. State can be either True or False.
Example:
>>> from vyos.ifconfig import EthernetIf
>>> i = EthernetIf('eth0')
>>> i.set_sg(True)
"""
if not isinstance(state, bool):
raise ValueError('Value out of range')
enabled, fixed = self.ethtool.get_scatter_gather()
if enabled != state:
if not fixed:
return self.set_interface('gro', 'on' if state else 'off')
else:
print('Adapter does not support changing scatter-gather settings!')
return False
def set_tso(self, state):
"""
Enable TCP segmentation offloading. State can be either True or False.
Example:
>>> from vyos.ifconfig import EthernetIf
>>> i = EthernetIf('eth0')
>>> i.set_tso(False)
"""
if not isinstance(state, bool):
raise ValueError('Value out of range')
enabled, fixed = self.ethtool.get_tcp_segmentation_offload()
if enabled != state:
if not fixed:
return self.set_interface('gro', 'on' if state else 'off')
else:
print('Adapter does not support changing tcp-segmentation-offload settings!')
return False
def set_ring_buffer(self, b_type, b_size):
"""
Example:
>>> from vyos.ifconfig import EthernetIf
>>> i = EthernetIf('eth0')
>>> i.set_ring_buffer('rx', '4096')
"""
ifname = self.config['ifname']
cmd = f'ethtool -G {ifname} {b_type} {b_size}'
output, code = self._popen(cmd)
# ethtool error codes:
# 80 - value already setted
# 81 - does not possible to set value
if code and code != 80:
print(f'could not set "{b_type}" ring-buffer for {ifname}')
return output
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
interface setup code and provide a single point of entry when workin
on any interface. """
# disable ethernet flow control (pause frames)
value = 'off' if 'disable_flow_control' in config else 'on'
self.set_flow_control(value)
# GRO (generic receive offload)
self.set_gro(dict_search('offload.gro', config) != None)
# GSO (generic segmentation offload)
self.set_gso(dict_search('offload.gso', config) != None)
# LRO (large receive offload)
self.set_lro(dict_search('offload.lro', config) != None)
# RPS - Receive Packet Steering
self.set_rps(dict_search('offload.rps', config) != None)
# scatter-gather option
self.set_sg(dict_search('offload.sg', config) != None)
# TSO (TCP segmentation offloading)
self.set_tso(dict_search('offload.tso', config) != None)
# Set physical interface speed and duplex
if {'speed', 'duplex'} <= set(config):
speed = config.get('speed')
duplex = config.get('duplex')
self.set_speed_duplex(speed, duplex)
# Set interface ring buffer
if 'ring_buffer' in config:
for b_type in config['ring_buffer']:
self.set_ring_buffer(b_type, config['ring_buffer'][b_type])
# call base class first
super().update(config)

File Metadata

Mime Type
text/x-diff
Expires
Sat, Oct 17, 12:24 AM (7 h, 44 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4403415
Default Alt Text
(25 KB)

Event Timeline