diff options
author | goodNETnick <33053932+goodNETnick@users.noreply.github.com> | 2022-03-31 13:48:47 +1000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-03-31 13:48:47 +1000 |
commit | aa5b35b68c1170bfd0b9661bafa72bb10fe6ca95 (patch) | |
tree | 46f3ffc41c29666c3251f25f2f93cb1f1b9a6c60 /python/vyos/ifconfig | |
parent | b776003cf55e1035ac83186e44f72764e52e9e0d (diff) | |
parent | bafb1973d906707cb571385e994a949d0d90b645 (diff) | |
download | vyos-1x-aa5b35b68c1170bfd0b9661bafa72bb10fe6ca95.tar.gz vyos-1x-aa5b35b68c1170bfd0b9661bafa72bb10fe6ca95.zip |
Merge branch 'vyos:current' into ocserv_local_otp
Diffstat (limited to 'python/vyos/ifconfig')
-rw-r--r-- | python/vyos/ifconfig/bridge.py | 12 | ||||
-rwxr-xr-x | python/vyos/ifconfig/interface.py | 128 | ||||
-rw-r--r-- | python/vyos/ifconfig/loopback.py | 13 | ||||
-rw-r--r-- | python/vyos/ifconfig/vxlan.py | 19 | ||||
-rw-r--r-- | python/vyos/ifconfig/wireless.py | 6 |
5 files changed, 106 insertions, 72 deletions
diff --git a/python/vyos/ifconfig/bridge.py b/python/vyos/ifconfig/bridge.py index 27073b266..ffd9c590f 100644 --- a/python/vyos/ifconfig/bridge.py +++ b/python/vyos/ifconfig/bridge.py @@ -298,7 +298,6 @@ class BridgeIf(Interface): 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 # add it later @@ -316,10 +315,13 @@ class BridgeIf(Interface): # enslave interface port to bridge self.add_port(interface) - # always set private-vlan/port isolation - tmp = dict_search('isolated', interface_config) - value = 'on' if (tmp != None) else 'off' - lower.set_port_isolation(value) + if not interface.startswith('wlan'): + # always set private-vlan/port isolation - this can not be + # done when lower link is a wifi link, as it will trigger: + # RTNETLINK answers: Operation not supported + tmp = dict_search('isolated', interface_config) + value = 'on' if (tmp != None) else 'off' + lower.set_port_isolation(value) # set bridge port path cost if 'cost' in interface_config: diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index 91c7f0c33..4fda1c0a9 100755 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -1,4 +1,4 @@ -# Copyright 2019-2021 VyOS maintainers and contributors <maintainers@vyos.io> +# Copyright 2019-2022 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 @@ -39,6 +39,7 @@ from vyos.util import read_file from vyos.util import get_interface_config from vyos.util import get_interface_namespace from vyos.util import is_systemd_service_active +from vyos.util import sysctl_read from vyos.template import is_ipv4 from vyos.template import is_ipv6 from vyos.validate import is_intf_addr_assigned @@ -1088,8 +1089,11 @@ class Interface(Control): elif addr == 'dhcpv6': self.set_dhcpv6(True) elif not is_intf_addr_assigned(self.ifname, addr): - self._cmd(f'ip addr add "{addr}" ' - f'{"brd + " if addr_is_v4 else ""}dev "{self.ifname}"') + tmp = f'ip addr add {addr} dev {self.ifname}' + # Add broadcast address for IPv4 + if is_ipv4(addr): tmp += ' brd +' + + self._cmd(tmp) else: return False @@ -1228,12 +1232,11 @@ class Interface(Control): options_file = f'{config_base}_{ifname}.options' pid_file = f'{config_base}_{ifname}.pid' lease_file = f'{config_base}_{ifname}.leases' - - # Stop client with old config files to get the right IF_METRIC. systemd_service = f'dhclient@{ifname}.service' - if is_systemd_service_active(systemd_service): - self._cmd(f'systemctl stop {systemd_service}') + # 'up' check is mandatory b/c even if the interface is A/D, as soon as + # the DHCP client is started the interface will be placed in u/u state. + # This is not what we intended to do when disabling an interface. if enable and 'disable' not in self._config: if dict_search('dhcp_options.host_name', self._config) == None: # read configured system hostname. @@ -1244,16 +1247,19 @@ class Interface(Control): tmp = {'dhcp_options' : { 'host_name' : hostname}} self._config = dict_merge(tmp, self._config) - render(options_file, 'dhcp-client/daemon-options.tmpl', - self._config) - render(config_file, 'dhcp-client/ipv4.tmpl', - self._config) + render(options_file, 'dhcp-client/daemon-options.tmpl', self._config) + render(config_file, 'dhcp-client/ipv4.tmpl', self._config) - # 'up' check is mandatory b/c even if the interface is A/D, as soon as - # the DHCP client is started the interface will be placed in u/u state. - # This is not what we intended to do when disabling an interface. - return self._cmd(f'systemctl restart {systemd_service}') + # When the DHCP client is restarted a brief outage will occur, as + # the old lease is released a new one is acquired (T4203). We will + # only restart DHCP client if it's option changed, or if it's not + # running, but it should be running (e.g. on system startup) + if 'dhcp_options_changed' in self._config or not is_systemd_service_active(systemd_service): + return self._cmd(f'systemctl restart {systemd_service}') + return None else: + if is_systemd_service_active(systemd_service): + self._cmd(f'systemctl stop {systemd_service}') # cleanup old config files for file in [config_file, options_file, pid_file, lease_file]: if os.path.isfile(file): @@ -1446,11 +1452,6 @@ class Interface(Control): value = tmp if (tmp != None) else '0' self.set_tcp_ipv4_mss(value) - # Configure MSS value for IPv6 TCP connections - tmp = dict_search('ipv6.adjust_mss', config) - value = tmp if (tmp != None) else '0' - self.set_tcp_ipv6_mss(value) - # Configure ARP cache timeout in milliseconds - has default value tmp = dict_search('ip.arp_cache_timeout', config) value = tmp if (tmp != None) else '30' @@ -1496,47 +1497,54 @@ class Interface(Control): value = tmp if (tmp != None) else '0' self.set_ipv4_source_validation(value) - # IPv6 forwarding - tmp = dict_search('ipv6.disable_forwarding', config) - value = '0' if (tmp != None) else '1' - self.set_ipv6_forwarding(value) - - # IPv6 router advertisements - 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 = 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 = dict_search('ipv6.dup_addr_detect_transmits', config) - value = tmp if (tmp != None) else '1' - self.set_ipv6_dad_messages(value) - - # MTU - Maximum Transfer Unit - if 'mtu' in config: - self.set_mtu(config.get('mtu')) - - # Delete old IPv6 EUI64 addresses before changing MAC - for addr in (dict_search('ipv6.address.eui64_old', config) or []): - self.del_ipv6_eui64_address(addr) - - # Manage IPv6 link-local addresses - if dict_search('ipv6.address.no_default_link_local', config) != None: - self.del_ipv6_eui64_address('fe80::/64') - else: - self.add_ipv6_eui64_address('fe80::/64') + # Only change IPv6 parameters if IPv6 was not explicitly disabled + if sysctl_read('net.ipv6.conf.all.disable_ipv6') == '0': + # Configure MSS value for IPv6 TCP connections + tmp = dict_search('ipv6.adjust_mss', config) + value = tmp if (tmp != None) else '0' + self.set_tcp_ipv6_mss(value) + + # IPv6 forwarding + tmp = dict_search('ipv6.disable_forwarding', config) + value = '0' if (tmp != None) else '1' + self.set_ipv6_forwarding(value) + + # IPv6 router advertisements + 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 = 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 = dict_search('ipv6.dup_addr_detect_transmits', config) + value = tmp if (tmp != None) else '1' + self.set_ipv6_dad_messages(value) + + # MTU - Maximum Transfer Unit + if 'mtu' in config: + self.set_mtu(config.get('mtu')) + + # Delete old IPv6 EUI64 addresses before changing MAC + for addr in (dict_search('ipv6.address.eui64_old', config) or []): + self.del_ipv6_eui64_address(addr) + + # Manage IPv6 link-local addresses + if dict_search('ipv6.address.no_default_link_local', config) != None: + self.del_ipv6_eui64_address('fe80::/64') + else: + self.add_ipv6_eui64_address('fe80::/64') - # Add IPv6 EUI-based addresses - tmp = dict_search('ipv6.address.eui64', config) - if tmp: - for addr in tmp: - self.add_ipv6_eui64_address(addr) + # Add IPv6 EUI-based addresses + tmp = dict_search('ipv6.address.eui64', config) + if tmp: + for addr in tmp: + self.add_ipv6_eui64_address(addr) # re-add ourselves to any bridge we might have fallen out of if 'is_bridge_member' in config: diff --git a/python/vyos/ifconfig/loopback.py b/python/vyos/ifconfig/loopback.py index 192c12f5c..de554ef44 100644 --- a/python/vyos/ifconfig/loopback.py +++ b/python/vyos/ifconfig/loopback.py @@ -1,4 +1,4 @@ -# Copyright 2019-2021 VyOS maintainers and contributors <maintainers@vyos.io> +# Copyright 2019-2022 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 @@ -13,6 +13,8 @@ # 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 vyos.util + from vyos.ifconfig.interface import Interface @Interface.register @@ -23,7 +25,6 @@ class LoopbackIf(Interface): """ _persistent_addresses = ['127.0.0.1/8', '::1/128'] iftype = 'loopback' - definition = { **Interface.definition, **{ @@ -32,6 +33,9 @@ class LoopbackIf(Interface): 'bridgeable': True, } } + + name = 'loopback' + def remove(self): """ Loopback interface can not be deleted from operating system. We can @@ -59,7 +63,10 @@ class LoopbackIf(Interface): addr = config.get('address', []) # We must ensure that the loopback addresses are never deleted from the system - addr += self._persistent_addresses + addr += ['127.0.0.1/8'] + + if (vyos.util.sysctl_read('net.ipv6.conf.all.disable_ipv6') == '0'): + addr += ['::1/128'] # Update IP address entry in our dictionary config.update({'address' : addr}) diff --git a/python/vyos/ifconfig/vxlan.py b/python/vyos/ifconfig/vxlan.py index 0c5282db4..516a19f24 100644 --- a/python/vyos/ifconfig/vxlan.py +++ b/python/vyos/ifconfig/vxlan.py @@ -1,4 +1,4 @@ -# Copyright 2019-2021 VyOS maintainers and contributors <maintainers@vyos.io> +# Copyright 2019-2022 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 @@ -68,6 +68,16 @@ class VXLANIf(Interface): 'vni' : 'id', } + # IPv6 flowlabels can only be used on IPv6 tunnels, thus we need to + # ensure that at least the first remote IP address is passed to the + # tunnel creation command. Subsequent tunnel remote addresses can later + # be added to the FDB + remote_list = None + if 'remote' in self.config: + # skip first element as this is already configured as remote + remote_list = self.config['remote'][1:] + self.config['remote'] = self.config['remote'][0] + cmd = 'ip link add {ifname} type {type} dstport {port}' for vyos_key, iproute2_key in mapping.items(): # dict_search will return an empty dict "{}" for valueless nodes like @@ -82,3 +92,10 @@ class VXLANIf(Interface): self._cmd(cmd.format(**self.config)) # interface is always A/D down. It needs to be enabled explicitly self.set_admin_state('down') + + # VXLAN tunnel is always recreated on any change - see interfaces-vxlan.py + if remote_list: + for remote in remote_list: + cmd = f'bridge fdb append to 00:00:00:00:00:00 dst {remote} ' \ + 'port {port} dev {ifname}' + self._cmd(cmd.format(**self.config)) diff --git a/python/vyos/ifconfig/wireless.py b/python/vyos/ifconfig/wireless.py index 748b6e02d..88eaa772b 100644 --- a/python/vyos/ifconfig/wireless.py +++ b/python/vyos/ifconfig/wireless.py @@ -49,10 +49,10 @@ class WiFiIf(Interface): on any interface. """ # We can not call add_to_bridge() until wpa_supplicant is running, thus - # we will remove the key from the config dict and react to this specal - # case in thie derived class. + # we will remove the key from the config dict and react to this special + # case in this derived class. # re-add ourselves to any bridge we might have fallen out of - bridge_member = '' + bridge_member = None if 'is_bridge_member' in config: bridge_member = config['is_bridge_member'] del config['is_bridge_member'] |