Verifying MPLS L3VPNs with Python: RD, RT, and the Routes That Should Be There
A repeatable check that catches the silent VPN leak before the customer calls.
MPLS VPNs fail in the quietest way possible: a single mistyped route-target and a customer's two sites simply cannot see each other, while every link is green. Verification means checking the control plane, not the cables.
The three identities that must line up
- VRF — the isolated routing table for the customer on each PE.
- Route Distinguisher — makes overlapping customer prefixes globally unique inside MP-BGP.
- Route Target — controls which VRFs import and export the routes. A VPN works only when PE-1's export RT matches PE-2's import RT.
Collect the VRF detail
from netmiko import ConnectHandler
def vrf_detail(host):
conn = ConnectHandler(device_type="cisco_ios_xr", host=host,
username="ro", password="••••")
# use_textfsm parses raw output into list[dict]
return conn.send_command("show vrf CUST-A detail", use_textfsm=True)The use_textfsm=True flag runs the output through a TextFSM template so you get structured records instead of text to regex.
Check RT consistency across PEs
pe1 = vrf_detail("10.0.0.1")[0]
pe2 = vrf_detail("10.0.0.2")[0]
# PE-1 must export what PE-2 imports, and vice versa
ok = (set(pe1["export_rt"]) == set(pe2["import_rt"]) and
set(pe2["export_rt"]) == set(pe1["import_rt"]))
if not ok:
print("RT MISMATCH")
print(f" PE-1 export {pe1['export_rt']} vs PE-2 import {pe2['import_rt']}")
print(f" PE-2 export {pe2['export_rt']} vs PE-1 import {pe1['import_rt']}")Prove the routes actually arrived
RT config being correct is necessary, not sufficient. Confirm the remote prefix is installed in the VRF.
routes = conn.send_command("show ip route vrf CUST-A", use_textfsm=True)
remote = [r for r in routes if r["network"].startswith("192.168.20.")]
print("Remote site reachable:" , bool(remote))show bgp vpnv4 unicast summary next.Make it a standing check
Schedule this across every PE pair and emit a finding keyed vpn/rt-mismatch/CUST-A on failure. The Intent engine can express the same invariant declaratively — "every PE serving CUST-A shares a symmetric RT set" — and verify it on a cadence.
Was this helpful?
Generate scripts for the task covered in this post
Describe what you need and NAPT writes production-ready automation in Netmiko, NAPALM, or Nornir.
Open Script Generator →Related posts
Compliance Without the Spreadsheet: Continuous Posture for Network Devices
The Compliance panel runs your hardening rule packs across the fleet, scores devices, and tracks drift so audits start with evidence, not promises.
Read →Inventory & IPAM: The Source of Truth Your Scripts Actually Trust
Upload a CSV, connect to NetBox, or generate an IP range — Inventory normalises every source into the same validated row shape for the platform.
Read →Runbooks: Living Documents That Run
Runbooks combine narrative, parameters, and executable scripts so on-call engineers stop choosing between reading the doc and fixing the problem.
Read →