MPLS · · 15 min read

Troubleshooting MPLS LDP: "unusable: no label" and Broken LSPs

MPLS forwarding runs on labels, not on IP reachability, so a dead LDP session leaves every green light green while the customer blackholes. Captured on CML with IOS XE 17.18.2: the unusable: no label CEF entry, the full LDP LIB, a hop-by-hop walk to find where the binding stops, and No Label...

Terminal showing an MPLS forwarding table entry reading No Label and a CEF entry reading unusable: no label

MPLS has a signature failure mode, and once you have seen it you never forget it: every IP test passes, the IGP is fully converged, you can ping every loopback in the core, and the customer's traffic is going nowhere. The reason is that MPLS forwarding does not run on IP reachability. It runs on labels, and labels come from LDP. Break LDP and the control plane looks perfect while the data plane is dead.

This is a structured way to troubleshoot the label plane: LDP neighbors, label bindings, and the LSPs they build. Every capture comes from live CML labs on IOS XE 17.18.2: a five-router L3VPN core with LDP deliberately broken on one link, and a minimal three-router core, no VRFs, where the before and after is one line of output changing.

If you got here by pasting unusable: no label into a search box: that string means the router resolved the route and the next hop, then had no label to put on the packet, so CEF refused to forward it. The transport LSP is incomplete somewhere, and the message does not say where. For L3VPN-specific route problems see what to check when the labels are fine but the VPN routes are missing, or start with how MPLS label switching works end to end.

Troubleshoot in Layers, Bottom Up

MPLS is a stack, and each layer depends entirely on the one below. Do not start in the middle:

1. Interface / IPshow ip interface brief
2. IGPshow ip ospf neighbor, is the far loopback a /32 in the table?
3. MPLS enabledshow mpls interfaces
4. LDP sessionshow mpls ldp neighbor (want State: Oper)
5. Label bindingsshow mpls ldp bindings
6. Forwardingshow mpls forwarding-table, show ip cef

Layer 2 being healthy tells you nothing about layer 4. That is the entire trap. Work up the stack and stop at the first layer that is wrong.

What Healthy Looks Like

You need a reference before you can spot a deviation. On PE1 in the L3VPN lab, the LDP session to the P router:

PE1#show mpls ldp neighbor
    Peer LDP Ident: 10.255.0.3:0; Local LDP Ident 10.255.0.1:0
	TCP connection: 10.255.0.3.60695 - 10.255.0.1.646
	State: Oper; Msgs sent/rcvd: 8/8; Downstream
	Up time: 00:00:34
	LDP discovery sources:
	  Ethernet0/1, Src IP addr: 10.30.30.2
        Addresses bound to peer LDP Ident:
          10.255.0.3      10.30.30.2      10.30.31.1

Four things to read every time:

  • State: Oper. Anything else and no labels are being exchanged. There is no partial credit.
  • The LDP identifiers (10.255.0.3:0, 10.255.0.1:0). These should be loopbacks. If you see a physical interface address here, someone forgot mpls ldp router-id Loopback0 force and the session will reset the next time that interface flaps.
  • TCP connection on port 646. LDP sessions are TCP; discovery is UDP 646 multicast. Which side owns 646 is not random: the higher router ID opens the connection and the lower one listens, so the attempt only ever happens in one direction (which matters when you write a core ACL). If discovery works but the session never establishes, look for an ACL blocking TCP 646, or for the router-id being an address the peer cannot reach.
  • Addresses bound to peer. The peer's full interface list. Useful for confirming you are talking to the router you think you are.

And show mpls interfaces, which tells you whether MPLS is actually on:

PE1#show mpls interfaces
Interface              IP            Tunnel   BGP Static Operational
Ethernet0/1            Yes (ldp)     No       No  No     Yes

One line, and only the core-facing interface. Ethernet0/0 (the PE-CE link) is correctly absent: the customer does not speak MPLS. If you see a CE-facing interface in this output, someone put mpls ip where it does not belong. Remember this command, because further down it produces the most misleading output in the whole toolkit.

Reading Label Bindings

The Label Information Base (LIB) is every label your router knows about for a prefix: the one it allocated locally, plus the ones its neighbors advertised. This is the raw material the forwarding table is built from.

P#show mpls ldp bindings 10.255.0.2 32
  lib entry: 10.255.0.2/32, rev 10
	local binding:  label: 17
	remote binding: lsr: 10.255.0.2:0, label: imp-null
	remote binding: lsr: 10.255.0.1:0, label: 18

