1. Topology and Goal

There are very few Turkish resources on Nokia SR OS, so I’m writing down what I learn in the lab. In this post we build a simple MPLS core and show two things:

  1. How do an IGP and LDP work together? OSPF teaches the loopbacks to each other, and LDP puts labels on top of those routes to build an LSP (transport tunnel) between the PEs.
  2. What is the label for? Inside the core, the packet moves by label, not by IP lookup. We’ll see step by step where the label is attached (push), where it is changed (swap) and where it is removed (pop).

Cargo analogy

Think of IP routing as reading the address on a parcel at every sorting hub and asking “where was this going?”. In MPLS, a barcode is stuck on the parcel at the first hub. The hubs in between don’t read the address, they just look at the barcode and steer the belt. LDP is the protocol where neighboring hubs tell each other “this barcode goes to this address”.

Topology

LDP Lab Topology

DeviceRoleLoopback (System)
CE1Customer edge1.1.1.1
PE1Provider Edge2.2.2.2
PProvider (core)3.3.3.3
PE2Provider Edge4.4.4.4
CE2Customer edge5.5.5.5
LinkSubnetInterfaces
CE1 - PE1192.168.10.0/24CE1 1/1/1 (.1) - PE1 1/1/1
PE1 - P10.23.23.0/24PE1 1/1/2 (.2) - P 1/1/2 (.3)
P - PE210.34.34.0/24P 1/1/1 (.3) - PE2 1/1/1 (.4)
PE2 - CE2192.168.10.0/24PE2 1/1/2 - CE2 1/1/2 (.2)

On the provider side (PE1, P, PE2) the IGP is OSPF. Our goal is to build an LSP with LDP between PE1 (2.2.2.2) and PE2 (4.4.4.4).

2. Starting Point: OSPF and Loopback Reachability

LDP has no path-finding ability of its own. When it distributes labels it looks at the routes built by the IGP: it gets the answer to “who is the next hop for this prefix?” from the routing table. So the IGP has to work properly first. Here all three routers run OSPF in a single area (0.0.0.0).

OSPF configuration

The structure is the same on all three routers: a single area (0.0.0.0), the system interface (to advertise the loopback) and the core-facing interfaces. We made the links point-to-point, so there is no DR/BDR election and the adjacency comes up faster.

PE1

A:PE1-R2>config>router>ospf# info
----------------------------------------------
            area 0.0.0.0
                interface "system"
                    no shutdown
                exit
                interface "toP"
                    interface-type point-to-point
                    no shutdown
                exit
            exit
            no shutdown
----------------------------------------------

P

A:P-R3>config>router>ospf# info
----------------------------------------------
            area 0.0.0.0
                interface "system"
                    no shutdown
                exit
                interface "toPE1"
                    interface-type point-to-point
                    no shutdown
                exit
                interface "toPE2"
                    interface-type point-to-point
                    no shutdown
                exit
            exit
            no shutdown

PE2

A:PE2-R4>config>router>ospf# info
----------------------------------------------
            area 0.0.0.0
                interface "system"
                    no shutdown
                exit
                interface "toP"
                    interface-type point-to-point
                    no shutdown
                exit
            exit
            no shutdown

We did not add the CE-facing interfaces (PE1 1/1/1, PE2 1/1/2) to OSPF. The customer side stays out of the provider IGP.

OSPF neighbors

All adjacencies on PE1, P and PE2 are in the Full state:

A:PE1-R2# show router ospf neighbor

===============================================================================
Rtr Base OSPFv2 Instance 0 Neighbors
===============================================================================
Interface-Name                   Rtr Id          State      Pri  RetxQ   TTL
   Area-Id
-------------------------------------------------------------------------------
toP                              3.3.3.3         Full       1    0       31
   0.0.0.0
-------------------------------------------------------------------------------
No. of Neighbors: 1
===============================================================================
A:P-R3# show router ospf neighbor

===============================================================================
Rtr Base OSPFv2 Instance 0 Neighbors
===============================================================================
Interface-Name                   Rtr Id          State      Pri  RetxQ   TTL
   Area-Id
-------------------------------------------------------------------------------
toPE1                            2.2.2.2         Full       1    0       33
   0.0.0.0
toPE2                            4.4.4.4         Full       1    0       36
   0.0.0.0
-------------------------------------------------------------------------------
No. of Neighbors: 2
A:PE2-R4# show router ospf neighbor

