MPLS and LDP: Label Distribution and Label Switching Paths
MPLS and LDP: Label Distribution and Label Switching Paths
Section titled “MPLS and LDP: Label Distribution and Label Switching Paths”This guide covers RouterOS 7 MPLS fundamentals and the Label Distribution Protocol (LDP): enabling MPLS forwarding on interfaces, configuring LDP for automatic label exchange, verifying label-switched paths (LSPs), and reading the Label Forwarding Information Base (LFIB).
MPLS separates the IP routing decision from the per-hop forwarding action. Once a packet enters an MPLS domain, routers forward it by swapping short fixed-length labels rather than performing a full IP lookup at every hop. LDP automates the process of distributing those labels between routers so that end-to-end LSPs form automatically from the IGP routing table.
Overview
Section titled “Overview”Label Operations
Section titled “Label Operations”Every router in an MPLS domain performs one of three label operations on each packet:
| Operation | Router Role | Action |
|---|---|---|
| Push | Ingress LER | Attach an MPLS label to an incoming IP packet, creating an MPLS packet. |
| Swap | Transit LSR | Replace the top label with a new label and forward to the next hop. |
| Pop | Egress LER | Remove the MPLS label and deliver the original IP packet. |
Router Roles
Section titled “Router Roles”- LER (Label Edge Router) — sits at the boundary between the IP and MPLS domains. The ingress LER pushes the first label; the egress LER pops the final label.
- LSR (Label Switch Router) — a core router that only swaps labels. It never examines the inner IP header.
Penultimate Hop Popping (PHP)
Section titled “Penultimate Hop Popping (PHP)”By default, RouterOS uses PHP: the router before the egress LER pops the label, forwarding a plain IP packet to the egress. This removes one lookup at the egress router. The label value 3 (implicit null) signals PHP to the penultimate hop.
Label Distribution Protocol (LDP)
Section titled “Label Distribution Protocol (LDP)”LDP automates LSP creation from the IGP topology:
- Hello discovery — LDP sends UDP hellos to the multicast address
224.0.0.202on port 646 to discover directly connected LDP neighbors. - Session establishment — neighbors negotiate a TCP session on port 646 using their LSR-IDs (typically loopback addresses) as transport endpoints.
- Label advertisement — each router assigns a local label to every IGP prefix it knows and advertises the binding to all LDP neighbors. Neighbors chain these bindings into end-to-end LSPs.
Prerequisites
Section titled “Prerequisites”- RouterOS 7.x (MPLS features are available by default; verify with
/system/package/print) - An IGP (OSPF or IS-IS) advertising loopback
/32addresses and transport subnets between all MPLS routers - A stable loopback interface on each router to serve as the LDP LSR-ID and OSPF router-id
- IP connectivity between all LDP transport addresses before enabling LDP
Configuration
Section titled “Configuration”The examples below use a three-router linear topology matching the diagram above:
| Router | Role | Loopback | Link to next-hop |
|---|---|---|---|
| R1 | Ingress LER | 1.1.1.1/32 | ether1 — 10.0.0.0/30 → R2 |
| R2 | Transit LSR | 2.2.2.2/32 | ether1 — 10.0.0.0/30 → R1, ether2 — 10.0.0.4/30 → R3 |
| R3 | Egress LER | 3.3.3.3/32 | ether1 — 10.0.0.4/30 → R2 |
Step 1: Configure Loopback and IGP Underlay
Section titled “Step 1: Configure Loopback and IGP Underlay”Each router needs a loopback with a /32 address and an IGP advertising it. OSPF is used here; IS-IS works equally well.
R1:
# Create loopback bridge/interface bridge add name=loopback
# Assign LSR-ID address/ip address add address=1.1.1.1/32 interface=loopback
# Configure OSPF with router-id matching the loopback/routing ospf instance add name=default router-id=1.1.1.1/routing ospf area add name=backbone area-id=0.0.0.0 instance=default/routing ospf interface-template add area=backbone interfaces=loopback passive/routing ospf interface-template add area=backbone interfaces=ether1R2:
/interface bridge add name=loopback/ip address add address=2.2.2.2/32 interface=loopback/routing ospf instance add name=default router-id=2.2.2.2/routing ospf area add name=backbone area-id=0.0.0.0 instance=default/routing ospf interface-template add area=backbone interfaces=loopback passive/routing ospf interface-template add area=backbone interfaces=ether1,ether2R3:
/interface bridge add name=loopback/ip address add address=3.3.3.3/32 interface=loopback/routing ospf instance add name=default router-id=3.3.3.3/routing ospf area add name=backbone area-id=0.0.0.0 instance=default/routing ospf interface-template add area=backbone interfaces=loopback passive/routing ospf interface-template add area=backbone interfaces=ether1Verify IGP reachability before proceeding:
# On R1 — should resolve to R3 loopback via OSPF/ip route print where dst-address=3.3.3.3/32/ping 3.3.3.3 count=3Step 2: Enable MPLS on Interfaces
Section titled “Step 2: Enable MPLS on Interfaces”MPLS must be enabled on the physical interfaces that carry labeled traffic. Do not enable MPLS on the loopback itself.
All routers — enable MPLS on core-facing interfaces:
# R1/mpls interface add interface=ether1
# R2/mpls interface add interface=ether1/mpls interface add interface=ether2
# R3/mpls interface add interface=ether1Verify:
/mpls interface printExpected output shows each interface with MPLS flag set.
Step 3: Configure LDP
Section titled “Step 3: Configure LDP”LDP requires a global LSR-ID (the loopback address) and per-interface enabling. LDP uses the LSR-ID as the transport address for TCP sessions, so it must match an address reachable via IGP.
All routers:
# R1 — set LSR-ID to loopback, enable LDP on core interface/mpls ldp set lsr-id=1.1.1.1 enabled=yes/mpls ldp interface add interface=ether1
# R2/mpls ldp set lsr-id=2.2.2.2 enabled=yes/mpls ldp interface add interface=ether1/mpls ldp interface add interface=ether2
# R3/mpls ldp set lsr-id=3.3.3.3 enabled=yes/mpls ldp interface add interface=ether1Step 4: Verify LDP Neighbor Sessions
Section titled “Step 4: Verify LDP Neighbor Sessions”LDP discovery starts within seconds of enabling LDP interfaces. Check for established sessions:
/mpls ldp neighbor print detailA healthy neighbor entry shows state=established and lists the remote LSR-ID, local and remote label spaces, and session uptime. If only state=connecting is shown, the TCP session has not formed — check IGP reachability to the remote LSR-ID.
Verification
Section titled “Verification”Check LDP Bindings
Section titled “Check LDP Bindings”After sessions form, routers exchange label bindings for all IGP prefixes:
/mpls ldp binding print detailEach entry shows:
prefix— the destination prefixnexthop— the LDP next-hoplocal-label— the label this router advertises to others for this prefixremote-label— the label received from the upstream LDP neighbor
Read the Label Forwarding Information Base (LFIB)
Section titled “Read the Label Forwarding Information Base (LFIB)”The LFIB is the active forwarding table used for labeled packet switching:
/mpls forwarding-table print detailKey fields:
| Field | Meaning |
|---|---|
in-label | Label value matched on incoming packets |
out-label | Label pushed on outgoing packets (3 = PHP/implicit-null, 0 = explicit-null) |
interface | Outgoing interface |
nexthop | Next-hop IP address |
operation | swap, pop, or push |
Verify LSP End-to-End
Section titled “Verify LSP End-to-End”From the ingress LER, confirm a full LSP exists to the egress loopback:
# On R1 — show binding for R3 loopback/mpls ldp binding print where prefix=3.3.3.3/32
# Confirm LFIB has forwarding entry/mpls forwarding-table print where nexthop~"10.0.0"If R2 is performing PHP, traffic from R1 will carry a label all the way to R2, where R2 pops it and sends a plain IP packet to R3. This is correct and expected behaviour.
Check Global MPLS Settings
Section titled “Check Global MPLS Settings”/mpls settings printReview propagate-ttl (whether IP TTL is decremented through the MPLS domain) and allow-fast-path (hardware/fast-path label switching).
Practical Examples
Section titled “Practical Examples”Example 1: Full LSP Verification on a Three-Router Chain
Section titled “Example 1: Full LSP Verification on a Three-Router Chain”After completing the configuration above, run these checks on each router:
R1 (Ingress LER):
# LDP neighbor to R2 should be established/mpls ldp neighbor print
# Binding for 3.3.3.3/32 should show remote-label from R2/mpls ldp binding print where prefix=3.3.3.3/32
# LFIB should push R2's advertised label for traffic to 3.3.3.3/32/mpls forwarding-table print detailR2 (Transit LSR):
# Two neighbors: R1 and R3/mpls ldp neighbor print
# Bindings for both 1.1.1.1/32 and 3.3.3.3/32/mpls ldp binding print
# LFIB shows swap or pop operations for each prefix/mpls forwarding-table print detailR3 (Egress LER):
# LDP neighbor to R2/mpls ldp neighbor print
# Bindings — local-label for 3.3.3.3/32 should be 3 (implicit-null, triggering PHP at R2)/mpls ldp binding print where prefix=3.3.3.3/32Example 2: Targeted LDP Sessions
Section titled “Example 2: Targeted LDP Sessions”For applications like VPLS that require LDP sessions between non-adjacent routers, use targeted (unicast) hellos:
# On R1 — establish targeted LDP session to R3 loopback/mpls ldp neighbor add address=3.3.3.3Targeted sessions use the same TCP port 646 but send unicast hellos instead of multicast. Verify with:
/mpls ldp neighbor print detail where address=3.3.3.3Troubleshooting
Section titled “Troubleshooting”LDP Neighbors Not Forming
Section titled “LDP Neighbors Not Forming”# 1. Verify MPLS is enabled on the interface/mpls interface print detail
# 2. Verify LDP is enabled on the interface/mpls ldp interface print detail
# 3. Check LDP global settings — lsr-id must be set/mpls ldp print
# 4. Confirm IGP reachability to the remote LSR-ID/ip route print where dst-address=<remote-lsr-id>/32/ping <remote-lsr-id>If /ping to the remote LSR-ID fails, fix the IGP underlay first. LDP TCP sessions cannot establish without routable transport addresses.
Labels Not Being Distributed
Section titled “Labels Not Being Distributed”# Confirm session is established (not just discovered)/mpls ldp neighbor print detail
# Check binding table — if empty, LDP session may be down/mpls ldp binding print
# Verify OSPF is advertising all loopbacks and transport subnets/routing ospf neighbor print/ip route print where protocol=ospfTraffic Not Being Label-Switched
Section titled “Traffic Not Being Label-Switched”# Confirm LFIB has entries for destination prefixes/mpls forwarding-table print detail
# Check if fast-path is enabled (hardware switching)/mpls settings print
# Trace label path/tool traceroute <destination> use-dns=noCommon Issues
Section titled “Common Issues”| Symptom | Likely Cause | Resolution |
|---|---|---|
state=connecting in neighbor table | No IP route to remote LSR-ID | Fix IGP; ensure loopbacks are advertised |
| Empty binding table after session up | LDP enabled=no globally | /mpls ldp set enabled=yes |
| LFIB missing entries | MPLS not enabled on interface | /mpls interface add interface=<iface> |
| PHP not occurring at penultimate hop | Remote router not advertising implicit-null | Check egress router LDP binding for label=3 on its own prefix |
| Labels assigned but traffic drops | MTU too small for MPLS overhead | Add 4 bytes per label to interface MTU; check /mpls settings |
Command Reference
Section titled “Command Reference”/mpls interface
Section titled “/mpls interface”Enables MPLS forwarding on a physical interface.
| Parameter | Description |
|---|---|
interface | Interface name |
/mpls interface add interface=ether1/mpls interface print detail/mpls interface remove [find interface=ether1]/mpls ldp
Section titled “/mpls ldp”Global LDP settings.
| Parameter | Description |
|---|---|
enabled | Enable/disable LDP globally (yes/no) |
lsr-id | Router LSR-ID, used as LDP transport address — typically loopback /32 |
transport-addresses | Override transport address per address-family |
/mpls ldp set lsr-id=1.1.1.1 enabled=yes/mpls ldp print/mpls ldp interface
Section titled “/mpls ldp interface”Enables LDP on a specific interface for neighbor discovery.
/mpls ldp interface add interface=ether1/mpls ldp interface print detail/mpls ldp neighbor
Section titled “/mpls ldp neighbor”View discovered and established LDP neighbors. Use add address= for static/targeted neighbors.
/mpls ldp neighbor print detail/mpls ldp neighbor add address=3.3.3.3/mpls ldp binding
Section titled “/mpls ldp binding”Label binding table — shows local and remote labels for each prefix.
/mpls ldp binding print detail/mpls ldp binding print where prefix=10.0.0.0/24/mpls forwarding-table
Section titled “/mpls forwarding-table”Active LFIB — the table used for label-based packet forwarding decisions.
/mpls forwarding-table print detail/mpls forwarding-table print where in-label=100/mpls settings
Section titled “/mpls settings”Global MPLS behaviour flags.
/mpls settings print/mpls settings set propagate-ttl=yesRelated Information
Section titled “Related Information”Related Topics
Section titled “Related Topics”- VPLS — Layer 2 VPN services built on top of MPLS LDP LSPs
- MPLS Traffic Engineering and RSVP-TE — TE tunnels, explicit paths, and bandwidth reservation with RSVP-TE
- MPLS-TE Explicit Paths — Detailed explicit path configuration and ERO notation
- MPLS-TE Hop Types — Strict and loose hop configuration for TE tunnels
- OSPF Configuration — IGP underlay required for LDP LSR-ID reachability
RFC References
Section titled “RFC References”- RFC 5036 — LDP Specification (core protocol)
- RFC 3031 — MPLS Architecture
- RFC 3032 — MPLS Label Stack Encoding
- RFC 3443 — TTL Processing in Multi-Protocol Label Switching (MPLS) Networks