Label Distribution Protocol (LDP)

Module Introduction

Before you start the hands-on part of this module, you should load the appropriate configuration and verify that the testbed is up and running by executing the corresponding robot file:

student@tour:~/trainings_resources/robot$ robot mpls_ldp/mpls_ldp_setup.robot

We use IS-IS as IGP for the examples and exercises in this module. The choice of IGP is not important for understanding and configuration of LDP. However, if you prefer to run OSPF instead, you can alternatively load the setup using the -v igp:ospf knob:

student@tour:~/trainings_resources/robot$ robot -v igp:ospf mpls_ldp/mpls_ldp_setup.robot

In order to get a better understanding, the lab setup is shown in the picture below.

mpls ldp lab
Figure 1. MPLS LDP Lab Setup

LDP Overview

The MPLS architecture does not mandate a single control plane protocol, allowing network operators the flexibility to choose one that best fits their needs.

Label Distribution Protocol (LDP), defined in RFC 5036, is the most widely used protocol for label distribution in MPLS networks. LDP is a simple signaling protocol used by Label Switching Routers to automatically establish Label Switched Paths across a network.

As its name suggests, LDP is focused solely on distributing label bindings and does not make routing decisions. Instead, it relies on an underlying IGP such as OSPF or IS-IS for routing information. Consequently, LDP-signaled LSPs always follow the IGP-determined shortest path and are constrained to a single autonomous system.

A router will only install a label binding from a peer if that peer is the next hop on the shortest IGP path to the destination. This tight coupling with the IGP means that during IGP reconvergence, traffic may be briefly blackholed or looped.

RBFS supports dual-stack operation, allowing LDP to exchange label bindings over both IPv4 and IPv6 networks.

LDP exchanges information using a common packet structure. The LDP header includes the LDP Identifier. An LDP packet can contain one or more LDP messages, each defined by a message type. Within each message, a type-length-value encoding scheme is used.

There are four categories of LDP messages:

  • Discovery messages (Hello messages) are used to announce and maintain the presence of an LSR in a network.

  • Session messages are used to establish, maintain, and terminate sessions between LDP peers. There are two main session messages, the Initialization and the Keepalive message.

  • Advertisement messages are used to create, change, and delete label mappings for FECs. This group includes the Label Mapping, Label Request, and Label Withdraw message.

  • Error Handling messages (or Notification messages) are used to provide advisory information and to signal error information.

LDP Peers

Two LSRs that use LDP to exchange label bindings are called LDP peers. An LDP peer is identified by an LDP identifier, which is a 6-octet value composed of a 4-octet router ID and a 2-octet label space ID. The label space refers to a range of labels used by the local LSR. There are two types of label spaces:

  • Per-interface label space: Used for interfaces that require interface-specific resources for label allocation, such as ATM VCIs.

  • Per-platform label space: Used when interfaces can share the same label space across the entire platform (e.g., Ethernet interfaces). The per-platform label space always sets the last octet of the LDP identifier to zero, e.g., 192.168.0.1:0.

LDP uses a discovery mechanism to find potential LDP peers. In the basic discovery mechanism, an LSR periodically sends Hello messages as UDP packets to the well-known LDP port 646, using the all routers on this subnet multicast address (224.0.0.2). The LDP Hello message includes the LDP identifier of the label space and the transport address to be used for the LDP session.

Once an LDP neighbor is discovered, an LDP session is established over TCP port 646. This involves exchanging Initialization messages to negotiate session parameters.

There is always one LDP session between two label spaces. If per-platform label space is used, there is only one LDP session between two LSRs independent of the number of links between them. However, for each link there might be a LDP Hello adjacencies.

Exercise 1: Configuring LDP Interfaces

Configure LDP in instance default. Activate LDP on all three interfaces (hostif-0/0/1/0, hostif-0/0/2/0, and lo-0/0/0/0). Are there any LDP neighbors and LDP sessions?

