Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(anta.tests): Add new interfaces.VerifyL2MTU test #346

Merged
merged 1 commit into from
Aug 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions anta/tests/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,3 +409,74 @@ def test(self) -> None:

else:
self.result.is_success()


class VerifyL2MTU(AntaTest):

"""
Verifies the global layer 2 Maximum Transfer Unit (MTU) for all L2 interfaces.

Test that L2 interfaces are configured with the correct MTU. It supports Ethernet, Port Channel and VLAN interfaces.
You can define a global MTU to check and also an MTU per interface and also ignored some interfaces.

Default ignored interfaces: ["Management", "Loopback", "Tunnel", "Vxlan"]

Expected Results:
* success: The test will pass if all layer 2 interfaces have the proper MTU configured.
* failure: The test will fail if one or many layer 2 interfaces have the wrong MTU configured.
* skipped: The test will be skipped if the MTU value is not provided.
"""

name = "VerifyL2MTU"
description = "Verifies the global layer 2 Maximum Transfer Unit (MTU) for all layer 2 interfaces."
categories = ["interfaces"]
commands = [AntaCommand(command="show interfaces")]

NOT_SUPPORTED_INTERFACES: List[str] = ["Management", "Loopback", "Tunnel", "Vxlan"]

@AntaTest.anta_test
def test(self, mtu: int = 9214, ignored_interfaces: Optional[List[str]] = None, specific_mtu: Optional[List[Dict[str, int]]] = None) -> None:
"""
Verifies the global L2 Maximum Transfer Unit (MTU) for interfaces.

Test that L2 interfaces are configured with the correct MTU. It supports Ethernet, Port Channel and VLAN interfaces.
You can define a global MTU to check and also an MTU per interface and also ignored some interfaces.

Args:
mtu (int, optional): Default MTU we should have configured on all non-excluded interfaces. Defaults to 9214.
ignored_interfaces (List[str]): A list of L2 interfaces to ignore. It will replace the built-in exclusion.
specific_mtu (Optional[List[Dict[str, int]]]): A list of dictionary of L2 interfaces with their specific MTU configured.
"""
if not mtu:
self.result.is_skipped(f"{self.__class__.name} did not run because mtu was not supplied")
return

if ignored_interfaces is None:
ignored_interfaces = self.NOT_SUPPORTED_INTERFACES

# Parameter to save incorrect interface settings
wrong_l2mtu_intf: List[Dict[str, int]] = []

command_output = self.instance_commands[0].json_output

# Set list of interfaces with specific settings
specific_interfaces: List[str] = []
if specific_mtu is not None:
for d in specific_mtu:
specific_interfaces.extend(d)
# Set default value if there is no specific settings.
else:
specific_mtu = []

for interface, values in command_output["interfaces"].items():
if re.findall(r"[a-z]+", interface, re.IGNORECASE)[0] not in ignored_interfaces and values["forwardingModel"] == "bridged":
if interface in specific_interfaces:
wrong_l2mtu_intf.extend({interface: values["mtu"]} for custom_data in specific_mtu if values["mtu"] != custom_data[interface])
# Comparison with generic setting
elif values["mtu"] != mtu:
wrong_l2mtu_intf.append({interface: values["mtu"]})

if wrong_l2mtu_intf:
self.result.is_failure(f"Some L2 interfaces do not have correct MTU configured:\n{wrong_l2mtu_intf}")
else:
self.result.is_success()
9 changes: 8 additions & 1 deletion examples/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ anta.tests.connectivity:
dst: 10.0.0.1
- src: Loopback0
dst: 10.0.0.2

anta.tests.field_notices:
- VerifyFieldNotice44Resolution:
- VerifyFieldNotice72Resolution:
Expand Down Expand Up @@ -102,6 +102,13 @@ anta.tests.interfaces:
template_params:
- intf: Ethernet1
- intf: Ethernet2
- VerifyL2MTU:
mtu: 1500
ignored_interfaces:
- Management1
- Vxlan1
specific_mtu:
- Ethernet1/1: 1500