===============================================================================
Rtr Base OSPFv2 Instance 0 Neighbors
===============================================================================
Interface-Name                   Rtr Id          State      Pri  RetxQ   TTL
   Area-Id
-------------------------------------------------------------------------------
toP                              3.3.3.3         Full       1    0       35
   0.0.0.0
-------------------------------------------------------------------------------
No. of Neighbors: 1

Since P sits in the middle it has two neighbors (PE1 and PE2), while each edge PE has just one.

Route table

Let’s look at PE1’s route table:

A:PE1-R2# show router route-table

===============================================================================
Route Table (Router: Base)
===============================================================================
Dest Prefix[Flags]                            Type    Proto     Age        Pref
      Next Hop[Interface Name]                                    Metric
-------------------------------------------------------------------------------
2.2.2.2/32                                    Local   Local     00h01m45s  0
       system                                                       0
3.3.3.3/32                                    Remote  OSPF      00h00m51s  10
       10.23.23.3                                                   100
4.4.4.4/32                                    Remote  OSPF      00h00m31s  10
       10.23.23.3                                                   200
10.23.23.0/24                                 Local   Local     00h00m55s  0
       toP                                                          0
10.34.34.0/24                                 Remote  OSPF      00h00m51s  10
       10.23.23.3                                                   200
-------------------------------------------------------------------------------
No. of Routes: 5

Pay attention here: PE1 learned PE2’s loopback (4.4.4.4/32) via OSPF, the next hop is 10.23.23.3 (the P router) and the metric is 200 (two hops, 100 per hop). The FECs LDP will distribute labels for are exactly these loopback prefixes.

But at this point we have IP reachability and no MPLS yet. A packet from PE1 to 4.4.4.4 is forwarded at P with a normal IP lookup. In the next section we’ll turn LDP on and see how labels get layered on top of this table.

3. LDP Configuration

The LDP configuration is actually very short. All we have to do is enable LDP on the router and tell it which interfaces to look for neighbors on. We only add the core-facing interfaces, we don’t enable LDP on the CE-facing ones. There is no point in giving labels to the customer.

When establishing a session, LDP uses the system (loopback) address by default. That means the two routers must be able to reach each other’s loopbacks. We made sure of this with OSPF in the previous section, and this is exactly why LDP needs an IGP.

When LDP is enabled, the router creates every interface under interface-parameters as dual-stack. In the output we see the ipv4 block and the IPv6 FECs disabled (disable) under fec-type-capability. We only use IPv4, so this part doesn’t concern us. The targeted-session block at the bottom is for remote (loopback-to-loopback) LDP sessions, which we’ll need on the service side.

PE1

A:PE1-R2>config>router>ldp# info
----------------------------------------------
            interface-parameters
                interface "toP" dual-stack
                    ipv4
                        fec-type-capability
                            prefix-ipv6 disable
                            p2mp-ipv6 disable
                        exit
                        no shutdown
                    exit
                    no shutdown
                exit
            exit
            targeted-session
            exit
            no shutdown
----------------------------------------------

P

A:P-R3>config>router>ldp# info
----------------------------------------------
            interface-parameters
                interface "toPE1" dual-stack
                    ipv4
                        fec-type-capability
                            prefix-ipv6 disable
                            p2mp-ipv6 disable
                        exit
                        no shutdown
                    exit
                    no shutdown
                exit
                interface "toPE2" dual-stack
                    ipv4
                        fec-type-capability
                            prefix-ipv6 disable
                            p2mp-ipv6 disable
                        exit
                        no shutdown
                    exit
                    no shutdown
                exit
            exit
            targeted-session
            exit
            no shutdown
----------------------------------------------

PE2

A:PE2-R4>config>router>ldp# info
----------------------------------------------
            interface-parameters
                interface "toP" dual-stack
                    ipv4
                        fec-type-capability
                            prefix-ipv6 disable
                            p2mp-ipv6 disable
                        exit
                        no shutdown
                    exit
                    no shutdown
                exit
            exit
            targeted-session
            exit
            no shutdown
----------------------------------------------

In short, we did two things on each router: enabled LDP with no shutdown and added the core-facing interfaces under interface-parameters. That’s one interface on the PEs and two on P.

4. Verifying LDP

The configuration is done. Now we verify that LDP is really working in three steps: neighbor discovery (hello adjacency), label distribution (bindings) and the resulting tunnel (tunnel-table). I’m taking the outputs from PE1.

Hello adjacency

