MPLS L3VPN is the protocol stack that carries enterprise WANs and provider VPN services — and it's notoriously hard to lab, because every piece (IGP, LDP, MP-BGP VPNv4, VRFs, route-targets, PE-CE routing) has to line up before a single customer ping works. This lab builds a multi-vendor L3VPN with a Cisco IOL (BYOI) PE, a Juniper cRPD (BYOI) PE, and a route reflector in the core, so you can see exactly where the chain breaks.
Bottom line: A working MPLS L3VPN lab means an OSPF+LDP core, a VPNv4 route reflector, VRFs with matching route-targets on two vendors, and PE-CE routing — a lot to wire by hand. As of 2026, NetPilot deploys this exact topology with real CLIs in ~2 minutes — grab the prompt at the bottom.
Lab topology
A three-router core (OSPF + LDP) with a route reflector in the middle. Customer A has two sites, one behind each PE, in VRF CUSTA.
[CE1]---[PE1 Cisco]======[RR/P Cisco]======[PE2 Juniper]---[CE2]
10.1.1/24 1.1.1.1 3.3.3.3 2.2.2.2 10.2.2/24
VRF CUSTA RD 65000:100 VPNv4 RR RD 65000:200 VRF CUSTA
RT 65000:100 (reflects VPNv4) RT 65000:100
<------------- OSPF area 0 + LDP ------------->- Core: OSPF area 0 for loopback reachability, LDP for label distribution.
- Overlay: MP-iBGP VPNv4 from each PE to the route reflector.
- VPN: VRF
CUSTAon both PEs; the RD differs per PE (uniqueness), the RT is shared (65000:100) — that's what stitches the two sites together.
PE1 — Cisco IOL
ip vrf CUSTA
rd 65000:100
route-target export 65000:100
route-target import 65000:100
!
interface Loopback0
ip address 1.1.1.1 255.255.255.255
ip ospf 1 area 0
!
interface Ethernet0/0
description core to RR
ip address 10.0.13.1 255.255.255.0
ip ospf 1 area 0
mpls ip
!
interface Ethernet0/1
description to CE1
ip vrf forwarding CUSTA
ip address 10.1.0.1 255.255.255.0
!
router ospf 1
router-id 1.1.1.1
mpls ldp router-id Loopback0 force
!
router bgp 65000
neighbor 3.3.3.3 remote-as 65000
neighbor 3.3.3.3 update-source Loopback0
address-family vpnv4
neighbor 3.3.3.3 activate
neighbor 3.3.3.3 send-community extended
address-family ipv4 vrf CUSTA
redistribute connected
redistribute static
!
ip route vrf CUSTA 10.1.1.0 255.255.255.0 10.1.0.2mpls ipon the core interface turns on LDP labeling — miss it and BGP next-hops resolve but packets have no transport label.send-community extendedis mandatory: VPNv4 routes carry their route-targets as extended communities. Forget it and the RR/PE silently drops the prefixes.
RR / P — Cisco IOL (route reflector)
interface Loopback0
ip address 3.3.3.3 255.255.255.255
ip ospf 1 area 0
!
interface Ethernet0/0
ip address 10.0.13.3 255.255.255.0
ip ospf 1 area 0
mpls ip
interface Ethernet0/1
ip address 10.0.23.3 255.255.255.0
ip ospf 1 area 0
mpls ip
!
router ospf 1
router-id 3.3.3.3
mpls ldp router-id Loopback0 force
!
router bgp 65000
no bgp default route-target filter
neighbor 1.1.1.1 remote-as 65000
neighbor 1.1.1.1 update-source Loopback0
neighbor 2.2.2.2 remote-as 65000
neighbor 2.2.2.2 update-source Loopback0
address-family vpnv4
neighbor 1.1.1.1 activate
neighbor 1.1.1.1 route-reflector-client
neighbor 1.1.1.1 send-community extended
neighbor 2.2.2.2 activate
neighbor 2.2.2.2 route-reflector-client
neighbor 2.2.2.2 send-community extendedno bgp default route-target filteris the line everyone forgets on a pure route reflector — without it the RR drops VPNv4 routes whose RTs it doesn't locally import (it has no VRFs), and the VPN never forms.
PE2 — Juniper cRPD
set interfaces lo0 unit 0 family inet address 2.2.2.2/32
set interfaces ge-0/0/0 unit 0 family inet address 10.0.23.2/24
set interfaces ge-0/0/1 unit 0 family inet address 10.2.0.1/24
set routing-options router-id 2.2.2.2
set routing-options autonomous-system 65000
set protocols mpls interface ge-0/0/0.0
set protocols ldp interface ge-0/0/0.0
set protocols ldp interface lo0.0
set protocols ospf area 0.0.0.0 interface lo0.0 passive
set protocols ospf area 0.0.0.0 interface ge-0/0/0.0
set protocols bgp group vpn type internal
set protocols bgp group vpn local-address 2.2.2.2
set protocols bgp group vpn family inet-vpn unicast
set protocols bgp group vpn neighbor 3.3.3.3
set routing-instances CUSTA instance-type vrf
set routing-instances CUSTA interface ge-0/0/1.0
set routing-instances CUSTA route-distinguisher 65000:200
set routing-instances CUSTA vrf-target target:65000:100
set routing-instances CUSTA routing-options static route 10.2.2.0/24 next-hop 10.2.0.2routing-options autonomous-system 65000is mandatory — Junos derives the local AS for the internal VPNv4 session from it, and the core-facingge-0/0/0carries OSPF + LDP for the underlay (the VRF'sge-0/0/1stays inside the routing-instance).- Junos rolls VRF, RD, and RT into one
routing-instancesstanza;vrf-target target:65000:100covers both import and export. family inet-vpn unicastis Junos' equivalent of Cisco'saddress-family vpnv4— the multi-vendor naming is exactly the kind of thing the agent translates for you.- cRPD is containerized, so the
ge-0/0/0/ge-0/0/1names shown here map to the container's underlying Linux interfaces (cRPD images may also exposeeth-style names) — NetPilot wires that mapping for you, so you write standard Junos config and it lands on the right container link.
PE-CE here is static for clarity; in production it's usually eBGP or OSPF between PE and CE — ask the agent to swap it in.
CE1 and CE2 — Cisco IOL
The CEs are plain customer routers — no MPLS, no VRF awareness. Each has a link to its PE and a Loopback0 standing in for the customer LAN (the host the far side pings), plus a default route toward the PE. The PE static routes above point at these CE LANs, so the topology only closes once the CEs exist.
! CE1 (behind PE1) — customer site 1
interface Ethernet0/0
description to PE1
ip address 10.1.0.2 255.255.255.0
!
interface Loopback0
description customer LAN 10.1.1.0/24
ip address 10.1.1.1 255.255.255.0
!
ip route 0.0.0.0 0.0.0.0 10.1.0.1! CE2 (behind PE2) — customer site 2
interface Ethernet0/0
description to PE2
ip address 10.2.0.2 255.255.255.0
!
interface Loopback0
description customer LAN 10.2.2.0/24
ip address 10.2.2.1 255.255.255.0
!
ip route 0.0.0.0 0.0.0.0 10.2.0.1The Loopback0 /24 mask makes each loopback represent the whole customer LAN, so PE1's 10.1.1.0/24 static and PE2's 10.2.2.0/24 static resolve to a real next hop (10.1.0.2 / 10.2.0.2) and 10.2.2.1 is reachable end to end across the L3VPN.
Verification
Lead with the agent — one prompt walks the whole control plane and translates each vendor's output:
"Verify the MPLS L3VPN: OSPF + LDP in the core, VPNv4 routes on both PEs via the route reflector, and end-to-end reachability between CUSTA site 1 and site 2."
NetPilot checks each layer across all four routers in parallel and flags the first place the chain breaks. To verify by hand:
! PE1 (Cisco)
show mpls ldp neighbor
show bgp vpnv4 unicast all summary
show ip route vrf CUSTA
ping vrf CUSTA 10.2.2.1 source 10.1.0.1# PE2 (Juniper)
show ldp neighbor
show route table bgp.l3vpn.0
show route table CUSTA.inet.0Expected: LDP neighbors up across the core, the remote site's prefix in each PE's VRF table (learned via VPNv4), and a successful customer ping across the provider core — with the traffic carrying two labels (transport + VPN).
Common MPLS L3VPN gotchas
- Route-target mismatch. Import/export RTs must line up between the two PEs. A typo here is the classic "BGP is up, VPNv4 routes exist, but they're not in the VRF."
- Missing
send-community extended. No extended communities means no route-targets travel — the VPN silently fails. - RR drops VPNv4 routes. Without
no bgp default route-target filter, a route reflector with no local VRFs filters everything. Set it on every RR. - LDP not running on a core link. BGP next-hops resolve via the IGP, but with no label there's no LSP — packets are dropped at the first P hop. Check
show mpls ldp neighborend to end. - RD reused incorrectly. RDs only need to be unique to keep overlapping customer prefixes distinct; they do not control VPN membership — that's the RT's job. Mixing the two up is the most common conceptual error.
Build this lab with AI
Skip the four-router wiring and describe the service:
"Build a multi-vendor MPLS L3VPN. Cisco IOL PE1 and Juniper cRPD PE2 with a Cisco route reflector in the core. Run OSPF + LDP in the core, MP-BGP VPNv4 to the RR, and a VRF 'CUSTA' (RT 65000:100) with a CE site behind each PE. Verify customer site-to-site reachability and isolation from a second VRF."
NetPilot generates the core, the VPNv4 route reflector, the per-vendor VRFs, and PE-CE routing, deploys to cloud ContainerLab, and confirms the customer reachability — then you SSH in and trace the label stack yourself.
Copy-paste ready: Grab the MPLS L3VPN prompt from our example library — RD/RT variants and a second customer VRF included.
Want to lab MPLS without the setup? Run it in an online network lab, or let the AI network emulator generate the PE/CE configs from a prompt. Related: EVPN-VXLAN Data Center Fabric and FRRouting in the Cloud. Try NetPilot — describe any provider topology and get a working multi-vendor lab in ~2 minutes.