Read it as a conversation. The P router says "for PE2's loopback, I will accept traffic on label 17." PE2 itself says "I am the owner of this prefix, send it to me with imp-null (implicit null), meaning pop the label before you send it." PE1 says "I use 18 for that prefix." imp-null is what drives penultimate hop popping: because PE2 advertised it, P pops the transport label instead of swapping it.

That is one prefix. The shape of the label plane only shows up in the whole database. This is the LIB from R2, the middle router of the three-router lab, with both sessions up (one connected /30 entry trimmed for length):

R2#show mpls ldp bindings
  lib entry: 1.1.1.1/32, rev 8
	local binding:  label: 16
	remote binding: lsr: 1.1.1.1:0, label: imp-null
	remote binding: lsr: 3.3.3.3:0, label: 16
  lib entry: 2.2.2.2/32, rev 2
	local binding:  label: imp-null
	remote binding: lsr: 1.1.1.1:0, label: 16
	remote binding: lsr: 3.3.3.3:0, label: 17
  lib entry: 3.3.3.3/32, rev 10
	local binding:  label: 17
	remote binding: lsr: 1.1.1.1:0, label: 18
	remote binding: lsr: 3.3.3.3:0, label: imp-null
  lib entry: 10.0.12.0/30, rev 4
	local binding:  label: imp-null
	remote binding: lsr: 1.1.1.1:0, label: imp-null
	remote binding: lsr: 3.3.3.3:0, label: 18

Every entry has the same shape: one local binding (what R2 tells everyone to use when sending it traffic for that prefix) and one remote binding per LSR. Three things fall out of that:

  • R2's local binding for its own 2.2.2.2/32 is imp-null, as is its local for the connected /30. A router advertises implicit null for anything it owns, which is exactly why PHP happens. It is not a fault.
  • R3 advertised label 16 for 1.1.1.1/32, a prefix R3 can only reach back through R2. R2 files it and never uses it. LDP on IOS is downstream unsolicited: everyone advertises everything to everyone.
  • Those five LIB entries produced two rows in the forwarding table, because the LFIB is only the subset the IGP picked. A broken LSP is therefore never a missing prefix in the LIB. It is a missing remote binding from the one LSR you needed it from.

The label format itself, including what "Pop Label" does to the stack, is covered in what is actually inside the label stack, and the mechanics of how LDP discovers neighbors and decides what to advertise are worth reading alongside this.

The Classic: LDP Down, IGP Up

Now break it. On the P router, one core-facing interface loses its MPLS configuration. The link stays up. The IP address stays. Only mpls ip is removed:

P(config)# interface Ethernet0/0
P(config-if)#  no mpls ip

Here is what a network engineer sees on PE1 when the customer calls. Start with the tests that people instinctively run first:

PE1#show ip ospf neighbor

Neighbor ID     Pri   State           Dead Time   Address         Interface
10.255.0.3        1   FULL/DR         00:00:31    10.30.30.2      Ethernet0/1

PE1#ping 10.255.0.2 source Loopback0
Sending 5, 100-byte ICMP Echos to 10.255.0.2, timeout is 2 seconds:
Packet sent with a source address of 10.255.0.1
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 2/2/4 ms

PE1#show ip bgp vpnv4 all summary
Neighbor        V           AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
10.20.1.2       4        65001      10      19       53    0    0 00:05:23        2
10.255.0.2      4        65000      34      23       53    0    0 00:11:26        3

OSPF adjacency FULL. Loopback-to-loopback ping across the core: 100 percent success. The MP-BGP VPNv4 session is up, established for eleven minutes, and has received three prefixes. Every green light you would normally check is green.

And yet:

PE1#ping vrf CUST-A 10.20.20.1 source Ethernet0/0
Sending 5, 100-byte ICMP Echos to 10.20.20.1, timeout is 2 seconds:
Packet sent with a source address of 10.20.1.1
.....
Success rate is 0 percent (0/5)

Total blackhole. Here is the layer everyone skips:

PE1#show mpls ldp neighbor
PE1#

Empty. No LDP session at all. And that has one consequence that explains everything:

PE1#show mpls forwarding-table 10.255.0.2
Local      Outgoing   Prefix           Bytes Label   Outgoing   Next Hop
Label      Label      or Tunnel Id     Switched      interface
18         No Label   10.255.0.2/32    0             Et0/1      10.30.30.2