LDP first finds its neighbor by sending hello packets out of the connected interfaces. The Estab state shows that PE1 has established its adjacency with P:

A:PE1-R2# show router ldp discovery

===============================================================================
LDP IPv4 Hello Adjacencies
===============================================================================
Interface Name                   Local Addr                              State
AdjType                          Peer Addr
-------------------------------------------------------------------------------
toP                              2.2.2.2:0                               Estab
link                             3.3.3.3:0

-------------------------------------------------------------------------------
No. of IPv4 Hello Adjacencies: 1
===============================================================================

AdjType is link, a directly connected adjacency. The neighbor’s address is 3.3.3.3:0, so the LDP session is established with P’s loopback address. (The IPv6 adjacency table is empty because we only use IPv4.)

Label bindings

After the adjacency, the routers send each other “use this label for this prefix”. The IPv4 prefix bindings on PE1:

A:PE1-R2# show router ldp bindings

===============================================================================
LDP IPv4 Prefix Bindings
===============================================================================
Prefix                                      IngLbl                    EgrLbl
Peer                                        EgrIntf/LspId
EgrNextHop
-------------------------------------------------------------------------------
2.2.2.2/32                                  131071U                     --
3.3.3.3:0                                     --
  --

3.3.3.3/32                                    --                      131071
3.3.3.3:0                                   1/1/2
10.23.23.3

4.4.4.4/32                                  131069N                   131069
3.3.3.3:0                                   1/1/2
10.23.23.3

-------------------------------------------------------------------------------
No. of IPv4 Prefix Bindings: 3
===============================================================================

The real output also has IPv6, P2MP and service FEC tables. All of them say No Matching Entries Found, so I cut them here.

How to read the columns:

  • IngLbl (ingress label): The label this router gives to its neighbor: “if you want to reach this prefix, come to me with this label”.
  • EgrLbl (egress label): The label the neighbor gives to this router: “send to me with this label for this prefix”.
  • U / N: U means the label is in use, N means not in use.

131071 is a special value here: implicit null. It means “this prefix is mine, pop the label and send it”. PE1 gave 131071 to P for its own loopback (2.2.2.2/32). P gave PE1 131071 for its own loopback (3.3.3.3/32). We’ll see why this matters in section 5.

The egress label PE1 will use for 4.4.4.4/32 is 131069, given by P.

Tunnel table

Once the labels are distributed, LDP creates a tunnel for each FEC and writes it into the tunnel-table:

A:PE1-R2# show router tunnel-table

===============================================================================
IPv4 Tunnel Table (Router: Base)
===============================================================================
Destination       Owner     Encap TunnelId  Pref     Nexthop        Metric
-------------------------------------------------------------------------------
3.3.3.3/32        ldp       MPLS  65537     9        10.23.23.3     100
4.4.4.4/32        ldp       MPLS  65538     9        10.23.23.3     200
-------------------------------------------------------------------------------
Flags: B = BGP backup route available
       E = inactive best-external BGP route
===============================================================================

Here is what we were looking for: there is an LDP LSP from PE1 to PE2’s loopback (4.4.4.4/32). Owner ldp, encapsulation MPLS, next hop P. OSPF decides the path of this tunnel (the metric is still 200), and LDP puts the label on it. So the IGP picks the path, LDP distributes labels along it.

5. Push / Swap / Pop

Now we look at what the label does hop by hop. For that we list the active bindings (the ones installed in the FIB and in use) on the three routers:

show router ldp bindings active

In the output, the Op column tells us what that router does with the label.

Three operations

OperationWhat it doesCargo analogy
PushAdds a label to the packetSticking a barcode on the parcel at the departure hub
SwapReplaces the incoming label with the label given by the next routerPeeling off the old barcode at an intermediate hub and sticking the new one the next hub will read
PopRemoves the labelRemoving the barcode at the delivery hub and delivering by the address

Key point: these operations are done for the LSP between the PEs. Only the ingress PE puts the label on the packet. The P router in the middle (transit) doesn’t look at the IP address, it only looks at the label and swaps it. The egress side removes the label.

Active binding outputs

PE1

A:PE1-R2# show router ldp bindings active

LDP IPv4 Prefix Bindings (Active)
===============================================================================
Prefix                                      Op              IngLbl    EgrLbl
EgrNextHop                                  EgrIf/LspId
-------------------------------------------------------------------------------
2.2.2.2/32                                  Pop             131071      --
  --                                          --

