IPv6 source address selection – what, why, how?

IPv6 source address selection must be very irritated; destination address selection gets all the press coverage.

This article will start to redress the balance, by talking about what IPv6 source address selection is, why it is needed, and how it works. If you want the nitty-gritty, check out RFC 6724 (which obsoletes RFC 3484).

Later articles will discuss why you might want to control source address selection, and how you can do that.

Why source address selection?

An interface on a modern computer can have several addresses – link local addresses, statically configured global unicast addresses, addresses acquired from a DHCPv6 server, autoconfigured addresses. It may have all of these at once, or even more than one of each of these at once. And that’s just IPv6 – a dual stack host will have IPv4 addresses on it as well – typically a localhost address and an address obtained via DHCPv4.

When an application – a web browser, say – sends data into the network stack for delivery, what source address should be put in the packets? This is where source address selection comes in.

How does it work?

Applications can always specify the source address. Server software especially will often control the source addresses in outgoing packets – the BIND nameserver, for example, has configuration options to control the source address responses that it issues. If an application does specify the source address, then the operating system has no choice to make.

Otherwise, the operating system takes the set of possible source addresses (that is, all the IPv4 and IPv6 addresses on all interfaces) and sorts them into order according to eight rules; it then returns the “top” address from the sorted list. During the sorting process, the rules are worked through in order for each pair of addresses being compared; as soon as a rule applies (i.e., puts either of the two addresses ahead of the other), the comparison of that pair stops. Once the sorting is complete, the “top” address will be used as the source address.

Here are the rules:

  1. Prefer same address.
  2. Prefer appropriate scope.
  3. Avoid deprecated addresses.
  4. Prefer home addresses.
  5. Prefer outgoing interface.
  6. Prefer matching label.
  7. Prefer privacy addresses.
  8. Use longest matching prefix.

Let’s look at those in more detail.

The first rule is “use the same address“. This rule says that if one of the candidate addresses is the same as the destination address, prefer that one (sort it before the other). Most operating systems can heavily optimise the case where a host is “talking to itself”.

The second rule is “prefer appropriate scope“. This means that if the destination is (say) a link local address, then sort link local addresses before global addresses. Or, if the destination is a global address, sort global candidates before link local candidates. For the purposes of this rule, addresses on the loopback interface are regarded as being link local. IPv4 addresses don’t have scope, so for the purposes of source address selection, scope is retrofitted – localhost addresses (127.0.0.0/8) and zeroconf addresses (169.254.0.0/16) are regarded as link-local, all others, including RFC1918 addresses, are regarded as global in scope.

The third rule is “avoid deprecated addresses“. This rule will sort deprecated addresses lower than non-deprecated candidates. If there are no non-deprecated candidates, then deprecated addresses may still end up at the top of the sorted list and may yet still be selected. For the purposes of this rule, addresses on the loopback interface are regarded as being preferred – that is, not deprecated, tentative or invalid. IPv4 addresses are also regarded as preferred.

The fourth rule is “prefer home addresses“. In MobileIPv6, a host carries around one or more addresses from its “home” network. This rule says that the host should sort those above any addresses it has from the network it happens to be in at the moment. For any host not doing MobileIPv6, this rule will have no effect. For more information about MobileIPv6, start with RFC6275.

The fifth rule is “prefer outgoing interface“. That is, if there are candidate addresses on the interface that the packet will go out from, sort those ahead of addresses from other interfaces.

The sixth rule is the most complicated one. It says “prefer matching label“. The most important job this rule does is to distinguish between IPv4 and IPv6 addresses, but there is a bit more to it than just that. There is a table available to the operating system, which pairs prefixes and labels. The operating system looks up the destination address in the table, choosing the entry that has the greatest number of identical contiguous leading bits to the destination address (the longest matching prefix). It notes the label for that entry. It then looks up the label for each of the candidate addresses in the same way, and any that match the label found for the destination address are sorted before any that do not. A label is just a number; it is tested for equality with other labels during this process, but the numbers have no meaning. The default label table looks like this (the rightmost column is not part of the table data):

Prefix              Label
  ::1/128             0      (localhost)
  ::/0                1      (any IPv6)
  ::ffff:0:0/96       4      (any IPv4)
  2002::/16           2      (6to4)
  2001::/32           5      (Teredo)
  fc00::/7           13      (ULA)
  ::/96               3      (IPv4 compatible, deprecated)
  fec0::/10          11      (site local, deprecated)
  3ffe::/16          12      (6bone, deprecated)

The seventh rule is “prefer privacy addresses“. This used to be the other way around, “prefer public addresses”; the idea was that privacy addresses come and go, so the host should prefer more stable addresses. But if you have configured privacy addresses, presumably you want to use them, so the revised RFC says that privacy addresses should be preferred; it also says that this rule should be able to be reversed by the system administrator – that is, the system administrator should be able to configure the system to prefer public addresses over privacy addresses. For more information on privacy addressing, see RFC4941.

