diff options
Diffstat (limited to 'python')
| -rw-r--r-- | python/vyos/ethtool.py | 88 | ||||
| -rw-r--r-- | python/vyos/ifconfig/bond.py | 3 | ||||
| -rw-r--r-- | python/vyos/ifconfig/ethernet.py | 3 | ||||
| -rw-r--r-- | python/vyos/ifconfig/interface.py | 3 | ||||
| -rw-r--r-- | python/vyos/ifconfig/wireguard.py | 110 |
5 files changed, 111 insertions, 96 deletions
diff --git a/python/vyos/ethtool.py b/python/vyos/ethtool.py index 80bb56fa2..21272cc5b 100644 --- a/python/vyos/ethtool.py +++ b/python/vyos/ethtool.py @@ -56,11 +56,8 @@ class Ethtool: # '100' : {'full': '', 'half': ''}, # '1000': {'full': ''} # } - _speed_duplex = {'auto': {'auto': ''}} _ring_buffer = None _driver_name = None - _auto_negotiation = False - _auto_negotiation_supported = None _flow_control = None def __init__(self, ifname): @@ -74,56 +71,51 @@ class Ethtool: self._driver_name = driver.group(1) # Build a dictinary of supported link-speed and dupley settings. - out, _ = 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 - 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 : ''}) - if 'Supports auto-negotiation:' in line: - # Split the following string: Auto-negotiation: off - # we are only interested in off or on - tmp = line.split()[-1] - self._auto_negotiation_supported = bool(tmp == 'Yes') - # Only read in if Auto-negotiation is supported - if self._auto_negotiation_supported and 'Auto-negotiation:' in line: - # Split the following string: Auto-negotiation: off - # we are only interested in off or on - tmp = line.split()[-1] - self._auto_negotiation = bool(tmp == 'on') + # [ { + # "ifname": "eth0", + # "supported-ports": [ "TP" ], + # "supported-link-modes": [ "10baseT/Half","10baseT/Full","100baseT/Half","100baseT/Full","1000baseT/Full" ], + # "supported-pause-frame-use": "Symmetric", + # "supports-auto-negotiation": true, + # "supported-fec-modes": [ ], + # "advertised-link-modes": [ "10baseT/Half","10baseT/Full","100baseT/Half","100baseT/Full","1000baseT/Full" ], + # "advertised-pause-frame-use": "Symmetric", + # "advertised-auto-negotiation": true, + # "advertised-fec-modes": [ ], + # "speed": 1000, + # "duplex": "Full", + # "auto-negotiation": false, + # "port": "Twisted Pair", + # "phyad": 1, + # "transceiver": "internal", + # "supports-wake-on": "pumbg", + # "wake-on": "g", + # "current-message-level": 7, + # "link-detected": true + # } ] + out, _ = popen(f'ethtool --json {ifname}') + self._base_settings = loads(out)[0] # Now populate driver features out, _ = popen(f'ethtool --json --show-features {ifname}') - self._features = loads(out) + self._features = loads(out)[0] # Get information about NIC ring buffers out, _ = popen(f'ethtool --json --show-ring {ifname}') - self._ring_buffer = loads(out) + self._ring_buffer = loads(out)[0] # 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 --json --show-pause {ifname}') if not bool(err): - self._flow_control = loads(out) + self._flow_control = loads(out)[0] def check_auto_negotiation_supported(self): """ Check if the NIC supports changing auto-negotiation """ - return self._auto_negotiation_supported + return self._base_settings['supports-auto-negotiation'] def get_auto_negotiation(self): - return self._auto_negotiation_supported and self._auto_negotiation + return self._base_settings['supports-auto-negotiation'] and self._base_settings['auto-negotiation'] def get_driver_name(self): return self._driver_name @@ -137,9 +129,9 @@ class Ethtool: """ active = False fixed = True - if feature in self._features[0]: - active = bool(self._features[0][feature]['active']) - fixed = bool(self._features[0][feature]['fixed']) + if feature in self._features: + active = bool(self._features[feature]['active']) + fixed = bool(self._features[feature]['fixed']) return active, fixed def get_generic_receive_offload(self): @@ -165,14 +157,14 @@ class Ethtool: # thus when it's impossible return None if rx_tx not in ['rx', 'tx']: ValueError('Ring-buffer type must be either "rx" or "tx"') - return str(self._ring_buffer[0].get(f'{rx_tx}-max', None)) + return str(self._ring_buffer.get(f'{rx_tx}-max', None)) def get_ring_buffer(self, rx_tx): # Configuration of RX/TX ring-buffers is not supported on every device, # thus when it's impossible return None if rx_tx not in ['rx', 'tx']: ValueError('Ring-buffer type must be either "rx" or "tx"') - return str(self._ring_buffer[0].get(rx_tx, None)) + return str(self._ring_buffer.get(rx_tx, None)) def check_speed_duplex(self, speed, duplex): """ Check if the passed speed and duplex combination is supported by @@ -184,12 +176,16 @@ class Ethtool: if duplex not in ['auto', 'full', 'half']: raise ValueError(f'Value "{duplex}" for duplex is invalid!') + if speed == 'auto' and duplex == 'auto': + return True + if self.get_driver_name() in _drivers_without_speed_duplex_flow: return False - if speed in self._speed_duplex: - if duplex in self._speed_duplex[speed]: - return True + # ['10baset/half', '10baset/full', '100baset/half', '100baset/full', '1000baset/full'] + tmp = [x.lower() for x in self._base_settings['supported-link-modes']] + if f'{speed}baset/{duplex}' in tmp: + return True return False def check_flow_control(self): @@ -201,4 +197,4 @@ class Ethtool: raise ValueError('Interface does not support changing '\ 'flow-control settings!') - return 'on' if bool(self._flow_control[0]['autonegotiate']) else 'off' + return 'on' if bool(self._flow_control['autonegotiate']) else 'off' diff --git a/python/vyos/ifconfig/bond.py b/python/vyos/ifconfig/bond.py index b8ea90049..8ba481728 100644 --- a/python/vyos/ifconfig/bond.py +++ b/python/vyos/ifconfig/bond.py @@ -504,3 +504,6 @@ class BondIf(Interface): # call base class first super().update(config) + + # enable/disable EAPoL (Extensible Authentication Protocol over Local Area Network) + self.set_eapol() diff --git a/python/vyos/ifconfig/ethernet.py b/python/vyos/ifconfig/ethernet.py index 8d96c863f..61da7b74b 100644 --- a/python/vyos/ifconfig/ethernet.py +++ b/python/vyos/ifconfig/ethernet.py @@ -452,3 +452,6 @@ class EthernetIf(Interface): # call base class last super().update(config) + + # enable/disable EAPoL (Extensible Authentication Protocol over Local Area Network) + self.set_eapol() diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index 31fcf6ca6..002d3da9e 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -1813,9 +1813,6 @@ class Interface(Control): value = '1' if (tmp != None) else '0' self.set_per_client_thread(value) - # enable/disable EAPoL (Extensible Authentication Protocol over Local Area Network) - self.set_eapol() - # Enable/Disable of an interface must always be done at the end of the # derived class to make use of the ref-counting set_admin_state() # function. We will only enable the interface if 'up' was called as diff --git a/python/vyos/ifconfig/wireguard.py b/python/vyos/ifconfig/wireguard.py index 5b5f25323..9030b1302 100644 --- a/python/vyos/ifconfig/wireguard.py +++ b/python/vyos/ifconfig/wireguard.py @@ -26,6 +26,7 @@ from vyos.ifconfig import Interface from vyos.ifconfig import Operational from vyos.template import is_ipv6 + class WireGuardOperational(Operational): def _dump(self): """Dump wireguard data in a python friendly way.""" @@ -54,7 +55,17 @@ class WireGuardOperational(Operational): } else: # We are entering a peer - device, public_key, preshared_key, endpoint, allowed_ips, latest_handshake, transfer_rx, transfer_tx, persistent_keepalive = items + ( + device, + public_key, + preshared_key, + endpoint, + allowed_ips, + latest_handshake, + transfer_rx, + transfer_tx, + persistent_keepalive, + ) = items if allowed_ips == '(none)': allowed_ips = [] else: @@ -72,75 +83,78 @@ class WireGuardOperational(Operational): def show_interface(self): from vyos.config import Config + c = Config() wgdump = self._dump().get(self.config['ifname'], None) - c.set_level(["interfaces", "wireguard", self.config['ifname']]) - description = c.return_effective_value(["description"]) - ips = c.return_effective_values(["address"]) + c.set_level(['interfaces', 'wireguard', self.config['ifname']]) + description = c.return_effective_value(['description']) + ips = c.return_effective_values(['address']) - answer = "interface: {}\n".format(self.config['ifname']) - if (description): - answer += " description: {}\n".format(description) - if (ips): - answer += " address: {}\n".format(", ".join(ips)) + answer = 'interface: {}\n'.format(self.config['ifname']) + if description: + answer += ' description: {}\n'.format(description) + if ips: + answer += ' address: {}\n'.format(', '.join(ips)) - answer += " public key: {}\n".format(wgdump['public_key']) - answer += " private key: (hidden)\n" - answer += " listening port: {}\n".format(wgdump['listen_port']) - answer += "\n" + answer += ' public key: {}\n'.format(wgdump['public_key']) + answer += ' private key: (hidden)\n' + answer += ' listening port: {}\n'.format(wgdump['listen_port']) + answer += '\n' - for peer in c.list_effective_nodes(["peer"]): + for peer in c.list_effective_nodes(['peer']): if wgdump['peers']: - pubkey = c.return_effective_value(["peer", peer, "public_key"]) + pubkey = c.return_effective_value(['peer', peer, 'public-key']) if pubkey in wgdump['peers']: wgpeer = wgdump['peers'][pubkey] - answer += " peer: {}\n".format(peer) - answer += " public key: {}\n".format(pubkey) + answer += ' peer: {}\n'.format(peer) + answer += ' public key: {}\n'.format(pubkey) """ figure out if the tunnel is recently active or not """ - status = "inactive" - if (wgpeer['latest_handshake'] is None): + status = 'inactive' + if wgpeer['latest_handshake'] is None: """ no handshake ever """ - status = "inactive" + status = 'inactive' else: if int(wgpeer['latest_handshake']) > 0: - delta = timedelta(seconds=int( - time.time() - wgpeer['latest_handshake'])) - answer += " latest handshake: {}\n".format(delta) - if (time.time() - int(wgpeer['latest_handshake']) < (60*5)): + delta = timedelta( + seconds=int(time.time() - wgpeer['latest_handshake']) + ) + answer += ' latest handshake: {}\n'.format(delta) + if time.time() - int(wgpeer['latest_handshake']) < (60 * 5): """ Five minutes and the tunnel is still active """ - status = "active" + status = 'active' else: """ it's been longer than 5 minutes """ - status = "inactive" + status = 'inactive' elif int(wgpeer['latest_handshake']) == 0: """ no handshake ever """ - status = "inactive" - answer += " status: {}\n".format(status) + status = 'inactive' + answer += ' status: {}\n'.format(status) if wgpeer['endpoint'] is not None: - answer += " endpoint: {}\n".format(wgpeer['endpoint']) + answer += ' endpoint: {}\n'.format(wgpeer['endpoint']) if wgpeer['allowed_ips'] is not None: - answer += " allowed ips: {}\n".format( - ",".join(wgpeer['allowed_ips']).replace(",", ", ")) + answer += ' allowed ips: {}\n'.format( + ','.join(wgpeer['allowed_ips']).replace(',', ', ') + ) if wgpeer['transfer_rx'] > 0 or wgpeer['transfer_tx'] > 0: - rx_size = size( - wgpeer['transfer_rx'], system=alternative) - tx_size = size( - wgpeer['transfer_tx'], system=alternative) - answer += " transfer: {} received, {} sent\n".format( - rx_size, tx_size) + rx_size = size(wgpeer['transfer_rx'], system=alternative) + tx_size = size(wgpeer['transfer_tx'], system=alternative) + answer += ' transfer: {} received, {} sent\n'.format( + rx_size, tx_size + ) if wgpeer['persistent_keepalive'] is not None: - answer += " persistent keepalive: every {} seconds\n".format( - wgpeer['persistent_keepalive']) + answer += ' persistent keepalive: every {} seconds\n'.format( + wgpeer['persistent_keepalive'] + ) answer += '\n' - return answer + super().formated_stats() + return answer @Interface.register @@ -151,27 +165,29 @@ class WireGuardIf(Interface): **Interface.definition, **{ 'section': 'wireguard', - 'prefixes': ['wg', ], + 'prefixes': [ + 'wg', + ], 'bridgeable': False, - } + }, } def get_mac(self): - """ Get a synthetic MAC address. """ + """Get a synthetic MAC address.""" return self.get_mac_synthetic() def update(self, config): - """ General helper function which works on a dictionary retrived by + """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. """ + on any interface.""" tmp_file = NamedTemporaryFile('w') tmp_file.write(config['private_key']) tmp_file.flush() # Wireguard base command is identical for every peer - base_cmd = 'wg set {ifname}' + base_cmd = 'wg set {ifname}' if 'port' in config: base_cmd += ' listen-port {port}' if 'fwmark' in config: @@ -201,7 +217,7 @@ class WireGuardIf(Interface): cmd += f' preshared-key {psk_file}' # Persistent keepalive is optional - if 'persistent_keepalive'in peer_config: + if 'persistent_keepalive' in peer_config: cmd += ' persistent-keepalive {persistent_keepalive}' # Multiple allowed-ip ranges can be defined - ensure we are always |
