diff options
author | Christian Poessinger <christian@poessinger.com> | 2020-09-22 18:37:00 +0200 |
---|---|---|
committer | Christian Poessinger <christian@poessinger.com> | 2020-09-22 18:38:35 +0200 |
commit | 83a9ce7991195c709736eec234fea3d60cde7582 (patch) | |
tree | 763b1c5b113dab172c6f1f00cdef2c1ca58316d3 /python | |
parent | d28a6a516d449ede788816574c35061fbf7d6485 (diff) | |
download | vyos-1x-83a9ce7991195c709736eec234fea3d60cde7582.tar.gz vyos-1x-83a9ce7991195c709736eec234fea3d60cde7582.zip |
ifconfig: T2653: bond: bridge: ensure member interface is not a source-interface
As we already check that a bond/bridge member interface is not a member of any
other bridge or bond, the check must be extended. We also need to ensure that
the bond member interface is not used as a source-interface to pppoe, macsec,
tunnel, pseudo-ethernet, vxlan interfaces.
Diffstat (limited to 'python')
-rw-r--r-- | python/vyos/configdict.py | 46 | ||||
-rw-r--r-- | python/vyos/configverify.py | 15 |
2 files changed, 59 insertions, 2 deletions
diff --git a/python/vyos/configdict.py b/python/vyos/configdict.py index 4a4a767f3..58ecd3f17 100644 --- a/python/vyos/configdict.py +++ b/python/vyos/configdict.py @@ -228,6 +228,41 @@ def is_member(conf, interface, intftype=None): old_level = conf.set_level(old_level) return ret_val +def is_source_interface(conf, interface, intftype=None): + """ + Checks if passed interface is configured as source-interface of other + interfaces of specified type. intftype is optional, if not passed it will + search all known types (currently pppoe, macsec, pseudo-ethernet, tunnel + and vxlan) + + Returns: + None -> Interface is not a member + interface name -> Interface is a member of this interface + False -> interface type cannot have members + """ + ret_val = None + intftypes = ['macsec', 'pppoe', 'pseudo-ethernet', 'tunnel', 'vxlan'] + if intftype not in intftypes + [None]: + raise ValueError(f'unknown interface type "{intftype}" or it can not ' + 'have a source-interface') + + intftype = intftypes if intftype == None else [intftype] + + # set config level to root + old_level = conf.get_level() + conf.set_level([]) + + for it in intftype: + base = ['interfaces', it] + for intf in conf.list_nodes(base): + lower_intf = base + [intf, 'source-interface'] + if conf.exists(lower_intf) and interface in conf.return_values(lower_intf): + ret_val = intf + break + + old_level = conf.set_level(old_level) + return ret_val + def get_interface_dict(config, base, ifname=''): """ Common utility function to retrieve and mandgle the interfaces available @@ -284,6 +319,17 @@ def get_interface_dict(config, base, ifname=''): bond = is_member(config, ifname, 'bonding') if bond: dict.update({'is_bond_member' : bond}) + # Some interfaces come with a source_interface which must also not be part + # of any other bond or bridge interface as it is exclusivly assigned as the + # Kernels "lower" interface to this new "virtual/upper" interface. + if 'source_interface' in dict: + # Check if source interface is member of another bridge + tmp = is_member(config, dict['source_interface'], 'bridge') + if tmp: dict.update({'source_interface_is_bridge_member' : tmp}) + + # Check if source interface is member of another bridge + tmp = is_member(config, dict['source_interface'], 'bonding') + if tmp: dict.update({'source_interface_is_bond_member' : tmp}) mac = leaf_node_changed(config, ['mac']) if mac: dict.update({'mac_old' : mac}) diff --git a/python/vyos/configverify.py b/python/vyos/configverify.py index 7e1930878..bf4e26fa7 100644 --- a/python/vyos/configverify.py +++ b/python/vyos/configverify.py @@ -82,9 +82,20 @@ def verify_source_interface(config): if 'source_interface' not in config: raise ConfigError('Physical source-interface required for ' 'interface "{ifname}"'.format(**config)) + if config['source_interface'] not in interfaces(): - raise ConfigError('Source interface {source_interface} does not ' - 'exist'.format(**config)) + raise ConfigError('Specified source-interface {source_interface} does ' + 'not exist'.format(**config)) + + if 'source_interface_is_bridge_member' in config: + raise ConfigError('Invalid source-interface {source_interface}. Interface ' + 'is already a member of bridge ' + '{source_interface_is_bridge_member}'.format(**config)) + + if 'source_interface_is_bond_member' in config: + raise ConfigError('Invalid source-interface {source_interface}. Interface ' + 'is already a member of bond ' + '{source_interface_is_bond_member}'.format(**config)) def verify_dhcpv6(config): """ |