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

fix(anta.tests): Minor fixes on BGP tests #987

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
6 changes: 4 additions & 2 deletions anta/input_models/routing/bgp.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,11 @@ class BgpPeer(BaseModel):
outbound_route_map: str | None = None
"""Outbound route map applied, defaults to None. Required field in the `VerifyBgpRouteMaps` test."""
maximum_routes: int | None = Field(default=None, ge=0, le=4294967294)
"""The maximum allowable number of BGP routes, `0` means unlimited. Required field in the `VerifyBGPPeerRouteLimit` test"""
"""The maximum allowable number of BGP routes. `0` means unlimited. Required field in the `VerifyBGPPeerRouteLimit` test"""
warning_limit: int | None = Field(default=None, ge=0, le=4294967294)
"""Optional maximum routes warning limit. If not provided, it defaults to `0` meaning no warning limit."""
"""The warning limit for the maximum routes. `0` means no warning.

Optional field in the `VerifyBGPPeerRouteLimit` test. If not provided, the test will not verify the warning limit."""

def __str__(self) -> str:
"""Return a human-readable string representation of the BgpPeer for reporting."""
Expand Down
47 changes: 22 additions & 25 deletions anta/tests/routing/bgp.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ def test(self) -> None:


class VerifyBGPExchangedRoutes(AntaTest):
"""Verifies the advertised and received routes of BGP peers.
"""Verifies the advertised and received routes of BGP IPv4 peer(s).

This test performs the following checks for each specified peer:

Expand Down Expand Up @@ -387,7 +387,7 @@ class Input(AntaTest.Input):
@field_validator("bgp_peers")
@classmethod
def validate_bgp_peers(cls, bgp_peers: list[BgpPeer]) -> list[BgpPeer]:
"""Validate that 'advertised_routes' or 'received_routes' field is provided in each address family."""
"""Validate that 'advertised_routes' or 'received_routes' field is provided in each BGP peer."""
for peer in bgp_peers:
if peer.advertised_routes is None or peer.received_routes is None:
msg = f"{peer} 'advertised_routes' or 'received_routes' field missing in the input"
Expand Down Expand Up @@ -435,7 +435,7 @@ def test(self) -> None:


class VerifyBGPPeerMPCaps(AntaTest):
"""Verifies the multiprotocol capabilities of BGP peers.
"""Verifies the multiprotocol capabilities of BGP IPv4 peer(s).

This test performs the following checks for each specified peer:

Expand Down Expand Up @@ -490,7 +490,7 @@ class Input(AntaTest.Input):
@field_validator("bgp_peers")
@classmethod
def validate_bgp_peers(cls, bgp_peers: list[T]) -> list[T]:
"""Validate that 'capabilities' field is provided in each address family."""
"""Validate that 'capabilities' field is provided in each BGP peer."""
for peer in bgp_peers:
if peer.capabilities is None:
msg = f"{peer} 'capabilities' field missing in the input"
Expand Down Expand Up @@ -537,7 +537,7 @@ def test(self) -> None:


class VerifyBGPPeerASNCap(AntaTest):
"""Verifies the four octet ASN capability of BGP peers.
"""Verifies the four octet ASN capability of BGP IPv4 peer(s).

This test performs the following checks for each specified peer:

Expand Down Expand Up @@ -606,7 +606,7 @@ def test(self) -> None:


class VerifyBGPPeerRouteRefreshCap(AntaTest):
"""Verifies the route refresh capabilities of a BGP peer in a specified VRF.
"""Verifies the route refresh capabilities of IPv4 BGP peer(s) in a specified VRF.

This test performs the following checks for each specified peer:

Expand Down Expand Up @@ -675,7 +675,7 @@ def test(self) -> None:


class VerifyBGPPeerMD5Auth(AntaTest):
"""Verifies the MD5 authentication and state of IPv4 BGP peers in a specified VRF.
"""Verifies the MD5 authentication and state of IPv4 BGP peer(s) in a specified VRF.

This test performs the following checks for each specified peer:

Expand Down Expand Up @@ -814,7 +814,7 @@ def test(self) -> None:


class VerifyBGPAdvCommunities(AntaTest):
"""Verifies that advertised communities are standard, extended and large for BGP peers.
"""Verifies that advertised communities are standard, extended and large for BGP IPv4 peer(s).

This test performs the following checks for each specified peer:

Expand Down Expand Up @@ -880,7 +880,7 @@ def test(self) -> None:


class VerifyBGPTimers(AntaTest):
"""Verifies the timers of BGP peers.
"""Verifies the timers of BGP IPv4 peer(s).

This test performs the following checks for each specified peer:

