MPLS L3VPN on Cisco IOS-XE: VRF, MP-BGP, and Label Forwarding Configuration Guide

MPLS L3VPN on Cisco IOS-XE: VRF, MP-BGP, and Label Forwarding Configuration Guide

What Is MPLS L3VPN and Why Should You Care?

If you’ve ever had to connect multiple enterprise sites across a service provider backbone while keeping their routing tables completely isolated from one another — and from the provider’s own infrastructure — you’ve run into the exact problem that MPLS Layer 3 VPN was built to solve.

MPLS L3VPN is the backbone technology behind most enterprise WAN services sold by carriers today. Whether you’re managing a multi-site retail chain, a bank with regional offices, or a government agency with distributed facilities, there’s a good chance the underlying transport is an MPLS L3VPN. Understanding how it works under the hood makes you a far more effective engineer when things go wrong — and they will.

In this post, we’ll configure a complete MPLS L3VPN lab from scratch on Cisco IOS-XE: provider core, provider edge, customer edge, VRFs, MP-BGP, LDP, route distinguishers, and route targets. We’ll walk through every command with real IOS-XE syntax and validate with show commands. If you want to understand the technology that underpins most modern enterprise WANs, this is it.

Lab topology: 2 PE routers (PE1, PE2), 1 P (provider core) router, 2 CE routers (CE1-A, CE2-A) representing one VPN customer, 2 CE routers (CE1-B, CE2-B) representing a second VPN customer. All PE and P routers run OSPF for IGP and LDP for label distribution. MP-BGP runs between PE1 and PE2 for VPN route exchange.

MPLS and LDP Fundamentals

Before touching a router, you need a clear mental model. MPLS (Multiprotocol Label Switching) forwards packets based on short fixed-length labels rather than full IP lookups. This gives service providers speed and flexibility — but more importantly for L3VPN, it enables traffic from completely separate customer routing domains to traverse the same physical infrastructure without any risk of route leakage.

LDP (Label Distribution Protocol) is the glue that makes this work at the label level. Every router in the provider core runs LDP and advertises a label for every prefix in its routing table to its neighbors. When PE1 needs to send a packet to PE2, it pushes a label stack: the outer label gets the packet across the provider core via LSP, and the inner label (the VPN label) tells PE2 which VRF the packet belongs to.

This two-label mechanism — often called label imposition — is why MPLS L3VPN provides true isolation. Customer A’s traffic and Customer B’s traffic can traverse the same physical links, but the inner VPN label on PE2 sorts them into completely separate routing tables (VRFs) before any IP lookup happens. If you’re new to Cisco’s platform landscape, the IOS vs IOS-XE vs IOS-XR comparison clarifies which platform these commands apply to — the config in this post targets IOS-XE throughout.

VRF Configuration on PE Routers

VRFs (Virtual Routing and Forwarding instances) are the core abstraction. Each customer gets their own VRF on each PE router, with a completely separate routing table, FIB, and BGP table.

On PE1, create VRFs for two customers:

PE1# configure terminal
PE1(config)# vrf definition CUSTOMER-A
PE1(config-vrf)# rd 65000:100
PE1(config-vrf)# route-target export 65000:100
PE1(config-vrf)# route-target import 65000:100
PE1(config-vrf)# address-family ipv4
PE1(config-vrf-af)# exit-address-family
PE1(config-vrf)# exit

PE1(config)# vrf definition CUSTOMER-B
PE1(config-vrf)# rd 65000:200
PE1(config-vrf)# route-target export 65000:200
PE1(config-vrf)# route-target import 65000:200
PE1(config-vrf)# address-family ipv4
PE1(config-vrf-af)# exit-address-family
PE1(config-vrf)# exit

A few things to understand here:

  • RD (Route Distinguisher): Makes VPN routes globally unique in the BGP table. Format is ASN:NN or IP:NN. The RD doesn’t control import/export — it just prevents address collisions if two customers use the same private IP space.
  • Route Target (RT): This is what actually controls which VRFs import which routes. The export RT gets attached to routes when they leave this VRF. The import RT determines which exported routes get pulled into this VRF.
  • This basic config uses the same RT for import and export — suitable for a simple full-mesh VPN. For extranet or hub-and-spoke designs, you’d use asymmetric RTs.

Repeat on PE2 with the same VRF definitions (same RD, same RTs per customer). The RD can technically differ per PE, but keeping it consistent significantly simplifies troubleshooting.

Enabling MPLS in the Provider Core