anta.tests.logging:
- VerifyLoggingPersistent:
Expand Down
219 changes: 219 additions & 0 deletions tests/units/anta_tests/interfaces/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,225 @@
},
]

INPUT_L2MTU: List[Dict[str, Any]] = [
{
"name": "success",
"eos_data": [
{
"interfaces": {
"Ethernet2": {
"name": "Ethernet2",
"forwardingModel": "routed",
"lineProtocolStatus": "up",
"interfaceStatus": "connected",
"hardware": "ethernet",
"mtu": 1500,
"l3MtuConfigured": True,
"l2Mru": 0,
},
"Ethernet10": {
"name": "Ethernet10",
"forwardingModel": "bridged",
"lineProtocolStatus": "up",
"interfaceStatus": "connected",
"hardware": "ethernet",
"mtu": 9214,
"l3MtuConfigured": False,
"l2Mru": 0,
},
"Management0": {
"name": "Management0",
"forwardingModel": "routed",
"lineProtocolStatus": "up",
"interfaceStatus": "connected",
"hardware": "ethernet",
"mtu": 1500,
"l3MtuConfigured": False,
"l2Mru": 0,
},
"Port-Channel2": {
"name": "Port-Channel2",
"forwardingModel": "bridged",
"lineProtocolStatus": "lowerLayerDown",
"interfaceStatus": "notconnect",
"hardware": "portChannel",
"mtu": 9214,
"l3MtuConfigured": False,
"l2Mru": 0,
},
"Loopback0": {
"name": "Loopback0",
"forwardingModel": "routed",
"lineProtocolStatus": "up",
"interfaceStatus": "connected",
"hardware": "loopback",
"mtu": 65535,
"l3MtuConfigured": False,
"l2Mru": 0,
},
"Vxlan1": {
"name": "Vxlan1",
"forwardingModel": "bridged",
"lineProtocolStatus": "down",
"interfaceStatus": "notconnect",
"hardware": "vxlan",
"mtu": 0,
"l3MtuConfigured": False,
"l2Mru": 0,
},
},
}
],
"side_effect": {"mtu": 9214},
"expected_result": "success",
"expected_messages": [],
},
{
"name": "failure",
"eos_data": [
{
"interfaces": {
"Ethernet2": {
"name": "Ethernet2",
"forwardingModel": "routed",
"lineProtocolStatus": "up",
"interfaceStatus": "connected",
"hardware": "ethernet",
"mtu": 1600,
"l3MtuConfigured": True,
"l2Mru": 0,
},
"Ethernet10": {
"name": "Ethernet10",
"forwardingModel": "bridged",
"lineProtocolStatus": "up",
"interfaceStatus": "connected",
"hardware": "ethernet",
"mtu": 9214,
"l3MtuConfigured": False,
"l2Mru": 0,
},
"Management0": {
"name": "Management0",
"forwardingModel": "routed",
"lineProtocolStatus": "up",
"interfaceStatus": "connected",
"hardware": "ethernet",
"mtu": 1500,
"l3MtuConfigured": False,
"l2Mru": 0,
},
"Port-Channel2": {
"name": "Port-Channel2",
"forwardingModel": "bridged",
"lineProtocolStatus": "lowerLayerDown",
"interfaceStatus": "notconnect",
"hardware": "portChannel",
"mtu": 9214,
"l3MtuConfigured": False,
"l2Mru": 0,
},
"Loopback0": {
"name": "Loopback0",
"forwardingModel": "routed",
"lineProtocolStatus": "up",
"interfaceStatus": "connected",
"hardware": "loopback",
"mtu": 65535,
"l3MtuConfigured": False,
"l2Mru": 0,
},
"Vxlan1": {
"name": "Vxlan1",
"forwardingModel": "bridged",
"lineProtocolStatus": "down",
"interfaceStatus": "notconnect",
"hardware": "vxlan",
"mtu": 0,
"l3MtuConfigured": False,
"l2Mru": 0,
},
},
}
],
"side_effect": {"mtu": 1500},
"expected_result": "failure",
"expected_messages": ["Some L2 interfaces do not have correct MTU configured:\n[{'Ethernet10': 9214}, {'Port-Channel2': 9214}]"],
},
{
"name": "skipped",
"eos_data": [
{
"interfaces": {
"Ethernet2": {
"name": "Ethernet2",
"forwardingModel": "routed",
"lineProtocolStatus": "up",
"interfaceStatus": "connected",
"hardware": "ethernet",
"mtu": 1600,
"l3MtuConfigured": True,
"l2Mru": 0,
},
"Ethernet10": {
"name": "Ethernet10",
"forwardingModel": "bridged",
"lineProtocolStatus": "up",
"interfaceStatus": "connected",
"hardware": "ethernet",
"mtu": 9214,
"l3MtuConfigured": False,
"l2Mru": 0,
},
"Management0": {
"name": "Management0",
"forwardingModel": "routed",
"lineProtocolStatus": "up",
"interfaceStatus": "connected",
"hardware": "ethernet",
"mtu": 1500,
"l3MtuConfigured": False,
"l2Mru": 0,
},
"Port-Channel2": {
"name": "Port-Channel2",
"forwardingModel": "bridged",
"lineProtocolStatus": "lowerLayerDown",
"interfaceStatus": "notconnect",
"hardware": "portChannel",
"mtu": 9214,
"l3MtuConfigured": False,
"l2Mru": 0,
},
"Loopback0": {
"name": "Loopback0",
"forwardingModel": "routed",
"lineProtocolStatus": "up",
"interfaceStatus": "connected",
"hardware": "loopback",
"mtu": 65535,
"l3MtuConfigured": False,
"l2Mru": 0,
},
"Vxlan1": {
"name": "Vxlan1",
"forwardingModel": "bridged",
"lineProtocolStatus": "down",
"interfaceStatus": "notconnect",
"hardware": "vxlan",
"mtu": 0,
"l3MtuConfigured": False,
"l2Mru": 0,
},
},
}
],
"side_effect": {"mtu": None},
"expected_result": "skipped",
"expected_messages": ['VerifyL2MTU did not run because mtu was not supplied'],
},
]

