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 + | 