Expand Down Expand Up @@ -928,7 +928,7 @@ class Input(AntaTest.Input):
@field_validator("bgp_peers")
@classmethod
def validate_bgp_peers(cls, bgp_peers: list[T]) -> list[T]:
"""Validate that 'hold_time' or 'keep_alive_time' field is provided in each address family."""
"""Validate that 'hold_time' or 'keep_alive_time' field is provided in each BGP peer."""
for peer in bgp_peers:
if peer.hold_time is None or peer.keep_alive_time is None:
msg = f"{peer} 'hold_time' or 'keep_alive_time' field missing in the input"
Expand Down Expand Up @@ -1158,10 +1158,7 @@ class Input(AntaTest.Input):
@field_validator("bgp_peers")
@classmethod
def validate_bgp_peers(cls, bgp_peers: list[T]) -> list[T]:
"""Validate that 'peers' field is provided in each address family.

At least one of 'inbound' or 'outbound' route-map must be provided.
"""
"""Validate that 'inbound_route_map' or 'outbound_route_map' field is provided in each BGP peer."""
for peer in bgp_peers:
if not (peer.inbound_route_map or peer.outbound_route_map):
msg = f"{peer}; At least one of 'inbound_route_map' or 'outbound_route_map' must be provided."
Expand Down Expand Up @@ -1196,22 +1193,22 @@ def test(self) -> None:


class VerifyBGPPeerRouteLimit(AntaTest):
"""Verifies maximum routes and outbound route-maps of BGP IPv4 peer(s).
"""Verifies maximum routes and warning limit for BGP IPv4 peer(s).

This test performs the following checks for each specified peer:

1. Confirms that the specified VRF is configured.
2. Verifies that the peer exists in the BGP configuration.
3. Confirms the Maximum routes and maximum routes warning limit, if provided match the expected value.
3. Confirms the maximum routes and maximum routes warning limit, if provided, match the expected value.

Expected Results
----------------
* Success: If all of the following conditions are met:
- All specified peers are found in the BGP configuration.
- The maximum routese/maximum routes warning limit match the expected value for a peer.
- The maximum routes/maximum routes warning limit match the expected value for a peer.
* Failure: If any of the following occur:
- A specified peer is not found in the BGP configuration.
- The maximum routese/maximum routes warning limit do not match the expected value for a peer.
- The maximum routes/maximum routes warning limit do not match the expected value for a peer.

Examples
--------
Expand Down Expand Up @@ -1240,7 +1237,7 @@ class Input(AntaTest.Input):
@field_validator("bgp_peers")
@classmethod
def validate_bgp_peers(cls, bgp_peers: list[T]) -> list[T]:
"""Validate that 'peers' field is provided in each address family."""
"""Validate that 'maximum_routes' field is provided in each BGP peer."""
for peer in bgp_peers:
if peer.maximum_routes is None:
msg = f"{peer}; 'maximum_routes' field missing in the input"
Expand All @@ -1265,10 +1262,10 @@ def test(self) -> None:
self.result.is_failure(f"{peer} - Not found")
continue

# Verify maximum routes configured.
if (actual_routes := peer_data.get("maxTotalRoutes", "Not Found")) != maximum_routes:
self.result.is_failure(f"{peer} - Maximum routes mismatch - Expected: {maximum_routes}, Actual: {actual_routes}")
# Verify maximum routes
if (actual_maximum_routes := peer_data.get("maxTotalRoutes", "Not Found")) != maximum_routes:
self.result.is_failure(f"{peer} - Maximum routes mismatch - Expected: {maximum_routes}, Actual: {actual_maximum_routes}")

