MPLS Introduction: Labels, LDP, and Packet Forwarding

IP routing makes forwarding decisions at every hop. Each router looks up the destination, checks its routing table, forwards the packet. Repeat at every hop. Works fine, but expensive at scale.

MPLS (Multi-Protocol Label Switching) adds a label at network edge. Interior routers forward based on label only — a simple table lookup, no IP processing. Labels are swapped at each hop until the edge, where the label is removed and IP routing resumes.

MPLS is still relevant for service provider networks — enabling VPNs, traffic engineering, and fast forwarding at scale.

MPLS Concepts

How MPLS Works

Without MPLS (IP forwarding):
[IP Header: dst=10.0.0.1] → Router A → [route lookup] → Router B → [route lookup] → Router C
With MPLS:
[IP Header] → Edge Router → adds [Label: 100] → Core Router → swaps [Label: 200] → Edge Router → removes label → [IP Header]

Key Terms

TermDescription
Label20-bit identifier for forwarding
LSPLabel Switched Path (tunnel through network)
LDPLabel Distribution Protocol (assigns labels)
PushAdd label to packet
PopRemove label from packet
SwapReplace label with new one
PHPPenultimate Hop Popping

MPLS Header

┌────────────────────────────────────────────┐
│ Label (20 bits) │ TC │ S │ TTL │ │
│ (0-1048575) │ 3b │1b │ 8b │ │
└────────────────────────────────────────────┘
TC: Traffic Class (QoS)
S: Bottom of Stack (1 if last label)
TTL: Time to Live

VyOS MPLS Support

VyOS supports MPLS through FRRouting:

Terminal window
# Check MPLS support
cat /proc/sys/net/mpls/platform_labels
# If exists, MPLS kernel support is available
# Load MPLS modules
modprobe mpls_router
modprobe mpls_iptunnel

Basic MPLS Configuration

Enable MPLS on Interfaces

Terminal window
configure
# Enable MPLS kernel support
set system sysctl parameter net.mpls.platform_labels value 100000
# Enable MPLS input on interfaces (via sysctl)
set system sysctl parameter net.mpls.conf.eth0.input value 1
set system sysctl parameter net.mpls.conf.eth1.input value 1
commit

Configure LDP

Terminal window
configure
# Enable LDP router ID
set protocols mpls ldp router-id 10.255.0.1
# Configure LDP interfaces
set protocols mpls ldp interface eth0
set protocols mpls ldp interface eth1
# Optional: Discovery hello interval
set protocols mpls ldp discovery hello-interval 5
set protocols mpls ldp discovery hello-holdtime 15
commit

LDP with Targeted Neighbors

Terminal window
configure
# For non-adjacent neighbors (over tunnels)
set protocols mpls ldp targeted-neighbor ipv4 address 10.255.0.2
commit

LDP Operation

LDP Session Establishment

1. Router discovers neighbors via Hello packets (UDP 646)
2. TCP session established to neighbor (port 646)
3. Label mappings exchanged
4. LSPs formed

Viewing LDP Status

Terminal window
# Show LDP neighbors
show mpls ldp neighbor
# Output:
# Peer LDP Identifier: 10.255.0.2:0
# TCP connection: 10.255.0.1:646 - 10.255.0.2:54321
# State: Operational
# Messages sent/received: 1234/5678
# Show LDP bindings (label mappings)
show mpls ldp binding
# Show MPLS forwarding table
show mpls table

MPLS Forwarding

Label Operations

Terminal window
# View MPLS forwarding table
show mpls table
# Output:
# Inbound Label Type Nexthop Outbound Label
# 100 LDP 10.0.0.2 200
# 101 LDP 10.0.0.2 201
# 102 LDP 10.0.0.2 implicit-null
# implicit-null = PHP (penultimate hop popping)

Penultimate Hop Popping (PHP)

Without PHP:
[Label:100] → Router A → [Label:200] → Router B → [Label:300] → Router C → [no label] → Destination
↑ Two operations: pop label + IP lookup
With PHP:
[Label:100] → Router A → [Label:200] → Router B → [no label] → Router C → Destination
↑ Pop here (second-to-last hop)
↑ Only IP lookup needed

Router C signals “implicit-null” label to Router B, telling it to pop the label.

MPLS with IGP

MPLS + OSPF

Terminal window
configure
# Configure OSPF
set protocols ospf area 0 network 10.0.0.0/24
set protocols ospf passive-interface default
set protocols ospf passive-interface lo disable
set protocols ospf interface eth0 passive disable
set protocols ospf interface eth1 passive disable
# LDP follows OSPF paths
set protocols mpls ldp interface eth0
set protocols mpls ldp interface eth1
commit

