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): Added the test case to verify BGP NLRI prefixes #792

Merged
merged 19 commits into from
Jan 15, 2025
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
2 changes: 1 addition & 1 deletion anta/input_models/routing/bgp.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ class BgpPeer(BaseModel):
received_routes: list[IPv4Network] | None = None
"""List of received routes in CIDR format. Required field in the `VerifyBGPExchangedRoutes` test."""
capabilities: list[MultiProtocolCaps] | None = None
"""List of BGP multiprotocol capabilities. Required field in the `VerifyBGPPeerMPCaps` test."""
"""List of BGP multiprotocol capabilities. Required field in the `VerifyBGPPeerMPCaps`, `VerifyBGPNlriAcceptance` tests."""
strict: bool = False
"""If True, requires exact match of the provided BGP multiprotocol capabilities.

Expand Down
75 changes: 75 additions & 0 deletions anta/tests/routing/bgp.py
Original file line number Diff line number Diff line change
Expand Up @@ -1544,3 +1544,78 @@ def test(self) -> None:
outq = peer["peerTcpInfo"]["outputQueueLength"]
if self.inputs.check_tcp_queues and (inq != 0 or outq != 0):
self.result.is_failure(f"Peer: {peer['peerAddress']} VRF: {vrf} - Session has non-empty message queues - InQ: {inq}, OutQ: {outq}")


class VerifyBGPNlriAcceptance(AntaTest):
"""Verifies that all received NLRI are accepted for all AFI/SAFI configured for BGP IPv4 peer(s).

This test performs the following checks for each specified peer:

1. Verifies that the peer is found in its VRF in the BGP configuration.
2. Verifies that all received NLRI were accepted by comparing `nlrisReceived` with `nlrisAccepted`.

Expected Results
----------------
* Success: If `nlrisReceived` equals `nlrisAccepted`, indicating all NLRI were accepted.
* Failure: If any of the following occur:
- The specified VRF is not configured.
- `nlrisReceived` does not equal `nlrisAccepted`, indicating some NLRI were rejected or filtered.

Examples
--------
```yaml
anta.tests.routing:
bgp:
- VerifyBGPNlriAcceptance:
bgp_peers:
- peer_address: 10.100.0.128
vrf: default
capabilities:
- ipv4Unicast
```
"""

categories: ClassVar[list[str]] = ["bgp"]
commands: ClassVar[list[AntaCommand | AntaTemplate]] = [AntaCommand(command="show bgp summary vrf all", revision=1)]

class Input(AntaTest.Input):
"""Input model for the VerifyBGPNlriAcceptance test."""

bgp_peers: list[BgpPeer]
"""List of BGP IPv4 peers."""

@field_validator("bgp_peers")
@classmethod
def validate_bgp_peers(cls, bgp_peers: list[T]) -> list[T]:
"""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"
raise ValueError(msg)
return bgp_peers

@AntaTest.anta_test
def test(self) -> None:
"""Main test function for VerifyBGPNlriAcceptance."""
self.result.is_success()

output = self.instance_commands[0].json_output

for peer in self.inputs.bgp_peers:
# Check if the peer is found
if not (peer_data := get_value(output, f"vrfs..{peer.vrf}..peers..{peer.peer_address}", separator="..")):
self.result.is_failure(f"{peer} - Not found")
continue

# Fetching the multiprotocol capabilities
for capability in peer.capabilities:
# Check if the capability is found
if (capability_status := get_value(peer_data, capability)) is None:
self.result.is_failure(f"{peer} - {capability} not found")
continue

if capability_status["afiSafiState"] != "negotiated":
self.result.is_failure(f"{peer} - {capability} not negotiated")

