From c1ad2a6461fc2e767d69567be9647150c3310569 Mon Sep 17 00:00:00 2001 From: Jernej Jakob Date: Sun, 3 May 2020 13:28:11 +0200 Subject: configdict: T2241: get interface name in intf/vlan_from_dict This is needed as later functions depend on it --- src/conf_mode/interfaces-pseudo-ethernet.py | 1 - 1 file changed, 1 deletion(-) (limited to 'src/conf_mode/interfaces-pseudo-ethernet.py') diff --git a/src/conf_mode/interfaces-pseudo-ethernet.py b/src/conf_mode/interfaces-pseudo-ethernet.py index f0f893b44..67250ec9f 100755 --- a/src/conf_mode/interfaces-pseudo-ethernet.py +++ b/src/conf_mode/interfaces-pseudo-ethernet.py @@ -85,7 +85,6 @@ def get_config(): conf.set_level(cfg_base) peth, disabled = intf_to_dict(conf, default_config_data) - peth['intf'] = ifname # ARP cache entry timeout in seconds if conf.exists(['ip', 'arp-cache-timeout']): -- cgit v1.2.3 From 900e75e387939a1d1d4d5b0b79809b8bb2305b91 Mon Sep 17 00:00:00 2001 From: Jernej Jakob Date: Sun, 3 May 2020 13:46:47 +0200 Subject: validate: T2241: rewrite is_bridge_member to generic is_member - rewrite the function to support both bridge and bonding interface types, if the type is passed it searches only that type, otherwise it searches both - move is_member check out of the deleted condition - move is_member check to intf_from_dict for interfaces that use it --- python/vyos/configdict.py | 3 ++ python/vyos/validate.py | 44 ++++++++++++++++++++--------- src/conf_mode/interfaces-bonding.py | 3 -- src/conf_mode/interfaces-dummy.py | 7 +++-- src/conf_mode/interfaces-geneve.py | 7 +++-- src/conf_mode/interfaces-openvpn.py | 7 +++-- src/conf_mode/interfaces-pseudo-ethernet.py | 5 +--- src/conf_mode/interfaces-tunnel.py | 4 +-- src/conf_mode/interfaces-vxlan.py | 7 +++-- src/conf_mode/interfaces-wireguard.py | 7 +++-- src/conf_mode/interfaces-wireless.py | 7 +++-- src/conf_mode/interfaces-wirelessmodem.py | 7 +++-- 12 files changed, 65 insertions(+), 43 deletions(-) (limited to 'src/conf_mode/interfaces-pseudo-ethernet.py') diff --git a/python/vyos/configdict.py b/python/vyos/configdict.py index cd3364c94..ab72aac6c 100644 --- a/python/vyos/configdict.py +++ b/python/vyos/configdict.py @@ -23,6 +23,7 @@ from copy import deepcopy from vyos import ConfigError from vyos.ifconfig import Interface +from vyos.validate import is_member from vyos.util import ifname_from_config @@ -268,6 +269,8 @@ def intf_to_dict(conf, default): # Media Access Control (MAC) address if conf.exists('mac'): intf['mac'] = conf.return_value('mac') + # check if interface is member of a bridge + intf['is_bridge_member'] = is_member(conf, intf['intf'], 'bridge') # IPv6 Duplicate Address Detection (DAD) tries if conf.exists('ipv6 dup-addr-detect-transmits'): diff --git a/python/vyos/validate.py b/python/vyos/validate.py index 446f6e4ca..eb3f8bf52 100644 --- a/python/vyos/validate.py +++ b/python/vyos/validate.py @@ -241,25 +241,43 @@ def assert_mac(m): if octets[:5] == (0, 0, 94, 0, 1): raise ValueError(f'{m} is a VRRP MAC address') -def is_bridge_member(conf, interface): +def is_member(conf, interface, intftype=None): """ - Checks if passed interfaces is part of a bridge device or not. - - Returns a tuple: - None -> Interface not a bridge member - Bridge -> Interface is a member of this bridge + Checks if passed interface is member of other interface of specified type. + intftype is optional, if not passed it will search all known types + (currently bridge and bonding) + + 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 - old_level = conf.get_level() + + if intftype not in ['bonding', 'bridge', None]: + raise ValueError(( + f'unknown interface type "{intftype}" or it cannot ' + f'have member interfaces')) + + intftype = ['bonding', 'bridge'] if intftype == None else [intftype] # set config level to root + old_level = conf.get_level() conf.set_level([]) - base = ['interfaces', 'bridge'] - for bridge in conf.list_nodes(base): - members = conf.list_nodes(base + [bridge, 'member', 'interface']) - if interface in members: - ret_val = bridge - break + + for it in intftype: + base = 'interfaces ' + it + for intf in conf.list_nodes(base): + memberintf = f'{base} {intf} member interface' + if conf.is_tag(memberintf): + if interface in conf.list_nodes(memberintf): + ret_val = intf + break + elif conf.is_leaf(memberintf): + if ( conf.exists(memberintf) and + interface in conf.return_values(memberintf) ): + ret_val = intf + break old_level = conf.set_level(old_level) return ret_val diff --git a/src/conf_mode/interfaces-bonding.py b/src/conf_mode/interfaces-bonding.py index 76caefabe..0fc8cfa6c 100755 --- a/src/conf_mode/interfaces-bonding.py +++ b/src/conf_mode/interfaces-bonding.py @@ -25,7 +25,6 @@ from vyos.ifconfig_vlan import apply_vlan_config, verify_vlan_config from vyos.configdict import list_diff, intf_to_dict, add_to_dict from vyos.config import Config from vyos.util import call, cmd -from vyos.validate import is_bridge_member from vyos import ConfigError default_config_data = { @@ -111,8 +110,6 @@ def get_config(): bond = deepcopy(default_config_data) bond['intf'] = ifname bond['deleted'] = True - # check if interface is member if a bridge - bond['is_bridge_member'] = is_bridge_member(conf, ifname) return bond # set new configuration level diff --git a/src/conf_mode/interfaces-dummy.py b/src/conf_mode/interfaces-dummy.py index 23eaa4ecb..7bc834be5 100755 --- a/src/conf_mode/interfaces-dummy.py +++ b/src/conf_mode/interfaces-dummy.py @@ -23,7 +23,7 @@ from netifaces import interfaces from vyos.ifconfig import DummyIf from vyos.configdict import list_diff from vyos.config import Config -from vyos.validate import is_bridge_member +from vyos.validate import is_member from vyos import ConfigError default_config_data = { @@ -47,11 +47,12 @@ def get_config(): dummy['intf'] = os.environ['VYOS_TAGNODE_VALUE'] + # check if we are a member of any bridge + dummy['is_bridge_member'] = is_member(conf, dummy['intf'], 'bridge') + # Check if interface has been removed if not conf.exists('interfaces dummy ' + dummy['intf']): dummy['deleted'] = True - # check if interface is member if a bridge - dummy['is_bridge_member'] = is_bridge_member(conf, dummy['intf']) return dummy # set new configuration level diff --git a/src/conf_mode/interfaces-geneve.py b/src/conf_mode/interfaces-geneve.py index 708a64474..98f0672c5 100755 --- a/src/conf_mode/interfaces-geneve.py +++ b/src/conf_mode/interfaces-geneve.py @@ -22,7 +22,7 @@ from netifaces import interfaces from vyos.config import Config from vyos.ifconfig import GeneveIf -from vyos.validate import is_bridge_member +from vyos.validate import is_member from vyos import ConfigError default_config_data = { @@ -49,11 +49,12 @@ def get_config(): geneve['intf'] = os.environ['VYOS_TAGNODE_VALUE'] + # check if interface is member if a bridge + geneve['is_bridge_member'] = is_member(conf, geneve['intf'], 'bridge') + # Check if interface has been removed if not conf.exists('interfaces geneve ' + geneve['intf']): geneve['deleted'] = True - # check if interface is member if a bridge - geneve['is_bridge_member'] = is_bridge_member(conf, geneve['intf']) return geneve # set new configuration level diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py index 029bc1d69..23a690bf2 100755 --- a/src/conf_mode/interfaces-openvpn.py +++ b/src/conf_mode/interfaces-openvpn.py @@ -29,7 +29,7 @@ from vyos.configdict import list_diff from vyos.ifconfig import VTunIf from vyos.template import render from vyos.util import call, chown, chmod_600, chmod_755 -from vyos.validate import is_addr_assigned, is_bridge_member, is_ipv4 +from vyos.validate import is_addr_assigned, is_member, is_ipv4 from vyos import ConfigError user = 'openvpn' @@ -199,11 +199,12 @@ def get_config(): openvpn['intf'] = os.environ['VYOS_TAGNODE_VALUE'] 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') + # Check if interface instance has been removed if not conf.exists('interfaces openvpn ' + openvpn['intf']): openvpn['deleted'] = True - # check if interface is member if a bridge - openvpn['is_bridge_member'] = is_bridge_member(conf, openvpn['intf']) return openvpn # Check if we belong to any bridge interface diff --git a/src/conf_mode/interfaces-pseudo-ethernet.py b/src/conf_mode/interfaces-pseudo-ethernet.py index 67250ec9f..f9523ca8b 100755 --- a/src/conf_mode/interfaces-pseudo-ethernet.py +++ b/src/conf_mode/interfaces-pseudo-ethernet.py @@ -21,10 +21,9 @@ from sys import exit from netifaces import interfaces from vyos.config import Config -from vyos.configdict import list_diff, vlan_to_dict, intf_to_dict, add_to_dict +from vyos.configdict import list_diff, intf_to_dict, add_to_dict from vyos.ifconfig import MACVLANIf, Section from vyos.ifconfig_vlan import apply_vlan_config, verify_vlan_config -from vyos.validate import is_bridge_member from vyos import ConfigError default_config_data = { @@ -77,8 +76,6 @@ def get_config(): if not conf.exists(cfg_base): peth = deepcopy(default_config_data) peth['deleted'] = True - # check if interface is member if a bridge - peth['is_bridge_member'] = is_bridge_member(conf, ifname) return peth # set new configuration level diff --git a/src/conf_mode/interfaces-tunnel.py b/src/conf_mode/interfaces-tunnel.py index fc084814a..1916d2de2 100755 --- a/src/conf_mode/interfaces-tunnel.py +++ b/src/conf_mode/interfaces-tunnel.py @@ -25,7 +25,7 @@ from vyos.config import Config from vyos.ifconfig import Interface, GREIf, GRETapIf, IPIPIf, IP6GREIf, IPIP6If, IP6IP6If, SitIf, Sit6RDIf from vyos.ifconfig.afi import IP4, IP6 from vyos.configdict import list_diff -from vyos.validate import is_ipv4, is_ipv6, is_bridge_member +from vyos.validate import is_ipv4, is_ipv6, is_member from vyos import ConfigError from vyos.dicts import FixedDict @@ -410,7 +410,7 @@ def get_config(): options['tunnel'] = {} # check for bridges - options['bridge'] = is_bridge_member(conf, ifname) + options['bridge'] = is_member(conf, ifname, 'bridge') options['interfaces'] = interfaces() for name in ct: diff --git a/src/conf_mode/interfaces-vxlan.py b/src/conf_mode/interfaces-vxlan.py index 74eae4281..334e418ab 100755 --- a/src/conf_mode/interfaces-vxlan.py +++ b/src/conf_mode/interfaces-vxlan.py @@ -22,7 +22,7 @@ from netifaces import interfaces from vyos.config import Config from vyos.ifconfig import VXLANIf, Interface -from vyos.validate import is_bridge_member +from vyos.validate import is_member from vyos import ConfigError default_config_data = { @@ -62,11 +62,12 @@ def get_config(): vxlan['intf'] = os.environ['VYOS_TAGNODE_VALUE'] + # check if interface is member if a bridge + vxlan['is_bridge_member'] = is_member(conf, vxlan['intf'], 'bridge') + # Check if interface has been removed if not conf.exists('interfaces vxlan ' + vxlan['intf']): vxlan['deleted'] = True - # check if interface is member if a bridge - vxlan['is_bridge_member'] = is_bridge_member(conf, vxlan['intf']) return vxlan # set new configuration level diff --git a/src/conf_mode/interfaces-wireguard.py b/src/conf_mode/interfaces-wireguard.py index 01f84260d..98d5fcb27 100755 --- a/src/conf_mode/interfaces-wireguard.py +++ b/src/conf_mode/interfaces-wireguard.py @@ -25,7 +25,7 @@ from vyos.config import Config from vyos.configdict import list_diff from vyos.ifconfig import WireGuardIf from vyos.util import chown, chmod_750, call -from vyos.validate import is_bridge_member +from vyos.validate import is_member from vyos import ConfigError kdir = r'/config/auth/wireguard' @@ -78,11 +78,12 @@ def get_config(): wg = deepcopy(default_config_data) wg['intf'] = os.environ['VYOS_TAGNODE_VALUE'] + # check if interface is member if a bridge + wg['is_bridge_member'] = is_member(conf, wg['intf'], 'bridge') + # Check if interface has been removed if not conf.exists(base + [wg['intf']]): wg['deleted'] = True - # check if interface is member if a bridge - wg['is_bridge_member'] = is_bridge_member(conf, wg['intf']) return wg conf.set_level(base + [wg['intf']]) diff --git a/src/conf_mode/interfaces-wireless.py b/src/conf_mode/interfaces-wireless.py index 148a7f6e0..04125ff31 100755 --- a/src/conf_mode/interfaces-wireless.py +++ b/src/conf_mode/interfaces-wireless.py @@ -29,7 +29,7 @@ from vyos.ifconfig import WiFiIf, Section from vyos.ifconfig_vlan import apply_vlan_config, verify_vlan_config from vyos.template import render from vyos.util import chown, call -from vyos.validate import is_bridge_member +from vyos.validate import is_member from vyos import ConfigError default_config_data = { @@ -134,12 +134,13 @@ def get_config(): wifi['intf'] = os.environ['VYOS_TAGNODE_VALUE'] + # check if interface is member if a bridge + wifi['is_bridge_member'] = is_member(conf, wifi['intf'], 'bridge') + # check if wireless interface has been removed cfg_base = 'interfaces wireless ' + wifi['intf'] if not conf.exists(cfg_base): wifi['deleted'] = True - # check if interface is member if a bridge - wifi['is_bridge_member'] = is_bridge_member(conf, wifi['intf']) # we can not bail out early as wireless interface can not be removed # Kernel will complain with: RTNETLINK answers: Operation not supported. # Thus we need to remove individual settings diff --git a/src/conf_mode/interfaces-wirelessmodem.py b/src/conf_mode/interfaces-wirelessmodem.py index a3a2a2648..03832f345 100755 --- a/src/conf_mode/interfaces-wirelessmodem.py +++ b/src/conf_mode/interfaces-wirelessmodem.py @@ -23,7 +23,7 @@ from netifaces import interfaces from vyos.config import Config from vyos.template import render from vyos.util import chown, chmod_755, cmd, call -from vyos.validate import is_bridge_member +from vyos.validate import is_member from vyos import ConfigError default_config_data = { @@ -64,11 +64,12 @@ def get_config(): wwan['logfile'] = f"/var/log/vyatta/ppp_{wwan['intf']}.log" wwan['chat_script'] = f"/etc/ppp/peers/chat.{wwan['intf']}" + # check if interface is member if a bridge + wwan['is_bridge_member'] = is_member(conf, wwan['intf'], 'bridge') + # Check if interface has been removed if not conf.exists('interfaces wirelessmodem ' + wwan['intf']): wwan['deleted'] = True - # check if interface is member if a bridge - wwan['is_bridge_member'] = is_bridge_member(conf, wwan['intf']) return wwan # set new configuration level -- cgit v1.2.3 From f11ce49a670507f814183e27c4f3e50e29e54e6e Mon Sep 17 00:00:00 2001 From: Jernej Jakob Date: Fri, 1 May 2020 19:41:42 +0200 Subject: pseudo-ethernet: T2241: make VRF and bridge membership mutually exclusive --- src/conf_mode/interfaces-pseudo-ethernet.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src/conf_mode/interfaces-pseudo-ethernet.py') diff --git a/src/conf_mode/interfaces-pseudo-ethernet.py b/src/conf_mode/interfaces-pseudo-ethernet.py index f9523ca8b..9f01cf0c1 100755 --- a/src/conf_mode/interfaces-pseudo-ethernet.py +++ b/src/conf_mode/interfaces-pseudo-ethernet.py @@ -122,9 +122,15 @@ def verify(peth): if not peth['source_interface'] in interfaces(): raise ConfigError('Pseudo-ethernet source-interface does not exist') - vrf_name = peth['vrf'] - if vrf_name and vrf_name not in interfaces(): - raise ConfigError(f'VRF "{vrf_name}" does not exist') + if peth['vrf']: + if peth['vrf'] not in interfaces(): + raise ConfigError(f'VRF "{peth["vrf"]}" does not exist') + + if peth['is_bridge_member']: + raise ConfigError(( + f'Interface "{peth["intf"]}" cannot be member of VRF ' + f'"{peth["vrf"]}" and bridge {peth["is_bridge_member"]} ' + f'at the same time!')) # use common function to verify VLAN configuration verify_vlan_config(peth) -- cgit v1.2.3 From 50ca89433c2a29367a36f5f049821a9bedb39d24 Mon Sep 17 00:00:00 2001 From: Jernej Jakob Date: Fri, 1 May 2020 19:44:17 +0200 Subject: pseudo-ethernet: T2241: make address and bridge membership mutually exclusive Bridge members should not have any addresses assigned. --- src/conf_mode/interfaces-pseudo-ethernet.py | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/conf_mode/interfaces-pseudo-ethernet.py') diff --git a/src/conf_mode/interfaces-pseudo-ethernet.py b/src/conf_mode/interfaces-pseudo-ethernet.py index 9f01cf0c1..e06f14a95 100755 --- a/src/conf_mode/interfaces-pseudo-ethernet.py +++ b/src/conf_mode/interfaces-pseudo-ethernet.py @@ -122,6 +122,14 @@ def verify(peth): if not peth['source_interface'] in interfaces(): raise ConfigError('Pseudo-ethernet source-interface does not exist') + if ( peth['is_bridge_member'] + and ( peth['address'] + or peth['ipv6_eui64_prefix'] + or peth['ipv6_autoconf'] ) ): + raise ConfigError(( + f'Cannot assign address to interface "{peth["intf"]}" ' + f'as it is a member of bridge "{peth["is_bridge_member"]}"!')) + if peth['vrf']: if peth['vrf'] not in interfaces(): raise ConfigError(f'VRF "{peth["vrf"]}" does not exist') -- cgit v1.2.3 From f45c165ca53d4c9e8017d36940de768d7419e097 Mon Sep 17 00:00:00 2001 From: Jernej Jakob Date: Fri, 1 May 2020 19:45:11 +0200 Subject: pseudo-ethernet: T2241: fix falling out of bridge when changing settings Previously, the interface was always deleted and recreated, which removed it from the bridge. - add checks to make VRF and bridge membership mutually exclusive - always re-add the interface back to any bridge it is part of --- src/conf_mode/interfaces-pseudo-ethernet.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/conf_mode/interfaces-pseudo-ethernet.py') diff --git a/src/conf_mode/interfaces-pseudo-ethernet.py b/src/conf_mode/interfaces-pseudo-ethernet.py index e06f14a95..bd0942fd8 100755 --- a/src/conf_mode/interfaces-pseudo-ethernet.py +++ b/src/conf_mode/interfaces-pseudo-ethernet.py @@ -213,8 +213,10 @@ def apply(peth): # IPv6 Duplicate Address Detection (DAD) tries p.set_ipv6_dad_messages(peth['ipv6_dup_addr_detect']) - # assign/remove VRF - p.set_vrf(peth['vrf']) + # assign/remove VRF (ONLY when not a member of a bridge, + # otherwise 'nomaster' removes it from it) + if not peth['is_bridge_member']: + p.set_vrf(peth['vrf']) # Delete old IPv6 EUI64 addresses before changing MAC for addr in peth['ipv6_eui64_prefix_remove']: @@ -245,6 +247,10 @@ def apply(peth): for addr in peth['address']: p.add_addr(addr) + # re-add ourselves to any bridge we might have fallen out of + if peth['is_bridge_member']: + p.add_to_bridge(peth['is_bridge_member']) + # remove no longer required service VLAN interfaces (vif-s) for vif_s in peth['vif_s_remove']: p.del_vlan(vif_s) -- cgit v1.2.3 From ee58d8ef363d989ab7c63441b84489a6c45cfc31 Mon Sep 17 00:00:00 2001 From: Jernej Jakob Date: Fri, 1 May 2020 19:48:48 +0200 Subject: pseudo-ethernet: T2241: cleanup verify section - make error output more user friendly - replace .format with f-strings - split into lines less than ~80 characters long --- src/conf_mode/interfaces-pseudo-ethernet.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'src/conf_mode/interfaces-pseudo-ethernet.py') diff --git a/src/conf_mode/interfaces-pseudo-ethernet.py b/src/conf_mode/interfaces-pseudo-ethernet.py index bd0942fd8..1d04d6dbe 100755 --- a/src/conf_mode/interfaces-pseudo-ethernet.py +++ b/src/conf_mode/interfaces-pseudo-ethernet.py @@ -110,17 +110,19 @@ def get_config(): def verify(peth): if peth['deleted']: if peth['is_bridge_member']: - interface = peth['intf'] - bridge = peth['is_bridge_member'] - raise ConfigError(f'Interface "{interface}" can not be deleted as it belongs to bridge "{bridge}"!') + raise ConfigError(( + f'Cannot delete interface "{peth["intf"]}" as it is a ' + f'member of bridge "{peth["is_bridge_member"]}"!')) return None if not peth['source_interface']: - raise ConfigError('source-interface must be set for virtual ethernet {}'.format(peth['intf'])) + raise ConfigError(( + f'Link device must be set for pseudo-ethernet "{peth["intf"]}"')) if not peth['source_interface'] in interfaces(): - raise ConfigError('Pseudo-ethernet source-interface does not exist') + raise ConfigError(( + f'Pseudo-ethernet "{peth["intf"]}" link device does not exist') if ( peth['is_bridge_member'] and ( peth['address'] -- cgit v1.2.3 From d6a93991d1a3a5e4575ccd3d586e9f8f48234544 Mon Sep 17 00:00:00 2001 From: Jernej Jakob Date: Tue, 5 May 2020 16:09:42 +0200 Subject: pseudo-ethernet: T2427: move VLAN adding to common function --- src/conf_mode/interfaces-pseudo-ethernet.py | 36 ++++------------------------- 1 file changed, 5 insertions(+), 31 deletions(-) (limited to 'src/conf_mode/interfaces-pseudo-ethernet.py') diff --git a/src/conf_mode/interfaces-pseudo-ethernet.py b/src/conf_mode/interfaces-pseudo-ethernet.py index 1d04d6dbe..4063b85b0 100755 --- a/src/conf_mode/interfaces-pseudo-ethernet.py +++ b/src/conf_mode/interfaces-pseudo-ethernet.py @@ -23,7 +23,7 @@ from netifaces import interfaces from vyos.config import Config from vyos.configdict import list_diff, intf_to_dict, add_to_dict from vyos.ifconfig import MACVLANIf, Section -from vyos.ifconfig_vlan import apply_vlan_config, verify_vlan_config +from vyos.ifconfig_vlan import apply_all_vlans, verify_vlan_config from vyos import ConfigError default_config_data = { @@ -56,9 +56,9 @@ default_config_data = { 'source_interface_changed': False, 'mac': '', 'mode': 'private', - 'vif_s': [], + 'vif_s': {}, 'vif_s_remove': [], - 'vif': [], + 'vif': {}, 'vif_remove': [], 'vrf': '' } @@ -253,34 +253,8 @@ def apply(peth): if peth['is_bridge_member']: p.add_to_bridge(peth['is_bridge_member']) - # remove no longer required service VLAN interfaces (vif-s) - for vif_s in peth['vif_s_remove']: - p.del_vlan(vif_s) - - # create service VLAN interfaces (vif-s) - for vif_s in peth['vif_s']: - s_vlan = p.add_vlan(vif_s['id'], ethertype=vif_s['ethertype']) - apply_vlan_config(s_vlan, vif_s) - - # remove no longer required client VLAN interfaces (vif-c) - # on lower service VLAN interface - for vif_c in vif_s['vif_c_remove']: - s_vlan.del_vlan(vif_c) - - # create client VLAN interfaces (vif-c) - # on lower service VLAN interface - for vif_c in vif_s['vif_c']: - c_vlan = s_vlan.add_vlan(vif_c['id']) - apply_vlan_config(c_vlan, vif_c) - - # remove no longer required VLAN interfaces (vif) - for vif in peth['vif_remove']: - p.del_vlan(vif) - - # create VLAN interfaces (vif) - for vif in peth['vif']: - vlan = p.add_vlan(vif['id']) - apply_vlan_config(vlan, vif) + # apply all vlans to interface + apply_all_vlans(b, bond) return None -- cgit v1.2.3