The provider core (P router) and both PE routers need MPLS and LDP enabled on their backbone interfaces. Configure OSPF first so the backbone has reachability, then enable MPLS globally.

! On PE1 — backbone interface toward P
PE1(config)# interface GigabitEthernet0/1
PE1(config-if)# description TO-P-ROUTER
PE1(config-if)# ip address 10.0.0.1 255.255.255.252
PE1(config-if)# mpls ip
PE1(config-if)# no shutdown

! OSPF for backbone reachability (loopbacks must be included)
PE1(config)# router ospf 1
PE1(config-router)# router-id 1.1.1.1
PE1(config-router)# network 10.0.0.0 0.0.0.255 area 0
PE1(config-router)# network 1.1.1.1 0.0.0.0 area 0
! Verify LDP is up
PE1# show mpls ldp neighbor
    Peer LDP Ident: 2.2.2.2:0; Local LDP Ident 1.1.1.1:0
        TCP connection: 2.2.2.2.646 - 1.1.1.1.23847
        State: Oper; Msgs sent/rcvd: 142/140; Downstream
        Up time: 02:15:43
        LDP discovery sources:
          GigabitEthernet0/1, Src IP addr: 10.0.0.2
        Addresses bound to peer LDP Ident:
          10.0.0.2    2.2.2.2
! Verify labels are being distributed
PE1# show mpls forwarding-table
Local  Outgoing    Prefix            Bytes Label  Outgoing   Next Hop
Label  Label or VC or Tunnel Id      Switched      interface
16     Pop Label   10.0.0.4/30       0             Gi0/1      10.0.0.2
17     17          3.3.3.3/32        0             Gi0/1      10.0.0.2
18     Pop Label   10.0.0.0/30       0             aggregate/1

The mpls ip command on each backbone interface enables both LDP and MPLS forwarding. Never put this on CE-facing interfaces — customers have no business participating in label distribution.

MP-BGP Between PE Routers

This is the critical piece that carries VPN routes between PE routers. Regular BGP only handles IPv4 unicast. MP-BGP (Multiprotocol BGP, RFC 4760) adds address family support, including vpnv4 — the address family that carries VPN routes with their RDs and RTs attached as extended communities.

On PE1:

PE1(config)# router bgp 65000
PE1(config-router)# bgp router-id 1.1.1.1
PE1(config-router)# no bgp default ipv4-unicast
PE1(config-router)# neighbor 3.3.3.3 remote-as 65000
PE1(config-router)# neighbor 3.3.3.3 update-source Loopback0
PE1(config-router)#
PE1(config-router)# address-family vpnv4
PE1(config-router-af)# neighbor 3.3.3.3 activate
PE1(config-router-af)# neighbor 3.3.3.3 send-community extended
PE1(config-router-af)# exit-address-family

Mirror this on PE2, pointing back at 1.1.1.1. Three commands that matter most:

  • no bgp default ipv4-unicast: Prevents the global routing table from bleeding into this IBGP session. You want VPN routes only.
  • update-source Loopback0: BGP sessions must source from loopbacks so they survive physical link failures — OSPF will reroute, and the session stays up.
  • send-community extended: Route Targets ride as BGP extended communities. Without this, RT information is stripped in transit and VPN routes won’t import correctly on the far end.
! Verify MP-BGP is up and exchanging VPN prefixes
PE1# show bgp vpnv4 unicast all summary
BGP router identifier 1.1.1.1, local AS number 65000
...
Neighbor        V    AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
3.3.3.3         4 65000      87      89       14    0    0 01:12:05        4

Four prefixes received from PE2 confirms VPN routes are flowing. If this shows 0, check send-community extended on both sides and verify RT symmetry between the exporting and importing VRFs.

PE-CE Routing: Connecting Customers

PE-CE routing runs entirely inside the VRF. The CE router is not MPLS-aware — it just runs standard routing toward the PE. You can use static routes, OSPF, EIGRP, or BGP for PE-CE; BGP is the most scalable and what most service providers deploy. The BGP fundamentals guide covers path selection and attribute manipulation in detail if you need to brush up before configuring PE-CE BGP.

On PE1, configure the CE-facing interface in the correct VRF and bring up BGP PE-CE for Customer A:

! CE-facing interface in VRF — MUST assign VRF before IP address
PE1(config)# interface GigabitEthernet0/2
PE1(config-if)# description CE1-A
PE1(config-if)# vrf forwarding CUSTOMER-A
PE1(config-if)# ip address 192.168.10.1 255.255.255.252
PE1(config-if)# no shutdown

