BGP

IPv6 over BGP: MP-BGP for IPv6 and 6PE Explained

6PE - IPv6 traceroute showing an MPLS label across an IPv4-only core on Cisco IOS XE
In: BGP, Labs, CCIE, IPv6, MPLS

Here is a problem that a great many service providers had, and some still have: a fully working, fully tuned, IPv4-only MPLS core, and customers who want IPv6. Upgrading every P router in the core to dual-stack is expensive, risky, and touches the one part of the network you least want to touch.

6PE is the answer. It carries IPv6 prefixes across an untouched IPv4 MPLS core by encapsulating them in MPLS labels, exchanged over MP-BGP. The P routers in the middle never learn a single IPv6 route and never even know IPv6 is involved. This article builds a working 6PE deployment on Cisco IOS XE in CML and shows the labels, the IPv4-mapped next-hops, and an end-to-end IPv6 traceroute crossing the v4 core. For the fundamentals, start at the complete BGP guide; for the MPLS side, see the MPLS pillar.

MP-BGP: the foundation

BGP-4 as originally specified could only carry IPv4. Multiprotocol BGP (RFC 4760) added two attributes - MP_REACH_NLRI and MP_UNREACH_NLRI - which carry an address family identifier plus the reachability information for that family. One BGP session, many address families.

This is the same machinery that carries VPNv4 for MPLS L3VPN, VPNv6 for 6VPE, and L2VPN signalling. IPv6 unicast is just another AFI/SAFI riding the same session.

The key insight for 6PE: the BGP session itself can run over IPv4 while carrying IPv6 NLRI. The transport and the payload are independent.

Plain MP-BGP for IPv6 (no MPLS)

If your core is dual-stacked, you do not need 6PE at all. You just enable the IPv6 address family:

router bgp 65001
 neighbor 2001:DB8:13::2 remote-as 100
 !
 address-family ipv6
  network 2001:DB8:10::/64
  neighbor 2001:DB8:13::2 activate
 exit-address-family

Note no bgp default ipv4-unicast is best practice here - without it, IOS tries to activate every neighbour in the IPv4 unicast AF, including your IPv6 peers, which produces confusing half-broken sessions.

And note the thing that catches everyone: a neighbour is defined globally but must be activated per address family. Forget the activate and the session will not even come up. We prove that in the troubleshooting section below.

6PE: the architecture

6PE (RFC 4798) has four moving parts:

The core (P routers)
IPv4 only. IGP + LDP. Never sees an IPv6 route, never runs an IPv6 process. Completely untouched.
The edge (6PE routers)
Dual stack. Speaks IPv6 to customers, IPv4 + MPLS to the core. This is the only place IPv6 exists inside the provider.
The iBGP session
Runs over IPv4 between the 6PE loopbacks. Carries the IPv6 unicast AF with send-label.
The label stack
Outer label = LDP label to the remote 6PE loopback (the core understands this). Inner label = the BGP-assigned IPv6 label (only the egress 6PE understands this).

The magic trick is the next-hop. When a 6PE advertises an IPv6 prefix over an IPv4 iBGP session, it must set an IPv6 next-hop. It uses an IPv4-mapped IPv6 address: ::FFFF:4.4.4.4. The receiving 6PE strips off the ::FFFF: prefix, recovers 4.4.4.4, looks that up in its IPv4 LFIB, and finds the LDP label-switched path to it. Now it has a way to send IPv6 packets across an IPv4 core.

The lab

ISP-A is AS 100, with two 6PE routers (R3 and R4) and an IPv4-only, LDP-enabled core link between them. R1 (customer, AS 65001) hangs off R3 with IPv6. R6 (customer, AS 300) hangs off R4 with IPv6. Neither customer knows the core is IPv4.

Core configuration (IPv4 + LDP only)

mpls label protocol ldp
!
interface Ethernet0/2
 description TO-R4-MPLS-CORE
 ip address 10.0.34.1 255.255.255.252
 mpls ip
!
router ospf 1
 network 3.3.3.3 0.0.0.0 area 0
 network 10.0.34.0 0.0.0.3 area 0

Note what is not there: no ipv6 address on the core interface, no IPv6 in OSPF. The core link is IPv4, full stop.

