Step 3: Verify the Routing Information using Parsers and pyATS Learn¶
Value Proposition: Ensuring flawless network connectivity and uninterrupted business operations is paramount in today’s fast-paced digital landscape. Our comprehensive testing process meticulously validates the integrity of critical routing paths across all devices within your testbed environment. By cross-checking the installation and propagation of vital loopback interfaces against the routing information base (RIB), we proactively identify and mitigate potential vulnerabilities that could disrupt data flows and impact service delivery. This rigorous approach fortifies your network’s resilience, safeguarding mission-critical applications and services from disruptions that could potentially lead to revenue loss, reputational damage, and customer dissatisfaction. By ensuring seamless routing and optimal traffic management, our testing methodology empowers your business with the agility, scalability, and reliability needed to stay ahead of the competition and deliver exceptional user experiences.
The high-level logic of the tests will be the following:
Connect to each device in the testbed.
Learn the routing information from the device’s RIB.
Verify that all critical routes are present in the device’s RIB.
Let’s connect to the pyATS shell and check our idea.
pyats shell --testbed-file pyats_testbed.yaml
Paste the following code into the pyATS shell:
csr = testbed.devices['csr1000v-1'] asa = testbed.devices['asav-1'] nx = testbed.devices['nx-osv-1'] csr.connect(log_stdout=False) asa.connect(log_stdout=False) nx.connect(log_stdout=False)
pyATS uses the learn method to collect the set of show commands output for a feature configured on the device, get its snapshot, and store it in a structured format (Python dictionary).
csr_routes = csr.learn('routing') nx_routes = nx.learn('routing')
Now we can observe the structure of the parsed outputs. We will start with the parsed output for the csr1000v-1.
Paste the following code into the pyATS shell:
import pprint pprint.pprint(csr_routes.info)
Observe the output in pyATS shell:
In [3]: import pprint ...: pprint.pprint(csr_routes.info) {'vrf': {'Mgmt-intf': {'address_family': {'ipv4': {'routes': {'0.0.0.0/0': {'active': True, 'metric': 0, 'next_hop': {'next_hop_list': {1: {'index': 1, 'next_hop': '198.18.1.1'}}}, 'route': '0.0.0.0/0', 'route_preference': 1, 'source_protocol': 'static', 'source_protocol_codes': 'S*'}, '198.18.1.201/32': {'active': True, 'next_hop': {'outgoing_interface': {'GigabitEthernet1': {'outgoing_interface': 'GigabitEthernet1'}}}, 'route': '198.18.1.201/32', 'source_protocol': 'local', 'source_protocol_codes': 'L'}}}}}, 'default': {'address_family': {'ipv4': {'routes': {'10.0.0.12/30': {'active': True, 'next_hop': {'outgoing_interface': {'GigabitEthernet2': {'outgoing_interface': 'GigabitEthernet2'}}}, 'route': '10.0.0.12/30', 'source_protocol': 'connected', 'source_protocol_codes': 'C'}, '10.0.0.13/32': {'active': True, 'next_hop': {'outgoing_interface': {'GigabitEthernet2': {'outgoing_interface': 'GigabitEthernet2'}}}, 'route': '10.0.0.13/32', 'source_protocol': 'local', 'source_protocol_codes': 'L'}, # ...
Now we understand that the routes for csr1000v-1 are stored under the following path:
pprint.pprint(csr_routes.info['vrf']['default']['address_family']['ipv4']['routes'])
For nx-osv-1, RIB routes are stored under the same path as for csr1000v-1:
pprint.pprint (nx_routes.info['vrf']['default']['address_family']['ipv4']['routes'])
Exit the pyATS shell using the exit command.
Open the file task3step3.py in Nano editor.
nano task3step3.py
Review the content of the routes test case. Note that we use the path to routes from the previous step to get the routing information. First, we’ll get a snapshot of the routing feature.
@aetest.test def routes(self, device): """ Verify that all devices have golden_routes installed in the RIB """ if (device.os == 'iosxe') or (device.os == 'nxos'): output = device.learn('routing') rib = {"replace": "me"}
Then we compare the loopback routes stored in golden_routes list with the content of rib. If the loopback route is not found, then we force the test case to fail.
golden_routes = ['192.168.0.3/32', '192.168.0.1/32']
for route in golden_routes: if route not in rib: self.failed(f'{route} is not found') else: pass
Note
Golden routes are /32 networks of loopback interfaces on csr1000v-1 and nx-osv-1.
Loopback0 on csr1000v-1:
csr1000v-1#sh ip int br Interface IP-Address OK? Method Status Protocol GigabitEthernet1 198.18.1.201 YES TFTP up up GigabitEthernet2 10.0.0.13 YES TFTP up up GigabitEthernet3 10.0.0.17 YES TFTP up up Loopback0 192.168.0.3 YES TFTP up up
Loopback0 on NX-OS:
nx-osv-1# sh ip interface brief vrf all IP Interface Status for VRF "default"(1) Interface IP Address Interface Status Lo0 192.168.0.1 protocol-up/link-up/admin-up Eth1/1 10.0.0.14 protocol-up/link-up/admin-up Eth1/2 10.0.0.18 protocol-up/link-up/admin-up Eth1/3 10.0.0.6 protocol-up/link-up/admin-up IP Interface Status for VRF "management"(2) Interface IP Address Interface Status mgmt0 198.18.1.203 protocol-up/link-up/admin-up IP Interface Status for VRF "inside"(3) Interface IP Address Interface Status Lo100 192.168.100.1 protocol-up/link-up/admin-up Eth1/4 10.0.0.10 protocol-up/link-up/admin-up
Complete this test case by replacing the
<<replace me>>
statement with a rib variable. To accomplish this, you must paste the path to the rib routes, which you figured out during the previous step:output.info['vrf']['default']['address_family']['ipv4']['routes']
# Before inserting the rib variable: rib = {"replace": "me"} # After inserting the rib variable: rib = output.info['vrf']['default']['address_family']['ipv4']['routes']
When you finish, save changes to file task3step3.py by pressing
Ctrl + O File Name to Write: task3step3.py Hit [Enter]
Execute the test script and check the results section:
python task3step3.py --testbed-file pyats_testbed.yaml
Note
For a list of definitions of test results, please go to this link
Section author: Luis Rueda <lurueda@cisco.com>, Jairo Leon <jaileon@cisco.com>