Initial formatting run with Black. Integration tests and unit tests pass before and after this change.

This commit is contained in:
Pim van Pelt
2022-04-22 13:05:55 +00:00
parent b375ddb433
commit baaaaa67b5
22 changed files with 1757 additions and 1178 deletions

View File

@ -21,77 +21,78 @@ import config.address as address
import config.mac as mac
import config.tap as tap
def get_qinx_parent_by_name(yaml, ifname):
""" Returns the sub-interface which matches a QinAD or QinQ outer tag, or None,None
if that sub-interface doesn't exist. """
"""Returns the sub-interface which matches a QinAD or QinQ outer tag, or None,None
if that sub-interface doesn't exist."""
if not is_qinx(yaml, ifname):
return None, None
qinx_ifname, qinx_iface = get_by_name(yaml, ifname)
if not qinx_iface:
return None,None
return None, None
qinx_encap = get_encapsulation(yaml, ifname)
if not qinx_encap:
return None,None
return None, None
parent_ifname, parent_iface = get_parent_by_name(yaml, ifname)
if not parent_iface:
return None,None
return None, None
for subid, sub_iface in parent_iface['sub-interfaces'].items():
for subid, sub_iface in parent_iface["sub-interfaces"].items():
sub_ifname = f"{parent_ifname}.{int(subid)}"
sub_encap = get_encapsulation(yaml, sub_ifname)
if not sub_encap:
continue
if qinx_encap['dot1q'] > 0 and sub_encap['dot1q'] == qinx_encap['dot1q']:
if qinx_encap["dot1q"] > 0 and sub_encap["dot1q"] == qinx_encap["dot1q"]:
return sub_ifname, sub_iface
if qinx_encap['dot1ad'] > 0 and sub_encap['dot1ad'] == qinx_encap['dot1ad']:
if qinx_encap["dot1ad"] > 0 and sub_encap["dot1ad"] == qinx_encap["dot1ad"]:
return sub_ifname, sub_iface
return None,None
return None, None
def get_parent_by_name(yaml, ifname):
""" Returns the sub-interface's parent, or None,None if the sub-int doesn't exist. """
"""Returns the sub-interface's parent, or None,None if the sub-int doesn't exist."""
try:
parent_ifname, subid = ifname.split('.')
parent_ifname, subid = ifname.split(".")
subid = int(subid)
iface = yaml['interfaces'][parent_ifname]
iface = yaml["interfaces"][parent_ifname]
return parent_ifname, iface
except:
pass
return None,None
return None, None
def get_by_lcp_name(yaml, lcpname):
""" Returns the interface or sub-interface by a given lcp name, or None,None if it does not exist """
if not 'interfaces' in yaml:
return None,None
for ifname, iface in yaml['interfaces'].items():
if 'lcp' in iface and iface['lcp'] == lcpname:
"""Returns the interface or sub-interface by a given lcp name, or None,None if it does not exist"""
if not "interfaces" in yaml:
return None, None
for ifname, iface in yaml["interfaces"].items():
if "lcp" in iface and iface["lcp"] == lcpname:
return ifname, iface
if not 'sub-interfaces' in iface:
if not "sub-interfaces" in iface:
continue
for subid, sub_iface in yaml['interfaces'][ifname]['sub-interfaces'].items():
for subid, sub_iface in yaml["interfaces"][ifname]["sub-interfaces"].items():
sub_ifname = f"{ifname}.{int(subid)}"
if 'lcp' in sub_iface and sub_iface['lcp'] == lcpname:
if "lcp" in sub_iface and sub_iface["lcp"] == lcpname:
return sub_ifname, sub_iface
return None,None
return None, None
def get_by_name(yaml, ifname):
""" Returns the interface or sub-interface by a given name, or None,None if it does not exist """
if '.' in ifname:
"""Returns the interface or sub-interface by a given name, or None,None if it does not exist"""
if "." in ifname:
try:
phy_ifname, subid = ifname.split('.')
phy_ifname, subid = ifname.split(".")
subid = int(subid)
iface = yaml['interfaces'][phy_ifname]['sub-interfaces'][subid]
iface = yaml["interfaces"][phy_ifname]["sub-interfaces"][subid]
return ifname, iface
except:
return None, None
try:
iface = yaml['interfaces'][ifname]
iface = yaml["interfaces"][ifname]
return ifname, iface
except:
pass
@ -99,121 +100,125 @@ def get_by_name(yaml, ifname):
def is_sub(yaml, ifname):
""" Returns True if this interface is a sub-interface """
"""Returns True if this interface is a sub-interface"""
parent_ifname, parent_iface = get_parent_by_name(yaml, ifname)
return isinstance(parent_iface, dict)
def has_sub(yaml, ifname):
""" Returns True if this interface has sub-interfaces """
if not 'interfaces' in yaml:
"""Returns True if this interface has sub-interfaces"""
if not "interfaces" in yaml:
return False
if ifname in yaml['interfaces']:
iface = yaml['interfaces'][ifname]
if 'sub-interfaces' in iface and len(iface['sub-interfaces']) > 0:
if ifname in yaml["interfaces"]:
iface = yaml["interfaces"][ifname]
if "sub-interfaces" in iface and len(iface["sub-interfaces"]) > 0:
return True
return False
def has_address(yaml, ifname):
""" Returns True if this interface or sub-interface has one or more addresses"""
"""Returns True if this interface or sub-interface has one or more addresses"""
ifname, iface = get_by_name(yaml, ifname)
if not iface:
return False
return 'addresses' in iface
return "addresses" in iface
def get_l2xc_interfaces(yaml):
""" Returns a list of all interfaces that have an L2 CrossConnect """
"""Returns a list of all interfaces that have an L2 CrossConnect"""
ret = []
if not 'interfaces' in yaml:
if not "interfaces" in yaml:
return ret
for ifname, iface in yaml['interfaces'].items():
if 'l2xc' in iface:
for ifname, iface in yaml["interfaces"].items():
if "l2xc" in iface:
ret.append(ifname)
if 'sub-interfaces' in iface:
for subid, sub_iface in iface['sub-interfaces'].items():
if "sub-interfaces" in iface:
for subid, sub_iface in iface["sub-interfaces"].items():
sub_ifname = f"{ifname}.{int(subid)}"
if 'l2xc' in sub_iface:
if "l2xc" in sub_iface:
ret.append(sub_ifname)
return ret
def is_l2xc_interface(yaml, ifname):
""" Returns True if this interface has an L2 CrossConnect """
"""Returns True if this interface has an L2 CrossConnect"""
return ifname in get_l2xc_interfaces(yaml)
def get_l2xc_target_interfaces(yaml):
""" Returns a list of all interfaces that are the target of an L2 CrossConnect """
"""Returns a list of all interfaces that are the target of an L2 CrossConnect"""
ret = []
if 'interfaces' in yaml:
for ifname, iface in yaml['interfaces'].items():
if 'l2xc' in iface:
ret.append(iface['l2xc'])
if 'sub-interfaces' in iface:
for subid, sub_iface in iface['sub-interfaces'].items():
if 'l2xc' in sub_iface:
ret.append(sub_iface['l2xc'])
if "interfaces" in yaml:
for ifname, iface in yaml["interfaces"].items():
if "l2xc" in iface:
ret.append(iface["l2xc"])
if "sub-interfaces" in iface:
for subid, sub_iface in iface["sub-interfaces"].items():
if "l2xc" in sub_iface:
ret.append(sub_iface["l2xc"])
return ret
def is_l2xc_target_interface(yaml, ifname):
""" Returns True if this interface is the target of an L2 CrossConnect """
"""Returns True if this interface is the target of an L2 CrossConnect"""
return ifname in get_l2xc_target_interfaces(yaml)
def is_l2xc_target_interface_unique(yaml, ifname):
""" Returns True if this interface is referenced as an l2xc target zero or one times """
"""Returns True if this interface is referenced as an l2xc target zero or one times"""
ifs = get_l2xc_target_interfaces(yaml)
return ifs.count(ifname) < 2
def has_lcp(yaml, ifname):
""" Returns True if this interface or sub-interface has an LCP """
"""Returns True if this interface or sub-interface has an LCP"""
ifname, iface = get_by_name(yaml, ifname)
if not iface:
return False
return 'lcp' in iface
return "lcp" in iface
def valid_encapsulation(yaml, ifname):
""" Returns True if the sub interface has a valid encapsulation, or
none at all """
"""Returns True if the sub interface has a valid encapsulation, or
none at all"""
ifname, iface = get_by_name(yaml, ifname)
if not iface:
return True
if not 'encapsulation' in iface:
if not "encapsulation" in iface:
return True
encap = iface['encapsulation']
if 'dot1ad' in encap and 'dot1q' in encap:
encap = iface["encapsulation"]
if "dot1ad" in encap and "dot1q" in encap:
return False
if 'inner-dot1q' in encap and not ('dot1ad' in encap or 'dot1q' in encap):
if "inner-dot1q" in encap and not ("dot1ad" in encap or "dot1q" in encap):
return False
if 'exact-match' in encap and encap['exact-match'] == False and has_lcp(yaml, ifname):
if (
"exact-match" in encap
and encap["exact-match"] == False
and has_lcp(yaml, ifname)
):
return False
return True
def get_encapsulation(yaml, ifname):
""" Returns the encapsulation of an interface name as a fully formed dictionary:
"""Returns the encapsulation of an interface name as a fully formed dictionary:
dot1q: int (default 0)
dot1ad: int (default 0)
inner-dot1q: int (default 0)
exact-match: bool (default False)
dot1q: int (default 0)
dot1ad: int (default 0)
inner-dot1q: int (default 0)
exact-match: bool (default False)
If the interface is not a sub-int with valid encapsulation, None is returned.
If the interface is not a sub-int with valid encapsulation, None is returned.
"""
if not valid_encapsulation(yaml, ifname):
return None
@ -225,49 +230,49 @@ def get_encapsulation(yaml, ifname):
parent_ifname, parent_iface = get_parent_by_name(yaml, ifname)
if not iface or not parent_iface:
return None
parent_ifname, subid = ifname.split('.')
parent_ifname, subid = ifname.split(".")
dot1q = 0
dot1ad = 0
inner_dot1q = 0
exact_match = False
if not 'encapsulation' in iface:
if not "encapsulation" in iface:
dot1q = int(subid)
exact_match = True
else:
if 'dot1q' in iface['encapsulation']:
dot1q = iface['encapsulation']['dot1q']
elif 'dot1ad' in iface['encapsulation']:
dot1ad = iface['encapsulation']['dot1ad']
if 'inner-dot1q' in iface['encapsulation']:
inner_dot1q = iface['encapsulation']['inner-dot1q']
if 'exact-match' in iface['encapsulation']:
exact_match = iface['encapsulation']['exact-match']
if "dot1q" in iface["encapsulation"]:
dot1q = iface["encapsulation"]["dot1q"]
elif "dot1ad" in iface["encapsulation"]:
dot1ad = iface["encapsulation"]["dot1ad"]
if "inner-dot1q" in iface["encapsulation"]:
inner_dot1q = iface["encapsulation"]["inner-dot1q"]
if "exact-match" in iface["encapsulation"]:
exact_match = iface["encapsulation"]["exact-match"]
return {
"dot1q": int(dot1q),
"dot1ad": int(dot1ad),
"inner-dot1q": int(inner_dot1q),
"exact-match": bool(exact_match)
}
"dot1q": int(dot1q),
"dot1ad": int(dot1ad),
"inner-dot1q": int(inner_dot1q),
"exact-match": bool(exact_match),
}
def get_phys(yaml):
""" Return a list of all toplevel (ie. non-sub) interfaces which are
"""Return a list of all toplevel (ie. non-sub) interfaces which are
assumed to be physical network cards, eg TenGigabitEthernet1/0/0. Note
that derived/created interfaces such as Tunnels, BondEthernets and
Loopbacks are not returned """
Loopbacks are not returned"""
ret = []
if not 'interfaces' in yaml:
if not "interfaces" in yaml:
return ret
for ifname, iface in yaml['interfaces'].items():
for ifname, iface in yaml["interfaces"].items():
if is_phy(yaml, ifname):
ret.append(ifname)
return ret
def is_phy(yaml, ifname):
""" Returns True if the ifname is the name of a physical network interface. """
"""Returns True if the ifname is the name of a physical network interface."""
ifname, iface = get_by_name(yaml, ifname)
if iface == None:
@ -287,33 +292,34 @@ def is_phy(yaml, ifname):
def get_interfaces(yaml):
""" Return a list of all interface and sub-interface names """
"""Return a list of all interface and sub-interface names"""
ret = []
if not 'interfaces' in yaml:
if not "interfaces" in yaml:
return ret
for ifname, iface in yaml['interfaces'].items():
for ifname, iface in yaml["interfaces"].items():
ret.append(ifname)
if not 'sub-interfaces' in iface:
if not "sub-interfaces" in iface:
continue
for subid, sub_iface in iface['sub-interfaces'].items():
for subid, sub_iface in iface["sub-interfaces"].items():
ret.append(f"{ifname}.{int(subid)}")
return ret
def get_sub_interfaces(yaml):
""" Return all interfaces which are a subinterface. """
"""Return all interfaces which are a subinterface."""
ret = []
for ifname in get_interfaces(yaml):
if is_sub(yaml, ifname):
ret.append(ifname)
return ret
def get_qinx_interfaces(yaml):
""" Return all interfaces which are double-tagged, either QinAD or QinQ.
These interfaces will always have a valid encapsulation with 'inner-dot1q'
set to non-zero.
Note: this is always a strict subset of get_sub_interfaces()
def get_qinx_interfaces(yaml):
"""Return all interfaces which are double-tagged, either QinAD or QinQ.
These interfaces will always have a valid encapsulation with 'inner-dot1q'
set to non-zero.
Note: this is always a strict subset of get_sub_interfaces()
"""
ret = []
for ifname in get_interfaces(yaml):
@ -322,19 +328,19 @@ def get_qinx_interfaces(yaml):
encap = get_encapsulation(yaml, ifname)
if not encap:
continue
if encap['inner-dot1q'] > 0:
if encap["inner-dot1q"] > 0:
ret.append(ifname)
return ret
def is_qinx(yaml, ifname):
""" Returns True if the interface is a double-tagged (QinQ or QinAD) interface """
"""Returns True if the interface is a double-tagged (QinQ or QinAD) interface"""
return ifname in get_qinx_interfaces(yaml)
def unique_encapsulation(yaml, sub_ifname):
""" Ensures that for the sub_ifname specified, there exist no other sub-ints on the
parent with the same encapsulation. """
"""Ensures that for the sub_ifname specified, there exist no other sub-ints on the
parent with the same encapsulation."""
new_ifname, iface = get_by_name(yaml, sub_ifname)
parent_ifname, parent_iface = get_parent_by_name(yaml, new_ifname)
if not iface or not parent_iface:
@ -345,7 +351,7 @@ def unique_encapsulation(yaml, sub_ifname):
return False
ncount = 0
for subid, sibling_iface in parent_iface['sub-interfaces'].items():
for subid, sibling_iface in parent_iface["sub-interfaces"].items():
sibling_ifname = f"{parent_ifname}.{int(subid)}"
sibling_encap = get_encapsulation(yaml, sibling_ifname)
if sub_encap == sibling_encap and new_ifname != sibling_ifname:
@ -355,7 +361,7 @@ def unique_encapsulation(yaml, sub_ifname):
def is_l2(yaml, ifname):
""" Returns True if the interface is an L2XC source, L2XC target or a member of a bridgedomain """
"""Returns True if the interface is an L2XC source, L2XC target or a member of a bridgedomain"""
if bridgedomain.is_bridge_interface(yaml, ifname):
return True
if is_l2xc_interface(yaml, ifname):
@ -366,22 +372,23 @@ def is_l2(yaml, ifname):
def is_l3(yaml, ifname):
""" Returns True if the interface exists and is neither l2xc target nor bridgedomain """
"""Returns True if the interface exists and is neither l2xc target nor bridgedomain"""
return not is_l2(yaml, ifname)
def get_lcp(yaml, ifname):
""" Returns the LCP of the interface. If the interface is a sub-interface with L3
"""Returns the LCP of the interface. If the interface is a sub-interface with L3
enabled, synthesize it based on its parent, using smart QinQ syntax.
Return None if no LCP can be found. """
Return None if no LCP can be found."""
ifname, iface = get_by_name(yaml, ifname)
if iface and 'lcp' in iface:
return iface['lcp']
if iface and "lcp" in iface:
return iface["lcp"]
return None
def get_mtu(yaml, ifname):
""" Returns MTU of the interface. If it's not set, return the parent's MTU, and
"""Returns MTU of the interface. If it's not set, return the parent's MTU, and
return 1500 if no MTU was set on the sub-int or the parent."""
ifname, iface = get_by_name(yaml, ifname)
if not iface:
@ -390,61 +397,70 @@ def get_mtu(yaml, ifname):
parent_ifname, parent_iface = get_parent_by_name(yaml, ifname)
try:
return iface['mtu']
return parent_iface['mtu']
return iface["mtu"]
return parent_iface["mtu"]
except:
pass
return 1500
def get_admin_state(yaml, ifname):
""" Return True if the interface admin state should be 'up'. Return False
if it does not exist, or if it's set to 'down'. """
"""Return True if the interface admin state should be 'up'. Return False
if it does not exist, or if it's set to 'down'."""
ifname, iface = get_by_name(yaml, ifname)
if not iface:
return False
if not 'state' in iface:
if not "state" in iface:
return True
return iface['state'] == 'up'
return iface["state"] == "up"
def validate_interfaces(yaml):
result = True
msgs = []
logger = logging.getLogger('vppcfg.config')
logger = logging.getLogger("vppcfg.config")
logger.addHandler(logging.NullHandler())
if not 'interfaces' in yaml:
if not "interfaces" in yaml:
return result, msgs
for ifname, iface in yaml['interfaces'].items():
for ifname, iface in yaml["interfaces"].items():
logger.debug(f"interface {iface}")
if ifname.startswith("BondEthernet") and (None,None) == bondethernet.get_by_name(yaml, ifname):
if ifname.startswith("BondEthernet") and (
None,
None,
) == bondethernet.get_by_name(yaml, ifname):
msgs.append(f"interface {ifname} does not exist in bondethernets")
result = False
if ifname.startswith("BondEthernet") and 'mac' in iface:
msgs.append(f"interface {ifname} is a member of bondethernet, cannot set MAC")
if ifname.startswith("BondEthernet") and "mac" in iface:
msgs.append(
f"interface {ifname} is a member of bondethernet, cannot set MAC"
)
result = False
if not 'state' in iface:
iface['state'] = 'up'
if not "state" in iface:
iface["state"] = "up"
if 'mac' in iface and mac.is_multicast(iface['mac']):
msgs.append(f"interface {ifname} MAC address {iface['mac']} cannot be multicast")
if "mac" in iface and mac.is_multicast(iface["mac"]):
msgs.append(
f"interface {ifname} MAC address {iface['mac']} cannot be multicast"
)
result = False
iface_mtu = get_mtu(yaml, ifname)
iface_lcp = get_lcp(yaml, ifname)
iface_address = has_address(yaml, ifname)
if ifname.startswith('tap'):
if ifname.startswith("tap"):
tap_ifname, tap_iface = tap.get_by_name(yaml, ifname)
if not tap_iface:
msgs.append(f"interface {ifname} is a TAP but does not exist in taps")
result = False
elif 'mtu' in tap_iface['host']:
host_mtu = tap_iface['host']['mtu']
elif "mtu" in tap_iface["host"]:
host_mtu = tap_iface["host"]["mtu"]
if host_mtu != iface_mtu:
msgs.append(f"interface {ifname} is a TAP so its MTU {int(iface_mtu)} must match host MTU {int(host_mtu)}")
msgs.append(
f"interface {ifname} is a TAP so its MTU {int(iface_mtu)} must match host MTU {int(host_mtu)}"
)
result = False
if iface_address:
msgs.append(f"interface {ifname} is a TAP so it cannot have an address")
@ -453,28 +469,38 @@ def validate_interfaces(yaml):
msgs.append(f"interface {ifname} is a TAP so it cannot have an LCP")
result = False
if has_sub(yaml, ifname):
msgs.append(f"interface {ifname} is a TAP so it cannot have sub-interfaces")
msgs.append(
f"interface {ifname} is a TAP so it cannot have sub-interfaces"
)
result = False
if is_l2(yaml, ifname) and iface_lcp:
msgs.append(f"interface {ifname} is in L2 mode but has LCP name {iface_lcp}")
msgs.append(
f"interface {ifname} is in L2 mode but has LCP name {iface_lcp}"
)
result = False
if is_l2(yaml, ifname) and iface_address:
msgs.append(f"interface {ifname} is in L2 mode but has an address")
result = False
if iface_lcp and not lcp.is_unique(yaml, iface_lcp):
msgs.append(f"interface {ifname} does not have a unique LCP name {iface_lcp}")
msgs.append(
f"interface {ifname} does not have a unique LCP name {iface_lcp}"
)
result = False
if 'addresses' in iface:
for a in iface['addresses']:
if not address.is_allowed(yaml, ifname, iface['addresses'], a):
msgs.append(f"interface {ifname} IP address {a} conflicts with another")
if "addresses" in iface:
for a in iface["addresses"]:
if not address.is_allowed(yaml, ifname, iface["addresses"], a):
msgs.append(
f"interface {ifname} IP address {a} conflicts with another"
)
result = False
if 'l2xc' in iface:
if "l2xc" in iface:
if has_sub(yaml, ifname):
msgs.append(f"interface {ifname} has l2xc so it cannot have sub-interfaces")
msgs.append(
f"interface {ifname} has l2xc so it cannot have sub-interfaces"
)
result = False
if iface_lcp:
msgs.append(f"interface {ifname} has l2xc so it cannot have an LCP")
@ -482,31 +508,45 @@ def validate_interfaces(yaml):
if iface_address:
msgs.append(f"interface {ifname} has l2xc so it cannot have an address")
result = False
if (None,None) == get_by_name(yaml, iface['l2xc']):
msgs.append(f"interface {ifname} l2xc target {iface['l2xc']} does not exist")
if (None, None) == get_by_name(yaml, iface["l2xc"]):
msgs.append(
f"interface {ifname} l2xc target {iface['l2xc']} does not exist"
)
result = False
if iface['l2xc'] == ifname:
if iface["l2xc"] == ifname:
msgs.append(f"interface {ifname} l2xc target cannot be itself")
result = False
target_mtu = get_mtu(yaml, iface['l2xc'])
target_mtu = get_mtu(yaml, iface["l2xc"])
if target_mtu != iface_mtu:
msgs.append(f"interface {ifname} l2xc target MTU {int(target_mtu)} does not match source MTU {int(iface_mtu)}")
msgs.append(
f"interface {ifname} l2xc target MTU {int(target_mtu)} does not match source MTU {int(iface_mtu)}"
)
result = False
if not is_l2xc_target_interface_unique(yaml, iface['l2xc']):
msgs.append(f"interface {ifname} l2xc target {iface['l2xc']} is not unique")
if not is_l2xc_target_interface_unique(yaml, iface["l2xc"]):
msgs.append(
f"interface {ifname} l2xc target {iface['l2xc']} is not unique"
)
result = False
if bridgedomain.is_bridge_interface(yaml, iface['l2xc']):
msgs.append(f"interface {ifname} l2xc target {iface['l2xc']} is in a bridgedomain")
if bridgedomain.is_bridge_interface(yaml, iface["l2xc"]):
msgs.append(
f"interface {ifname} l2xc target {iface['l2xc']} is in a bridgedomain"
)
result = False
if has_lcp(yaml, iface['l2xc']):
msgs.append(f"interface {ifname} l2xc target {iface['l2xc']} cannot have an LCP")
if has_lcp(yaml, iface["l2xc"]):
msgs.append(
f"interface {ifname} l2xc target {iface['l2xc']} cannot have an LCP"
)
result = False
if has_address(yaml, iface['l2xc']):
msgs.append(f"interface {ifname} l2xc target {iface['l2xc']} cannot have an address")
if has_address(yaml, iface["l2xc"]):
msgs.append(
f"interface {ifname} l2xc target {iface['l2xc']} cannot have an address"
)
result = False
if has_sub(yaml, ifname):
for sub_id, sub_iface in yaml['interfaces'][ifname]['sub-interfaces'].items():
for sub_id, sub_iface in yaml["interfaces"][ifname][
"sub-interfaces"
].items():
logger.debug(f"sub-interface {sub_iface}")
sub_ifname = f"{ifname}.{int(sub_id)}"
if not sub_iface:
@ -514,93 +554,138 @@ def validate_interfaces(yaml):
result = False
continue
if not 'state' in sub_iface:
sub_iface['state'] = 'up'
if sub_iface['state'] == 'up' and iface['state'] == 'down':
msgs.append(f"sub-interface {sub_ifname} cannot be up if parent {ifname} is down")
if not "state" in sub_iface:
sub_iface["state"] = "up"
if sub_iface["state"] == "up" and iface["state"] == "down":
msgs.append(
f"sub-interface {sub_ifname} cannot be up if parent {ifname} is down"
)
result = False
sub_mtu = get_mtu(yaml, sub_ifname)
if sub_mtu > iface_mtu:
msgs.append(f"sub-interface {sub_ifname} has MTU {int(sub_iface['mtu'])} higher than parent {ifname} MTU {int(iface_mtu)}")
msgs.append(
f"sub-interface {sub_ifname} has MTU {int(sub_iface['mtu'])} higher than parent {ifname} MTU {int(iface_mtu)}"
)
result = False
if is_qinx(yaml, sub_ifname):
mid_ifname, mid_iface = get_qinx_parent_by_name(yaml, sub_ifname)
mid_mtu = get_mtu(yaml, mid_ifname)
if sub_mtu > mid_mtu:
msgs.append(f"sub-interface {sub_ifname} has MTU {int(sub_iface['mtu'])} higher than parent {mid_ifname} MTU {int(mid_mtu)}")
msgs.append(
f"sub-interface {sub_ifname} has MTU {int(sub_iface['mtu'])} higher than parent {mid_ifname} MTU {int(mid_mtu)}"
)
result = False
sub_lcp = get_lcp(yaml, sub_ifname)
if is_l2(yaml, sub_ifname) and sub_lcp:
msgs.append(f"sub-interface {sub_ifname} is in L2 mode but has LCP name {sub_lcp}")
msgs.append(
f"sub-interface {sub_ifname} is in L2 mode but has LCP name {sub_lcp}"
)
result = False
if sub_lcp and not lcp.is_unique(yaml, sub_lcp):
msgs.append(f"sub-interface {sub_ifname} does not have a unique LCP name {sub_lcp}")
msgs.append(
f"sub-interface {sub_ifname} does not have a unique LCP name {sub_lcp}"
)
result = False
if sub_lcp and not iface_lcp:
msgs.append(f"sub-interface {sub_ifname} has LCP name {sub_lcp} but {ifname} does not have an LCP")
msgs.append(
f"sub-interface {sub_ifname} has LCP name {sub_lcp} but {ifname} does not have an LCP"
)
result = False
if sub_lcp and is_qinx(yaml, sub_ifname):
mid_ifname, mid_iface = get_qinx_parent_by_name(yaml, sub_ifname)
if not mid_iface:
msgs.append(f"sub-interface {sub_ifname} is QinX and has LCP name {sub_lcp} which requires a parent")
msgs.append(
f"sub-interface {sub_ifname} is QinX and has LCP name {sub_lcp} which requires a parent"
)
result = False
elif not get_lcp(yaml, mid_ifname):
msgs.append(f"sub-interface {sub_ifname} is QinX and has LCP name {sub_lcp} but {mid_ifname} does not have an LCP")
msgs.append(
f"sub-interface {sub_ifname} is QinX and has LCP name {sub_lcp} but {mid_ifname} does not have an LCP"
)
result = False
encap = get_encapsulation(yaml, sub_ifname)
if sub_lcp and (not encap or not encap['exact-match']):
msgs.append(f"sub-interface {sub_ifname} has LCP name {sub_lcp} but its encapsulation is not exact-match")
if sub_lcp and (not encap or not encap["exact-match"]):
msgs.append(
f"sub-interface {sub_ifname} has LCP name {sub_lcp} but its encapsulation is not exact-match"
)
result = False
if has_address(yaml, sub_ifname):
if not encap or not encap['exact-match']:
msgs.append(f"sub-interface {sub_ifname} has an address but its encapsulation is not exact-match")
if not encap or not encap["exact-match"]:
msgs.append(
f"sub-interface {sub_ifname} has an address but its encapsulation is not exact-match"
)
result = False
if is_l2(yaml, sub_ifname):
msgs.append(f"sub-interface {sub_ifname} is in L2 mode but has an address")
msgs.append(
f"sub-interface {sub_ifname} is in L2 mode but has an address"
)
result = False
for a in sub_iface['addresses']:
if not address.is_allowed(yaml, sub_ifname, sub_iface['addresses'], a):
msgs.append(f"sub-interface {sub_ifname} IP address {a} conflicts with another")
for a in sub_iface["addresses"]:
if not address.is_allowed(
yaml, sub_ifname, sub_iface["addresses"], a
):
msgs.append(
f"sub-interface {sub_ifname} IP address {a} conflicts with another"
)
result = False
if not valid_encapsulation(yaml, sub_ifname):
msgs.append(f"sub-interface {sub_ifname} has invalid encapsulation")
result = False
elif not unique_encapsulation(yaml, sub_ifname):
msgs.append(f"sub-interface {sub_ifname} does not have unique encapsulation")
msgs.append(
f"sub-interface {sub_ifname} does not have unique encapsulation"
)
result = False
if 'l2xc' in sub_iface:
if "l2xc" in sub_iface:
if has_lcp(yaml, sub_ifname):
msgs.append(f"sub-interface {sub_ifname} has l2xc so it cannot have an LCP")
msgs.append(
f"sub-interface {sub_ifname} has l2xc so it cannot have an LCP"
)
result = False
if has_address(yaml, sub_ifname):
msgs.append(f"sub-interface {sub_ifname} has l2xc so it cannot have an address")
msgs.append(
f"sub-interface {sub_ifname} has l2xc so it cannot have an address"
)
result = False
if (None, None) == get_by_name(yaml, sub_iface['l2xc']):
msgs.append(f"sub-interface {sub_ifname} l2xc target {sub_iface['l2xc']} does not exist")
if (None, None) == get_by_name(yaml, sub_iface["l2xc"]):
msgs.append(
f"sub-interface {sub_ifname} l2xc target {sub_iface['l2xc']} does not exist"
)
result = False
if sub_iface['l2xc'] == sub_ifname:
msgs.append(f"sub-interface {sub_ifname} l2xc target cannot be itself")
if sub_iface["l2xc"] == sub_ifname:
msgs.append(
f"sub-interface {sub_ifname} l2xc target cannot be itself"
)
result = False
target_mtu = get_mtu(yaml, sub_iface['l2xc'])
target_mtu = get_mtu(yaml, sub_iface["l2xc"])
if target_mtu != sub_mtu:
msgs.append(f"sub-interface {ifname} l2xc target MTU {int(target_mtu)} does not match source MTU {int(sub_mtu)}")
msgs.append(
f"sub-interface {ifname} l2xc target MTU {int(target_mtu)} does not match source MTU {int(sub_mtu)}"
)
result = False
if not is_l2xc_target_interface_unique(yaml, sub_iface['l2xc']):
msgs.append(f"sub-interface {sub_ifname} l2xc target {sub_iface['l2xc']} is not unique")
if not is_l2xc_target_interface_unique(yaml, sub_iface["l2xc"]):
msgs.append(
f"sub-interface {sub_ifname} l2xc target {sub_iface['l2xc']} is not unique"
)
result = False
if bridgedomain.is_bridge_interface(yaml, sub_iface['l2xc']):
msgs.append(f"sub-interface {sub_ifname} l2xc target {sub_iface['l2xc']} is in a bridgedomain")
if bridgedomain.is_bridge_interface(yaml, sub_iface["l2xc"]):
msgs.append(
f"sub-interface {sub_ifname} l2xc target {sub_iface['l2xc']} is in a bridgedomain"
)
result = False
if has_lcp(yaml, sub_iface['l2xc']):
msgs.append(f"sub-interface {sub_ifname} l2xc target {sub_iface['l2xc']} cannot have an LCP")
if has_lcp(yaml, sub_iface["l2xc"]):
msgs.append(
f"sub-interface {sub_ifname} l2xc target {sub_iface['l2xc']} cannot have an LCP"
)
result = False
if has_address(yaml, sub_iface['l2xc']):
msgs.append(f"sub-interface {sub_ifname} l2xc target {sub_iface['l2xc']} cannot have an address")
if has_address(yaml, sub_iface["l2xc"]):
msgs.append(
f"sub-interface {sub_ifname} l2xc target {sub_iface['l2xc']} cannot have an address"
)
result = False
return result, msgs