Skip to content

ANTA catalog for Router path-selection tests

Tests

Test functions related to various router path-selection settings.

VerifyPathsHealth

Verifies the path and telemetry state of all paths under router path-selection.

The expected states are ‘IPsec established’, ‘Resolved’ for path and ‘active’ for telemetry.

Expected Results
  • Success: The test will pass if all path states under router path-selection are either ‘IPsec established’ or ‘Resolved’ and their telemetry state as ‘active’.
  • Failure: The test will fail if router path-selection is not configured or if any path state is not ‘IPsec established’ or ‘Resolved’, or the telemetry state is ‘inactive’.
Examples
anta.tests.path_selection:
  - VerifyPathsHealth:
Source code in anta/tests/path_selection.py
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
class VerifyPathsHealth(AntaTest):
    """Verifies the path and telemetry state of all paths under router path-selection.

    The expected states are 'IPsec established', 'Resolved' for path and 'active' for telemetry.

    Expected Results
    ----------------
    * Success: The test will pass if all path states under router path-selection are either 'IPsec established' or 'Resolved'
               and their telemetry state as 'active'.
    * Failure: The test will fail if router path-selection is not configured or if any path state is not 'IPsec established' or 'Resolved',
               or the telemetry state is 'inactive'.

    Examples
    --------
    ```yaml
    anta.tests.path_selection:
      - VerifyPathsHealth:
    ```
    """

    categories: ClassVar[list[str]] = ["path-selection"]
    commands: ClassVar[list[AntaCommand | AntaTemplate]] = [AntaCommand(command="show path-selection paths", revision=1)]

    @skip_on_platforms(["cEOSLab", "vEOS-lab"])
    @AntaTest.anta_test
    def test(self) -> None:
        """Main test function for VerifyPathsHealth."""
        self.result.is_success()

        command_output = self.instance_commands[0].json_output["dpsPeers"]

        # If no paths are configured for router path-selection, the test fails
        if not command_output:
            self.result.is_failure("No path configured for router path-selection")
            return

        # Check the state of each path
        for peer, peer_data in command_output.items():
            for group, group_data in peer_data["dpsGroups"].items():
                for path_data in group_data["dpsPaths"].values():
                    path_state = path_data["state"]
                    session = path_data["dpsSessions"]["0"]["active"]

                    # If the path state of any path is not 'ipsecEstablished' or 'routeResolved', the test fails
                    expected_state = ["ipsecEstablished", "routeResolved"]
                    if path_state not in expected_state:
                        self.result.is_failure(f"Peer: {peer} Path Group: {group} - Invalid path state - Expected: {', '.join(expected_state)} Actual: {path_state}")

                    # If the telemetry state of any path is inactive, the test fails
                    elif not session:
                        self.result.is_failure(f"Peer: {peer} Path Group {group} - Telemetry state inactive")

VerifySpecificPath

Verifies the DPS path and telemetry state of an IPv4 peer.

This test performs the following checks:

  1. Verifies that the specified peer is configured.
  2. Verifies that the specified path group is found.
  3. For each specified DPS path:
    • Verifies that the expected source and destination address matches the expected.
    • Verifies that the state is ipsecEstablished or routeResolved.
    • Verifies that the telemetry state is active.
Expected Results
  • Success: The test will pass if the path state under router path-selection is either ‘IPsecEstablished’ or ‘Resolved’ and telemetry state as ‘active’.
  • Failure: The test will fail if router path selection or the peer is not configured or if the path state is not ‘IPsec established’ or ‘Resolved’, or the telemetry state is ‘inactive’.
Examples
anta.tests.path_selection:
  - VerifySpecificPath:
      paths:
        - peer: 10.255.0.1
          path_group: internet
          source_address: 100.64.3.2
          destination_address: 100.64.1.2

Inputs