3.3.3.3/32                                  Push              --      131071
10.23.23.3                                  1/1/2

4.4.4.4/32                                  Push              --      131069
10.23.23.3                                  1/1/2

4.4.4.4/32                                  Swap            131069    131069
10.23.23.3                                  1/1/2

-------------------------------------------------------------------------------

P

A:P-R3# show router ldp bindings active

LDP IPv4 Prefix Bindings (Active)
===============================================================================
Prefix                                      Op              IngLbl    EgrLbl
EgrNextHop                                  EgrIf/LspId
-------------------------------------------------------------------------------
2.2.2.2/32                                  Push              --      131071
10.23.23.2                                  1/1/2

2.2.2.2/32                                  Swap            131070    131071
10.23.23.2                                  1/1/2

3.3.3.3/32                                  Pop             131071      --
  --                                          --

4.4.4.4/32                                  Push              --      131071
10.34.34.4                                  1/1/1

4.4.4.4/32                                  Swap            131069    131071
10.34.34.4                                  1/1/1

-------------------------------------------------------------------------------

PE2

A:PE2-R4# show router ldp bindings active

LDP IPv4 Prefix Bindings (Active)
===============================================================================
Prefix                                      Op              IngLbl    EgrLbl
EgrNextHop                                  EgrIf/LspId
-------------------------------------------------------------------------------
2.2.2.2/32                                  Push              --      131070
10.34.34.3                                  1/1/1

2.2.2.2/32                                  Swap            131070    131070
10.34.34.3                                  1/1/1

3.3.3.3/32                                  Push              --      131071
10.34.34.3                                  1/1/1

4.4.4.4/32                                  Pop             131071      --
  --                                          --

-------------------------------------------------------------------------------

If you want to see the outputs of all three routers side by side on the GNS3 screen:

Active LDP binding outputs of PE1, P and PE2

The path from PE1 to PE2 (4.4.4.4/32)

Let’s trace the path from PE1 to PE2’s loopback (4.4.4.4/32) step by step from the outputs:

StepRouterOperationLabel
1PE1 (ingress)Push131069 is put on the packet, it goes to P via 1/1/2
2P (transit)SwapThe incoming 131069 is replaced, the outgoing label is 131071 (implicit null), it goes to PE2 via 1/1/1
3PE2 (egress)Pop4.4.4.4/32 is PE2’s own address, the label is already 131071, the packet is processed as plain IP

The reverse direction: PE2 to PE1 (2.2.2.2/32)

When the direction is reversed, the same logic applies:

StepRouterOperationLabel
1PE2 (ingress)Push131070 is put on, it goes to P via 1/1/1
2P (transit)Swap131070 → 131071 (implicit null), it goes to PE1 via 1/1/2
3PE1 (egress)Pop2.2.2.2/32 is PE1 itself

Implicit null and PHP

There is something notable in the P line above: the egress label is 131071. That is implicit null. P doesn’t replace the label with a real value, it removes it and sends a plain IP packet to PE2. This is called PHP (Penultimate Hop Popping), meaning the label is removed at the second-to-last hop.

Why is it done this way? If PE2 removed the label, it would first have to look at the label and then do an IP lookup as well. When the label is removed at P, PE2 only does an IP lookup, one job less.

In practice: if you capture a packet on the link between P and PE2 (10.34.34.0/24), you won’t see a label on it. On the link between PE1 and P you will see the label 131069. The label is only carried on the first leg of this LSP.

If we look at the other FECs (for example PE1’s 3.3.3.3/32 line), it’s the same there: the label P gives for its own loopback is 131071, so PE1 sends to P without adding a label (Push + implicit null), and it shows up as Pop on P.

The extra Swap lines on PE1 and PE2 (e.g. 131069 → 131069 for 4.4.4.4/32 on PE1) are not part of this flow. When reading the table it’s enough to focus on Push, the Swap on P and the Pop on the destination PE.

6. Summary

  • OSPF taught the PEs’ loopbacks to each other and decided the path.
  • LDP distributed labels over these routes and built an LSP between PE1 and PE2 (show router tunnel-table).
  • The ingress PE does push, the P router does swap, the egress side does pop. Thanks to implicit null, the label is actually removed at P (PHP).
  • The P router forwards using only the label, without looking at the packet’s IP address. That is the gain MPLS provides in the core.

In the next post we’ll build a service (Epipe/VPLS) on top of this LSP and connect CE1 with CE2.