MPLS + IS-IS

Terminal window
configure
# Configure IS-IS
set protocols isis interface eth0
set protocols isis interface eth1
set protocols isis net 49.0001.0100.0100.0001.00
# LDP follows IS-IS paths
set protocols mpls ldp interface eth0
set protocols mpls ldp interface eth1
commit

Simple MPLS Network Example

Topology

[CE1] ── [PE1] ═══ [P1] ═══ [PE2] ── [CE2]
10.255.0.1 10.255.0.2 10.255.0.3
PE = Provider Edge (MPLS edge)
P = Provider (MPLS core)
CE = Customer Edge (no MPLS)

PE1 Configuration

Terminal window
configure
# Loopback for router-id
set interfaces loopback lo address 10.255.0.1/32
# WAN interface toward P1
set interfaces ethernet eth0 address 10.0.0.1/30
# Customer interface (no MPLS)
set interfaces ethernet eth1 address 192.168.1.1/24
# OSPF
set protocols ospf router-id 10.255.0.1
set protocols ospf area 0 network 10.255.0.1/32
set protocols ospf area 0 network 10.0.0.0/30
# LDP
set protocols mpls ldp router-id 10.255.0.1
set protocols mpls ldp interface eth0
commit

P1 Configuration

Terminal window
configure
# Loopback
set interfaces loopback lo address 10.255.0.2/32
# Interfaces
set interfaces ethernet eth0 address 10.0.0.2/30
set interfaces ethernet eth1 address 10.0.0.5/30
# OSPF
set protocols ospf router-id 10.255.0.2
set protocols ospf area 0 network 10.255.0.2/32
set protocols ospf area 0 network 10.0.0.0/30
set protocols ospf area 0 network 10.0.0.4/30
# LDP
set protocols mpls ldp router-id 10.255.0.2
set protocols mpls ldp interface eth0
set protocols mpls ldp interface eth1
commit

Troubleshooting MPLS

LDP Neighbor Not Forming

Terminal window
# Check interface MPLS is enabled
show interfaces ethernet eth0
# Check LDP is listening
ss -tulnp | grep 646
# Check for LDP hellos
sudo tcpdump -i eth0 udp port 646
# Check OSPF/IGP adjacency (LDP follows IGP)
show ip ospf neighbor

Labels Not Assigned

Terminal window
# Check LDP bindings
show mpls ldp binding
# Check MPLS forwarding table
show mpls table
# Verify MPLS modules loaded
lsmod | grep mpls

Packets Not Label-Switched

Terminal window
# Verify ingress interface has MPLS enabled
cat /proc/sys/net/mpls/conf/eth0/input
# Should be 1, if 0:
echo 1 > /proc/sys/net/mpls/conf/eth0/input
# Check kernel MPLS support
cat /proc/sys/net/mpls/platform_labels

MPLS MTU Considerations

MPLS label adds 4 bytes per label:

Terminal window
# Standard Ethernet MTU: 1500
# With one MPLS label: 1500 - 4 = 1496 effective payload
# With two labels (VPN): 1500 - 8 = 1492 effective payload
# Option 1: Increase MTU on MPLS interfaces
set interfaces ethernet eth0 mtu 1508
# Option 2: Fragment at ingress (less efficient)

MPLS Security

Control Plane Security

Terminal window
# Restrict LDP sessions
# Only accept from known neighbors
set protocols mpls ldp neighbor 10.255.0.2 password "secret"
# Filter LDP discovery
# (Use firewall to limit UDP 646)

Data Plane Considerations

Terminal window
# MPLS doesn't encrypt traffic
# Anyone on the path can read label and content
# For encryption, use:
# - IPsec over MPLS
# - MACSec at Layer 2

The Lesson

MPLS is still relevant for service provider networks.

MPLS provides:

  • Fast forwarding (label lookup vs. IP lookup)
  • VPN services (L2VPN, L3VPN)
  • Traffic engineering (explicit paths)
  • QoS capabilities

VyOS MPLS support is functional but limited:

  • Basic LDP works
  • Advanced features (RSVP-TE, Segment Routing) may be limited
  • Check VyOS version for specific feature support

For modern networks:

  • Small networks: IP routing is fine
  • Large SP networks: MPLS still valuable
  • Newer alternative: Segment Routing (SR-MPLS, SRv6)

Understand MPLS fundamentals even if you don’t use it daily — many service provider networks and VPN services depend on it.