! BGP PE-CE for Customer A (customer AS 65100)
PE1(config)# router bgp 65000
PE1(config-router)# address-family ipv4 vrf CUSTOMER-A
PE1(config-router-af)# neighbor 192.168.10.2 remote-as 65100
PE1(config-router-af)# neighbor 192.168.10.2 activate
PE1(config-router-af)# exit-address-family

On CE1-A (plain IOS/IOS-XE — no VRF config needed on the customer device):

CE1-A(config)# router bgp 65100
CE1-A(config-router)# bgp router-id 10.1.1.1
CE1-A(config-router)# neighbor 192.168.10.1 remote-as 65000
CE1-A(config-router)# address-family ipv4
CE1-A(config-router-af)# neighbor 192.168.10.1 activate
CE1-A(config-router-af)# network 10.1.0.0 mask 255.255.0.0
CE1-A(config-router-af)# exit-address-family

CE1-A advertises 10.1.0.0/16 to PE1. PE1 receives it, tags it with the VRF’s export RT (65000:100), and redistributes it into MP-BGP as a VPN route. PE2 receives this VPN route, checks the RT against its VRF import policy, matches, and installs the route into the CUSTOMER-A VRF’s routing table on PE2’s side — where CE2-A can reach it.

Verifying the Full Path

! Check VRF routing table on PE1
PE1# show ip route vrf CUSTOMER-A
Routing Table: CUSTOMER-A
...
B        10.2.0.0/16 [200/0] via 3.3.3.3, 00:05:22
C        192.168.10.0/30 is directly connected, GigabitEthernet0/2
C        10.1.0.0/16 via 192.168.10.2

