Also allow loopback interfaces to be unnumbered
This commit is contained in:
@ -16,6 +16,7 @@ import logging
|
|||||||
from . import lcp
|
from . import lcp
|
||||||
from . import address
|
from . import address
|
||||||
from . import mac
|
from . import mac
|
||||||
|
from . import interface
|
||||||
|
|
||||||
|
|
||||||
def get_loopbacks(yaml):
|
def get_loopbacks(yaml):
|
||||||
@ -53,6 +54,32 @@ def is_loopback(yaml, ifname):
|
|||||||
return iface is not None
|
return iface is not None
|
||||||
|
|
||||||
|
|
||||||
|
def get_unnumbered_loopbacks(yaml):
|
||||||
|
"""Returns a list of all loopbacks that are unnumbered"""
|
||||||
|
ret = []
|
||||||
|
if not "loopbacks" in yaml:
|
||||||
|
return ret
|
||||||
|
for ifname, iface in yaml["loopbacks"].items():
|
||||||
|
if "unnumbered" in iface:
|
||||||
|
ret.append(ifname)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
def is_unnumbered(yaml, ifname):
|
||||||
|
"""Returns True if the loopback exists and is unnumbered"""
|
||||||
|
return ifname in get_unnumbered_loopbacks(yaml)
|
||||||
|
|
||||||
|
|
||||||
|
def has_address(yaml, ifname):
|
||||||
|
"""Returns True if this loopback has one or more addresses"""
|
||||||
|
|
||||||
|
ifname, iface = get_by_name(yaml, ifname)
|
||||||
|
if not iface:
|
||||||
|
return False
|
||||||
|
return "addresses" in iface
|
||||||
|
|
||||||
|
|
||||||
def validate_loopbacks(yaml):
|
def validate_loopbacks(yaml):
|
||||||
"""Validate the semantics of all YAML 'loopbacks' entries"""
|
"""Validate the semantics of all YAML 'loopbacks' entries"""
|
||||||
result = True
|
result = True
|
||||||
@ -76,6 +103,31 @@ def validate_loopbacks(yaml):
|
|||||||
f"loopback {ifname} does not have a unique LCP name {iface['lcp']}"
|
f"loopback {ifname} does not have a unique LCP name {iface['lcp']}"
|
||||||
)
|
)
|
||||||
result = False
|
result = False
|
||||||
|
if "unnumbered" in iface:
|
||||||
|
target = iface["unnumbered"]
|
||||||
|
_, target_iface = get_by_name(yaml, target)
|
||||||
|
if not target_iface:
|
||||||
|
_, target_iface = interface.get_by_name(yaml, target)
|
||||||
|
if not target_iface:
|
||||||
|
msgs.append(
|
||||||
|
f"loopback {ifname} unnumbered target {target} does not exist"
|
||||||
|
)
|
||||||
|
result = False
|
||||||
|
if is_unnumbered(yaml, target):
|
||||||
|
msgs.append(
|
||||||
|
f"loopback {ifname} unnumbered target {target} cannot also be unnumbered"
|
||||||
|
)
|
||||||
|
result = False
|
||||||
|
if ifname == target:
|
||||||
|
msgs.append(
|
||||||
|
f"loopback {ifname} unnumbered target cannot point to itself"
|
||||||
|
)
|
||||||
|
result = False
|
||||||
|
if has_address(yaml, ifname):
|
||||||
|
msgs.append(
|
||||||
|
f"loopback {ifname} cannot also have addresses when it is unnumbered"
|
||||||
|
)
|
||||||
|
result = False
|
||||||
if "addresses" in iface:
|
if "addresses" in iface:
|
||||||
for addr in iface["addresses"]:
|
for addr in iface["addresses"]:
|
||||||
if not address.is_allowed(yaml, ifname, iface["addresses"], addr):
|
if not address.is_allowed(yaml, ifname, iface["addresses"], addr):
|
||||||
|
@ -35,6 +35,7 @@ loopback:
|
|||||||
lcp: str(max=15,matches='[a-z]+[a-z0-9-]*',required=False)
|
lcp: str(max=15,matches='[a-z]+[a-z0-9-]*',required=False)
|
||||||
mtu: int(min=128,max=9216,required=False)
|
mtu: int(min=128,max=9216,required=False)
|
||||||
addresses: list(ip_interface(),min=1,max=6,required=False)
|
addresses: list(ip_interface(),min=1,max=6,required=False)
|
||||||
|
unnumbered: str(required=False)
|
||||||
mpls: bool(required=False)
|
mpls: bool(required=False)
|
||||||
---
|
---
|
||||||
bondethernet:
|
bondethernet:
|
||||||
|
@ -7,6 +7,18 @@ loopbacks:
|
|||||||
loop0:
|
loop0:
|
||||||
mtu: 9216
|
mtu: 9216
|
||||||
addresses: [ 192.0.2.1/32, 2001:db8:1::1/128 ]
|
addresses: [ 192.0.2.1/32, 2001:db8:1::1/128 ]
|
||||||
|
loop1:
|
||||||
|
mtu: 1500
|
||||||
|
addresses: [ 192.0.2.17/32, 2001:db8:10::1/128 ]
|
||||||
|
loop2:
|
||||||
|
mtu: 1500
|
||||||
|
unnumbered: loop1
|
||||||
|
loop3:
|
||||||
|
mtu: 1500
|
||||||
|
unnumbered: GigabitEthernet1/0/0
|
||||||
|
loop4:
|
||||||
|
mtu: 1500
|
||||||
|
unnumbered: GigabitEthernet3/0/0.100
|
||||||
|
|
||||||
interfaces:
|
interfaces:
|
||||||
GigabitEthernet1/0/0:
|
GigabitEthernet1/0/0:
|
||||||
|
@ -2,21 +2,27 @@ test:
|
|||||||
description: "Nonexistent unnumbered target"
|
description: "Nonexistent unnumbered target"
|
||||||
errors:
|
errors:
|
||||||
expected:
|
expected:
|
||||||
- "^sub-interface .* unnumbered target .* does not exist"
|
- "(sub-)?interface .* unnumbered target .* does not exist"
|
||||||
- "^interface .* unnumbered target .* does not exist"
|
- "loopback .* unnumbered target .* does not exist"
|
||||||
count: 4
|
count: 6
|
||||||
---
|
---
|
||||||
loopbacks:
|
loopbacks:
|
||||||
loop0:
|
loop0:
|
||||||
mtu: 9216
|
mtu: 9216
|
||||||
addresses: [ 192.0.2.1/32, 2001:db8:1::1/128 ]
|
addresses: [ 192.0.2.1/32, 2001:db8:1::1/128 ]
|
||||||
|
loop1:
|
||||||
|
mtu: 9216
|
||||||
|
unnumbered: loop2
|
||||||
|
loop3:
|
||||||
|
mtu: 9216
|
||||||
|
unnumbered: GigabitEthernet0/0/0
|
||||||
|
|
||||||
interfaces:
|
interfaces:
|
||||||
GigabitEthernet1/0/0:
|
GigabitEthernet1/0/0:
|
||||||
sub-interfaces:
|
sub-interfaces:
|
||||||
101:
|
101:
|
||||||
description: "Error: non existent loopback device"
|
description: "Error: non existent loopback device"
|
||||||
unnumbered: loop1
|
unnumbered: loop2
|
||||||
|
|
||||||
GigabitEthernet2/0/0:
|
GigabitEthernet2/0/0:
|
||||||
addresses: [ 192.0.2.5/30, 2001:db8:2::1/64 ]
|
addresses: [ 192.0.2.5/30, 2001:db8:2::1/64 ]
|
||||||
|
@ -4,8 +4,18 @@ test:
|
|||||||
expected:
|
expected:
|
||||||
- "(sub-)?interface .* unnumbered target cannot point to itself"
|
- "(sub-)?interface .* unnumbered target cannot point to itself"
|
||||||
- "(sub-)?interface .* unnumbered target .* cannot also be unnumbered"
|
- "(sub-)?interface .* unnumbered target .* cannot also be unnumbered"
|
||||||
count: 8
|
- "loopback .* unnumbered target cannot point to itself"
|
||||||
|
- "loopback .* unnumbered target .* cannot also be unnumbered"
|
||||||
|
count: 12
|
||||||
---
|
---
|
||||||
|
loopbacks:
|
||||||
|
loop0:
|
||||||
|
unnumbered: loop1
|
||||||
|
loop1:
|
||||||
|
unnumbered: loop0
|
||||||
|
loop2:
|
||||||
|
unnumbered: loop2
|
||||||
|
|
||||||
interfaces:
|
interfaces:
|
||||||
GigabitEthernet1/0/0:
|
GigabitEthernet1/0/0:
|
||||||
description: "Cannot point to the same interface"
|
description: "Cannot point to the same interface"
|
||||||
|
@ -3,12 +3,17 @@ test:
|
|||||||
errors:
|
errors:
|
||||||
expected:
|
expected:
|
||||||
- "(sub-)?interface .* cannot also have addresses when it is unnumbered"
|
- "(sub-)?interface .* cannot also have addresses when it is unnumbered"
|
||||||
count: 3
|
- "loopback .* cannot also have addresses when it is unnumbered"
|
||||||
|
count: 4
|
||||||
---
|
---
|
||||||
loopbacks:
|
loopbacks:
|
||||||
loop0:
|
loop0:
|
||||||
mtu: 9216
|
mtu: 9216
|
||||||
addresses: [ 192.0.2.1/32, 2001:db8:1::1/128 ]
|
addresses: [ 192.0.2.1/32, 2001:db8:1::1/128 ]
|
||||||
|
loop1:
|
||||||
|
mtu: 9216
|
||||||
|
unnumbered: loop0
|
||||||
|
addresses: [ 192.0.2.13/32, 2001:db8:4::1/128 ]
|
||||||
|
|
||||||
interfaces:
|
interfaces:
|
||||||
GigabitEthernet1/0/0:
|
GigabitEthernet1/0/0:
|
||||||
|
Reference in New Issue
Block a user