IPv6 addresses not available at boot

One of things that’s always bugged me regarding Linux and IPv6 is the
behaviour that’s exhibited during boot time. Specifically, the short delay before IPv6 addresses transition from their “tentative” state on an interface to being fully available for use by various daemons and services. With IPv4, you can be pretty much guaranteed that you can bind to any of the configured addresses at boot time, under normal circumstances.

With IPv6 on Linux, things aren’t so straightforward. Duplicate Address Detection (DAD), which basically does what it says on the tin, introduces a short delay before addresses are fully configured, the address has been added to the network interface, but not really.

I recently came across this whilst attempting to get BIND to listen on some secondary service addresses on a particular machine. BIND would not er, bind, to the IPv6 addresses at boot, failing with messages like this:

bind9 could not listen on UDP socket: address not available

Modifying /etc/init.d/bind9 to print the output of “ip addr show” to a file at the time BIND attempted to start up showed the tell-tale “tentative” flag on each IPv6 address being added to eth0. Since the addresses are in this state, BIND or other daemons will refuse to listen on them.

The problem has become very noticeable since parallel boot systems such as Upstart have become the default in quite a few Linux distros. Daemons will often fire up before the network is fully ready and in some extreme cases network filesystems that reference hostnames may fail to mount if you are using an IPv6 DNS resolver. Of course this isn’t the case across the board, some daemons and services appear to handle the unavailability of an IPv6 address somewhat gracefully, backing off and trying again a short time later rather than simply giving up on the first go.

Anyway, a simple “hairy hack” to get over this problem is to add something like the following to your startup script:

sleep 5

Yes, a one line sleep command to make the daemon wait a short while before actually starting. This seems to ensure that the IPv6 address has moved out of the tentative state, but it’s still somewhat silly..