Click to reveal the answer
cfg> set instance default protocol ldp router-id 192.168.0.1
cfg> set instance default protocol ldp interface hostif-0/0/1/0
cfg> set instance default protocol ldp interface hostif-0/0/2/0
cfg> set instance default protocol ldp interface lo-0/0/0/0
cfg> commit

After configuring the LDP interfaces, we can see that there are two LDP neighbors. The exchange of Hello messages have revealed the LSP ID and the transport IP address of both neighbors:

cfg> show ldp neighbor
Instance: default
  Interface/Peer      LDP ID              Transport IP      Up Since                  Expires
  hostif-0/0/1/0      192.168.0.2:0       192.168.0.2       Tue Apr 25 11:40:25       in 12s
  hostif-0/0/2/0      192.168.0.3:0       192.168.0.3       Tue Apr 25 11:40:25       in 12s

The transport IP address is used to setup the LDP session via TCP:

cfg> show ldp session
Instance: default
  LDP ID            Peer IP               State             Up/Down           FECRcvd   FECSent
  192.168.0.2:0     192.168.0.2           Non-Existent      Never             -         -
  192.168.0.3:0     192.168.0.3           Non-Existent      Never             -         -

Although the LDP discovery process was successful in finding LDP neighbors, the LDP session establishment failed due to missing TCP authentication which is an optional feature.

Exercise 2: Configuring LDP TCP Authentication

Configure for both LDP neighbors TCP session authentication with type MD5, key-id 11 and password rtbrick.

Click to reveal the answer
cfg> set instance default tcp authentication LDP
cfg> set instance default tcp authentication LDP type MD5
cfg> set instance default tcp authentication LDP key1-id 11
cfg> set instance default tcp authentication LDP key1-encrypted-text $21e4946e31b406de98b3077aef03ed5a7
cfg> set instance default protocol ldp session ipv4 192.168.0.2 authentication-id LDP
cfg> set instance default protocol ldp session ipv4 192.168.0.3 authentication-id LDP
cfg> commit
cfg> show ldp session
Instance: default
  LDP ID            Peer IP               State             Up/Down           FECRcvd   FECSent
  192.168.0.2:0     192.168.0.2           Operational       0d:00h:01m:02s          7         9
  192.168.0.3:0     192.168.0.3           Operational       0d:00h:01m:04s          7         9

In addition to the basic discovery mechanism, LDP also supports an extended discovery mechanism that enables LDP sessions between non-directly connected LSRs. In this mechanism, an LSR periodically sends LDP Targeted Hello messages to a specific unicast IP address. These Targeted Hellos are sent as UDP packets addressed to the well-known LDP discovery port.

Exercise 3: Configuring Targeted LDP Session

Configure a targeted LDP session to peer 192.168.0.4 using the targeted-neighbor keyword. Set the source address to the loopback address of R1 and re-use the authentication parameters configured in the last exercise.

Click to reveal the answer
cfg> set instance default protocol ldp targeted-neighbor ipv4 192.168.0.4 192.168.0.1
cfg> set instance default protocol ldp session ipv4 192.168.0.4 authentication-id LDP
cfg> commit
cfg> show ldp neighbor
Instance: default
  Interface/Peer      LDP ID              Transport IP              Up Since                  Expires
  192.168.0.4         192.168.0.4:0       192.168.0.4               Thu May 15 08:40:13       in 35s
  hostif-0/0/1/0      192.168.0.2:0       192.168.0.2               Thu May 15 08:35:59       in 10s
  hostif-0/0/2/0      192.168.0.3:0       192.168.0.3               Thu May 15 08:35:59       in 10s
cfg> show ldp session
Instance: default
  LDP ID            Peer IP                   State             Up/Down           FECRcvd   FECSent
  192.168.0.2:0     192.168.0.2               Operational       0d:00h:04m:24s          7        10
  192.168.0.3:0     192.168.0.3               Operational       0d:00h:04m:27s          7        10
  192.168.0.4:0     192.168.0.4               Operational       0d:00h:00m:06s          8        10