The eighth rule is “use longest matching prefix“. That is, use the address that shares the greatest number of contiguous leading bits with the destination address. Such an address is likely to be topologically closer to the destination address. The comparison stops after the prefix length of the source address; a deeper comparison is meaningless.

In the now obsoleted RFC 3484, there was a final step, “choose one“, in an implementation-dependent (unspecified) way. With RFC 6724, whichever address is now at the top of the sorted list will be selected.

A worked example

Let’s say that you have a host with a single ethernet interface and of course a loopback interface. The loopback interface has a local host address; the ethernet interface has a link local address, an ordinary autoconfigured address, a temporary (“privacy”) address, and an address obtained via DHCPv6. I’m running dual stack, so I also have an IPv4 localhost address on the loopback interface and an IPv4 address obtained via DHCP on the ethernet interface. The complete list of candidate source addresses thus looks like this:

   fe80::302:2ff:fe04:506/64
   2001:db8:0:100:302:2ff:fe04:506/64
   2001:db8:0:100:1234:5678:9abc:def0/64
   2001:db8:0:100::27/64
   ::1/128
   127.0.0.1/32
   192.168.1.77/24

They are all fake, by the way, for the purposes of this article. The temporary addresses aren’t very random :-)

Another host in the same subnet has a similar set of addresses:

   fe80::305:6ff:fe07:809/64
   2001:db8:0:100:305:6ff:fe07:809/64
   2001:db8:0:100:4321:8765:cba9:0fed/64
   2001:db8:0:100::38/64
   ::1/128
   127.0.0.1/32
   192.168.1.78/24

If I send a ping from the first host to the second host’s DHCPv6 address, which source address will be used? Here goes!

Rule 1, “use same address”, doesn’t apply will never apply in a comparison; I am not sending to one of my own addresses.

Rule 2, “prefer appropriate scope” will apply to any comparison between addresses of different scopes. This effectively sorts all the link-local addresses down the list and out of contention, because the destination address is a global one.

Rule 3, “avoid deprecated addresses”, doesn’t change the sorted order, because none of the addresses involved are deprecated.

Rule 4, “prefer home addresses” doesn’t do anything either; we are not doing MobileIPv6.

Rule 5, “prefer outgoing interface”, will sort the addresses on the lo interface below the addresses on the ethernet interfaces. All the global candidate addresses are on the same interface anyway. Because all the addresses on the only other interface are link local and our destination is global, Rule 2 means that this rule will never be reached.

Rule 6, “prefer matching label”, will sort any IPv4 addresses below any IPv6 addresses. The default table looks like this (you can see your own table using “ip addrlabel show” in Linux, or “netsh int ipv6 show prefixpolicies” in Windows). Note that the comments I’ve added in the rightmost column are not part of the actual label table:

Prefix              Label
  ::1/128             0      (localhost)
  ::/0                1      (any IPv6)
  ::ffff:0:0/96       4      (any IPv4)
  2002::/16           2      (6to4)
  2001::/32           5      (Teredo)
  fc00::/7           13      (ULA)
  ::/96               3      (IPv4 compatible, deprecated)
  fec0::/10          11      (site local, deprecated)
  3ffe::/16          12      (6bone, deprecated)

So our destination address will match ::/0, which has the label “0”. Both the remaining IPv6 addresses will also match this prefix, but the IPv4 address will match ::ffff:0:0/96. Since the label “4” does not match the label “0”, the IPv4 addresses will be sorted after the IPv6 addresses, which do.

Rule 7, “prefer privacy addresses”, will push the temporary address to the top.

Rule 8, “use longest matching prefix”, will not change the sorted order, because the comparison stops at 64 bits in each case (bot source addresses have 64-bit prefixes), and the two candidate addresses share the same first 64 bits as the destination.

So the temporary address is at the top, followed by the DHCPv6 address and the autoconfigured address. Actually we don’t know in what order the second two will be, because none of the rules discriminated between them. Linux orders the initial list in order of insertion, so for Linux, most likely the autoconfigured GUA would be the first of the two.

The topmost address, however, will be the temporary address, so that address will be selected for use as the source address.

Now imagine that we were not using temporary addresses, and remove those from the example. Which address will be chosen as the source address, the DHCPv6 address or the autoconfigured one?

Well in this case, we don’t know. As noted above, none of the rules discriminated between them. Is that an unsatisfying answer? Surely it should be possible to deterministically say one or the other is selected? Well, it might be nice, but it is not necessary. Either of these two addresses will do fine – there is literally no practical difference between them.

If there were an important difference, such that you (the system administrator) wanted one or the other address to be preferred, you would need to set up a difference that the above procedure could detect and operate on. Depending on the situation you might be able to modify the label table (see this article about that if you are using Linux) or use different prefixes.

[This article was copied from my personal blog, where it was originally posted on July 21, 2012]

Leave a Reply

Your email address will not be published. Required fields are marked *