When IPv6 global-unicast addresses are unavailable in a network and there is a need to pass IPv6 traffic, typically, IPv4-mapped IPv6 addresses are assigned based on the existing IPv4 address assignments. However, this could cause a difference in the IPv4 and IPv6 next-hop information, and result in unexpected exclave of the IPv6 subnet.
This article describes a pitfall in developing networks by using IPv4-mapped IPv6 addresses and suggests possible solutions.
A customer migrates the IPv4 network to IPv4/v6 dual stack network by using an IPv4-mapped IPv6 address.
An example topology is as follows:
+----------------------+ point-to-point +---------------+ ::ffff:203.0.113.0/120 +---------------+ | R1 |gr-0/0/0.0 gr-0/0/0.0| R2 |.20 203.0.113.16/28 .21| R3 | | +--------------------------+ +-------------------------------+ | | 203.0.113.251 |ge-0/0/1 ge-0/0/1| 203.0.113.252 |ge-0/0/0 ge-0/0/0| 203.0.113.253 | | ::ffff:203.0.113.251 | | | | | +----------------------+ +---------------+ +---------------+ aggregate ::/0 MP-BGP MP-BGP <-----------iBGP---------> <-------------eBGP------------> ===> ===> advertise ::/0 advertise ::/0
The router R2 learns IPv6 routes from R1 and advertises them but unlike the IPv4 route, R2's next-hops indicate the loopback address of R1 instead of its own address.
lab@R2> show route advertising-protocol bgp 203.0.113.21 inet.0: 14 destinations, 18 routes (14 active, 0 holddown, 1 hidden) Prefix Nexthop MED Lclpref AS path * 0.0.0.0/0 Self I * 100.0.0.0/8 Self I inet6.0: 12 destinations, 14 routes (12 active, 0 holddown, 0 hidden) Prefix Nexthop MED Lclpref AS path * ::/0 ::ffff:203.0.113.251 I * 1000::/8 ::ffff:203.0.113.251 I
Since R2 advertises IPv6 routes as shown above, R3 learns the routes with the next-hop being set to R1's loopback address.
Note: R2 does not have a routing policy to modify the next-hop to "self."
lab@R3> show route receive-protocol bgp 203.0.113.20 inet.0: 11 destinations, 11 routes (11 active, 0 holddown, 0 hidden) Prefix Nexthop MED Lclpref AS path * 0.0.0.0/0 203.0.113.20 65001 I * 100.0.0.0/8 203.0.113.20 65001 I inet6.0: 8 destinations, 8 routes (8 active, 0 holddown, 0 hidden) Prefix Nexthop MED Lclpref AS path * ::/0 ::ffff:203.0.113.251 65001 I * 1000::/8 ::ffff:203.0.113.251 65001 I lab@R3> ping 1000::1 source 3333::3 rapid PING6(56=40+8+8 bytes) 3333::3 --> 1000::1 ..... --- 1000::1 ping6 statistics --- 5 packets transmitted, 0 packets received, 100% packet loss
In this scenario, the IPv6 routes in question are carried over the external IPv4 MP-BGP session between R2 and R3. However, the gotcha is that the address ::ffff:203.0.113.251 that is showing up as the next-hop is lying under the IPv6 subnet ::ffff:203.0.113.0/120 between R2 and R3.
When R2 sees the next-hop address of IPv6 routes from R1, R2 thinks that the next-hop address belongs to the IPv6 subnet toward R3. Therefore, R2 throws ::/0 with the next-hop address ::ffff:203.0.113.251 towards R3 due to which you will see R1's loopback address as the next-hop of ::/0 in R3.
This process is not for R2's RIB resolution, but R2's route advertising calculation perspective.
This behavior is by design and expected. The problem arises when R1's IPv4-mapped loopback address becomes an exclave of R2's directly connected network.
To work around this situation, some options that are available are as follows:
Changing R1's loopback IPv4-mapped address to out-of-prefix from ::ffff:203.0.113.0/120
Changing the R2--R3 link prefix-length to a much narrower range, so that it does not include ::ffff:203.0.113.251
Each of these options and the possible configuration workarounds are given as follows:
Option A
Skipped since it is the obvious solution
[R1]
set interfaces lo0 unit 0 family inet address 198.51.100.251/32 set routing-options router-id 198.51.100.251 set protocols bgp group AS65001 local-address 198.51.100.251
[R2]
set routing-options rib inet6.0 static route ::ffff:198.51.100.251/128 next-hop gr-0/0/0.0 set routing-options static route 198.51.100.251/32 next-hop 192.168.100.10 set protocols bgp group AS65001 neighbor 198.51.100.251 peer-as 65001
lab@R2> show route advertising-protocol bgp 203.0.113.21 inet.0: 14 destinations, 18 routes (14 active, 0 holddown, 1 hidden) Prefix Nexthop MED Lclpref AS path * 0.0.0.0/0 Self I * 100.0.0.0/8 Self I inet6.0: 14 destinations, 16 routes (14 active, 0 holddown, 1 hidden) Prefix Nexthop MED Lclpref AS path * ::/0 Self I * 1000::/8 Self I lab@R3> show route receive-protocol bgp 203.0.113.20 inet.0: 11 destinations, 11 routes (11 active, 0 holddown, 0 hidden) Prefix Nexthop MED Lclpref AS path * 0.0.0.0/0 203.0.113.20 65001 I * 100.0.0.0/8 203.0.113.20 65001 I inet6.0: 9 destinations, 9 routes (9 active, 0 holddown, 0 hidden) Prefix Nexthop MED Lclpref AS path * ::/0 ::ffff:203.0.113.20 65001 I * 1000::/8 ::ffff:203.0.113.20 65001 I lab@R3> ping 1000::1 source 3333::3 rapid PING6(56=40+8+8 bytes) 3333::3 --> 1000::1 !!!!! --- 1000::1 ping6 statistics --- 5 packets transmitted, 5 packets received, 0% packet loss round-trip min/avg/max/std-dev = 2.523/26.049/77.999/30.221 ms
set interfaces ge-0/0/0 unit 0 family inet6 address ::ffff:203.0.113.20/124
[R3]
set interfaces ge-0/0/0 unit 0 family inet6 address ::ffff:203.0.113.21/124 lab@R2> show route advertising-protocol bgp 203.0.113.21 inet.0: 14 destinations, 18 routes (14 active, 0 holddown, 1 hidden) Prefix Nexthop MED Lclpref AS path * 0.0.0.0/0 Self I * 100.0.0.0/8 Self I inet6.0: 14 destinations, 14 routes (14 active, 0 holddown, 0 hidden) Prefix Nexthop MED Lclpref AS path * ::/0 Self I * 1000::/8 Self I lab@R3> show route receive-protocol bgp 203.0.113.20 inet.0: 11 destinations, 11 routes (11 active, 0 holddown, 0 hidden) Prefix Nexthop MED Lclpref AS path * 0.0.0.0/0 203.0.113.20 65001 I * 100.0.0.0/8 203.0.113.20 65001 I inet6.0: 9 destinations, 9 routes (9 active, 0 holddown, 0 hidden) Prefix Nexthop MED Lclpref AS path * ::/0 ::ffff:203.0.113.20 65001 I * 1000::/8 ::ffff:203.0.113.20 65001 I lab@R3> ping 1000::1 source 3333::3 rapid PING6(56=40+8+8 bytes) 3333::3 --> 1000::1 !!!!! --- 1000::1 ping6 statistics --- 5 packets transmitted, 5 packets received, 0% packet loss round-trip min/avg/max/std-dev = 2.725/3.557/6.085/1.280 ms
Option D
set policy-options policy-statement nhs term 10 from family inet6 set policy-options policy-statement nhs term 10 from protocol bgp set policy-options policy-statement nhs term 10 then next-hop self set protocols bgp group AS65002 export nhs
lab@R2> show route advertising-protocol bgp 203.0.113.21 inet.0: 14 destinations, 18 routes (14 active, 0 holddown, 1 hidden) Prefix Nexthop MED Lclpref AS path * 0.0.0.0/0 Self I * 100.0.0.0/8 Self I inet6.0: 14 destinations, 14 routes (14 active, 0 holddown, 0 hidden) Prefix Nexthop MED Lclpref AS path * ::/0 Self I * 1000::/8 Self I
lab@R3> show route receive-protocol bgp 203.0.113.20 inet.0: 11 destinations, 11 routes (11 active, 0 holddown, 0 hidden) Prefix Nexthop MED Lclpref AS path * 0.0.0.0/0 203.0.113.20 65001 I * 100.0.0.0/8 203.0.113.20 65001 I inet6.0: 9 destinations, 9 routes (9 active, 0 holddown, 0 hidden) Prefix Nexthop MED Lclpref AS path * ::/0 ::ffff:203.0.113.20 65001 I * 1000::/8 ::ffff:203.0.113.20 65001 I lab@R3> ping 1000::1 source 3333::3 rapid PING6(56=40+8+8 bytes) 3333::3 --> 1000::1 !!!!! --- 1000::1 ping6 statistics --- 5 packets transmitted, 5 packets received, 0% packet loss round-trip min/avg/max/std-dev = 2.725/3.557/6.085/1.280 ms
Note that this behavior is not only for IPv6. The R2-R3 link has the /28 subnet mask on ge-0/0/0, which does not contain R1's loopback address. If the network includes R1's loopback address, the same issue happens in IPv4 as shown below:
set interfaces ge-0/0/0 unit 0 family inet address 203.0.113.20/24 lab@R2> show route advertising-protocol bgp 203.0.113.21 inet.0: 14 destinations, 18 routes (14 active, 0 holddown, 1 hidden) Prefix Nexthop MED Lclpref AS path * 0.0.0.0/0 203.0.113.251 I * 100.0.0.0/8 203.0.113.251 I inet6.0: 14 destinations, 16 routes (14 active, 0 holddown, 1 hidden) Prefix Nexthop MED Lclpref AS path * ::/0 ::ffff:203.0.113.251 I * 1000::/8 ::ffff:203.0.113.251 I