! Inspect the BGP VPN route — confirm RT and VPN label assignment
PE1# show bgp vpnv4 unicast all 10.2.0.0/16
BGP routing table entry for 65000:100:10.2.0.0/16, version 9
Paths: (1 available, best #1, table CUSTOMER-A)
  Local
    3.3.3.3 (metric 2) from 3.3.3.3 (3.3.3.3)
      Origin incomplete, metric 0, localpref 100, valid, internal, best
      Extended Community: RT:65000:100
      mpls labels in/out 18/19
! Verify label forwarding for the VPN route
PE1# show mpls forwarding-table vrf CUSTOMER-A
Local  Outgoing    Prefix            Bytes Label  Outgoing   Next Hop
Label  Label or VC or Tunnel Id      Switched      interface
18     19          10.2.0.0/16       0             Gi0/1      10.0.0.2
! End-to-end ping from CE1-A to CE2-A
CE1-A# ping 10.2.1.1 source 10.1.1.1
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 10.2.1.1, timeout is 2 seconds:
Packet sent with a source address of 10.1.1.1
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 2/3/4 ms

! Confirm VRF isolation — Customer B CANNOT reach Customer A's space
CE1-B# ping 10.1.1.1 source 10.2.1.1
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 10.1.1.1, timeout is 2 seconds:
.....
Success rate is 0 percent (0/5)

That last output is exactly what you want. Customer B has zero reachability into Customer A’s address space. The VRF separation is working correctly.

Troubleshooting MPLS L3VPN: Where Things Break

In production, failures tend to cluster into four categories.

1. LDP Not Forming / No Labels

PE1# show mpls ldp neighbor
! If empty, check discovery:
PE1# show mpls ldp discovery
  Local LDP Identifier:
      1.1.1.1:0
  Discovery Sources:
    Interfaces:
        GigabitEthernet0/1 (ldp): xmit

If you see xmit but no peer, the remote end is missing mpls ip, or there’s an LDP transport address mismatch. Check show mpls ldp parameters on both sides — the transport address must be reachable via OSPF.

2. BGP VPNv4 Routes Missing

! Confirm RT symmetry between PEs
PE1# show vrf detail CUSTOMER-A | include RT
  Import VPN route-target communities
    RT:65000:100
  Export VPN route-target communities
    RT:65000:100

RT mismatch is the most common L3VPN config error. If PE1 exports with RT 65000:100 but PE2’s VRF imports 65000:101, no routes will appear in the remote VRF. Verify with show vrf detail on both PEs and cross-check manually.

3. Routes Present in VRF But Ping Fails

! Trace the label stack across the core
PE1# traceroute vrf CUSTOMER-A 10.2.1.1 source 10.1.1.1
  1  10.0.0.2  [MPLS: Labels 17/19 Exp 0] 2 msec
  2  10.0.0.6  [MPLS: Label 19 Exp 0] 2 msec
  3  192.168.20.2  3 msec

Labels 17 and 19 stacked on the first hop confirm penultimate hop popping is occurring at the P router. If the trace dies mid-path, check show mpls forwarding-table at the failing hop.

4. Penultimate Hop Popping (PHP) Behavior

! PHP is enabled by default — verify
P# show mpls forwarding-table 3.3.3.3/32
Local  Outgoing    Prefix            Bytes Label  Outgoing   Next Hop
Label  Label or VC or Tunnel Id      Switched      interface
17     Pop Label   3.3.3.3/32        0             Gi0/2      10.0.0.6

Pop Label confirms PHP is working. The P router pops the outer transport label one hop before PE2, so PE2 receives only the VPN label — saving a lookup cycle. To disable PHP (e.g., for QoS marking preservation through the core), configure mpls ldp explicit-null on the PE loopbacks.

Route Distinguishers vs Route Targets: The Persistent Confusion

This trips up even experienced engineers, so let’s be explicit:

Attribute Route Distinguisher (RD) Route Target (RT)
Purpose Makes VPN routes globally unique in BGP Controls VRF import/export policy
Format ASN:NN or IP:NN ASN:NN or IP:NN
Unique per PE? Can be unique or shared Must match between exporting and importing VRFs
BGP attribute Prepended to prefix in VPNv4 NLRI Carried as extended community
Affects routing? No — only a disambiguator Yes — determines which VRFs accept which routes

Think of the RD as a serial number on a shipping label (makes the address globally unique even if two customers both use 10.0.0.0/8) and the RT as a sorting code at the destination warehouse (determines which shelf the package lands on).

For extranet designs — where Customer A needs read access to a shared services VRF — configure asymmetric RTs. The shared services VRF exports with RT 65000:999. Customer A’s VRF imports RT 65000:999 in addition to its own RT 65000:100. Customer A sees shared service routes; shared services never see Customer A routes. Clean and auditable.

Common Production Pitfalls

  • BGP AS_PATH loops on PE-CE BGP: If two CE sites in the same customer AS exchange routes via the PE, the receiving CE may drop them because its own AS appears in the path. Fix with neighbor X.X.X.X as-override on the PE, which replaces the customer AS with the provider AS in the path — the CE no longer sees its own AS and accepts the routes.
  • MTU and MPLS label overhead: Each label adds 4 bytes. A typical 2-label stack adds 8 bytes. If your CE-to-CE path runs a 1500-byte MTU with no MTU adjustment, you’ll hit silent fragmentation or drops. Increase backbone interface MTU to at least 1508, or configure mpls mtu 1512 on MPLS-enabled interfaces.
  • OSPF PE-CE with backdoor links: If CE sites have a direct link and also connect via MPLS, OSPF will prefer the backdoor (intra-area) over the MPLS path (inter-area via PE redistribution). Resolve with OSPF sham-links configured between PEs within the VRF address family to simulate intra-area adjacency across the backbone.
  • VRF-aware management services: NTP, SNMP, syslog, and RADIUS all require explicit VRF binding on PE routers. ntp server vrf MGMT X.X.X.X. Forgetting this causes management traffic to use the global routing table, which may have no path to your management hosts.

If you want to automate VRF provisioning, BGP neighbor templates, and route target assignments across a fleet of PE routers, our network automation guide with Python, Netmiko, and NAPALM covers exactly this kind of templated multi-device deployment — particularly useful when you’re onboarding new VPN customers at scale.

Wrapping Up

MPLS L3VPN is one of those technologies that looks intimidating until you break it into its components — VRFs for isolation, LDP for label distribution, MP-BGP for VPN route exchange, and route targets for policy control. Once you’ve built it in a lab and watched a two-label stack traverse a provider core, the mental model clicks into place and stays there.

The configuration in this post covers the full stack: IGP to VPN label forwarding to PE-CE BGP, with verification commands at every step. In production, you’ll layer on top: QoS marking preservation with explicit-null, route reflectors for larger provider cores, and CsC (Carrier Supporting Carrier) for nested MPLS scenarios. But this foundation handles the vast majority of enterprise L3VPN deployments you’ll encounter in the field.

Keep your RDs and RTs documented per-customer in your change management system. Label collisions and RT mismatches are the two fastest ways to cause a production outage on an MPLS network — and both are entirely avoidable with clean documentation and a disciplined numbering scheme.

Enjoying this post?

Get more guides like this delivered straight to your inbox. No spam, just tech and trails.