PE1#show ip cef vrf CUST-A 10.20.20.0
10.20.20.0/24
  nexthop 10.30.30.2 Ethernet0/1 unusable: no label

unusable: no label. That string is the whole diagnosis. PE1 knows the route. It knows the BGP next hop is 10.255.0.2. It can ping 10.255.0.2 all day. But an L3VPN packet needs a two-label stack (transport label to reach PE2, VPN label to identify the customer), and PE1 has no transport label for PE2's loopback, because the LDP session that would have supplied it is gone. CEF refuses to forward a packet it cannot label, so it drops it.

Note also that show mpls forwarding-table did not go blank. The entry is still there, with the outgoing label replaced by No Label. If you skim that output looking for a missing line, you will miss it. Read the Outgoing Label column.

Why the VPN dies but plain IP does not

This confuses people, so it is worth stating explicitly. Ordinary IP traffic across the core does not need a label; if the IGP has a route, the packet forwards. But a VPN packet must be labelled, because that is how PE2 knows which customer it belongs to. There is no unlabelled fallback. MPLS Flags: MPLS Required, as the routing table puts it:

PE1#show ip route vrf CUST-A 10.20.20.0 255.255.255.0
Routing entry for 10.20.20.0/24
  Known via "bgp 65000", distance 200, metric 0, type internal
  * 10.255.0.2 (default), from 10.255.0.2
      MPLS label: 22
      MPLS Flags: MPLS Required

So: IP works, VPN does not. Every time you see that combination, go straight to LDP.

Walking the Path to Find Where the Label Stops

In that lab the break was one hop away. In a real core it will not be. unusable: no label is reported by the ingress router, and all that router knows is that its own downstream neighbor never handed it a label for the remote loopback. The break can be several hops on, and every router in between looks flawless.

Check the IGP first, because LDP installs labels against IGP next hops and cannot route around an IGP problem: if the loopback is missing or flapping in the OSPF process that builds the table LDP follows, fix that and the label plane usually fixes itself. Then, from the ingress router:

  1. Identify the address the LSP has to reach. For L3VPN that is the BGP next hop, the remote PE loopback.
  2. show mpls forwarding-table <that /32>. No Label means the break is at or below this router. A number or Pop Label means the break is downstream.
  3. show mpls ldp neighbor. Is there an Oper session with the IGP next hop for that /32? If not, you have found it.
  4. If the session is Oper, run show mpls ldp bindings <prefix> <mask> and look for a remote binding from that specific LSR. Session up with no binding from it puts the problem one hop further along.
  5. Move to that next hop and repeat from step 2. The first router reading No Label is the one adjacent to the break.
  6. There, show mpls ldp discovery separates "the far end is not configured" from "something is eating UDP 646."

Two commands per hop, binary answer every time. Here is step 3 on the router adjacent to the break: R2 sits between R1 and R3, and R3's Ethernet0/0 is missing mpls ip.

R2#show mpls ldp neighbor
    Peer LDP Ident: 1.1.1.1:0; Local LDP Ident 2.2.2.2:0
	TCP connection: 1.1.1.1.646 - 2.2.2.2.51092
	State: Oper; Msgs sent/rcvd: 9/9; Downstream
	Up time: 00:00:56
	LDP discovery sources:
	  Ethernet0/0, Src IP addr: 10.0.12.1
        Addresses bound to peer LDP Ident:
          10.0.12.1       1.1.1.1

One peer, not two. An absent neighbor is easy to miss when you are scanning for something wrong rather than something missing, so count peers against MPLS-enabled core links before reading any detail. Then comes the most misleading command in the set:

R2#show mpls interfaces
Interface              IP            Tunnel   BGP Static Operational
Ethernet0/0            Yes (ldp)     No       No  No     Yes
Ethernet0/1            Yes (ldp)     No       No  No     Yes

Both interfaces read Yes (ldp) and Operational Yes. Correct, and useless on its own, because show mpls interfaces only reports your side of the wire. R2 is sending hellos out Ethernet0/1 quite happily and nobody is answering. Plenty of engineers stop here, see two green lines, and conclude the box is healthy. It is. The neighbor is the problem. And here is the fingerprint on a router with no VRF and no BGP anywhere near it:

