[Day #41 PyATS Series] Validate Routing Table Entries Across Cisco/Arista/Palo Alto/Fortigate Using pyATS for Cisco [Python for Network Engineer]
Table of Contents
Introduction on the Key Points
Routing tables are the backbone of IP packet forwarding. Any mismatch, stale route, or missing entry can lead to packet drops, suboptimal routing, or even complete network outages. Traditionally, network engineers log in to each device and manually inspect the routing table—a time-consuming and error-prone process.
With pyATS, you can automate multi-vendor routing table validation, ensuring that routes are consistently learned and advertised across Cisco, Arista, Palo Alto, and Fortinet devices. This tutorial shows you how to:
- Collect routing tables automatically from multiple vendors
- Validate route existence, next-hops, and administrative distances
- Detect anomalies such as missing or incorrect routes
- Generate structured reports for operational teams
If you’re a Python for Network Engineer enthusiast, this is a must-have automation skill that scales your routing verification tasks across heterogeneous environments.
Topology Overview
Our example network consists of a multi-vendor setup:

- Cisco device acts as the primary core router.
- Arista switch runs L3 and learns dynamic routes.
- Palo Alto firewall participates in OSPF/BGP for security zones.
- Fortinet firewall is the WAN edge device with static and dynamic routes.
Our goal is to ensure that all expected routes (e.g., 10.10.0.0/16
, 192.168.1.0/24
) are present and correctly propagated to every device.
Topology & Communications
- Protocols: OSPF and BGP dynamically share routes between devices.
- Communication: pyATS connects via SSH to devices and retrieves routing tables.
- Vendor Agnostic: Using Genie parsers or custom parsing logic for Palo Alto and Fortinet, we standardize route data.
- Validation: Cross-checks routing tables to ensure every device has the same expected prefixes.
Workflow Script
from genie.testbed import load import json EXPECTED_ROUTES = [ '10.10.0.0/16', '192.168.1.0/24', '172.16.0.0/12' ] def collect_routes(device): device.connect(log_stdout=False) output = device.parse('show ip route') device.disconnect() routes = set() for prefix in output.get('vrf', {}).get('default', {}).get('address_family', {}).get('ipv4', {}).get('routes', {}): routes.add(prefix) return routes if __name__ == "__main__": testbed = load('testbed.yml') results = {} for name, device in testbed.devices.items(): print(f"Collecting routes from {name}...") device_routes = collect_routes(device) missing = [route for route in EXPECTED_ROUTES if route not in device_routes] results[name] = { "found_routes": list(device_routes), "missing_routes": missing } with open('routing_validation.json', 'w') as f: json.dump(results, f, indent=4) print("Routing table validation completed. See routing_validation.json for details.")
Explanation by Line
- EXPECTED_ROUTES: Define all critical routes that should be present on every device.
- collect_routes: Connects to each device, parses routing entries, and extracts prefixes.
- Output Parsing: Uses Genie’s structured parsing for Cisco/Arista. Palo Alto and Fortinet can use CLI parsing or API integrations.
- Validation Logic: Compares actual routes with expected ones and lists any missing prefixes.
- Output: Generates a JSON report showing per-device route validation results.
testbed.yml Example
testbed: name: routing_validation devices: Cisco_Core: os: iosxe type: router connections: cli: protocol: ssh ip: 192.168.100.1 credentials: default: username: admin password: cisco123 Arista_L3: os: eos type: switch connections: cli: protocol: ssh ip: 192.168.100.2 credentials: default: username: admin password: arista123 Palo_FW: os: panos type: firewall connections: cli: protocol: ssh ip: 192.168.100.3 credentials: default: username: admin password: palo123 Fortinet_Edge: os: fortinet type: firewall connections: cli: protocol: ssh ip: 192.168.100.4 credentials: default: username: admin password: forti123
Post-validation CLI Screenshots (Expected Output)
Cisco Core Router:
Router# show ip route ... 10.10.0.0/16 is variably subnetted, 2 subnets 192.168.1.0/24 is directly connected 172.16.0.0/12 [110/2] via 10.1.1.1
Script Output Example:
{ "Cisco_Core": { "found_routes": ["10.10.0.0/16", "192.168.1.0/24", "172.16.0.0/12"], "missing_routes": [] }, "Arista_L3": { "found_routes": ["10.10.0.0/16", "192.168.1.0/24"], "missing_routes": ["172.16.0.0/12"] }, "Palo_FW": { "found_routes": ["192.168.1.0/24"], "missing_routes": ["10.10.0.0/16", "172.16.0.0/12"] }, "Fortinet_Edge": { "found_routes": ["10.10.0.0/16", "172.16.0.0/12"], "missing_routes": ["192.168.1.0/24"] } }
FAQs
1. How does pyATS retrieve routing table information across different vendors?
pyATS uses its built-in Genie parsers for Cisco and Arista devices to structure CLI output, while Palo Alto and Fortinet devices can be integrated using CLI-based custom parsers or REST APIs. This standardization allows cross-vendor routing data comparison.
2. Can this script validate both IPv4 and IPv6 routing tables?
Yes. The solution can be extended to parse show ipv6 route
outputs or API equivalents, enabling validation of IPv6 prefixes, next-hops, and metrics alongside IPv4.
3. How does the script handle VRFs or multiple routing instances?
pyATS can loop through each VRF, collect routes individually, and validate them against expected entries. This ensures that each virtual routing context is fully verified.
4. Does this automation check next-hop accuracy and administrative distances?
Yes. By enhancing the script, you can verify not just the presence of routes but also their next-hop IPs, protocols (OSPF, BGP, static), metrics, and admin distances to detect misconfigurations.
5. Is it safe to run this routing table validation in a live production network?
Absolutely. The script uses read-only commands (e.g., show ip route
), meaning there’s no risk of configuration changes or traffic disruption.
6. Can pyATS scale to validate routing tables across hundreds of devices?
Yes. With parallel execution and a properly designed testbed, pyATS can handle large-scale enterprise or service provider networks efficiently.
7. How frequently should routing table validations be performed?
It’s best practice to run validations:
- After every routing policy change
- Following network migrations or failovers
- On a scheduled basis (daily or weekly) to detect route leaks or missing prefixes early
8. Can the validation results be integrated into dashboards or CI/CD pipelines?
Yes. The output (JSON/CSV) can be fed into monitoring dashboards like Grafana or Kibana, and integrated into CI/CD pipelines to automatically validate routing states during deployments.
YouTube Link
Watch the Complete Python for Network Engineer: Validate Routing Table Entries Across Cisco/Arista/Palo Alto/Fortigate Using pyATS for Cisco [Python for Network Engineer] Lab Demo & Explanation on our channel:
Join Our Training
Validating routing tables manually wastes valuable time and risks outages due to overlooked discrepancies. Automating this with pyATS ensures network reliability and consistency across vendors.
Trainer Sagar Dhawan offers a 3-month, instructor-led course teaching Python, Ansible, APIs, and Cisco DevNet for Network Engineers. You’ll learn to build advanced network validation scripts like this one, preparing you for real-world automation challenges.
Join Our Training and elevate your automation skills with Python for Network Engineer.
Enroll Now & Future‑Proof Your Career
Email: info@networkjourney.com
WhatsApp / Call: +91 97395 21088