diff options
author | Christian Poessinger <christian@poessinger.com> | 2020-10-17 20:06:36 +0200 |
---|---|---|
committer | Christian Poessinger <christian@poessinger.com> | 2020-10-17 22:06:49 +0200 |
commit | b5ef10cfeb839dca28ae5376bfabafe29ae07aec (patch) | |
tree | 10f5858d48e91f93ca440d2cd24c5c78c7a36add /src | |
parent | 1353c006469754ae96c1cc4e6238d80e735985bc (diff) | |
download | vyos-1x-b5ef10cfeb839dca28ae5376bfabafe29ae07aec.tar.gz vyos-1x-b5ef10cfeb839dca28ae5376bfabafe29ae07aec.zip |
ifconfig: T2985: support on demand bridge creation
The current implementation for bridge based interfaces has an issue which is
caused by priority inheritance. We always assumed that the bridge interface will
be created last, but this may not be true in all cases, where some interfaces
will be created "on demand" - e.g. OpenVPN or late (VXLAN, GENEVE).
As we already have a bunch of verify steps in place we should not see a bridge
interface leak to the underlaying infrastructure code. This means, whenever an
interface will be member of a bridge, and the bridge does yet not exist, we will
create it in advance in the interface context, as the bridge code will be run
in the same commit but maybe sooner or later.
This will also be the solution for T2924.
Diffstat (limited to 'src')
-rwxr-xr-x | src/conf_mode/interfaces-bonding.py | 6 | ||||
-rwxr-xr-x | src/conf_mode/interfaces-bridge.py | 23 | ||||
-rwxr-xr-x | src/conf_mode/interfaces-openvpn.py | 3 | ||||
-rwxr-xr-x | src/conf_mode/interfaces-tunnel.py | 3 |
4 files changed, 18 insertions, 17 deletions
diff --git a/src/conf_mode/interfaces-bonding.py b/src/conf_mode/interfaces-bonding.py index 9763620ac..ea9bd54d4 100755 --- a/src/conf_mode/interfaces-bonding.py +++ b/src/conf_mode/interfaces-bonding.py @@ -109,7 +109,7 @@ def get_config(config=None): # Check if member interface is already member of a bond tmp = is_member(conf, interface, 'bonding') - if tmp and tmp != bond['ifname']: + if tmp and bond['ifname'] not in tmp: interface_config.update({'is_bond_member' : tmp}) # Check if member interface is used as source-interface on another interface @@ -162,11 +162,11 @@ def verify(bond): raise ConfigError(error_msg + 'it does not exist!') if 'is_bridge_member' in interface_config: - tmp = interface_config['is_bridge_member'] + tmp = next(iter(interface_config['is_bridge_member'])) raise ConfigError(error_msg + f'it is already a member of bridge "{tmp}"!') if 'is_bond_member' in interface_config: - tmp = interface_config['is_bond_member'] + tmp = next(iter(interface_config['is_bond_member'])) raise ConfigError(error_msg + f'it is already a member of bond "{tmp}"!') if 'is_source_interface' in interface_config: diff --git a/src/conf_mode/interfaces-bridge.py b/src/conf_mode/interfaces-bridge.py index 485decb17..4aeb8fc67 100755 --- a/src/conf_mode/interfaces-bridge.py +++ b/src/conf_mode/interfaces-bridge.py @@ -24,6 +24,7 @@ from vyos.configdict import get_interface_dict from vyos.configdict import node_changed from vyos.configdict import is_member from vyos.configdict import is_source_interface +from vyos.configdict import dict_merge from vyos.configverify import verify_dhcpv6 from vyos.configverify import verify_vrf from vyos.ifconfig import BridgeIf @@ -69,25 +70,26 @@ def get_config(config=None): # the default dictionary is not properly paged into the dict (see T2665) # thus we will ammend it ourself default_member_values = defaults(base + ['member', 'interface']) - for interface, interface_config in bridge['member']['interface'].items(): - interface_config.update(default_member_values) + for interface in bridge['member']['interface']: + bridge['member']['interface'][interface] = dict_merge( + default_member_values, bridge['member']['interface'][interface]) # Check if member interface is already member of another bridge tmp = is_member(conf, interface, 'bridge') - if tmp and tmp != bridge['ifname']: - interface_config.update({'is_bridge_member' : tmp}) + if tmp and bridge['ifname'] not in tmp: + bridge['member']['interface'][interface].update({'is_bridge_member' : tmp}) # Check if member interface is already member of a bond tmp = is_member(conf, interface, 'bonding') - if tmp: interface_config.update({'is_bond_member' : tmp}) + if tmp: bridge['member']['interface'][interface].update({'is_bond_member' : tmp}) # Check if member interface is used as source-interface on another interface tmp = is_source_interface(conf, interface) - if tmp: interface_config.update({'is_source_interface' : tmp}) + if tmp: bridge['member']['interface'][interface].update({'is_source_interface' : tmp}) # Bridge members must not have an assigned address tmp = has_address_configured(conf, interface) - if tmp: interface_config.update({'has_address' : ''}) + if tmp: bridge['member']['interface'][interface].update({'has_address' : ''}) return bridge @@ -105,15 +107,12 @@ def verify(bridge): if interface == 'lo': raise ConfigError('Loopback interface "lo" can not be added to a bridge') - if interface not in interfaces(): - raise ConfigError(error_msg + 'it does not exist!') - if 'is_bridge_member' in interface_config: - tmp = interface_config['is_bridge_member'] + tmp = next(iter(interface_config['is_bridge_member'])) raise ConfigError(error_msg + f'it is already a member of bridge "{tmp}"!') if 'is_bond_member' in interface_config: - tmp = interface_config['is_bond_member'] + tmp = next(iter(interface_config['is_bond_member'])) raise ConfigError(error_msg + f'it is already a member of bond "{tmp}"!') if 'is_source_interface' in interface_config: diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py index 518dbdc0e..f2b580c6f 100755 --- a/src/conf_mode/interfaces-openvpn.py +++ b/src/conf_mode/interfaces-openvpn.py @@ -208,7 +208,8 @@ def get_config(config=None): openvpn['auth_user_pass_file'] = f"/run/openvpn/{openvpn['intf']}.pw" # check if interface is member of a bridge - openvpn['is_bridge_member'] = is_member(conf, openvpn['intf'], 'bridge') + tmp = is_member(conf, openvpn['intf'], 'bridge') + if tmp: openvpn['is_bridge_member'] = next(iter(tmp)) # Check if interface instance has been removed if not conf.exists('interfaces openvpn ' + openvpn['intf']): diff --git a/src/conf_mode/interfaces-tunnel.py b/src/conf_mode/interfaces-tunnel.py index f1d885b15..5561514bd 100755 --- a/src/conf_mode/interfaces-tunnel.py +++ b/src/conf_mode/interfaces-tunnel.py @@ -462,7 +462,8 @@ def get_config(config=None): options['tunnel'] = {} # check for bridges - options['bridge'] = is_member(config, ifname, 'bridge') + tmp = is_member(config, ifname, 'bridge') + if tmp: options['bridge'] = next(iter(tmp)) options['interfaces'] = interfaces() for name in ct: |