LDP Label Exchange

LDP uses a Type Length Value (TLV) format to encode information which is carried in LDP messages, e.g., the Address List TLV that contains a list of all addresses of the LSR. These addresses are compared with the next hop addresses in the unicast routing table to select the correct LSR for packet forwarding.

cfg> show ldp address instance default ipv4
Instance: default, LDP Identifier: 192.168.0.2:0, AFI: ipv4
  172.16.0.2
  192.168.0.2
  172.16.0.13
  172.16.0.25
Instance: default, LDP Identifier: 192.168.0.3:0, AFI: ipv4
  192.168.0.3
  172.16.0.6
  172.16.0.14
  172.16.0.29

The LDP label mapping messages contain at least two TLVs, the FEC TLV and the Label TLV which result in a database that contains label bindings, i.e., a mapping between FECs and labels.

mpls ldp msg
Figure 2. LDP Label Mapping Messages
cfg> show ldp binding
Instance: default, AFI: ipv4
  Prefix                In Label           Out Label          LDP ID             Status
  192.168.0.1/32        -                  3                  -                  Best
                        20010              0                  192.168.0.2:0      Non-best
                        20009              0                  192.168.0.3:0      Non-best
                        20006              0                  192.168.0.4:0      Non-best
  192.168.0.2/32        3                  20004              192.168.0.2:0      Best
                        20001              0                  192.168.0.3:0      Non-best
                        20004              0                  192.168.0.4:0      Non-best
  192.168.0.3/32        3                  20001              192.168.0.3:0      Best
                        20001              0                  192.168.0.2:0      Non-best
                        20003              0                  192.168.0.4:0      Non-best
  192.168.0.4/32        20003              20006              192.168.0.3:0      Best
                        20007              0                  192.168.0.2:0      Best
                        3                  0                  192.168.0.4:0      Non-best
  192.168.0.5/32        20006              20005              192.168.0.2:0      Best
                        20007              0                  192.168.0.3:0      Non-best
                        20002              0                  192.168.0.4:0      Non-best
  192.168.0.6/32        20002              20002              192.168.0.3:0      Best
                        20004              0                  192.168.0.2:0      Non-best
                        20001              0                  192.168.0.4:0      Non-best
Instance: default, AFI: ipv6
  Prefix                In Label           Out Label          LDP ID             Status
  fc00:c0a8::192:168:0:1/128 -                  3                  -                  Best
                        20005              0                  192.168.0.4:0      Non-best
  fc00:c0a8::192:168:0:2/128 3                  0                  192.168.0.2:0      Best
  fc00:c0a8::192:168:0:3/128 3                  0                  192.168.0.3:0      Best
  fc00:c0a8::192:168:0:4/128 3                  20003              192.168.0.4:0      Best

The show ldp binding command offers useful options such as sent or received to view only the label bindings that were advertised to other LDP peers or learned from LDP peers. In addition, the output can be restricted to a particular LDP peer using the ldp-id <peer> filter.

By default, RBFS supports IPv4/IPv6 dual-stack operation. As shown in the CLI output above, label bindings for an IPv6 prefix FEC were learned. If single-stack operation is desired, you need to disable the dual-stack functionality and one of the address families.

Exercise 4: Configuring IPv4 Single-Stack Operation

On R1, disable IPv4/IPv6 dual-stack operation by turning off the dual-stack-interop setting in general, and specifically disabling the IPv6 address family.

Click to reveal the answer
cfg> set instance default protocol ldp dual-stack-interop disable
cfg> set instance default protocol ldp address-family ipv6 status disable
cfg> commit

By default, RBFS only advertises label binding for loopback addresses to it’s neighbors. Some LDP implementations also advertise bindings for directly connected interfaces. If you want to have he same behavior, you need to redistribute these interfaces into LDP.

Exercise 5: Configuring LDP Redistribution