6PE configuration on R3

router bgp 100
 no bgp default ipv4-unicast
 neighbor 4.4.4.4 remote-as 100
 neighbor 4.4.4.4 update-source Loopback0
 neighbor 2001:DB8:13::1 remote-as 65001
 !
 address-family ipv4
  neighbor 4.4.4.4 activate
  neighbor 4.4.4.4 next-hop-self
 exit-address-family
 !
 address-family ipv6
  neighbor 4.4.4.4 activate
  neighbor 4.4.4.4 send-label
  neighbor 4.4.4.4 next-hop-self
  neighbor 2001:DB8:13::1 activate
 exit-address-family

Look at the IPv6 address family. The neighbour activated there is 4.4.4.4 - an IPv4 address. That is the whole trick, in one line. The session is IPv4; the payload is IPv6.

The three commands that make 6PE 6PE:

  • send-label - this is the one that turns MP-BGP for IPv6 into 6PE. It tells BGP to allocate and advertise an MPLS label with each IPv6 prefix. Without it, you have plain MP-BGP IPv6 over an IPv4 session, and no way to forward the packets.
  • next-hop-self - required, because the receiving PE must resolve the next-hop to a loopback it has a label-switched path to.
  • update-source Loopback0 - the LSP terminates on the loopback, so the BGP next-hop must be the loopback.

Verification: the labels

On R3, the BGP IPv6 table with labels:

R3#show bgp ipv6 unicast labels
   Network          Next Hop      In label/Out label
   2001:DB8:10::/64 2001:DB8:13::1  17/nolabel
   2001:DB8:60::/64 ::FFFF:4.4.4.4  nolabel/17

Two lines, two directions:

  • 2001:DB8:10::/64 is R1's prefix, learned from the customer over native IPv6. R3 allocated label 17 for it (the in label) and will advertise that label to R4. There is no out label because the next hop is a directly connected customer, not another LSP.
  • 2001:DB8:60::/64 is R6's prefix, learned from R4 over the iBGP session. The next-hop is ::FFFF:4.4.4.4 - there is the IPv4-mapped address, exactly as advertised. The out label is 17: that is the label R4 allocated, and R3 must push it.

The detail view makes the mechanism explicit:

