2014-10-09 16:02:46 -07:00
#!/usr/bin/python
#
# Copyright 2014 Cumulus Networks, Inc. All rights reserved.
# Author: Roopa Prabhu, roopa@cumulusnetworks.com
#
from sets import Set
from ifupdown . iface import *
2016-03-14 16:45:12 -07:00
import ifupdown . policymanager as policymanager
2016-06-07 18:37:40 +01:00
from ifupdown . utils import utils
2014-10-09 16:02:46 -07:00
from ifupdownaddons . modulebase import moduleBase
from ifupdownaddons . bridgeutils import brctl
from ifupdownaddons . iproute2 import iproute2
2014-11-15 15:42:52 -08:00
from collections import Counter
2016-05-29 18:04:23 +01:00
from ifupdown . netlink import netlink
2016-04-14 14:45:47 -07:00
import ifupdown . ifupdownflags as ifupdownflags
2014-10-09 16:02:46 -07:00
import itertools
import re
2014-10-22 13:42:08 -07:00
import time
2014-10-09 16:02:46 -07:00
2015-04-23 20:19:22 -04:00
class bridgeFlags :
PORT_PROCESSED = 0x1
2015-11-08 12:13:16 -08:00
PORT_PROCESSED_OVERRIDE = 0x2
2015-04-23 20:19:22 -04:00
2014-10-09 16:02:46 -07:00
class bridge ( moduleBase ) :
""" ifupdown2 addon module to configure linux bridges """
2014-10-31 11:28:07 -07:00
_modinfo = { ' mhelp ' : ' Bridge configuration module. Supports both ' +
' vlan aware and non vlan aware bridges. For the vlan ' +
' aware bridge, the port specific attributes must be ' +
' specified under the port. And for vlan unaware bridge ' +
' port specific attributes must be specified under the ' +
' bridge. ' ,
2014-10-09 16:02:46 -07:00
' attrs ' : {
2014-10-24 10:11:07 -07:00
' bridge-vlan-aware ' :
2014-10-31 11:28:07 -07:00
{ ' help ' : ' vlan aware bridge. Setting this ' +
' attribute to yes enables vlan filtering ' +
' on the bridge ' ,
2016-05-31 13:12:21 -07:00
' validvals ' : [ ' yes ' , ' no ' ] ,
2014-10-24 10:11:07 -07:00
' example ' : [ ' bridge-vlan-aware yes/no ' ] } ,
2014-10-09 16:02:46 -07:00
' bridge-ports ' :
{ ' help ' : ' bridge ports ' ,
2016-05-31 13:12:21 -07:00
' multivalue ' : True ,
2014-10-09 16:02:46 -07:00
' required ' : True ,
2016-08-01 09:19:31 +02:00
' validvals ' : [ ' <interface-list> ' ] ,
2014-10-09 16:02:46 -07:00
' example ' : [ ' bridge-ports swp1.100 swp2.100 swp3.100 ' ,
' bridge-ports glob swp1-3.100 ' ,
' bridge-ports regex (swp[1|2|3].100) ' ] } ,
' bridge-stp ' :
{ ' help ' : ' bridge-stp yes/no ' ,
' example ' : [ ' bridge-stp no ' ] ,
' validvals ' : [ ' yes ' , ' on ' , ' off ' , ' no ' ] ,
' default ' : ' no ' } ,
' bridge-bridgeprio ' :
{ ' help ' : ' bridge priority ' ,
2016-05-31 13:12:21 -07:00
' validrange ' : [ ' 0 ' , ' 65535 ' ] ,
2014-10-09 16:02:46 -07:00
' example ' : [ ' bridge-bridgeprio 32768 ' ] ,
' default ' : ' 32768 ' } ,
' bridge-ageing ' :
{ ' help ' : ' bridge ageing ' ,
2016-05-31 13:12:21 -07:00
' validrange ' : [ ' 0 ' , ' 65535 ' ] ,
2014-10-09 16:02:46 -07:00
' example ' : [ ' bridge-ageing 300 ' ] ,
' default ' : ' 300 ' } ,
' bridge-fd ' :
{ ' help ' : ' bridge forward delay ' ,
2016-05-31 13:12:21 -07:00
' validrange ' : [ ' 0 ' , ' 255 ' ] ,
2014-10-09 16:02:46 -07:00
' example ' : [ ' bridge-fd 15 ' ] ,
' default ' : ' 15 ' } ,
' bridge-gcint ' :
# XXX: recheck values
{ ' help ' : ' bridge garbage collection interval in secs ' ,
2016-05-31 13:12:21 -07:00
' validrange ' : [ ' 0 ' , ' 255 ' ] ,
2014-10-09 16:02:46 -07:00
' example ' : [ ' bridge-gcint 4 ' ] ,
2016-05-10 17:53:41 -07:00
' default ' : ' 4 ' ,
' compat ' : True ,
' deprecated ' : True } ,
2014-10-09 16:02:46 -07:00
' bridge-hello ' :
{ ' help ' : ' bridge set hello time ' ,
2016-05-31 13:12:21 -07:00
' validrange ' : [ ' 0 ' , ' 255 ' ] ,
2014-10-09 16:02:46 -07:00
' example ' : [ ' bridge-hello 2 ' ] ,
' default ' : ' 2 ' } ,
' bridge-maxage ' :
{ ' help ' : ' bridge set maxage ' ,
2016-05-31 13:12:21 -07:00
' validrange ' : [ ' 0 ' , ' 255 ' ] ,
2014-10-09 16:02:46 -07:00
' example ' : [ ' bridge-maxage 20 ' ] ,
' default ' : ' 20 ' } ,
' bridge-pathcosts ' :
{ ' help ' : ' bridge set port path costs ' ,
2016-08-01 09:19:31 +02:00
' validvals ' : [ ' <interface-range-list> ' ] ,
2016-05-31 13:12:21 -07:00
' validrange ' : [ ' 0 ' , ' 65535 ' ] ,
' example ' : [ ' under the bridge: bridge-pathcosts swp1=100 swp2=100 ' ,
' under the port (recommended): bridge-pathcosts 100 ' ] ,
2014-10-09 16:02:46 -07:00
' default ' : ' 100 ' } ,
' bridge-portprios ' :
{ ' help ' : ' bridge port prios ' ,
2016-08-01 09:19:31 +02:00
' validvals ' : [ ' <interface-range-list> ' ] ,
2016-05-31 13:12:21 -07:00
' validrange ' : [ ' 0 ' , ' 65535 ' ] ,
' example ' : [ ' under the bridge: bridge-portprios swp1=32 swp2=32 ' ,
' under the port (recommended): bridge-portprios 32 ' ] ,
2014-10-09 16:02:46 -07:00
' default ' : ' 32 ' } ,
' bridge-mclmc ' :
{ ' help ' : ' set multicast last member count ' ,
2016-05-31 13:12:21 -07:00
' validrange ' : [ ' 0 ' , ' 255 ' ] ,
2014-10-09 16:02:46 -07:00
' example ' : [ ' bridge-mclmc 2 ' ] ,
' default ' : ' 2 ' } ,
' bridge-mcrouter ' :
{ ' help ' : ' set multicast router ' ,
2016-06-07 18:37:40 +01:00
' validvals ' : [ ' yes ' , ' no ' , ' 0 ' , ' 1 ' ] ,
' default ' : ' yes ' ,
' example ' : [ ' bridge-mcrouter yes ' ] } ,
2014-10-09 16:02:46 -07:00
' bridge-mcsnoop ' :
{ ' help ' : ' set multicast snooping ' ,
2016-06-07 18:37:40 +01:00
' validvals ' : [ ' yes ' , ' no ' , ' 0 ' , ' 1 ' ] ,
' default ' : ' yes ' ,
' example ' : [ ' bridge-mcsnoop yes ' ] } ,
2014-10-09 16:02:46 -07:00
' bridge-mcsqc ' :
{ ' help ' : ' set multicast startup query count ' ,
2016-05-31 13:12:21 -07:00
' validrange ' : [ ' 0 ' , ' 255 ' ] ,
2014-10-09 16:02:46 -07:00
' default ' : ' 2 ' ,
' example ' : [ ' bridge-mcsqc 2 ' ] } ,
' bridge-mcqifaddr ' :
{ ' help ' : ' set multicast query to use ifaddr ' ,
2016-06-07 18:37:40 +01:00
' validvals ' : [ ' yes ' , ' no ' , ' 0 ' , ' 1 ' ] ,
' default ' : ' no ' ,
' example ' : [ ' bridge-mcqifaddr no ' ] } ,
2014-10-09 16:02:46 -07:00
' bridge-mcquerier ' :
{ ' help ' : ' set multicast querier ' ,
2016-06-07 18:37:40 +01:00
' validvals ' : [ ' yes ' , ' no ' , ' 0 ' , ' 1 ' ] ,
' default ' : ' no ' ,
' example ' : [ ' bridge-mcquerier no ' ] } ,
2014-10-09 16:02:46 -07:00
' bridge-hashel ' :
{ ' help ' : ' set hash elasticity ' ,
2016-05-31 13:12:21 -07:00
' validrange ' : [ ' 0 ' , ' 4096 ' ] ,
2014-10-09 16:02:46 -07:00
' default ' : ' 4096 ' ,
' example ' : [ ' bridge-hashel 4096 ' ] } ,
' bridge-hashmax ' :
{ ' help ' : ' set hash max ' ,
2016-05-31 13:12:21 -07:00
' validrange ' : [ ' 0 ' , ' 4096 ' ] ,
2014-10-09 16:02:46 -07:00
' default ' : ' 4096 ' ,
' example ' : [ ' bridge-hashmax 4096 ' ] } ,
' bridge-mclmi ' :
{ ' help ' : ' set multicast last member interval (in secs) ' ,
2016-05-31 13:12:21 -07:00
' validrange ' : [ ' 0 ' , ' 255 ' ] ,
2014-10-09 16:02:46 -07:00
' default ' : ' 1 ' ,
' example ' : [ ' bridge-mclmi 1 ' ] } ,
' bridge-mcmi ' :
{ ' help ' : ' set multicast membership interval (in secs) ' ,
2016-05-31 13:12:21 -07:00
' validrange ' : [ ' 0 ' , ' 255 ' ] ,
2014-10-09 16:02:46 -07:00
' default ' : ' 260 ' ,
' example ' : [ ' bridge-mcmi 260 ' ] } ,
' bridge-mcqpi ' :
{ ' help ' : ' set multicast querier interval (in secs) ' ,
2016-05-31 13:12:21 -07:00
' validrange ' : [ ' 0 ' , ' 255 ' ] ,
2014-10-09 16:02:46 -07:00
' default ' : ' 255 ' ,
' example ' : [ ' bridge-mcqpi 255 ' ] } ,
' bridge-mcqi ' :
{ ' help ' : ' set multicast query interval (in secs) ' ,
2016-05-31 13:12:21 -07:00
' validrange ' : [ ' 0 ' , ' 255 ' ] ,
2014-10-09 16:02:46 -07:00
' default ' : ' 125 ' ,
' example ' : [ ' bridge-mcqi 125 ' ] } ,
' bridge-mcqri ' :
{ ' help ' : ' set multicast query response interval (in secs) ' ,
2016-05-31 13:12:21 -07:00
' validrange ' : [ ' 0 ' , ' 255 ' ] ,
2014-10-09 16:02:46 -07:00
' default ' : ' 10 ' ,
' example ' : [ ' bridge-mcqri 10 ' ] } ,
' bridge-mcsqi ' :
{ ' help ' : ' set multicast startup query interval (in secs) ' ,
2016-05-31 13:12:21 -07:00
' validrange ' : [ ' 0 ' , ' 255 ' ] ,
2014-10-09 16:02:46 -07:00
' default ' : ' 31 ' ,
' example ' : [ ' bridge-mcsqi 31 ' ] } ,
' bridge-mcqv4src ' :
{ ' help ' : ' set per VLAN v4 multicast querier source address ' ,
2016-05-31 13:12:21 -07:00
' validvals ' : [ ' <number-ipv4-list> ' , ] ,
' multivalue ' : True ,
2014-10-31 11:28:07 -07:00
' compat ' : True ,
2014-10-09 16:02:46 -07:00
' example ' : [ ' bridge-mcqv4src 100=172.16.100.1 101=172.16.101.1 ' ] } ,
' bridge-portmcrouter ' :
{ ' help ' : ' set port multicast routers ' ,
2016-08-01 09:19:31 +02:00
' validvals ' : [ ' <interface-yes-no-0-1-list> ' ] ,
2016-06-07 18:37:40 +01:00
' default ' : ' yes ' ,
' example ' : [ ' under the bridge: bridge-portmcrouter swp1=yes swp2=yes ' ,
' under the port (recommended): bridge-portmcrouter yes ' ] } ,
2014-10-09 16:02:46 -07:00
' bridge-portmcfl ' :
2014-10-31 11:28:07 -07:00
{ ' help ' : ' port multicast fast leave. ' ,
2016-08-01 09:19:31 +02:00
' validvals ' : [ ' <interface-range-list> ' ] ,
2016-05-31 13:12:21 -07:00
' validrange ' : [ ' 0 ' , ' 65535 ' ] ,
2014-10-09 16:02:46 -07:00
' default ' : ' 0 ' ,
2014-10-31 11:28:07 -07:00
' example ' : [ ' under the bridge: bridge-portmcfl swp1=0 swp2=0 ' ,
2016-05-31 13:12:21 -07:00
' under the port (recommended): bridge-portmcfl 0 ' ] } ,
2014-10-09 16:02:46 -07:00
' bridge-waitport ' :
{ ' help ' : ' wait for a max of time secs for the ' +
' specified ports to become available, ' +
' if no ports are specified then those ' +
' specified on bridge-ports will be ' +
' used here. Specifying no ports here ' +
' should not be used if we are using ' +
' regex or \" all \" on bridge_ports, ' +
' as it wouldnt work. ' ,
' default ' : ' 0 ' ,
2016-08-01 09:19:31 +02:00
' validvals ' : [ ' <number-interface-list> ' ] ,
2014-10-09 16:02:46 -07:00
' example ' : [ ' bridge-waitport 4 swp1 swp2 ' ] } ,
' bridge-maxwait ' :
{ ' help ' : ' forces to time seconds the maximum time ' +
2016-05-31 13:12:21 -07:00
' that the Debian bridge setup scripts will ' +
2014-10-09 16:02:46 -07:00
' wait for the bridge ports to get to the ' +
' forwarding status, doesn \' t allow factional ' +
' part. If it is equal to 0 then no waiting ' +
' is done ' ,
2016-05-31 13:12:21 -07:00
' validrange ' : [ ' 0 ' , ' 255 ' ] ,
2014-10-09 16:02:46 -07:00
' default ' : ' 0 ' ,
' example ' : [ ' bridge-maxwait 3 ' ] } ,
' bridge-vids ' :
2014-10-31 11:28:07 -07:00
{ ' help ' : ' bridge port vids. Can be specified ' +
' under the bridge or under the port. ' +
' If specified under the bridge the ports ' +
' inherit it unless overridden by a ' +
2016-05-31 13:12:21 -07:00
' bridge-vids attribute under the port ' ,
2016-08-01 09:19:31 +02:00
' validvals ' : [ ' <number-range-list> ' ] ,
2014-11-11 21:58:12 -08:00
' example ' : [ ' bridge-vids 4000 ' ,
' bridge-vids 2000 2200-3000 ' ] } ,
2014-10-24 10:11:07 -07:00
' bridge-pvid ' :
2014-10-31 11:28:07 -07:00
{ ' help ' : ' bridge port pvid. Must be specified under ' +
' the bridge port ' ,
2016-05-31 13:12:21 -07:00
' validrange ' : [ ' 0 ' , ' 4096 ' ] ,
2014-10-24 10:11:07 -07:00
' example ' : [ ' bridge-pvid 1 ' ] } ,
' bridge-access ' :
2014-10-31 11:28:07 -07:00
{ ' help ' : ' bridge port access vlan. Must be ' +
' specified under the bridge port ' ,
2016-05-31 13:12:21 -07:00
' validrange ' : [ ' 0 ' , ' 4096 ' ] ,
2014-10-24 10:11:07 -07:00
' example ' : [ ' bridge-access 300 ' ] } ,
2015-08-07 20:45:12 -07:00
' bridge-allow-untagged ' :
{ ' help ' : ' indicate if the bridge port accepts ' +
' untagged packets or not. Must be ' +
' specified under the bridge port. ' +
' Default is \' yes \' ' ,
2016-05-31 13:12:21 -07:00
' validvals ' : [ ' yes ' , ' no ' ] ,
2015-08-07 20:45:12 -07:00
' example ' : [ ' bridge-allow-untagged yes ' ] ,
' default ' : ' yes ' } ,
2014-10-09 16:02:46 -07:00
' bridge-port-vids ' :
{ ' help ' : ' bridge vlans ' ,
2014-10-31 11:28:07 -07:00
' compat ' : True ,
2014-10-09 16:02:46 -07:00
' example ' : [ ' bridge-port-vids bond0=1-1000,1010-1020 ' ] } ,
' bridge-port-pvids ' :
{ ' help ' : ' bridge port vlans ' ,
2014-10-31 11:28:07 -07:00
' compat ' : True ,
2014-10-09 16:02:46 -07:00
' example ' : [ ' bridge-port-pvids bond0=100 bond1=200 ' ] } ,
2014-10-28 16:10:00 -07:00
} }
2014-10-09 16:02:46 -07:00
def __init__ ( self , * args , * * kargs ) :
moduleBase . __init__ ( self , * args , * * kargs )
self . ipcmd = None
2015-04-23 20:19:22 -04:00
self . name = self . __class__ . __name__
2014-10-09 16:02:46 -07:00
self . brctlcmd = None
2014-10-24 10:11:07 -07:00
self . _running_vidinfo = { }
self . _running_vidinfo_valid = False
2014-11-11 21:58:12 -08:00
self . _resv_vlan_range = self . _get_reserved_vlan_range ( )
self . logger . debug ( ' %s : using reserved vlan range %s '
% ( self . __class__ . __name__ , str ( self . _resv_vlan_range ) ) )
2016-03-14 16:45:12 -07:00
default_stp_attr = policymanager . policymanager_api . get_attr_default (
module_name = self . __class__ . __name__ , attr = ' bridge-stp ' )
if ( default_stp_attr and ( default_stp_attr == ' on ' or default_stp_attr == ' yes ' ) ) :
self . default_stp_on = True
else :
self . default_stp_on = False
2014-10-09 16:02:46 -07:00
2016-04-29 21:22:52 +02:00
should_warn = policymanager . policymanager_api . \
get_module_globals ( module_name = self . __class__ . __name__ ,
attr = ' warn_on_untagged_bridge_absence ' )
self . warn_on_untagged_bridge_absence = should_warn == ' yes '
2014-10-09 16:02:46 -07:00
def _is_bridge ( self , ifaceobj ) :
if ifaceobj . get_attr_value_first ( ' bridge-ports ' ) :
return True
return False
2016-03-29 00:47:03 +02:00
def _get_ifaceobj_bridge_ports ( self , ifaceobj ) :
ports = ifaceobj . get_attr_value ( ' bridge-ports ' )
2016-03-29 04:29:24 +02:00
if ports and len ( ports ) > 1 :
2016-03-29 00:47:03 +02:00
self . log_warn ( ' %s : ignoring duplicate bridge-ports lines: %s '
% ( ifaceobj . name , ports [ 1 : ] ) )
return ports [ 0 ] if ports else None
2014-10-24 10:11:07 -07:00
def _is_bridge_port ( self , ifaceobj ) :
if self . brctlcmd . is_bridge_port ( ifaceobj . name ) :
return True
return False
2014-10-09 16:02:46 -07:00
def get_dependent_ifacenames ( self , ifaceobj , ifacenames_all = None ) :
if not self . _is_bridge ( ifaceobj ) :
return None
2014-12-17 12:39:38 -08:00
if ifaceobj . link_type != ifaceLinkType . LINK_NA :
ifaceobj . link_type = ifaceLinkType . LINK_MASTER
2015-06-02 20:35:08 -04:00
ifaceobj . link_kind | = ifaceLinkKind . BRIDGE
2015-06-24 11:39:56 -04:00
# for special vlan aware bridges, we need to add another bit
if ifaceobj . get_attr_value_first ( ' bridge-vlan-aware ' ) == ' yes ' :
2016-03-30 11:54:58 -07:00
ifaceobj . link_kind | = ifaceLinkKind . BRIDGE
ifaceobj . link_privflags | = ifaceLinkPrivFlags . BRIDGE_VLAN_AWARE
2015-06-02 20:35:08 -04:00
ifaceobj . role | = ifaceRole . MASTER
2015-04-03 21:24:25 -07:00
ifaceobj . dependency_type = ifaceDependencyType . MASTER_SLAVE
2015-11-15 21:27:07 -08:00
return self . parse_port_list ( ifaceobj . name ,
2016-03-29 00:47:03 +02:00
self . _get_ifaceobj_bridge_ports ( ifaceobj ) ,
ifacenames_all )
2014-10-09 16:02:46 -07:00
def get_dependent_ifacenames_running ( self , ifaceobj ) :
self . _init_command_handlers ( )
if not self . brctlcmd . bridge_exists ( ifaceobj . name ) :
return None
return self . brctlcmd . get_bridge_ports ( ifaceobj . name )
def _get_bridge_port_list ( self , ifaceobj ) :
# port list is also available in the previously
# parsed dependent list. Use that if available, instead
# of parsing port expr again
port_list = ifaceobj . lowerifaces
if port_list :
return port_list
2016-03-29 00:47:03 +02:00
ports = self . _get_ifaceobj_bridge_ports ( ifaceobj )
2014-10-09 16:02:46 -07:00
if ports :
2015-11-15 21:27:07 -08:00
return self . parse_port_list ( ifaceobj . name , ports )
2014-10-09 16:02:46 -07:00
else :
return None
def _process_bridge_waitport ( self , ifaceobj , portlist ) :
waitport_value = ifaceobj . get_attr_value_first ( ' bridge-waitport ' )
if not waitport_value : return
try :
waitportvals = re . split ( r ' [ \ s \ t] \ s* ' , waitport_value , 1 )
if not waitportvals : return
try :
waitporttime = int ( waitportvals [ 0 ] )
except :
self . log_warn ( ' %s : invalid waitport value \' %s \' '
% ( ifaceobj . name , waitporttime ) )
return
if waitporttime < = 0 : return
try :
2015-11-15 21:27:07 -08:00
waitportlist = self . parse_port_list ( ifaceobj . name ,
waitportvals [ 1 ] )
2014-10-09 16:02:46 -07:00
except IndexError , e :
# ignore error and use all bridge ports
waitportlist = portlist
pass
if not waitportlist : return
self . logger . info ( ' %s : waiting for ports %s to exist ... '
% ( ifaceobj . name , str ( waitportlist ) ) )
starttime = time . time ( )
while ( ( time . time ( ) - starttime ) < waitporttime ) :
if all ( [ False for p in waitportlist
if not self . ipcmd . link_exists ( p ) ] ) :
break ;
time . sleep ( 1 )
except Exception , e :
self . log_warn ( ' %s : unable to process waitport: %s '
% ( ifaceobj . name , str ( e ) ) )
2016-04-25 00:32:59 +02:00
def _enable_disable_ipv6 ( self , port , enable = ' 1 ' ) :
try :
self . write_file ( ' /proc/sys/net/ipv6/conf/ %s /disable_ipv6 ' % port , enable )
except Exception , e :
self . logger . info ( str ( e ) )
def handle_ipv6 ( self , ports , state , ifaceobj = None ) :
if ifaceobj and ( ifaceobj . link_privflags & ifaceLinkPrivFlags . BRIDGE_VXLAN ) :
self . _enable_disable_ipv6 ( ifaceobj . name , state )
2014-12-27 20:29:44 -08:00
for p in ports :
2016-04-25 00:32:59 +02:00
self . _enable_disable_ipv6 ( p , state )
2014-12-27 20:29:44 -08:00
2016-05-15 13:28:10 -07:00
def _pretty_print_add_ports_error ( self , errstr , bridgeifaceobj , bridgeports ) :
2015-11-21 22:53:29 -08:00
""" pretty print bridge port add errors.
since the commands are batched and the kernel only returns error
codes , this function tries to interpret some error codes
and prints clearer errors """
if re . search ( ' RTNETLINK answers: Invalid argument ' , errstr ) :
# Cumulus Linux specific error checks
try :
if self . sysctl_get ( ' net.bridge.bridge-allow-multiple-vlans ' ) == ' 0 ' :
vlanid = None
for bport in bridgeports :
ifattrs = bport . split ( ' . ' )
if vlanid :
if ( len ( ifattrs ) == 1 or ifattrs [ 1 ] != vlanid ) :
2016-05-15 13:28:10 -07:00
self . log_error ( ' %s : ' % bridgeifaceobj . name +
' net.bridge.bridge-allow-multiple-vlans not set, multiple vlans not allowed ' , bridgeifaceobj )
2015-11-21 22:53:29 -08:00
break
if len ( ifattrs ) == 2 :
vlanid = ifattrs [ 1 ]
except :
pass
2016-05-15 13:28:10 -07:00
self . log_error ( bridgeifaceobj . name + ' : ' + errstr , bridgeifaceobj )
2015-11-21 22:53:29 -08:00
2014-10-09 16:02:46 -07:00
def _add_ports ( self , ifaceobj ) :
bridgeports = self . _get_bridge_port_list ( ifaceobj )
runningbridgeports = [ ]
2014-12-27 20:29:44 -08:00
removedbridgeports = [ ]
2014-10-09 16:02:46 -07:00
2014-12-11 19:06:21 -08:00
self . ipcmd . batch_start ( )
2014-10-09 16:02:46 -07:00
self . _process_bridge_waitport ( ifaceobj , bridgeports )
2014-12-12 23:45:31 -08:00
self . ipcmd . batch_start ( )
2014-10-09 16:02:46 -07:00
# Delete active ports not in the new port list
2016-04-14 14:45:47 -07:00
if not ifupdownflags . flags . PERFMODE :
2014-10-09 16:02:46 -07:00
runningbridgeports = self . brctlcmd . get_bridge_ports ( ifaceobj . name )
if runningbridgeports :
2014-12-11 19:06:21 -08:00
for bport in runningbridgeports :
if not bridgeports or bport not in bridgeports :
2014-12-27 20:29:44 -08:00
self . ipcmd . link_set ( bport , ' nomaster ' )
removedbridgeports . append ( bport )
2014-10-09 16:02:46 -07:00
else :
runningbridgeports = [ ]
if not bridgeports :
2014-12-11 19:06:21 -08:00
self . ipcmd . batch_commit ( )
2014-10-09 16:02:46 -07:00
return
err = 0
2015-07-30 15:01:24 -07:00
ports = 0
2015-11-21 22:53:29 -08:00
newbridgeports = Set ( bridgeports ) . difference ( Set ( runningbridgeports ) )
for bridgeport in newbridgeports :
2014-10-09 16:02:46 -07:00
try :
2016-04-14 14:45:47 -07:00
if ( not ifupdownflags . flags . DRYRUN and
not self . ipcmd . link_exists ( bridgeport ) ) :
2016-05-15 13:28:10 -07:00
self . log_error ( ' %s : bridge port %s does not exist '
% ( ifaceobj . name , bridgeport ) , ifaceobj )
2014-10-09 16:02:46 -07:00
err + = 1
continue
2015-02-10 11:17:00 -08:00
hwaddress = self . ipcmd . link_get_hwaddress ( bridgeport )
if not self . _valid_ethaddr ( hwaddress ) :
self . log_warn ( ' %s : skipping port %s , ' % ( ifaceobj . name ,
bridgeport ) + ' invalid ether addr %s '
% hwaddress )
continue
2014-10-09 16:02:46 -07:00
self . ipcmd . link_set ( bridgeport , ' master ' , ifaceobj . name )
self . ipcmd . addr_flush ( bridgeport )
2015-07-30 15:01:24 -07:00
ports + = 1
if ports == 250 :
ports = 0
self . ipcmd . batch_commit ( )
self . ipcmd . batch_start ( )
2014-10-09 16:02:46 -07:00
except Exception , e :
2014-12-11 19:06:21 -08:00
self . logger . error ( str ( e ) )
pass
2014-12-27 20:29:44 -08:00
try :
self . ipcmd . batch_commit ( )
except Exception , e :
2016-05-15 13:28:10 -07:00
self . _pretty_print_add_ports_error ( str ( e ) , ifaceobj ,
2015-11-21 22:53:29 -08:00
bridgeports )
2014-12-27 20:29:44 -08:00
pass
# enable ipv6 for ports that were removed
2016-04-25 00:32:59 +02:00
self . handle_ipv6 ( removedbridgeports , ' 0 ' )
2014-10-09 16:02:46 -07:00
if err :
self . log_error ( ' bridge configuration failed (missing ports) ' )
2014-12-27 20:29:44 -08:00
2014-10-09 16:02:46 -07:00
def _process_bridge_maxwait ( self , ifaceobj , portlist ) :
maxwait = ifaceobj . get_attr_value_first ( ' bridge-maxwait ' )
if not maxwait : return
try :
maxwait = int ( maxwait )
except :
self . log_warn ( ' %s : invalid maxwait value \' %s \' ' % ( ifaceobj . name ,
maxwait ) )
return
if not maxwait : return
self . logger . info ( ' %s : waiting for ports to go to fowarding state .. '
% ifaceobj . name )
try :
starttime = time . time ( )
while ( ( time . time ( ) - starttime ) < maxwait ) :
if all ( [ False for p in portlist
if self . read_file_oneline (
' /sys/class/net/ %s /brif/ %s /state '
% ( ifaceobj . name , p ) ) != ' 3 ' ] ) :
break ;
time . sleep ( 1 )
except Exception , e :
self . log_warn ( ' %s : unable to process maxwait: %s '
% ( ifaceobj . name , str ( e ) ) )
def _ints_to_ranges ( self , ints ) :
for a , b in itertools . groupby ( enumerate ( ints ) , lambda ( x , y ) : y - x ) :
b = list ( b )
yield b [ 0 ] [ 1 ] , b [ - 1 ] [ 1 ]
def _ranges_to_ints ( self , rangelist ) :
""" returns expanded list of integers given set of string ranges
example : [ ' 1 ' , ' 2-4 ' , ' 6 ' ] returns [ 1 , 2 , 3 , 4 , 6 ]
"""
result = [ ]
for part in rangelist :
if ' - ' in part :
a , b = part . split ( ' - ' )
a , b = int ( a ) , int ( b )
result . extend ( range ( a , b + 1 ) )
else :
a = int ( part )
result . append ( a )
return result
2016-08-08 08:18:34 -07:00
def _compress_into_ranges ( self , vids_ints ) :
return [ ' %d ' % start if start == end else ' %d - %d ' % ( start , end )
for start , end in self . _ints_to_ranges ( vids_ints ) ]
def _diff_vids ( self , vids1_ints , vids2_ints ) :
vids_to_add = Set ( vids1_ints ) . difference ( vids2_ints )
vids_to_del = Set ( vids2_ints ) . difference ( vids1_ints )
2014-10-09 16:02:46 -07:00
return ( vids_to_del , vids_to_add )
2016-05-23 09:06:10 -07:00
def _compare_vids ( self , vids1 , vids2 , pvid = None ) :
2014-10-09 16:02:46 -07:00
""" Returns true if the vids are same else return false """
vids1_ints = self . _ranges_to_ints ( vids1 )
vids2_ints = self . _ranges_to_ints ( vids2 )
2016-05-23 09:06:10 -07:00
set_diff = Set ( vids1_ints ) . symmetric_difference ( vids2_ints )
2016-07-25 10:32:47 -07:00
if pvid and int ( pvid ) in set_diff :
2016-08-08 08:18:34 -07:00
set_diff . remove ( int ( pvid ) )
2016-05-23 09:06:10 -07:00
if set_diff :
2014-10-09 16:02:46 -07:00
return False
else :
return True
2014-10-24 10:11:07 -07:00
def _set_bridge_mcqv4src_compat ( self , ifaceobj ) :
#
# Sets old style igmp querier
#
2014-10-09 16:02:46 -07:00
attrval = ifaceobj . get_attr_value_first ( ' bridge-mcqv4src ' )
if attrval :
running_mcqv4src = { }
2016-04-14 14:45:47 -07:00
if not ifupdownflags . flags . PERFMODE :
2014-10-09 16:02:46 -07:00
running_mcqv4src = self . brctlcmd . get_mcqv4src ( ifaceobj . name )
mcqs = { }
srclist = attrval . split ( )
for s in srclist :
k , v = s . split ( ' = ' )
mcqs [ k ] = v
k_to_del = Set ( running_mcqv4src . keys ( ) ) . difference ( mcqs . keys ( ) )
for v in k_to_del :
self . brctlcmd . del_mcqv4src ( ifaceobj . name , v )
for v in mcqs . keys ( ) :
self . brctlcmd . set_mcqv4src ( ifaceobj . name , v , mcqs [ v ] )
2014-10-24 10:11:07 -07:00
def _get_running_vidinfo ( self ) :
if self . _running_vidinfo_valid :
return self . _running_vidinfo
self . _running_vidinfo = { }
2015-11-10 14:16:00 -08:00
# CM-8161. Removed check for PERFMODE. Need the get in all cases
# including reboot, so that we can configure the pvid correctly.
2016-08-08 08:18:34 -07:00
self . _running_vidinfo = self . ipcmd . bridge_port_vids_get_all_json ( )
2014-10-24 10:11:07 -07:00
self . _running_vidinfo_valid = True
return self . _running_vidinfo
def _flush_running_vidinfo ( self ) :
self . _running_vidinfo = { }
self . _running_vidinfo_valid = False
def _set_bridge_vidinfo_compat ( self , ifaceobj ) :
#
# Supports old style vlan vid info format
# for compatibility
#
2016-04-23 22:32:14 -07:00
bridge_port_pvids = ifaceobj . get_attr_value_first ( ' bridge-port-pvids ' )
bridge_port_vids = ifaceobj . get_attr_value_first ( ' bridge-port-vids ' )
if not bridge_port_pvids and not bridge_port_vids :
return
2014-10-24 10:11:07 -07:00
# Handle bridge vlan attrs
# Install pvids
2016-04-23 22:32:14 -07:00
if bridge_port_pvids :
portlist = self . parse_port_list ( ifaceobj . name , bridge_port_pvids )
2014-10-24 10:11:07 -07:00
if not portlist :
self . log_warn ( ' %s : could not parse \' %s %s \' '
2016-04-23 22:32:14 -07:00
% ( ifaceobj . name , ' bridge-port-pvids ' ,
bridge_port_pvids ) )
2014-10-24 10:11:07 -07:00
return
for p in portlist :
try :
( port , pvid ) = p . split ( ' = ' )
2016-08-08 08:18:34 -07:00
pvid = int ( pvid )
running_pvid = self . _get_running_pvid ( port )
2014-10-24 10:11:07 -07:00
if running_pvid :
if running_pvid == pvid :
continue
else :
self . ipcmd . bridge_port_pvid_del ( port , running_pvid )
self . ipcmd . bridge_port_pvid_add ( port , pvid )
except Exception , e :
self . log_warn ( ' %s : failed to set pvid ` %s ` ( %s ) '
% ( ifaceobj . name , p , str ( e ) ) )
# install port vids
2016-04-23 22:32:14 -07:00
if bridge_port_vids :
portlist = self . parse_port_list ( ifaceobj . name , bridge_port_vids )
2014-10-09 16:02:46 -07:00
if not portlist :
2016-04-23 22:32:14 -07:00
self . log_warn ( ' %s : could not parse \' %s %s \' ' % ( ifaceobj . name ,
' bridge-port-vids ' , bridge_port_vids ) )
2014-10-09 16:02:46 -07:00
return
for p in portlist :
try :
( port , val ) = p . split ( ' = ' )
vids = val . split ( ' , ' )
2016-08-08 08:18:34 -07:00
vids_int = self . _ranges_to_ints ( vids )
running_vids = self . _get_running_vids ( port )
if running_vids :
2014-10-09 16:02:46 -07:00
( vids_to_del , vids_to_add ) = \
2016-08-08 08:18:34 -07:00
self . _diff_vids ( vids_int , running_vids )
2014-10-09 16:02:46 -07:00
if vids_to_del :
2016-08-08 08:18:34 -07:00
self . ipcmd . bridge_port_vids_del ( port ,
self . _compress_into_ranges ( vids_to_del ) )
2014-10-09 16:02:46 -07:00
if vids_to_add :
2016-08-08 08:18:34 -07:00
self . ipcmd . bridge_port_vids_add ( port ,
self . _compress_into_ranges ( vids_to_add ) )
2014-10-09 16:02:46 -07:00
else :
2016-08-08 08:18:34 -07:00
self . ipcmd . bridge_port_vids_add ( port , vids_int )
2014-10-09 16:02:46 -07:00
except Exception , e :
self . log_warn ( ' %s : failed to set vid ` %s ` ( %s ) '
% ( ifaceobj . name , p , str ( e ) ) )
2015-11-08 12:13:16 -08:00
def _is_running_stp_state_on ( self , bridgename ) :
""" Returns True if running stp state is on, else False """
stp_state_file = ' /sys/class/net/ %s /bridge/stp_state ' % bridgename
if not stp_state_file :
return False
running_stp_state = self . read_file_oneline ( stp_state_file )
if running_stp_state and running_stp_state != ' 0 ' :
return True
return False
def _is_config_stp_state_on ( self , ifaceobj ) :
""" Returns true if user specified stp state is on, else False """
stp_attr = ifaceobj . get_attr_value_first ( ' bridge-stp ' )
2016-03-14 16:45:12 -07:00
if not stp_attr :
return self . default_stp_on
2015-11-08 12:13:16 -08:00
if ( stp_attr and ( stp_attr == ' on ' or stp_attr == ' yes ' ) ) :
return True
return False
2014-10-09 16:02:46 -07:00
def _apply_bridge_settings ( self , ifaceobj ) :
try :
2015-11-08 12:13:16 -08:00
if self . _is_config_stp_state_on ( ifaceobj ) :
if not self . _is_running_stp_state_on ( ifaceobj . name ) :
self . brctlcmd . set_stp ( ifaceobj . name , " on " )
self . logger . info ( ' %s : stp state reset, reapplying port '
' settings ' % ifaceobj . name )
ifaceobj . module_flags [ ifaceobj . name ] = \
ifaceobj . module_flags . setdefault ( self . name , 0 ) | \
bridgeFlags . PORT_PROCESSED_OVERRIDE
2014-11-15 15:42:52 -08:00
else :
# If stp not specified and running stp state on, set it to off
2015-11-08 12:13:16 -08:00
if self . _is_running_stp_state_on ( ifaceobj . name ) :
2014-11-15 15:42:52 -08:00
self . brctlcmd . set_stp ( ifaceobj . name , ' no ' )
2014-11-21 10:17:37 -08:00
2014-10-09 16:02:46 -07:00
# Use the brctlcmd bulk set method: first build a dictionary
# and then call set
bridgeattrs = { k : v for k , v in
{ ' ageing ' :
ifaceobj . get_attr_value_first ( ' bridge-ageing ' ) ,
' bridgeprio ' :
ifaceobj . get_attr_value_first (
' bridge-bridgeprio ' ) ,
' fd ' :
ifaceobj . get_attr_value_first ( ' bridge-fd ' ) ,
' hello ' :
ifaceobj . get_attr_value_first ( ' bridge-hello ' ) ,
' maxage ' :
ifaceobj . get_attr_value_first ( ' bridge-maxage ' ) ,
' mclmc ' :
ifaceobj . get_attr_value_first ( ' bridge-mclmc ' ) ,
' mcrouter ' :
ifaceobj . get_attr_value_first (
' bridge-mcrouter ' ) ,
' mcsnoop ' :
ifaceobj . get_attr_value_first ( ' bridge-mcsnoop ' ) ,
' mcsqc ' :
ifaceobj . get_attr_value_first ( ' bridge-mcsqc ' ) ,
' mcqifaddr ' :
ifaceobj . get_attr_value_first (
' bridge-mcqifaddr ' ) ,
' mcquerier ' :
ifaceobj . get_attr_value_first (
' bridge-mcquerier ' ) ,
' hashel ' :
ifaceobj . get_attr_value_first ( ' bridge-hashel ' ) ,
' hashmax ' :
ifaceobj . get_attr_value_first ( ' bridge-hashmax ' ) ,
' mclmi ' :
ifaceobj . get_attr_value_first ( ' bridge-mclmi ' ) ,
' mcmi ' :
ifaceobj . get_attr_value_first ( ' bridge-mcmi ' ) ,
' mcqpi ' :
ifaceobj . get_attr_value_first ( ' bridge-mcqpi ' ) ,
' mcqi ' :
ifaceobj . get_attr_value_first ( ' bridge-mcqi ' ) ,
' mcqri ' :
ifaceobj . get_attr_value_first ( ' bridge-mcqri ' ) ,
' mcsqi ' :
ifaceobj . get_attr_value_first ( ' bridge-mcsqi ' )
} . items ( )
if v }
if bridgeattrs :
2016-06-07 18:37:40 +01:00
utils . support_yesno_attrs ( bridgeattrs , [ ' mcqifaddr ' ,
' mcquerier ' ,
' mcrouter ' ,
' mcsnoop ' ] )
2014-10-09 16:02:46 -07:00
self . brctlcmd . set_bridge_attrs ( ifaceobj . name , bridgeattrs )
portattrs = { }
for attrname , dstattrname in { ' bridge-pathcosts ' : ' pathcost ' ,
' bridge-portprios ' : ' portprio ' ,
' bridge-portmcrouter ' : ' portmcrouter ' ,
' bridge-portmcfl ' : ' portmcfl ' } . items ( ) :
attrval = ifaceobj . get_attr_value_first ( attrname )
if not attrval :
continue
2015-11-15 21:27:07 -08:00
portlist = self . parse_port_list ( ifaceobj . name , attrval )
2014-10-09 16:02:46 -07:00
if not portlist :
2016-05-15 13:28:10 -07:00
self . log_error ( ' %s : could not parse \' %s %s \' '
% ( ifaceobj . name , attrname , attrval ) , ifaceobj ,
raise_error = False )
2014-10-09 16:02:46 -07:00
continue
for p in portlist :
try :
( port , val ) = p . split ( ' = ' )
if not portattrs . get ( port ) :
portattrs [ port ] = { }
2016-06-07 18:37:40 +01:00
if attrname == ' bridge-portmcrouter ' :
portattrs [ port ] . update ( { dstattrname : utils . boolean_support_binary ( val ) } )
else :
portattrs [ port ] . update ( { dstattrname : val } )
2014-10-09 16:02:46 -07:00
except Exception , e :
2016-05-15 13:28:10 -07:00
self . log_error ( ' %s : could not parse %s ( %s ) '
% ( ifaceobj . name , attrname , str ( e ) ) ,
ifaceobj , raise_error = False )
2014-10-09 16:02:46 -07:00
for port , attrdict in portattrs . iteritems ( ) :
2014-12-27 20:29:44 -08:00
try :
self . brctlcmd . set_bridgeport_attrs ( ifaceobj . name , port ,
attrdict )
except Exception , e :
2016-05-15 13:28:10 -07:00
self . log_error ( ' %s : %s ' % ( ifaceobj . name , str ( e ) ) , ifaceobj ,
raise_error = False )
2014-12-27 20:29:44 -08:00
pass
2014-10-24 10:11:07 -07:00
self . _set_bridge_vidinfo_compat ( ifaceobj )
self . _set_bridge_mcqv4src_compat ( ifaceobj )
2014-10-09 16:02:46 -07:00
self . _process_bridge_maxwait ( ifaceobj ,
self . _get_bridge_port_list ( ifaceobj ) )
except Exception , e :
2016-05-15 13:28:10 -07:00
self . log_error ( str ( e ) , ifaceobj )
2014-10-09 16:02:46 -07:00
2014-12-03 14:03:34 -08:00
def _check_vids ( self , ifaceobj , vids ) :
ret = True
for v in vids :
if ' - ' in v :
va , vb = v . split ( ' - ' )
va , vb = int ( va ) , int ( vb )
if ( self . _handle_reserved_vlan ( va , ifaceobj . name ) or
self . _handle_reserved_vlan ( vb , ifaceobj . name ) ) :
ret = False
else :
va = int ( v )
if self . _handle_reserved_vlan ( va , ifaceobj . name ) :
ret = False
return ret
2014-10-24 10:11:07 -07:00
def _apply_bridge_port_pvids ( self , bportifaceobj , pvid , running_pvid ) :
# Install pvids
try :
if running_pvid :
if running_pvid != pvid :
self . ipcmd . bridge_port_pvid_del ( bportifaceobj . name ,
running_pvid )
2014-10-28 16:10:00 -07:00
self . ipcmd . bridge_port_pvid_add ( bportifaceobj . name , pvid )
else :
self . ipcmd . bridge_port_pvid_add ( bportifaceobj . name , pvid )
2014-10-24 10:11:07 -07:00
except Exception , e :
2016-05-15 13:28:10 -07:00
self . log_error ( ' %s : failed to set pvid ` %s ` ( %s ) '
% ( bportifaceobj . name , pvid , str ( e ) ) , bportifaceobj )
2014-10-24 10:11:07 -07:00
2016-08-08 08:18:34 -07:00
def _get_running_pvid ( self , ifacename ) :
pvid = 0
running_vidinfo = self . _get_running_vidinfo ( )
for vinfo in running_vidinfo . get ( ifacename , { } ) :
v = vinfo . get ( ' vlan ' )
pvid = v if ' PVID ' in vinfo . get ( ' flags ' , [ ] ) else 0
if pvid :
return pvid
return pvid
def _get_running_vids ( self , ifacename ) :
vids = [ ]
running_vidinfo = self . _get_running_vidinfo ( )
for vinfo in running_vidinfo . get ( ifacename , { } ) :
v = vinfo . get ( ' vlan ' )
ispvid = True if ' PVID ' in vinfo . get ( ' flags ' , [ ] ) else False
if ispvid :
pvid = v if ' PVID ' in vinfo . get ( ' flags ' , [ ] ) else 0
if pvid == 1 :
continue
vEnd = vinfo . get ( ' vlanEnd ' )
if vEnd :
vids . extend ( range ( v , vEnd + 1 ) )
else :
vids . append ( v )
return vids
def _get_running_vids_n_pvid ( self , ifacename ) :
vids = [ ]
pvid = 0
running_vidinfo = self . _get_running_vidinfo ( )
for vinfo in running_vidinfo . get ( ifacename , { } ) :
v = vinfo . get ( ' vlan ' )
ispvid = True if ' PVID ' in vinfo . get ( ' flags ' , [ ] ) else False
if ispvid :
pvid = v if ' PVID ' in vinfo . get ( ' flags ' , [ ] ) else 0
vEnd = vinfo . get ( ' vlanEnd ' )
if vEnd :
vids . extend ( range ( v , vEnd + 1 ) )
else :
vids . append ( v )
return ( vids , pvid )
def _get_running_vids_n_pvid_str ( self , ifacename ) :
vids = [ ]
pvid = None
( vids , pvid ) = self . _get_running_vids_n_pvid ( ifacename )
if vids :
ret_vids = self . _compress_into_ranges ( vids )
else :
ret_vids = None
if pvid :
ret_pvid = ' %s ' % pvid
else :
ret_pvid = None
return ( ret_vids , ret_pvid )
def _get_running_vids_n_pvid_str2 ( self , ifacename ) :
vids = [ ]
pvid = None
running_vidinfo = self . _get_running_vidinfo ( )
for vinfo in running_vidinfo . get ( ifacename , { } ) :
v = vinfo . get ( ' vlan ' )
if not pvid :
pvid = ' %s ' % v if ' PVID ' in vinfo . get ( ' flags ' , [ ] ) else None
vEnd = vinfo . get ( ' vlanEnd ' )
if vEnd :
vids . append ( ' %s - %s ' % ( v , vEnd ) )
else :
vids . append ( ' %s ' % v )
return ( vids , pvid )
def _apply_bridge_vids_and_pvid ( self , bportifaceobj , vids , pvid ,
isbridge ) :
2015-04-30 12:59:16 -07:00
""" This method is a combination of methods _apply_bridge_vids and
_apply_bridge_port_pvids above . A combined function is
found necessary to do the deletes first and the adds later
because kernel does honor vid info flags during deletes .
"""
2016-08-08 08:18:34 -07:00
vids_int = self . _ranges_to_ints ( vids )
pvid_int = int ( pvid ) if pvid else 0
vids_to_del = [ ]
vids_to_add = vids_int
pvid_to_del = None
pvid_to_add = pvid_int
2015-04-30 12:59:16 -07:00
try :
if not self . _check_vids ( bportifaceobj , vids ) :
return
2016-08-08 08:18:34 -07:00
( running_vids , running_pvid ) = self . _get_running_vids_n_pvid (
bportifaceobj . name )
2015-04-30 12:59:16 -07:00
2016-08-19 11:09:57 -07:00
if not running_vids and not running_pvid :
2016-08-10 15:35:48 -07:00
# There cannot be a no running pvid.
# It might just not be in our cache:
# this can happen if at the time we were
# creating the bridge vlan cache, the port
2016-08-19 11:09:57 -07:00
# was not part of the bridge. And we need
# to make sure both vids and pvid is not in
# the cache, to declare that our cache may
# be stale.
2016-08-10 15:35:48 -07:00
running_pvid = 1
2016-08-19 11:09:57 -07:00
running_vids = [ 1 ]
if running_vids :
( vids_to_del , vids_to_add ) = \
self . _diff_vids ( vids_to_add , running_vids )
2015-04-30 12:59:16 -07:00
2016-08-11 22:36:39 -07:00
if running_pvid :
if running_pvid != pvid_int and running_pvid != 0 :
pvid_to_del = running_pvid
2016-08-08 08:18:34 -07:00
if ( pvid_to_del and ( pvid_to_del in vids_int ) and
2015-04-30 12:59:16 -07:00
( pvid_to_del not in vids_to_add ) ) :
# kernel deletes dont take into account
# bridge vid flags and its possible that
# the pvid deletes we do end up deleting
# the vids. Be proactive and add the pvid
# to the vid add list if it is in the vids
# and not already part of vids_to_add.
# This helps with a small corner case:
# - running
# pvid 100
# vid 101 102
# - new change is going to move the state to
# pvid 101
# vid 100 102
2016-08-08 08:18:34 -07:00
vids_to_add . add ( pvid_to_del )
2015-04-30 12:59:16 -07:00
except Exception , e :
2016-05-15 13:28:10 -07:00
self . log_error ( ' %s : failed to process vids/pvids '
% bportifaceobj . name + ' vids = %s ' % str ( vids ) +
' pvid = %s ' % pvid + ' ( %s ) ' % str ( e ) ,
bportifaceobj , raise_error = False )
2015-04-30 12:59:16 -07:00
try :
if vids_to_del :
2016-08-08 08:18:34 -07:00
if pvid_to_add in vids_to_del :
vids_to_del . remove ( pvid_to_add )
2015-04-30 12:59:16 -07:00
self . ipcmd . bridge_vids_del ( bportifaceobj . name ,
2016-08-08 08:18:34 -07:00
self . _compress_into_ranges (
vids_to_del ) , isbridge )
2015-04-30 12:59:16 -07:00
except Exception , e :
self . log_warn ( ' %s : failed to del vid ` %s ` ( %s ) '
% ( bportifaceobj . name , str ( vids_to_del ) , str ( e ) ) )
try :
if pvid_to_del :
self . ipcmd . bridge_port_pvid_del ( bportifaceobj . name ,
pvid_to_del )
except Exception , e :
self . log_warn ( ' %s : failed to del pvid ` %s ` ( %s ) '
% ( bportifaceobj . name , pvid_to_del , str ( e ) ) )
try :
if vids_to_add :
self . ipcmd . bridge_vids_add ( bportifaceobj . name ,
2016-08-08 08:18:34 -07:00
self . _compress_into_ranges (
vids_to_add ) , isbridge )
2015-04-30 12:59:16 -07:00
except Exception , e :
2016-05-15 13:28:10 -07:00
self . log_error ( ' %s : failed to set vid ` %s ` ( %s ) '
2016-08-08 08:18:34 -07:00
% ( bportifaceobj . name , str ( vids_to_add ) ,
str ( e ) ) , bportifaceobj , raise_error = False )
2015-04-30 12:59:16 -07:00
try :
2016-08-08 08:18:34 -07:00
if pvid_to_add and pvid_to_add != running_pvid :
self . ipcmd . bridge_port_pvid_add ( bportifaceobj . name ,
pvid_to_add )
2015-04-30 12:59:16 -07:00
except Exception , e :
2016-05-15 13:28:10 -07:00
self . log_error ( ' %s : failed to set pvid ` %s ` ( %s ) '
% ( bportifaceobj . name , pvid_to_add , str ( e ) ) ,
bportifaceobj )
2015-04-30 12:59:16 -07:00
2014-10-24 10:11:07 -07:00
def _apply_bridge_vlan_aware_port_settings_all ( self , bportifaceobj ,
2014-11-11 21:58:12 -08:00
bridge_vids = None ,
bridge_pvid = None ) :
2014-10-24 10:11:07 -07:00
vids = None
pvids = None
2015-04-30 12:59:16 -07:00
vids_final = [ ]
pvid_final = None
2014-10-24 10:11:07 -07:00
bport_access = bportifaceobj . get_attr_value_first ( ' bridge-access ' )
if bport_access :
vids = re . split ( r ' [ \ s \ t] \ s* ' , bport_access )
pvids = vids
2015-08-07 20:45:12 -07:00
allow_untagged = ' yes '
2014-11-11 21:58:12 -08:00
else :
2015-08-07 20:45:12 -07:00
allow_untagged = bportifaceobj . get_attr_value_first ( ' bridge-allow-untagged ' ) or ' yes '
2014-11-11 21:58:12 -08:00
bport_vids = bportifaceobj . get_attr_value_first ( ' bridge-vids ' )
if bport_vids :
vids = re . split ( r ' [ \ s \ t,] \ s* ' , bport_vids )
2014-10-24 10:11:07 -07:00
2014-11-11 21:58:12 -08:00
bport_pvids = bportifaceobj . get_attr_value_first ( ' bridge-pvid ' )
if bport_pvids :
pvids = re . split ( r ' [ \ s \ t] \ s* ' , bport_pvids )
2014-10-24 10:11:07 -07:00
if vids :
2015-04-30 12:59:16 -07:00
vids_final = vids
2014-10-24 10:11:07 -07:00
elif bridge_vids :
2015-04-30 12:59:16 -07:00
vids_final = bridge_vids
2015-08-07 20:45:12 -07:00
if allow_untagged == ' yes ' :
if pvids :
pvid_final = pvids [ 0 ]
elif bridge_pvid :
pvid_final = bridge_pvid
else :
pvid_final = ' 1 '
else :
pvid_final = None
2014-10-24 10:11:07 -07:00
2015-04-30 12:59:16 -07:00
self . _apply_bridge_vids_and_pvid ( bportifaceobj , vids_final ,
2016-08-08 08:18:34 -07:00
pvid_final , False )
2014-10-24 10:11:07 -07:00
def _apply_bridge_port_settings ( self , bportifaceobj , bridgename = None ,
bridgeifaceobj = None ) :
if not bridgename and bridgeifaceobj :
bridgename = bridgeifaceobj . name
# Set other stp and igmp attributes
portattrs = { }
for attrname , dstattrname in {
2014-10-28 16:10:00 -07:00
' bridge-pathcosts ' : ' pathcost ' ,
' bridge-portprios ' : ' portprio ' ,
' bridge-portmcrouter ' : ' portmcrouter ' ,
' bridge-portmcfl ' : ' portmcfl ' } . items ( ) :
2014-10-24 10:11:07 -07:00
attrval = bportifaceobj . get_attr_value_first ( attrname )
if not attrval :
# Check if bridge has that attribute
2014-10-24 14:21:54 -07:00
#if bridgeifaceobj:
# attrval = bridgeifaceobj.get_attr_value_first(attrname)
# if not attrval:
# continue
#else:
continue
2014-10-24 10:11:07 -07:00
portattrs [ dstattrname ] = attrval
try :
self . brctlcmd . set_bridgeport_attrs ( bridgename ,
bportifaceobj . name , portattrs )
except Exception , e :
2016-05-15 13:28:10 -07:00
self . log_error ( str ( e ) , bportifaceobj )
2014-10-24 10:11:07 -07:00
def _apply_bridge_port_settings_all ( self , ifaceobj ,
2016-08-03 12:22:14 -07:00
ifaceobj_getfunc = None ,
bridge_vlan_aware = False ) :
2014-12-27 20:29:44 -08:00
err = False
2014-10-24 10:11:07 -07:00
if ( ifaceobj . get_attr_value_first ( ' bridge-port-vids ' ) and
ifaceobj . get_attr_value_first ( ' bridge-port-pvids ' ) ) :
# Old style bridge port vid info
# skip new style setting on ports
return
self . logger . info ( ' %s : applying bridge configuration '
% ifaceobj . name + ' specific to ports ' )
bridge_vids = ifaceobj . get_attr_value_first ( ' bridge-vids ' )
if bridge_vids :
2014-11-11 21:58:12 -08:00
bridge_vids = re . split ( r ' [ \ s \ t,] \ s* ' , bridge_vids )
2014-10-24 10:11:07 -07:00
else :
bridge_vids = None
2014-11-11 21:58:12 -08:00
bridge_pvid = ifaceobj . get_attr_value_first ( ' bridge-pvid ' )
if bridge_pvid :
2014-11-15 15:42:52 -08:00
bridge_pvid = re . split ( r ' [ \ s \ t] \ s* ' , bridge_pvid ) [ 0 ]
2014-11-11 21:58:12 -08:00
else :
bridge_pvid = None
2015-11-08 12:13:16 -08:00
if ( ifaceobj . module_flags . get ( self . name , 0x0 ) &
bridgeFlags . PORT_PROCESSED_OVERRIDE ) :
port_processed_override = True
else :
port_processed_override = False
2014-10-24 10:11:07 -07:00
bridgeports = self . _get_bridge_port_list ( ifaceobj )
2014-11-19 14:42:14 -08:00
if not bridgeports :
self . logger . debug ( ' %s : cannot find bridgeports ' % ifaceobj . name )
return
2016-07-10 16:34:34 -07:00
self . ipcmd . batch_start ( )
2014-10-24 10:11:07 -07:00
for bport in bridgeports :
# Use the brctlcmd bulk set method: first build a dictionary
# and then call set
2014-10-28 16:10:00 -07:00
if not self . ipcmd . bridge_port_exists ( ifaceobj . name , bport ) :
self . logger . info ( ' %s : skipping bridge config ' % ifaceobj . name +
' for port %s (missing port) ' % bport )
continue
2014-10-24 10:11:07 -07:00
self . logger . info ( ' %s : processing bridge config for port %s '
% ( ifaceobj . name , bport ) )
bportifaceobjlist = ifaceobj_getfunc ( bport )
if not bportifaceobjlist :
continue
for bportifaceobj in bportifaceobjlist :
2014-10-29 12:51:21 -07:00
# Dont process bridge port if it already has been processed
2015-11-08 12:13:16 -08:00
# and there is no override on port_processed
if ( not port_processed_override and
( bportifaceobj . module_flags . get ( self . name , 0x0 ) &
bridgeFlags . PORT_PROCESSED ) ) :
2014-10-29 12:51:21 -07:00
continue
2014-12-27 20:29:44 -08:00
try :
# Add attributes specific to the vlan aware bridge
if bridge_vlan_aware :
self . _apply_bridge_vlan_aware_port_settings_all (
2014-11-11 21:58:12 -08:00
bportifaceobj , bridge_vids , bridge_pvid )
2014-12-27 20:29:44 -08:00
self . _apply_bridge_port_settings ( bportifaceobj ,
2014-10-29 12:51:21 -07:00
bridgeifaceobj = ifaceobj )
2016-04-29 21:22:52 +02:00
elif self . warn_on_untagged_bridge_absence :
self . _check_untagged_bridge ( ifaceobj . name , bportifaceobj , ifaceobj_getfunc )
2014-12-27 20:29:44 -08:00
except Exception , e :
err = True
self . logger . warn ( ' %s : %s ' % ( ifaceobj . name , str ( e ) ) )
pass
2016-07-10 16:34:34 -07:00
self . ipcmd . bridge_batch_commit ( )
2014-12-27 20:29:44 -08:00
if err :
raise Exception ( ' %s : errors applying port settings ' % ifaceobj . name )
2014-10-24 10:11:07 -07:00
2016-04-29 21:22:52 +02:00
def _check_untagged_bridge ( self , bridgename , bridgeportifaceobj , ifaceobj_getfunc ) :
if bridgeportifaceobj . link_kind & ifaceLinkKind . VLAN :
lower_ifaceobj_list = ifaceobj_getfunc ( bridgeportifaceobj . lowerifaces [ 0 ] )
if lower_ifaceobj_list and lower_ifaceobj_list [ 0 ] and \
not lower_ifaceobj_list [ 0 ] . link_privflags & ifaceLinkPrivFlags . BRIDGE_PORT :
self . logger . warn ( ' %s : untagged bridge not found. Please configure a bridge with untagged bridge ports to avoid Spanning Tree Interoperability issue. ' % bridgename )
self . warn_on_untagged_bridge_absence = False
2015-07-23 10:17:02 -07:00
def _get_bridgename ( self , ifaceobj ) :
for u in ifaceobj . upperifaces :
if self . ipcmd . is_bridge ( u ) :
return u
return None
2014-10-24 10:11:07 -07:00
def _up ( self , ifaceobj , ifaceobj_getfunc = None ) :
2015-07-23 10:17:02 -07:00
# Check if bridge port and see if we need to add it to the bridge
add_port = False
2014-10-29 12:51:21 -07:00
bridgename = self . ipcmd . bridge_port_get_bridge_name ( ifaceobj . name )
2015-07-23 10:17:02 -07:00
if ( not bridgename and
2016-03-31 21:39:55 -07:00
( ifaceobj . link_privflags & ifaceLinkPrivFlags . BRIDGE_PORT ) ) :
2015-07-23 10:17:02 -07:00
# get bridgename and add port to bridge
bridgename = self . _get_bridgename ( ifaceobj )
add_port = True
2014-10-29 12:51:21 -07:00
if bridgename :
2016-04-13 23:56:49 -07:00
if self . ipcmd . bridge_is_vlan_aware ( bridgename ) :
if add_port :
# add ifaceobj to bridge
self . ipcmd . link_set ( ifaceobj . name , ' master ' , bridgename )
bridge_vids = self . _get_bridge_vids ( bridgename ,
ifaceobj_getfunc )
bridge_pvid = self . _get_bridge_pvid ( bridgename ,
ifaceobj_getfunc )
self . _apply_bridge_vlan_aware_port_settings_all ( ifaceobj ,
bridge_vids ,
bridge_pvid )
self . _apply_bridge_port_settings ( ifaceobj , bridgename = bridgename )
ifaceobj . module_flags [ self . name ] = ifaceobj . module_flags . setdefault ( self . name , 0 ) | \
2015-04-23 20:19:22 -04:00
bridgeFlags . PORT_PROCESSED
2016-04-13 23:56:49 -07:00
return
2014-10-24 10:11:07 -07:00
if not self . _is_bridge ( ifaceobj ) :
return
2014-12-27 20:29:44 -08:00
err = False
errstr = ' '
running_ports = ' '
2016-04-13 23:56:49 -07:00
bridge_just_created = False
2014-10-09 16:02:46 -07:00
try :
2016-04-14 14:45:47 -07:00
if not ifupdownflags . flags . PERFMODE :
2014-10-09 16:02:46 -07:00
if not self . ipcmd . link_exists ( ifaceobj . name ) :
2014-12-27 20:29:44 -08:00
self . ipcmd . link_create ( ifaceobj . name , ' bridge ' )
2016-04-13 23:56:49 -07:00
bridge_just_created = True
2014-10-09 16:02:46 -07:00
else :
self . ipcmd . link_create ( ifaceobj . name , ' bridge ' )
2016-04-13 23:56:49 -07:00
bridge_just_created = True
2014-12-27 20:29:44 -08:00
except Exception , e :
raise Exception ( str ( e ) )
2016-02-19 14:14:29 -08:00
try :
2016-08-03 12:22:14 -07:00
bridge_vlan_aware = False
2016-02-19 14:14:29 -08:00
if ifaceobj . get_attr_value_first ( ' bridge-vlan-aware ' ) == ' yes ' :
2016-08-03 12:22:14 -07:00
bridge_vlan_aware = True
2016-04-13 23:56:49 -07:00
if ( bridge_just_created or
2016-04-29 21:19:42 +02:00
not self . ipcmd . bridge_is_vlan_aware ( ifaceobj . name ) ) :
2016-04-13 23:56:49 -07:00
self . ipcmd . link_set ( ifaceobj . name , ' vlan_filtering ' , ' 1 ' ,
False , " bridge " )
if not bridge_just_created :
ifaceobj . module_flags [ self . name ] = ifaceobj . module_flags . setdefault ( self . name , 0 ) | bridgeFlags . PORT_PROCESSED_OVERRIDE
2016-08-03 12:22:14 -07:00
elif ( not bridge_just_created and
ifaceobj . get_attr_value_first ( ' bridge-vlan-aware ' ) == ' no '
and self . ipcmd . bridge_is_vlan_aware ( ifaceobj . name ) ) :
self . ipcmd . link_set ( ifaceobj . name , ' vlan_filtering ' , ' 0 ' ,
False , " bridge " )
bridge_vlan_aware = False
2016-02-19 14:14:29 -08:00
except Exception , e :
raise Exception ( str ( e ) )
2014-12-27 20:29:44 -08:00
try :
self . _add_ports ( ifaceobj )
except Exception , e :
err = True
errstr = str ( e )
pass
try :
2014-10-09 16:02:46 -07:00
self . _apply_bridge_settings ( ifaceobj )
2014-12-27 20:29:44 -08:00
except Exception , e :
err = True
errstr = str ( e )
pass
try :
running_ports = self . brctlcmd . get_bridge_ports ( ifaceobj . name )
if not running_ports :
return
# disable ipv6 for ports that were added to bridge
2016-04-25 00:32:59 +02:00
self . handle_ipv6 ( running_ports , ' 1 ' , ifaceobj = ifaceobj )
2014-10-24 10:11:07 -07:00
self . _apply_bridge_port_settings_all ( ifaceobj ,
2016-08-03 12:22:14 -07:00
ifaceobj_getfunc = ifaceobj_getfunc ,
bridge_vlan_aware = bridge_vlan_aware )
2014-10-09 16:02:46 -07:00
except Exception , e :
2014-12-27 20:29:44 -08:00
err = True
errstr = str ( e )
pass
2014-11-12 10:51:07 -08:00
finally :
2014-12-17 12:39:38 -08:00
if ifaceobj . link_type != ifaceLinkType . LINK_NA :
2015-02-25 13:45:37 -08:00
for p in running_ports :
try :
2016-05-29 18:04:23 +01:00
netlink . link_set_updown ( p , " up " )
2015-02-25 13:45:37 -08:00
except Exception , e :
self . logger . debug ( ' %s : %s : link set up ( %s ) '
% ( ifaceobj . name , p , str ( e ) ) )
pass
2014-12-27 20:29:44 -08:00
if ifaceobj . addr_method == ' manual ' :
2016-05-29 18:04:23 +01:00
netlink . link_set_updown ( ifaceobj . name , " up " )
2014-12-27 20:29:44 -08:00
if err :
raise Exception ( errstr )
2014-10-09 16:02:46 -07:00
2014-10-24 10:11:07 -07:00
def _down ( self , ifaceobj , ifaceobj_getfunc = None ) :
2014-10-09 16:02:46 -07:00
try :
2016-03-29 00:47:03 +02:00
if self . _get_ifaceobj_bridge_ports ( ifaceobj ) :
2014-10-09 16:02:46 -07:00
ports = self . brctlcmd . get_bridge_ports ( ifaceobj . name )
2014-12-11 19:06:21 -08:00
self . brctlcmd . delete_bridge ( ifaceobj . name )
2014-10-09 16:02:46 -07:00
if ports :
2016-04-26 17:10:09 +02:00
self . handle_ipv6 ( ports , ' 0 ' )
2014-12-31 23:47:18 -08:00
if ifaceobj . link_type != ifaceLinkType . LINK_NA :
2016-05-29 18:04:23 +01:00
map ( lambda p : netlink . link_set_updown ( p , " down " ) ,
ports )
2014-10-09 16:02:46 -07:00
except Exception , e :
self . log_error ( str ( e ) )
2014-10-28 16:10:00 -07:00
def _query_running_vidinfo_compat ( self , ifaceobjrunning , ports ) :
2014-10-09 16:02:46 -07:00
running_attrs = { }
if ports :
running_bridge_port_vids = ' '
for p in ports :
try :
2016-08-08 08:18:34 -07:00
running_vids = self . _get_runing_vids ( p )
2014-10-09 16:02:46 -07:00
if running_vids :
running_bridge_port_vids + = ' %s = %s ' % ( p ,
' , ' . join ( running_vids ) )
except Exception :
pass
running_attrs [ ' bridge-port-vids ' ] = running_bridge_port_vids
2016-08-08 08:18:34 -07:00
running_bridge_port_pvid = ' '
2014-10-09 16:02:46 -07:00
for p in ports :
try :
2016-08-08 08:18:34 -07:00
running_pvid = self . _get_runing_pvid ( p )
if running_pvid :
running_bridge_port_pvid + = ' %s = %s ' % ( p ,
running_pvid )
2014-10-09 16:02:46 -07:00
except Exception :
pass
2016-08-08 08:18:34 -07:00
running_attrs [ ' bridge-port-pvids ' ] = running_bridge_port_pvid
2014-10-09 16:02:46 -07:00
2016-08-08 08:18:34 -07:00
running_bridge_vids = self . _get_running_vids ( ifaceobjrunning . name )
2014-10-09 16:02:46 -07:00
if running_bridge_vids :
2016-08-08 08:18:34 -07:00
running_attrs [ ' bridge-vids ' ] = ' , ' . join ( self . _compress_into_ranges ( running_bridge_vids ) )
2014-10-09 16:02:46 -07:00
return running_attrs
2014-11-15 15:42:52 -08:00
def _query_running_vidinfo ( self , ifaceobjrunning , ifaceobj_getfunc ,
bridgeports = None ) :
2014-10-28 16:10:00 -07:00
running_attrs = { }
2014-11-15 15:42:52 -08:00
# 'bridge-vids' under the bridge is all about 'vids' on the port.
# so query the ports
running_bridgeport_vids = [ ]
running_bridgeport_pvids = [ ]
for bport in bridgeports :
2016-08-08 08:18:34 -07:00
( vids , pvid ) = self . _get_running_vids_n_pvid_str ( bport )
2014-11-15 15:42:52 -08:00
if vids :
running_bridgeport_vids . append ( ' ' . join ( vids ) )
2016-08-08 08:18:34 -07:00
if pvid :
running_bridgeport_pvids . append ( pvid )
2014-11-15 15:42:52 -08:00
bridge_vids = None
if running_bridgeport_vids :
( vidval , freq ) = Counter ( running_bridgeport_vids ) . most_common ( ) [ 0 ]
if freq == len ( bridgeports ) :
running_attrs [ ' bridge-vids ' ] = vidval
bridge_vids = vidval . split ( )
bridge_pvid = None
if running_bridgeport_pvids :
( vidval , freq ) = Counter ( running_bridgeport_pvids ) . most_common ( ) [ 0 ]
if freq == len ( bridgeports ) and vidval != ' 1 ' :
running_attrs [ ' bridge-pvid ' ] = vidval
2016-08-08 08:18:34 -07:00
bridge_pvid = vidval . split ( ) [ 0 ]
2014-11-15 15:42:52 -08:00
# Go through all bridge ports and find their vids
for bport in bridgeports :
bportifaceobj = ifaceobj_getfunc ( bport )
if not bportifaceobj :
continue
2016-08-08 08:18:34 -07:00
bport_vids = [ ]
bport_pvid = None
( vids , pvid ) = self . _get_running_vids_n_pvid_str ( bport )
2014-11-15 15:42:52 -08:00
if vids and vids != bridge_vids :
bport_vids = vids
2016-08-08 08:18:34 -07:00
if pvid and pvid != bridge_pvid :
bport_pvid = pvid
if bport_vids and bport_pvid in bport_vids :
bport_vids . remove ( bport_pvid )
if ( not bport_vids and bport_pvid and bport_pvid != ' 1 ' ) :
bportifaceobj [ 0 ] . replace_config ( ' bridge-access ' , bport_pvid )
bportifaceobj [ 0 ] . delete_config ( ' bridge-pvid ' )
bportifaceobj [ 0 ] . delete_config ( ' bridge-vids ' )
2014-11-15 15:42:52 -08:00
else :
2016-08-08 08:18:34 -07:00
if bport_pvid and bport_pvid != ' 1 ' :
bportifaceobj [ 0 ] . replace_config ( ' bridge-pvid ' , bport_pvid )
2014-11-15 15:42:52 -08:00
else :
# delete any stale bridge-vids under ports
bportifaceobj [ 0 ] . delete_config ( ' bridge-pvid ' )
if bport_vids :
bportifaceobj [ 0 ] . replace_config ( ' bridge-vids ' ,
' ' . join ( bport_vids ) )
else :
# delete any stale bridge-vids under ports
bportifaceobj [ 0 ] . delete_config ( ' bridge-vids ' )
2014-10-28 16:10:00 -07:00
return running_attrs
2014-10-09 16:02:46 -07:00
def _query_running_mcqv4src ( self , ifaceobjrunning ) :
running_mcqv4src = self . brctlcmd . get_mcqv4src ( ifaceobjrunning . name )
mcqs = [ ' %s = %s ' % ( v , i ) for v , i in running_mcqv4src . items ( ) ]
mcqs . sort ( )
mcq = ' ' . join ( mcqs )
return mcq
2014-11-15 15:42:52 -08:00
def _query_running_attrs ( self , ifaceobjrunning , ifaceobj_getfunc ,
bridge_vlan_aware = False ) :
2014-10-09 16:02:46 -07:00
bridgeattrdict = { }
userspace_stp = 0
ports = None
skip_kernel_stp_attrs = 0
2016-08-06 02:51:46 +02:00
if self . systcl_get_net_bridge_stp_user_space ( ) == ' 1 ' :
2014-10-09 16:02:46 -07:00
userspace_stp = 1
tmpbridgeattrdict = self . brctlcmd . get_bridge_attrs ( ifaceobjrunning . name )
if not tmpbridgeattrdict :
self . logger . warn ( ' %s : unable to get bridge attrs '
% ifaceobjrunning . name )
return bridgeattrdict
# Fill bridge_ports and bridge stp attributes first
ports = tmpbridgeattrdict . get ( ' ports ' )
if ports :
bridgeattrdict [ ' bridge-ports ' ] = [ ' ' . join ( ports . keys ( ) ) ]
stp = tmpbridgeattrdict . get ( ' stp ' , ' no ' )
if stp != self . get_mod_subattr ( ' bridge-stp ' , ' default ' ) :
bridgeattrdict [ ' bridge-stp ' ] = [ stp ]
if stp == ' yes ' and userspace_stp :
skip_kernel_stp_attrs = 1
2016-07-29 13:20:13 -07:00
bool2str = { ' 0 ' : ' no ' , ' 1 ' : ' yes ' }
2014-10-09 16:02:46 -07:00
# pick all other attributes
for k , v in tmpbridgeattrdict . items ( ) :
if not v :
continue
if k == ' ports ' or k == ' stp ' :
continue
if skip_kernel_stp_attrs and k [ : 2 ] != ' mc ' :
# only include igmp attributes if kernel stp is off
continue
attrname = ' bridge- ' + k
2016-07-29 13:20:13 -07:00
mod_default = self . get_mod_subattr ( attrname , ' default ' )
if v != mod_default :
# convert '0|1' running values to 'no|yes'
if v in bool2str . keys ( ) and bool2str [ v ] == mod_default :
continue
2014-10-09 16:02:46 -07:00
bridgeattrdict [ attrname ] = [ v ]
2014-10-28 16:10:00 -07:00
if bridge_vlan_aware :
2014-11-15 15:42:52 -08:00
bridgevidinfo = self . _query_running_vidinfo ( ifaceobjrunning ,
ifaceobj_getfunc ,
ports . keys ( ) )
2014-10-28 16:10:00 -07:00
else :
bridgevidinfo = self . _query_running_vidinfo_compat ( ifaceobjrunning ,
ports )
2014-10-09 16:02:46 -07:00
if bridgevidinfo :
2014-10-28 16:10:00 -07:00
bridgeattrdict . update ( { k : [ v ] for k , v in bridgevidinfo . items ( )
if v } )
2014-10-09 16:02:46 -07:00
mcq = self . _query_running_mcqv4src ( ifaceobjrunning )
if mcq :
bridgeattrdict [ ' bridge-mcqv4src ' ] = [ mcq ]
if skip_kernel_stp_attrs :
return bridgeattrdict
2016-07-29 13:20:13 -07:00
# Do this only for vlan-UNAWARE-bridge
if ports and not bridge_vlan_aware :
2014-10-09 16:02:46 -07:00
portconfig = { ' bridge-pathcosts ' : ' ' ,
' bridge-portprios ' : ' ' }
for p , v in ports . items ( ) :
v = self . brctlcmd . get_pathcost ( ifaceobjrunning . name , p )
if v and v != self . get_mod_subattr ( ' bridge-pathcosts ' ,
' default ' ) :
portconfig [ ' bridge-pathcosts ' ] + = ' %s = %s ' % ( p , v )
v = self . brctlcmd . get_portprio ( ifaceobjrunning . name , p )
if v and v != self . get_mod_subattr ( ' bridge-portprios ' ,
' default ' ) :
portconfig [ ' bridge-portprios ' ] + = ' %s = %s ' % ( p , v )
bridgeattrdict . update ( { k : [ v ] for k , v in portconfig . items ( )
if v } )
return bridgeattrdict
def _query_check_mcqv4src ( self , ifaceobj , ifaceobjcurr ) :
running_mcqs = self . _query_running_mcqv4src ( ifaceobj )
attrval = ifaceobj . get_attr_value_first ( ' bridge-mcqv4src ' )
if attrval :
mcqs = attrval . split ( )
mcqs . sort ( )
mcqsout = ' ' . join ( mcqs )
ifaceobjcurr . update_config_with_status ( ' bridge-mcqv4src ' ,
running_mcqs , 1 if running_mcqs != mcqsout else 0 )
2014-10-28 16:10:00 -07:00
def _query_check_bridge_vidinfo ( self , ifaceobj , ifaceobjcurr ) :
2014-10-09 16:02:46 -07:00
err = 0
attrval = ifaceobj . get_attr_value_first ( ' bridge-port-vids ' )
if attrval :
running_bridge_port_vids = ' '
2015-11-15 21:27:07 -08:00
portlist = self . parse_port_list ( ifaceobj . name , attrval )
2014-10-09 16:02:46 -07:00
if not portlist :
2016-05-12 16:00:41 +02:00
self . log_warn ( ' %s : could not parse \' bridge-port-vids %s \' '
% ( ifaceobj . name , attrval ) )
2014-10-09 16:02:46 -07:00
return
err = 0
for p in portlist :
try :
( port , val ) = p . split ( ' = ' )
vids = val . split ( ' , ' )
2016-08-08 08:18:34 -07:00
running_vids = self . _get_running_vids ( port )
2014-10-09 16:02:46 -07:00
if running_vids :
if not self . _compare_vids ( vids , running_vids ) :
err + = 1
running_bridge_port_vids + = ' %s = %s ' % ( port ,
' , ' . join ( running_vids ) )
else :
running_bridge_port_vids + = ' %s ' % p
else :
err + = 1
except Exception , e :
self . log_warn ( ' %s : failure checking vid %s ( %s ) '
% ( ifaceobj . name , p , str ( e ) ) )
if err :
ifaceobjcurr . update_config_with_status ( ' bridge-port-vids ' ,
running_bridge_port_vids , 1 )
else :
ifaceobjcurr . update_config_with_status ( ' bridge-port-vids ' ,
attrval , 0 )
attrval = ifaceobj . get_attr_value_first ( ' bridge-port-pvids ' )
if attrval :
2015-11-15 21:27:07 -08:00
portlist = self . parse_port_list ( ifaceobj . name , attrval )
2014-10-09 16:02:46 -07:00
if not portlist :
2016-05-12 16:00:41 +02:00
self . log_warn ( ' %s : could not parse \' bridge-port-pvids %s \' '
% ( ifaceobj . name , attrval ) )
2014-10-09 16:02:46 -07:00
return
running_bridge_port_pvids = ' '
err = 0
for p in portlist :
try :
( port , pvid ) = p . split ( ' = ' )
2016-08-08 08:18:34 -07:00
running_pvid = self . _get_running_vids ( port )
2014-10-09 16:02:46 -07:00
if running_pvid and running_pvid == pvid :
running_bridge_port_pvids + = ' %s ' % p
else :
err + = 1
running_bridge_port_pvids + = ' %s = %s ' % ( port ,
running_pvid )
except Exception , e :
self . log_warn ( ' %s : failure checking pvid %s ( %s ) '
% ( ifaceobj . name , pvid , str ( e ) ) )
if err :
ifaceobjcurr . update_config_with_status ( ' bridge-port-pvids ' ,
running_bridge_port_pvids , 1 )
else :
ifaceobjcurr . update_config_with_status ( ' bridge-port-pvids ' ,
running_bridge_port_pvids , 0 )
attrval = ifaceobj . get_attr_value_first ( ' bridge-vids ' )
2014-10-31 11:28:07 -07:00
if attrval :
ifaceobjcurr . update_config_with_status ( ' bridge-vids ' , attrval , - 1 )
2014-10-28 16:10:00 -07:00
2016-04-20 03:02:26 -07:00
def _query_check_bridge ( self , ifaceobj , ifaceobjcurr ,
ifaceobj_getfunc = None ) :
2014-10-24 10:11:07 -07:00
if not self . _is_bridge ( ifaceobj ) :
return
if not self . brctlcmd . bridge_exists ( ifaceobj . name ) :
self . logger . info ( ' %s : bridge: does not exist ' % ( ifaceobj . name ) )
return
2014-10-28 16:10:00 -07:00
2014-10-24 10:11:07 -07:00
ifaceattrs = self . dict_key_subset ( ifaceobj . config ,
self . get_mod_attrs ( ) )
2016-04-19 15:25:23 -07:00
#Add default attributes if --with-defaults is set
2016-04-20 03:02:26 -07:00
if ifupdownflags . flags . WITHDEFAULTS and ' bridge-stp ' not in ifaceattrs :
2016-04-19 15:25:23 -07:00
ifaceattrs . append ( ' bridge-stp ' )
2014-10-24 10:11:07 -07:00
if not ifaceattrs :
return
try :
runningattrs = self . brctlcmd . get_bridge_attrs ( ifaceobj . name )
if not runningattrs :
self . logger . debug ( ' %s : bridge: unable to get bridge attrs '
% ifaceobj . name )
runningattrs = { }
except Exception , e :
self . logger . warn ( str ( e ) )
runningattrs = { }
2016-06-07 18:37:40 +01:00
self . _query_check_support_yesno_attrs ( runningattrs , ifaceobj )
2014-10-24 10:11:07 -07:00
filterattrs = [ ' bridge-vids ' , ' bridge-port-vids ' ,
' bridge-port-pvids ' ]
for k in Set ( ifaceattrs ) . difference ( filterattrs ) :
# get the corresponding ifaceobj attr
v = ifaceobj . get_attr_value_first ( k )
if not v :
2016-04-20 03:02:26 -07:00
if ifupdownflags . flags . WITHDEFAULTS and k == ' bridge-stp ' :
v = ' on ' if self . default_stp_on else ' off '
else :
continue
2014-10-24 10:11:07 -07:00
rv = runningattrs . get ( k [ 7 : ] )
if k == ' bridge-mcqv4src ' :
continue
2016-04-20 03:02:26 -07:00
if k == ' bridge-maxwait ' or k == ' bridge-waitport ' :
ifaceobjcurr . update_config_with_status ( k , v , 0 )
continue
2015-07-23 12:15:16 -07:00
if k == ' bridge-vlan-aware ' :
rv = self . ipcmd . bridge_is_vlan_aware ( ifaceobj . name )
if ( rv and v == ' yes ' ) or ( not rv and v == ' no ' ) :
2014-10-28 16:10:00 -07:00
ifaceobjcurr . update_config_with_status ( ' bridge-vlan-aware ' ,
v , 0 )
else :
ifaceobjcurr . update_config_with_status ( ' bridge-vlan-aware ' ,
v , 1 )
elif k == ' bridge-stp ' :
2014-10-24 10:11:07 -07:00
# special case stp compare because it may
# contain more than one valid values
stp_on_vals = [ ' on ' , ' yes ' ]
2016-04-19 15:25:23 -07:00
stp_off_vals = [ ' off ' , ' no ' ]
2014-10-24 10:11:07 -07:00
if ( ( v in stp_on_vals and rv in stp_on_vals ) or
( v in stp_off_vals and rv in stp_off_vals ) ) :
ifaceobjcurr . update_config_with_status ( ' bridge-stp ' ,
2016-04-19 15:25:23 -07:00
rv , 0 )
2014-10-24 10:11:07 -07:00
else :
ifaceobjcurr . update_config_with_status ( ' bridge-stp ' ,
2016-04-20 03:02:26 -07:00
rv , 1 )
2014-10-24 10:11:07 -07:00
elif k == ' bridge-ports ' :
# special case ports because it can contain regex or glob
running_port_list = rv . keys ( ) if rv else [ ]
bridge_port_list = self . _get_bridge_port_list ( ifaceobj )
if not running_port_list and not bridge_port_list :
2014-10-09 16:02:46 -07:00
continue
2014-10-24 10:11:07 -07:00
portliststatus = 1
if running_port_list and bridge_port_list :
difference = set ( running_port_list
) . symmetric_difference ( bridge_port_list )
if not difference :
portliststatus = 0
ifaceobjcurr . update_config_with_status ( ' bridge-ports ' ,
' ' . join ( running_port_list )
if running_port_list else ' ' , portliststatus )
elif ( k == ' bridge-pathcosts ' or
k == ' bridge-portprios ' or k == ' bridge-portmcrouter '
or k == ' bridge-portmcfl ' ) :
2016-04-20 03:02:26 -07:00
brctlcmdattrname = k [ 7 : ] . rstrip ( ' s ' )
2014-10-24 10:11:07 -07:00
# for port attributes, the attributes are in a list
# <portname>=<portattrvalue>
status = 0
currstr = ' '
2015-11-15 21:27:07 -08:00
vlist = self . parse_port_list ( ifaceobj . name , v )
2014-10-24 10:11:07 -07:00
if not vlist :
continue
for vlistitem in vlist :
try :
( p , v ) = vlistitem . split ( ' = ' )
currv = self . brctlcmd . get_bridgeport_attr (
ifaceobj . name , p ,
brctlcmdattrname )
if currv :
currstr + = ' %s = %s ' % ( p , currv )
else :
currstr + = ' %s = %s ' % ( p , ' None ' )
if currv != v :
status = 1
except Exception , e :
self . log_warn ( str ( e ) )
pass
ifaceobjcurr . update_config_with_status ( k , currstr , status )
elif not rv :
2016-04-20 03:02:26 -07:00
if k == ' bridge-pvid ' or k == ' bridge-vids ' or k == ' bridge-allow-untagged ' :
2015-11-17 09:48:21 -08:00
# bridge-pvid and bridge-vids on a bridge does
# not correspond directly to a running config
# on the bridge. They correspond to default
# values for the bridge ports. And they are
# already checked against running config of the
# bridge port and reported against a bridge port.
# So, ignore these attributes under the bridge.
# Use '2' for ignore today. XXX: '2' will be
# mapped to a defined value in subsequent patches.
ifaceobjcurr . update_config_with_status ( k , v , 2 )
else :
ifaceobjcurr . update_config_with_status ( k , ' notfound ' , 1 )
2014-10-24 10:11:07 -07:00
continue
elif v != rv :
ifaceobjcurr . update_config_with_status ( k , rv , 1 )
else :
ifaceobjcurr . update_config_with_status ( k , rv , 0 )
2014-10-09 16:02:46 -07:00
2014-10-28 16:10:00 -07:00
self . _query_check_bridge_vidinfo ( ifaceobj , ifaceobjcurr )
self . _query_check_mcqv4src ( ifaceobj , ifaceobjcurr )
def _get_bridge_vids ( self , bridgename , ifaceobj_getfunc ) :
ifaceobjs = ifaceobj_getfunc ( bridgename )
for ifaceobj in ifaceobjs :
vids = ifaceobj . get_attr_value_first ( ' bridge-vids ' )
2014-11-11 21:58:12 -08:00
if vids : return re . split ( r ' [ \ s \ t,] \ s* ' , vids )
2014-10-28 16:10:00 -07:00
return None
2014-11-11 21:58:12 -08:00
def _get_bridge_pvid ( self , bridgename , ifaceobj_getfunc ) :
ifaceobjs = ifaceobj_getfunc ( bridgename )
pvid = None
for ifaceobj in ifaceobjs :
pvid = ifaceobj . get_attr_value_first ( ' bridge-pvid ' )
2015-11-17 09:48:21 -08:00
if pvid :
break
2014-11-11 21:58:12 -08:00
return pvid
2014-10-28 16:10:00 -07:00
def _get_bridge_name ( self , ifaceobj ) :
return self . ipcmd . bridge_port_get_bridge_name ( ifaceobj . name )
def _query_check_bridge_port_vidinfo ( self , ifaceobj , ifaceobjcurr ,
ifaceobj_getfunc , bridgename ) :
attr_name = ' bridge-access '
2016-08-08 08:18:34 -07:00
vid = ifaceobj . get_attr_value_first ( attr_name )
if vid :
( running_vids , running_pvid ) = self . _get_running_vids_n_pvid_str (
ifaceobj . name )
if ( not running_pvid or running_pvid != vid or
( running_vids and running_vids [ 0 ] != vid ) ) :
2014-10-28 16:10:00 -07:00
ifaceobjcurr . update_config_with_status ( attr_name ,
2016-08-08 08:18:34 -07:00
running_pvid , 1 )
else :
ifaceobjcurr . update_config_with_status ( attr_name , vid , 0 )
return
2014-10-28 16:10:00 -07:00
2016-08-08 08:18:34 -07:00
( running_vids , running_pvid ) = self . _get_running_vids_n_pvid_str (
ifaceobj . name )
2016-05-23 09:06:10 -07:00
attr_name = ' bridge-pvid '
2016-07-13 14:18:48 -07:00
pvid = ifaceobj . get_attr_value_first ( ' bridge-pvid ' )
2016-05-23 09:06:10 -07:00
if pvid :
2016-07-13 14:18:48 -07:00
if running_pvid and running_pvid == pvid :
ifaceobjcurr . update_config_with_status ( attr_name ,
2016-08-08 08:18:34 -07:00
running_pvid , 0 )
2016-07-13 14:18:48 -07:00
else :
ifaceobjcurr . update_config_with_status ( attr_name ,
2016-08-08 08:18:34 -07:00
running_pvid , 1 )
2016-08-03 15:35:04 -07:00
elif ( not ( ifaceobj . flags & iface . HAS_SIBLINGS ) or
( ( ifaceobj . flags & iface . HAS_SIBLINGS ) and
( ifaceobj . flags & iface . OLDEST_SIBLING ) ) ) :
# if the interface has multiple iface sections,
# we check the below only for the oldest sibling
# or the last iface section
2016-07-13 14:18:48 -07:00
pvid = self . _get_bridge_pvid ( bridgename , ifaceobj_getfunc )
if pvid :
if not running_pvid or running_pvid != pvid :
ifaceobjcurr . status = ifaceStatus . ERROR
ifaceobjcurr . status_str = ' bridge pvid error '
elif not running_pvid or running_pvid != ' 1 ' :
ifaceobjcurr . status = ifaceStatus . ERROR
ifaceobjcurr . status_str = ' bridge pvid error '
2016-05-23 09:06:10 -07:00
2014-10-28 16:10:00 -07:00
attr_name = ' bridge-vids '
vids = ifaceobj . get_attr_value_first ( attr_name )
if vids :
vids = re . split ( r ' [ \ s \ t] \ s* ' , vids )
2016-08-08 08:18:34 -07:00
if not running_vids or not self . _compare_vids ( vids , running_vids ,
running_pvid ) :
2014-10-28 16:10:00 -07:00
ifaceobjcurr . update_config_with_status ( attr_name ,
2016-08-08 08:18:34 -07:00
' ' . join ( running_vids ) , 1 )
2014-10-28 16:10:00 -07:00
else :
ifaceobjcurr . update_config_with_status ( attr_name ,
2016-08-08 08:18:34 -07:00
' ' . join ( vids ) , 0 )
2016-08-03 15:35:04 -07:00
elif ( not ( ifaceobj . flags & iface . HAS_SIBLINGS ) or
( ( ifaceobj . flags & iface . HAS_SIBLINGS ) and
( ifaceobj . flags & iface . OLDEST_SIBLING ) ) ) :
# if the interface has multiple iface sections,
# we check the below only for the oldest sibling
# or the last iface section
2014-10-28 16:10:00 -07:00
# check if it matches the bridge vids
bridge_vids = self . _get_bridge_vids ( bridgename , ifaceobj_getfunc )
if ( bridge_vids and ( not running_vids or
2016-07-13 14:18:48 -07:00
not self . _compare_vids ( bridge_vids , running_vids , running_pvid ) ) ) :
2014-10-28 16:10:00 -07:00
ifaceobjcurr . status = ifaceStatus . ERROR
ifaceobjcurr . status_str = ' bridge vid error '
def _query_check_bridge_port ( self , ifaceobj , ifaceobjcurr ,
ifaceobj_getfunc ) :
if not self . _is_bridge_port ( ifaceobj ) :
# Mark all bridge attributes as failed
2014-12-17 12:39:38 -08:00
ifaceobjcurr . check_n_update_config_with_status_many ( ifaceobj ,
2014-10-28 16:10:00 -07:00
[ ' bridge-vids ' , ' bridge-pvid ' , ' bridge-access ' ,
' bridge-pathcosts ' , ' bridge-portprios ' ,
' bridge-portmcrouter ' ,
2014-12-17 12:39:38 -08:00
' bridge-portmcfl ' ] , 1 )
2014-10-28 16:10:00 -07:00
return
bridgename = self . _get_bridge_name ( ifaceobj )
if not bridgename :
self . logger . warn ( ' %s : unable to determine bridge name '
% ifaceobj . name )
return
if self . ipcmd . bridge_is_vlan_aware ( bridgename ) :
self . _query_check_bridge_port_vidinfo ( ifaceobj , ifaceobjcurr ,
ifaceobj_getfunc ,
bridgename )
for attr , dstattr in { ' bridge-pathcosts ' : ' pathcost ' ,
2016-06-29 16:38:50 -07:00
' bridge-portprios ' : ' portprio ' ,
' bridge-portmcrouter ' : ' portmcrouter ' ,
' bridge-portmcfl ' : ' portmcfl ' } . items ( ) :
2014-10-28 16:10:00 -07:00
attrval = ifaceobj . get_attr_value_first ( attr )
if not attrval :
continue
2014-10-09 16:02:46 -07:00
2014-10-28 16:10:00 -07:00
try :
running_attrval = self . brctlcmd . get_bridgeport_attr (
bridgename , ifaceobj . name , dstattr )
2016-06-07 18:37:40 +01:00
2016-06-29 16:38:50 -07:00
if dstattr == ' portmcrouter ' :
2016-06-07 18:37:40 +01:00
if not utils . is_binary_bool ( attrval ) and running_attrval :
running_attrval = utils . get_yesno_boolean (
utils . get_boolean_from_string ( running_attrval ) )
2014-10-28 16:10:00 -07:00
if running_attrval != attrval :
ifaceobjcurr . update_config_with_status ( attr ,
running_attrval , 1 )
else :
ifaceobjcurr . update_config_with_status ( attr ,
running_attrval , 0 )
except Exception , e :
self . log_warn ( ' %s : %s ' % ( ifaceobj . name , str ( e ) ) )
2014-10-09 16:02:46 -07:00
2016-04-20 03:02:26 -07:00
def _query_check ( self , ifaceobj , ifaceobjcurr , ifaceobj_getfunc = None ) :
2014-10-28 16:10:00 -07:00
if self . _is_bridge ( ifaceobj ) :
2016-04-20 03:02:26 -07:00
self . _query_check_bridge ( ifaceobj , ifaceobjcurr )
2014-10-28 16:10:00 -07:00
else :
self . _query_check_bridge_port ( ifaceobj , ifaceobjcurr ,
ifaceobj_getfunc )
2014-11-15 15:42:52 -08:00
def _query_running_bridge ( self , ifaceobjrunning , ifaceobj_getfunc ) :
2014-10-28 16:10:00 -07:00
if self . ipcmd . bridge_is_vlan_aware ( ifaceobjrunning . name ) :
ifaceobjrunning . update_config ( ' bridge-vlan-aware ' , ' yes ' )
ifaceobjrunning . update_config_dict ( self . _query_running_attrs (
ifaceobjrunning ,
2014-11-15 15:42:52 -08:00
ifaceobj_getfunc ,
2014-10-28 16:10:00 -07:00
bridge_vlan_aware = True ) )
else :
ifaceobjrunning . update_config_dict ( self . _query_running_attrs (
2014-11-15 15:42:52 -08:00
ifaceobjrunning , None ) )
2014-10-28 16:10:00 -07:00
def _query_running_bridge_port_attrs ( self , ifaceobjrunning , bridgename ) :
2016-08-06 02:51:46 +02:00
if self . systcl_get_net_bridge_stp_user_space ( ) == ' 1 ' :
2014-10-28 16:10:00 -07:00
return
v = self . brctlcmd . get_pathcost ( bridgename , ifaceobjrunning . name )
if v and v != self . get_mod_subattr ( ' bridge-pathcosts ' , ' default ' ) :
ifaceobjrunning . update_config ( ' bridge-pathcosts ' , v )
v = self . brctlcmd . get_pathcost ( bridgename , ifaceobjrunning . name )
if v and v != self . get_mod_subattr ( ' bridge-portprios ' , ' default ' ) :
ifaceobjrunning . update_config ( ' bridge-portprios ' , v )
def _query_running_bridge_port ( self , ifaceobjrunning ,
ifaceobj_getfunc = None ) :
2016-08-08 08:18:34 -07:00
2014-10-28 16:10:00 -07:00
bridgename = self . ipcmd . bridge_port_get_bridge_name (
ifaceobjrunning . name )
2014-11-15 15:42:52 -08:00
bridge_vids = None
bridge_pvid = None
2014-10-28 16:10:00 -07:00
if not bridgename :
self . logger . warn ( ' %s : unable to find bridgename '
% ifaceobjrunning . name )
return
if not self . ipcmd . bridge_is_vlan_aware ( bridgename ) :
2014-10-09 16:02:46 -07:00
return
2014-10-28 16:10:00 -07:00
2016-08-08 08:18:34 -07:00
( bridge_port_vids , bridge_port_pvid ) = self . _get_running_vids_n_pvid_str (
ifaceobjrunning . name )
2014-11-15 15:42:52 -08:00
bridgeifaceobjlist = ifaceobj_getfunc ( bridgename )
if bridgeifaceobjlist :
bridge_vids = bridgeifaceobjlist [ 0 ] . get_attr_value ( ' bridge-vids ' )
bridge_pvid = bridgeifaceobjlist [ 0 ] . get_attr_value_first ( ' bridge-pvid ' )
2014-10-28 16:10:00 -07:00
if not bridge_port_vids and bridge_port_pvid :
# must be an access port
2014-11-15 15:42:52 -08:00
if bridge_port_pvid != ' 1 ' :
ifaceobjrunning . update_config ( ' bridge-access ' ,
2014-10-28 16:10:00 -07:00
bridge_port_pvid )
else :
if bridge_port_vids :
2014-11-15 15:42:52 -08:00
if ( not bridge_vids or bridge_port_vids != bridge_vids ) :
ifaceobjrunning . update_config ( ' bridge-vids ' ,
2014-10-28 16:10:00 -07:00
' ' . join ( bridge_port_vids ) )
if bridge_port_pvid and bridge_port_pvid != ' 1 ' :
2014-11-15 15:42:52 -08:00
if ( not bridge_pvid or ( bridge_port_pvid != bridge_pvid ) ) :
ifaceobjrunning . update_config ( ' bridge-pvid ' ,
2014-10-28 16:10:00 -07:00
bridge_port_pvid )
self . _query_running_bridge_port_attrs ( ifaceobjrunning , bridgename )
2014-11-15 15:42:52 -08:00
def _query_running ( self , ifaceobjrunning , ifaceobj_getfunc = None ) :
2014-10-28 16:10:00 -07:00
if self . brctlcmd . bridge_exists ( ifaceobjrunning . name ) :
2014-11-15 15:42:52 -08:00
self . _query_running_bridge ( ifaceobjrunning , ifaceobj_getfunc )
2014-10-28 16:10:00 -07:00
elif self . brctlcmd . is_bridge_port ( ifaceobjrunning . name ) :
2014-11-15 15:42:52 -08:00
self . _query_running_bridge_port ( ifaceobjrunning , ifaceobj_getfunc )
2014-10-09 16:02:46 -07:00
2016-04-24 17:24:31 -07:00
def _query ( self , ifaceobj , * * kwargs ) :
""" add default policy attributes supported by the module """
2016-04-26 15:00:08 -07:00
if ( not ( ifaceobj . link_kind & ifaceLinkKind . BRIDGE ) or
ifaceobj . get_attr_value_first ( ' bridge-stp ' ) ) :
2016-04-24 17:38:00 -07:00
return
2016-04-24 17:24:31 -07:00
if self . default_stp_on :
ifaceobj . update_config ( ' bridge-stp ' , ' yes ' )
2016-06-07 18:37:40 +01:00
def _query_check_support_yesno_attrs ( self , runningattrs , ifaceobj ) :
for attrl in [ [ ' mcqifaddr ' , ' bridge-mcqifaddr ' ] ,
[ ' mcquerier ' , ' bridge-mcquerier ' ] ,
[ ' mcrouter ' , ' bridge-mcrouter ' ] ,
[ ' mcsnoop ' , ' bridge-mcsnoop ' ] ] :
value = ifaceobj . get_attr_value_first ( attrl [ 1 ] )
if value and not utils . is_binary_bool ( value ) :
if attrl [ 0 ] in runningattrs :
bool = utils . get_boolean_from_string ( runningattrs [ attrl [ 0 ] ] )
runningattrs [ attrl [ 0 ] ] = utils . get_yesno_boolean ( bool )
attrval = ifaceobj . get_attr_value_first ( ' bridge-portmcrouter ' )
if attrval :
portlist = self . parse_port_list ( ifaceobj . name , attrval )
if portlist :
to_convert = [ ]
for p in portlist :
( port , val ) = p . split ( ' = ' )
if not utils . is_binary_bool ( val ) :
to_convert . append ( port )
for port in to_convert :
runningattrs [ ' ports ' ] [ port ] [ ' portmcrouter ' ] = utils . get_yesno_boolean (
utils . get_boolean_from_string ( runningattrs [ ' ports ' ] [ port ] [ ' portmcrouter ' ] ) )
2014-10-09 16:02:46 -07:00
_run_ops = { ' pre-up ' : _up ,
' post-down ' : _down ,
' query-checkcurr ' : _query_check ,
2016-04-24 17:24:31 -07:00
' query-running ' : _query_running ,
' query ' : _query }
2014-10-09 16:02:46 -07:00
def get_ops ( self ) :
""" returns list of ops supported by this module """
return self . _run_ops . keys ( )
def _init_command_handlers ( self ) :
if not self . ipcmd :
2016-04-14 14:45:47 -07:00
self . ipcmd = iproute2 ( )
2014-10-09 16:02:46 -07:00
if not self . brctlcmd :
2016-04-14 14:45:47 -07:00
self . brctlcmd = brctl ( )
2014-10-09 16:02:46 -07:00
2014-10-24 10:11:07 -07:00
def run ( self , ifaceobj , operation , query_ifaceobj = None ,
2016-04-20 03:02:26 -07:00
ifaceobj_getfunc = None ) :
2014-10-09 16:02:46 -07:00
""" run bridge configuration on the interface object passed as
argument . Can create bridge interfaces if they dont exist already
Args :
* * ifaceobj * * ( object ) : iface object
* * operation * * ( str ) : any of ' pre-up ' , ' post-down ' , ' query-checkcurr ' ,
' query-running '
Kwargs :
* * query_ifaceobj * * ( object ) : query check ifaceobject . This is only
valid when op is ' query-checkcurr ' . It is an object same as
ifaceobj , but contains running attribute values and its config
status . The modules can use it to return queried running state
of interfaces . status is success if the running state is same
as user required state in ifaceobj . error otherwise .
"""
op_handler = self . _run_ops . get ( operation )
if not op_handler :
return
self . _init_command_handlers ( )
2016-08-08 08:18:34 -07:00
#self._flush_running_vidinfo()
2014-10-09 16:02:46 -07:00
if operation == ' query-checkcurr ' :
2014-10-24 10:11:07 -07:00
op_handler ( self , ifaceobj , query_ifaceobj ,
ifaceobj_getfunc = ifaceobj_getfunc )
2014-10-09 16:02:46 -07:00
else :
2014-10-24 10:11:07 -07:00
op_handler ( self , ifaceobj , ifaceobj_getfunc = ifaceobj_getfunc )