What Is LDP
LDP (Label Distribution Protocol, RFC 5036) distributes MPLS labels to neighbouring routers. The routes themselves come from OSPF or IS-IS; LDP carries only the mapping that says “this is the label I use for that prefix”. This article explains how LDP finds a neighbour, builds a session and advertises labels, then follows a full establishment packet by packet in an IOS XR (XRd) lab. Label operations are covered in MPLS Label Operations (push / swap / pop) and PHP.
The three stages of LDP
LDP works in three stages.
| Stage | Transport | What happens |
|---|---|---|
| Discovery | UDP 646, sent to 224.0.0.2 | Hellos find neighbouring LSRs |
| Session | TCP 646 | A TCP connection is opened to the peer and parameters are agreed |
| Advertisement | The same TCP connection | Addresses and label mappings are sent |
Only the Hello is multicast. Once the peer is known, everything moves to a unicast TCP connection. The side with the higher transport address opens the connection; the lower one listens.
The LDP Identifier
LDP identifies a peer by its LDP Identifier, six octets written as <LSR Id>:<label space>.
The first four octets identify the router and are normally set to the same value as the router ID. The last two are the label space number, where 0 means a single label space for the whole platform. A non-zero value is used when label spaces are kept per interface.
LDP messages
RFC 5036 defines eleven messages. The Type is two octets and each message has its own number.
| Message | Type | Role |
|---|---|---|
| Notification | 0x0001 | Reports an error or the end of a session |
| Hello | 0x0100 | Finds neighbours. The only message sent over UDP |
| Initialization | 0x0200 | Proposes the session parameters |
| KeepAlive | 0x0201 | Keeps the session alive |
| Address | 0x0300 | Announces the IP addresses the router owns |
| Address Withdraw | 0x0301 | Withdraws an announced address |
| Label Mapping | 0x0400 | Announces a prefix-to-label mapping |
| Label Request | 0x0401 | Requests a label (used by Downstream-on-Demand) |
| Label Abort Request | 0x0402 | Cancels an outstanding request |
| Label Withdraw | 0x0403 | Withdraws a label that was advertised |
| Label Release | 0x0404 | Returns a label that was received |
The withdraw and release messages are used when a route disappears or a session goes down.
Address is needed because the LDP Identifier and the IP address a label is attached to are different things. The receiver uses the list learned from Address to work out which LDP peer a given next hop belongs to.
How labels are advertised
The IOS XR default is Downstream-Unsolicited: a router advertises its labels without waiting to be asked. The alternative, Downstream-on-Demand, advertises only on request and uses Label Request. The difference between the modes is covered in a separate article.
When a session comes up, the router first sends Address with its own addresses, then one Label Mapping for every prefix it holds. After that only changes are sent, and KeepAlive maintains the connection.
Discovery and Session are counted differently
Of the three stages, Discovery is per link and Session is per peer. The two do not correspond, so the numbers diverge as soon as there is more than one link.
| Item | Discovery | Session |
|---|---|---|
| Unit | One per interface | One per LDP peer |
| Address used | The interface IP address | The transport address, normally a loopback |
| Transport | UDP 646 multicast | TCP 646 unicast |
| How the peer is chosen | Found by multicast | Connect to the transport address learned from Hello |
| Role | Learn which LSR is next door | Build a reliable channel for carrying labels |
| Time before it is declared down | Hello hold time, 15 seconds | Session hold time, 180 seconds |
Connect PE1 and P1 with two links and there are two Discoveries but one Session. LDP identifies a peer by its LDP Identifier, which is a label space. When the label space is :0, one per platform, the same label is valid whichever link it arrived on, so there is no reason to split the session.
The asymmetry matters operationally. Losing one link does not bring the session down. One Discovery Source disappears and the TCP connection continues over what remains, so labels are not redistributed on every link failure. Conversely, when every link goes down the Discovery Sources reach zero and the session ends.
Lab verification
Lab setup
CE1 — PE1 — P1 — P2 — PE2 — CE2 are connected in a line. PE1 / P1 / P2 / PE2 in AS 65001 form the MPLS network, distributing routes with OSPF (area 0, network point-to-point on every link) and labels with LDP. CE3 and CE4 are customers in VRF CUST-A.
| Router | Role | Lo0 | Links |
|---|---|---|---|
| CE1 | Customer side (AS 65101), advertises 192.168.1.0/24 | 1.1.1.1/32 | Gi0/0/0/0 10.1.2.1 |
| PE1 | Ingress / egress LSR (AS 65001) | 2.2.2.2/32 | Gi0/0/0/0 10.1.2.2 / Gi0/0/0/1 10.2.3.2 |
| P1 | Transit LSR | 3.3.3.3/32 | Gi0/0/0/0 10.2.3.3 / Gi0/0/0/1 10.3.4.3 |
| P2 | Transit LSR | 4.4.4.4/32 | Gi0/0/0/0 10.3.4.4 / Gi0/0/0/1 10.4.5.4 |
| PE2 | Ingress / egress LSR (AS 65001) | 5.5.5.5/32 | Gi0/0/0/0 10.4.5.5 / Gi0/0/0/1 10.5.6.5 |
| CE2 | Customer side (AS 65102), advertises 192.168.6.0/24 | 6.6.6.6/32 | Gi0/0/0/0 10.5.6.6 |
| CE3 | Customer side in VRF CUST-A (AS 65107), advertises 192.168.7.0/24 | 7.7.7.7/32 | Gi0/0/0/0 10.2.7.7 (PE1 Gi0/0/0/2) |
| CE4 | Customer side in VRF CUST-A (AS 65108), advertises 192.168.8.0/24 | 8.8.8.8/32 | Gi0/0/0/0 10.5.8.8 (PE2 Gi0/0/0/2) |
The single link PE1 - P1 is captured to follow the LDP exchange packet by packet.
Verification steps
| STEP | Change | What it shows |
|---|---|---|
| 0 | Initial state | Steady-state Hellos and KeepAlives, the LDP Identifiers and the bindings |
| 1 | Remove interface Gi0/0/0/1 from mpls ldp on PE1, then put it back | A full establishment captured in one pcap |
| 2 | Configure LDP authentication on PE1 only | The session cannot come up while the Hellos keep flowing |
| 3 | Remove the authentication | The state returns to that of STEP 0 |
| 4 | Add a second PE1 - P1 link | Discovery grows to two while the Session stays at one |
STEP 0: Initial state
The neighbour as seen from PE1. Its own LDP Identifier is 2.2.2.2:0 and the peer is 3.3.3.3:0.
Local LDP Identifier: 2.2.2.2:0
Discovery Sources:
Interfaces:
GigabitEthernet0/0/0/1 : xmit/recv
VRF: 'default' (0x60000000)
LDP Id: 3.3.3.3:0, Transport address: 3.3.3.3
Hold time: 15 sec (local:15 sec, peer:15 sec)
Established: Sep 10 14:56:38.298 (08:28:02 ago)xmit/recv means Hellos are being sent and received. The hold time is 15 seconds; if no Hello arrives within it, the neighbour is considered lost.
The session side is TCP. show mpls ldp neighbor detail shows both ends of the connection.
Peer LDP Identifier: 3.3.3.3:0
TCP connection: 3.3.3.3:63514 - 2.2.2.2:646
Graceful Restart: No
Session Holdtime: 180 sec
State: Oper; Msgs sent/rcvd: 590/590; Downstream-Unsolicited
Up time: 08:28:01
LDP Discovery Sources:
IPv4: (1)
GigabitEthernet0/0/0/1
IPv6: (0)
Addresses bound to this peer:
IPv4: (3)
3.3.3.3 10.2.3.3 10.3.4.3
IPv6: (0)
Peer holdtime: 180 sec; KA interval: 60 sec; Peer state: EstabP1 connected from port 63514 and PE1 is listening on 646. The transport addresses are 3.3.3.3 and 2.2.2.2, so the higher one, P1, is the side that connects. Addresses bound to this peer is the list learned from the Address message.
The labels advertised and received appear in show mpls ldp bindings.
2.2.2.2/32, rev 7
Local binding: label: ImpNull
Remote bindings: (1 peers)
Peer Label
----------------- ---------
3.3.3.3:0 24002
3.3.3.3/32, rev 11
Local binding: label: 24000
Remote bindings: (1 peers)
Peer Label
----------------- ---------
3.3.3.3:0 ImpNull For its own Loopback0, 2.2.2.2/32, PE1 advertises ImpNull (implicit-null): it is the egress, so it asks the previous hop to remove the label.
In the capture, Hellos flow every five seconds as UDP 646 multicast and KeepAlives every sixty seconds as TCP 646 unicast.
STEP 1: Take LDP down and bring it back
interface GigabitEthernet0/0/0/1 was removed from mpls ldp on PE1 and put back 49 seconds later. The syslog holds exactly one down and one up.
RP/0/RP0/CPU0:Sep 10 23:30:49.514 UTC: mpls_ldp[1178]: %ROUTING-LDP-5-NBR_CHANGE : VRF 'default' (0x60000000), Neighbor 3.3.3.3:0 is DOWN (LDP IPv4 disabled on interface)
RP/0/RP0/CPU0:Sep 10 23:31:38.596 UTC: mpls_ldp[1178]: %ROUTING-LDP-5-NBR_CHANGE : VRF 'default' (0x60000000), Neighbor 3.3.3.3:0 is UP (IPv4 connection) The capture holds the whole establishment in consecutive frames. No.39 through No.47 are one round.
39 58.809799000 3.3.3.3 2.2.2.2 28509 → 646 [SYN] Seq=0 Win=16384 Len=0 MSS=1240 WS=1
41 58.830371000 2.2.2.2 3.3.3.3 646 → 28509 [SYN, ACK] Seq=0 Ack=1 Win=16384 Len=0 MSS=1240 WS=1
42 58.833393000 3.3.3.3 2.2.2.2 28509 → 646 [ACK] Seq=1 Ack=1 Win=16384 Len=0
43 58.834409000 3.3.3.3 2.2.2.2 Initialization Message
44 58.939718000 2.2.2.2 3.3.3.3 Initialization Message Keep Alive Message
45 58.943971000 3.3.3.3 2.2.2.2 Keep Alive Message
46 59.021589000 2.2.2.2 3.3.3.3 Address Message Label Mapping Message Label Mapping Message Label Mapping Message Label Mapping Message Label Mapping Message Label Mapping Message Label Mapping Message Label Mapping Message
47 59.024623000 3.3.3.3 2.2.2.2 Address Message Label Mapping Message Label Mapping Message Label Mapping Message Label Mapping Message Label Mapping Message Label Mapping Message Label Mapping Message The TCP three-way handshake completes, Initialization flows in both directions, KeepAlive confirms it, and Address plus Label Mapping follow. From the SYN to the label advertisement takes 0.2 seconds.
Inside the Initialization are the LDP Identifier and the session parameters.
Internet Protocol Version 4, Src: 3.3.3.3, Dst: 2.2.2.2
Version: 1
PDU Length: 68
LSR ID: 3.3.3.3
Label Space ID: 0
Message Type: Initialization Message (0x200)
Session Protocol Version: 1
Session KeepAlive Time: 180
Session Max PDU Length: 0Session KeepAlive Time: 180 is the hold time being proposed. The lower of the two values is used, and a third of it, 60 seconds, becomes the KeepAlive interval.
No.46 is an Address plus eight Label Mappings inside a single TCP segment.
Download the pcap of the packet mentioned above (No.46, Address + 8 Label Mappings)A Notification is sent when the session goes down. No.12 carried two of them.
Message Type: Notification Message (0x1)
..00 0000 0000 0000 0000 0000 0000 1001 = Status Data: Hold Timer Expired (0x9)
Message Type: Notification Message (0x1)
..00 0000 0000 0000 0000 0000 0000 1010 = Status Data: Shutdown (0xA)Six messages were observed in this capture, and their Type values match the RFC 5036 definitions.
| Observed message | Type |
|---|---|
| Notification | 0x0001 |
| Hello | 0x0100 |
| Initialization | 0x0200 |
| KeepAlive | 0x0201 |
| Address | 0x0300 |
| Label Mapping | 0x0400 |
Label Request, Label Abort Request, Label Withdraw, Label Release and Address Withdraw were not observed in this lab.
STEP 2: Configure authentication on one side only
LDP authentication was configured on PE1 only. This state shows clearly that Discovery and Session are separate stages.
Local LDP Identifier: 2.2.2.2:0
Discovery Sources:
Interfaces:
GigabitEthernet0/0/0/1 : xmit/recv
VRF: 'default' (0x60000000)
LDP Id: 3.3.3.3:0, Transport address: 3.3.3.3
Hold time: 15 sec (local:15 sec, peer:15 sec)
Established: Sep 10 23:31:38.337 (00:14:27 ago)Hellos are not authenticated, so the state stays xmit/recv and the peer’s LDP Identifier is still visible. Even so there are no neighbours, because the TCP connection cannot be built. The capture holds nothing but retransmitted SYNs.
9 11.273014000 2.2.2.2 3.3.3.3 646 → 28509 [FIN, ACK] Seq=1 Ack=19 Win=15867 Len=0
11 11.279687000 3.3.3.3 2.2.2.2 28509 → 646 [FIN, ACK] Seq=19 Ack=2 Win=15867 Len=0
16 13.302019000 3.3.3.3 2.2.2.2 29559 → 646 [SYN] Seq=0 Win=16384 Len=0 MSS=1240 WS=1
18 15.303119000 3.3.3.3 2.2.2.2 [TCP Retransmission] 29559 → 646 [SYN] Seq=0 Win=16384 Len=0 MSS=1240 WS=1
21 19.303361000 3.3.3.3 2.2.2.2 [TCP Retransmission] 29559 → 646 [SYN] Seq=0 Win=16384 Len=0 MSS=1240 WS=1
28 27.303824000 3.3.3.3 2.2.2.2 [TCP Retransmission] 29559 → 646 [SYN] Seq=0 Win=16384 Len=0 MSS=1240 WS=1PE1 discards the SYNs it receives, and the syslog gives the reason.
RP/0/RP0/CPU0:Sep 10 23:41:19.620 UTC: mpls_ldp[1178]: %ROUTING-LDP-5-NBR_CHANGE : VRF 'default' (0x60000000), Neighbor 3.3.3.3:0 is DOWN (Session MD5 password changed)
RP/0/RP0/CPU0:Sep 10 23:41:21.652 UTC: tcp[134]: %IP-TCP-3-BADAUTH : Invalid MD5 digest from 3.3.3.3:29559 to 2.2.2.2:646 for vrf:default (0x60000000) LDP authentication is an MD5 signature on the TCP connection, so the failure happens at the TCP stage and not a single LDP message is exchanged. Configuring authentication itself is covered in a separate article.
STEP 3: Remove the authentication
Removing the configuration brings the session back and the bindings return to eight entries, the same state as STEP 0.
STEP 4: Add a second PE1 - P1 link
PE1 Gi0/0/0/3 and P1 Gi0/0/0/2 were connected as 10.2.13.0/24 with OSPF and LDP enabled on both. The OSPF cost of the second link is 100, so forwarding still takes the first one.
PE1 now has two Discovery Sources.
Local LDP Identifier: 2.2.2.2:0
Discovery Sources:
Interfaces:
GigabitEthernet0/0/0/1 : xmit/recv
VRF: 'default' (0x60000000)
LDP Id: 3.3.3.3:0, Transport address: 3.3.3.3
Hold time: 15 sec (local:15 sec, peer:15 sec)
Established: Sep 11 02:59:52.792 (00:10:03 ago)
GigabitEthernet0/0/0/3 : xmit/recv
VRF: 'default' (0x60000000)
LDP Id: 3.3.3.3:0, Transport address: 3.3.3.3
Hold time: 15 sec (local:15 sec, peer:15 sec)
Established: Sep 11 02:59:52.883 (00:10:03 ago)Both point at the same peer, 3.3.3.3:0, with the same transport address. The session, meanwhile, is still a single one.
Peer LDP Identifier: 3.3.3.3:0
TCP connection: 3.3.3.3:54016 - 2.2.2.2:646
Graceful Restart: No
Session Holdtime: 180 sec
State: Oper; Msgs sent/rcvd: 22/21; Downstream-Unsolicited
Up time: 00:09:50
LDP Discovery Sources:
IPv4: (2)
GigabitEthernet0/0/0/1
GigabitEthernet0/0/0/3
IPv6: (0)
Addresses bound to this peer:
IPv4: (4)
3.3.3.3 10.2.3.3 10.2.13.3 10.3.4.3
IPv6: (0)
Peer holdtime: 180 sec; KA interval: 60 sec; Peer state: EstabThere is one Peer LDP Identifier and one TCP connection, and beneath them LDP Discovery Sources: IPv4: (2) lists both interfaces. Two Discoveries collapsing into one Session is readable from this single screen. Addresses bound to this peer grew from three to four because the Address message carried 10.2.13.3, the address of the second link.
Putting OSPF beside LDP makes the difference in counting clear.
| Protocol | Adjacencies with P1 seen from PE1 |
|---|---|
| OSPF | 2, one per link |
| LDP Discovery | 2, one Hello per link |
| LDP Session | 1, one per peer |
Capturing both links at once separates what flows where.
| Link | Hello (UDP 646) | Packets on TCP 646 |
|---|---|---|
| First (10.2.3.0/24) | 65 | 12 |
| Second (10.2.13.0/24) | 64 | 0 |
Hellos flow on both links and TCP only on the first. LDP is enabled on the second link and the neighbour is visible there, but the session is already established over the first one, so it goes unused. Which link is chosen is settled when the session comes up.
Captures
The single link PE1 - P1 was captured, with no filter.
STEP 0 steady state
STEP 1 teardown and establishment
STEP 2 authentication mismatch
STEP 4 first link (10.2.3.0/24)
STEP 4 second link (10.2.13.0/24)
Verification config and show output
The following file types were collected from all eight routers at every STEP, split per router. The verification config is these ..._run.txt files (the final state is the one from the last STEP).
| File | Contents |
|---|---|
..._show.txt | show version / show interface description / show route and the OSPF, LDP, MPLS forwarding and BGP set |
..._log.txt | show logging limited to that STEP |
..._run.txt | show running-config at that STEP (the verification config for that STEP) |
..._trace.txt | LDP and LSD traces on the four core routers |
STEP 0: Initial state
| Router | show | syslog | running-config | trace |
|---|---|---|---|---|
| CE1 | show | log | run | - |
| PE1 | show | log | run | trace |
| P1 | show | log | run | trace |
| P2 | show | log | run | trace |
| PE2 | show | log | run | trace |
| CE2 | show | log | run | - |
| CE3 | show | log | run | - |
| CE4 | show | log | run | - |
STEP 1: Take LDP down and bring it back
| Router | show | syslog | running-config | trace |
|---|---|---|---|---|
| CE1 | show | log | run | - |
| PE1 | show | log | run | trace |
| P1 | show | log | run | trace |
| P2 | show | log | run | trace |
| PE2 | show | log | run | trace |
| CE2 | show | log | run | - |
| CE3 | show | log | run | - |
| CE4 | show | log | run | - |
STEP 2: Configure authentication on one side only
| Router | show | syslog | running-config | trace |
|---|---|---|---|---|
| CE1 | show | log | run | - |
| PE1 | show | log | run | trace |
| P1 | show | log | run | trace |
| P2 | show | log | run | trace |
| PE2 | show | log | run | trace |
| CE2 | show | log | run | - |
| CE3 | show | log | run | - |
| CE4 | show | log | run | - |
STEP 3: Remove the authentication (final state)
| Router | show | syslog | running-config | trace |
|---|---|---|---|---|
| CE1 | show | log | run | - |
| PE1 | show | log | run | trace |
| P1 | show | log | run | trace |
| P2 | show | log | run | trace |
| PE2 | show | log | run | trace |
| CE2 | show | log | run | - |
| CE3 | show | log | run | - |
| CE4 | show | log | run | - |
| STEP 4: Add a second PE1 - P1 link |
| Router | show | syslog | running-config | trace |
|---|---|---|---|---|
| CE1 | show | log | run | - |
| PE1 | show | log | run | trace |
| P1 | show | log | run | trace |
| P2 | show | log | run | trace |
| PE2 | show | log | run | trace |
| CE2 | show | log | run | - |
| CE3 | show | log | run | - |
| CE4 | show | log | run | - |
References
| RFC | Title | Summary |
|---|---|---|
| RFC 5036 | LDP Specification | Discovery (section 2.4), the session establishment state machine (2.5.4), port 646 for both TCP and UDP (3.10.1) and the message Type values. |
| RFC 3031 | Multiprotocol Label Switching Architecture | Where a label distribution protocol fits. |
Book: Luc De Ghein, MPLS Fundamentals (Cisco Press, 2006), Chapter 4