1
0
mirror of https://github.com/CumulusNetworks/ifupdown2.git synced 2024-05-06 15:54:50 +00:00

ifupdownmain: redo shared dependent checks

Ticket: CM-10027
Reviewed By: julien, nikhil
Testing Done: Tested with an interfaces file with shared dependents

In the process of fixing this saw a few more issues with link kind
handing. Its better to separate kind from interface private flags
like bond slave and bridge port. this patch cleans up all that handling.

Example errors:
error: misconfig..? swp5.2 vrfslave  is enslaved to multiple interfaces
['vrf1012', 'br2']
error: misconfig..? swp5.2 bridgeport  is enslaved to multiple
interfaces ['vrf1012', 'br2']
This commit is contained in:
Roopa Prabhu
2016-03-30 11:54:58 -07:00
parent 9219cef3d6
commit 858a230f91
5 changed files with 85 additions and 35 deletions

View File

@@ -128,8 +128,10 @@ class address(moduleBase):
if not addrs: if not addrs:
continue continue
if ((ifaceobj.role & ifaceRole.SLAVE) or if (((ifaceobj.role & ifaceRole.SLAVE) and
(ifaceobj.link_kind & ifaceLinkKind.BRIDGE_VLAN_AWARE)): not (ifaceobj.link_privflags & ifaceLinkPrivFlags.VRF_SLAVE)) or
((ifaceobj.link_kind & ifaceLinkKind.BRIDGE) and
(ifaceobj.link_privflags & ifaceLinkPrivFlags.BRIDGE_VLAN_AWARE))):
# we must not configure an IP address if the interface is # we must not configure an IP address if the interface is
# enslaved or is a VLAN AWARE BRIDGE # enslaved or is a VLAN AWARE BRIDGE
self.logger.info('%s: ignoring ip address. Interface is ' self.logger.info('%s: ignoring ip address. Interface is '

View File

@@ -244,7 +244,8 @@ class bridge(moduleBase):
ifaceobj.link_kind |= ifaceLinkKind.BRIDGE ifaceobj.link_kind |= ifaceLinkKind.BRIDGE
# for special vlan aware bridges, we need to add another bit # for special vlan aware bridges, we need to add another bit
if ifaceobj.get_attr_value_first('bridge-vlan-aware') == 'yes': if ifaceobj.get_attr_value_first('bridge-vlan-aware') == 'yes':
ifaceobj.link_kind |= ifaceLinkKind.BRIDGE_VLAN_AWARE ifaceobj.link_kind |= ifaceLinkKind.BRIDGE
ifaceobj.link_privflags |= ifaceLinkPrivFlags.BRIDGE_VLAN_AWARE
ifaceobj.role |= ifaceRole.MASTER ifaceobj.role |= ifaceRole.MASTER
ifaceobj.dependency_type = ifaceDependencyType.MASTER_SLAVE ifaceobj.dependency_type = ifaceDependencyType.MASTER_SLAVE
return self.parse_port_list(ifaceobj.name, return self.parse_port_list(ifaceobj.name,
@@ -987,7 +988,7 @@ class bridge(moduleBase):
add_port = False add_port = False
bridgename = self.ipcmd.bridge_port_get_bridge_name(ifaceobj.name) bridgename = self.ipcmd.bridge_port_get_bridge_name(ifaceobj.name)
if (not bridgename and if (not bridgename and
(ifaceobj.link_kind & ifaceLinkKind.BRIDGE_PORT)): (ifaceobj.link_privflags & ifaceLinkPrivFlags.BRIDGE_PORT)):
# get bridgename and add port to bridge # get bridgename and add port to bridge
bridgename = self._get_bridgename(ifaceobj) bridgename = self._get_bridgename(ifaceobj)
add_port = True add_port = True

View File

@@ -169,7 +169,7 @@ class vrf(moduleBase):
if not vrf_iface_name: if not vrf_iface_name:
return None return None
ifaceobj.link_type = ifaceLinkType.LINK_SLAVE ifaceobj.link_type = ifaceLinkType.LINK_SLAVE
ifaceobj.link_kind |= ifaceLinkKind.VRF_SLAVE ifaceobj.link_privflags |= ifaceLinkPrivFlags.VRF_SLAVE
return [vrf_iface_name] return [vrf_iface_name]

View File

@@ -26,10 +26,9 @@ class ifaceStatusUserStrs():
UNKNOWN = "unknown" UNKNOWN = "unknown"
class ifaceType(): class ifaceType():
UNKNOWN = 0x0 UNKNOWN = 0x00
IFACE = 0x1 IFACE = 0x01
BRIDGE_VLAN = 0x2 BRIDGE_VLAN = 0x10
class ifaceRole(): class ifaceRole():
""" ifaceRole is used to classify the ifaceobj.role of """ ifaceRole is used to classify the ifaceobj.role of
@@ -37,9 +36,9 @@ class ifaceRole():
with bond-slaves or bridge-ports. A bond in a bridge with bond-slaves or bridge-ports. A bond in a bridge
is both a master and slave (0x3) is both a master and slave (0x3)
""" """
UNKNOWN = 0x0 UNKNOWN = 0x00
SLAVE = 0x1 SLAVE = 0x01
MASTER = 0x2 MASTER = 0x10
class ifaceLinkKind(): class ifaceLinkKind():
""" ifaceLlinkKind is used to identify interfaces """ ifaceLlinkKind is used to identify interfaces
@@ -47,16 +46,47 @@ class ifaceLinkKind():
bond have an ifaceobj.role attribute of SLAVE and the bridge or bond have an ifaceobj.role attribute of SLAVE and the bridge or
bond itself has ifaceobj.role of MASTER. bond itself has ifaceobj.role of MASTER.
""" """
UNKNOWN = 0x0 UNKNOWN = 0x000000
BRIDGE = 0x1 BRIDGE = 0x000001
BOND = 0x2 BOND = 0x000010
VLAN = 0x4 VLAN = 0x000100
VXLAN = 0x8 VXLAN = 0x001000
BRIDGE_VLAN_AWARE = 0x10 VRF = 0x010000
BRIDGE_PORT = 0x20
BOND_SLAVE = 0x40 class ifaceLinkPrivFlags():
VRF = 0x80 """ This corresponds to kernel netdev->priv_flags
VRF_SLAVE = 0x100 and can be BRIDGE_PORT, BOND_SLAVE etc """
UNKNOWN = 0x0000
BRIDGE_PORT = 0x0001
BOND_SLAVE = 0x0010
VRF_SLAVE = 0x0100
BRIDGE_VLAN_AWARE = 0x1000
@classmethod
def get_str(cls, flag):
if flag == cls.UNKNOWN:
return 'unknown'
elif flag == cls.BRIDGE_PORT:
return 'bridge port'
elif flag == cls.BOND_SLAVE:
return 'bond slave'
elif flag == cls.VRF_SLAVE:
return 'vrf slave'
elif flag == cls.BRIDGE_VLAN_AWARE:
return 'vlan aware bridge'
@classmethod
def get_all_str(cls, flags):
str = ''
if (flags & cls.BRIDGE_PORT):
str += 'bridgeport '
if (flags == cls.BOND_SLAVE):
str += 'bondslave '
elif flags == cls.VRF_SLAVE:
str += 'vrfslave '
elif flags == cls.BRIDGE_VLAN_AWARE:
str += 'vlanawarebridge '
return str
class ifaceLinkType(): class ifaceLinkType():
LINK_UNKNOWN = 0x0 LINK_UNKNOWN = 0x0
@@ -344,6 +374,7 @@ class iface():
self.realname = None self.realname = None
self.link_type = ifaceLinkType.LINK_UNKNOWN self.link_type = ifaceLinkType.LINK_UNKNOWN
self.link_kind = ifaceLinkKind.UNKNOWN self.link_kind = ifaceLinkKind.UNKNOWN
self.link_privflags = ifaceLinkPrivFlags.UNKNOWN
# The below attribute is used to disambiguate between various # The below attribute is used to disambiguate between various
# types of dependencies # types of dependencies
@@ -561,6 +592,7 @@ class iface():
del odict['env'] del odict['env']
del odict['link_type'] del odict['link_type']
del odict['link_kind'] del odict['link_kind']
del odict['link_privflags']
del odict['role'] del odict['role']
del odict['dependency_type'] del odict['dependency_type']
del odict['blacklisted'] del odict['blacklisted']
@@ -584,6 +616,7 @@ class iface():
self.flags |= self._PICKLED self.flags |= self._PICKLED
self.link_type = ifaceLinkType.LINK_NA self.link_type = ifaceLinkType.LINK_NA
self.link_kind = ifaceLinkKind.UNKNOWN self.link_kind = ifaceLinkKind.UNKNOWN
self.link_privflags = ifaceLinkPrivFlags.UNKNOWN
self.dependency_type = ifaceDependencyType.UNKNOWN self.dependency_type = ifaceDependencyType.UNKNOWN
self.blacklisted = False self.blacklisted = False

View File

@@ -140,7 +140,7 @@ class ifupdownMain(ifupdownBase):
def run_down(self, ifaceobj): def run_down(self, ifaceobj):
# Skip link sets on ifaceobjs of type 'vlan' (used for l2 attrs) # Skip link sets on ifaceobjs of type 'vlan' (used for l2 attrs)
# there is no real interface behind it # there is no real interface behind it
if ifaceobj.kind & ifaceLinkKind.VRF: if ifaceobj.link_kind & ifaceLinkKind.VRF:
return return
if ifaceobj.type == ifaceType.BRIDGE_VLAN: if ifaceobj.type == ifaceType.BRIDGE_VLAN:
return return
@@ -417,7 +417,7 @@ class ifupdownMain(ifupdownBase):
return self.is_ifaceobj_noconfig(ifaceobj) return self.is_ifaceobj_noconfig(ifaceobj)
def check_shared_dependents(self, ifaceobj, dlist): def check_shared_dependents(self, ifaceobj, dlist):
""" Check if dlist intersects with any other """ ABSOLETE: Check if dlist intersects with any other
interface with slave dependents. interface with slave dependents.
example: bond and bridges. example: bond and bridges.
This function logs such errors """ This function logs such errors """
@@ -439,22 +439,38 @@ class ifupdownMain(ifupdownBase):
%(ifaceobj.name, ifacename) + %(ifaceobj.name, ifacename) +
'seem to share dependents/ports %s' %str(list(common))) 'seem to share dependents/ports %s' %str(list(common)))
def _set_iface_role(self, ifaceobj, role):
if (self.flags.CHECK_SHARED_DEPENDENTS and
(ifaceobj.role & ifaceRole.SLAVE) and role == ifaceRole.SLAVE):
self.logger.error("misconfig..? %s %s is enslaved to multiple interfaces %s"
%(ifaceobj.name,
ifaceLinkPrivFlags.get_all_str(ifaceobj.link_privflags), str(ifaceobj.upperifaces)))
ifaceobj.set_status(ifaceStatus.ERROR)
return
ifaceobj.role = role
def _set_iface_role_n_kind(self, ifaceobj, upperifaceobj): def _set_iface_role_n_kind(self, ifaceobj, upperifaceobj):
if (upperifaceobj.link_kind & ifaceLinkKind.BOND): if (upperifaceobj.link_kind & ifaceLinkKind.BOND):
ifaceobj.role |= ifaceRole.SLAVE self._set_iface_role(ifaceobj, ifaceRole.SLAVE)
ifaceobj.link_kind |= ifaceLinkKind.BOND_SLAVE ifaceobj.link_privflags |= ifaceLinkPrivFlags.BOND_SLAVE
if (upperifaceobj.link_kind & ifaceLinkKind.BRIDGE): if (upperifaceobj.link_kind & ifaceLinkKind.BRIDGE):
ifaceobj.role |= ifaceRole.SLAVE self._set_iface_role(ifaceobj, ifaceRole.SLAVE)
ifaceobj.link_kind |= ifaceLinkKind.BRIDGE_PORT ifaceobj.link_privflags |= ifaceLinkPrivFlags.BRIDGE_PORT
# vrf masters get processed after slaves, which means
# check both link_kind vrf and vrf slave
if ((upperifaceobj.link_kind & ifaceLinkKind.VRF) or
(ifaceobj.link_privflags & ifaceLinkPrivFlags.VRF_SLAVE)):
self._set_iface_role(ifaceobj, ifaceRole.SLAVE)
ifaceobj.link_privflags |= ifaceLinkPrivFlags.VRF_SLAVE
if self._link_master_slave: if self._link_master_slave:
if upperifaceobj.link_type == ifaceLinkType.LINK_MASTER: if upperifaceobj.link_type == ifaceLinkType.LINK_MASTER:
ifaceobj.link_type = ifaceLinkType.LINK_SLAVE ifaceobj.link_type = ifaceLinkType.LINK_SLAVE
else: else:
upperifaceobj.link_type = ifaceLinkType.LINK_NA upperifaceobj.link_type = ifaceLinkType.LINK_NA
ifaceobj.link_type = ifaceLinkType.LINK_NA ifaceobj.link_type = ifaceLinkType.LINK_NA
if (ifaceobj.link_kind == ifaceLinkKind.BOND_SLAVE and
len(ifaceobj.upperifaces) > 1):
self.logger.warn("misconfig..? bond slave \'%s\' is enslaved to multiple interfaces %s" %(ifaceobj.name, str(ifaceobj.upperifaces)))
def dump_iface_dependency_info(self): def dump_iface_dependency_info(self):
""" debug funtion to print raw dependency """ debug funtion to print raw dependency
@@ -485,10 +501,6 @@ class ifupdownMain(ifupdownBase):
""" """
del_list = [] del_list = []
if (upperifaceobj.dependency_type == ifaceDependencyType.MASTER_SLAVE
and self.flags.CHECK_SHARED_DEPENDENTS):
self.check_shared_dependents(upperifaceobj, dlist)
for d in dlist: for d in dlist:
dilist = self.get_ifaceobjs(d) dilist = self.get_ifaceobjs(d)
if not dilist: if not dilist:
@@ -630,6 +642,7 @@ class ifupdownMain(ifupdownBase):
ifaceobj = self.get_ifaceobj_first(i) ifaceobj = self.get_ifaceobj_first(i)
if not ifaceobj: if not ifaceobj:
continue continue
if ifaceobj.blacklisted and not ifaceobj.upperifaces: if ifaceobj.blacklisted and not ifaceobj.upperifaces:
# if blacklisted and was not picked up as a # if blacklisted and was not picked up as a
# dependent of a upper interface, delete the # dependent of a upper interface, delete the
@@ -649,6 +662,7 @@ class ifupdownMain(ifupdownBase):
pass pass
self.logger.debug("populate_dependency_info: deleting blacklisted interface %s" %i) self.logger.debug("populate_dependency_info: deleting blacklisted interface %s" %i)
del self.dependency_graph[i] del self.dependency_graph[i]
continue
def _check_config_no_repeats(self, ifaceobj): def _check_config_no_repeats(self, ifaceobj):
""" check if object has an attribute that is """ check if object has an attribute that is