diff options
Diffstat (limited to 'python/vyos/ifconfig')
-rw-r--r-- | python/vyos/ifconfig/bond.py | 8 | ||||
-rw-r--r-- | python/vyos/ifconfig/bridge.py | 77 | ||||
-rw-r--r-- | python/vyos/ifconfig/ethernet.py | 12 | ||||
-rw-r--r-- | python/vyos/ifconfig/interface.py | 40 | ||||
-rw-r--r-- | python/vyos/ifconfig/l2tpv3.py | 25 | ||||
-rw-r--r-- | python/vyos/ifconfig/tunnel.py | 2 | ||||
-rw-r--r-- | python/vyos/ifconfig/vtun.py | 44 | ||||
-rw-r--r-- | python/vyos/ifconfig/wireguard.py | 2 |
8 files changed, 164 insertions, 46 deletions
diff --git a/python/vyos/ifconfig/bond.py b/python/vyos/ifconfig/bond.py index 9108fc180..709222b09 100644 --- a/python/vyos/ifconfig/bond.py +++ b/python/vyos/ifconfig/bond.py @@ -17,7 +17,7 @@ import os from vyos.ifconfig.interface import Interface from vyos.util import cmd -from vyos.util import vyos_dict_search +from vyos.util import dict_search from vyos.validate import assert_list from vyos.validate import assert_positive @@ -360,7 +360,7 @@ class BondIf(Interface): self.set_arp_ip_target('-' + addr) # Add configured ARP target addresses - value = vyos_dict_search('arp_monitor.target', config) + value = dict_search('arp_monitor.target', config) if isinstance(value, str): value = [value] if value: @@ -384,7 +384,7 @@ class BondIf(Interface): # Removing an interface from a bond will always place the underlaying # physical interface in admin-down state! If physical interface is # not disabled, re-enable it. - if not vyos_dict_search(f'member.interface_remove.{interface}.disable', config): + if not dict_search(f'member.interface_remove.{interface}.disable', config): Interface(interface).set_admin_state('up') # Bonding policy/mode @@ -392,7 +392,7 @@ class BondIf(Interface): if value: self.set_mode(value) # Add (enslave) interfaces to bond - value = vyos_dict_search('member.interface', config) + value = dict_search('member.interface', config) for interface in (value or []): # if we've come here we already verified the interface # does not have an addresses configured so just flush diff --git a/python/vyos/ifconfig/bridge.py b/python/vyos/ifconfig/bridge.py index bf78f8972..7eac9b886 100644 --- a/python/vyos/ifconfig/bridge.py +++ b/python/vyos/ifconfig/bridge.py @@ -19,7 +19,7 @@ from vyos.ifconfig.interface import Interface from vyos.validate import assert_boolean from vyos.validate import assert_positive from vyos.util import cmd -from vyos.util import vyos_dict_search +from vyos.util import dict_search @Interface.register class BridgeIf(Interface): @@ -41,6 +41,7 @@ class BridgeIf(Interface): 'section': 'bridge', 'prefixes': ['br', ], 'broadcast': True, + 'vlan': True, }, } @@ -73,6 +74,10 @@ class BridgeIf(Interface): 'validate': assert_boolean, 'location': '/sys/class/net/{ifname}/bridge/stp_state', }, + 'vlan_filter': { + 'validate': assert_boolean, + 'location': '/sys/class/net/{ifname}/bridge/vlan_filtering', + }, 'multicast_querier': { 'validate': assert_boolean, 'location': '/sys/class/net/{ifname}/bridge/multicast_querier', @@ -152,6 +157,16 @@ class BridgeIf(Interface): >>> BridgeIf('br0').set_stp(1) """ self.set_interface('stp', state) + + def set_vlan_filter(self, state): + """ + Set bridge Vlan Filter state. 0 -> Vlan Filter disabled, 1 -> Vlan Filter enabled + + Example: + >>> from vyos.ifconfig import BridgeIf + >>> BridgeIf('br0').set_vlan_filter(1) + """ + self.set_interface('vlan_filter', state) def set_multicast_querier(self, enable): """ @@ -177,8 +192,13 @@ class BridgeIf(Interface): >>> BridgeIf('br0').add_port('eth0') >>> BridgeIf('br0').add_port('eth1') """ + # Bridge port handling of wireless interfaces is done by hostapd. + if 'wlan' in interface: + return + return self.set_interface('add_port', interface) + def del_port(self, interface): """ Remove member port from bridge instance. @@ -197,6 +217,8 @@ class BridgeIf(Interface): # call base class first super().update(config) + + ifname = config['ifname'] # Set ageing time value = config.get('aging') @@ -223,17 +245,18 @@ class BridgeIf(Interface): self.set_stp(value) # enable or disable IGMP querier - tmp = vyos_dict_search('igmp.querier', config) + tmp = dict_search('igmp.querier', config) value = '1' if (tmp != None) else '0' self.set_multicast_querier(value) # remove interface from bridge - tmp = vyos_dict_search('member.interface_remove', config) + tmp = dict_search('member.interface_remove', config) for member in (tmp or []): if member in interfaces(): self.del_port(member) + vlan_filter = 0 - tmp = vyos_dict_search('member.interface', config) + tmp = dict_search('member.interface', config) if tmp: for interface, interface_config in tmp.items(): # if interface does yet not exist bail out early and @@ -260,7 +283,51 @@ class BridgeIf(Interface): if 'priority' in interface_config: value = interface_config.get('priority') lower.set_path_priority(value) - + + tmp = dict_search('native_vlan_removed', interface_config) + + if tmp and 'native_vlan_removed' not in interface_config: + vlan_id = tmp + cmd = f'bridge vlan add dev {interface} vid 1 pvid untagged master' + self._cmd(cmd) + cmd = f'bridge vlan del dev {interface} vid {vlan_id}' + self._cmd(cmd) + + tmp = dict_search('allowed_vlan_removed', interface_config) + + + for vlan_id in (tmp or []): + cmd = f'bridge vlan del dev {interface} vid {vlan_id}' + self._cmd(cmd) + + if 'native_vlan' in interface_config: + vlan_filter = 1 + cmd = f'bridge vlan del dev {interface} vid 1' + self._cmd(cmd) + vlan_id = interface_config['native_vlan'] + cmd = f'bridge vlan add dev {interface} vid {vlan_id} pvid untagged master' + self._cmd(cmd) + else: + cmd = f'bridge vlan del dev {interface} vid 1' + self._cmd(cmd) + + if 'allowed_vlan' in interface_config: + vlan_filter = 1 + for vlan in interface_config['allowed_vlan']: + cmd = f'bridge vlan add dev {interface} vid {vlan} master' + self._cmd(cmd) + + + vif = dict_search('vif', config) + if vif: + for vlan_id,vif_config in vif.items(): + cmd = f'bridge vlan add dev {ifname} vid {vlan_id} self master' + self._cmd(cmd) + + # enable/disable Vlan Filter + self.set_vlan_filter(vlan_filter) + + # 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/ethernet.py b/python/vyos/ifconfig/ethernet.py index 1d48941f9..12d1ec265 100644 --- a/python/vyos/ifconfig/ethernet.py +++ b/python/vyos/ifconfig/ethernet.py @@ -19,7 +19,7 @@ import re from vyos.ifconfig.interface import Interface from vyos.validate import assert_list from vyos.util import run -from vyos.util import vyos_dict_search +from vyos.util import dict_search @Interface.register class EthernetIf(Interface): @@ -282,27 +282,27 @@ class EthernetIf(Interface): self.set_flow_control(value) # GRO (generic receive offload) - tmp = vyos_dict_search('offload_options.generic_receive', config) + tmp = dict_search('offload_options.generic_receive', config) value = tmp if (tmp != None) else 'off' self.set_gro(value) # GSO (generic segmentation offload) - tmp = vyos_dict_search('offload_options.generic_segmentation', config) + tmp = dict_search('offload_options.generic_segmentation', config) value = tmp if (tmp != None) else 'off' self.set_gso(value) # scatter-gather option - tmp = vyos_dict_search('offload_options.scatter_gather', config) + tmp = dict_search('offload_options.scatter_gather', config) value = tmp if (tmp != None) else 'off' self.set_sg(value) # TSO (TCP segmentation offloading) - tmp = vyos_dict_search('offload_options.udp_fragmentation', config) + tmp = dict_search('offload_options.udp_fragmentation', config) value = tmp if (tmp != None) else 'off' self.set_tso(value) # UDP fragmentation offloading - tmp = vyos_dict_search('offload_options.udp_fragmentation', config) + tmp = dict_search('offload_options.udp_fragmentation', config) value = tmp if (tmp != None) else 'off' self.set_ufo(value) diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index ae747e87c..893623284 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -34,9 +34,9 @@ from vyos.configdict import list_diff from vyos.configdict import dict_merge from vyos.template import render from vyos.util import mac2eui64 -from vyos.util import vyos_dict_search -from vyos.validate import is_ipv4 -from vyos.validate import is_ipv6 +from vyos.util import dict_search +from vyos.template import is_ipv4 +from vyos.template import is_ipv6 from vyos.validate import is_intf_addr_assigned from vyos.validate import assert_boolean from vyos.validate import assert_list @@ -880,7 +880,7 @@ class Interface(Control): lease_file = f'{config_base}_{ifname}.leases' if enable and 'disable' not in self._config: - if vyos_dict_search('dhcp_options.host_name', self._config) == None: + if dict_search('dhcp_options.host_name', self._config) == None: # read configured system hostname. # maybe change to vyos hostd client ??? hostname = 'vyos' @@ -959,7 +959,7 @@ class Interface(Control): # always ensure DHCPv6 client is stopped (when not configured as client # for IPv6 address or prefix delegation - dhcpv6pd = vyos_dict_search('dhcpv6_options.pd', config) + dhcpv6pd = dict_search('dhcpv6_options.pd', config) if 'dhcpv6' not in new_addr or dhcpv6pd == None: self.del_addr('dhcpv6') @@ -987,64 +987,64 @@ class Interface(Control): self.set_vrf(config.get('vrf', '')) # Configure ARP cache timeout in milliseconds - has default value - tmp = vyos_dict_search('ip.arp_cache_timeout', config) + tmp = dict_search('ip.arp_cache_timeout', config) value = tmp if (tmp != None) else '30' self.set_arp_cache_tmo(value) # Configure ARP filter configuration - tmp = vyos_dict_search('ip.disable_arp_filter', config) + tmp = dict_search('ip.disable_arp_filter', config) value = '0' if (tmp != None) else '1' self.set_arp_filter(value) # Configure ARP accept - tmp = vyos_dict_search('ip.enable_arp_accept', config) + tmp = dict_search('ip.enable_arp_accept', config) value = '1' if (tmp != None) else '0' self.set_arp_accept(value) # Configure ARP announce - tmp = vyos_dict_search('ip.enable_arp_announce', config) + tmp = dict_search('ip.enable_arp_announce', config) value = '1' if (tmp != None) else '0' self.set_arp_announce(value) # Configure ARP ignore - tmp = vyos_dict_search('ip.enable_arp_ignore', config) + tmp = dict_search('ip.enable_arp_ignore', config) value = '1' if (tmp != None) else '0' self.set_arp_ignore(value) # Enable proxy-arp on this interface - tmp = vyos_dict_search('ip.enable_proxy_arp', config) + tmp = dict_search('ip.enable_proxy_arp', config) value = '1' if (tmp != None) else '0' self.set_proxy_arp(value) # Enable private VLAN proxy ARP on this interface - tmp = vyos_dict_search('ip.proxy_arp_pvlan', config) + tmp = dict_search('ip.proxy_arp_pvlan', config) value = '1' if (tmp != None) else '0' self.set_proxy_arp_pvlan(value) # IPv4 forwarding - tmp = vyos_dict_search('ip.disable_forwarding', config) + tmp = dict_search('ip.disable_forwarding', config) value = '0' if (tmp != None) else '1' self.set_ipv4_forwarding(value) # IPv6 forwarding - tmp = vyos_dict_search('ipv6.disable_forwarding', config) + tmp = dict_search('ipv6.disable_forwarding', config) value = '0' if (tmp != None) else '1' self.set_ipv6_forwarding(value) # IPv6 router advertisements - tmp = vyos_dict_search('ipv6.address.autoconf', config) + tmp = dict_search('ipv6.address.autoconf', config) value = '2' if (tmp != None) else '1' if 'dhcpv6' in new_addr: value = '2' self.set_ipv6_accept_ra(value) # IPv6 address autoconfiguration - tmp = vyos_dict_search('ipv6.address.autoconf', config) + tmp = dict_search('ipv6.address.autoconf', config) value = '1' if (tmp != None) else '0' self.set_ipv6_autoconf(value) # IPv6 Duplicate Address Detection (DAD) tries - tmp = vyos_dict_search('ipv6.dup_addr_detect_transmits', config) + tmp = dict_search('ipv6.dup_addr_detect_transmits', config) value = tmp if (tmp != None) else '1' self.set_ipv6_dad_messages(value) @@ -1053,7 +1053,7 @@ class Interface(Control): self.set_mtu(config.get('mtu')) # Delete old IPv6 EUI64 addresses before changing MAC - tmp = vyos_dict_search('ipv6.address.eui64_old', config) + tmp = dict_search('ipv6.address.eui64_old', config) if tmp: for addr in tmp: self.del_ipv6_eui64_address(addr) @@ -1068,7 +1068,7 @@ class Interface(Control): self.set_mac(mac) # Manage IPv6 link-local addresses - tmp = vyos_dict_search('ipv6.address.no_default_link_local', config) + tmp = dict_search('ipv6.address.no_default_link_local', config) # we must check explicitly for None type as if the key is set we will # get an empty dict (<class 'dict'>) if tmp is not None: @@ -1077,7 +1077,7 @@ class Interface(Control): self.add_ipv6_eui64_address('fe80::/64') # Add IPv6 EUI-based addresses - tmp = vyos_dict_search('ipv6.address.eui64', config) + tmp = dict_search('ipv6.address.eui64', config) if tmp: for addr in tmp: self.add_ipv6_eui64_address(addr) diff --git a/python/vyos/ifconfig/l2tpv3.py b/python/vyos/ifconfig/l2tpv3.py index 5fd90f9cf..8ed3d5afb 100644 --- a/python/vyos/ifconfig/l2tpv3.py +++ b/python/vyos/ifconfig/l2tpv3.py @@ -68,8 +68,9 @@ class L2TPv3If(Interface): cmd += ' peer_session_id {peer_session_id}' self._cmd(cmd.format(**self.config)) - # interface is always A/D down. It needs to be enabled explicitly - self.set_admin_state('down') + # No need for interface shut down. There exist no function to permanently enable tunnel. + # But you can disable interface permanently with shutdown/disable command. + self.set_admin_state('up') def remove(self): """ @@ -93,4 +94,24 @@ class L2TPv3If(Interface): if self.config['tunnel_id']: cmd = 'ip l2tp del tunnel tunnel_id {tunnel_id}' self._cmd(cmd.format(**self.config)) + + + 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. """ + + # call base class first + super().update(config) + + # 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 + # often as 'down'. This is required by some interface implementations + # as certain parameters can only be changed when the interface is + # in admin-down state. This ensures the link does not flap during + # reconfiguration. + state = 'down' if 'disable' in config else 'up' + self.set_admin_state(state) diff --git a/python/vyos/ifconfig/tunnel.py b/python/vyos/ifconfig/tunnel.py index 964ffe383..4122d1a2f 100644 --- a/python/vyos/ifconfig/tunnel.py +++ b/python/vyos/ifconfig/tunnel.py @@ -179,7 +179,7 @@ class GRETapIf(_Tunnel): default = {'type': 'gretap'} required = ['local', ] - options = ['local', 'remote', ] + options = ['local', 'remote', 'ttl',] updates = ['mtu', ] create = 'ip link add {ifname} type {type}' diff --git a/python/vyos/ifconfig/vtun.py b/python/vyos/ifconfig/vtun.py index b25e32d63..99a592b3e 100644 --- a/python/vyos/ifconfig/vtun.py +++ b/python/vyos/ifconfig/vtun.py @@ -19,6 +19,7 @@ from vyos.ifconfig.interface import Interface class VTunIf(Interface): default = { 'type': 'vtun', + 'device_type': 'tun', } definition = { **Interface.definition, @@ -28,15 +29,44 @@ class VTunIf(Interface): 'bridgeable': True, }, } - - # stub this interface is created in the configure script + options = Interface.options + ['device_type'] def _create(self): - # we can not create this interface as it is managed outside - # it requires configuring OpenVPN + """ Depending on OpenVPN operation mode the interface is created + immediately (e.g. Server mode) or once the connection to the server is + established (client mode). The latter will only be brought up once the + server can be reached, thus we might need to create this interface in + advance for the service to be operational. """ + try: + cmd = 'openvpn --mktun --dev-type {device_type} --dev {ifname}'.format(**self.config) + return self._cmd(cmd) + except PermissionError: + # interface created by OpenVPN daemon in the meantime ... + pass + + def add_addr(self, addr): + # IP addresses are managed by OpenVPN daemon pass - def _delete(self): - # we can not create this interface as it is managed outside - # it requires configuring OpenVPN + def del_addr(self, addr): + # IP addresses are managed by OpenVPN daemon pass + + 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. """ + + # call base class first + super().update(config) + + # 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 + # often as 'down'. This is required by some interface implementations + # as certain parameters can only be changed when the interface is + # in admin-down state. This ensures the link does not flap during + # reconfiguration. + state = 'down' if 'disable' in config else 'up' + self.set_admin_state(state) diff --git a/python/vyos/ifconfig/wireguard.py b/python/vyos/ifconfig/wireguard.py index d8e89229d..da3bd4e89 100644 --- a/python/vyos/ifconfig/wireguard.py +++ b/python/vyos/ifconfig/wireguard.py @@ -24,7 +24,7 @@ from hurry.filesize import alternative from vyos.config import Config from vyos.ifconfig import Interface from vyos.ifconfig import Operational -from vyos.validate import is_ipv6 +from vyos.template import is_ipv6 class WireGuardOperational(Operational): def _dump(self): |