R2#show mpls forwarding-table
Local      Outgoing   Prefix           Bytes Label   Outgoing   Next Hop
Label      Label      or Tunnel Id     Switched      interface
16         Pop Label  1.1.1.1/32       0             Et0/0      10.0.12.1
17         No Label   3.3.3.3/32       0             Et0/1      10.0.23.2

Both loopbacks are in OSPF with a valid next hop and a valid outgoing interface. 1.1.1.1/32 goes out through the working session and has a label. 3.3.3.3/32 goes out through the dead one and reads No Label. The only difference between those two lines is a binding that never arrived, and on an ingress PE that same condition is what CEF reports as unusable: no label.

The Fix, and the Line That Proves It

Putting mpls ip back on R3's core interface is the whole fix, and the router announces it:

%LDP-5-NBRCHG: LDP Neighbor 3.3.3.3:0 (2) is UP

That message deserves a monitoring rule, because the same one going the other way is usually your only warning before a ticket: IP keeps working throughout and nothing else will fire. The neighbor table confirms it:

R2#show mpls ldp neighbor
    Peer LDP Ident: 1.1.1.1:0; Local LDP Ident 2.2.2.2:0
	TCP connection: 1.1.1.1.646 - 2.2.2.2.51092
	State: Oper; Msgs sent/rcvd: 11/11; Downstream
	  Ethernet0/0, Src IP addr: 10.0.12.1
    Peer LDP Ident: 3.3.3.3:0; Local LDP Ident 2.2.2.2:0
	TCP connection: 3.3.3.3.31330 - 2.2.2.2.646
	State: Oper; Msgs sent/rcvd: 9/9; Downstream
	  Ethernet0/1, Src IP addr: 10.0.23.2
        Addresses bound to peer LDP Ident:
          10.0.23.2       3.3.3.3

Two sessions, both Oper, and the TCP lines show the active-side rule in practice: R2 opened the session to R1 from port 51092, R3 opened the session to R2 from 31330. Higher router ID connects, lower listens. Now the forwarding table:

R2#show mpls forwarding-table
Local      Outgoing   Prefix           Bytes Label   Outgoing   Next Hop
Label      Label      or Tunnel Id     Switched      interface
16         Pop Label  1.1.1.1/32       0             Et0/0      10.0.12.1
17         Pop Label  3.3.3.3/32       0             Et0/1      10.0.23.2

One word changed. No Label became Pop Label for 3.3.3.3/32, with no change to OSPF, to any IP address, or to any routing table in the path. The IP layer was involved in neither the failure nor the fix, which is the whole point.

What This Was Captured On

Both labs ran on CML with iol-xe nodes on IOS XE 17.18.2, which does full LDP including TCP 646 sessions and implicit-null bindings, so this reproduces in a small virtual lab. The three-router topology is R1 to R2 to R3 in a line, OSPF area 0 on the core links and loopbacks, loopbacks 1.1.1.1, 2.2.2.2 and 3.3.3.3 doubling as LDP router IDs, and mpls ip everywhere except R3's Ethernet0/0. Those captures are all from R2, the transit router.

The LDP Failure Checklist

When show mpls ldp neighbor is empty or the session will not reach Oper, the cause is almost always one of these:

mpls ip missing on one side
LDP needs it on both ends of the link. Check show mpls interfaces on each. This is the most common cause by a wide margin.
Router ID not reachable
Discovery is link-local, but the TCP session is built to the router ID. If the peer's LDP ID (usually a loopback) is not in your routing table, discovery succeeds and the session never comes up.
Router ID not pinned to a loopback
Without mpls ldp router-id Loopback0 force, LDP picks the highest interface IP. When that interface flaps, the session resets and every LSP through it rebuilds.
ACL blocking 646
UDP 646 for discovery, TCP 646 for the session, and only the higher-router-ID side ever initiates. An inbound ACL on a core interface that forgets any of that produces a very confusing outage.
MTU mismatch
Labels add 4 bytes each. A 1500-byte core with a two-label stack needs 1508. Symptoms are worse than a clean failure: small packets work, large ones vanish.
Authentication mismatch
If LDP MD5 is configured on one side only, discovery works and the TCP session is refused.

When the Session Is Up but the LSP Is Broken

A subtler class of failure: LDP is Oper on every link, but traffic still fails somewhere in the middle. The tools:

