Mixing IPv4 and IPv6 in BGP (posted 2016-03-18)
When I first started running IPv6 over BGP, I ran into an interesting problem. The Cisco router I was working on had four full BGP feeds over IPv4. But when did show ip bgp, I noticed the router had five copies of each prefix. One of these paths had a really weird next hop address and was marked as unreachable.
Turned out those were IPv4 prefixes learned over an IPv6 BGP session.
What had happened was that when adding an IPv6 BGP session, I didn't specifically tell the router to not do IPv4 over that session. So despite the session being between two IPv6 addresses, the routers on both sides negotiated the use of the IPv4 unicast address family over that session, and thus exchanged IPv4 prefixes.
The problem with that is that BGP's automatic next hop processing then doesn't work: normally, the next hop is set to the IP address the router uses for the TCP session that BGP runs over. So when router 192.0.2.1 sends IPv4 prefixes to router 192.0.2.2, it sets the next hop attribute in those updates to 192.0.2.1. That doesn't work so well when the IP addresses for that BGP session are 2001:db8::1 and 2001:db8::2. What actually seems to happen is that the routers set the IPv4 next hop address to the first 32 bits of the IPv6 address used for the BGP TCP session...
So this is why for eBGP, we recommend using an IPv4 BGP session to exchange IPv4 prefixes and an IPv6 BGP session to exchange IPv6 prefixes. As the default is IPv4, for IPv6 BGP sessions you usually need to disable IPv4 and enable IPv6 (unless the defaults have been changed at some point, but you really don't want to depend on that):
! router bgp 65550 neighbor 2001:db8::2 remote-as 65551 ! address-family ipv4 no neighbor 2001:db8::2 activate ! address-family ipv6 neighbor 2001:db8::2 activate !
Or you can make a route map that sets the next hop address to an address that does work.
For iBGP, it's often easier to also use the IPv4 BGP sessions for IPv6, as the number of iBGP sessions adds up quickly and iBGP doesn't modify the next hop address, so the issue above doesn't come up.
However, there's an additional complication when mixing IPv4 and IPv6 in BGP: debugging gets much harder.
If you want to see what's happening with your BGP sessions, you can use the show bgp ipv4 unicast summary and show bgp ipv6 unicast summary commands:
# show bgp ipv4 unicast summary Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd 18.104.22.168 4 81 23 24 0 0 0 00:20:28 16 2001:1c00:161d:df00::1 4 81 24 24 0 0 0 00:20:27 19
# show bgp ipv6 unicast summary Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd 2001:1c00:161d:df00::1 4 81 26 26 0 0 0 00:22:01 1
So with these commands, we get to see the BGP sessions for which IPv4 or IPv6 is activated, regardless of whether the session runs over IPv4 or IPv6. So far, so good. And in later Cisco IOS versions, I believe this works the same for other show bgp commands. But under older IOS versions the IPv4 commands won't always take an IPv6 address and vice versa.
But at least under Cisco IOS, the commands now make a reasonable amount of sense: rather than show ip bgp ... for IPv4 and show bgp ... for IPv6, we can now use the much more consistent show bgp ipv4 unicast ... and show bgp ipv6 unicast ... commands.
Not so much under Quagga, though. At least, under version 0.99.22.4. The good news is that you can actually use show ip bgp neighbors <IPv6 address> and show bgp neighbors <IPv4 address>. The bad news is that even though Quagga understands the show bgp ipv4 unicast summary command, it doesn't understand the show bgp ipv4 unicast neighbors ... command. You have to use show ip bgp neighbors ... instead.
So the moral of the story is that you make life a lot easier if you don't mix IPv4 and IPv6 in BGP. If you do, it helps to use recent software, but make sure you check all the possible variations of the different commands, because they're not necessarily used consistently.