On 09/06/11 11:17, Tim Chown wrote:
> It's as if OS X will just ignore AAAA responses if they don't come
> back quickly enough, and thus you 'lock' into IPv4 if the A response
> arrives quickly. I need to rig up some tests, but if anyone has
> looked in detail at that already and has the info, it would be
> appreciated.
Interesting. The following (lengthy) story might shed some light on the
reasoning behind the MacOS X behaviour.
We had some problems a while back with Linux machines querying our DNS
server. Glibc on Linux (quite legally) creates a new UDP socket for the
A/AAAA requests, then deletes it - only ever sending two packets.
The packets of course come from the same source port, and are emitted in
such quick succession (microseconds) that the load balancers in front of
(one of - the other is anycasted) our DNS IPs had problems. The session
was still being built as the 2nd (AAAA) packet arrived, leading to it
being dropped and a lengthy DNS timeout.
The problem was exacerbated by glibc not "remembering" this failure as
it was supposed to, giving the timeout on every DNS query. During login,
the timeouts exceeded 60 seconds - and the login itself timed out.
It turns out a lot of people were having that problem, as many devices
have such "racy" conditions for 2-packet UDP flows with a microsecond
gap. The glibc maintainer was quite definite that this was the device
vendors responsibility to fix:
https://bugzilla.redhat.com/show_bug.cgi?id=505105#c21
...although personally I doubt the practicality; most ADSL CPEs are
abandonware as soon as they hit the shelves. I suspect it's only because
the bug above led to a "remember broken" flag that it's not still
causing problems.
I wonder if Apple had found the same thing in their testing and added
some kind of fast timeout feature? If it were me, I would be tempted to
do this:
create socket
send A
send AAAA
select(socket, timeout=1 second)
read 1st reply, or fail
select(socket, timeout=0.01 second)
read 2nd reply, or fail
i.e. wait much less time for the 2nd reply. Since the "A" query is sent
1st, it'll usually be the 1st reply.
(Actually, if it were me I'd be tempted to run a full caching resolver
locally and stop trying to re-implement stuff that's hard inside a
50-line C function, but there we go.... ;o)
Presumably there is then some kind of caching of the output of the query
(e.g. nscd-alike) that means a reply failure never gets retried. There
are some genuinely awful stub resolvers out there!
I did notice yesterday frequent behaviour like this:
$ host www.google.com
www.google.com is an alias for www.l.google.com.
www.l.google.com has address 209.85.146.106
www.l.google.com has address 209.85.146.147
www.l.google.com has address 209.85.146.99
www.l.google.com has address 209.85.146.103
www.l.google.com has address 209.85.146.104
www.l.google.com has address 209.85.146.105
<0.25-0.75 second pause>
www.l.google.com has IPv6 address 2a00:1450:400c:c00::93
...so something was happening to make the AAAA query take a lot longer.
"host" on my system seems to use a single socket to make the DNS queries
in sequence, so similar to Linux/glibc. At that point, my home DNS
lookups were going to Hurricane Electric's IPv6 DNS server, with no NAT
in play, so I'm not sure where the slowness was coming from.
|