How MPLS routers automatically hand each other labels for every IGP prefix — discovery, sessions, distribution modes, IGP sync, and why Segment Routing is retiring it.
LDP exists to solve one narrow problem: in a plain MPLS network you need a label-switched path (LSP)
to every egress loopback, and hand-configuring static labels on every hop does not scale. LDP builds
those LSPs automatically by following the IGP — for every prefix in the routing table (typically
the /32 loopbacks that VPN and PW services target), each router allocates a local label and tells its
neighbors, so a full mesh of hop-by-hop LSPs appears with almost no configuration.
The one-sentence summary: LDP distributes labels bound to IGP-learned FECs so that every LSR has an LSP to every other LSR's loopback. It has no traffic-engineering ability of its own — the path an LSP takes is exactly whatever the IGP shortest path is. If you want explicit paths or bandwidth reservation you need RSVP-TE or Segment Routing on top of / instead of it.
| Term | Meaning |
|---|---|
| FEC | Forwarding Equivalence Class — the group of packets treated the same way. In vanilla LDP the FEC is almost always an IGP prefix (a loopback /32). |
| Label binding | A mapping FEC → label. A router advertises the label it wants upstream neighbors to use to reach that FEC through it. |
| LSR / LER | Label Switch Router (transit, swaps labels) / Label Edge Router (ingress imposes, egress pops). |
| LSP | Label Switched Path — the unidirectional chain of label swaps from ingress LER to egress for one FEC. |
| Upstream / downstream | Downstream = the direction the traffic flows toward (closer to the egress/FEC). Labels are always allocated by the downstream router and used by the upstream one. "Downstream" is the whole mental model for LDP. |
| PHP | Penultimate Hop Popping — the egress advertises the implicit-null label (value 3) so the second-to-last router pops the transport label, saving the egress a lookup. |
| LSR-ID / LDP Identifier | 6-byte ID: 4-byte router ID (LSR-ID, usually a loopback) + 2-byte label space number (:0 = per-platform label space). |
LDP runs on UDP and TCP port 646. It is a two-stage process: lightweight UDP Hellos to discover a neighbor, then a reliable TCP session to exchange labels.
R1 R2
│ UDP 646 Link Hello → 224.0.0.2 (LDP-ID R1) │ Basic discovery
│ ◀───────────────────────────────────────────────▶ │ (multicast on the link)
│ │
│ Higher LSR-ID actively opens TCP 646 │ R2 (higher ID) = active
│ ═════════════════════════════════════════════════▶│
│ TCP handshake, then LDP Initialization │ negotiate params
│ ◀═══════════════════════════════════════════════▶ │
│ Keepalive / Address / Label Mapping messages │ session UP
│ ◀═══════════════════════════════════════════════▶ │
224.0.0.2 on each enabled interface. Each Hello carries the sender's
LDP Identifier and a hold time; missing Hellos past the hold time tears the adjacency down.Three orthogonal knobs describe how and when a router advertises and keeps labels. On modern Ethernet/packet networks the defaults are almost universal: DU + Independent + Liberal (Cisco/Juniper defaults). Know all three axes and their tradeoffs.
| Mode | Behavior | Tradeoff / where used |
|---|---|---|
| Downstream Unsolicited (DU) | A router advertises a label binding for every FEC to all LDP peers without being asked, as soon as it has one. | Fast convergence, no request round-trip; more label state and more messages. Default on frame/packet networks. |
| Downstream-on-Demand (DoD) | A router advertises a label for a FEC only when a peer explicitly requests it (Label Request → Label Mapping). | Minimal label state; extra RTT to obtain a label. Historically used on ATM/Frame-Relay LC-ATM interfaces where label space is scarce. |
| Control | Behavior | Tradeoff |
|---|---|---|
| Independent | A router allocates and advertises a label for a FEC immediately, as soon as it recognizes the FEC in its RIB — without waiting for a label from its own downstream. | Faster convergence; but an upstream may start labeling before the full LSP is stitched, so briefly a label may point at a not-yet-complete path. Common default. |
| Ordered | A router advertises a label for a FEC only after it has received a label for that FEC from its own downstream neighbor (or it is the egress for the FEC). | The LSP is built end-to-end before labels propagate upstream — cleaner, no transient half-built LSPs; slightly slower to converge. |
| Retention | Behavior | Tradeoff |
|---|---|---|
| Liberal | Keep all label bindings received from every neighbor, even from neighbors that are not the current IGP next-hop for that FEC. | More memory, but a label for the new next-hop is already in hand after an IGP reconvergence → very fast switchover. Default with DU. |
| Conservative | Keep only the binding from the current next-hop; discard the rest. | Minimal label state (fits scarce ATM label space); on a next-hop change you must re-request/relearn the label → slower. Pairs with DoD. |
Packet MPLS defaults to Downstream Unsolicited + Independent control + Liberal retention: every router floods labels for every loopback to every peer, allocates them without waiting, and keeps them all. The result is maximum label state but the fastest possible convergence — after the IGP moves a next-hop, the replacement label is already stored and forwarding updates in one step.
All LDP PDUs use a common header (version, PDU length, LDP Identifier) carrying one or more TLV-encoded messages. Hellos ride UDP; everything else rides the reliable TCP session.
| Message | Transport | Purpose |
|---|---|---|
| Hello | UDP 646 | Discovery + adjacency keepalive; carries LDP-ID, hold time, and transport address. Link (multicast) or Targeted (unicast). |
| Initialization | TCP 646 | Negotiate session parameters (mode, keepalive, PDU length, label space) at session bring-up. |
| Keepalive | TCP 646 | Maintain the session; if none arrives within the negotiated keepalive time, the session is torn down. |
| Address / Address Withdraw | TCP 646 | Advertise the local interface IP addresses so a peer can map an IGP next-hop address to the right LDP peer (label lookup). |
| Label Mapping | TCP 646 | Advertise a FEC → label binding. The workhorse message that actually distributes labels. |
| Label Request | TCP 646 | Ask a downstream peer for a label for a FEC (used in DoD, or on-demand). |
| Label Withdraw | TCP 646 | Revoke a previously advertised binding (e.g. FEC lost from the RIB). |
| Label Release | TCP 646 | Upstream tells downstream it no longer needs a binding it was given (e.g. under conservative retention, or after a withdraw). |
| Notification | TCP 646 | Signal errors / advisory events; fatal notifications close the session. |
This is a top interview topic because it explains a real, subtle black-holing failure. LDP follows the IGP, but the two converge independently and at different speeds. When a link comes up, the IGP can install a route and start forwarding over it before LDP has finished building the LSP over that same link.
The failure: the IGP marks the new link as the best path, MPLS traffic is steered onto it, but LDP has no label binding for that next-hop yet → the ingress has no label to impose (or the transit has nothing to swap to) → labeled traffic (and every VPN/PW riding on top of it) is dropped / black-holed until LDP catches up.
The fix — LDP-IGP sync (RFC 5443):
0xffff / max-metric, IS-IS max cost) so it is used only as a last
resort. Traffic keeps using an existing labeled path instead of the un-labeled new one.Basic LDP only talks to directly connected neighbors. Targeted LDP uses unicast Targeted Hellos to form an LDP session with a remote, non-adjacent LSR — the signaling channel for pseudowires.
VC-ID / VPN-ID → label binding that identifies the specific
pseudowire. This is the inner (service/VC) label; the outer transport label to reach the remote PE still comes from
ordinary LDP (or SR/RSVP).The strategic question. LDP is simple but limited: no traffic engineering, no bandwidth awareness, and it is yet another protocol and pile of per-hop state layered on top of the IGP. Its label paths are always exactly the IGP shortest path.
| LDP | RSVP-TE | Segment Routing (SR-MPLS) | |
|---|---|---|---|
| Path selection | IGP shortest path only | Explicit / constraint-based (CSPF) | IGP shortest path or explicit via a stack of segments |
| Traffic engineering | None | Full — ERO, affinities | Yes — SR-TE policies, no per-hop reservation state |
| Bandwidth reservation | No | Yes (admission control) | No hard reservation; controller/PCE-driven |
| Label distribution | LDP sessions (TCP 646) | RSVP Path/Resv signaling | The IGP itself (OSPF/IS-IS SR extensions) — no label protocol |
| Per-LSP state in core | Per-FEC label state on every LSR | Heavy — soft-state per LSP on every hop | None — state lives only in the packet's label stack |
| Extra protocol to run | Yes (LDP) | Yes (RSVP + TE extensions) | No — reuses the IGP you already run |
| Fast reroute | LFA / RLFA (with IGP) | RSVP FRR (link/node protection) | TI-LFA — sub-50ms, guaranteed, simple |
| ECMP | Yes | Poor (per-LSP paths) | Native (prefix-SID follows IGP ECMP) |
# IOS-XR — is the LDP neighbor / session up?
RP/0/0/CPU0:R1# show mpls ldp neighbor
Peer LDP Identity: 10.0.0.2:0 ; Local LDP Identity: 10.0.0.1:0
TCP connection: 10.0.0.2:646 - 10.0.0.1:38912
State: Oper; Msgs sent/rcvd: 512/509; Downstream-Unsolicited
# Label bindings for a FEC (the loopback of R2)
RP/0/0/CPU0:R1# show mpls ldp bindings 10.0.0.2/32
lsr: 10.0.0.2:0, local binding: label 24001
remote binding: lsr 10.0.0.2:0, label imp-null <- PHP at egress
remote binding: lsr 10.0.0.3:0, label 24007 <- kept (liberal retention)
# Forwarding: what label do I push toward R2?
RP/0/0/CPU0:R1# show mpls forwarding prefix 10.0.0.2/32
Local Outgoing Prefix Outgoing Next Hop
Label Label or ID Interface
24001 Pop 10.0.0.2/32 Gi0/0/0/0 192.168.12.2
show mpls ldp neighbor — confirms the TCP session, the advertisement mode, and the peer LDP-ID.show mpls ldp bindings — the LIB: local label plus every remote label learned
(liberal retention shows bindings from non-next-hop peers too).show mpls forwarding — the LFIB: the single label actually programmed for the
current next-hop (Pop = implicit-null / PHP).