if (received := capability_status.get("nlrisReceived")) != (accepted := capability_status.get("nlrisAccepted")):
self.result.is_failure(f"{peer} AFI/SAFI: {capability} - some NLRI were filtered or rejected - Accepted: {accepted} Received: {received}")
7 changes: 7 additions & 0 deletions examples/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,13 @@ anta.tests.routing.bgp:
- 192.0.254.5/32
received_routes:
- 192.0.254.3/32
- VerifyBGPNlriAcceptance:
# Verifies that all received NLRI are accepted for all AFI/SAFI configured for BGP IPv4 peer(s).
bgp_peers:
- peer_address: 10.100.0.128
vrf: default
capabilities:
- ipv4Unicast
- VerifyBGPPeerASNCap:
# Verifies the four octet ASN capability of BGP IPv4 peer(s).
bgp_peers:
Expand Down
266 changes: 266 additions & 0 deletions tests/units/anta_tests/routing/test_bgp.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from anta.tests.routing.bgp import (
VerifyBGPAdvCommunities,
VerifyBGPExchangedRoutes,
VerifyBGPNlriAcceptance,
VerifyBGPPeerASNCap,
VerifyBGPPeerCount,
VerifyBGPPeerDropStats,
Expand Down Expand Up @@ -4609,4 +4610,269 @@ def test_check_bgp_neighbor_capability(input_dict: dict[str, bool], expected: bo
],
},
},
{
"name": "success",
"test": VerifyBGPNlriAcceptance,
"eos_data": [
{
"vrfs": {
"default": {
"vrf": "default",
"routerId": "10.100.1.5",
"asn": "65102",
"peers": {
"10.100.0.8": {
"peerState": "Established",
"peerAsn": "65100",
"ipv4Unicast": {"afiSafiState": "negotiated", "nlrisReceived": 17, "nlrisAccepted": 17},
"l2VpnEvpn": {"afiSafiState": "negotiated", "nlrisReceived": 56, "nlrisAccepted": 56},
},
},
},
"MGMT": {
"vrf": "MGMT",
"routerId": "10.100.1.5",
"asn": "65102",
"peers": {
"10.100.4.5": {
"peerState": "Established",
"peerAsn": "65102",
"ipv4Unicast": {"afiSafiState": "negotiated", "nlrisReceived": 14, "nlrisAccepted": 14},
"l2VpnEvpn": {"afiSafiState": "negotiated", "nlrisReceived": 56, "nlrisAccepted": 56},
}
},
},
}
}
],
"inputs": {
"bgp_peers": [
{
"peer_address": "10.100.0.8",
"vrf": "default",
"capabilities": ["Ipv4 Unicast", "L2vpnEVPN"],
},
{
"peer_address": "10.100.4.5",
"vrf": "MGMT",
"capabilities": ["ipv4 Unicast", "L2vpnEVPN"],
},
]
},
"expected": {"result": "success"},
},
{
"name": "failure-vrf-not-configured",
"test": VerifyBGPNlriAcceptance,
"eos_data": [
{
"vrfs": {
"default": {
"vrf": "default",
"routerId": "10.100.1.5",
"asn": "65102",
"peers": {},
},
"MGMT": {
"vrf": "MGMT",
"routerId": "10.100.1.5",
"asn": "65102",
"peers": {},
},
}
}
],
"inputs": {
"bgp_peers": [
{
"peer_address": "10.100.0.8",
"vrf": "default",
"capabilities": ["Ipv4 Unicast", "L2vpnEVPN"],
},
{
"peer_address": "10.100.4.5",
"vrf": "MGMT",
"capabilities": ["ipv4 Unicast", "L2vpnEVPN"],
},
]
},
"expected": {
"result": "failure",
"messages": [
"Peer: 10.100.0.8 VRF: default - Not found",
"Peer: 10.100.4.5 VRF: MGMT - Not found",
],
},
},
{
"name": "failure-capability-not-found",
"test": VerifyBGPNlriAcceptance,
"eos_data": [
{
"vrfs": {
"default": {
"vrf": "default",
"routerId": "10.100.1.5",
"asn": "65102",
"peers": {
"10.100.0.8": {
"peerState": "Established",
"peerAsn": "65100",
"ipv4Unicast": {"afiSafiState": "negotiated", "nlrisReceived": 17, "nlrisAccepted": 17},
},
},
},
"MGMT": {
"vrf": "MGMT",
"routerId": "10.100.1.5",
"asn": "65102",
"peers": {
"10.100.4.5": {
"peerState": "Established",
"peerAsn": "65102",
"l2VpnEvpn": {"afiSafiState": "negotiated", "nlrisReceived": 56, "nlrisAccepted": 56},
}
},
},
}
}
],
"inputs": {
"bgp_peers": [
{
"peer_address": "10.100.0.8",
"vrf": "default",
"capabilities": ["Ipv4 Unicast", "L2vpnEVPN"],
},
{
"peer_address": "10.100.4.5",
"vrf": "MGMT",
"capabilities": ["ipv4 Unicast", "L2vpnEVPN"],
},
]
},
"expected": {
"result": "failure",
"messages": [
"Peer: 10.100.0.8 VRF: default - l2VpnEvpn not found",
"Peer: 10.100.4.5 VRF: MGMT - ipv4Unicast not found",
],
},
},
{
"name": "failure-capability-not-negotiated",
"test": VerifyBGPNlriAcceptance,
"eos_data": [
{
"vrfs": {
"default": {
"vrf": "default",
"routerId": "10.100.1.5",
"asn": "65102",
"peers": {
"10.100.0.8": {
"peerState": "Established",
"peerAsn": "65100",
"ipv4Unicast": {"afiSafiState": "configured", "nlrisReceived": 17, "nlrisAccepted": 17},
},
},
},
"MGMT": {
"vrf": "MGMT",
"routerId": "10.100.1.5",
"asn": "65102",
"peers": {
"10.100.4.5": {
"peerState": "Established",
"peerAsn": "65102",
"l2VpnEvpn": {"afiSafiState": "configured", "nlrisReceived": 56, "nlrisAccepted": 56},
}
},
},
}
}
],
"inputs": {
"bgp_peers": [
{
"peer_address": "10.100.0.8",
"vrf": "default",
"capabilities": ["Ipv4 Unicast", "L2vpnEVPN"],
},
{
"peer_address": "10.100.4.5",
"vrf": "MGMT",
"capabilities": ["ipv4 Unicast", "L2vpnEVPN"],
},
]
},
"expected": {
"result": "failure",
"messages": [
"Peer: 10.100.0.8 VRF: default - ipv4Unicast not negotiated",
"Peer: 10.100.0.8 VRF: default - l2VpnEvpn not found",
"Peer: 10.100.4.5 VRF: MGMT - ipv4Unicast not found",
"Peer: 10.100.4.5 VRF: MGMT - l2VpnEvpn not negotiated",
],
},
},
{
"name": "failure-nlris-not-accepted",
"test": VerifyBGPNlriAcceptance,
"eos_data": [
{
"vrfs": {
"default": {
"vrf": "default",
"routerId": "10.100.1.5",
"asn": "65102",
"peers": {
"10.100.0.8": {
"peerState": "Established",
"peerAsn": "65100",
"ipv4Unicast": {"afiSafiState": "negotiated", "nlrisReceived": 17, "nlrisAccepted": 16},
"l2VpnEvpn": {"afiSafiState": "negotiated", "nlrisReceived": 58, "nlrisAccepted": 56},
},
},
},
"MGMT": {
"vrf": "MGMT",
"routerId": "10.100.1.5",
"asn": "65102",
"peers": {
"10.100.4.5": {
"peerState": "Established",
"peerAsn": "65102",
"ipv4Unicast": {"afiSafiState": "negotiated", "nlrisReceived": 15, "nlrisAccepted": 14},
"l2VpnEvpn": {"afiSafiState": "negotiated", "nlrisReceived": 59, "nlrisAccepted": 56},
}
},
},
}
}
],
"inputs": {
"bgp_peers": [
{
"peer_address": "10.100.0.8",
"vrf": "default",
"capabilities": ["Ipv4 Unicast", "L2vpnEVPN"],
},
{
"peer_address": "10.100.4.5",
"vrf": "MGMT",
"capabilities": ["ipv4 Unicast", "L2vpnEVPN"],
},
]
},
"expected": {
"result": "failure",
"messages": [
"Peer: 10.100.0.8 VRF: default AFI/SAFI: ipv4Unicast - some NLRI were filtered or rejected - Accepted: 16 Received: 17",
"Peer: 10.100.0.8 VRF: default AFI/SAFI: l2VpnEvpn - some NLRI were filtered or rejected - Accepted: 56 Received: 58",
"Peer: 10.100.4.5 VRF: MGMT AFI/SAFI: ipv4Unicast - some NLRI were filtered or rejected - Accepted: 14 Received: 15",
"Peer: 10.100.4.5 VRF: MGMT AFI/SAFI: l2VpnEvpn - some NLRI were filtered or rejected - Accepted: 56 Received: 59",
],
},
},
]
Loading
Loading