From 6453725ec66345e4facdbef57a1ab0ce121fdc7c Mon Sep 17 00:00:00 2001 From: VitthalMagadum Date: Mon, 19 Aug 2024 01:34:08 -0400 Subject: [PATCH] issue_786 Added TC for BGP NLRIs --- anta/tests/routing/bgp.py | 66 +++++++++++++ examples/tests.yaml | 6 ++ tests/units/anta_tests/routing/test_bgp.py | 103 +++++++++++++++++++++ 3 files changed, 175 insertions(+) diff --git a/anta/tests/routing/bgp.py b/anta/tests/routing/bgp.py index 6a7002356..79cfcdab7 100644 --- a/anta/tests/routing/bgp.py +++ b/anta/tests/routing/bgp.py @@ -1404,3 +1404,69 @@ def test(self) -> None: self.result.is_success() else: self.result.is_failure(f"The following BGP peers are not configured or have non-zero update error counters:\n{failures}") + + +class VerifyBGPPeerNLRIs(AntaTest): + """Verifies BGP IPv4 peer(s) consistency of NLRIs received and accepted in a BGP session. + + Expected Results + ---------------- + * Success: The test will pass if the `nlrisReceived` equals `nlrisAccepted`, indicating that all received NLRIs were accepted.. + * Failure: The test will fail if the `nlrisReceived` is not equal to `nlrisAccepted`, indicating that some NLRIs were rejected or filtered out. + + Examples + -------- + ```yaml + anta.tests.routing: + bgp: + - VerifyBGPPeerNLRIs: + bgp_peers: + - peer_address: 172.30.11.1 + vrf: default + ``` + """ + + name = "VerifyBGPPeerNLRIs" + description = "Verifies the NLRIs received and accepted of a BGP IPv4 peer." + categories: ClassVar[list[str]] = ["bgp"] + commands: ClassVar[list[AntaCommand | AntaTemplate]] = [AntaCommand(command="show bgp summary", revision=1)] + + class Input(AntaTest.Input): + """Input model for the VerifyBGPPeerNLRIs test.""" + + bgp_peers: list[BgpPeer] + """List of BGP peers""" + + class BgpPeer(BaseModel): + """Model for a BGP peer.""" + + peer_address: IPv4Address + """IPv4 address of a BGP peer.""" + vrf: str = "default" + """Optional VRF for BGP peer. If not provided, it defaults to `default`.""" + + @AntaTest.anta_test + def test(self) -> None: + """Main test function for VerifyBGPPeerNLRIs.""" + failures: dict[Any, Any] = {} + + # Iterate over each bgp peer + for bgp_peer in self.inputs.bgp_peers: + peer_address = str(bgp_peer.peer_address) + vrf = bgp_peer.vrf + + if not (peer_details := get_value(self.instance_commands[0].json_output, f"vrfs..{vrf}..peers..{peer_address}", separator="..")): + failures[peer_address] = {vrf: "Not configured"} + continue + + # Verifies the NLRIs received is equal to accepted. + if (nlri_rec := get_value(peer_details, "ipv4Unicast.nlrisReceived")) != (nlri_acc := get_value(peer_details, "ipv4Unicast.nlrisAccepted")): + failures[peer_address] = { + vrf: f"The NLRIs received and accepted should be consistent, but found NLRI received `{nlri_rec}` and NLRI accepted `{nlri_acc}` instead." + } + + # Check if any failures + if not failures: + self.result.is_success() + else: + self.result.is_failure(f"The following BGP peers are not configured or NLRI(s) received and accepted are not consistent:\n{failures}") diff --git a/examples/tests.yaml b/examples/tests.yaml index c5f87fae7..fcf6cd7cf 100644 --- a/examples/tests.yaml +++ b/examples/tests.yaml @@ -593,6 +593,12 @@ anta.tests.routing: update_errors: - inUpdErrWithdraw - inUpdErrIgnore + - VerifyBGPPeerNLRIs: + bgp_peers: + - peer_address: 10.100.0.10 + vrf: default + - peer_address: 10.100.0.8 + vrf: default ospf: - VerifyOSPFNeighborState: - VerifyOSPFNeighborCount: diff --git a/tests/units/anta_tests/routing/test_bgp.py b/tests/units/anta_tests/routing/test_bgp.py index 47db8e60b..e529264cb 100644 --- a/tests/units/anta_tests/routing/test_bgp.py +++ b/tests/units/anta_tests/routing/test_bgp.py @@ -18,6 +18,7 @@ VerifyBGPPeerDropStats, VerifyBGPPeerMD5Auth, VerifyBGPPeerMPCaps, + VerifyBGPPeerNLRIs, VerifyBGPPeerRouteRefreshCap, VerifyBGPPeersHealth, VerifyBGPPeerUpdateErrors, @@ -4357,4 +4358,106 @@ ], }, }, + { + "name": "success", + "test": VerifyBGPPeerNLRIs, + "eos_data": [ + { + "vrfs": { + "default": { + "peers": { + "10.100.0.8": { + "peerState": "Established", + "peerAsn": "65100", + "ipv4Unicast": {"afiSafiState": "negotiated", "nlrisReceived": 17, "nlrisAccepted": 17}, + }, + } + }, + "MGMT": { + "peers": { + "10.100.0.10": { + "peerState": "Established", + "peerAsn": "65100", + "ipv4Unicast": {"afiSafiState": "negotiated", "nlrisReceived": 17, "nlrisAccepted": 17}, + }, + } + }, + } + } + ], + "inputs": { + "bgp_peers": [ + {"peer_address": "10.100.0.8", "vrf": "default"}, + {"peer_address": "10.100.0.10", "vrf": "MGMT"}, + ] + }, + "expected": {"result": "success"}, + }, + { + "name": "failure", + "test": VerifyBGPPeerNLRIs, + "eos_data": [ + { + "vrfs": { + "default": { + "peers": { + "10.100.0.8": { + "peerState": "Established", + "peerAsn": "65100", + "ipv4Unicast": {"afiSafiState": "negotiated", "nlrisReceived": 20, "nlrisAccepted": 15}, + }, + } + }, + "MGMT": { + "peers": { + "10.100.0.10": { + "peerState": "Established", + "peerAsn": "65100", + "ipv4Unicast": {"afiSafiState": "negotiated", "nlrisReceived": 18, "nlrisAccepted": 17}, + }, + } + }, + } + } + ], + "inputs": { + "bgp_peers": [ + {"peer_address": "10.100.0.8", "vrf": "default"}, + {"peer_address": "10.100.0.10", "vrf": "MGMT"}, + ] + }, + "expected": { + "result": "failure", + "messages": [ + "The following BGP peers are not configured or NLRI(s) received and accepted are not consistent:\n" + "{'10.100.0.8': {'default': 'The NLRIs received and accepted should be consistent, but found NLRI received `20` and NLRI accepted `15` instead.'}, " + "'10.100.0.10': {'MGMT': 'The NLRIs received and accepted should be consistent, but found NLRI received `18` and NLRI accepted `17` instead.'}}" + ], + }, + }, + { + "name": "failure-not-found", + "test": VerifyBGPPeerNLRIs, + "eos_data": [ + { + "vrfs": { + "default": {"peers": {}}, + "MGMT": {"peers": {}}, + } + } + ], + "inputs": { + "bgp_peers": [ + {"peer_address": "10.100.0.8", "vrf": "default"}, + {"peer_address": "10.100.0.10", "vrf": "MGMT"}, + ] + }, + "expected": { + "result": "failure", + "messages": [ + "The following BGP peers are not configured or NLRI(s) received and accepted are not consistent:\n" + "{'10.100.0.8': {'default': 'Not configured'}, '10.100.0.10': {'MGMT': 'Not configured'}}" + ], + }, + }, ]