R3#show bgp ipv6 unicast 2001:DB8:60::/64
BGP routing table entry for 2001:DB8:60::/64, version 2
Paths: (1 available, best #1, table default)
  300
    ::FFFF:4.4.4.4 (metric 11) from 4.4.4.4 (4.4.4.4)
      Origin IGP, metric 0, localpref 100, valid, internal, best
      mpls labels in/out nolabel/17

(metric 11) is the OSPF cost to 4.4.4.4. R3 resolved an IPv6 next-hop through the IPv4 IGP. That sentence is the entirety of 6PE.

The LFIB

R3#show mpls forwarding-table
Local      Outgoing   Prefix           Bytes Label   Outgoing   Next Hop
Label      Label      or Tunnel Id     Switched      interface
16         Pop Label  4.4.4.4/32       0             Et0/2      10.0.34.2
17         No Label   2001:DB8:10::/64 882           Et0/0      FE80::A8BB:CCFF:FE00:3A10

Label 16 is an ordinary LDP label for the IPv4 loopback 4.4.4.4 - the transport label. Label 17 is the BGP-assigned IPv6 label: packets arriving with label 17 get it popped and are forwarded as native IPv6 out to the customer.

R4 is the mirror image:

R4#show bgp ipv6 unicast labels
   Network          Next Hop      In label/Out label
   2001:DB8:10::/64 ::FFFF:3.3.3.3  nolabel/17
   2001:DB8:60::/64 2001:DB8:46::2  17/nolabel

Verification: end to end

From R1 (customer, IPv6 only, no idea MPLS exists) to R6 (customer on the far side):

R1#show bgp ipv6 unicast
     Network          Next Hop            Metric LocPrf Weight Path
 *>   2001:DB8:10::/64 ::                       0         32768 i
 *>   2001:DB8:60::/64 2001:DB8:13::2                         0 100 300 i

R1#ping 2001:DB8:60::1 source Loopback10
Sending 5, 100-byte ICMP Echos to 2001:DB8:60::1, timeout is 2 seconds:
Packet sent with a source address of 2001:DB8:10::1
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 3/3/5 ms

And the traceroute, which is the single most satisfying output in this entire article:

R1#traceroute 2001:DB8:60::1 source 2001:DB8:10::1 probe 1 timeout 2
Tracing the route to 2001:DB8:60::1

  1 2001:DB8:13::2 3 msec
  2 2001:DB8:46::1 [MPLS: Label 17 Exp 0] 4 msec
  3 2001:DB8:46::2 4 msec

Hop 2 shows [MPLS: Label 17 Exp 0]. An IPv6 traceroute, reporting an MPLS label, from a customer router that has never been configured with MPLS - because the ICMP time-exceeded came back from a router that was label-switching the packet. The IPv6 packet crossed an IPv4 core inside a label. That is 6PE working.

Note that from R1's perspective the core is a single hop. The P routers do not decrement the IPv6 hop limit, because they never look at the IPv6 header. This is normal MPLS behaviour and it is why an MPLS core appears "flat" in traceroute.

6PE vs 6VPE vs dual-stack

6PE
Address family: ipv6 unicast + send-label
Isolation: none - global table
Use when: you provide IPv6 internet transit over a v4 MPLS core
6VPE
Address family: vpnv6 unicast
Isolation: full - per-VRF, with RDs and RTs
Use when: you sell IPv6 L3VPN to multiple customers
Dual-stack core
Address family: native IPv6 everywhere
Isolation: none
Use when: you are building new, or you can afford to touch every P router

6PE is a migration technology, and a very good one. It buys you IPv6 service delivery without a core upgrade. But it is not the destination: a dual-stack core is simpler to operate, simpler to troubleshoot, and does not depend on a label stack for basic reachability. Treat 6PE as the bridge, not the bank of the river.

Troubleshooting 6PE

  1. Session will not come up. Did you activate the neighbour in the IPv6 address family? With no bgp default ipv4-unicast set, a neighbour that is not activated in any AF has nothing to talk about, and the session goes to Idle. We demonstrate this exact failure in the expert BGP troubleshooting article.
  2. Prefixes present, forwarding broken. You are missing send-label. Run show bgp ipv6 unicast labels - if every line says nolabel/nolabel, that is your answer.
  3. Next-hop inaccessible. The next-hop is ::FFFF:<ipv4> and must resolve through the IPv4 IGP with a label-switched path. Check show mpls ldp neighbor and show mpls forwarding-table for the remote loopback. No LSP, no 6PE.
  4. Missing next-hop-self. If the 6PE passes the customer's link-local or global next-hop through untouched, the remote PE has no LSP to it. Always next-hop-self on the 6PE iBGP session.
  5. LDP not labelling the loopback. The loopback must be a /32 in the IGP and LDP must have a binding for it. show mpls ldp bindings 4.4.4.4 32.

Key takeaways

  • 6PE carries IPv6 across an IPv4-only MPLS core. The P routers are never touched and never learn an IPv6 route.
  • The iBGP session between 6PE routers runs over IPv4 and carries the IPv6 unicast address family. Activate an IPv4 neighbour inside address-family ipv6 - that looks wrong and is exactly right.
  • send-label is the command that makes it 6PE. Without it you have MP-BGP IPv6 with no forwarding path.
  • The next-hop is an IPv4-mapped IPv6 address, ::FFFF:x.x.x.x, which the receiving PE resolves through the IPv4 IGP and the LDP LSP.
  • Two labels: the LDP transport label to the remote loopback, and the BGP IPv6 label the egress PE assigned.
  • show bgp ipv6 unicast labels is the single most useful verification command. An IPv6 traceroute showing [MPLS: Label n] is the proof.
  • 6PE is global-table IPv6 transit. If you need per-customer isolation, that is 6VPE and the VPNv6 address family.

Next: five broken BGP scenarios, ticket style. The full cluster index lives on the BGP pillar guide, and the MPLS side of this story is on the MPLS pillar.

Written by
More from Ping Labz
Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to Ping Labz.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.