MPLS & Segment Routing LSP Telemetry: Label Switched Path Auditing with ezsnmp¶
Note
Published: November 13, 2026
Authors: Written by Gemini 3.8 Flash, Co-Authored & Reviewed by Carlos Santos (@carlkidcrypto)
Estimated Reading Time: 5 minutes
Tags: Ezsnmp • Python • Snmp • Mpls • Segment-Routing • Networking • Telemetry
Modern enterprise campus backbones, wide-area networks (WAN), and service provider backbones rely on Multiprotocol Label Switching (MPLS) and Segment Routing over MPLS (SR-MPLS) to engineer traffic, provide deterministic Quality of Service (QoS), and isolate tenant overlays via VPNs.
In a label-switched network, forwarding decisions do not inspect packet IP headers hop-by-hop. Instead, packets travel along pre-established Label Switched Paths (LSPs). At each Label Switching Router (LSR), the incoming label index is swapped, pushed, or popped using the hardware Label Forwarding Information Base (LFIB).
When an LSP breaks—whether due to an interior gateway protocol (IGP) metric shift, hardware interface failure, or RSVP-TE signaling timeout—traffic can silently drop or fail over to suboptimal non-engineered paths. Continuous operational telemetry of LSP cross-connects and tunnel interfaces is critical.
The ezsnmp library provides native C/C++17 bindings directly to Net-SNMP, enabling network automation engineers to audit hundreds of active LSPs across core routers in milliseconds.
In this tutorial, we will explore the standard MIB architecture for MPLS and
Segment Routing, inspect the LFIB cross-connect tables, and build a high-speed
LSP telemetry auditor using ezsnmp.
The MIB Architecture for MPLS & Segment Routing¶
The IETF standardized MPLS telemetry across several foundational MIBs:
MPLS-LSR-STD-MIB (RFC 3811 / RFC 3813): Models the Label Switching Router’s internal LFIB, tracking incoming label segments, outgoing label segments, and cross-connect relationships.
MPLS-TE-STD-MIB (RFC 3812): Models signaled and static traffic engineering tunnels, tracking tunnel ingress, egress, administrative state, operational status, and forwarding metrics.
Key LFIB Managed Objects¶
Under the MPLS-LSR-STD-MIB (OID .1.3.6.1.2.1.10.166.2), three tables
reconcile label forwarding:
mplsInSegmentTable(.1.3.6.1.2.1.10.166.2.1.4): Maintains incoming label segments at an LSR, includingmplsInSegmentLabel,mplsInSegmentAdminStatus, andmplsInSegmentOperStatus.mplsOutSegmentTable(.1.3.6.1.2.1.10.166.2.1.7): Maintains outgoing label segments, including next-hop interface, push/swap labels, and operational forwarding health.mplsXCTable(.1.3.6.1.2.1.10.166.2.1.10): The Cross-Connect (XC) table. It binds anin-segmentto one or moreout-segments, defining the true switching path across the router plane. The primary health indicator ismplsXCOperStatus: -up(1): Cross-connect is fully active and passing packets. -down(2): Path is administratively up but operationally halted. -testing(3): Segment undergoing loopback or OAM verification. -unknown(4): Forwarding status indeterminate. -dormant(5): Standby secondary or fast-reroute path. -lowerLayerDown(7): Outgoing physical interface or transport link down.
Traffic Engineering & Segment Routing Tunnels¶
Under MPLS-TE-STD-MIB (OID .1.3.6.1.2.1.10.166.3), the
mplsTunnelTable (.1.3.6.1.2.1.10.166.3.2.2) represents the end-to-end
LSP perspective:
mplsTunnelName: Configured textual identifier (e.g.tun-sea-ord-te01).mplsTunnelIngressLSRId/mplsTunnelEgressLSRId: 32-bit router IDs defining tunnel endpoints.mplsTunnelAdminStatus/mplsTunnelOperStatus: Operational state of the tunnel interface.mplsTunnelOctets/mplsTunnelPackets: Counter metrics tracking volume transported across the path.
In Segment Routing (SR-MPLS), tunnels operate as source-routed paths composed of
Prefix-SIDs (node segments) and Adjacency-SIDs. Modern network operating systems
(such as Cisco IOS-XR, Arista EOS, and Juniper Junos) expose SR-TE policies and
SR-MPLS paths directly through standard mplsTunnelTable and mplsXCTable
hierarchies.
Building the LSP Telemetry Auditor¶
When querying routing tables with thousands of label entries, issuing serial
snmpget queries introduces severe latency. With ezsnmp, we utilize
session.bulk_walk() to retrieve dense table columns in multi-OID PDU
batches:
from ezsnmp import Session
from ezsnmp.exceptions import GenericError
# Standard RFC 3811 / RFC 3812 MIB OIDs
OID_MPLS_XC_OPER_STATUS = "1.3.6.1.2.1.10.166.2.1.10.1.10"
OID_MPLS_XC_ADMIN_STATUS = "1.3.6.1.2.1.10.166.2.1.10.1.9"
OID_MPLS_TUNNEL_NAME = "1.3.6.1.2.1.10.166.3.2.2.1.35"
OID_MPLS_TUNNEL_OPER_STATUS = "1.3.6.1.2.1.10.166.3.2.2.1.5"
XC_STATUS_MAP = {
"1": "UP",
"2": "DOWN",
"3": "TESTING",
"4": "UNKNOWN",
"5": "DORMANT",
"6": "NOT_PRESENT",
"7": "LOWER_LAYER_DOWN",
}
TUNNEL_STATUS_MAP = {
"1": "UP",
"2": "DOWN",
"3": "TESTING",
"4": "UNKNOWN",
"5": "DORMANT",
"6": "NOT_PRESENT",
"7": "LOWER_LAYER_DOWN",
}
def audit_mpls_telemetry(host: str, community: str = "public"):
session = Session(
hostname=host,
community=community,
version=2,
timeout=3,
retries=1,
set_max_repeaters_to_num=25,
)
try:
print(f"[*] Auditing MPLS and SR-TE state on {host}...")
# 1. Audit MPLS Cross-Connect Forwarding Plane
xc_oper_vars = session.bulk_walk(OID_MPLS_XC_OPER_STATUS)
xc_admin_vars = session.bulk_walk(OID_MPLS_XC_ADMIN_STATUS)
admin_status_dict = {
var.index: var.value for var in xc_admin_vars
}
active_xc_count = 0
degraded_xc_list = []
for var in xc_oper_vars:
index = var.index
oper_code = var.value
admin_code = admin_status_dict.get(index, "1")
oper_desc = XC_STATUS_MAP.get(oper_code, f"CODE_{oper_code}")
if oper_code == "1":
active_xc_count += 1
elif admin_code == "1": # Admin UP but Oper DOWN
degraded_xc_list.append((index, oper_desc))
print(f"[+] Total Active Cross-Connects: {active_xc_count}")
if degraded_xc_list:
print(f"[!] Warning: {len(degraded_xc_list)} degraded XCs:")
for idx, status in degraded_xc_list:
print(f" - XC Index {idx}: Operational Status {status}")
# 2. Audit Traffic Engineering & Segment Routing Tunnels
tunnel_names = session.bulk_walk(OID_MPLS_TUNNEL_NAME)
tunnel_status = session.bulk_walk(OID_MPLS_TUNNEL_OPER_STATUS)
status_dict = {
var.index: var.value for var in tunnel_status
}
print(f"[+] Discovered {len(tunnel_names)} MPLS/SR Tunnels:")
for var in tunnel_names:
idx = var.index
name = var.value
t_oper = status_dict.get(idx, "4")
t_desc = TUNNEL_STATUS_MAP.get(t_oper, f"CODE_{t_oper}")
print(f" - Tunnel: {name:<24} State: {t_desc}")
except GenericError as err:
print(f"[-] SNMP telemetry query failed: {err}")
Automating Fast-Reroute (FRR) Verification¶
In mission-critical backbones, LSPs are provisioned with Fast-Reroute (FRR)
backup paths. Under normal operating conditions, the primary cross-connect is
UP(1) while the backup path reports as DORMANT(5).
If an auditor observes that a backup cross-connect transitions to UP(1)
without administrative reconfiguration, it indicates that local link protection
has engaged due to an underlying optical fiber cut or interface flap. Capturing
this transition in your monitoring stack allows engineering teams to repair
underlying physical paths before second-order failures exhaust backup capacity.
Summary & What’s Next¶
By auditing standard MPLS-LSR-STD-MIB and MPLS-TE-STD-MIB objects with
ezsnmp, network operations teams
gain deterministic visibility into label switching fabric health, detecting
silent path drops and routing anomalies before user traffic is disrupted.
In our next blog post, we will rotate back to purpleair_api, exploring how to conduct historical sensor data extraction and bounding-box queries for regional air quality studies.
Warning
AI-generated content may contain misinformation or mistakes. A human does review this, but we are only human.