INPUT_IP_PROXY_ARP: List[Dict[str, Any]] = [
{
"name": "success",
Expand Down
19 changes: 19 additions & 0 deletions tests/units/anta_tests/interfaces/test_exc.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
VerifyInterfacesStatus,
VerifyInterfaceUtilization,
VerifyIPProxyARP,
VerifyL2MTU,
VerifyL3MTU,
VerifyLoopbackCount,
VerifyPortChannels,
Expand All @@ -36,6 +37,7 @@
INPUT_INTERFACE_UTILIZATION,
INPUT_INTERFACES_STATUS,
INPUT_IP_PROXY_ARP,
INPUT_L2MTU,
INPUT_L3MTU,
INPUT_LOOPBACK_COUNT,
INPUT_PORT_CHANNELS,
Expand Down Expand Up @@ -231,6 +233,23 @@ def test_VerifyL3MTU(mocked_device: MagicMock, test_data: Any) -> None:
assert test.result.messages == test_data["expected_messages"]


@pytest.mark.parametrize("test_data", INPUT_L2MTU, ids=generate_test_ids_list(INPUT_L2MTU))
def test_VerifyL2MTU(mocked_device: MagicMock, test_data: Any) -> None:
"""Check VerifyL3MTU"""

logging.info(f"Mocked device is: {mocked_device.host}")
logging.info(f"Mocked HW is: {mocked_device.hw_model}")

test = VerifyL2MTU(mocked_device, eos_data=test_data["eos_data"])
asyncio.run(test.test(mtu=test_data["side_effect"]["mtu"]))

logging.info(f"test result is: {test.result}")

assert str(test.result.name) == mocked_device.name
assert test.result.result == test_data["expected_result"]
assert test.result.messages == test_data["expected_messages"]


@pytest.mark.parametrize("test_data", INPUT_IP_PROXY_ARP, ids=generate_test_ids_list(INPUT_IP_PROXY_ARP))
def test_VerifyIPProxyARP(mocked_device: MagicMock, test_data: Any) -> None:
"""Check VerifyIPProxyARP"""
Expand Down