Labelled traceroute is the fastest way to see where the stack falls apart. Healthy, from CE1 across the VPN:

CE1#traceroute 10.20.20.1 source Ethernet0/0
  1 10.20.1.1 2 msec
  2 10.30.30.2 [MPLS: Labels 17/22 Exp 0] 5 msec
  3 10.20.2.1 [MPLS: Label 22 Exp 0] 5 msec
  4 10.20.2.2 6 msec

Hop 2 carries two labels (transport 17, VPN 22). Hop 3 carries one, because the P router popped the transport label (PHP). If a hop that should be labelled shows no label, the LSP breaks there. If the labels stop changing when they should be swapping, you have found your router.

MPLS ping and traceroute test the LSP itself rather than IP:

PE1#ping mpls ipv4 10.255.0.2/32
PE1#traceroute mpls ipv4 10.255.0.2/32

These use LSP echo (RFC 4379) and will tell you the LSP is broken even when the IP path is fine. When you have an IP-works-MPLS-does-not situation, this names the hop in one command instead of six.

Byte counters in show mpls forwarding-table are underrated. Run the command twice with traffic flowing. If the Bytes Switched column is not incrementing on the entry you expect, traffic is not taking the LSP you think it is. (Every counter above reads 0 because those captures came off a lab with no traffic offered; a zero counter in production on a busy LSP is itself a finding.)

FAQ

Does "No Label" always mean LDP is down?

No. It means this router has no usable remote binding for the prefix via its chosen next hop. A dead session is the common cause, but the same output appears when the prefix is not in the IGP, when label filtering excludes it, or when the next hop sits outside the MPLS domain. show mpls ldp bindings tells you which: no LIB entry at all is a different problem from a LIB entry missing one LSR's binding.

My LDP neighbor is up but I have no labels for some prefixes. Why?

LDP only allocates labels for prefixes in the IGP, and by default IOS does not allocate labels for BGP-learned prefixes. If the prefix is not in your IGP, there is no label. Check with show mpls ldp bindings <prefix> <mask>.

Should I filter which prefixes get labels?

In a large core, yes. You only need labels for the PE loopbacks. mpls ldp label allocate global host-routes (or an explicit prefix list) cuts the LIB down dramatically and is standard practice in production.

Does LDP need its own adjacency, or does it follow the IGP?

Both, in a sense. LDP discovers neighbors on directly connected links with UDP hellos, then builds a TCP session to the peer's router ID. But the labels it installs in the forwarding table are chosen based on the IGP's best next hop, so LDP follows the IGP. This is also why an IGP/LDP synchronisation problem after a link comes back can blackhole traffic, and why mpls ldp sync exists.

Can I run MPLS without LDP?

Yes. Segment routing distributes labels in the IGP itself and removes LDP entirely, along with this whole failure mode. See distributing labels in the IGP instead of running LDP.

Key Takeaways

  • Troubleshoot bottom up: interface, IGP, mpls interfaces, LDP session, bindings, forwarding table.
  • A working IGP proves nothing about MPLS. Loopback pings can succeed at 100 percent while the VPN is completely down.
  • State: Oper is the only acceptable LDP neighbor state, and show mpls interfaces only ever proves your own side is configured.
  • show ip cef vrf <name> <prefix> returning unusable: no label is the definitive fingerprint of a broken transport LSP, but it names the symptom, not the location.
  • Walk the path. The first router whose forwarding table reads No Label for the remote loopback is the one adjacent to the break.
  • In the forwarding table, a broken LSP shows as No Label in the Outgoing Label column, not as a missing row.
  • imp-null in the bindings is what triggers penultimate hop popping. It is normal and expected.
  • Pin the LDP router ID to a loopback with force, or an interface flap will reset your sessions.

Next: Troubleshooting MPLS L3VPN for the VPN-layer failures (missing RTs, missing redistribution), or back to the full MPLS cluster guide.

Read next

Terminal card showing a repeating CDP native VLAN mismatch log naming Ethernet0/0 native VLAN 1 against SW2 Ethernet0/0 native VLAN 99
VLANs ·

Native VLAN Mismatch: Read the CDP Log, Fix the Trunk

%CDP-4-NATIVE_VLAN_MISMATCH hands you both interfaces and both native VLANs in one line. The real damage is underneath it: untagged frames get re-homed at the trunk boundary and two VLANs quietly become one. Captured live on IOS XE 17.18.2 in CML.