Configure LDP to redistribute all directly connected interfaces. Hint, redistribution is done on a per-address family basis.

Click to reveal the answer
cfg> set instance default protocol ldp address-family ipv4 redistribute direct
cfg> commit
cfg> show ldp binding
Instance: default, AFI: ipv4
  Prefix                In Label           Out Label          LDP ID             Status
  172.16.0.0/30         -                  label:3            -                  Best
  172.16.0.1/32         -                  label:3            -                  Best
                        label:20076        -                  192.168.0.3:0      Non-best
                        label:20069        -                  192.168.0.2:0      Non-best
  <...>

The LDP label bindings are combined with the result of the IGP SPF calculation to create the best path to each destination:

cfg> show ldp route
Instance: default, AFI: ipv4, SAFI: labeled-unicast
  Prefix/Label         Advertised label  Received label    Next Hop          Interface           Metric
  192.168.0.1/32       3                 -                 -                 -                   -
  192.168.0.2/32       20004             -                 172.16.0.2        hostif-0/0/1/0      100
  192.168.0.3/32       20001             -                 172.16.0.6        hostif-0/0/2/0      100
  192.168.0.4/32       20006             20067             172.16.0.2        hostif-0/0/1/0
                                         20066             172.16.0.6        hostif-0/0/2/0      300
  192.168.0.5/32       20005             20065             172.16.0.2        hostif-0/0/1/0      200
  192.168.0.6/32       20002             20071             172.16.0.6        hostif-0/0/2/0      200
Instance: default, AFI: ipv6, SAFI: labeled-unicast
  Prefix/Label         Advertised label  Received label    Next Hop          Interface           Metric
  fc00:c0a8::192:168:0:1/1283                 -                 -            -                   -
Instance: default, AFI: mpls, SAFI: unicast
  Prefix/Label         Advertised label  Received label    Next Hop          Interface           Metric
  20001                -                 -                 172.16.0.6        hostif-0/0/2/0      -
  20001,bos:1          -                 -                 172.16.0.6        hostif-0/0/2/0      -
  20002                -                 20071             172.16.0.6        hostif-0/0/2/0      -
  20002,bos:1          -                 20071             172.16.0.6        hostif-0/0/2/0      -
  20004                -                 -                 172.16.0.2        hostif-0/0/1/0      -
  20004,bos:1          -                 -                 172.16.0.2        hostif-0/0/1/0      -
  20005                -                 20065             172.16.0.2        hostif-0/0/1/0      -
  20005,bos:1          -                 20065             172.16.0.2        hostif-0/0/1/0      -
  20006                -                 20066             172.16.0.6        hostif-0/0/2/0
                                         20067             172.16.0.2        hostif-0/0/1/0      -
  20006,bos:1          -                 20066             172.16.0.6        hostif-0/0/2/0
                                         20067             172.16.0.2        hostif-0/0/1/0      -

The resulting routes are either of type ipv4/ipv6 labeled-unicast or mpls unicast. If the device is an ingress LER, then the labeled-unicast routes are used, i.e., an IPv4 or IPV6 FEC is associated with a LDP-established LSP. In this case the label referred to as Received label is used, because this is the one learned from the downstream neighbor. The labels shown in column Advertised label are the labels allocated by the local router and advertised to its neighbors and are for information only and not relevant during ipv4/ipv6 labeled-unicast route lookup.

If the device is a transit LSR, then the mpls unicast routes are used, i.e., the incoming labeli (see column Prefix/Label) is swapped with the corrsponding label from column Received label.

The resulting entries are used to populate the routing table:

cfg> show route ipv4 labeled-unicast source ldp
Instance: default, AFI: ipv4, SAFI: labeled-unicast
Prefix/Label               Source            Pref    Next Hop            Interface              Label
192.168.0.2/32             ldp               9       172.16.0.2          hostif-0/0/1/0         -
192.168.0.3/32             ldp               9       172.16.0.6          hostif-0/0/2/0         -
192.168.0.4/32             ldp               9       172.16.0.2          hostif-0/0/1/0         20067
                                                     172.16.0.6          hostif-0/0/2/0         20066
