unnumbered: Add syntax and semantic checking and unit tests
This commit is contained in:
@ -152,6 +152,23 @@ def get_l2xc_interfaces(yaml):
|
||||
return ret
|
||||
|
||||
|
||||
def get_unnumbered_interfaces(yaml):
|
||||
"""Returns a list of all interfaces that are unnumbered"""
|
||||
ret = []
|
||||
if not "interfaces" in yaml:
|
||||
return ret
|
||||
for ifname, iface in yaml["interfaces"].items():
|
||||
if "unnumbered" in iface:
|
||||
ret.append(ifname)
|
||||
if "sub-interfaces" in iface:
|
||||
for subid, sub_iface in iface["sub-interfaces"].items():
|
||||
sub_ifname = f"{ifname}.{int(subid)}"
|
||||
if "unnumbered" in sub_iface:
|
||||
ret.append(sub_ifname)
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def is_l2xc_interface(yaml, ifname):
|
||||
"""Returns True if this interface has an L2 CrossConnect"""
|
||||
|
||||
@ -381,6 +398,11 @@ def is_l3(yaml, ifname):
|
||||
return not is_l2(yaml, ifname)
|
||||
|
||||
|
||||
def is_unnumbered(yaml, ifname):
|
||||
"""Returns True if the interface exists and is unnumbered"""
|
||||
return ifname in get_unnumbered_interfaces(yaml)
|
||||
|
||||
|
||||
def get_lcp(yaml, ifname):
|
||||
"""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.
|
||||
@ -494,6 +516,37 @@ def validate_interfaces(yaml):
|
||||
)
|
||||
result = False
|
||||
|
||||
if "unnumbered" in iface:
|
||||
target = iface["unnumbered"]
|
||||
_, target_iface = loopback.get_by_name(yaml, target)
|
||||
if not target_iface:
|
||||
_, target_iface = get_by_name(yaml, target)
|
||||
if not target_iface:
|
||||
msgs.append(
|
||||
f"interface {ifname} unnumbered target {target} does not exist"
|
||||
)
|
||||
result = False
|
||||
if is_l2(yaml, target):
|
||||
msgs.append(
|
||||
f"interface {ifname} unnumbered target {target} cannot be in L2 mode"
|
||||
)
|
||||
result = False
|
||||
if is_unnumbered(yaml, target):
|
||||
msgs.append(
|
||||
f"interface {ifname} unnumbered target {target} cannot also be unnumbered"
|
||||
)
|
||||
result = False
|
||||
if ifname == target:
|
||||
msgs.append(
|
||||
f"interface {ifname} unnumbered target cannot point to itself"
|
||||
)
|
||||
result = False
|
||||
if has_address(yaml, ifname):
|
||||
msgs.append(
|
||||
f"interface {ifname} cannot also have addresses when it is unnumbered"
|
||||
)
|
||||
result = False
|
||||
|
||||
if "addresses" in iface:
|
||||
for addr in iface["addresses"]:
|
||||
if not address.is_allowed(yaml, ifname, iface["addresses"], addr):
|
||||
@ -625,6 +678,37 @@ def validate_interfaces(yaml):
|
||||
)
|
||||
result = False
|
||||
|
||||
if "unnumbered" in sub_iface:
|
||||
target = sub_iface["unnumbered"]
|
||||
_, target_iface = loopback.get_by_name(yaml, target)
|
||||
if not target_iface:
|
||||
_, target_iface = get_by_name(yaml, target)
|
||||
if not target_iface:
|
||||
msgs.append(
|
||||
f"sub-interface {sub_ifname} unnumbered target {target} does not exist"
|
||||
)
|
||||
result = False
|
||||
if is_l2(yaml, target):
|
||||
msgs.append(
|
||||
f"sub-interface {sub_ifname} unnumbered target {target} cannot be in L2 mode"
|
||||
)
|
||||
result = False
|
||||
if is_unnumbered(yaml, target):
|
||||
msgs.append(
|
||||
f"sub-interface {sub_ifname} unnumbered target {target} cannot also be unnumbered"
|
||||
)
|
||||
result = False
|
||||
if sub_ifname == target:
|
||||
msgs.append(
|
||||
f"sub-interface {sub_ifname} unnumbered target cannot point to itself"
|
||||
)
|
||||
result = False
|
||||
if has_address(yaml, sub_ifname):
|
||||
msgs.append(
|
||||
f"sub-interface {sub_ifname} cannot also have addresses when it is unnumbered"
|
||||
)
|
||||
result = False
|
||||
|
||||
if has_address(yaml, sub_ifname):
|
||||
if not encap or not encap["exact-match"]:
|
||||
msgs.append(
|
||||
|
@ -26,12 +26,12 @@ class TestInterfaceMethods(unittest.TestCase):
|
||||
|
||||
def test_enumerators(self):
|
||||
ifs = interface.get_interfaces(self.cfg)
|
||||
self.assertEqual(len(ifs), 19)
|
||||
self.assertEqual(len(ifs), 27)
|
||||
self.assertIn("GigabitEthernet1/0/1", ifs)
|
||||
self.assertIn("GigabitEthernet1/0/1.200", ifs)
|
||||
|
||||
ifs = interface.get_sub_interfaces(self.cfg)
|
||||
self.assertEqual(len(ifs), 13)
|
||||
self.assertEqual(len(ifs), 17)
|
||||
self.assertNotIn("GigabitEthernet1/0/1", ifs)
|
||||
self.assertIn("GigabitEthernet1/0/1.200", ifs)
|
||||
self.assertIn("GigabitEthernet1/0/1.201", ifs)
|
||||
@ -261,7 +261,7 @@ class TestInterfaceMethods(unittest.TestCase):
|
||||
|
||||
def test_get_phys(self):
|
||||
phys = interface.get_phys(self.cfg)
|
||||
self.assertEqual(len(phys), 6)
|
||||
self.assertEqual(len(phys), 10)
|
||||
self.assertIn("GigabitEthernet1/0/0", phys)
|
||||
self.assertNotIn("GigabitEthernet1/0/0.100", phys)
|
||||
|
||||
@ -284,3 +284,20 @@ class TestInterfaceMethods(unittest.TestCase):
|
||||
self.assertFalse(interface.is_mpls(self.cfg, "GigabitEthernet1/0/0"))
|
||||
self.assertFalse(interface.is_mpls(self.cfg, "GigabitEthernet1/0/0.100"))
|
||||
self.assertFalse(interface.is_mpls(self.cfg, "notexist"))
|
||||
|
||||
def test_get_unnumbered_interfaces(self):
|
||||
unnumbered_ifaces = interface.get_unnumbered_interfaces(self.cfg)
|
||||
self.assertEqual(len(unnumbered_ifaces), 5)
|
||||
self.assertNotIn("GigabitEthernet4/0/0", unnumbered_ifaces)
|
||||
self.assertIn("GigabitEthernet4/0/1", unnumbered_ifaces)
|
||||
self.assertNotIn("GigabitEthernet4/0/3.100", unnumbered_ifaces)
|
||||
self.assertIn("GigabitEthernet4/0/3.101", unnumbered_ifaces)
|
||||
|
||||
def test_is_unnumbered(self):
|
||||
self.assertFalse(interface.is_unnumbered(self.cfg, "GigabitEthernet4/0/0"))
|
||||
self.assertTrue(interface.is_unnumbered(self.cfg, "GigabitEthernet4/0/1"))
|
||||
self.assertTrue(interface.is_unnumbered(self.cfg, "GigabitEthernet4/0/2"))
|
||||
self.assertFalse(interface.is_unnumbered(self.cfg, "GigabitEthernet4/0/3.100"))
|
||||
self.assertTrue(interface.is_unnumbered(self.cfg, "GigabitEthernet4/0/3.101"))
|
||||
self.assertTrue(interface.is_unnumbered(self.cfg, "GigabitEthernet4/0/3.102"))
|
||||
self.assertTrue(interface.is_unnumbered(self.cfg, "GigabitEthernet4/0/3.103"))
|
||||
|
Reference in New Issue
Block a user