Name Type Description Default
paths list[DpsPath]
List of router paths to verify.
-
RouterPath type[DpsPath]
To maintain backward compatibility.
DpsPath
Source code in anta/tests/path_selection.py
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
class VerifySpecificPath(AntaTest):
    """Verifies the DPS path and telemetry state of an IPv4 peer.

    This test performs the following checks:

      1. Verifies that the specified peer is configured.
      2. Verifies that the specified path group is found.
      3. For each specified DPS path:
         - Verifies that the expected source and destination address matches the expected.
         - Verifies that the state is `ipsecEstablished` or `routeResolved`.
         - Verifies that the telemetry state is `active`.

    Expected Results
    ----------------
    * Success: The test will pass if the path state under router path-selection is either 'IPsecEstablished' or 'Resolved'
               and telemetry state as 'active'.
    * Failure: The test will fail if router path selection or the peer is not configured or if the path state is not 'IPsec established' or 'Resolved',
               or the telemetry state is 'inactive'.

    Examples
    --------
    ```yaml
    anta.tests.path_selection:
      - VerifySpecificPath:
          paths:
            - peer: 10.255.0.1
              path_group: internet
              source_address: 100.64.3.2
              destination_address: 100.64.1.2
    ```
    """

    categories: ClassVar[list[str]] = ["path-selection"]
    commands: ClassVar[list[AntaCommand | AntaTemplate]] = [AntaCommand(command="show path-selection paths", revision=1)]

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

        paths: list[DpsPath]
        """List of router paths to verify."""
        RouterPath: ClassVar[type[DpsPath]] = DpsPath
        """To maintain backward compatibility."""

    @skip_on_platforms(["cEOSLab", "vEOS-lab"])
    @AntaTest.anta_test
    def test(self) -> None:
        """Main test function for VerifySpecificPath."""
        self.result.is_success()

        command_output = self.instance_commands[0].json_output

        # If the dpsPeers details are not found in the command output, the test fails.
        if not (dps_peers_details := get_value(command_output, "dpsPeers")):
            self.result.is_failure("Router path-selection not configured")
            return

        # Iterating on each DPS peer mentioned in the inputs.
        for dps_path in self.inputs.paths:
            peer = str(dps_path.peer)
            peer_details = dps_peers_details.get(peer, {})
            # If the peer is not configured for the path group, the test fails
            if not peer_details:
                self.result.is_failure(f"{dps_path} - Peer not found")
                continue

            path_group = dps_path.path_group
            source = str(dps_path.source_address)
            destination = str(dps_path.destination_address)
            path_group_details = get_value(peer_details, f"dpsGroups..{path_group}..dpsPaths", separator="..")
            # If the expected path group is not found for the peer, the test fails.
            if not path_group_details:
                self.result.is_failure(f"{dps_path} - No DPS path found for this peer and path group")
                continue

            path_data = next((path for path in path_group_details.values() if (path.get("source") == source and path.get("destination") == destination)), None)
            #  Source and destination address do not match, the test fails.
            if not path_data:
                self.result.is_failure(f"{dps_path} - No path matching the source and destination found")
                continue

            path_state = path_data.get("state")
            session = get_value(path_data, "dpsSessions.0.active")

            # If the state of the path is not 'ipsecEstablished' or 'routeResolved', or the telemetry state is 'inactive', the test fails
            if path_state not in ["ipsecEstablished", "routeResolved"]:
                self.result.is_failure(f"{dps_path} - Invalid state path - Expected: ipsecEstablished, routeResolved Actual: {path_state}")
            elif not session:
                self.result.is_failure(f"{dps_path} - Telemetry state inactive for this path")

Input models

Module containing input models for path-selection tests.

DpsPath

Model for a list of DPS path entries.

Name Type Description Default
peer IPv4Address
Static peer IPv4 address.
-
path_group str
Router path group name.
-
source_address IPv4Address
Source IPv4 address of path.
-
destination_address IPv4Address
Destination IPv4 address of path.
-
Source code in anta/input_models/path_selection.py
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class DpsPath(BaseModel):
    """Model for a list of DPS path entries."""

    model_config = ConfigDict(extra="forbid")
    peer: IPv4Address
    """Static peer IPv4 address."""
    path_group: str
    """Router path group name."""
    source_address: IPv4Address
    """Source IPv4 address of path."""
    destination_address: IPv4Address
    """Destination IPv4 address of path."""

    def __str__(self) -> str:
        """Return a human-readable string representation of the DpsPath for reporting."""
        return f"Peer: {self.peer} PathGroup: {self.path_group} Source: {self.source_address} Destination: {self.destination_address}"