192.168.0.5/32             ldp               9       172.16.0.2          hostif-0/0/1/0         20065
192.168.0.6/32             ldp               9       172.16.0.6          hostif-0/0/2/0


cfg> show route mpls label 20002 detail
Instance: default, AFI: mpls, SAFI: unicast
20002
  Source: ldp, Preference: 9
    Next Hop: 172.16.0.6
      Covering prefix: 172.16.0.6/32
      Next Hop type: mpls transit, Next Hop action: None
      Resolved in: default-ipv4-labeled-unicast
      Egress interface: hostif-0/0/2/0, NextHop MAC: 7a:00:3f:c0:00:02
      MPLS-Label: 20071

LDP Settings

Loop Detection

LDP provides an optional loop detection mechanism that can be configured to help prevent routing loops. This mechanism uses two additional TLVs: the Hop Count TLV and the Path Vector TLV. The Hop Count TLV contains the number of LSRs that the message has traversed, while the Path Vector TLV includes a list of these LSRs.

When an LSR receives a Label Mapping or Label Request message from its next hop that either contains a Hop Count TLV exceeding the configured maximum value, or a Path Vector TLV that includes its own LSR ID or exceeds the maximum allowable length, it detects a potential loop. In this case, the LSR considers the message looped and discards it.

Exercise 6: Configuring LDP Loop Detection

Enable LDP loop detection using the set instance default protocol ldp loop-detection command hierarchy. Set the vector-length to 16 and the hop-count limit to 32.

Click to reveal the answer
cfg> set instance default protocol ldp loop-detection status enable
cfg> set instance default protocol ldp loop-detection vector-length 16
cfg> set instance default protocol ldp loop-detection hop-count 32
cfg> commit
cfg> show ldp summary
Instance: default
<...>
  Capabilities:
    IPv6 address family: -  , Graceful restart: False
    Loop detection: True
      Hop count: 32, Vector length: 16
<...>

After configuring LDP loop detection on all LSRs in the network, we can reset a LDP session and inspect the Label Mapping messages:

