diff options
-rw-r--r-- | python/vyos/ethtool.py | 75 |
1 files changed, 57 insertions, 18 deletions
diff --git a/python/vyos/ethtool.py b/python/vyos/ethtool.py index 0ae526346..8add1a327 100644 --- a/python/vyos/ethtool.py +++ b/python/vyos/ethtool.py @@ -13,13 +13,13 @@ # 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: # { @@ -32,10 +32,38 @@ class Ethtool: # 'tx-checksumming': {'fixed': False, 'enabled': True}, # 'tx-esp-segmentation': {'fixed': True, 'enabled': False}, # } - features = { } - ring_buffers = { } + _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}') # skip the first line, it only says: "Features for eth0": @@ -45,7 +73,7 @@ class Ethtool: fixed = bool('fixed' in value) if fixed: value = value.split()[0].strip() - self.features[key.strip()] = { + self._features[key.strip()] = { 'enabled' : bool(value == 'on'), 'fixed' : fixed } @@ -61,27 +89,22 @@ class Ethtool: # 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 is_fixed_lro(self): - # in case of a missing configuration, rather return "fixed". In Ethtool - # terminology "fixed" means the setting can not be changed by the user. - return self.features.get('large-receive-offload', True).get('fixed', True) + self._ring_buffers[key] = int(value) def _get_generic(self, feature): """ - Generic method to read self.features and return a tuple for 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'] + 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): @@ -108,9 +131,25 @@ class Ethtool: 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) + 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) + 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 + |