BGP – 6PE
1. Intro
We have a small service provider which is providing IPv4 internet services. It has a really simple design with a flat OSPF network, and internal iBGP session via a Route Reflector. No MPLS at this stage.

### Cust-A config:
root@R1# show protocols bgp | display set
set protocols bgp group eBGP type external
set protocols bgp group eBGP family inet unicast
set protocols bgp group eBGP export PS-BGP-EXPORT
set protocols bgp group eBGP peer-as 34569
set protocols bgp group eBGP neighbor 17.8.1.2
### PE config:
root@R3# show protocols ospf | display set
set protocols ospf traffic-engineering
set protocols ospf area 0.0.0.0 interface lo0.0 passive
set protocols ospf area 0.0.0.0 interface ge-0/0/4.0 interface-type p2p
set protocols ospf area 0.0.0.0 interface ge-0/0/4.0 metric 1000
set protocols ospf area 0.0.0.0 interface ge-0/0/5.0 interface-type p2p
set protocols ospf area 0.0.0.0 interface ge-0/0/5.0 metric 1000
root@R3# show protocols bgp | display set
set protocols bgp group iBGP type internal
set protocols bgp group iBGP local-address 17.0.0.3
set protocols bgp group iBGP family inet unicast
set protocols bgp group iBGP export BGP-NHS
set protocols bgp group iBGP neighbor 17.0.0.2
set protocols bgp group eBGP type external
set protocols bgp group eBGP family inet unicast
set protocols bgp group eBGP peer-as 100
set protocols bgp group eBGP neighbor 17.8.1.1
### RR config:
root@R2# show protocols bgp | display set
set protocols bgp group iBGP type internal
set protocols bgp group iBGP local-address 17.0.0.2
set protocols bgp group iBGP family inet unicast
set protocols bgp group iBGP family inet6 unicast
set protocols bgp group iBGP cluster 17.0.0.2
set protocols bgp group iBGP neighbor 17.0.0.3
set protocols bgp group iBGP neighbor 17.0.0.4
set protocols bgp group iBGP neighbor 17.0.0.5
set protocols bgp group iBGP neighbor 17.0.0.6
set protocols bgp group iBGP neighbor 17.0.0.9
### P router config:
root@R4# show protocols bgp | display set
set protocols bgp group iBGP type internal
set protocols bgp group iBGP local-address 17.0.0.4
set protocols bgp group iBGP family inet unicast
set protocols bgp group iBGP neighbor 17.0.0.2
### Ping works from Cust-A to Cust-B:
root@R1# run ping 192.70.1.1 source 192.10.1.1
PING 192.70.1.1 (192.70.1.1): 56 data bytes
64 bytes from 192.70.1.1: icmp_seq=0 ttl=60 time=6.124 ms
64 bytes from 192.70.1.1: icmp_seq=1 ttl=60 time=46.184 ms
64 bytes from 192.70.1.1: icmp_seq=2 ttl=60 time=5.973 ms
^C
--- 192.70.1.1 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 5.973/19.427/46.184/18.920 ms
### A TCP dump on one of the core links shows native IP (no MPLS):
12:25:02.075907 IP 192.10.1.1 > 192.70.1.1: ICMP echo request, id 38759, seq 0, length 64
12:25:02.078789 IP 192.70.1.1 > 192.10.1.1: ICMP echo reply, id 38759, seq 0, length 64
2. Dual-Stack IPv6
Now, we are being asked to add IPv6 to our network. One way to do it is with dual-stack deployment, where IPv4 and IPv6 run simultaneously.
### Cust-A Config:
set interfaces ge-0/0/2 unit 0 family inet6 address ::ffff:17.8.1.1/120
set protocols bgp group eBGP type external
set protocols bgp group eBGP family inet unicast
set protocols bgp group eBGP family inet6 unicast
set protocols bgp group eBGP export PS-BGP-EXPORT
set protocols bgp group eBGP peer-as 34569
set protocols bgp group eBGP neighbor 17.8.1.2
### Cust-B Config:
set interfaces ge-0/0/2 unit 0 family inet6 address 2001:db88:8:e::2/64
set protocols bgp group eBGPv6 type external
set protocols bgp group eBGPv6 family inet6 unicast
set protocols bgp group eBGPv6 export PS-BGP-EXPORT-v6
set protocols bgp group eBGPv6 peer-as 34569
set protocols bgp group eBGPv6 neighbor 2001:db88:8:e::1
### PE Config:
set interfaces ge-0/0/4 unit 0 family inet6 address 2001:db88:8:b::1/64
set interfaces ge-0/0/5 unit 0 family inet6 address 2001:db88:8:c::1/64
set interfaces lo0 unit 0 family inet6 address 2001:db88::3/128
set protocols ospf3 area 0.0.0.0 interface lo0.0 passive
set protocols ospf3 area 0.0.0.0 interface ge-0/0/4.0 interface-type p2p
set protocols ospf3 area 0.0.0.0 interface ge-0/0/4.0 metric 1000
set protocols ospf3 area 0.0.0.0 interface ge-0/0/5.0 interface-type p2p
set protocols ospf3 area 0.0.0.0 interface ge-0/0/5.0 metric 1000
set protocols bgp group eBGP type external
set protocols bgp group eBGP family inet unicast
set protocols bgp group eBGP family inet6 unicast
set protocols bgp group eBGP peer-as 100
set protocols bgp group eBGP neighbor 17.8.1.1
set protocols bgp group iBGPv6 type internal
set protocols bgp group iBGPv6 local-address 2001:db88::3
set protocols bgp group iBGPv6 family inet6 unicast
set protocols bgp group iBGPv6 export BGP-NHS
set protocols bgp group iBGPv6 neighbor 2001:db88::2
### RR config:
set interfaces ge-0/0/3 unit 0 family inet6 address 2001:db88:8:9::1/64
set interfaces lo0 unit 0 family inet6 address 2001:db88::2/128
set protocols ospf3 area 0.0.0.0 interface lo0.0 passive
set protocols ospf3 area 0.0.0.0 interface ge-0/0/3.0 interface-type p2p
set protocols ospf3 area 0.0.0.0 interface ge-0/0/3.0 metric 1000
set protocols bgp group iBGPv6 type internal
set protocols bgp group iBGPv6 local-address 2001:db88::2
set protocols bgp group iBGPv6 family inet6 unicast
set protocols bgp group iBGPv6 cluster 17.0.0.2
set protocols bgp group iBGPv6 neighbor 2001:db88::3
set protocols bgp group iBGPv6 neighbor 2001:db88::4
set protocols bgp group iBGPv6 neighbor 2001:db88::5
set protocols bgp group iBGPv6 neighbor 2001:db88::6
set protocols bgp group iBGPv6 neighbor 2001:db88::9
### P router config:
set interfaces lo0 unit 0 family inet6 address 2001:db88::4/128
set protocols bgp group iBGPv6 type internal
set protocols bgp group iBGPv6 local-address 2001:db88::4
set protocols bgp group iBGPv6 family inet6 unicast
set protocols bgp group iBGPv6 neighbor 2001:db88::2
set protocols ospf3 area 0.0.0.0 interface ge-0/0/4.0 interface-type p2p
set protocols ospf3 area 0.0.0.0 interface ge-0/0/4.0 metric 1000
set protocols ospf3 area 0.0.0.0 interface ge-0/0/2.0 interface-type p2p
set protocols ospf3 area 0.0.0.0 interface ge-0/0/2.0 metric 1000
set protocols ospf3 area 0.0.0.0 interface ge-0/0/3.0 interface-type p2p
set protocols ospf3 area 0.0.0.0 interface ge-0/0/3.0 metric 1000
### Ping works from Cust-A to Cust-B:
root@R1# run ping 2001:db8:70::1 source 2001:db8:10::1
PING6(56=40+8+8 bytes) 2001:db8:10::1 --> 2001:db8:70::1
16 bytes from 2001:db8:70::1, icmp_seq=0 hlim=60 time=6.231 ms
16 bytes from 2001:db8:70::1, icmp_seq=1 hlim=60 time=7.420 ms
16 bytes from 2001:db8:70::1, icmp_seq=2 hlim=60 time=6.072 ms
^C
--- 2001:db8:70::1 ping6 statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/std-dev = 6.072/6.574/7.420/0.601 ms
### A TCP dump on one of the core links shows native IP (no MPLS):
14:08:29.615648 IP6 2001:db8:10::1 > 2001:db8:70::1: ICMP6, echo request, id 34040, seq 4, length 16
14:08:29.617984 IP6 2001:db8:70::1 > 2001:db8:10::1: ICMP6, echo reply, id 34040, seq 4, length 16
3. 6PE
Our service provider want’s to take advantage of MPLS, this means that we will use 6PE instead of our dual-stack deployment.
Rollback config to IPv4 only, and add 6PE instead:
### Rollback and delete the 'dual-stack' config:
delete protocols bgp group iBGPv6
delete protocols ospf3
delete interfaces lo0 unit 0 family inet6
delete interfaces ge-0/0/4 unit 0 family inet6
delete interfaces ge-0/0/5 unit 0 family inet6
### We also need to activate mpls and LDP on all routers core interfaces:
set interfaces ge-0/0/4 unit 0 family mpls
set interfaces ge-0/0/5 unit 0 family mpls
set protocols ldp track-igp-metric
set protocols ldp transport-address router-id
set protocols ldp interface ge-0/0/4.0
set protocols ldp interface ge-0/0/5.0
set protocols ldp interface lo0.0
set protocols mpls interface lo0.0
set protocols mpls interface ge-0/0/4.0
set protocols mpls interface ge-0/0/5.0
At this stage, of course there is no more IPv6 forwarding, but how about IPv4?
### IPv4 ping works:
root@R1# run ping 192.70.1.1 source 192.10.1.1
PING 192.70.1.1 (192.70.1.1): 56 data bytes
64 bytes from 192.70.1.1: icmp_seq=0 ttl=60 time=6.284 ms
64 bytes from 192.70.1.1: icmp_seq=1 ttl=60 time=7.182 ms
64 bytes from 192.70.1.1: icmp_seq=2 ttl=60 time=6.174 ms
^C
--- 192.70.1.1 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 6.174/6.547/7.182/0.451 ms
### But, since we activated MPLS/LDP, with tcmdump we can see label forwarding:
14:51:42.057389 MPLS (label 299776, exp 0, [S], ttl 62) IP 192.10.1.1 > 192.70.1.1: ICMP echo request, id 13322, seq 6, length 64
14:51:42.060298 MPLS (label 301008, exp 0, [S], ttl 62) IP 192.70.1.1 > 192.10.1.1: ICMP echo reply, id 13322, seq 6, length 64
### This means we can now have a BGP free core
### We can deactivate BGP on the P routers:
root@R4# delete protocols bgp
root@R4# commit
root@R5# delete protocols bgp
root@R5# commit
root@R9# delete protocols bgp
root@R9# commit
### IPv4 still works:
root@R1# run ping 192.70.1.1 source 192.10.1.1
PING 192.70.1.1 (192.70.1.1): 56 data bytes
64 bytes from 192.70.1.1: icmp_seq=0 ttl=60 time=6.333 ms
64 bytes from 192.70.1.1: icmp_seq=1 ttl=60 time=5.428 ms
64 bytes from 192.70.1.1: icmp_seq=2 ttl=60 time=42.430 ms
^C
--- 192.70.1.1 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 5.428/18.064/42.430/17.234 ms
Before we activate 6PE, let’s check some BGP prefixes:
### On the PE router (R3), we are receiving the IPv6 prefix from Cust-A:
root@R3# run show route protocol bgp
inet.0: 36 destinations, 36 routes (36 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
192.10.1.0/24 *[BGP/170] 22:59:05, localpref 100
AS path: 100 I, validation-state: unverified
> to 17.8.1.1 via ge-0/0/1.0
192.70.1.0/24 *[BGP/170] 00:21:52, localpref 100, from 17.0.0.2
AS path: 700 I, validation-state: unverified
> to 17.8.11.2 via ge-0/0/4.0, Push 300992
inet.3: 3 destinations, 3 routes (3 active, 0 holddown, 0 hidden)
mpls.0: 8 destinations, 8 routes (8 active, 0 holddown, 0 hidden)
inet6.0: 15 destinations, 15 routes (15 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
2001:db8:10::/48 *[BGP/170] 01:00:49, localpref 100, from 17.8.1.1
AS path: 100 I, validation-state: unverified
> to ::ffff:17.8.1.1 via ge-0/0/1.0
### But the prefix is not crossing to the other side of the network, to the remote PE:
root@R6# run show route protocol bgp
inet.0: 36 destinations, 36 routes (36 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
192.10.1.0/24 *[BGP/170] 00:24:55, localpref 100, from 17.0.0.2
AS path: 100 I, validation-state: unverified
> to 17.8.13.1 via ge-0/0/2.0, Push 300400
192.70.1.0/24 *[BGP/170] 03:28:27, localpref 100
AS path: 700 I, validation-state: unverified
> to 17.8.14.2 via ge-0/0/3.0
inet.3: 3 destinations, 3 routes (3 active, 0 holddown, 0 hidden)
mpls.0: 8 destinations, 8 routes (8 active, 0 holddown, 0 hidden)
inet6.0: 13 destinations, 13 routes (13 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
2001:db8:70::/48 *[BGP/170] 03:27:54, localpref 100
AS path: 700 I, validation-state: unverified
> to 2001:db88:8:e::2 via ge-0/0/3.0
### Let's check the RR:
root@R2# run show route hidden
inet.0: 35 destinations, 35 routes (35 active, 0 holddown, 0 hidden)
iso.0: 2 destinations, 2 routes (2 active, 0 holddown, 0 hidden)
mpls.0: 4 destinations, 4 routes (4 active, 0 holddown, 0 hidden)
inet6.0: 14 destinations, 14 routes (12 active, 0 holddown, 2 hidden)
+ = Active Route, - = Last Active, * = Both
2001:db8:10::/48 [BGP/170] 00:18:06, localpref 100, from 17.0.0.3
AS path: 100 I, validation-state: unverified
Unusable
2001:db8:70::/48 [BGP/170] 00:21:37, localpref 100, from 17.0.0.6
AS path: 700 I, validation-state: unverified
Unusable
### The IPv6 next hop is unusable by the route reflector:
root@R2# run show route 2001:db8:10::/48 extensive hidden
inet6.0: 14 destinations, 14 routes (12 active, 0 holddown, 2 hidden)
2001:db8:10::/48 (1 entry, 0 announced)
BGP Preference: 170/-101
Next hop type: Unusable, Next hop index: 0
Address: 0x7bbd5b4
Next-hop reference count: 2, key opaque handle: 0x0, non-key opaque handle: 0x0
Kernel Table Id: 0
Source: 17.0.0.3
State: <Hidden Int Ext Changed>
Local AS: 34569 Peer AS: 34569
Age: 27:19
Validation State: unverified
Task: BGP_34569.17.0.0.3
AS path: 100 I
Accepted
Route Label: 2
Localpref: 100
Router ID: 17.0.0.3
Thread: junos-main
Indirect next hops: 1
Protocol next hop: ::ffff:17.0.0.3 ResolvState: PnhUnresolv
Label operation: Push 2
Label TTL action: prop-ttl
Load balance label: Label 2: None;
Indirect next hop: 0x0 - INH Session ID: 0
### Resolution should happen on the inet6.3 table, but it is empty:
root@R2# run show route table inet6.3
[edit]
root@R2#
root@R3# run show route table inet6.3
[edit]
root@R3#
We can finally implement 6PE:
### As per JunOS documentation, inet6 labeled-unicast was already added to BGP, on PE and RR:
set protocols bgp group iBGP family inet6 labeled-unicast explicit-null
### Next, we need to activate 'ipv6-tunneling'.
### This command will basically copy IPv4 next-hops from inet.3 to inet6.3:
root@R3# set protocols mpls ipv6-tunneling
[edit]
root@R3# commit
commit complete
root@R3# run show route table inet6.3
inet6.3: 3 destinations, 3 routes (3 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
::ffff:17.0.0.4/128*[LDP/9] 00:00:06, metric 1000
> to 17.8.11.2 via ge-0/0/4.0
::ffff:17.0.0.5/128*[LDP/9] 00:00:06, metric 2000
> to 17.8.11.2 via ge-0/0/4.0, Push 300976
::ffff:17.0.0.6/128*[LDP/9] 00:00:06, metric 3000
> to 17.8.11.2 via ge-0/0/4.0, Push 300992
### After doing the same on the RR and the remote PE, now we can check the RR:
root@R2# run show route table inet6.3
inet6.3: 4 destinations, 4 routes (4 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
::ffff:17.0.0.3/128*[LDP/9] 00:00:02, metric 2000
> to 17.8.9.2 via ge-0/0/3.0, Push 301008
::ffff:17.0.0.4/128*[LDP/9] 00:00:02, metric 1000
> to 17.8.9.2 via ge-0/0/3.0
::ffff:17.0.0.5/128*[LDP/9] 00:00:02, metric 2000
> to 17.8.9.2 via ge-0/0/3.0, Push 300976
::ffff:17.0.0.6/128*[LDP/9] 00:00:02, metric 3000
> to 17.8.9.2 via ge-0/0/3.0, Push 300992
### Prefises are no longer hidden:
root@R2# run show route protocol bgp
inet.0: 35 destinations, 35 routes (35 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
192.10.1.0/24 *[BGP/170] 00:39:21, localpref 100, from 17.0.0.3
AS path: 100 I, validation-state: unverified
> to 17.8.9.2 via ge-0/0/3.0, Push 301008
192.70.1.0/24 *[BGP/170] 00:42:52, localpref 100, from 17.0.0.6
AS path: 700 I, validation-state: unverified
> to 17.8.9.2 via ge-0/0/3.0, Push 300992
inet.3: 4 destinations, 4 routes (4 active, 0 holddown, 0 hidden)
mpls.0: 9 destinations, 9 routes (9 active, 0 holddown, 0 hidden)
inet6.0: 14 destinations, 14 routes (14 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
2001:db8:10::/48 *[BGP/170] 00:00:14, localpref 100, from 17.0.0.3
AS path: 100 I, validation-state: unverified
> to 17.8.9.2 via ge-0/0/3.0, Push 2, Push 301008(top)
2001:db8:70::/48 *[BGP/170] 00:00:14, localpref 100, from 17.0.0.6
AS path: 700 I, validation-state: unverified
> to 17.8.9.2 via ge-0/0/3.0, Push 2, Push 300992(top)
inet6.3: 4 destinations, 4 routes (4 active, 0 holddown, 0 hidden)
### Next-Hop resolution is now OK:
root@R2# run show route 2001:db8:10::/48 extensive
inet6.0: 14 destinations, 14 routes (14 active, 0 holddown, 0 hidden)
2001:db8:10::/48 (1 entry, 1 announced)
TSI:
KRT in-kernel 2001:db8:10::/48 -> {indirect(1048577)}
Page 0 idx 0, (group iBGP type Internal) Type 1 val 0x9f27480 (adv_entry)
Advertised metrics:
Nexthop: ::ffff:17.0.0.3
Localpref: 100
AS path: [34569] 100 I
Communities:
Cluster ID: 17.0.0.2
Originator ID: 17.0.0.3
Label: 2
Advertise: 00000008
Path 2001:db8:10::
from 17.0.0.3
Vector len 4. Val: 0
*BGP Preference: 170/-101
Next hop type: Indirect, Next hop index: 0
Address: 0x7bbece4
Next-hop reference count: 2, key opaque handle: 0x0, non-key opaque handle: 0x0
Kernel Table Id: 0
Source: 17.0.0.3
Next hop type: Router, Next hop index: 634
Next hop: 17.8.9.2 via ge-0/0/3.0, selected
Label operation: Push 2, Push 301008(top)
Label TTL action: prop-ttl, prop-ttl(top)
Load balance label: Label 2: None; Label 301008: None;
Label element ptr: 0x9f49e78
Label parent element ptr: 0x9eecab0
Label element references: 1
Label element child references: 0
Label element lsp id: 0
Session Id: 14d
Protocol next hop: ::ffff:17.0.0.3
Label operation: Push 2
Label TTL action: prop-ttl
Load balance label: Label 2: None;
Indirect next hop: 0x8498c88 1048577 INH Session ID: 351
State: <Active Int Ext>
Local AS: 34569 Peer AS: 34569
Age: 24 Metric2: 2000
Validation State: unverified
Task: BGP_34569.17.0.0.3
Announcement bits (3): 0-KRT 2-BGP_RT_Background 3-Resolve tree 5
AS path: 100 I
Accepted
Route Label: 2
Localpref: 100
Router ID: 17.0.0.3
Thread: junos-main
Indirect next hops: 1
Protocol next hop: ::ffff:17.0.0.3 Metric: 2000 ResolvState: Resolved
Label operation: Push 2
Label TTL action: prop-ttl
Load balance label: Label 2: None;
Indirect next hop: 0x8498c88 1048577 INH Session ID: 351
Indirect path forwarding next hops: 1
Next hop type: Router
Next hop: 17.8.9.2 via ge-0/0/3.0
Session Id: 14d
::ffff:17.0.0.3/128 Originating RIB: inet6.3
Metric: 2000 Node path count: 1
Forwarding nexthops: 1
Next hop type: Router
Next hop: 17.8.9.2 via ge-0/0/3.0
Session Id: 14d
### Control plane now looks ok, let's test with a ping:
root@R1# run ping 2001:db8:70::1 source 2001:db8:10::1
PING6(56=40+8+8 bytes) 2001:db8:10::1 --> 2001:db8:70::1
^C
--- 2001:db8:70::1 ping6 statistics ---
25 packets transmitted, 0 packets received, 100% packet loss
### We need to do one more thing. We must activate IPv6 forwarding on our core interfaces.
### We don't need a complicated addressing plan, we just need to activate link local addressing:
root@R3# show | compare
[edit interfaces ge-0/0/4 unit 0]
+ family inet6;
[edit interfaces ge-0/0/5 unit 0]
+ family inet6;
[edit]
root@R3# commit
commit complete
### The same was done on all routers, all core interfaces.
### Now ping works:
root@R1# run ping 2001:db8:70::1 source 2001:db8:10::1
PING6(56=40+8+8 bytes) 2001:db8:10::1 --> 2001:db8:70::1
16 bytes from 2001:db8:70::1, icmp_seq=0 hlim=60 time=6.322 ms
16 bytes from 2001:db8:70::1, icmp_seq=1 hlim=60 time=5.623 ms
16 bytes from 2001:db8:70::1, icmp_seq=2 hlim=60 time=6.191 ms
^C
--- 2001:db8:70::1 ping6 statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/std-dev = 5.623/6.045/6.322/0.303 ms
### TCP Dump shows the labels being used, including the explicit null label (2):
15:33:10.677484 MPLS (label 299776, exp 0, ttl 62) (label 2, exp 0, [S], ttl 63) IP6 2001:db8:10::1 > 2001:db8:70::1: ICMP6, echo request, id 5503, seq 4, length 16
15:33:10.679685 MPLS (label 301008, exp 0, ttl 62) (label 2, exp 0, [S], ttl 63) IP6 2001:db8:70::1 > 2001:db8:10::1: ICMP6, echo reply, id 5503, seq 4, length 16
Conclusion
There is a good chance that you will already have in place the prerequisites: BGP (inet unicast), IGP protocol (OSPF, ISIS), MPLS (LDP, RSVP or SR).
If that is the case, then you only need to add:
- BGP ->
family inet6 labeled-unicast explicit-null - MPLS ->
mpls ipv6-tunneling - Interface link local ->
interfaces ge-0/0/x unit 0 family inet6
External Resources: