Mental model
Traditional IP routing makes a forwarding decision at every hop. Each router looks up the destination IP in its routing table, finds the longest-prefix match, picks an outgoing interface, and forwards. This works but has limits:
- Longest-prefix match is expensive at internet scale (millions of routes).
- You can’t easily steer traffic — routing follows the IGP, period.
- Mixing customers’ overlapping IP space on one network is hard.
MPLS solves all three by adding a short label between Layer 2 and Layer 3. Once a packet is labeled at the edge, every core router just looks at the label, swaps it, forwards — no IP lookup at all. The label can also carry information about which customer, which path, which QoS class.
That’s the whole idea: lookup IP once at the edge, label-swap through the core.
The label
A 32-bit (4-byte) header inserted between the Layer 2 frame header and the Layer 3 packet:
[ Ethernet ] [ MPLS Label ] [ IP Header ] [ Payload ]
^^^^^^^^^^^^
20-bit label + 3-bit Exp (QoS) + 1-bit S (stack-bottom) + 8-bit TTL
EtherType 0x8847 (unicast) or 0x8848 (multicast) on the frame tells receivers this is MPLS.
Multiple labels can stack — used for L3VPN (outer label = transport, inner label = VRF), Traffic Engineering, and FRR. The S bit marks the bottom of the stack.
The three roles — CE / PE / P
┌── Provider MPLS Core ──┐
│ │
Customer1 ──[CE1]──[PE1]──[P1]──[P2]──[PE2]──[CE2]── Customer1
(same customer, different site)
Customer2 ──[CE3]──[PE1]──┘ └──[PE2]──[CE4]── Customer2
- CE (Customer Edge) — the customer’s router. Knows nothing about MPLS. Speaks IGP/BGP to its PE as normal.
- PE (Provider Edge) — the provider’s edge router. Does the heavy lifting: VRFs per customer, MP-BGP to other PEs, label imposition at ingress / disposition at egress.
- P (Provider Core) — the provider’s transit router. Label-swap only. No customer-specific knowledge. Doesn’t run BGP. Fast.
This is the PE/P separation — provider edge handles complexity, provider core stays simple and fast.
Label distribution — LDP
How do routers learn what label to use for what destination? Two main protocols:
| Protocol | What it does |
|---|---|
| LDP (Label Distribution Protocol) | Distributes labels for IGP routes. Most common. |
| RSVP-TE (Resource Reservation Protocol with TE) | Distributes labels along engineered paths. Used for Traffic Engineering. |
| MP-BGP | Distributes VPN labels (inner label of the stack). |
LDP forms adjacencies between directly-connected LSRs (Label Switch Routers — basically every MPLS-enabled router) and advertises: “To reach 10.1.1.0/24, use label 17 when sending to me.”
A device builds a LFIB (Label Forwarding Information Base) — like a routing table but indexed by incoming label rather than destination IP.
The forwarding action — label swap
The core operation:
- Packet arrives at P1 with incoming label = 17.
- P1 looks up label 17 in LFIB → outgoing label = 23, outgoing interface = Gi0/2.
- P1 swaps 17 → 23 and forwards.
No IP lookup. No longest-prefix match. Just a hash-table lookup by label. Implemented in ASIC at line rate.
Penultimate hop popping (PHP)
A small optimization. The router one hop before the egress PE pops the label entirely, so the egress PE receives a plain IP packet — saves it one lookup.
The egress PE signals this by advertising label 3 (implicit-null) to the penultimate hop: “don’t bother labeling — I’ll do the IP lookup anyway.”
MPLS L3VPN — the killer use case
The problem: Customer A and Customer B both use 10.0.0.0/8 internally. They both connect to your provider network. Without VPNs, routes would overlap chaotically.
The solution — VRF + MP-BGP:
- On each PE, create a VRF (Virtual Routing and Forwarding instance) per customer. Each VRF has its own private routing table.
- CE-PE exchanges routes normally (OSPF, BGP, static — depends on customer).
- PE-PE exchanges routes via MP-BGP with a special address family
VPNv4— routes carry a Route Distinguisher (RD) that makes them globally unique (e.g.,65000:1:10.0.0.0/24instead of just10.0.0.0/24). - PEs use Route Targets (RTs) to control which routes leak into which VRFs.
- Forwarding uses two labels:
- Outer label = transport label (LDP-learned), tells the core how to reach the egress PE.
- Inner label = VPN label (BGP-learned), tells the egress PE which VRF to deliver into.
A customer’s CE doesn’t know it’s running on MPLS. It just sees a private routing exchange with its PE.
[Eth][outer label][inner label][IP packet (customer VRF)][payload]
└─ identifies VRF on egress PE
└─ steers across the provider backbone via LDP/RSVP-TE
Traffic Engineering (RSVP-TE)
Vanilla MPLS follows the IGP — same path as IP would take. MPLS-TE lets you override that.
Use case: You have two paths between PE1 and PE2 — one short (low capacity), one long (high capacity). IGP picks the short one. With TE, you signal an explicit LSP (Label Switched Path) over the long route — useful for bandwidth, latency, or fast-reroute purposes.
CCNA doesn’t drill on this — just know it exists.
L2VPN — point-to-point and VPLS
MPLS can also transport Layer 2 frames end-to-end:
- EoMPLS / Pseudowire — point-to-point Ethernet tunnel. Two sites think they’re on the same Ethernet cable.
- VPLS (Virtual Private LAN Service) — multipoint L2. Many sites feel like one bridged LAN.
Customers like this for use cases that need Layer 2 adjacency (mainframe legacy, broadcast-dependent apps).
Configuration — a tiny PE example (Cisco IOS-XR/XE)
! Enable LDP
PE1(config)# mpls ldp
PE1(config-mpls-ldp)# router-id 10.255.255.1
! Enable MPLS on the core-facing interfaces
PE1(config)# interface Gi0/1
PE1(config-if)# mpls ip
PE1(config-if)# mpls label protocol ldp
! Create a customer VRF
PE1(config)# vrf definition CUSTOMER-A
PE1(config-vrf)# rd 65000:1
PE1(config-vrf)# address-family ipv4
PE1(config-vrf-af)# route-target export 65000:1
PE1(config-vrf-af)# route-target import 65000:1
! Bind the customer-facing interface to the VRF
PE1(config)# interface Gi0/2
PE1(config-if)# vrf forwarding CUSTOMER-A
PE1(config-if)# ip address 192.168.10.1 255.255.255.0
! MP-BGP to the other PE
PE1(config)# router bgp 65000
PE1(config-router)# neighbor 10.255.255.2 remote-as 65000
PE1(config-router)# neighbor 10.255.255.2 update-source Loopback0
PE1(config-router)# address-family vpnv4
PE1(config-router-af)# neighbor 10.255.255.2 activate
Verification
PE1# show mpls interfaces
PE1# show mpls ldp neighbor
PE1# show mpls forwarding-table
PE1# show ip route vrf CUSTOMER-A
PE1# show bgp vpnv4 unicast all summary
PE1# show bgp vpnv4 unicast all ! see VPNv4 routes with RD prefixes
PE1# ping vrf CUSTOMER-A 192.168.20.1
PE1# traceroute mpls ipv4 10.255.255.2/32 ! end-to-end label trace
MPLS vs SD-WAN — the modern context
For 20 years MPLS dominated enterprise WAN: SLA-backed, low-latency, QoS-guaranteed. The downside: expensive ($/Mbps) and slow to add new sites.
SD-WAN (SD-WAN Concepts) eats into the use case by using internet + IPsec overlay to deliver “good enough” WAN at a fraction of the cost. Modern designs mix both: MPLS for SLA-bound voice/transactional traffic, internet for SaaS and bulk.
MPLS isn’t going away — service-provider cores and large enterprise WANs still run on it — but for branch-to-cloud connectivity, SD-WAN is winning.
Common mistakes
-
Confusing MPLS L3VPN with a customer’s own VPN. L3VPN is the provider’s fabric — the customer just gets a private routing service. Customer-side IPsec is something else entirely.
-
Running BGP on the P routers. Provider core (
P) should never carry BGP — keep it lean with only IGP + LDP. BGP belongs at the PE. -
VRF without the corresponding interface. A
vrf forwardingline under the interface is what binds the link to that VRF. Forgetting it leaves the interface in the global table. -
Mismatching Route Targets. Importing the wrong RT means the customer doesn’t see remote-site routes. Always document export/import pairs.
-
Not advertising loopbacks into LDP. LDP needs the BGP next-hop (typically the remote PE’s loopback) to be reachable via an LDP-labeled path. If the loopback isn’t in the IGP, LDP has nothing to label.
-
Penultimate-hop popping gotchas. PHP changes the TTL accounting —
tracerouteacross MPLS sometimes hides hops. Usetraceroute mplsfor accurate visibility. -
Treating MPLS as encrypted. It’s not. MPLS is a forwarding plane, not a security plane. If you need confidentiality, you still need IPsec on top.
Lab to try tonight
- Cisco DevNet Sandbox has free MPLS L3VPN labs. Spin one up — or build it in CML/EVE-NG with 4 routers (2 PE, 2 P, plus 2 CE).
- Run OSPF in the provider core (P + PE loopbacks).
- Enable
mpls ipon every core link. Verify LDP neighbors withshow mpls ldp neighbor. - Create one VRF on each PE for CUSTOMER-A. Configure CE-PE static or BGP routing.
- Configure MP-BGP between the two PE loopbacks with VPNv4 address-family.
- From CE1, ping CE2 — packets traverse the labeled path. Verify with
show mpls forwarding-tablealong the way. - Bonus:
traceroute mplsend-to-end and watch the label stack progression. - Bonus: shut a core link → routing reconverges, LDP relearns, but with TE you could pre-signal a backup LSP for sub-second failover.
Cheat strip
| Concept | Plain English |
|---|---|
| MPLS | Multi-Protocol Label Switching. Lookup once at edge, label-swap in core |
| Label | 4-byte header inserted between L2 and L3 |
| CE / PE / P | Customer Edge / Provider Edge / Provider Core |
| LDP | Distributes transport labels (paired with IGP) |
| MP-BGP VPNv4 | Distributes VPN (inner) labels for L3VPN |
| VRF | Per-customer routing table on the PE |
| RD / RT | Route Distinguisher (uniqueness) / Route Target (import-export control) |
| PHP | Penultimate-hop popping — strip the label one hop before egress |
| MPLS-TE | Traffic Engineering — explicit LSPs that deviate from IGP |
| L3VPN vs L2VPN | L3 = routed customer service. L2 = transparent Ethernet (pseudowire / VPLS) |
| Not encrypted | MPLS provides separation, not confidentiality |
| CCNA depth | Recognize labels, roles, and L3VPN concept — no deep config required |