# Verify warning limit if given.
if warning_limit and (actual_warning_limit := peer_data.get("totalRoutesWarnLimit", "Not Found")) != warning_limit:
self.result.is_failure(f"{peer} - Maximum route warning limit mismatch - Expected: {warning_limit}, Actual: {actual_warning_limit}")
# Verify warning limit if provided. By default, EOS does not have a warning limit and `totalRoutesWarnLimit` is not present in the output.
if warning_limit is not None and (actual_warning_limit := peer_data.get("totalRoutesWarnLimit", 0)) != warning_limit:
self.result.is_failure(f"{peer} - Maximum routes warning limit mismatch - Expected: {warning_limit}, Actual: {actual_warning_limit}")
16 changes: 8 additions & 8 deletions examples/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -366,14 +366,14 @@ anta.tests.ptp:
# Verifies the PTP interfaces state.
anta.tests.routing.bgp:
- VerifyBGPAdvCommunities:
# Verifies that advertised communities are standard, extended and large for BGP peers.
# Verifies that advertised communities are standard, extended and large for BGP IPv4 peer(s).
bgp_peers:
- peer_address: 172.30.11.17
vrf: default
- peer_address: 172.30.11.21
vrf: default
- VerifyBGPExchangedRoutes:
# Verifies the advertised and received routes of BGP peers.
# Verifies the advertised and received routes of BGP IPv4 peer(s).
bgp_peers:
- peer_address: 172.30.255.5
vrf: default
Expand All @@ -389,7 +389,7 @@ anta.tests.routing.bgp:
received_routes:
- 192.0.254.3/32
- VerifyBGPPeerASNCap:
# Verifies the four octet ASN capability of BGP peers.
# Verifies the four octet ASN capability of BGP IPv4 peer(s).
bgp_peers:
- peer_address: 172.30.11.1
vrf: default
Expand Down Expand Up @@ -419,29 +419,29 @@ anta.tests.routing.bgp:
- inDropAsloop
- prefixEvpnDroppedUnsupportedRouteType
- VerifyBGPPeerMD5Auth:
# Verifies the MD5 authentication and state of IPv4 BGP peers in a specified VRF.
# Verifies the MD5 authentication and state of IPv4 BGP peer(s) in a specified VRF.
bgp_peers:
- peer_address: 172.30.11.1
vrf: default
- peer_address: 172.30.11.5
vrf: default
- VerifyBGPPeerMPCaps:
# Verifies the multiprotocol capabilities of BGP peers.
# Verifies the multiprotocol capabilities of BGP IPv4 peer(s).
bgp_peers:
- peer_address: 172.30.11.1
vrf: default
strict: False
capabilities:
- ipv4Unicast
- VerifyBGPPeerRouteLimit:
# Verifies maximum routes and outbound route-maps of BGP IPv4 peer(s).
# Verifies maximum routes and warning limit for BGP IPv4 peer(s).
bgp_peers:
- peer_address: 172.30.11.1
vrf: default
maximum_routes: 12000
warning_limit: 10000
- VerifyBGPPeerRouteRefreshCap:
# Verifies the route refresh capabilities of a BGP peer in a specified VRF.
# Verifies the route refresh capabilities of IPv4 BGP peer(s) in a specified VRF.
bgp_peers:
- peer_address: 172.30.11.1
vrf: default
Expand Down Expand Up @@ -478,7 +478,7 @@ anta.tests.routing.bgp:
- 10.1.255.2
- 10.1.255.4
- VerifyBGPTimers:
# Verifies the timers of BGP peers.
# Verifies the timers of BGP IPv4 peer(s).
bgp_peers:
- peer_address: 172.30.11.1
vrf: default
Expand Down
43 changes: 38 additions & 5 deletions tests/units/anta_tests/routing/test_bgp.py
Original file line number Diff line number Diff line change
Expand Up @@ -3740,6 +3740,39 @@ def test_check_bgp_neighbor_capability(input_dict: dict[str, bool], expected: bo
},
"expected": {"result": "success"},
},
{
"name": "success-no-warning-limit",
"test": VerifyBGPPeerRouteLimit,
"eos_data": [
{
"vrfs": {
"default": {
"peerList": [
{
"peerAddress": "10.100.0.8",
"maxTotalRoutes": 12000,
}
]
},
"MGMT": {
"peerList": [
{
"peerAddress": "10.100.0.9",
"maxTotalRoutes": 10000,
}
]
},
},
},
],
"inputs": {
"bgp_peers": [
{"peer_address": "10.100.0.8", "vrf": "default", "maximum_routes": 12000, "warning_limit": 0},
{"peer_address": "10.100.0.9", "vrf": "MGMT", "maximum_routes": 10000},
]
},
"expected": {"result": "success"},
},
{
"name": "failure-peer-not-found",
"test": VerifyBGPPeerRouteLimit,
Expand Down Expand Up @@ -3802,9 +3835,9 @@ def test_check_bgp_neighbor_capability(input_dict: dict[str, bool], expected: bo
"result": "failure",
"messages": [
"Peer: 10.100.0.8 VRF: default - Maximum routes mismatch - Expected: 12000, Actual: 13000",
"Peer: 10.100.0.8 VRF: default - Maximum route warning limit mismatch - Expected: 10000, Actual: 11000",
"Peer: 10.100.0.8 VRF: default - Maximum routes warning limit mismatch - Expected: 10000, Actual: 11000",
"Peer: 10.100.0.9 VRF: MGMT - Maximum routes mismatch - Expected: 10000, Actual: 11000",
"Peer: 10.100.0.9 VRF: MGMT - Maximum route warning limit mismatch - Expected: 9000, Actual: 10000",
"Peer: 10.100.0.9 VRF: MGMT - Maximum routes warning limit mismatch - Expected: 9000, Actual: 10000",
],
},
},
Expand All @@ -3826,6 +3859,7 @@ def test_check_bgp_neighbor_capability(input_dict: dict[str, bool], expected: bo
"peerList": [
{
"peerAddress": "10.100.0.9",
"maxTotalRoutes": 10000,
}
]
},
Expand All @@ -3841,9 +3875,8 @@ def test_check_bgp_neighbor_capability(input_dict: dict[str, bool], expected: bo
"expected": {
"result": "failure",
"messages": [
"Peer: 10.100.0.8 VRF: default - Maximum route warning limit mismatch - Expected: 10000, Actual: Not Found",
"Peer: 10.100.0.9 VRF: MGMT - Maximum routes mismatch - Expected: 10000, Actual: Not Found",
"Peer: 10.100.0.9 VRF: MGMT - Maximum route warning limit mismatch - Expected: 9000, Actual: Not Found",
"Peer: 10.100.0.8 VRF: default - Maximum routes warning limit mismatch - Expected: 10000, Actual: 0",
"Peer: 10.100.0.9 VRF: MGMT - Maximum routes warning limit mismatch - Expected: 9000, Actual: 0",
],
},
},
Expand Down
Loading