2025-05-15T10:25:08.039487+0000 7a:fc:da:c0:00:01 > 7a:77:1f:c0:00:01, ethertype IPv4 (0x0800), length 137: (tos 0xc0, ttl 253, id 3563, offset 0, flags [none], proto TCP (6), length 123)
    192.168.0.4.58342 > 192.168.0.1.646: Flags [P.], seq 78804:78867, ack 12250, win 2983, options [nop,nop,md5 shared secret not supplied with -M, can't check - 56f2ae61e34451d618c64cde81d23583], length 63
        LDP, Label-Space-ID: 192.168.0.4:0, pdu-length: 59
          Label Mapping Message (0x0400), length: 49, Message ID: 0x00000112, Flags: [ignore if unknown]
            FEC TLV (0x0100), length: 8, Flags: [ignore and don't forward if unknown]
              Prefix FEC (0x02): IPv4 prefix 192.168.0.1/32
            Generic Label TLV (0x0200), length: 4, Flags: [ignore and don't forward if unknown]
              Label: 20006
            Hop Count TLV (0x0103), length: 1, Flags: [ignore and don't forward if unknown]
              Hop Count: 4                                                               (1)
            Path Vector TLV (0x0104), length: 16, Flags: [ignore and don't forward if unknown]
              Path Vector: 192.168.0.1, 192.168.0.3, 192.168.0.6, 192.168.0.4            (2)
1 After activating the loop detection feature, the hop count TLV is added to the label binding indicating how many LSRs this binding has traversed.
2 The path vector TLV represents a list of all LSRs, that this label binding messages has traversed.

IGP Synchronization

The main purpose of LDP is to establish MPLS LSPs along the shortest path to a destination, as determined by the IGP. Many MPLS services rely on the existence of an end-to-end LSP, which requires all links along the IGP shortest path from the ingress LER to the egress LER to have operational LDP sessions and to have exchanged label bindings.

If any link along this path lacks an operational LDP session, traffic may be blackholed. This is because the IGP continues to forward traffic along what it sees as the best path, even though the corresponding LSP is incomplete.

To prevent this, the IGP (such as OSPF or IS-IS) can advertise the affected link with a maximum metric, effectively removing it from the IGP’s best path calculation until LDP becomes operational. This process is known as LDP IGP synchronization.

Exercise 7: Enabling LDP IGP Synchronization

Enable ldp-synchronization on both core interface on router R1 in the IGP configuration.

Click to reveal the answer
cfg> set instance default protocol isis interface hostif-0/0/1/0 ldp-synchronization enable
cfg> set instance default protocol isis interface hostif-0/0/2/0 ldp-synchronization enable
cfg> set instance default protocol ldp igp-synchronization hold-timer 5
cfg> commit

Now, that we have activated LDP IGP synchronization, let’s have a quick check: From the following output, we can see that the link metric for neighbor R2 is 100.

cfg> show isis database level-2 lsp id 1921.6800.0001.00-00
<...>
    IS Reachability TLVs (22):
      IS neighbor: 1921.6800.0002.00              Metric:      100             (1)
      IS neighbor: 1921.6800.0003.00              Metric:      100
<...>

cfg> clear ldp session instance default peer ldp-id 192.168.0.2:0
LDP session cleared for peer 192.168.0.2
cfg> show isis database level-2 lsp id 1921.6800.0001.00-00
<...>
    IS Reachability TLVs (22):
      IS neighbor: 1921.6800.0002.00              Metric: 16777214             (2)
      IS neighbor: 1921.6800.0003.00              Metric:      100
<...>
1 Metric to reach IS-IS neighbor R2 is 100.
2 IS-IS metric is increased to maximum value during LDP session outage.

After clearing the LDP session, the metric is adjusted in IS-IS as long as the LDP session is not fully operational.

LDP Timer

Hello messages and keepalive messages are sent periodically and it is possible to adjust the corresponding intervals. In general, the default values are suitable for most networks and are designed to ensure stability and interoperability. Adjustments may be justified in special cases, e.g., if faster convergence is required.

The Hello interval and hold-time used in LDP discovery are encoded in Hello messages, so peers can adapt. The Keepalive timer is not negotiated. It is local to each LSR, and affects how quickly each side considers the TCP session dead if no keepalive or other message is received. If keepalive timer values differ, a LSR might tear down the session sooner than the LDP peer expects, leading to unexpected session resets or flapping. Thus, it is very important to keep LDP timers consistent across peers unless there is a specific need to change them.

Exercise 8: Modifying LDP Timers

On R1, set the LDP hello interval to 10s and the hold-time to 30s using the set instance default protocol ldp timer command hierarchy. In addition, set the session keepalive interval to 15s and the timeout to 45s.

Click to reveal the answer
cfg> set instance default protocol ldp timer hello interval 10
cfg> set instance default protocol ldp timer hello hold-time 30
cfg> set instance default protocol ldp timer session keepalive-interval 15
cfg> set instance default protocol ldp timer session keepalive-timeout 45
cfg> commit
cfg> show ldp summary
<...>
  Timers:
    Adjacency:
      Hello: 10s, Holdtime: 30s
    Targeted adjacency:
      Hello: 15s, Holdtime: 45s
    Session:
      Keepalive: 15s, Holdtime: 45s
<...>

Summary

This module outlined the operation and configuration of Label Distribution Protocol (LDP). You should be able to understand how LDP sessions are established and how LDP bindings are exchanged.

If you have completed the exercise, you can check the results by executing

student@tour:~/trainings_resources/robot$ robot mpls_ldp/mpls_ldp_verify.robot